react-native-roster 0.2.0 → 0.4.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/README.md +73 -3
- package/dist/src/components/roster/body-layout.d.ts +3 -1
- package/dist/src/components/roster/body-layout.d.ts.map +1 -1
- package/dist/src/components/roster/body-layout.js +6 -2
- package/dist/src/components/roster/body-layout.js.map +1 -1
- package/dist/src/components/roster/index.d.ts.map +1 -1
- package/dist/src/components/roster/index.js +4 -3
- package/dist/src/components/roster/index.js.map +1 -1
- package/dist/src/components/roster/parts/body.d.ts.map +1 -1
- package/dist/src/components/roster/parts/body.js +2 -2
- package/dist/src/components/roster/parts/body.js.map +1 -1
- package/dist/src/components/roster/parts/lane-list.d.ts +2 -2
- package/dist/src/components/roster/parts/lane-list.d.ts.map +1 -1
- package/dist/src/components/roster/parts/now-line.d.ts +3 -0
- package/dist/src/components/roster/parts/now-line.d.ts.map +1 -0
- package/dist/src/components/roster/parts/now-line.js +16 -0
- package/dist/src/components/roster/parts/now-line.js.map +1 -0
- package/dist/src/components/roster/roster.types.d.ts +17 -1
- package/dist/src/components/roster/roster.types.d.ts.map +1 -1
- package/dist/src/components/roster/use-roster.d.ts.map +1 -1
- package/dist/src/components/roster/use-roster.js +6 -1
- package/dist/src/components/roster/use-roster.js.map +1 -1
- package/dist/src/core/index.d.ts +2 -1
- package/dist/src/core/index.d.ts.map +1 -1
- package/dist/src/core/index.js +6 -1
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/core/layout.d.ts.map +1 -1
- package/dist/src/core/layout.js +2 -1
- package/dist/src/core/layout.js.map +1 -1
- package/dist/src/core/snap.d.ts +4 -0
- package/dist/src/core/snap.d.ts.map +1 -1
- package/dist/src/core/snap.js +5 -0
- package/dist/src/core/snap.js.map +1 -1
- package/dist/src/core/spans.d.ts +19 -0
- package/dist/src/core/spans.d.ts.map +1 -1
- package/dist/src/core/spans.js +64 -0
- package/dist/src/core/spans.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/nativewind/index.d.ts +1 -0
- package/dist/src/nativewind/index.d.ts.map +1 -1
- package/llms.txt +51 -7
- package/package.json +2 -2
- package/src/components/roster/README.md +16 -5
- package/src/components/roster/body-layout.tsx +15 -0
- package/src/components/roster/index.tsx +5 -0
- package/src/components/roster/parts/body.tsx +39 -2
- package/src/components/roster/parts/lane-list.tsx +2 -2
- package/src/components/roster/parts/now-line.tsx +19 -0
- package/src/components/roster/roster.types.ts +15 -9
- package/src/components/roster/use-roster.ts +8 -1
- package/src/core/README.md +15 -2
- package/src/core/index.ts +2 -1
- package/src/core/layout.ts +2 -1
- package/src/core/snap.ts +9 -0
- package/src/core/spans.ts +66 -2
- package/src/index.ts +3 -0
package/dist/src/core/spans.d.ts
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
1
|
import type { Interval, Window } from './types';
|
|
2
2
|
export declare function sourceSpans(intervals: Interval[], window: Window): Interval[];
|
|
3
|
+
/**
|
|
4
|
+
* Earliest start through latest end in epoch milliseconds, end-exclusive; empty input returns null.
|
|
5
|
+
* Throws RangeError for non-finite bounds or end <= start.
|
|
6
|
+
* Inputs may be unsorted, overlapping, nested, or duplicated; inputs are not mutated.
|
|
7
|
+
*/
|
|
8
|
+
export declare function extentOf(segments: readonly Window[]): Window | null;
|
|
9
|
+
/**
|
|
10
|
+
* Shared epoch milliseconds, end-exclusive; empty input or an empty intersection returns null.
|
|
11
|
+
* Throws RangeError for non-finite bounds or end <= start.
|
|
12
|
+
* Inputs may be unsorted, overlapping, nested, or duplicated; inputs are not mutated.
|
|
13
|
+
*/
|
|
14
|
+
export declare function intersectionOf(spans: readonly Window[]): Window | null;
|
|
15
|
+
/**
|
|
16
|
+
* Merged end-exclusive epoch windows sorted by start; empty input returns an empty array.
|
|
17
|
+
* Overlapping or touching spans merge; disjoint spans remain separate.
|
|
18
|
+
* Throws RangeError for non-finite bounds or end <= start.
|
|
19
|
+
* Returns new objects without mutating inputs.
|
|
20
|
+
*/
|
|
21
|
+
export declare function unionOf(spans: readonly Window[]): Window[];
|
|
3
22
|
//# sourceMappingURL=spans.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spans.d.ts","sourceRoot":"","sources":["../../../src/core/spans.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"spans.d.ts","sourceRoot":"","sources":["../../../src/core/spans.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAU,MAAM,EAAE,MAAM,SAAS,CAAC;AAIxD,wBAAgB,WAAW,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,EAAE,CAmD7E;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CASnE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAUtE;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAgB1D"}
|
package/dist/src/core/spans.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.sourceSpans = sourceSpans;
|
|
4
|
+
exports.extentOf = extentOf;
|
|
5
|
+
exports.intersectionOf = intersectionOf;
|
|
6
|
+
exports.unionOf = unionOf;
|
|
4
7
|
function sourceSpans(intervals, window) {
|
|
5
8
|
const boundaries = [];
|
|
6
9
|
for (const interval of intervals) {
|
|
@@ -57,4 +60,65 @@ function sourceSpans(intervals, window) {
|
|
|
57
60
|
}
|
|
58
61
|
return spans;
|
|
59
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Earliest start through latest end in epoch milliseconds, end-exclusive; empty input returns null.
|
|
65
|
+
* Throws RangeError for non-finite bounds or end <= start.
|
|
66
|
+
* Inputs may be unsorted, overlapping, nested, or duplicated; inputs are not mutated.
|
|
67
|
+
*/
|
|
68
|
+
function extentOf(segments) {
|
|
69
|
+
let start = Infinity;
|
|
70
|
+
let end = -Infinity;
|
|
71
|
+
for (const segment of segments) {
|
|
72
|
+
validateSpan(segment);
|
|
73
|
+
start = Math.min(start, segment.start);
|
|
74
|
+
end = Math.max(end, segment.end);
|
|
75
|
+
}
|
|
76
|
+
return start < end ? { start, end } : null;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Shared epoch milliseconds, end-exclusive; empty input or an empty intersection returns null.
|
|
80
|
+
* Throws RangeError for non-finite bounds or end <= start.
|
|
81
|
+
* Inputs may be unsorted, overlapping, nested, or duplicated; inputs are not mutated.
|
|
82
|
+
*/
|
|
83
|
+
function intersectionOf(spans) {
|
|
84
|
+
if (spans.length === 0)
|
|
85
|
+
return null;
|
|
86
|
+
let start = -Infinity;
|
|
87
|
+
let end = Infinity;
|
|
88
|
+
for (const span of spans) {
|
|
89
|
+
validateSpan(span);
|
|
90
|
+
start = Math.max(start, span.start);
|
|
91
|
+
end = Math.min(end, span.end);
|
|
92
|
+
}
|
|
93
|
+
return start < end ? { start, end } : null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Merged end-exclusive epoch windows sorted by start; empty input returns an empty array.
|
|
97
|
+
* Overlapping or touching spans merge; disjoint spans remain separate.
|
|
98
|
+
* Throws RangeError for non-finite bounds or end <= start.
|
|
99
|
+
* Returns new objects without mutating inputs.
|
|
100
|
+
*/
|
|
101
|
+
function unionOf(spans) {
|
|
102
|
+
const sorted = spans.map((span) => {
|
|
103
|
+
validateSpan(span);
|
|
104
|
+
return { start: span.start, end: span.end };
|
|
105
|
+
});
|
|
106
|
+
sorted.sort((a, b) => a.start - b.start);
|
|
107
|
+
const merged = [];
|
|
108
|
+
for (const span of sorted) {
|
|
109
|
+
const last = merged.at(-1);
|
|
110
|
+
if (last && span.start <= last.end) {
|
|
111
|
+
last.end = Math.max(last.end, span.end);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
merged.push(span);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return merged;
|
|
118
|
+
}
|
|
119
|
+
function validateSpan(span) {
|
|
120
|
+
if (!Number.isFinite(span.start) || !Number.isFinite(span.end) || span.end <= span.start) {
|
|
121
|
+
throw new RangeError('Span bounds must be finite with end greater than start');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
60
124
|
//# sourceMappingURL=spans.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spans.js","sourceRoot":"","sources":["../../../src/core/spans.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"spans.js","sourceRoot":"","sources":["../../../src/core/spans.ts"],"names":[],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -13,7 +13,8 @@ export { RosterHeader } from './components/roster/parts/header';
|
|
|
13
13
|
export { RosterHeaderCell } from './components/roster/parts/header-cell';
|
|
14
14
|
export { RosterLaneLabelColumn } from './components/roster/parts/lane-label-column';
|
|
15
15
|
export { RosterLaneList } from './components/roster/parts/lane-list';
|
|
16
|
-
export
|
|
16
|
+
export { RosterNowLine } from './components/roster/parts/now-line';
|
|
17
|
+
export type { BodyInput, GridInput, HeaderCellInput, HeaderInput, IntervalDetailInput, LabelColumnInput, LaneLabelInput, LaneListInput, RosterInput, RosterModel, RosterNowLineInput, RosterProjection, RosterProps, RosterScroll, RosterStyleProps, RosterTick, } from './components/roster/roster.types';
|
|
17
18
|
export { RosterSelectionPopover } from './components/roster/selection/selection-layout';
|
|
18
19
|
export type { SelectionLayoutProps } from './components/roster/selection/selection-layout.types';
|
|
19
20
|
export { useRoster } from './components/roster/use-roster';
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,YAAY,EACV,SAAS,EACT,SAAS,EACT,eAAe,EACf,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,UAAU,GACX,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,gDAAgD,CAAC;AACxF,YAAY,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AACjG,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,cAAc,QAAQ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,YAAY,EACV,SAAS,EACT,SAAS,EACT,eAAe,EACf,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,UAAU,GACX,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,sBAAsB,EAAE,MAAM,gDAAgD,CAAC;AACxF,YAAY,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AACjG,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,+CAA+C,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,cAAc,QAAQ,CAAC"}
|
package/dist/src/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.useSchedule = exports.ScheduleIncomplete = exports.ScheduleGutter = exports.ScheduleTransition = exports.ScheduleSkippedDate = exports.ScheduleNowLine = exports.ScheduleGrid = exports.ScheduleDayHeader = exports.ScheduleColumn = exports.Schedule = exports.useRoster = exports.RosterSelectionPopover = exports.RosterLaneList = exports.RosterLaneLabelColumn = exports.RosterHeaderCell = exports.RosterHeader = exports.RosterGrid = exports.RosterEmpty = exports.RosterCorner = exports.RosterBody = exports.RosterLaneLabel = exports.RosterBodyLayout = exports.Roster = exports.PortalHost = exports.Portal = exports.RosterInterval = exports.RosterGap = void 0;
|
|
17
|
+
exports.useSchedule = exports.ScheduleIncomplete = exports.ScheduleGutter = exports.ScheduleTransition = exports.ScheduleSkippedDate = exports.ScheduleNowLine = exports.ScheduleGrid = exports.ScheduleDayHeader = exports.ScheduleColumn = exports.Schedule = exports.useRoster = exports.RosterSelectionPopover = exports.RosterNowLine = exports.RosterLaneList = exports.RosterLaneLabelColumn = exports.RosterHeaderCell = exports.RosterHeader = exports.RosterGrid = exports.RosterEmpty = exports.RosterCorner = exports.RosterBody = exports.RosterLaneLabel = exports.RosterBodyLayout = exports.Roster = exports.PortalHost = exports.Portal = exports.RosterInterval = exports.RosterGap = void 0;
|
|
18
18
|
var gap_1 = require("./components/layers/parts/gap");
|
|
19
19
|
Object.defineProperty(exports, "RosterGap", { enumerable: true, get: function () { return gap_1.RosterGap; } });
|
|
20
20
|
var interval_1 = require("./components/layers/parts/interval");
|
|
@@ -44,6 +44,8 @@ var lane_label_column_1 = require("./components/roster/parts/lane-label-column")
|
|
|
44
44
|
Object.defineProperty(exports, "RosterLaneLabelColumn", { enumerable: true, get: function () { return lane_label_column_1.RosterLaneLabelColumn; } });
|
|
45
45
|
var lane_list_1 = require("./components/roster/parts/lane-list");
|
|
46
46
|
Object.defineProperty(exports, "RosterLaneList", { enumerable: true, get: function () { return lane_list_1.RosterLaneList; } });
|
|
47
|
+
var now_line_1 = require("./components/roster/parts/now-line");
|
|
48
|
+
Object.defineProperty(exports, "RosterNowLine", { enumerable: true, get: function () { return now_line_1.RosterNowLine; } });
|
|
47
49
|
var selection_layout_1 = require("./components/roster/selection/selection-layout");
|
|
48
50
|
Object.defineProperty(exports, "RosterSelectionPopover", { enumerable: true, get: function () { return selection_layout_1.RosterSelectionPopover; } });
|
|
49
51
|
var use_roster_1 = require("./components/roster/use-roster");
|
|
@@ -56,8 +58,8 @@ var day_header_1 = require("./components/schedule/days/parts/day-header");
|
|
|
56
58
|
Object.defineProperty(exports, "ScheduleDayHeader", { enumerable: true, get: function () { return day_header_1.ScheduleDayHeader; } });
|
|
57
59
|
var grid_2 = require("./components/schedule/days/parts/grid");
|
|
58
60
|
Object.defineProperty(exports, "ScheduleGrid", { enumerable: true, get: function () { return grid_2.ScheduleGrid; } });
|
|
59
|
-
var
|
|
60
|
-
Object.defineProperty(exports, "ScheduleNowLine", { enumerable: true, get: function () { return
|
|
61
|
+
var now_line_2 = require("./components/schedule/days/parts/now-line");
|
|
62
|
+
Object.defineProperty(exports, "ScheduleNowLine", { enumerable: true, get: function () { return now_line_2.ScheduleNowLine; } });
|
|
61
63
|
var skipped_date_1 = require("./components/schedule/days/parts/skipped-date");
|
|
62
64
|
Object.defineProperty(exports, "ScheduleSkippedDate", { enumerable: true, get: function () { return skipped_date_1.ScheduleSkippedDate; } });
|
|
63
65
|
var transition_1 = require("./components/schedule/days/parts/transition");
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AACA,qDAA0D;AAAjD,gGAAA,SAAS,OAAA;AAClB,+DAAoE;AAA3D,0GAAA,cAAc,OAAA;AACvB,yDAAoE;AAA3D,gGAAA,MAAM,OAAA;AAAE,oGAAA,UAAU,OAAA;AAC3B,8CAA6C;AAApC,gGAAA,MAAM,OAAA;AACf,+DAAmE;AAA1D,+GAAA,gBAAgB,OAAA;AACzB,yEAA6E;AAApE,6GAAA,eAAe,OAAA;AACxB,uDAA4D;AAAnD,kGAAA,UAAU,OAAA;AACnB,2DAAgE;AAAvD,sGAAA,YAAY,OAAA;AACrB,yDAA8D;AAArD,oGAAA,WAAW,OAAA;AACpB,uDAA4D;AAAnD,kGAAA,UAAU,OAAA;AACnB,2DAAgE;AAAvD,sGAAA,YAAY,OAAA;AACrB,qEAAyE;AAAhE,+GAAA,gBAAgB,OAAA;AACzB,iFAAoF;AAA3E,0HAAA,qBAAqB,OAAA;AAC9B,iEAAqE;AAA5D,2GAAA,cAAc,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AACA,qDAA0D;AAAjD,gGAAA,SAAS,OAAA;AAClB,+DAAoE;AAA3D,0GAAA,cAAc,OAAA;AACvB,yDAAoE;AAA3D,gGAAA,MAAM,OAAA;AAAE,oGAAA,UAAU,OAAA;AAC3B,8CAA6C;AAApC,gGAAA,MAAM,OAAA;AACf,+DAAmE;AAA1D,+GAAA,gBAAgB,OAAA;AACzB,yEAA6E;AAApE,6GAAA,eAAe,OAAA;AACxB,uDAA4D;AAAnD,kGAAA,UAAU,OAAA;AACnB,2DAAgE;AAAvD,sGAAA,YAAY,OAAA;AACrB,yDAA8D;AAArD,oGAAA,WAAW,OAAA;AACpB,uDAA4D;AAAnD,kGAAA,UAAU,OAAA;AACnB,2DAAgE;AAAvD,sGAAA,YAAY,OAAA;AACrB,qEAAyE;AAAhE,+GAAA,gBAAgB,OAAA;AACzB,iFAAoF;AAA3E,0HAAA,qBAAqB,OAAA;AAC9B,iEAAqE;AAA5D,2GAAA,cAAc,OAAA;AACvB,+DAAmE;AAA1D,yGAAA,aAAa,OAAA;AAmBtB,mFAAwF;AAA/E,0HAAA,sBAAsB,OAAA;AAE/B,6DAA2D;AAAlD,uGAAA,SAAS,OAAA;AAClB,kDAAiD;AAAxC,oGAAA,QAAQ,OAAA;AACjB,kEAAyE;AAAhE,wGAAA,cAAc,OAAA;AACvB,0EAAgF;AAAvE,+GAAA,iBAAiB,OAAA;AAC1B,8DAAqE;AAA5D,oGAAA,YAAY,OAAA;AACrB,sEAA4E;AAAnE,2GAAA,eAAe,OAAA;AACxB,8EAAoF;AAA3E,mHAAA,mBAAmB,OAAA;AAC5B,0EAAiF;AAAxE,gHAAA,kBAAkB,OAAA;AAC3B,6DAAoE;AAA3D,wGAAA,cAAc,OAAA;AACvB,qEAA4E;AAAnE,gHAAA,kBAAkB,OAAA;AAY3B,mEAAiE;AAAxD,2GAAA,WAAW,OAAA;AACpB,yCAAuB"}
|
|
@@ -9,6 +9,7 @@ type Mapping<T> = {
|
|
|
9
9
|
export declare const rosterClassNames: Mapping<RosterStyleProps>;
|
|
10
10
|
export declare const scheduleClassNames: Mapping<ScheduleStyleProps>;
|
|
11
11
|
export declare const Roster: import("react").ComponentType<Omit<import("../components/roster/roster.types").RosterInput, "selectable"> & RosterStyleProps & {
|
|
12
|
+
nowLineComponent?: import("react").ComponentType<import("../components/roster/roster.types").RosterNowLineInput>;
|
|
12
13
|
intervalDetailComponent?: import("react").ComponentType<import("../components/roster/roster.types").IntervalDetailInput>;
|
|
13
14
|
selectionLayout?: import("react").ComponentType<import("..").SelectionLayoutProps>;
|
|
14
15
|
portalHost?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/nativewind/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAE1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAEhF,KAAK,aAAa,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,WAAW,GAAG,GAAG,MAAM,WAAW,CAAC,CAAC;AACtF,KAAK,WAAW,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,MAAM,WAAW,GACrE,GAAG,MAAM,OAAO,GAChB,OAAO,CAAC;AACZ,KAAK,OAAO,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;CAAE,CAAC;AAEhE,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,CAKtD,CAAC;AACF,eAAO,MAAM,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,CAK1D,CAAC;AAIF,eAAO,MAAM,MAAM
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/nativewind/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAE1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAEhF,KAAK,aAAa,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,WAAW,GAAG,GAAG,MAAM,WAAW,CAAC,CAAC;AACtF,KAAK,WAAW,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,MAAM,WAAW,GACrE,GAAG,MAAM,OAAO,GAChB,OAAO,CAAC;AACZ,KAAK,OAAO,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;CAAE,CAAC;AAEhE,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,CAKtD,CAAC;AACF,eAAO,MAAM,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,CAK1D,CAAC;AAIF,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;EAA2C,CAAC;AAC/D,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;EAA+C,CAAC"}
|
package/llms.txt
CHANGED
|
@@ -144,11 +144,28 @@ show the incompleteLabel; do not describe incomplete empty time as definitive.
|
|
|
144
144
|
|
|
145
145
|
| Import | Runtime exports and purpose |
|
|
146
146
|
| --- | --- |
|
|
147
|
-
| react-native-roster | Roster, Schedule,
|
|
148
|
-
| react-native-roster/core | layoutLane, coverageFor, flagFor, windowFor, prev, next, today, dayColumnsFor, timeAtX, timeAtY, snapToStep, byLabel, byCoverage, and core counters/caches. |
|
|
147
|
+
| react-native-roster | Roster, Schedule, useRoster, useSchedule, default slot components, RosterSelectionPopover, PortalHost, Portal, and core re-exports. |
|
|
148
|
+
| react-native-roster/core | layoutLane, coverageFor, flagFor, hasSource, extentOf, intersectionOf, unionOf, windowFor, prev, next, today, dayColumnsFor, xAtTime, timeAtX, timeAtY, snapToStep, byLabel, byCoverage, and core counters/caches. |
|
|
149
149
|
| react-native-roster/rrule | expandRuleSet, envelopeFor, expandStats, resetExpandStats, clearExpandCache; RuleSet, RosterRule, RosterDate, ExpandOptions, ExpandResult, and ExpandStats types. |
|
|
150
150
|
| react-native-roster/nativewind | Side-effect registration of Roster and Schedule with NativeWind's cssInterop, plus the registered Roster and Schedule and the rosterClassNames/scheduleClassNames mappings. Imports the optional nativewind peer. |
|
|
151
151
|
|
|
152
|
+
## Interval helpers
|
|
153
|
+
|
|
154
|
+
extentOf(segments: readonly Window[]): Window | null returns earliest start through
|
|
155
|
+
latest end, bridging disjoint segments. intersectionOf(spans: readonly Window[]):
|
|
156
|
+
Window | null returns latest start through earliest end. Both use end-exclusive
|
|
157
|
+
epoch milliseconds and return null for empty input.
|
|
158
|
+
Inputs may be unsorted, overlapping, nested, or duplicated; inputs are not mutated.
|
|
159
|
+
An empty intersection, including touching bounds, returns null. Every input is
|
|
160
|
+
validated; non-finite bounds or end <= start throw RangeError. Window is the bare
|
|
161
|
+
{ start, end } type; Span remains the axis choice type.
|
|
162
|
+
|
|
163
|
+
unionOf(spans: readonly Window[]): Window[] merges overlapping or touching
|
|
164
|
+
end-exclusive windows, sorts them by start, and keeps disjoint windows separate.
|
|
165
|
+
Empty input returns []; every returned window is a new object. The input array
|
|
166
|
+
and its windows remain untouched. Every span is validated with the same
|
|
167
|
+
RangeError rules as extentOf and intersectionOf.
|
|
168
|
+
|
|
152
169
|
No default exports. Root exports renderer inputs/models/slot input types as well as
|
|
153
170
|
core types. Core imports standard JS and Intl only. Only /rrule imports
|
|
154
171
|
rrule-temporal 1.6.0 and @js-temporal/polyfill 0.5.1. Those are installed runtime
|
|
@@ -171,7 +188,8 @@ Component props are ComponentType<Input>.
|
|
|
171
188
|
## Renderer contracts
|
|
172
189
|
|
|
173
190
|
Roster required props: lanes: Lane[], windowSpec: WindowSpec.
|
|
174
|
-
Optional:
|
|
191
|
+
Optional: now (epoch ms or null, default null), minuteStep (60), rowHeight (48),
|
|
192
|
+
pxPerMinute (minimum 0.5, fits viewport),
|
|
175
193
|
sortLanes (byLabel), highlightSource, onNavigate, onIntervalPress, onGapPress,
|
|
176
194
|
onCellPress, onIntervalHover (web only), style, headerStyle, laneLabelColumnStyle,
|
|
177
195
|
bodyStyle, laneLabelWidth (180), neverSetLabel, incompleteLabel, and zones below.
|
|
@@ -186,9 +204,14 @@ outside React state.
|
|
|
186
204
|
|
|
187
205
|
useRoster returns window, projection, orderedLanes, coverage, laneState,
|
|
188
206
|
geometryFor(lane), scroll, press(lane,x,y), ticks, contentWidth, viewport,
|
|
189
|
-
onLayout, navigate, selection, dismissSelection, and status ('empty' or 'ready'). There is no visibleRange
|
|
207
|
+
now, nowLine, onLayout, navigate, selection, dismissSelection, and status ('empty' or 'ready'). There is no visibleRange
|
|
190
208
|
field in the shipped public model. Custom layouts must wire onLayout. Custom
|
|
191
209
|
bodies compute geometry only for mounted lanes, preserving virtualization.
|
|
210
|
+
now retains the raw instant. nowLine is { x, now }, using xAtTime with the fitted
|
|
211
|
+
projection.pxPerMinute scale; it is null when now is null or outside the
|
|
212
|
+
end-exclusive window. The caller owns clock updates.
|
|
213
|
+
The vertical now line follows horizontal scroll without invalidating mounted lanes.
|
|
214
|
+
The every-zone gallery offers a fixed window-midpoint now toggle.
|
|
192
215
|
A zero-duration window has contentWidth=0 and renders no Roster body. Positive
|
|
193
216
|
windows use their exact elapsed duration, including sub-minute spans. Cell times
|
|
194
217
|
are clamped up to window.start and rejected at or beyond window.end.
|
|
@@ -214,8 +237,11 @@ interaction. Input types, including HeaderCellInput, are exported from root.
|
|
|
214
237
|
Mount a React context provider above Roster for extra consumer data, and read it with useContext in a module-scope slot component.
|
|
215
238
|
Avoid inline closures or memoized factories returning a new component per render; new interval types remount every interval and defeat the body's content key.
|
|
216
239
|
|
|
217
|
-
RosterBody composes the exported RosterBodyLayout (gridZone/listZone
|
|
218
|
-
scroll wiring) and RosterLaneList (LegendList,
|
|
240
|
+
RosterBody composes the exported RosterBodyLayout (gridZone/listZone and optional
|
|
241
|
+
absolute overlayZone nodes with scroll wiring) and RosterLaneList (LegendList,
|
|
242
|
+
geometryFor, and LaneRow mounting). BodyInput extends LaneListInput with ticks,
|
|
243
|
+
gridComponent, nowLine, and nowLineComponent. The body picks lane-list props
|
|
244
|
+
explicitly; the overlay wrapper mounts only when overlayZone is provided.
|
|
219
245
|
Keep its viewport gate and measured estimatedListSize in custom compositions.
|
|
220
246
|
|
|
221
247
|
## Roster zones
|
|
@@ -227,11 +253,12 @@ Keep its viewport gate and measured estimatedListSize in custom compositions.
|
|
|
227
253
|
| `headerCellComponent` | `HeaderCellInput` (`tick`) | `RosterHeaderCell`: tick label. |
|
|
228
254
|
| `intervalComponent` | `rect`, `layer`, `lane`, `highlighted` | `RosterInterval`: positioned colored rect, with final inset bounds. |
|
|
229
255
|
| `gapComponent` | `rect`, `layer`, `lane` | `RosterGap`: no visible content; the row supplies pressable bounds. |
|
|
256
|
+
| `nowLineComponent` | `RosterNowLineInput` (`x`, `now`) | `RosterNowLine`: noninteractive 2 px red vertical line across the body. |
|
|
230
257
|
| `gridComponent` | `ticks`, `contentWidth` | `RosterGrid`: one hairline per tick behind every lane. |
|
|
231
258
|
| `cornerZone` | `ReactNode` | `RosterCorner`: nothing; the cell above the labels, laneLabelWidth wide. |
|
|
232
259
|
| `headerComponent` | `ticks`, `projection`, `scroll`, `contentWidth`, `headerCellComponent` | `RosterHeader`: frozen header following horizontal offset. |
|
|
233
260
|
| `laneLabelColumnComponent` | `labels: LaneLabelInput[]`, `projection`, `scroll`, `laneLabelComponent` | `RosterLaneLabelColumn`: frozen labels following vertical offset. |
|
|
234
|
-
| `bodyComponent` | Ordered `lanes`, `window`, `geometryFor`, `projection`, `scroll`, `press`, `ticks`, `viewport`, `contentWidth`, highlight/hover, incomplete label, and rect components | `RosterBody`: virtualized lanes. |
|
|
261
|
+
| `bodyComponent` | Ordered `lanes`, `window`, `geometryFor`, `projection`, `scroll`, `press`, `ticks`, `viewport`, `contentWidth`, `nowLine`, `nowLineComponent`, highlight/hover, incomplete label, and rect components | `RosterBody`: virtualized lanes. |
|
|
235
262
|
|
|
236
263
|
## Selection
|
|
237
264
|
|
|
@@ -349,6 +376,7 @@ ordinary wall time resumes. timeAtY inverts this region to the absolute occurren
|
|
|
349
376
|
The repeat divider uses dividerY, the projected transition instant, even when
|
|
350
377
|
the surviving repeat regions have unequal heights.
|
|
351
378
|
|
|
379
|
+
xAtTime(projection,window,time) returns horizontal pixels from the window origin.
|
|
352
380
|
timeAtX(projection,window,x) returns absolute time with origin from window.
|
|
353
381
|
timeAtY(projection,columnIndex,y) returns an absolute occurrence or null for
|
|
354
382
|
skipped time/outside bounds. Inverse times stay below each scale piece's exclusive
|
|
@@ -519,6 +547,22 @@ ruleSetEditorZone. useRuleSetDraft owns text, parse result, and the applied set;
|
|
|
519
547
|
Apply validates before updating the roster, keeping the last valid set on error.
|
|
520
548
|
These are demo hooks/zones, not library exports.
|
|
521
549
|
|
|
550
|
+
The home page also links to /showcase. Its feature lives in
|
|
551
|
+
demo/components/team-roster. Every generated event has a scheduled window, title,
|
|
552
|
+
description, expected attendees, and seeded attendance for elapsed time. The hook
|
|
553
|
+
owns a fixed seeded now separating past, live, and future events. Attendees have
|
|
554
|
+
expected, pending, present, attended, or absent presence states. Present spans draw
|
|
555
|
+
through now without exposing future departures; immutable seeded arrival and
|
|
556
|
+
departure facts keep late departures present after scheduled end.
|
|
557
|
+
TeamInterval draws disjoint strips over the union of attendances on the lighter
|
|
558
|
+
scheduled block, retaining gaps and overhang. EventDetail in team-roster/events
|
|
559
|
+
is the intervalDetailComponent; its popover shows named presence rows against a
|
|
560
|
+
shared shaded scheduled band and scale. The footer status line defaults to the
|
|
561
|
+
attendance legend and scheduled-band explanation. Web hover or visible keyboard
|
|
562
|
+
focus shows row detail; keyboard focus wins when both are active. Native taps
|
|
563
|
+
toggle detail or switch rows. Event detail belongs to the popover; the inspector
|
|
564
|
+
retains member selection. See [showcase](./demo/components/team-roster/README.md).
|
|
565
|
+
|
|
522
566
|
Every route exposes live counter functions on web window.__roster. Its identity
|
|
523
567
|
stays stable until unmount; on-screen snapshots sample every 500 ms. The 200-lane
|
|
524
568
|
route feeds real adapter output to workload W and includes cold-layout, rule-hour,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-roster",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Layered intervals with provenance across lanes and a shared time axis for React Native.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"rrule-temporal": "1.6.0"
|
|
125
125
|
},
|
|
126
126
|
"devDependencies": {
|
|
127
|
-
"@biomejs/biome": "2.5.
|
|
127
|
+
"@biomejs/biome": "2.5.13",
|
|
128
128
|
"@legendapp/list": "2.0.19",
|
|
129
129
|
"@semantic-release/changelog": "^7.0.0",
|
|
130
130
|
"@semantic-release/commit-analyzer": "13.0.1",
|
|
@@ -6,13 +6,13 @@ This feature is about a roster; its children are lanes.
|
|
|
6
6
|
`XxxInput` slot input type from `roster.types.ts`
|
|
7
7
|
|
|
8
8
|
- `index.tsx`: the chassis; calls `useRoster`, branches on `status`, composes zones
|
|
9
|
-
- `use-roster.ts`: the hook; owns window, projection, scroll, geometry, and selection
|
|
9
|
+
- `use-roster.ts`: the hook; owns window, projection, nowLine, scroll, geometry, and selection
|
|
10
10
|
- `use-roster-press.ts`: isolates the stable press ref so React Compiler can retain derived body inputs
|
|
11
11
|
- `layout.tsx`: arranges corner, header, label column, and body regions only
|
|
12
12
|
- `roster.types.ts`: props, model, and every slot input type
|
|
13
|
-
- `body-layout.tsx`: arranges grid and
|
|
13
|
+
- `body-layout.tsx`: arranges grid, list, and optional absolute overlay nodes with horizontal scroll wiring
|
|
14
14
|
- `parts/lane-list.tsx`: `RosterLaneList` owns LegendList and its lane render callback
|
|
15
|
-
- `parts/`: collection-level parts (body, header, header cell, grid, corner, label column, empty)
|
|
15
|
+
- `parts/`: collection-level parts (body, header, header cell, grid, now line, corner, label column, empty)
|
|
16
16
|
- `lanes/`: `LaneRow`, the interval-hover platform pair, and lane-local parts
|
|
17
17
|
- `utils/`: ticks and the body content key
|
|
18
18
|
|
|
@@ -20,8 +20,10 @@ Interval and gap components live in `../layers`; press geometry and `regionStyle
|
|
|
20
20
|
in `../primitives`. Zone contracts are documented in the README's Roster zones
|
|
21
21
|
section and in `llms.txt`. Tests: `test/components/roster`.
|
|
22
22
|
|
|
23
|
-
`RosterBody` gates
|
|
24
|
-
measurement and composes the body layout and lane list.
|
|
23
|
+
This feature is about a roster body; its children are lanes. `RosterBody` gates
|
|
24
|
+
measurement and composes the body layout and lane list. `BodyInput` extends the
|
|
25
|
+
positive `LaneListInput` with ticks, grid, and now-line inputs; the body explicitly
|
|
26
|
+
picks the lane-list props. The `onRowRender` prop on
|
|
25
27
|
`RosterBody` and `RosterLaneList` is a development-only Profiler hook used by the
|
|
26
28
|
gallery, not a supported customization point. Production Profiler callbacks are disabled.
|
|
27
29
|
|
|
@@ -29,6 +31,15 @@ Input-bearing slots accept component types and mount in the data-owning parts.
|
|
|
29
31
|
The chassis binds defaults once; emptyZone and cornerZone accept nodes. The body
|
|
30
32
|
content key tracks interval and gap component identity, including class components.
|
|
31
33
|
|
|
34
|
+
`now` is a controlled epoch millisecond value, default null. `useRoster` derives
|
|
35
|
+
`nowLine` (`{ x, now }`) during render via `xAtTime` using the fitted horizontal
|
|
36
|
+
scale; it is null when `now` is null or outside the end-exclusive window. The model
|
|
37
|
+
retains the raw `now` instant. The exported `RosterNowLine` fills the body's `overlayZone`
|
|
38
|
+
with a noninteractive 2 px red line; `nowLineComponent` accepts the exported
|
|
39
|
+
`RosterNowLineInput` (`{ x, now }`). The overlay scrolls horizontally with the
|
|
40
|
+
content. Now values and component identity never enter the lane list or body
|
|
41
|
+
content key. The caller owns clock updates.
|
|
42
|
+
|
|
32
43
|
`selection/` holds the runtime-swappable presentation strategies (native popover, web popover) for one `SelectionLayoutProps` contract.
|
|
33
44
|
|
|
34
45
|
- `selection/selection-layout.types.ts`: exported `SelectionLayoutProps`, with body
|
|
@@ -8,12 +8,26 @@ export function RosterBodyLayout({
|
|
|
8
8
|
viewport,
|
|
9
9
|
gridZone,
|
|
10
10
|
listZone,
|
|
11
|
+
overlayZone,
|
|
11
12
|
}: Pick<BodyInput, 'scroll' | 'contentWidth' | 'viewport'> & {
|
|
12
13
|
/** Noninteractive grid behind the lane list. */
|
|
13
14
|
gridZone: ReactNode;
|
|
14
15
|
/** Virtualized lane collection within the measured viewport. */
|
|
15
16
|
listZone: ReactNode;
|
|
17
|
+
/** Noninteractive content above the grid and lane list, following horizontal scroll. */
|
|
18
|
+
overlayZone?: ReactNode;
|
|
16
19
|
}) {
|
|
20
|
+
let overlay: ReactNode = null;
|
|
21
|
+
if (overlayZone != null) {
|
|
22
|
+
overlay = (
|
|
23
|
+
<View
|
|
24
|
+
pointerEvents="none"
|
|
25
|
+
style={{ position: 'absolute', top: 0, bottom: 0, left: 0, right: 0, zIndex: 1 }}
|
|
26
|
+
>
|
|
27
|
+
{overlayZone}
|
|
28
|
+
</View>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
17
31
|
const [contentOffset] = useState(() => ({ x: scroll.x.get(), y: 0 }));
|
|
18
32
|
const bodyRef = scroll.bodyRef;
|
|
19
33
|
useEffect(() => {
|
|
@@ -32,6 +46,7 @@ export function RosterBodyLayout({
|
|
|
32
46
|
<View style={{ width: contentWidth, height: viewport.height }}>
|
|
33
47
|
{gridZone}
|
|
34
48
|
{listZone}
|
|
49
|
+
{overlay}
|
|
35
50
|
</View>
|
|
36
51
|
</ScrollView>
|
|
37
52
|
);
|
|
@@ -11,6 +11,7 @@ import { RosterGrid } from './parts/grid';
|
|
|
11
11
|
import { RosterHeader } from './parts/header';
|
|
12
12
|
import { RosterHeaderCell } from './parts/header-cell';
|
|
13
13
|
import { RosterLaneLabelColumn } from './parts/lane-label-column';
|
|
14
|
+
import { RosterNowLine } from './parts/now-line';
|
|
14
15
|
import type { RosterProps } from './roster.types';
|
|
15
16
|
import { RosterSelectionPopover } from './selection/selection-layout';
|
|
16
17
|
import type { SelectionLayoutProps } from './selection/selection-layout.types';
|
|
@@ -21,6 +22,7 @@ const defaultCornerZone = <RosterCorner />;
|
|
|
21
22
|
|
|
22
23
|
export function Roster(props: RosterProps) {
|
|
23
24
|
const {
|
|
25
|
+
nowLine,
|
|
24
26
|
selection,
|
|
25
27
|
dismissSelection,
|
|
26
28
|
status,
|
|
@@ -49,6 +51,7 @@ export function Roster(props: RosterProps) {
|
|
|
49
51
|
intervalComponent = RosterInterval,
|
|
50
52
|
gapComponent = RosterGap,
|
|
51
53
|
gridComponent = RosterGrid,
|
|
54
|
+
nowLineComponent = RosterNowLine,
|
|
52
55
|
incompleteLabel = 'Availability may be incomplete',
|
|
53
56
|
neverSetLabel = 'No availability set',
|
|
54
57
|
} = props;
|
|
@@ -129,6 +132,8 @@ export function Roster(props: RosterProps) {
|
|
|
129
132
|
contentZone={contentZone}
|
|
130
133
|
anchorZone={
|
|
131
134
|
<BodyComponent
|
|
135
|
+
nowLine={nowLine}
|
|
136
|
+
nowLineComponent={nowLineComponent}
|
|
132
137
|
lanes={orderedLanes}
|
|
133
138
|
window={window}
|
|
134
139
|
geometryFor={geometryFor}
|
|
@@ -9,7 +9,26 @@ export function RosterBody(
|
|
|
9
9
|
onRowRender?: ProfilerOnRenderCallback;
|
|
10
10
|
},
|
|
11
11
|
) {
|
|
12
|
-
const {
|
|
12
|
+
const {
|
|
13
|
+
nowLine,
|
|
14
|
+
nowLineComponent: NowLineComponent,
|
|
15
|
+
ticks,
|
|
16
|
+
gridComponent: GridComponent,
|
|
17
|
+
lanes,
|
|
18
|
+
geometryFor,
|
|
19
|
+
projection,
|
|
20
|
+
scroll,
|
|
21
|
+
press,
|
|
22
|
+
contentWidth,
|
|
23
|
+
viewport,
|
|
24
|
+
window,
|
|
25
|
+
intervalComponent,
|
|
26
|
+
gapComponent,
|
|
27
|
+
highlightSource,
|
|
28
|
+
onIntervalHover,
|
|
29
|
+
incompleteLabel,
|
|
30
|
+
onRowRender,
|
|
31
|
+
} = props;
|
|
13
32
|
// LegendList requires a measured viewport and does not support static rendering.
|
|
14
33
|
if (viewport.width <= 0 || viewport.height <= 0) return null;
|
|
15
34
|
return (
|
|
@@ -18,7 +37,25 @@ export function RosterBody(
|
|
|
18
37
|
contentWidth={contentWidth}
|
|
19
38
|
viewport={viewport}
|
|
20
39
|
gridZone={<GridComponent ticks={ticks} contentWidth={contentWidth} />}
|
|
21
|
-
listZone={
|
|
40
|
+
listZone={
|
|
41
|
+
<RosterLaneList
|
|
42
|
+
lanes={lanes}
|
|
43
|
+
geometryFor={geometryFor}
|
|
44
|
+
projection={projection}
|
|
45
|
+
scroll={scroll}
|
|
46
|
+
press={press}
|
|
47
|
+
contentWidth={contentWidth}
|
|
48
|
+
viewport={viewport}
|
|
49
|
+
window={window}
|
|
50
|
+
intervalComponent={intervalComponent}
|
|
51
|
+
gapComponent={gapComponent}
|
|
52
|
+
highlightSource={highlightSource}
|
|
53
|
+
onIntervalHover={onIntervalHover}
|
|
54
|
+
incompleteLabel={incompleteLabel}
|
|
55
|
+
onRowRender={onRowRender}
|
|
56
|
+
/>
|
|
57
|
+
}
|
|
58
|
+
overlayZone={nowLine ? <NowLineComponent {...nowLine} /> : null}
|
|
22
59
|
/>
|
|
23
60
|
);
|
|
24
61
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LegendList } from '@legendapp/list';
|
|
2
2
|
import { Profiler, type ProfilerOnRenderCallback, useState } from 'react';
|
|
3
3
|
import { LaneRow } from '../lanes/lane';
|
|
4
|
-
import type {
|
|
4
|
+
import type { LaneListInput } from '../roster.types';
|
|
5
5
|
import { bodyContentKey } from '../utils/body-content-key';
|
|
6
6
|
|
|
7
7
|
export function RosterLaneList({
|
|
@@ -19,7 +19,7 @@ export function RosterLaneList({
|
|
|
19
19
|
onIntervalHover,
|
|
20
20
|
incompleteLabel,
|
|
21
21
|
onRowRender,
|
|
22
|
-
}:
|
|
22
|
+
}: LaneListInput & {
|
|
23
23
|
/** Development-only Profiler hook used by the gallery; not a supported customization point. */
|
|
24
24
|
onRowRender?: ProfilerOnRenderCallback;
|
|
25
25
|
}) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { View } from 'react-native';
|
|
2
|
+
import type { RosterNowLineInput } from '../roster.types';
|
|
3
|
+
|
|
4
|
+
export function RosterNowLine({ x }: RosterNowLineInput) {
|
|
5
|
+
return (
|
|
6
|
+
<View
|
|
7
|
+
testID="roster-now-line"
|
|
8
|
+
pointerEvents="none"
|
|
9
|
+
style={{
|
|
10
|
+
position: 'absolute',
|
|
11
|
+
left: x,
|
|
12
|
+
top: 0,
|
|
13
|
+
bottom: 0,
|
|
14
|
+
width: 2,
|
|
15
|
+
backgroundColor: '#dc2626',
|
|
16
|
+
}}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -48,6 +48,8 @@ export type RosterInput = {
|
|
|
48
48
|
lanes: Lane[];
|
|
49
49
|
windowSpec: WindowSpec;
|
|
50
50
|
minuteStep?: number;
|
|
51
|
+
/** Current instant in epoch milliseconds; default null draws no now line. */
|
|
52
|
+
now?: number | null;
|
|
51
53
|
sortLanes?: LaneComparator;
|
|
52
54
|
highlightSource?: Source;
|
|
53
55
|
onNavigate?: (next: WindowSpec) => void;
|
|
@@ -76,6 +78,8 @@ export type RosterModel = {
|
|
|
76
78
|
press: (lane: Lane, x: number, y: number) => void;
|
|
77
79
|
status: 'empty' | 'ready';
|
|
78
80
|
ticks: RosterTick[];
|
|
81
|
+
now: number | null;
|
|
82
|
+
nowLine: RosterNowLineInput | null;
|
|
79
83
|
contentWidth: number;
|
|
80
84
|
viewport: { width: number; height: number };
|
|
81
85
|
onLayout: (input: LayoutChangeEvent) => void;
|
|
@@ -89,6 +93,7 @@ export type LaneLabelInput = {
|
|
|
89
93
|
incompleteLabel: string;
|
|
90
94
|
neverSetLabel: string;
|
|
91
95
|
};
|
|
96
|
+
export type RosterNowLineInput = { x: number; now: number };
|
|
92
97
|
export type HeaderCellInput = { tick: RosterTick };
|
|
93
98
|
export type GridInput = { ticks: RosterTick[]; contentWidth: number };
|
|
94
99
|
export type HeaderInput = Pick<RosterModel, 'ticks' | 'projection' | 'scroll' | 'contentWidth'> & {
|
|
@@ -100,16 +105,9 @@ export type LabelColumnInput = Pick<RosterModel, 'projection' | 'scroll'> & {
|
|
|
100
105
|
/** Lane label filler, positioned at the fixed row height. */
|
|
101
106
|
laneLabelComponent: ComponentType<LaneLabelInput>;
|
|
102
107
|
};
|
|
103
|
-
export type
|
|
108
|
+
export type LaneListInput = Pick<
|
|
104
109
|
RosterModel,
|
|
105
|
-
| '
|
|
106
|
-
| 'projection'
|
|
107
|
-
| 'scroll'
|
|
108
|
-
| 'press'
|
|
109
|
-
| 'ticks'
|
|
110
|
-
| 'contentWidth'
|
|
111
|
-
| 'viewport'
|
|
112
|
-
| 'window'
|
|
110
|
+
'geometryFor' | 'projection' | 'scroll' | 'press' | 'contentWidth' | 'viewport' | 'window'
|
|
113
111
|
> & {
|
|
114
112
|
lanes: Lane[];
|
|
115
113
|
highlightSource?: Source;
|
|
@@ -119,6 +117,12 @@ export type BodyInput = Pick<
|
|
|
119
117
|
intervalComponent: ComponentType<IntervalInput>;
|
|
120
118
|
/** Removed rect filler, placed inside a pressable by LaneRow. */
|
|
121
119
|
gapComponent: ComponentType<GapInput>;
|
|
120
|
+
};
|
|
121
|
+
export type BodyInput = LaneListInput & {
|
|
122
|
+
ticks: RosterTick[];
|
|
123
|
+
nowLine: RosterNowLineInput | null;
|
|
124
|
+
/** Noninteractive current-time line positioned in body content pixels. */
|
|
125
|
+
nowLineComponent: ComponentType<RosterNowLineInput>;
|
|
122
126
|
/** Noninteractive tick lines behind every lane, sized to the content width. */
|
|
123
127
|
gridComponent: ComponentType<GridInput>;
|
|
124
128
|
};
|
|
@@ -145,6 +149,8 @@ export type RosterStyleProps = {
|
|
|
145
149
|
};
|
|
146
150
|
export type RosterProps = Omit<RosterInput, 'selectable'> &
|
|
147
151
|
RosterStyleProps & {
|
|
152
|
+
/** Noninteractive current-time line; RosterNowLine spans the body height at x. */
|
|
153
|
+
nowLineComponent?: ComponentType<RosterNowLineInput>;
|
|
148
154
|
/**
|
|
149
155
|
* Selected interval content; absent means interval presses retain no selection.
|
|
150
156
|
* Lives on RosterProps because the chassis mounts content and enables useRoster selection.
|