react-native-roster 0.0.1 → 0.2.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.
Files changed (122) hide show
  1. package/README.md +209 -32
  2. package/dist/src/components/primitives/portal.d.ts +12 -0
  3. package/dist/src/components/primitives/portal.d.ts.map +1 -0
  4. package/dist/src/components/primitives/portal.js +41 -0
  5. package/dist/src/components/primitives/portal.js.map +1 -0
  6. package/dist/src/components/roster/body-layout.d.ts +9 -0
  7. package/dist/src/components/roster/body-layout.d.ts.map +1 -0
  8. package/dist/src/components/roster/body-layout.js +15 -0
  9. package/dist/src/components/roster/body-layout.js.map +1 -0
  10. package/dist/src/components/roster/index.d.ts +2 -1
  11. package/dist/src/components/roster/index.d.ts.map +1 -1
  12. package/dist/src/components/roster/index.js +34 -27
  13. package/dist/src/components/roster/index.js.map +1 -1
  14. package/dist/src/components/roster/lanes/lane.d.ts +2 -2
  15. package/dist/src/components/roster/lanes/lane.d.ts.map +1 -1
  16. package/dist/src/components/roster/lanes/lane.js +4 -8
  17. package/dist/src/components/roster/lanes/lane.js.map +1 -1
  18. package/dist/src/components/roster/parts/body.d.ts +3 -3
  19. package/dist/src/components/roster/parts/body.d.ts.map +1 -1
  20. package/dist/src/components/roster/parts/body.js +5 -20
  21. package/dist/src/components/roster/parts/body.js.map +1 -1
  22. package/dist/src/components/roster/parts/header-cell.d.ts +2 -4
  23. package/dist/src/components/roster/parts/header-cell.d.ts.map +1 -1
  24. package/dist/src/components/roster/parts/header-cell.js.map +1 -1
  25. package/dist/src/components/roster/parts/header.d.ts +1 -1
  26. package/dist/src/components/roster/parts/header.d.ts.map +1 -1
  27. package/dist/src/components/roster/parts/header.js +2 -2
  28. package/dist/src/components/roster/parts/header.js.map +1 -1
  29. package/dist/src/components/roster/parts/lane-label-column.d.ts +1 -1
  30. package/dist/src/components/roster/parts/lane-label-column.d.ts.map +1 -1
  31. package/dist/src/components/roster/parts/lane-label-column.js +2 -2
  32. package/dist/src/components/roster/parts/lane-label-column.js.map +1 -1
  33. package/dist/src/components/roster/parts/lane-list.d.ts +7 -0
  34. package/dist/src/components/roster/parts/lane-list.d.ts.map +1 -0
  35. package/dist/src/components/roster/parts/lane-list.js +26 -0
  36. package/dist/src/components/roster/parts/lane-list.js.map +1 -0
  37. package/dist/src/components/roster/roster.types.d.ts +48 -21
  38. package/dist/src/components/roster/roster.types.d.ts.map +1 -1
  39. package/dist/src/components/roster/selection/selection-layout.d.ts +4 -0
  40. package/dist/src/components/roster/selection/selection-layout.d.ts.map +1 -0
  41. package/dist/src/components/roster/selection/selection-layout.js +82 -0
  42. package/dist/src/components/roster/selection/selection-layout.js.map +1 -0
  43. package/dist/src/components/roster/selection/selection-layout.types.d.ts +25 -0
  44. package/dist/src/components/roster/selection/selection-layout.types.d.ts.map +1 -0
  45. package/dist/src/components/roster/selection/selection-layout.types.js +3 -0
  46. package/dist/src/components/roster/selection/selection-layout.types.js.map +1 -0
  47. package/dist/src/components/roster/selection/selection-layout.web.d.ts +4 -0
  48. package/dist/src/components/roster/selection/selection-layout.web.d.ts.map +1 -0
  49. package/dist/src/components/roster/selection/selection-layout.web.js +52 -0
  50. package/dist/src/components/roster/selection/selection-layout.web.js.map +1 -0
  51. package/dist/src/components/roster/use-roster-press.d.ts +6 -0
  52. package/dist/src/components/roster/use-roster-press.d.ts.map +1 -0
  53. package/dist/src/components/roster/use-roster-press.js +61 -0
  54. package/dist/src/components/roster/use-roster-press.js.map +1 -0
  55. package/dist/src/components/roster/use-roster.d.ts.map +1 -1
  56. package/dist/src/components/roster/use-roster.js +40 -30
  57. package/dist/src/components/roster/use-roster.js.map +1 -1
  58. package/dist/src/components/roster/utils/body-content-key.d.ts +1 -1
  59. package/dist/src/components/roster/utils/body-content-key.d.ts.map +1 -1
  60. package/dist/src/components/roster/utils/body-content-key.js +10 -10
  61. package/dist/src/components/roster/utils/body-content-key.js.map +1 -1
  62. package/dist/src/components/schedule/days/day.d.ts +2 -2
  63. package/dist/src/components/schedule/days/day.d.ts.map +1 -1
  64. package/dist/src/components/schedule/days/day.js +2 -11
  65. package/dist/src/components/schedule/days/day.js.map +1 -1
  66. package/dist/src/components/schedule/days/header-layout.d.ts +1 -1
  67. package/dist/src/components/schedule/days/header-layout.d.ts.map +1 -1
  68. package/dist/src/components/schedule/days/parts/column.d.ts +1 -1
  69. package/dist/src/components/schedule/days/parts/column.d.ts.map +1 -1
  70. package/dist/src/components/schedule/days/parts/column.js +4 -8
  71. package/dist/src/components/schedule/days/parts/column.js.map +1 -1
  72. package/dist/src/components/schedule/index.d.ts.map +1 -1
  73. package/dist/src/components/schedule/index.js +7 -8
  74. package/dist/src/components/schedule/index.js.map +1 -1
  75. package/dist/src/components/schedule/schedule.types.d.ts +17 -17
  76. package/dist/src/components/schedule/schedule.types.d.ts.map +1 -1
  77. package/dist/src/core/index.d.ts +1 -0
  78. package/dist/src/core/index.d.ts.map +1 -1
  79. package/dist/src/core/index.js +3 -1
  80. package/dist/src/core/index.js.map +1 -1
  81. package/dist/src/core/source.d.ts +4 -0
  82. package/dist/src/core/source.d.ts.map +1 -0
  83. package/dist/src/core/source.js +9 -0
  84. package/dist/src/core/source.js.map +1 -0
  85. package/dist/src/index.d.ts +6 -1
  86. package/dist/src/index.d.ts.map +1 -1
  87. package/dist/src/index.js +10 -1
  88. package/dist/src/index.js.map +1 -1
  89. package/dist/src/nativewind/index.d.ts +28 -27
  90. package/dist/src/nativewind/index.d.ts.map +1 -1
  91. package/docs/migrations.md +61 -0
  92. package/llms.txt +112 -30
  93. package/package.json +12 -5
  94. package/src/components/layers/README.md +7 -3
  95. package/src/components/primitives/README.md +13 -2
  96. package/src/components/primitives/portal.tsx +48 -0
  97. package/src/components/roster/README.md +62 -5
  98. package/src/components/roster/body-layout.tsx +38 -0
  99. package/src/components/roster/index.tsx +109 -46
  100. package/src/components/roster/lanes/lane.tsx +16 -13
  101. package/src/components/roster/parts/body.tsx +17 -84
  102. package/src/components/roster/parts/header-cell.tsx +2 -2
  103. package/src/components/roster/parts/header.tsx +7 -2
  104. package/src/components/roster/parts/lane-label-column.tsx +2 -2
  105. package/src/components/roster/parts/lane-list.tsx +76 -0
  106. package/src/components/roster/roster.types.ts +47 -17
  107. package/src/components/roster/selection/selection-layout.tsx +90 -0
  108. package/src/components/roster/selection/selection-layout.types.ts +20 -0
  109. package/src/components/roster/selection/selection-layout.web.tsx +88 -0
  110. package/src/components/roster/use-roster-press.ts +74 -0
  111. package/src/components/roster/use-roster.ts +57 -44
  112. package/src/components/roster/utils/body-content-key.ts +13 -13
  113. package/src/components/schedule/README.md +8 -3
  114. package/src/components/schedule/days/day.tsx +31 -18
  115. package/src/components/schedule/days/header-layout.tsx +1 -1
  116. package/src/components/schedule/days/parts/column.tsx +10 -12
  117. package/src/components/schedule/index.tsx +20 -21
  118. package/src/components/schedule/schedule.types.ts +13 -13
  119. package/src/core/README.md +4 -0
  120. package/src/core/index.ts +1 -0
  121. package/src/core/source.ts +9 -0
  122. package/src/index.ts +7 -0
