kaafil-react-uikit 0.1.0-beta.1

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 (79) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/LICENSE +21 -0
  3. package/README.md +187 -0
  4. package/dist/OfflineFallbackScreen-B5dfaJBN.d.ts +37 -0
  5. package/dist/OfflineFallbackScreen-Ctm7nBa-.d.cts +37 -0
  6. package/dist/SessionExpiredScreen-CytQNuak.d.cts +50 -0
  7. package/dist/SessionExpiredScreen-D8GHyZc3.d.ts +50 -0
  8. package/dist/admin/index.cjs +23779 -0
  9. package/dist/admin/index.cjs.map +1 -0
  10. package/dist/admin/index.d.cts +1157 -0
  11. package/dist/admin/index.d.ts +1157 -0
  12. package/dist/admin/index.js +23724 -0
  13. package/dist/admin/index.js.map +1 -0
  14. package/dist/chunk-6FPAGGFL.js +6028 -0
  15. package/dist/chunk-6FPAGGFL.js.map +1 -0
  16. package/dist/chunk-ACVU55PZ.cjs +294 -0
  17. package/dist/chunk-ACVU55PZ.cjs.map +1 -0
  18. package/dist/chunk-EM7JV3D7.cjs +6051 -0
  19. package/dist/chunk-EM7JV3D7.cjs.map +1 -0
  20. package/dist/chunk-IIPQ4JNC.js +287 -0
  21. package/dist/chunk-IIPQ4JNC.js.map +1 -0
  22. package/dist/chunk-LL243STJ.cjs +2195 -0
  23. package/dist/chunk-LL243STJ.cjs.map +1 -0
  24. package/dist/chunk-PJRZCOFF.cjs +958 -0
  25. package/dist/chunk-PJRZCOFF.cjs.map +1 -0
  26. package/dist/chunk-PTQ2CJKE.cjs +40 -0
  27. package/dist/chunk-PTQ2CJKE.cjs.map +1 -0
  28. package/dist/chunk-PZKXLQSU.js +10 -0
  29. package/dist/chunk-PZKXLQSU.js.map +1 -0
  30. package/dist/chunk-QHUDOVKW.cjs +111 -0
  31. package/dist/chunk-QHUDOVKW.cjs.map +1 -0
  32. package/dist/chunk-TOBZFADB.cjs +12 -0
  33. package/dist/chunk-TOBZFADB.cjs.map +1 -0
  34. package/dist/chunk-UUGMNP27.js +936 -0
  35. package/dist/chunk-UUGMNP27.js.map +1 -0
  36. package/dist/chunk-UYJ6LIWP.js +2154 -0
  37. package/dist/chunk-UYJ6LIWP.js.map +1 -0
  38. package/dist/chunk-VHTSTUCJ.cjs +346 -0
  39. package/dist/chunk-VHTSTUCJ.cjs.map +1 -0
  40. package/dist/chunk-WUAFL77X.js +340 -0
  41. package/dist/chunk-WUAFL77X.js.map +1 -0
  42. package/dist/chunk-XI7MK4Y7.js +38 -0
  43. package/dist/chunk-XI7MK4Y7.js.map +1 -0
  44. package/dist/chunk-YDGR7JSY.js +107 -0
  45. package/dist/chunk-YDGR7JSY.js.map +1 -0
  46. package/dist/core/index.cjs +1254 -0
  47. package/dist/core/index.cjs.map +1 -0
  48. package/dist/core/index.d.cts +1267 -0
  49. package/dist/core/index.d.ts +1267 -0
  50. package/dist/core/index.js +995 -0
  51. package/dist/core/index.js.map +1 -0
  52. package/dist/index.css +1 -0
  53. package/dist/manager/index.cjs +13562 -0
  54. package/dist/manager/index.cjs.map +1 -0
  55. package/dist/manager/index.d.cts +1054 -0
  56. package/dist/manager/index.d.ts +1054 -0
  57. package/dist/manager/index.js +13518 -0
  58. package/dist/manager/index.js.map +1 -0
  59. package/dist/testing/index.cjs +221 -0
  60. package/dist/testing/index.cjs.map +1 -0
  61. package/dist/testing/index.d.cts +269 -0
  62. package/dist/testing/index.d.ts +269 -0
  63. package/dist/testing/index.js +208 -0
  64. package/dist/testing/index.js.map +1 -0
  65. package/dist/tokenStyle-CToG5oOS.d.cts +3 -0
  66. package/dist/tokenStyle-CToG5oOS.d.ts +3 -0
  67. package/dist/traveller/index.cjs +1799 -0
  68. package/dist/traveller/index.cjs.map +1 -0
  69. package/dist/traveller/index.d.cts +58 -0
  70. package/dist/traveller/index.d.ts +58 -0
  71. package/dist/traveller/index.js +1789 -0
  72. package/dist/traveller/index.js.map +1 -0
  73. package/dist/useAgencyTrip-BUYSIaC2.d.cts +454 -0
  74. package/dist/useAgencyTrip-BzyJB1D9.d.ts +454 -0
  75. package/dist/useNotifications-BZW1Z_ur.d.cts +356 -0
  76. package/dist/useNotifications-D262i5BQ.d.ts +356 -0
  77. package/dist/useVendors-DXOuZWhZ.d.cts +784 -0
  78. package/dist/useVendors-DXOuZWhZ.d.ts +784 -0
  79. package/package.json +95 -0