package/README.md CHANGED
@@ -34,7 +34,7 @@ hundred people without lying about time zones, this is the one.
34
34
  z-order; coverage math unions availability, subtracts bookings, and sorts.
35
35
  - **Recurrence adapter.** Weekly, daily, and monthly rules with exclusions,
36
36
  caps, and content-keyed caches, kept out of the core.
37
- - **Zones everywhere.** Every visual region is an optional render function, and
37
+ - **Zones everywhere.** Input-bearing regions accept component types, singletons accept nodes, and
38
38
  every chrome region takes `style` plus a NativeWind `className` twin.
39
39
  - **Virtualized and measured.** Geometry runs only for mounted lanes; CI gates
40
40
  layout, coverage, bundle size, and browser action budgets.
@@ -130,7 +130,7 @@ export function RecurringExample() {
130
130
 
131
131
  Tuesday is a gap carrying the dated exclusion; the other weekdays carry the
132
132
  include rule. Expand once per `windowFor(spec)` in your screen's hook, never
133
- inside a zone filler; content-keyed caches reuse unchanged occurrences. The
133
+ inside a slot component; content-keyed caches reuse unchanged occurrences. The
134
134
  [adapter guide](./docs/adapters.md) covers validation, caps, cache lifetime,
135
135
  and mapping tables or feeds without a recurrence dependency;
136
136
  [recurrence semantics](./docs/recurrence.md) records the exact anchor, UNTIL,
@@ -167,12 +167,13 @@ and "Availability may be incomplete"; both are localizable props.
167
167
 
168
168
  | Import | Shipped surface |
169
169
  | --- | --- |
170
- | `react-native-roster` | `Roster`, `Schedule`, `useRoster`, `useSchedule`, zone fillers, and all core exports. |
170
+ | `react-native-roster` | `Roster`, `Schedule`, hooks, slot components, `RosterSelectionPopover`, `PortalHost`, `Portal`, and all core exports. |
171
171
  | `react-native-roster/core` | Types, `layoutLane`, `coverageFor`, `flagFor`, axis helpers, comparators, and counters. Standard JavaScript and `Intl` only. |
172
172
  | `react-native-roster/rrule` | `expandRuleSet`, `envelopeFor`, types, and expansion counters and caches. Uses pinned `rrule-temporal` and `@js-temporal/polyfill`. |
173
173
  | `react-native-roster/nativewind` | Registers `Roster` and `Schedule` with NativeWind so their `className` props resolve; re-exports the registered components. |
174
174
 
175
- Root and core never import recurrence dependencies. Metro selects TypeScript
175
+ Root and core never import recurrence dependencies. Public entry aliases retain the
176
+ implementation function identities while keeping CommonJS export overhead within the size gates. Metro selects TypeScript
176
177
  source through the `react-native` export condition; other bundlers select
177
178
  emitted CommonJS with declarations in `dist/src`. The emit is CommonJS, so
178
179
  importing one function from the root costs the whole root bundle; import from
@@ -203,23 +204,44 @@ to `byLabel`; `byCoverage({ measure })` sorts by coverage descending.
203
204
 
204
205
  ## Roster zones
205
206
 
206
- Every zone is an optional render function. Compose the exported default filler
207
- inside a replacement to retain scrolling, geometry, or press behavior.
207
+ Props ending in `Component` accept `ComponentType<Input>` and are mounted by React.
208
+ Props ending in `Zone` accept `ReactNode`. Define components at module scope so
209
+ state survives rerenders; hooks and class components are supported. Compose the
210
+ exported default components inside replacements to retain scrolling, geometry,
211
+ or press behavior. Pass `null` to a node slot to suppress its default.
208
212
 
209
- | Zone | Receives | Default filler and behavior |
213
+ | Slot | Component inputs or node | Default and behavior |
210
214
  | --- | --- | --- |
211
- | `emptyZone` | Nothing | `RosterEmpty`: No lanes. |
212
- | `cornerZone` | Nothing | `RosterCorner`: nothing; the cell above the labels, `laneLabelWidth` wide. |
213
- | `laneLabelZone` | `lane`, `flag`, `complete`, `viewTimezone`, localized labels | `RosterLaneLabel`: label, differing IANA zone badge, and notices. |
214
- | `headerCellZone` | `tick` | `RosterHeaderCell`: tick label. |
215
- | `intervalZone` | `rect`, `layer`, `lane`, `highlighted` | `RosterInterval`: positioned colored rect, with final inset bounds. |
216
- | `gapZone` | `rect`, `layer`, `lane` | `RosterGap`: no visible content; the row supplies pressable bounds. |
217
- | `gridZone` | `ticks`, `contentWidth` | `RosterGrid`: one hairline per tick behind every lane. |
218
- | `headerZone` | `ticks`, `projection`, `scroll`, `contentWidth`, `headerCellZone` | `RosterHeader`: frozen header following horizontal offset. |
219
- | `laneLabelColumnZone` | `labels`, `projection`, `scroll`, `laneLabelZone` | `RosterLaneLabelColumn`: frozen labels following vertical offset. |
220
- | `bodyZone` | Ordered `lanes`, `window`, `geometryFor`, `projection`, `scroll`, `press`, `ticks`, `viewport`, `contentWidth`, highlight and hover, incomplete label, and rect zones | `RosterBody`: virtualized lanes. |
221
-
222
- A custom interval filler positions at `rect.x/y`, uses `rect.width/height/z`,
215
+ | `emptyZone` | `ReactNode` | `RosterEmpty`: No lanes. |
216
+ | `cornerZone` | `ReactNode` | `RosterCorner`: nothing; the cell above the labels, `laneLabelWidth` wide. |
217
+ | `laneLabelComponent` | `lane`, `flag`, `complete`, `viewTimezone`, localized labels | `RosterLaneLabel`: label, differing IANA zone badge, and notices. |
218
+ | `headerCellComponent` | `HeaderCellInput` (`tick`) | `RosterHeaderCell`: tick label. |
219
+ | `intervalComponent` | `rect`, `layer`, `lane`, `highlighted` | `RosterInterval`: positioned colored rect, with final inset bounds. |
220
+ | `intervalDetailComponent` | `rect`, `layer`, `lane`, `highlighted`, absolute `start` and `end`, `viewTimezone` | Absent by default; enables selection and fills its details. |
221
+ | `selectionLayout` | `SelectionLayoutProps`: nodes, targetBounds, open, dismissal, host, and shared scroll | `RosterSelectionPopover`: native portal or Radix web popover; replace at runtime. |
222
+ | `gapComponent` | `rect`, `layer`, `lane` | `RosterGap`: no visible content; the row supplies pressable bounds. |
223
+ | `gridComponent` | `ticks`, `contentWidth` | `RosterGrid`: one hairline per tick behind every lane. |
224
+ | `headerComponent` | `ticks`, `projection`, `scroll`, `contentWidth`, `headerCellComponent` | `RosterHeader`: frozen header following horizontal offset. |
225
+ | `laneLabelColumnComponent` | `labels`, `projection`, `scroll`, `laneLabelComponent` | `RosterLaneLabelColumn`: frozen labels following vertical offset. |
226
+ | `bodyComponent` | Ordered `lanes`, `window`, `geometryFor`, `projection`, `scroll`, `press`, `ticks`, `viewport`, `contentWidth`, highlight and hover, incomplete label, and rect components | `RosterBody`: virtualized lanes. |
227
+
228
+ `RosterBody` composes `RosterBodyLayout`, which arranges `gridZone` and `listZone`
229
+ nodes with scroll wiring, and `RosterLaneList`, which owns LegendList and its
230
+ per-lane callback. The body waits for viewport measurement before mounting the list.
231
+
232
+ ```tsx
233
+ import type { LaneLabelInput } from 'react-native-roster';
234
+ import { Text } from 'react-native';
235
+
236
+ function LaneLabel({ lane }: LaneLabelInput) {
237
+ return <Text>{lane.label}</Text>;
238
+ }
239
+
240
+ <Roster lanes={lanes} windowSpec={windowSpec}
241
+ laneLabelComponent={LaneLabel} cornerZone={<Text>People</Text>} />
242
+ ```
243
+
244
+ A custom interval component positions at `rect.x/y`, uses `rect.width/height/z`,
223
245
  and sets `pointerEvents="none"` so the parent hit-test walk owns presses. Gap
224
246
  fillers are already inside positioned pressables. `useRoster` exposes ordered
225
247
  lanes, coverage, lane state, ticks, `geometryFor`, shared scrolling, `press`,
@@ -230,6 +252,160 @@ holding the corner and ticks), `laneLabelColumnStyle`, and `bodyStyle`.
230
252
  `laneLabelWidth` sizes the corner and label column, default 180. Each style
231
253
  prop has a `className` twin; see [NativeWind](#nativewind).
232
254
 
255
+ ### Selection
256
+
257
+ Add `intervalDetailComponent` to enable pressed-interval details. The press still
258
+ fires `onIntervalPress`; without the component, presses retain no selection.
259
+ `useRoster` owns `selection` and `dismissSelection`.
260
+ Pressing the selected interval again dismisses it; pressing another interval
261
+ switches selection. Cell and gap presses dismiss selection while still firing
262
+ `onCellPress` and `onGapPress`. These rules live in the hook and apply on native
263
+ and web; web outside press and Escape still dismiss.
264
+ Removing the selected lane, layer, or interval bounds clears selection. The private
265
+ reconcileSelection helper matches source identity sets and chooses nearest bounds with
266
+ a total difference of at most 1 ms for projection roundoff.
267
+
268
+ Native has no intercepting dismissal overlay; body presses reach the hook, and the detail
269
+ card captures its own presses. Web excludes the body wrapper from Radix outside
270
+ dismissal, leaving body presses to the hook while preserving true outside presses and Escape.
271
+ The hook toggles the selected interval closed, switches to another interval, and dismisses
272
+ on cell or gap presses while preserving their callbacks. The body restores horizontal
273
+ and vertical offsets from shared values on remount when selectionLayout changes.
274
+ A mount effect calls the horizontal ScrollView ref's scrollTo without animation;
275
+ native also retains contentOffset. LegendList restores initialScrollOffset through
276
+ its own web mount effect and native initial offset.
277
+
278
+ Current data and geometry replace old references, including after resizing or sorting. Reconciliation matches the layer id and
279
+ order-insensitive source identities, then chooses the nearest absolute bounds. The sum
280
+ of bound differences must be at most 1 ms. Stored bounds remain the display values.
281
+
282
+ `selectable?: boolean` belongs only to the hook input, `RosterInput`, and defaults to false.
283
+ It is excluded from `RosterProps`. Hook consumers
284
+ pass `selectable: true` to `useRoster` to retain selection. `intervalDetailComponent`,
285
+ `selectionLayout`, and `portalHost` live on `RosterProps` because the chassis mounts
286
+ the content and layout. The chassis enables selection with
287
+ `selectable: Boolean(intervalDetailComponent)`. Custom chassis mount their layout
288
+ with the returned selection, dismissal, and scroll inputs.
289
+
290
+ ```tsx
291
+ import { Text, View } from 'react-native';
292
+ import { Roster } from 'react-native-roster';
293
+ import type { IntervalDetailInput, Lane } from 'react-native-roster';
294
+
295
+ function IntervalDetails({ lane, layer, rect, start, end, viewTimezone }: IntervalDetailInput) {
296
+ const format = new Intl.DateTimeFormat('en-US', { timeZone: viewTimezone, timeStyle: 'short' });
297
+ return <View style={{ padding: 16, backgroundColor: 'white' }}>
298
+ <Text>{lane.label}: {layer.label ?? layer.id}</Text>
299
+ <Text>{format.format(start)} to {format.format(end)}</Text>
300
+ {rect.sources.map((source) =>
301
+ <Text key={JSON.stringify([source.kind, source.id])}>
302
+ {source.label ?? source.id}
303
+ </Text>)}
304
+ </View>;
305
+ }
306
+
307
+ export function SelectionExample({ lanes }: { lanes: Lane[] }) {
308
+ return <Roster lanes={lanes}
309
+ windowSpec={{ span: 'day', anchorDate: '2024-01-01', timezone: 'UTC' }}
310
+ style={{ height: 480, flex: undefined }}
311
+ intervalDetailComponent={IntervalDetails} />;
312
+ }
313
+ ```
314
+
315
+ Web consumers install `bun add @radix-ui/react-popover`. It is an optional peer
316
+ for native and core-only consumers, and required by the web root entry. Consumers
317
+ resolving the library from source with a web bundler (Vite, Storybook, or Metro web)
318
+ must install it even without enabling selection because `selection-layout.web.tsx`
319
+ is in the module graph. Native and core-only consumers do not need it.
320
+ `RosterSelectionPopover` selects native or web through platform resolution.
321
+ Native mounts a local `PortalHost` and registers `Portal` content; web uses Radix
322
+ for portal placement, outside press, Escape, and collisions. The layout returns focus
323
+ to the previously focused element only after Escape.
324
+ The overlay tracks both scroll offsets with Reanimated shared values, without
325
+ React scroll state. Native clamps details horizontally to the measured viewport,
326
+ flips above when that fits, and uses the top edge when neither vertical placement
327
+ fits. The default native popover waits for viewport measurement and scrolls oversized
328
+ content on both axes within a maximum size of the viewport minus 8 px on each axis.
329
+ Consumers wanting a different presentation supply `selectionLayout`.
330
+ Native also dismisses on hardware back.
331
+
332
+ `selectionLayout?: ComponentType<SelectionLayoutProps>` is the layout strategy
333
+ naming exception to the `Component` suffix. The chassis mounts it with `anchorZone`
334
+ (the body), `contentZone` (details or null), `targetBounds` (body-content bounds), `open`,
335
+ `onDismiss`, `portalHost`, and `scroll`. The target bounds include the lane offset and
336
+ interval inset. Layout scroll inputs are limited to `x`, `y`, `headerStyle`, and
337
+ `labelStyle`. Render each node once. A consumer inspector
338
+ can arrange the nodes in columns and call `onDismiss` from its close button.
339
+ The [interval-detail gallery route](./demo/app/gallery/interval-detail.tsx)
340
+ switches presentations at runtime.
341
+
342
+ `portalHost` overrides the native destination name, whose default uses a unique
343
+ per-roster `useId`. Give separate rosters separate override names. The default
344
+ layout owns its host; do not also mount that name at an ancestor. Custom layouts
345
+ can instead target their own ancestor host, using the exported `PortalHost` and
346
+ `Portal`. A store-based portal does not preserve context from the registration
347
+ site; place required providers above the host or re-provide them in the content.
348
+ Selection never enters the lane list's body content key.
349
+
350
+ Schedule does not yet support selection; it is a later change.
351
+
352
+ ### Consumer data in slot components
353
+
354
+ For consumer data beyond a slot's Input, mount a React context provider above
355
+ `Roster` and read it with `useContext` in a module-scope slot component. This
356
+ example supplies density and locale while keeping the header cell type stable:
357
+
358
+ ```tsx
359
+ import { createContext, useContext } from 'react';
360
+ import { Text } from 'react-native';
361
+ import type { HeaderCellInput, RosterProps } from 'react-native-roster';
362
+ import { Roster } from 'react-native-roster';
363
+
364
+ type SlotPreferences = {
365
+ density: 'compact' | 'comfortable';
366
+ locale: string;
367
+ };
368
+
369
+ const SlotPreferencesContext = createContext<SlotPreferences>({
370
+ density: 'comfortable',
371
+ locale: 'en-US',
372
+ });
373
+
374
+ function LocalizedHeaderCell({ tick }: HeaderCellInput) {
375
+ const { density, locale } = useContext(SlotPreferencesContext);
376
+ const label = new Intl.DateTimeFormat(locale, {
377
+ timeZone: 'UTC',
378
+ ...(tick.kind === 'day'
379
+ ? { month: 'short', day: 'numeric' }
380
+ : { hour: 'numeric', minute: '2-digit' }),
381
+ }).format(tick.time);
382
+
383
+ return (
384
+ <Text numberOfLines={1} style={{ padding: density === 'compact' ? 2 : 6 }}>
385
+ {label}
386
+ </Text>
387
+ );
388
+ }
389
+
390
+ export function ConsumerRoster({ lanes }: Pick<RosterProps, 'lanes'>) {
391
+ return (
392
+ <SlotPreferencesContext.Provider value={{ density: 'compact', locale: 'en-GB' }}>
393
+ <Roster
394
+ lanes={lanes}
395
+ windowSpec={{ span: 'week', anchorDate: '2024-01-01', timezone: 'UTC' }}
396
+ style={{ height: 480, flex: undefined }}
397
+ headerCellComponent={LocalizedHeaderCell}
398
+ />
399
+ </SlotPreferencesContext.Provider>
400
+ );
401
+ }
402
+ ```
403
+
404
+ An inline closure or a memoized factory that returns a new component per render
405
+ is not the recommended path. A new interval component type remounts every interval
406
+ and defeats the body's content key. Context supplies changing consumer data while
407
+ preserving the module-scope component type.
408
+
233
409
  ## Schedule and its zones
234
410
 
235
411
  ```tsx
@@ -249,17 +425,17 @@ reserves a 48 px gutter, and fits the day columns without horizontal scrolling.
249
425
  `pxPerHour` defaults to 48. Chrome takes `style`, `headerStyle`, `gutterStyle`,
250
426
  and `daysStyle`, each with a `className` twin.
251
427
 
252
- | Zone | Receives | Default filler and behavior |
428
+ | Slot | Component inputs or node | Default and behavior |
253
429
  | --- | --- | --- |
254
- | `gutterZone` | `hours`, `pxPerHour` | `ScheduleGutter`: 24 frozen hour labels. |
255
- | `gridZone` | `hours`, `pxPerHour` | `ScheduleGrid`: 24 bordered hour bands behind each day's rects. |
256
- | `dayHeaderZone` | `day` | `ScheduleDayHeader`: weekday, localDate, and transition badge. |
257
- | `skippedDateZone` | `localDate` | `ScheduleSkippedDate`: zero-width header marker for a wholly skipped date. |
258
- | `columnZone` | `day`, `rects`, `gapRects`, `lane`, `highlightSource`, `press`, interval and gap zones | `ScheduleColumn`: final rect bounds in layer order. |
259
- | `transitionZone` | `day`, `transition`, `y`, `dividerY`, `height`, `width` | `ScheduleTransition`: skipped-time hatch, or repeat divider and again label. |
260
- | `nowLineZone` | `y`, `column` | `ScheduleNowLine`: line in the current day's column, updated each minute. |
261
- | `intervalZone`, `gapZone` | Same inputs as Roster | Shared `RosterInterval` and `RosterGap`. |
262
- | `incompleteZone` | `lane`, `label` | `ScheduleIncomplete`: notice above the grid when the lane is incomplete. |
430
+ | `gutterComponent` | `hours`, `pxPerHour` | `ScheduleGutter`: 24 frozen hour labels. |
431
+ | `gridComponent` | `hours`, `pxPerHour` | `ScheduleGrid`: 24 bordered hour bands behind each day's rects. |
432
+ | `dayHeaderComponent` | `day` | `ScheduleDayHeader`: weekday, localDate, and transition badge. |
433
+ | `skippedDateComponent` | `localDate` | `ScheduleSkippedDate`: zero-width header marker for a wholly skipped date. |
434
+ | `columnComponent` | `day`, `rects`, `gapRects`, `lane`, `highlightSource`, `press`, interval and gap components | `ScheduleColumn`: final rect bounds in layer order. |
435
+ | `transitionComponent` | `day`, `transition`, `y`, `dividerY`, `height`, `width` | `ScheduleTransition`: skipped-time hatch, or repeat divider and again label. |
436
+ | `nowLineComponent` | `y`, `column` | `ScheduleNowLine`: line in the current day's column, updated each minute. |
437
+ | `intervalComponent`, `gapComponent` | Same inputs as Roster | Shared `RosterInterval` and `RosterGap`. |
438
+ | `incompleteComponent` | `lane`, `label` | `ScheduleIncomplete`: notice above the grid when the lane is incomplete. |
263
439
 
264
440
  ## NativeWind
265
441
 
@@ -297,8 +473,8 @@ import { Roster } from 'react-native-roster';
297
473
  />
298
474
  ```
299
475
 
300
- Zone fillers are ordinary React Native views, so a custom `laneLabelZone` or
301
- `intervalZone` uses `className` on `View` and `Text` directly. Without the
476
+ Slot components are ordinary React Native views, so a custom `laneLabelComponent` or
477
+ `intervalComponent` uses `className` on `View` and `Text` directly. Without the
302
478
  entry point, class props are ignored and style props still work. The entry
303
479
  point is the package's only module with side effects and is listed in
304
480
  `sideEffects`. The [showcase route](./demo/app/showcase.tsx) styles every region
@@ -321,7 +497,7 @@ network). The home page lists every fixture route:
321
497
  - The showcase at `/showcase`: twelve generated people across seven zones,