@@ -0,0 +1,1054 @@
1
+ export { B as BootErrorScreen, a as BootErrorScreenProps, b as BootFailureMode, O as OfflineFallbackScreen, c as OfflineFallbackScreenProps } from '../OfflineFallbackScreen-B5dfaJBN.js';
2
+ export { L as LockedTripScreen, a as LockedTripScreenProps, N as NotFoundScreen, b as NotFoundScreenProps, S as SessionExpiredScreen, c as SessionExpiredScreenProps } from '../SessionExpiredScreen-D8GHyZc3.js';
3
+ import { ComponentType, ReactNode } from 'react';
4
+ import { C as ChecklistSectionRow, a as ChecklistsReady, T as TripFormRow, L as FormDefinitionDetail, M as FormResponseDetail, N as TravellerFormResponseRow, I as ItineraryDayRow, d as ItineraryItemRow, r as ItineraryReady, O as ExpenseLiveRow, s as RoomingReady, e as TripVendorRow } from '../useVendors-DXOuZWhZ.js';
5
+ export { Q as ChecklistAvailableTemplateRow, F as FileListItem, S as FilePurpose, b as FloatLedgerMovementRow, f as FloatLedgerSummaryRow, U as ManagerFileView } from '../useVendors-DXOuZWhZ.js';
6
+ import { K as KaafilTokenOverrides } from '../tokenStyle-CToG5oOS.js';
7
+ import { p as CloseoutBlockerRow, d as ManagerTodayReady, q as PickupManifestResult, M as ManagerMeReady, h as SeatingReady } from '../useNotifications-D262i5BQ.js';
8
+ export { r as CloseoutAggregate, C as ConflictRecord, c as ManagerNotification, s as PartiesTripRosterRow } from '../useNotifications-D262i5BQ.js';
9
+ import { PickupStopDeltaRow, ManagerOwnTrip } from 'kaafil-js/client';
10
+ export { ManagerOwnTrip, OutboxOp, PickupStopDeltaRow } from 'kaafil-js/client';
11
+
12
+ interface ItemRowProps {
13
+ readonly item: ChecklistItemLiveRow;
14
+ /** Resolved via `useManagers(tripRef)`, joined on `managerId` — real name,
15
+ * never a raw id, never fabricated when the join can't resolve. */
16
+ readonly completedByName: string | undefined;
17
+ readonly pending: boolean;
18
+ readonly onToggle: () => void;
19
+ readonly onEdit: () => void;
20
+ readonly onDelete: () => void;
21
+ }
22
+
23
+ interface ProgressCardProps {
24
+ readonly title: string | undefined;
25
+ readonly subtitle: string | undefined;
26
+ readonly progress: {
27
+ readonly total: number;
28
+ readonly complete: number;
29
+ } | undefined;
30
+ }
31
+
32
+ interface SectionCardProps {
33
+ readonly section: ChecklistSectionRow;
34
+ readonly items: readonly ChecklistItemLiveRow[];
35
+ readonly completedByNameFor: (managerId: string) => string | undefined;
36
+ readonly pendingItemIds: ReadonlySet<string>;
37
+ readonly onToggleItem: (item: ChecklistItemLiveRow) => void;
38
+ readonly onEditItem: (item: ChecklistItemLiveRow) => void;
39
+ readonly onDeleteItem: (item: ChecklistItemLiveRow) => void;
40
+ readonly ItemRowComponent: ComponentType<ItemRowProps>;
41
+ }
42
+
43
+ /** One row of `useChecklists()`'s `items[]` — a live item or a tombstone,
44
+ * `useChecklists.ts`'s own documented split. */
45
+ type ChecklistItemDeltaRow = ChecklistsReady['items'][number];
46
+ /** `ChecklistItemDeltaRow`, narrowed to the live shape — a
47
+ * deleted-since-last-cursor row carries no `title`/`status`/etc. at all. */
48
+ type ChecklistItemLiveRow = Exclude<ChecklistItemDeltaRow, {
49
+ readonly _tombstone: true;
50
+ }>;
51
+ type ChecklistItemPhase = ChecklistSectionRow['phase'];
52
+ type ChecklistItemGate = ChecklistItemLiveRow['gate'];
53
+ interface ManagerChecklistSectionProps {
54
+ /** The trip this section reads `useChecklists(tripRef)` for. */
55
+ readonly tripRef: string;
56
+ /** Tier-4 named-component overrides — the three genuinely reskinnable
57
+ * regions. Each receives EXACTLY the same props this composite's own
58
+ * default renders it with. */
59
+ readonly components?: {
60
+ readonly ProgressCard?: ComponentType<ProgressCardProps>;
61
+ readonly SectionCard?: ComponentType<SectionCardProps>;
62
+ readonly ItemRow?: ComponentType<ItemRowProps>;
63
+ };
64
+ readonly style?: KaafilTokenOverrides;
65
+ }
66
+
67
+ declare function ManagerChecklistSection({ tripRef, components, style, }: ManagerChecklistSectionProps): ReactNode;
68
+
69
+ interface BlockerRowProps {
70
+ readonly blocker: CloseoutBlockerRow;
71
+ readonly onAction?: (blocker: CloseoutBlockerRow) => void;
72
+ }
73
+
74
+ interface ManagerCloseoutSectionProps {
75
+ readonly tripRef: string;
76
+ /** Real dispatch, never a fabricated route: `ManagerTripSection` wires
77
+ * this to its own `actionKey → ManagerTripTabKey` map and switches its
78
+ * own tab state — see this composite's own header. Omit to render every
79
+ * blocker action button disabled/absent-of-navigation (still shows the
80
+ * blocker itself, just no dispatch). */
81
+ readonly onBlockerAction?: (blocker: CloseoutBlockerRow) => void;
82
+ /** `UnlockForm`'s own real contract (`04-closing-day.md`, verbatim): "this
83
+ * screen makes no `kaafil-js` call of its own" for unlock — `unlockCloseout`
84
+ * is `apiKeyAuth`-only. Submitting the reason form calls this instead, the
85
+ * host's own out-of-band route to ops. Omitted → a static "contact ops to
86
+ * reopen" message renders in place of the form. */
87
+ readonly onSubmitUnlockRequest?: (payload: {
88
+ readonly tripRef: string;
89
+ readonly reason: string;
90
+ }) => Promise<void>;
91
+ readonly components?: {
92
+ readonly BlockerRow?: ComponentType<BlockerRowProps>;
93
+ };
94
+ readonly style?: KaafilTokenOverrides;
95
+ }
96
+
97
+ declare function ManagerCloseoutSection({ tripRef, onBlockerAction, onSubmitUnlockRequest, components, style, }: ManagerCloseoutSectionProps): ReactNode;
98
+
99
+ interface ManagerDocumentsSectionProps {
100
+ readonly tripRef: string;
101
+ readonly style?: KaafilTokenOverrides;
102
+ }
103
+
104
+ declare function ManagerDocumentsSection({ tripRef, style, }: ManagerDocumentsSectionProps): ReactNode;
105
+
106
+ interface ManagerFloatLedgerSectionProps {
107
+ readonly tripRef: string;
108
+ readonly style?: KaafilTokenOverrides;
109
+ }
110
+
111
+ declare function ManagerFloatLedgerSection({ tripRef, style, }: ManagerFloatLedgerSectionProps): ReactNode;
112
+
113
+ /** One answer this composite is about to write back — mirrors
114
+ * `SubmitFormResponseInput['answers'][number]` so nothing here hand-shapes
115
+ * the array passed to `submitResponse`. */
116
+ interface FieldAnswer {
117
+ readonly fieldKey: string;
118
+ readonly value: unknown;
119
+ }
120
+
121
+ interface FormFillRendererProps {
122
+ readonly form: TripFormRow;
123
+ readonly definition: FormDefinitionDetail;
124
+ /** The subject's (self, or the on-behalf traveller's) existing response,
125
+ * when one is known — `undefined` starts a fresh fill. */
126
+ readonly existingResponse: FormResponseDetail | undefined;
127
+ /** `existingResponse?.status === 'SUBMITTED'`, OR the parent's own
128
+ * optimistic "we just submitted this" flag — kept as an explicit prop
129
+ * rather than derived only from `existingResponse` so a just-submitted
130
+ * fill locks immediately using the answers already held in THIS
131
+ * component's own local state, without the parent fabricating a
132
+ * `FormResponseDetail` it doesn't really have back from the write. */
133
+ readonly locked: boolean;
134
+ /** Set only for on-behalf capture — gates the `SELF_ONLY` sensitivity
135
+ * filter (05-forms.md's own privacy rule). */
136
+ readonly travellerRef: string | undefined;
137
+ readonly pending: boolean;
138
+ readonly hasConflict: boolean;
139
+ readonly onSave: (answers: readonly FieldAnswer[]) => void;
140
+ readonly onSubmit: (answers: readonly FieldAnswer[]) => void;
141
+ readonly onRefreshAfterConflict: () => void;
142
+ readonly onBack: () => void;
143
+ }
144
+
145
+ interface TripFormsPanelProps {
146
+ readonly rows: readonly FormsListRow[];
147
+ readonly now: string | undefined;
148
+ readonly travellerScoped: boolean;
149
+ readonly onSelectForm: (row: FormsListRow) => void;
150
+ }
151
+
152
+ /** One row of `TripFormsPanel`'s list. `response` is the SUBJECT's own
153
+ * response for this form when known — always `undefined` in self-fill mode
154
+ * (`useForms.ts` exposes no "list my own manager responses" read; this
155
+ * composite's own header documents the gap), populated in traveller-scoped
156
+ * mode (`travellerRef` set) from `travellerResponses(travellerRef)`. */
157
+ interface FormsListRow {
158
+ readonly form: TripFormRow;
159
+ readonly response: TravellerFormResponseRow | undefined;
160
+ }
161
+ interface ManagerFormsSectionProps {
162
+ /** The trip this section reads `useForms(tripRef)` for. */
163
+ readonly tripRef: string;
164
+ /** Deep-link straight into one form's fill UI, skipping the list. */
165
+ readonly initialFormRef?: string;
166
+ /**
167
+ * Scopes this composite to a SINGLE traveller instead of the manager's
168
+ * own self-fill list — the only honest way to serve "view what a
169
+ * traveller submitted," using the two real reads this SDK exposes
170
+ * (`travellerResponses`/`getResponse`). A caller who already knows which
171
+ * traveller (e.g. a row-tap in `ManagerManifestSection`/
172
+ * `ManagerTravellerProfileSection`) mounts this composite with
173
+ * `travellerRef` set; the list switches to that traveller's response rows
174
+ * joined against `forms[]`, and an unanswered row's tap becomes on-behalf
175
+ * capture (`submitResponse({ travellerRef, ... })`).
176
+ */
177
+ readonly travellerRef?: string;
178
+ readonly onSubmitted?: (formRef: string, responseId: string) => void;
179
+ /** Tier-4 named-component overrides — the two genuinely reskinnable
180
+ * regions, matching `05-forms.md`'s own `FormFillFlow.components` slot. */
181
+ readonly components?: {
182
+ readonly TripFormsPanel?: ComponentType<TripFormsPanelProps>;
183
+ readonly FormFillRenderer?: ComponentType<FormFillRendererProps>;
184
+ };
185
+ readonly style?: KaafilTokenOverrides;
186
+ }
187
+
188
+ declare function ManagerFormsSection({ tripRef, initialFormRef, travellerRef, onSubmitted, components, style, }: ManagerFormsSectionProps): ReactNode;
189
+
190
+ interface DayStripProps {
191
+ readonly days: readonly ItineraryDayRow[];
192
+ readonly selectedDayIndex: number;
193
+ readonly onSelect: (dayIndex: number) => void;
194
+ }
195
+
196
+ interface ItemCardProps {
197
+ readonly item: ItineraryItemRow;
198
+ readonly canMoveUp: boolean;
199
+ readonly canMoveDown: boolean;
200
+ readonly onMoveUp: (item: ItineraryItemRow) => void;
201
+ readonly onMoveDown: (item: ItineraryItemRow) => void;
202
+ readonly onEdit: (item: ItineraryItemRow) => void;
203
+ }
204
+
205
+ type ItineraryChangeLogRow = ItineraryReady['changeLog'][number];
206
+ interface ManagerItinerarySectionProps {
207
+ /** The trip this section reads `useItinerary()`'s own reads for. */
208
+ readonly tripRef: string;
209
+ /** Overrides the "no days yet" empty state — same render-prop shape
210
+ * `ManagerRoomingSection.emptyView`/`ManagerVehiclesSection.emptyView`
211
+ * already establish. Omit for the built-in message. Days materialize
212
+ * lazily server-side on first read, so this should never actually fire
213
+ * in practice, but the composite still handles it honestly rather than
214
+ * crashing on an empty `days[]`. */
215
+ readonly emptyView?: ReactNode | (() => ReactNode);
216
+ /** Tier-4 named-component overrides (`04-customization-ladder.md`'s own
217
+ * "the only way to replace a named component"). Each receives EXACTLY
218
+ * the same props this composite's own default renders it with. */
219
+ readonly components?: {
220
+ readonly DayStrip?: ComponentType<DayStripProps>;
221
+ readonly ItemCard?: ComponentType<ItemCardProps>;
222
+ };
223
+ readonly style?: KaafilTokenOverrides;
224
+ }
225
+
226
+ declare function ManagerItinerarySection({ tripRef, emptyView, components, style, }: ManagerItinerarySectionProps): ReactNode;
227
+
228
+ interface TripBookingGroupCardProps {
229
+ readonly group: ManifestBookingGroup;
230
+ readonly onCollect: (groupId: string) => void;
231
+ /** Fired when a member chip is tapped — the same real destination
232
+ * `TripTravellerRow.onOpen` already opens, so a traveller reachable from
233
+ * either the group card or the all-travellers list below lands on the
234
+ * identical `ManagerTravellerProfileSection`. */
235
+ readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
236
+ }
237
+
238
+ interface ManifestStats {
239
+ readonly confirmedCount: number;
240
+ readonly vegCount: number;
241
+ readonly totalCount: number;
242
+ readonly balanceDueMinor: number;
243
+ readonly currency: string;
244
+ }
245
+
246
+ interface TripManifestStatsProps {
247
+ readonly stats: ManifestStats;
248
+ }
249
+
250
+ interface TripTravellerRowProps {
251
+ readonly traveller: ManifestTraveller;
252
+ /** `fullName` is passed alongside the id — already in scope here, so a
253
+ * host wiring `onOpenTraveller` to a header/nav can show a real name
254
+ * immediately, before `ManagerTravellerProfileSection` finishes its own
255
+ * fetch, without a second lookup. */
256
+ readonly onOpen: (travellerId: string, fullName: string) => void;
257
+ }
258
+
259
+ interface ManagerManifestSectionProps {
260
+ /** The trip this section reads `useParties()`'s two real reads for. */
261
+ readonly tripRef: string;
262
+ /** Fired when a booking group's "Collect" CTA is tapped — nav-only
263
+ * (hard rule #9): no group-level collect endpoint exists (`collections`'s
264
+ * DTOs key strictly on `travellerId`), so the host resolves this into
265
+ * whatever real per-traveller flow it wants. */
266
+ readonly onCollectFromGroup: (groupId: string) => void;
267
+ /** Fired when a traveller row is tapped — the destination is
268
+ * `ManagerTravellerProfileSection` (a standalone composite, also
269
+ * exported), still fired via a callback rather than a router (hard rule
270
+ * #9). `fullName` is passed alongside the id so a host can show a real
271
+ * header title immediately, before the profile composite's own fetch
272
+ * resolves. */
273
+ readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
274
+ /** Overrides the "no travellers match your search or filters" empty
275
+ * state — same render-prop shape `ManagerNowSection.idleView` already
276
+ * establishes for a state override. Omit for the built-in message. */
277
+ readonly emptyView?: ReactNode | (() => ReactNode);
278
+ /** Tier-4 named-component overrides (`04-customization-ladder.md`'s own
279
+ * "the only way to replace a named component") — the three leaf pieces a
280
+ * partner CRM is most likely to reskin: its own traveller-row layout,
281
+ * its own booking-group card, its own stat cells. Each receives EXACTLY
282
+ * the same props this composite's own default renders it with; a host
283
+ * overriding `TravellerRow` still gets real `onOpen`/real traveller data,
284
+ * never a stripped-down shape. */
285
+ readonly components?: {
286
+ readonly TravellerRow?: ComponentType<TripTravellerRowProps>;
287
+ readonly BookingGroupCard?: ComponentType<TripBookingGroupCardProps>;
288
+ readonly Stats?: ComponentType<TripManifestStatsProps>;
289
+ };
290
+ readonly style?: KaafilTokenOverrides;
291
+ }
292
+ type ManifestDiet = 'V' | 'NV' | 'J';
293
+ /** `BookingStatus` (`kaafil-engine`'s real Prisma enum) — never a free
294
+ * string; the DTO widens it to `z.string()` on the wire, but this composite
295
+ * only ever recognizes these three real values. */
296
+ type ManifestBookingStatus = 'CONFIRMED' | 'TENTATIVE' | 'CANCELLED';
297
+ interface ManifestTraveller {
298
+ readonly travellerId: string;
299
+ readonly fullName: string;
300
+ readonly bookingStatus: ManifestBookingStatus;
301
+ readonly diet: ManifestDiet | null;
302
+ readonly groupId: string | null;
303
+ readonly dueMinor: number;
304
+ readonly currency: string;
305
+ }
306
+ interface ManifestBookingGroup {
307
+ readonly groupId: string;
308
+ /** `Party.kind` (real) — used only for the i18n fallback name when
309
+ * `label` is null, never rendered as its own badge (the reference
310
+ * screenshot shows no kind badge on the group card itself). */
311
+ readonly kind: 'FAMILY' | 'COUPLE' | 'FRIENDS' | 'CORPORATE' | 'OTHER';
312
+ readonly label: string | null;
313
+ readonly members: readonly {
314
+ readonly travellerId: string;
315
+ readonly fullName: string;
316
+ }[];
317
+ readonly dueMinor: number;
318
+ readonly currency: string;
319
+ }
320
+
321
+ declare function ManagerManifestSection({ tripRef, onCollectFromGroup, onOpenTraveller, emptyView, components, style, }: ManagerManifestSectionProps): ReactNode;
322
+
323
+ interface ManagerMeSectionProps {
324
+ /** Fired when a recent-trip row is tapped — the host's own real
325
+ * navigation into `ManagerTripSection` for that trip (hard rule #9, ships
326
+ * no router). Omit to render rows as plain, non-interactive text. */
327
+ readonly onOpenTrip?: (tripRef: string) => void;
328
+ /** Renders a "Sign out" button only when supplied — `useSession()` itself
329
+ * exposes no sign-out method (credential storage is host-owned), same
330
+ * "prop presence gates the affordance" convention `ManagerCloseoutSection`
331
+ * `UnlockRequestForm` already establishes. */
332
+ readonly onSignOut?: () => void;
333
+ readonly style?: KaafilTokenOverrides;
334
+ }
335
+
336
+ declare function ManagerMeSection({ onOpenTrip, onSignOut, style, }: ManagerMeSectionProps): ReactNode;
337
+
338
+ interface BalanceDueDisplayRow {
339
+ readonly travellerId: string;
340
+ readonly fullName: string;
341
+ readonly initials: string;
342
+ readonly outstandingMinor: number;
343
+ readonly currency: string;
344
+ }
345
+
346
+ interface BalancesDueSectionProps {
347
+ readonly rows: readonly BalanceDueDisplayRow[];
348
+ readonly showingAll: boolean;
349
+ readonly onSelect: (row: BalanceDueDisplayRow) => void;
350
+ readonly onSeeAll: () => void;
351
+ }
352
+
353
+ interface MoneyStatsProps {
354
+ readonly float?: {
355
+ readonly balanceMinor: number;
356
+ readonly issuedMinor: number;
357
+ readonly currency: string;
358
+ };
359
+ readonly spend?: {
360
+ readonly amountMinor: number;
361
+ readonly currency: string;
362
+ };
363
+ readonly collect?: {
364
+ readonly amountMinor: number;
365
+ readonly travellerCount: number;
366
+ readonly currency: string;
367
+ };
368
+ readonly reimbursable?: {
369
+ readonly amountMinor: number;
370
+ readonly count: number;
371
+ readonly currency: string;
372
+ };
373
+ }
374
+
375
+ interface RecentExpensesSectionProps {
376
+ readonly expenses: readonly ExpenseLiveRow[];
377
+ readonly onSelect: (expense: ExpenseLiveRow) => void;
378
+ }
379
+
380
+ interface ManagerMoneySectionProps {
381
+ /** The trip this section reads every real hook's own data for. */
382
+ readonly tripRef: string;
383
+ /** Fired when a balances-due row's traveller name is tapped — the same
384
+ * real destination `ManagerManifestSection`/`ManagerRoomingSection`'s
385
+ * `onOpenTraveller` already open. Still fired via a callback rather than
386
+ * a router (hard rule #9). */
387
+ readonly onOpenTraveller?: (travellerId: string, fullName: string) => void;
388
+ /** Fired when the float balance card's "View full ledger" affordance is
389
+ * tapped — the host pushes `ManagerFloatLedgerSection` (a full-screen
390
+ * deep-dive, never a tab, matching the `openTraveller`/`openTraveller`-
391
+ * style push convention). Omit to hide the affordance entirely — "prop
392
+ * presence gates the affordance," the same convention
393
+ * `ManagerCloseoutSection`'s own `UnlockRequestForm` establishes. */
394
+ readonly onViewFloatLedger?: () => void;
395
+ /** Tier-4 named-component overrides (`04-customization-ladder.md`'s own
396
+ * "the only way to replace a named component") — the three genuinely
397
+ * reskinnable regions. Each receives EXACTLY the same props this
398
+ * composite's own default renders it with. */
399
+ readonly components?: {
400
+ readonly Stats?: ComponentType<MoneyStatsProps>;
401
+ readonly RecentExpenses?: ComponentType<RecentExpensesSectionProps>;
402
+ readonly BalancesDue?: ComponentType<BalancesDueSectionProps>;
403
+ };
404
+ readonly style?: KaafilTokenOverrides;
405
+ }
406
+
407
+ declare function ManagerMoneySection({ tripRef, onViewFloatLedger, components, style, }: ManagerMoneySectionProps): ReactNode;
408
+
409
+ interface ManagerNotificationsSectionProps {
410
+ /** Fired after a row marks itself read — the host decides what a non-null
411
+ * `tripId` means (navigate there); a `null` tripId row has nowhere to go,
412
+ * so a host may simply no-op. Required, matching the spec's own
413
+ * `NotificationsFeed` contract (never optional — a row with no navigation
414
+ * destination at all would be a dead tap target). */
415
+ readonly onSelectNotification: (notification: {
416
+ readonly notificationId: string;
417
+ readonly tripId: string | null;
418
+ }) => void;
419
+ readonly style?: KaafilTokenOverrides;
420
+ }
421
+
422
+ declare function ManagerNotificationsSection({ onSelectNotification, style, }: ManagerNotificationsSectionProps): ReactNode;
423
+
424
+ type WireOnly<T> = T extends unknown ? Omit<T, 'status' | 'syncedAt'> : never;
425
+ type ManagerTodayEngaged = Extract<WireOnly<ManagerTodayReady>, {
426
+ kind: 'trip';
427
+ }>;
428
+ type ManagerTodayIdle = Extract<WireOnly<ManagerTodayReady>, {
429
+ kind: 'idle';
430
+ }>;
431
+ interface ManagerNowSectionProps {
432
+ /** The trip this section reads `useManagerToday(tripRef)` for — resolved
433
+ * by the caller, typically off `useManagerMe()`'s own `defaultTripId`. */
434
+ readonly tripRef: string;
435
+ /** Fired when a hero quick-link chip (Manifest/Rooming/Checklist/Docs) OR
436
+ * the post-trip closeout card's "N item(s) still need closing" row is
437
+ * tapped — pure navigation, no router (hard rule #9). The host decides
438
+ * where each key routes to; a module whose composite doesn't exist yet
439
+ * (`'closing-day'` included — `ClosingDayFlow` is a later wave) still
440
+ * fires this callback, so the host can no-op it until it does. */
441
+ readonly onNavigateModule: (moduleKey: 'manifest' | 'rooming' | 'checklist' | 'docs' | 'closing-day') => void;
442
+ /** Fired once a Quick Actions "Log an expense" submit REALLY succeeds
443
+ * (the FAB opens a real `LogExpenseSheet` internally, backed by
444
+ * `useExpenses(tripRef).log()` — the same sheet `ManagerMoneySection`'s
445
+ * own "+" menu uses) — a completion hook for host-side toasts/analytics,
446
+ * not the trigger that opens anything. */
447
+ readonly onLogExpense: () => void;
448
+ /** Fired once a Quick Actions "Collect payment" submit REALLY succeeds
449
+ * (backed by `useCollections(tripRef).record()`), same shape as
450
+ * `onLogExpense` above. */
451
+ readonly onCollectPayment: () => void;
452
+ readonly components?: {
453
+ readonly ManagerNowSectionUI?: ComponentType<ManagerNowSectionUIProps>;
454
+ };
455
+ /** Overrides the default `kind: 'idle'` empty/upcoming-trip card. */
456
+ readonly idleView?: ReactNode | ((reading: ManagerTodayIdle) => ReactNode);
457
+ readonly style?: KaafilTokenOverrides;
458
+ }
459
+ interface ManagerNowSectionUIProps {
460
+ readonly data: ManagerTodayEngaged;
461
+ readonly syncedAt: string;
462
+ readonly onNavigateModule: ManagerNowSectionProps['onNavigateModule'];
463
+ readonly onLogExpense: () => void;
464
+ readonly onCollectPayment: () => void;
465
+ readonly style?: KaafilTokenOverrides;
466
+ }
467
+
468
+ declare function ManagerNowSection(props: ManagerNowSectionProps): ReactNode;
469
+
470
+ interface ManagerOverviewSectionProps {
471
+ readonly tripRef: string;
472
+ readonly style?: KaafilTokenOverrides;
473
+ }
474
+
475
+ declare function ManagerOverviewSection({ tripRef, style }: ManagerOverviewSectionProps): ReactNode;
476
+
477
+ interface CloseStopResolution {
478
+ readonly travellerId: string;
479
+ readonly status: 'BOARDED' | 'NO_SHOW';
480
+ }
481
+
482
+ interface BoardingViewProps {
483
+ readonly manifest: PickupManifestResult;
484
+ readonly activeStopId: string;
485
+ readonly eventType: 'TRIP' | 'TREK';
486
+ readonly pendingWriteIds: ReadonlySet<string>;
487
+ readonly closePending: boolean;
488
+ readonly onSelectStop: (stopId: string) => void;
489
+ readonly onBoard: (travellerId: string, status: 'BOARDED' | 'NO_SHOW') => void;
490
+ readonly onCorrect: (travellerId: string, status: 'BOARDED' | 'NO_SHOW') => void;
491
+ readonly onCloseStop: (input: {
492
+ readonly resolutions?: readonly CloseStopResolution[];
493
+ readonly confirm?: boolean;
494
+ readonly confirmedHeadCount?: number;
495
+ }) => void;
496
+ readonly onBack: () => void;
497
+ }
498
+
499
+ interface StopListProps {
500
+ readonly stops: readonly PickupStopLiveRow[];
501
+ readonly kind: PickupStopKind;
502
+ readonly hasDropStops: boolean;
503
+ readonly onKindChange: (kind: PickupStopKind) => void;
504
+ readonly onSelectStop: (stop: PickupStopLiveRow) => void;
505
+ }
506
+
507
+ /** `PickupStopDeltaRow`, narrowed to the live shape — a deleted-since-last-
508
+ * cursor row carries no `name`/`rollup`/etc at all. */
509
+ type PickupStopLiveRow = Exclude<PickupStopDeltaRow, {
510
+ readonly _tombstone: true;
511
+ }>;
512
+ type PickupStopKind = PickupStopLiveRow['kind'];
513
+ interface ManagerPickupsSectionProps {
514
+ /** The trip this section reads `usePickups(tripRef)` for. */
515
+ readonly tripRef: string;
516
+ /** Real, resolved upstream (`useManagerMe()`'s own trip row) — the close-
517
+ * stop flow's two real policies (TRIP hard-resolve vs TREK short-close
518
+ * confirm) are selected by this, never re-derived inside this composite. */
519
+ readonly eventType: 'TRIP' | 'TREK';
520
+ /** Tier-4 named-component overrides — the two genuinely reskinnable
521
+ * regions. */
522
+ readonly components?: {
523
+ readonly StopList?: ComponentType<StopListProps>;
524
+ readonly BoardingView?: ComponentType<BoardingViewProps>;
525
+ };
526
+ readonly style?: KaafilTokenOverrides;
527
+ }
528
+
529
+ declare function ManagerPickupsSection({ tripRef, eventType, components, style, }: ManagerPickupsSectionProps): ReactNode;
530
+
531
+ interface RoomCardProps {
532
+ readonly room: RoomingRoom;
533
+ readonly onSelectBed: (room: RoomingRoom, bed: RoomingBed) => void;
534
+ readonly onEditRoom: (room: RoomingRoom) => void;
535
+ }
536
+
537
+ interface RoomingBedStats {
538
+ readonly occupied: number;
539
+ readonly total: number;
540
+ }
541
+
542
+ interface RoomingStatsProps {
543
+ readonly roomCount: number;
544
+ readonly beds: RoomingBedStats;
545
+ readonly unassignedCount: number;
546
+ }
547
+
548
+ interface UnassignedPoolSectionProps$1 {
549
+ readonly travellers: readonly RoomingOccupantRow[];
550
+ readonly loaded: boolean;
551
+ readonly onSelectTraveller: (traveller: RoomingOccupantRow) => void;
552
+ }
553
+
554
+ type RoomingRoomDeltaRow = RoomingReady['rooms'][number];
555
+ type RoomingRoom = Exclude<RoomingRoomDeltaRow, {
556
+ readonly _tombstone: true;
557
+ }>;
558
+ type RoomingStayWindowDeltaRow = RoomingReady['stayWindows'][number];
559
+ type RoomingStayWindow = Exclude<RoomingStayWindowDeltaRow, {
560
+ readonly _tombstone: true;
561
+ }>;
562
+ type RoomingOccupantRow = RoomingReady['unassignedPool']['travellers'][number];
563
+ type RoomingBed = RoomingRoom['beds'][number];
564
+ type RoomingAutoAssignResult = Awaited<ReturnType<RoomingReady['autoAssign']>>;
565
+ interface ManagerRoomingSectionProps {
566
+ /** The trip this section reads `useRooming()`'s own reads for. */
567
+ readonly tripRef: string;
568
+ /** Fired when an occupied bed's "View profile" row is tapped — the same
569
+ * real destination `ManagerManifestSection.onOpenTraveller` already opens,
570
+ * so a traveller reachable from the rooming board lands on the identical
571
+ * `ManagerTravellerProfileSection`. Still fired via a callback rather than
572
+ * a router (hard rule #9). */
573
+ readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
574
+ /** Overrides the "no rooms in this stay window yet" empty state — same
575
+ * render-prop shape `ManagerManifestSection.emptyView`/
576
+ * `ManagerNowSection.idleView` already establish. Omit for the built-in
577
+ * message. */
578
+ readonly emptyView?: ReactNode | (() => ReactNode);
579
+ /** Tier-4 named-component overrides (`04-customization-ladder.md`'s own
580
+ * "the only way to replace a named component") — the three leaf pieces a
581
+ * partner CRM is most likely to reskin. Each receives EXACTLY the same
582
+ * props this composite's own default renders it with. */
583
+ readonly components?: {
584
+ readonly Stats?: ComponentType<RoomingStatsProps>;
585
+ readonly RoomCard?: ComponentType<RoomCardProps>;
586
+ readonly UnassignedPool?: ComponentType<UnassignedPoolSectionProps$1>;
587
+ };
588
+ readonly style?: KaafilTokenOverrides;
589
+ }
590
+
591
+ declare function ManagerRoomingSection({ tripRef, onOpenTraveller, emptyView, components, style, }: ManagerRoomingSectionProps): ReactNode;
592
+
593
+ interface ManagerRosterSectionProps {
594
+ readonly tripRef: string;
595
+ /** Same prop shape `ManagerManifestSection` already exposes and
596
+ * `ManagerTripSection` already threads through — reused verbatim, not a
597
+ * new contract. */
598
+ readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
599
+ readonly style?: KaafilTokenOverrides;
600
+ }
601
+
602
+ declare function ManagerRosterSection({ tripRef, onOpenTraveller, style, }: ManagerRosterSectionProps): ReactNode;
603
+
604
+ interface ManagerSyncCenterSectionProps {
605
+ /** Scopes the itemized outbox view to one trip's own lane — the real
606
+ * `OutboxOp.tripRef` field. Per spec, `SyncCenterScreen`'s own `tripRef`
607
+ * is optional (aggregating across every open lane when omitted); this
608
+ * composite requires it because every other manager composite in this
609
+ * package is already single-trip-scoped (no cross-trip aggregation
610
+ * exists anywhere else to be consistent with). */
611
+ readonly tripRef: string;
612
+ /** The host supplies this since only it knows every module's own label
613
+ * conventions for a `listName` — omit to fall back to the real
614
+ * `entity.listName` (or the op's own `path` when no `entity` is set)
615
+ * verbatim, never a fabricated generic label. `entityId` is the real
616
+ * `OutboxEntityRef.id`, renamed at this boundary only to keep the bare
617
+ * word "id" out of every exported prop table (U-019/dx-17). */
618
+ readonly getEntityLabel?: (entity: {
619
+ readonly listName: string;
620
+ readonly entityId?: string;
621
+ }) => string;
622
+ /** Fired after a conflict resolves, for host-side telemetry only — per
623
+ * spec, T2. */
624
+ readonly onResolved?: (opId: string, choice: 'keep-queued' | 'keep-current') => void;
625
+ readonly style?: KaafilTokenOverrides;
626
+ }
627
+
628
+ declare function ManagerSyncCenterSection({ tripRef, getEntityLabel, onResolved, style, }: ManagerSyncCenterSectionProps): ReactNode;
629
+
630
+ type TravellerDiet = 'V' | 'NV' | 'J';
631
+ interface DietaryRow {
632
+ readonly key: string;
633
+ readonly labelKey: string;
634
+ readonly value: string;
635
+ readonly diet: TravellerDiet | null;
636
+ readonly isAlert: boolean;
637
+ }
638
+
639
+ interface TravellerDietaryCardProps {
640
+ readonly rows: readonly DietaryRow[];
641
+ }
642
+
643
+ interface TravellerEmergencyCardProps {
644
+ readonly name: string;
645
+ readonly relation: string | null;
646
+ readonly phone: string | null;
647
+ }
648
+
649
+ interface TravellerNote {
650
+ readonly id: string;
651
+ readonly body: string;
652
+ readonly performedByKind: string | null;
653
+ readonly createdAt: string;
654
+ }
655
+ interface TravellerNotesSectionProps {
656
+ readonly notes: readonly TravellerNote[];
657
+ readonly onAddNote: (body: string) => Promise<void>;
658
+ }
659
+
660
+ interface TravellerPaymentCardProps {
661
+ readonly currency: string;
662
+ readonly totalMinor: number;
663
+ readonly collectedMinor: number;
664
+ readonly dueMinor: number;
665
+ readonly canLogPayment: boolean;
666
+ readonly onLogPayment: () => void;
667
+ }
668
+
669
+ interface ManagerTravellerProfileSectionProps {
670
+ /** The trip this section reads `useTravellerProfile`/`useParties`/
671
+ * `useCollections` for. */
672
+ readonly tripRef: string;
673
+ readonly travellerRef: string;
674
+ /** Tier-4 named-component overrides (`04-customization-ladder.md`) — the
675
+ * leaf pieces a partner CRM is most likely to reskin. Each receives
676
+ * exactly the same real props this composite's own default renders it
677
+ * with. */
678
+ readonly components?: {
679
+ readonly DietaryCard?: ComponentType<TravellerDietaryCardProps>;
680
+ readonly EmergencyCard?: ComponentType<TravellerEmergencyCardProps>;
681
+ readonly PaymentCard?: ComponentType<TravellerPaymentCardProps>;
682
+ readonly NotesSection?: ComponentType<TravellerNotesSectionProps>;
683
+ };
684
+ readonly style?: KaafilTokenOverrides;
685
+ }
686
+
687
+ declare function ManagerTravellerProfileSection({ tripRef, travellerRef, components, style, }: ManagerTravellerProfileSectionProps): ReactNode;
688
+
689
+ /** The one real trip-vs-trek field (`Trip.eventType`, no third value) —
690
+ * derived structurally off `useManagerMe()`'s own trip row so this file
691
+ * never imports `kaafil-js` directly. */
692
+ type ManagerTripEventType = ManagerMeReady['trips'][number]['eventType'];
693
+ /**
694
+ * Every real tab key this composite knows about — the merge this build's
695
+ * own plan locks in: ONE tab set computed from `eventType`, never two
696
+ * independent screens (the boilerplate's own posture, deliberately not
697
+ * followed here). `docs`/`info` are excluded entirely: no real endpoint
698
+ * backs either (this build's own audit), so no tab key is minted for a
699
+ * screen that would always render nothing.
700
+ */
701
+ type ManagerTripTabKey = 'manifest' | 'rooming' | 'vehicles' | 'itinerary' | 'money' | 'vendors' | 'checklist' | 'forms' | 'pickups' | 'overview' | 'roster' | 'closing' | 'documents';
702
+ interface ManagerTripSectionProps {
703
+ /** The trip this section reads `useManagerMe()`'s own trip list for,
704
+ * resolved by the caller — same convention `ManagerNowSection.tripRef`
705
+ * already establishes. */
706
+ readonly tripRef: string;
707
+ /** Uncontrolled by default (the section owns its own active-tab state,
708
+ * same as `ManagerShell`'s bottom bar being host-controlled while this
709
+ * screen's OWN chip row is nested one level below it) — pass both to
710
+ * control it from outside. */
711
+ readonly activeTabKey?: ManagerTripTabKey;
712
+ readonly onTabChange?: (key: ManagerTripTabKey) => void;
713
+ /** Fired when a booking group's "Collect" CTA is tapped — nav-only
714
+ * (hard rule #9): no group-level collect endpoint exists (`collections`'s
715
+ * DTOs key strictly on `travellerId`), so the host resolves this into
716
+ * whatever real per-traveller flow it wants. Required once the manifest
717
+ * panel is live; a caller with no groups yet may still pass a no-op. */
718
+ readonly onCollectFromGroup: (groupId: string) => void;
719
+ /** Fired when a traveller row is tapped — see
720
+ * `ManagerManifestSectionProps.onOpenTraveller`'s own doc comment (this
721
+ * composite just forwards it to its built-in manifest panel). */
722
+ readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
723
+ /** Fired when a vendor row is tapped in the built-in vendors panel — see
724
+ * `ManagerVendorsSectionProps.onVendorSelect`'s own doc comment (this
725
+ * composite just forwards it). */
726
+ readonly onVendorSelect: (tripVendorId: string) => void;
727
+ /** Forwarded straight through to the built-in `'money'` panel's own
728
+ * `onViewFloatLedger` — see `ManagerMoneySectionProps`'s own doc comment.
729
+ * Omit to hide the "View full ledger" affordance entirely. */
730
+ readonly onViewFloatLedger?: () => void;
731
+ /** Forwarded straight through to the built-in `'closing'` panel's own
732
+ * `onSubmitUnlockRequest` — see `ManagerCloseoutSectionProps`'s own doc
733
+ * comment for why this composite never calls `closeout.unlock()` itself
734
+ * (`apiKeyAuth`-only). Omit to render the built-in closing panel's static
735
+ * "contact ops to reopen" message once locked. */
736
+ readonly onSubmitUnlockRequest?: (payload: {
737
+ readonly tripRef: string;
738
+ readonly reason: string;
739
+ }) => Promise<void>;
740
+ /** Registry of real panel content, keyed by tab (hard rule #8 — never a
741
+ * switch/if-else here). Overrides this composite's OWN built-in panel for
742
+ * a key (`'manifest'`, this wave) when supplied; every other key still
743
+ * renders the built-in "not built yet" placeholder until a later wave
744
+ * fills it — no restructuring required when that happens. */
745
+ readonly panels?: Partial<Record<ManagerTripTabKey, ReactNode>>;
746
+ readonly style?: KaafilTokenOverrides;
747
+ }
748
+
749
+ declare function ManagerTripSection(props: ManagerTripSectionProps): ReactNode;
750
+
751
+ interface UnassignedPoolSectionProps {
752
+ readonly travellers: readonly SeatingOccupantRow[];
753
+ readonly loaded: boolean;
754
+ readonly onSelectTraveller: (traveller: SeatingOccupantRow) => void;
755
+ }
756
+
757
+ interface VehicleCardProps {
758
+ readonly vehicle: SeatingVehicle;
759
+ readonly ownerName: string | undefined;
760
+ readonly onSelectSeat: (vehicle: SeatingVehicle, seat: SeatingSeatSlot) => void;
761
+ readonly onSelectOccupant: (vehicle: SeatingVehicle, travellerId: string) => void;
762
+ readonly onAddOccupant: (vehicle: SeatingVehicle) => void;
763
+ /** Opens the sheet's `customSeat` flow — a manager types the traveller's
764
+ * REAL boarding-pass/ticket seat number (business rows, exit rows, gaps
765
+ * this vehicle's synthesised grid doesn't model), rather than being
766
+ * limited to the grid's own auto-generated labels. Only offered on a
767
+ * seat-mapped vehicle. */
768
+ readonly onEnterCustomSeat: (vehicle: SeatingVehicle) => void;
769
+ readonly onEditVehicle: (vehicle: SeatingVehicle) => void;
770
+ readonly onEditOwner: (vehicle: SeatingVehicle) => void;
771
+ /** Opens `VehicleRosterSheet` — a full scrollable list of every real
772
+ * occupant on this vehicle, for a capacity too large to scan comfortably
773
+ * as wrapped chips (e.g. a 12-seat tempo traveller). */
774
+ readonly onViewRoster: (vehicle: SeatingVehicle) => void;
775
+ }
776
+
777
+ interface VehicleStatsProps {
778
+ readonly vehicleCount: number;
779
+ readonly seated: number;
780
+ readonly capacity: number;
781
+ readonly unassignedCount: number;
782
+ }
783
+
784
+ type SeatingVehicleRowRaw = SeatingReady['vehicles'][number];
785
+ type SeatingVehicle = Exclude<SeatingVehicleRowRaw, {
786
+ readonly _tombstone: true;
787
+ }>;
788
+ type SeatingOccupantRow = SeatingReady['unassignedPool']['travellers'][number];
789
+ type SeatingSeatSlot = SeatingVehicle['seats'][number];
790
+ interface ManagerVehiclesSectionProps {
791
+ /** The trip this section reads `useSeating()`'s own reads for. */
792
+ readonly tripRef: string;
793
+ /** Fired when an occupied seat/occupant slot's "View profile" row is
794
+ * tapped — the same real destination `ManagerManifestSection`/
795
+ * `ManagerRoomingSection.onOpenTraveller` already open, so a traveller
796
+ * reachable from the vehicles board lands on the identical
797
+ * `ManagerTravellerProfileSection`. Still fired via a callback rather
798
+ * than a router (hard rule #9). */
799
+ readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
800
+ /** Overrides the "no vehicles yet" empty state — same render-prop shape
801
+ * `ManagerRoomingSection.emptyView`/`ManagerManifestSection.emptyView`
802
+ * already establish. Omit for the built-in message. */
803
+ readonly emptyView?: ReactNode | (() => ReactNode);
804
+ /** Tier-4 named-component overrides (`04-customization-ladder.md`'s own
805
+ * "the only way to replace a named component") — the three leaf pieces a
806
+ * partner CRM is most likely to reskin. Each receives EXACTLY the same
807
+ * props this composite's own default renders it with. */
808
+ readonly components?: {
809
+ readonly Stats?: ComponentType<VehicleStatsProps>;
810
+ readonly VehicleCard?: ComponentType<VehicleCardProps>;
811
+ readonly UnassignedPool?: ComponentType<UnassignedPoolSectionProps>;
812
+ };
813
+ readonly style?: KaafilTokenOverrides;
814
+ }
815
+
816
+ declare function ManagerVehiclesSection({ tripRef, onOpenTraveller, emptyView, components, style, }: ManagerVehiclesSectionProps): ReactNode;
817
+
818
+ interface VendorListSectionProps {
819
+ readonly vendors: readonly TripVendorRow[];
820
+ readonly onVendorSelect: (tripVendorId: string) => void;
821
+ readonly emptyView?: ReactNode | (() => ReactNode);
822
+ }
823
+
824
+ type VendorCategory = TripVendorRow['category'];
825
+ interface ManagerVendorsSectionProps {
826
+ /** The trip this section reads `useVendors(tripRef, '')` for. */
827
+ readonly tripRef: string;
828
+ /** Narrows the already-fetched list to one category, client-side — the
829
+ * spec's own claim that this is "the SDK's own `?category=` filter,
830
+ * passed straight through" does not match the real
831
+ * `client.vendors.list()` signature (verified: no such query param
832
+ * exists), so this never round-trips to the server. */
833
+ readonly category?: VendorCategory;
834
+ /** Fired when a vendor row is tapped — a pure passthrough (`10-vendors.md`
835
+ * §VendorList's own "Does NOT": "`onVendorSelect` only reports which row
836
+ * was activated"). No detail sheet exists in this build; the host decides
837
+ * what happens next, the same convention `onOpenTraveller` already
838
+ * establishes elsewhere in this UIKit. */
839
+ readonly onVendorSelect: (tripVendorId: string) => void;
840
+ /** Overrides the default empty state shown when the real list is
841
+ * genuinely empty (zero vendors is a legitimate state, never confused
842
+ * with a dark capability) — same `ReactNode | (() => ReactNode)` shape
843
+ * `ManagerVehiclesSection.emptyView`/`ManagerManifestSection.emptyView`
844
+ * already use. */
845
+ readonly emptyView?: ReactNode | (() => ReactNode);
846
+ /** Tier-4 named-component override — the one genuinely reskinnable
847
+ * region, named after the spec's own `VendorList` component. */
848
+ readonly components?: {
849
+ readonly VendorListUI?: ComponentType<VendorListSectionProps>;
850
+ };
851
+ readonly style?: KaafilTokenOverrides;
852
+ }
853
+
854
+ declare function ManagerVendorsSection({ tripRef, category, onVendorSelect, emptyView, components, style, }: ManagerVendorsSectionProps): ReactNode;
855
+
856
+ /** The 3 bottom-nav destinations this Surface owns — Trip/Trek merge into
857
+ * one tab (icon/label switch off the selected trip's real `eventType`),
858
+ * matching `apps/sample-manager/src/App.tsx`'s own real `BottomTabKey`. */
859
+ type KaafilManagerAppTabKey = 'now' | 'trip' | 'me';
860
+ interface TripListRowProps {
861
+ readonly trip: ManagerOwnTrip;
862
+ readonly onSelect: (tripRef: string) => void;
863
+ readonly style?: KaafilTokenOverrides;
864
+ }
865
+ interface KaafilManagerAppProps {
866
+ /** Seeds which trip is selected on first mount — skips the trip-list
867
+ * picker even with 2+ live trips (the deep-link case). Ignored once
868
+ * `selectedTripRef` (below) is supplied, since that makes selection fully
869
+ * host-controlled. */
870
+ readonly initialTripRef?: string;
871
+ /** Fully controls which trip is selected — omit to let this component own
872
+ * its own selection state (seeded by `initialTripRef`, then updated by the
873
+ * trip-list picker / "Me" tab's own trip list / a trip-linked
874
+ * notification, exactly as `apps/sample-manager/src/App.tsx` already
875
+ * does). Supplying this makes the Surface a controlled component for trip
876
+ * selection — `onSelectTrip` still fires so the host can react. */
877
+ readonly selectedTripRef?: string;
878
+ /** Fully controls the bottom-tab selection — omit to let this component
879
+ * own it (defaulting to `'now'`). */
880
+ readonly activeTab?: KaafilManagerAppTabKey;
881
+ /** Seeds `ManagerTripSection`'s own internal chip-tab (Manifest/Rooming/
882
+ * Money/etc.) on first entry into the Trip tab — a second, real
883
+ * deep-linking level below `initialTripRef`/`activeTab` (e.g. landing
884
+ * directly on the Money tab from a push notification). */
885
+ readonly initialTripTabKey?: ManagerTripTabKey;
886
+ /** → `ManagerNowSection.onNavigateModule` (required there). */
887
+ readonly onNavigateModule: (moduleKey: 'manifest' | 'rooming' | 'checklist' | 'docs' | 'closing-day') => void;
888
+ /** → `ManagerNowSection.onLogExpense` (required there). */
889
+ readonly onLogExpense: () => void;
890
+ /** → `ManagerNowSection.onCollectPayment` (required there). */
891
+ readonly onCollectPayment: () => void;
892
+ /** → `ManagerTripSection.onCollectFromGroup` (required there). */
893
+ readonly onCollectFromGroup: (groupId: string) => void;
894
+ /** → `ManagerTripSection.onVendorSelect` (required there). */
895
+ readonly onVendorSelect: (tripVendorId: string) => void;
896
+ /** → `ManagerTripSection.onSubmitUnlockRequest` (optional there — omit to
897
+ * render its own static "contact ops to reopen" message once locked). */
898
+ readonly onSubmitUnlockRequest?: (payload: {
899
+ readonly tripRef: string;
900
+ readonly reason: string;
901
+ }) => Promise<void>;
902
+ /** Renders "Sign out" on the Me tab only when supplied (prop-presence
903
+ * gates the affordance, same convention `ManagerMeSection` itself already
904
+ * establishes) — this Surface has no credential/session-teardown method
905
+ * of its own to call first. */
906
+ readonly onSignOut?: () => void;
907
+ /** Fires whenever the selected trip changes (picker row tap, the Me tab's
908
+ * own trip list, or a trip-linked notification) — per spec, T2. */
909
+ readonly onSelectTrip?: (tripRef: string) => void;
910
+ /** Fires whenever the bottom tab changes — per spec, T2. */
911
+ readonly onTabChange?: (tabKey: KaafilManagerAppTabKey) => void;
912
+ /** Fires whenever `ManagerTripSection`'s own internal chip-tab changes —
913
+ * the second deep-linking level `initialTripTabKey` seeds. */
914
+ readonly onTripTabChange?: (tabKey: ManagerTripTabKey) => void;
915
+ /** Fired alongside the internal traveller-profile push opening/closing —
916
+ * an analytics/URL-sync hook, never the only way this navigation happens
917
+ * (the real trigger is always a row tap inside a mounted composite). */
918
+ readonly onOpenTraveller?: (travellerId: string, fullName: string) => void;
919
+ readonly onCloseTraveller?: () => void;
920
+ /** Fired alongside the internal notifications push opening/closing. */
921
+ readonly onOpenNotifications?: () => void;
922
+ readonly onCloseNotifications?: () => void;
923
+ /** Fired alongside the internal float-ledger push opening/closing. */
924
+ readonly onOpenFloatLedger?: () => void;
925
+ readonly onCloseFloatLedger?: () => void;
926
+ /** Fired alongside the internal sync-center push opening/closing — the
927
+ * real destination the connectivity badge's own "N need attention" text
928
+ * opens (`ManagerSyncCenterSection`); a caught bug this wave: that text
929
+ * rendered with nowhere to go before this push existed. */
930
+ readonly onOpenSyncCenter?: () => void;
931
+ readonly onCloseSyncCenter?: () => void;
932
+ /** → `ManagerSyncCenterSection.getEntityLabel` (optional there; `entityId`
933
+ * is that composite's own renamed `OutboxEntityRef.id`, kept consistent
934
+ * at this boundary too so this prop table stays free of the bare word
935
+ * "id", U-019/dx-17). */
936
+ readonly getSyncEntityLabel?: (entity: {
937
+ readonly listName: string;
938
+ readonly entityId?: string;
939
+ }) => string;
940
+ /** → `ManagerSyncCenterSection.onResolved` (optional there). */
941
+ readonly onConflictResolved?: (opId: string, choice: 'keep-queued' | 'keep-current') => void;
942
+ readonly components?: {
943
+ /** The trip-list picker's own row renderer (spec-named). */
944
+ readonly TripListItem?: ComponentType<TripListRowProps>;
945
+ /** Maps onto `ManagerShell`'s own existing `components.TabIcon` slot —
946
+ * the only real tab-bar customization point that exists today.
947
+ * Deliberately narrower than the spec's "TabBar" name implies:
948
+ * `ManagerShell` has no slot to replace the whole tab-bar chrome with,
949
+ * so this Surface does not invent a second, parallel tab-bar renderer
950
+ * just to satisfy the literal name (one mechanism per slot, U-004). */
951
+ readonly TabBar?: ComponentType<{
952
+ readonly icon: string;
953
+ }>;
954
+ /** Overrides the honest "no active trip assignment" empty state — real
955
+ * integrators reskin/rebrand this message, they don't fabricate a fake
956
+ * trip to avoid it. */
957
+ readonly EmptyState?: ComponentType<Record<string, never>>;
958
+ /** Overrides the initial loading skeleton. */
959
+ readonly LoadingView?: ComponentType<Record<string, never>>;
960
+ /** Overrides the unconditional connectivity indicator (spec: "not a
961
+ * prop an integrator can turn off" — replacing its PRESENTATION is
962
+ * still allowed; only removing it entirely is not, so this slot has no
963
+ * `false`/hide variant). */
964
+ readonly SyncStatusBadge?: ComponentType<{
965
+ readonly isOnline: boolean;
966
+ readonly pending: number;
967
+ readonly parked: number;
968
+ readonly onOpenSyncCenter?: () => void;
969
+ }>;
970
+ };
971
+ readonly style?: KaafilTokenOverrides;
972
+ }
973
+
974
+ declare function KaafilManagerApp(props: KaafilManagerAppProps): ReactNode;
975
+
976
+ interface ManagerFabProps {
977
+ readonly onClick: () => void;
978
+ /** Accessible name — there is no visible label on the button itself
979
+ * (boilerplate's own `MFab`: an icon-only circle), so this is required,
980
+ * never optional. */
981
+ readonly label: string;
982
+ /** Defaults to a plus glyph — the one icon every family composite that
983
+ * has reached for a FAB so far has needed (`ManagerNowSection`'s own
984
+ * quick-actions trigger); pass a different icon for a family composite
985
+ * that needs a different primary action. */
986
+ readonly icon?: ReactNode;
987
+ readonly tone?: 'accent' | 'ink';
988
+ readonly style?: KaafilTokenOverrides;
989
+ }
990
+
991
+ declare function ManagerFab({ onClick, label, icon, tone, style, }: ManagerFabProps): ReactNode;
992
+
993
+ interface ManagerShellTab {
994
+ readonly key: string;
995
+ readonly label: string;
996
+ /** One glyph, `icon="clock"` etc. — a registry key (hard rule #8), never
997
+ * an inline SVG passed per-tab (`ManagerShell` owns its own icon set,
998
+ * matching the boilerplate's own fixed 4-icon tab bar; a host wanting a
999
+ * fifth tab's own glyph uses `components.TabIcon`). */
1000
+ readonly icon: 'now' | 'trek' | 'trip' | 'me';
1001
+ }
1002
+ interface ManagerShellHeaderPage {
1003
+ readonly variant?: 'page';
1004
+ readonly eyebrow?: string;
1005
+ readonly title: string;
1006
+ /** Real unread count (`useNotifications()`'s own `unreadCount`) — never a
1007
+ * boolean or a guessed number; omit entirely to hide the bell. */
1008
+ readonly unread?: number;
1009
+ readonly onBellPress?: () => void;
1010
+ /** 2-letter avatar initials — omit renders a person glyph, never a "?"
1011
+ * (boilerplate's own `m-header.tsx` documents exactly this reasoning:
1012
+ * a question mark on your own avatar reads as "we don't know who you
1013
+ * are," which is never true once a session is open). */
1014
+ readonly avatarInitials?: string;
1015
+ readonly onAvatarPress?: () => void;
1016
+ /** Replaces the whole right-hand slot (bell + avatar) at once. */
1017
+ readonly right?: ReactNode;
1018
+ readonly style?: KaafilTokenOverrides;
1019
+ }
1020
+ interface ManagerShellHeaderBack {
1021
+ readonly variant: 'back';
1022
+ readonly eyebrow?: string;
1023
+ readonly title: string;
1024
+ readonly onBack: () => void;
1025
+ readonly right?: ReactNode;
1026
+ readonly style?: KaafilTokenOverrides;
1027
+ }
1028
+ type ManagerShellHeaderConfig = ManagerShellHeaderPage | ManagerShellHeaderBack;
1029
+ interface ManagerShellProps {
1030
+ readonly children?: ReactNode;
1031
+ /** Omit to render no header at all — a screen that wants a "back" header
1032
+ * passes `{ variant: 'back', ... }` here instead of mounting its own. */
1033
+ readonly header?: ManagerShellHeaderConfig;
1034
+ /** Omit to render no tab bar (e.g. a screen pushed on top of the tab
1035
+ * stack) — the tab bar is never assumed present. */
1036
+ readonly tabs?: readonly ManagerShellTab[];
1037
+ readonly activeTabKey?: string;
1038
+ readonly onTabChange?: (key: string) => void;
1039
+ /** The floating action button slot — a fully caller-owned node (usually
1040
+ * an `MFab`-equivalent button this family will ship once the FAB pattern
1041
+ * is needed by more than one composite); `ManagerShell` only positions
1042
+ * it, never renders a default. */
1043
+ readonly fab?: ReactNode;
1044
+ readonly components?: {
1045
+ readonly TabIcon?: ComponentType<{
1046
+ readonly icon: string;
1047
+ }>;
1048
+ };
1049
+ readonly style?: KaafilTokenOverrides;
1050
+ }
1051
+
1052
+ declare function ManagerShell({ children, header, tabs, activeTabKey, onTabChange, fab, style, }: ManagerShellProps): ReactNode;
1053
+
1054
+ export { type ChecklistItemDeltaRow, type ChecklistItemGate, type ChecklistItemLiveRow, type ChecklistItemPhase, ChecklistSectionRow, CloseoutBlockerRow, FormDefinitionDetail, FormResponseDetail, type ItineraryChangeLogRow, ItineraryDayRow, ItineraryItemRow, KaafilManagerApp, type KaafilManagerAppProps, type KaafilManagerAppTabKey, ManagerChecklistSection, type ManagerChecklistSectionProps, ManagerCloseoutSection, type ManagerCloseoutSectionProps, ManagerDocumentsSection, type ManagerDocumentsSectionProps, ManagerFab, type ManagerFabProps, ManagerFloatLedgerSection, type ManagerFloatLedgerSectionProps, ManagerFormsSection, type ManagerFormsSectionProps, ManagerItinerarySection, type ManagerItinerarySectionProps, ManagerManifestSection, type ManagerManifestSectionProps, ManagerMeSection, type ManagerMeSectionProps, ManagerMoneySection, type ManagerMoneySectionProps, ManagerNotificationsSection, type ManagerNotificationsSectionProps, ManagerNowSection, type ManagerNowSectionProps, type ManagerNowSectionUIProps, ManagerOverviewSection, type ManagerOverviewSectionProps, ManagerPickupsSection, type ManagerPickupsSectionProps, ManagerRoomingSection, type ManagerRoomingSectionProps, ManagerRosterSection, type ManagerRosterSectionProps, ManagerShell, type ManagerShellHeaderBack, type ManagerShellHeaderConfig, type ManagerShellHeaderPage, type ManagerShellProps, type ManagerShellTab, ManagerSyncCenterSection, type ManagerSyncCenterSectionProps, type ManagerTodayEngaged, type ManagerTodayIdle, ManagerTravellerProfileSection, type ManagerTravellerProfileSectionProps, type ManagerTripEventType, ManagerTripSection, type ManagerTripSectionProps, type ManagerTripTabKey, ManagerVehiclesSection, type ManagerVehiclesSectionProps, ManagerVendorsSection, type ManagerVendorsSectionProps, type ManifestBookingGroup, type ManifestBookingStatus, type ManifestDiet, type ManifestTraveller, PickupManifestResult, type RoomingAutoAssignResult, type RoomingBed, type RoomingOccupantRow, type RoomingRoom, type RoomingStayWindow, type SeatingOccupantRow, type SeatingSeatSlot, type SeatingVehicle, TravellerFormResponseRow, TripFormRow, type TripListRowProps, TripVendorRow, type VendorCategory };