322
498
  weekly hours and exclusions from the recurrence adapter, booked events, day
323
499
  and week spans, sorting, filtering, and a per-person Schedule, styled with
324
- NativeWind class props and zone fillers, with a sun and moon theme toggle.
500
+ NativeWind class props and slot components, with a sun and moon theme toggle.
325
501
  Names, titles, and the organization come from `@faker-js/faker` with a fixed
326
502
  seed; any resemblance to real people is coincidental.
327
503
 
@@ -362,6 +538,7 @@ bun run check
362
538
  the library build, the static web export, tests with coverage, knip, strict
363
539
  publint, size-limit, and Playwright.
364
540
 
541
+ - [Migrations](https://github.com/simiancraft/react-native-roster/blob/main/docs/migrations.md) lists prop renames by version with before-and-after examples.
365
542
  - [Adapter guide](./docs/adapters.md), [recurrence semantics](./docs/recurrence.md),
366
543
  [timezones](./docs/timezones.md), [caches](./docs/caches.md), and the
367
544
  [performance guide](./docs/performance.md).
@@ -0,0 +1,12 @@
1
+ import { type ReactNode } from 'react';
2
+ /** Mount once at the destination for a named native portal. */
3
+ export declare function PortalHost({ name }: {
4
+ name: string;
5
+ }): import("react/jsx-runtime").JSX.Element[];
6
+ /** Register content at a named native host; caller context does not cross the store. */
7
+ export declare function Portal({ hostName, name, children, }: {
8
+ hostName: string;
9
+ name: string;
10
+ children: ReactNode;
11
+ }): null;
12
+ //# sourceMappingURL=portal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal.d.ts","sourceRoot":"","sources":["../../../../src/components/primitives/portal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAmC,MAAM,OAAO,CAAC;AAgBlF,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,6CAOpD;AAED,wFAAwF;AACxF,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB,QAYA"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PortalHost = PortalHost;
4
+ exports.Portal = Portal;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("react");
7
+ const hosts = new Map();
8
+ const listeners = new Set();
9
+ const empty = new Map();
10
+ function subscribe(listener) {
11
+ listeners.add(listener);
12
+ return () => listeners.delete(listener);
13
+ }
14
+ function publish(hostName, nodes) {
15
+ if (nodes.size)
16
+ hosts.set(hostName, nodes);
17
+ else
18
+ hosts.delete(hostName);
19
+ for (const listener of listeners)
20
+ listener();
21
+ }
22
+ /** Mount once at the destination for a named native portal. */
23
+ function PortalHost({ name }) {
24
+ const nodes = (0, react_1.useSyncExternalStore)(subscribe, () => hosts.get(name) ?? empty, () => empty);
25
+ return Array.from(nodes, ([key, node]) => (0, jsx_runtime_1.jsx)(react_1.Fragment, { children: node }, key));
26
+ }
27
+ /** Register content at a named native host; caller context does not cross the store. */
28
+ function Portal({ hostName, name, children, }) {
29
+ (0, react_1.useEffect)(() => {
30
+ const nodes = new Map(hosts.get(hostName));
31
+ nodes.set(name, children);
32
+ publish(hostName, nodes);
33
+ return () => {
34
+ const nodes = new Map(hosts.get(hostName));
35
+ nodes.delete(name);
36
+ publish(hostName, nodes);
37
+ };
38
+ }, [hostName, name, children]);
39
+ return null;
40
+ }
41
+ //# sourceMappingURL=portal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal.js","sourceRoot":"","sources":["../../../../src/components/primitives/portal.tsx"],"names":[],"mappings":";;;;;AAAA,iCAAkF;AAElF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkC,CAAC;AACxD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;AACxC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqB,CAAC;AAE3C,SAAS,SAAS,CAAC,QAAoB;IACrC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1C,CAAC;AACD,SAAS,OAAO,CAAC,QAAgB,EAAE,KAA6B;IAC9D,IAAI,KAAK,CAAC,IAAI;QAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;;QACtC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5B,KAAK,MAAM,QAAQ,IAAI,SAAS;QAAE,QAAQ,EAAE,CAAC;AAC/C,CAAC;AAED,+DAA+D;AAC/D,oBAA2B,EAAE,IAAI,EAAoB;IACnD,MAAM,KAAK,GAAG,IAAA,4BAAoB,EAChC,SAAS,EACT,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,EAC9B,GAAG,EAAE,CAAC,KAAK,CACZ,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,uBAAC,gBAAQ,cAAY,IAAI,IAAV,GAAG,CAAmB,CAAC,CAAC;AACnF,CAAC;AAED,wFAAwF;AACxF,gBAAuB,EACrB,QAAQ,EACR,IAAI,EACJ,QAAQ,GAKT;IACC,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC3C,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1B,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACzB,OAAO,GAAG,EAAE;YACV,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC3C,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC3B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC/B,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { BodyInput } from './roster.types';
3
+ export declare function RosterBodyLayout({ scroll, contentWidth, viewport, gridZone, listZone, }: Pick<BodyInput, 'scroll' | 'contentWidth' | 'viewport'> & {
4
+ /** Noninteractive grid behind the lane list. */
5
+ gridZone: ReactNode;
6
+ /** Virtualized lane collection within the measured viewport. */
7
+ listZone: ReactNode;
8
+ }): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=body-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-layout.d.ts","sourceRoot":"","sources":["../../../../src/components/roster/body-layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,QAAQ,GACT,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,GAAG,cAAc,GAAG,UAAU,CAAC,GAAG;IAC3D,gDAAgD;IAChD,QAAQ,EAAE,SAAS,CAAC;IACpB,gEAAgE;IAChE,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAsBA"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RosterBodyLayout = RosterBodyLayout;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const react_native_1 = require("react-native");
7
+ function RosterBodyLayout({ scroll, contentWidth, viewport, gridZone, listZone, }) {
8
+ const [contentOffset] = (0, react_1.useState)(() => ({ x: scroll.x.get(), y: 0 }));
9
+ const bodyRef = scroll.bodyRef;
10
+ (0, react_1.useEffect)(() => {
11
+ bodyRef.current?.scrollTo({ x: contentOffset.x, animated: false });
12
+ }, [bodyRef, contentOffset]);
13
+ return ((0, jsx_runtime_1.jsx)(react_native_1.ScrollView, { testID: "roster-horizontal-scroll", ref: scroll.bodyRef, contentOffset: contentOffset, horizontal: true, onScroll: scroll.onBodyScroll, scrollEventThrottle: 16, style: { flex: 1 }, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { width: contentWidth, height: viewport.height }, children: [gridZone, listZone] }) }));
14
+ }
15
+ //# sourceMappingURL=body-layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-layout.js","sourceRoot":"","sources":["../../../../src/components/roster/body-layout.tsx"],"names":[],"mappings":";;;;AAAA,iCAA4D;AAC5D,+CAAgD;AAGhD,0BAAiC,EAC/B,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,QAAQ,GAMT;IACC,MAAM,CAAC,aAAa,CAAC,GAAG,IAAA,gBAAQ,EAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/B,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;IAC7B,OAAO,CACL,uBAAC,yBAAU,IACT,MAAM,EAAC,0BAA0B,EACjC,GAAG,EAAE,MAAM,CAAC,OAAO,EACnB,aAAa,EAAE,aAAa,EAC5B,UAAU,QACV,QAAQ,EAAE,MAAM,CAAC,YAAY,EAC7B,mBAAmB,EAAE,EAAE,EACvB,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,YAElB,wBAAC,mBAAI,IAAC,KAAK,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,aAC1D,QAAQ,EACR,QAAQ,IACJ,GACI,CACd,CAAC;AACJ,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { type ReactNode } from 'react';
1
2
  import type { RosterProps } from './roster.types';
2
- export declare function Roster(props: RosterProps): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | Iterable<import("react").ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null | undefined;
3
+ export declare function Roster(props: RosterProps): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null;
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/roster/index.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,2WA2ExC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/roster/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAS,MAAM,OAAO,CAAC;AAa9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAQlD,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,+TAmIxC"}
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Roster = Roster;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const core_1 = require("../../core");
5
7
  const gap_1 = require("../layers/parts/gap");
6
8
  const interval_1 = require("../layers/parts/interval");
7
9
  const lane_label_1 = require("./lanes/parts/lane-label");
@@ -13,17 +15,37 @@ const grid_1 = require("./parts/grid");
13
15
  const header_1 = require("./parts/header");
14
16
  const header_cell_1 = require("./parts/header-cell");
15
17
  const lane_label_column_1 = require("./parts/lane-label-column");
18
+ const selection_layout_1 = require("./selection/selection-layout");
16
19
  const use_roster_1 = require("./use-roster");
20
+ const defaultEmptyZone = (0, jsx_runtime_1.jsx)(empty_1.RosterEmpty, {});
21
+ const defaultCornerZone = (0, jsx_runtime_1.jsx)(corner_1.RosterCorner, {});
17
22
  function Roster(props) {
18
- const { status, orderedLanes, laneState, window, geometryFor, projection, scroll, press, ticks, contentWidth, viewport, onLayout, } = (0, use_roster_1.useRoster)(props);
19
- const { emptyZone = empty_1.RosterEmpty, cornerZone = corner_1.RosterCorner, headerZone = header_1.RosterHeader, laneLabelColumnZone = lane_label_column_1.RosterLaneLabelColumn, bodyZone = body_1.RosterBody, headerCellZone = header_cell_1.RosterHeaderCell, laneLabelZone = lane_label_1.RosterLaneLabel, intervalZone = interval_1.RosterInterval, gapZone = gap_1.RosterGap, gridZone = grid_1.RosterGrid, incompleteLabel = 'Availability may be incomplete', neverSetLabel = 'No availability set', } = props;
23
+ const { selection, dismissSelection, status, orderedLanes, laneState, window, geometryFor, projection, scroll, press, ticks, contentWidth, viewport, onLayout, } = (0, use_roster_1.useRoster)({ ...props, selectable: Boolean(props.intervalDetailComponent) });
24
+ const { intervalDetailComponent: IntervalDetailComponent, selectionLayout: SelectionLayout = selection_layout_1.RosterSelectionPopover, emptyZone = defaultEmptyZone, cornerZone = defaultCornerZone, headerComponent: HeaderComponent = header_1.RosterHeader, laneLabelColumnComponent: LaneLabelColumnComponent = lane_label_column_1.RosterLaneLabelColumn, bodyComponent: BodyComponent = body_1.RosterBody, headerCellComponent = header_cell_1.RosterHeaderCell, laneLabelComponent = lane_label_1.RosterLaneLabel, intervalComponent = interval_1.RosterInterval, gapComponent = gap_1.RosterGap, gridComponent = grid_1.RosterGrid, incompleteLabel = 'Availability may be incomplete', neverSetLabel = 'No availability set', } = props;
25
+ const hostId = (0, react_1.useId)();
20
26
  if (status === 'empty')
21
- return emptyZone();
27
+ return emptyZone;
22
28
  if (window.start === window.end)
23
29
  return null;
24
- return ((0, jsx_runtime_1.jsx)(layout_1.RosterLayout, { style: props.style, headerStyle: props.headerStyle, laneLabelColumnStyle: props.laneLabelColumnStyle, bodyStyle: props.bodyStyle, laneLabelWidth: props.laneLabelWidth, onLayout: onLayout, cornerZone: cornerZone(), headerZone: headerZone({ ticks, projection, scroll, contentWidth, headerCellZone }), laneLabelColumnZone: laneLabelColumnZone({
25
- labels: orderedLanes.map((lane) => {
26
- const state = laneState.get(lane.id) ?? { flag: 'none', complete: true };
30
+ let targetBounds = null;
31
+ if (selection) {
32
+ targetBounds = {
33
+ x: selection.rect.x,
34
+ y: orderedLanes.findIndex((lane) => lane.id === selection.lane.id) * projection.rowHeight +
35
+ selection.rect.y,
36
+ width: selection.rect.width,
37
+ height: selection.rect.height,
38
+ };
39
+ }
40
+ let contentZone = null;
41
+ if (selection && IntervalDetailComponent) {
42
+ contentZone = ((0, jsx_runtime_1.jsx)(IntervalDetailComponent, { ...selection, viewTimezone: projection.viewTimezone, highlighted: (0, core_1.hasSource)(selection.rect.sources, props.highlightSource) }));
43
+ }
44
+ return ((0, jsx_runtime_1.jsx)(layout_1.RosterLayout, { style: props.style, headerStyle: props.headerStyle, laneLabelColumnStyle: props.laneLabelColumnStyle, bodyStyle: props.bodyStyle, laneLabelWidth: props.laneLabelWidth, onLayout: onLayout, cornerZone: cornerZone, headerZone: (0, jsx_runtime_1.jsx)(HeaderComponent, { ticks: ticks, projection: projection, scroll: scroll, contentWidth: contentWidth, headerCellComponent: headerCellComponent }), laneLabelColumnZone: (0, jsx_runtime_1.jsx)(LaneLabelColumnComponent, { labels: orderedLanes.map((lane) => {
45
+ const state = laneState.get(lane.id) ?? {
46
+ flag: 'none',
47
+ complete: true,
48
+ };
27
49
  return {
28
50
  lane,
29
51
  ...state,
@@ -31,26 +53,11 @@ function Roster(props) {
31
53
  incompleteLabel,
32
54
  neverSetLabel,
33
55
  };
34
- }),
35
- projection,
36
- scroll,
37
- laneLabelZone,
38
- }), bodyZone: bodyZone({
39
- lanes: orderedLanes,
40
- window,
41
- geometryFor,
42
- projection,
43
- scroll,
44
- press,
45
- ticks,
46
- contentWidth,
47
- viewport,
48
- intervalZone,
49
- gapZone,
50
- gridZone,
51
- highlightSource: props.highlightSource,
52
- onIntervalHover: props.onIntervalHover,
53
- incompleteLabel,
54
- }) }));
56
+ }), projection: projection, scroll: scroll, laneLabelComponent: laneLabelComponent }), bodyZone: (0, jsx_runtime_1.jsx)(SelectionLayout, { portalHost: props.portalHost ?? `roster-${hostId}`, open: selection !== null, onDismiss: dismissSelection, scroll: {
57
+ x: scroll.x,
58
+ y: scroll.y,
59
+ headerStyle: scroll.headerStyle,
60
+ labelStyle: scroll.labelStyle,
61
+ }, targetBounds: targetBounds, contentZone: contentZone, anchorZone: (0, jsx_runtime_1.jsx)(BodyComponent, { lanes: orderedLanes, window: window, geometryFor: geometryFor, projection: projection, scroll: scroll, press: press, ticks: ticks, contentWidth: contentWidth, viewport: viewport, intervalComponent: intervalComponent, gapComponent: gapComponent, gridComponent: gridComponent, highlightSource: props.highlightSource, onIntervalHover: props.onIntervalHover, incompleteLabel: incompleteLabel }) }) }));
55
62
  }
56
63
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/roster/index.tsx"],"names":[],"mappings":";;;;AAAA,6CAAgD;AAChD,uDAA0D;AAC1D,yDAA2D;AAC3D,qCAAwC;AACxC,uCAA0C;AAC1C,2CAA8C;AAC9C,yCAA4C;AAC5C,uCAA0C;AAC1C,2CAA8C;AAC9C,qDAAuD;AACvD,iEAAkE;AAElE,6CAAyC;AAEzC,gBAAuB,KAAkB;IACvC,MAAM,EACJ,MAAM,EACN,YAAY,EACZ,SAAS,EACT,MAAM,EACN,WAAW,EACX,UAAU,EACV,MAAM,EACN,KAAK,EACL,KAAK,EACL,YAAY,EACZ,QAAQ,EACR,QAAQ,GACT,GAAG,IAAA,sBAAS,EAAC,KAAK,CAAC,CAAC;IACrB,MAAM,EACJ,SAAS,GAAG,mBAAW,EACvB,UAAU,GAAG,qBAAY,EACzB,UAAU,GAAG,qBAAY,EACzB,mBAAmB,GAAG,yCAAqB,EAC3C,QAAQ,GAAG,iBAAU,EACrB,cAAc,GAAG,8BAAgB,EACjC,aAAa,GAAG,4BAAe,EAC/B,YAAY,GAAG,yBAAc,EAC7B,OAAO,GAAG,eAAS,EACnB,QAAQ,GAAG,iBAAU,EACrB,eAAe,GAAG,gCAAgC,EAClD,aAAa,GAAG,qBAAqB,GACtC,GAAG,KAAK,CAAC;IACV,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,SAAS,EAAE,CAAC;IAC3C,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,CACL,uBAAC,qBAAY,IACX,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,WAAW,EAAE,KAAK,CAAC,WAAW,EAC9B,oBAAoB,EAAE,KAAK,CAAC,oBAAoB,EAChD,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,cAAc,EAAE,KAAK,CAAC,cAAc,EACpC,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,UAAU,EAAE,EACxB,UAAU,EAAE,UAAU,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC,EACnF,mBAAmB,EAAE,mBAAmB,CAAC;YACvC,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;gBAChC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBACzE,OAAO;oBACL,IAAI;oBACJ,GAAG,KAAK;oBACR,YAAY,EAAE,UAAU,CAAC,YAAY;oBACrC,eAAe;oBACf,aAAa;iBACd,CAAC;YACJ,CAAC,CAAC;YACF,UAAU;YACV,MAAM;YACN,aAAa;SACd,CAAC,EACF,QAAQ,EAAE,QAAQ,CAAC;YACjB,KAAK,EAAE,YAAY;YACnB,MAAM;YACN,WAAW;YACX,UAAU;YACV,MAAM;YACN,KAAK;YACL,KAAK;YACL,YAAY;YACZ,QAAQ;YACR,YAAY;YACZ,OAAO;YACP,QAAQ;YACR,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,eAAe;SAChB,CAAC,GACF,CACH,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/roster/index.tsx"],"names":[],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import type { Lane, LaneGeometry } from '../../../core';
2
2
  import type { BodyInput } from '../roster.types';
3
- export type LaneRowProps = Pick<BodyInput, 'press' | 'intervalZone' | 'gapZone' | 'highlightSource' | 'onIntervalHover' | 'incompleteLabel'> & {
3
+ export type LaneRowProps = Pick<BodyInput, 'press' | 'intervalComponent' | 'gapComponent' | 'highlightSource' | 'onIntervalHover' | 'incompleteLabel'> & {
4
4
  lane: Lane;
5
5
  geometry: LaneGeometry;
6
6
  width: number;
7
7
  rowHeight: number;
8
8
  };
9
- export declare function LaneRow({ lane, geometry, width, rowHeight, press, intervalZone, gapZone, highlightSource, onIntervalHover, incompleteLabel, }: LaneRowProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function LaneRow({ lane, geometry, width, rowHeight, press, intervalComponent: IntervalComponent, gapComponent: GapComponent, highlightSource, onIntervalHover, incompleteLabel, }: LaneRowProps): import("react/jsx-runtime").JSX.Element;
10
10
  //# sourceMappingURL=lane.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lane.d.ts","sourceRoot":"","sources":["../../../../../src/components/roster/lanes/lane.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,MAAM,YAAY,GAAG,IAAI,CAC7B,SAAS,EACT,OAAO,GAAG,cAAc,GAAG,SAAS,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,iBAAiB,CACjG,GAAG;IACF,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,SAAS,EACT,KAAK,EACL,YAAY,EACZ,OAAO,EACP,eAAe,EACf,eAAe,EACf,eAAkD,GACnD,EAAE,YAAY,2CA0Dd"}
1
+ {"version":3,"file":"lane.d.ts","sourceRoot":"","sources":["../../../../../src/components/roster/lanes/lane.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,MAAM,YAAY,GAAG,IAAI,CAC7B,SAAS,EACP,OAAO,GACP,mBAAmB,GACnB,cAAc,GACd,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,CACpB,GAAG;IACF,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,SAAS,EACT,KAAK,EACL,iBAAiB,EAAE,iBAAiB,EACpC,YAAY,EAAE,YAAY,EAC1B,eAAe,EACf,eAAe,EACf,eAAkD,GACnD,EAAE,YAAY,2CAuDd"}
@@ -4,22 +4,18 @@ exports.LaneRow = LaneRow;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const react_native_1 = require("react-native");
7
+ const core_1 = require("../../../core");
7
8
  const press_point_1 = require("../../primitives/press-point");
8
9
  const interval_hover_1 = require("./interval-hover");
9
10
  const incomplete_1 = require("./parts/incomplete");
10
- function LaneRow({ lane, geometry, width, rowHeight, press, intervalZone, gapZone, highlightSource, onIntervalHover, incompleteLabel = 'Availability may be incomplete', }) {
11
+ function LaneRow({ lane, geometry, width, rowHeight, press, intervalComponent: IntervalComponent, gapComponent: GapComponent, highlightSource, onIntervalHover, incompleteLabel = 'Availability may be incomplete', }) {
11
12
  const layers = [...lane.layers].sort((a, b) => a.z - b.z);
12
13
  return ((0, jsx_runtime_1.jsxs)(react_native_1.Pressable, { ...(0, interval_hover_1.intervalHoverProps)({ lane, geometry, onIntervalHover }), testID: `roster-lane-${lane.id}`, accessibilityLabel: lane.label, onPress: (input) => {
13
14
  const point = (0, press_point_1.pressPoint)(input);
14
15
  press(lane, point.x, point.y);
15
16
  }, style: { width, height: rowHeight }, children: [(0, jsx_runtime_1.jsx)(incomplete_1.RosterIncomplete, { lane: lane, geometry: geometry, width: width, label: incompleteLabel }), layers.map((layer) => ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [geometry.rects
16
17
  .filter((rect) => rect.layerId === layer.id)
17
- .map((rect) => ((0, jsx_runtime_1.jsx)(react_1.Fragment, { children: intervalZone({
18
- rect,
19
- layer,
20
- lane,
21
- highlighted: rect.sources.some((source) => source.kind === highlightSource?.kind && source.id === highlightSource.id),
22
- }) }, `interval-${rect.x}:${rect.width}`))), geometry.gapRects
18
+ .map((rect) => ((0, jsx_runtime_1.jsx)(react_1.Fragment, { children: (0, jsx_runtime_1.jsx)(IntervalComponent, { rect: rect, layer: layer, lane: lane, highlighted: (0, core_1.hasSource)(rect.sources, highlightSource) }) }, `interval-${rect.x}:${rect.width}`))), geometry.gapRects
23
19
  .filter((rect) => rect.layerId === layer.id)
24
20
  .map((rect) => ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { accessibilityLabel: `${lane.label}: removed time`, onPress: (input) => {
25
21
  input.stopPropagation();
@@ -32,6 +28,6 @@ function LaneRow({ lane, geometry, width, rowHeight, press, intervalZone, gapZon
32
28
  width: rect.width,
33
29
  height: rect.height,
34
30
  zIndex: rect.z,
35
- }, children: gapZone({ rect, layer, lane }) }, `gap-${rect.x}:${rect.width}`)))] }, layer.id)))] }));
31
+ }, children: (0, jsx_runtime_1.jsx)(GapComponent, { rect: rect, layer: layer, lane: lane }) }, `gap-${rect.x}:${rect.width}`)))] }, layer.id)))] }));
36
32
  }
37
33
  //# sourceMappingURL=lane.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lane.js","sourceRoot":"","sources":["../../../../../src/components/roster/lanes/lane.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lane.js","sourceRoot":"","sources":["../../../../../src/components/roster/lanes/lane.tsx"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { type ProfilerOnRenderCallback } from 'react';
1
+ import type { ProfilerOnRenderCallback } from 'react';
2
2
  import type { BodyInput } from '../roster.types';
3
- export declare function RosterBody({ lanes, geometryFor, projection, scroll, press, ticks, contentWidth, viewport, window, intervalZone, gapZone, gridZone, highlightSource, onIntervalHover, incompleteLabel, onRowRender, }: BodyInput & {
4
- /** Optional per-lane commit observer; used by the development gallery's Profiler gate. */
3
+ export declare function RosterBody(props: BodyInput & {
4
+ /** Development-only Profiler hook used by the gallery; not a supported customization point. */
5
5
  onRowRender?: ProfilerOnRenderCallback;
6
6
  }): import("react/jsx-runtime").JSX.Element | null;
7
7
  //# sourceMappingURL=body.d.ts.map