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,1157 @@
1
+ export { B as BootErrorScreen, a as BootErrorScreenProps, b as BootFailureMode, O as OfflineFallbackScreen, c as OfflineFallbackScreenProps } from '../OfflineFallbackScreen-Ctm7nBa-.cjs';
2
+ export { L as LockedTripScreen, a as LockedTripScreenProps, N as NotFoundScreen, b as NotFoundScreenProps, S as SessionExpiredScreen, c as SessionExpiredScreenProps } from '../SessionExpiredScreen-CytQNuak.cjs';
3
+ import { ReactNode, ComponentType } from 'react';
4
+ import { K as KaafilTokenOverrides } from '../tokenStyle-CToG5oOS.cjs';
5
+ import { C as ChecklistTemplateRow, a as ChecklistTemplateItemRow, F as FormDetailRow, b as FormFieldRow, c as FormRow, M as ManagerListRowResponse, T as TravellerDirectoryItemResponse, J as JourneyTriggerRow, A as AgencyTripRow, d as TripManifestRow, e as CollectionDeltaRow, f as AgencyTripRead } from '../useAgencyTrip-BUYSIaC2.cjs';
6
+ export { g as AgencySettingsDocument, B as FormBuilderBindingRow, h as FormSectionRow } from '../useAgencyTrip-BUYSIaC2.cjs';
7
+ import { ManagerAgencyProfileResponse, TravellerAgencyProfileResponse, BookingListRow, PickupStopDeltaRow, RoomingRoomDeltaRow, SeatingVehicleDeltaRow } from 'kaafil-js/client';
8
+ export { BookingListRow, ManagerAgencyProfileResponse, SeatingOccupant, TravellerAgencyProfileResponse, AgencyTripSegmentCounts as TripDirectorySegmentCounts, TripManifestFacets } from 'kaafil-js/client';
9
+ import { C as ChecklistSectionRow, a as ChecklistsReady, F as FileListItem, E as ExpenseDeltaRow, b as FloatMovementRow, T as TripFormRow, c as TripFormResponseRow, I as ItineraryDayRow, d as ItineraryItemRow, R as RoomingStayWindowRow, e as TripVendorRow } from '../useVendors-DXOuZWhZ.cjs';
10
+ export { f as FloatSummaryRow } from '../useVendors-DXOuZWhZ.cjs';
11
+
12
+ type PlanLockedReason = 'agency' | 'partner-ceiling';
13
+ interface PlanLockedScreenProps {
14
+ /** The capability this route was headed for. Read for its own triple
15
+ * only — never exhaustively switched on (`§6` point 5's open-set rule). */
16
+ readonly capabilityKey: string;
17
+ /** The host's own upsell/support flow — Kaafil has no in-product upgrade
18
+ * path to hand off to. `undefined` means the wire did not say which
19
+ * queue this belongs in; see this file's header. */
20
+ readonly onUpgradeRequest: (reason: PlanLockedReason | undefined) => void;
21
+ /** Supplied by the caller when it saw a refusal that named one. */
22
+ readonly reason?: PlanLockedReason;
23
+ readonly components?: {
24
+ readonly PlanLockedScreenUI?: () => ReactNode;
25
+ };
26
+ readonly style?: KaafilTokenOverrides;
27
+ }
28
+ declare function PlanLockedScreen({ capabilityKey, onUpgradeRequest, reason, components, style, }: PlanLockedScreenProps): ReactNode;
29
+
30
+ /** One field's current draft state. `set: false` means this field is
31
+ * omitted from the outgoing PATCH entirely (inherits the Kaafil default) —
32
+ * `value` is meaningless in that case, kept only so re-enabling the field
33
+ * restores the last value the admin had entered rather than resetting to
34
+ * blank. `value: null` is itself a real, explicit state (`set: true`) for
35
+ * the one field where the wire distinguishes "no default" from "explicitly
36
+ * unlimited" (`files.ttlDays`). */
37
+ interface FieldEntry {
38
+ readonly set: boolean;
39
+ readonly value: boolean | number | string | readonly string[] | null;
40
+ }
41
+ type SectionDraft = Record<string, FieldEntry>;
42
+ interface FieldOption {
43
+ readonly value: string;
44
+ readonly labelKey: string;
45
+ }
46
+ interface ToggleFieldDef {
47
+ readonly kind: 'toggle';
48
+ readonly key: string;
49
+ readonly labelKey: string;
50
+ readonly hintKey?: string;
51
+ }
52
+ interface NumberFieldDef {
53
+ readonly kind: 'number';
54
+ readonly key: string;
55
+ readonly labelKey: string;
56
+ readonly hintKey?: string;
57
+ readonly min?: number;
58
+ /** When true, this field's wire type is `number | null` and the UI offers
59
+ * a distinct explicit-null state (a checkbox), not just blank-vs-number. */
60
+ readonly nullable?: boolean;
61
+ readonly nullLabelKey?: string;
62
+ readonly visibleWhen?: (draft: SectionDraft) => boolean;
63
+ }
64
+ interface SelectFieldDef {
65
+ readonly kind: 'select';
66
+ readonly key: string;
67
+ readonly labelKey: string;
68
+ readonly options: readonly FieldOption[];
69
+ readonly visibleWhen?: (draft: SectionDraft) => boolean;
70
+ }
71
+ interface ArrayFieldDef {
72
+ readonly kind: 'array';
73
+ readonly key: string;
74
+ readonly labelKey: string;
75
+ readonly options: readonly FieldOption[];
76
+ /** Order carries real meaning on the wire (e.g. `rooming.strategyOrder` —
77
+ * the solver applies strategies in this order) — show move-up/move-down
78
+ * controls only when true. */
79
+ readonly reorderable?: boolean;
80
+ }
81
+ type FieldDef = ToggleFieldDef | NumberFieldDef | SelectFieldDef | ArrayFieldDef;
82
+ interface SectionDef {
83
+ readonly id: string;
84
+ /** A presentation-only grouping label (`settings-shell.tsx`'s own
85
+ * "Workspace" / "Your account" / "Advanced" grouping is the identical
86
+ * device) — purely a nav-rail organizing aid, never a real category on
87
+ * the wire; `Agency.settings` itself has no concept of a section group. */
88
+ readonly groupTitleKey: string;
89
+ readonly titleKey: string;
90
+ readonly descriptionKey: string;
91
+ readonly fields: readonly FieldDef[];
92
+ }
93
+ /** `'conflict'` — another write landed first (`CONFLICT_VERSION`); the only
94
+ * safe recovery is discarding this card's local draft and re-reading the
95
+ * server's value, never silently overwriting it. `'failed'` — any other
96
+ * save failure (network, validation); the local draft is still valid, so
97
+ * the recovery is just "try again", no reseed. */
98
+ type SectionSaveErrorKind = 'conflict' | 'failed';
99
+ interface SectionCardProps {
100
+ readonly section: SectionDef;
101
+ /** The stored section object (`document.settings[section.id]`), or
102
+ * `undefined` if this agency has never set anything in this section. */
103
+ readonly stored: Record<string, unknown> | undefined;
104
+ readonly saving: boolean;
105
+ readonly errorKind: SectionSaveErrorKind | undefined;
106
+ readonly onSave: (sectionId: string, patch: Record<string, unknown>) => void;
107
+ /** Fired when the admin dismisses the error banner — for `'conflict'` the
108
+ * parent refreshes and this card reseeds its draft from the fresh value;
109
+ * for `'failed'` the parent just clears the error and the draft is left
110
+ * untouched so the admin can retry the same edit. */
111
+ readonly onDismissError: () => void;
112
+ readonly style?: KaafilTokenOverrides;
113
+ }
114
+ interface AgencySettingsScreenProps {
115
+ readonly title?: string;
116
+ readonly subtitle?: string;
117
+ readonly components?: {
118
+ readonly SectionCard?: ComponentType<SectionCardProps>;
119
+ };
120
+ readonly style?: KaafilTokenOverrides;
121
+ }
122
+
123
+ declare function AgencySettingsScreen({ title, subtitle, components, style, }: AgencySettingsScreenProps): ReactNode;
124
+
125
+ /** A locally-edited draft of one item — the same shape `items[]` needs to
126
+ * become on save (`PatchChecklistTemplateRequest`'s item shape: `key`,
127
+ * `title`, `subLine`, `isMandatory`, `gate`, `dayOffset` — no `id`/
128
+ * `sortOrder`, array order IS sort order), plus a local-only `draftId` so
129
+ * React can key a not-yet-saved row before the server assigns a real `id`. */
130
+ interface ChecklistTemplateItemDraft {
131
+ readonly draftId: string;
132
+ readonly key: string;
133
+ readonly title: string;
134
+ readonly subLine: string;
135
+ readonly isMandatory: boolean;
136
+ readonly gate: ChecklistTemplateItemRow['gate'];
137
+ readonly dayOffset: string;
138
+ }
139
+ interface TemplateEditorHeaderProps {
140
+ readonly template: ChecklistTemplateRow;
141
+ readonly title: string;
142
+ readonly onTitleChange: (title: string) => void;
143
+ readonly hasChanges: boolean;
144
+ readonly saving: boolean;
145
+ readonly onSave: () => void;
146
+ readonly canPublish: boolean;
147
+ readonly publishing: boolean;
148
+ readonly onPublish: () => void;
149
+ readonly style?: KaafilTokenOverrides;
150
+ }
151
+ interface TemplateItemRowProps {
152
+ readonly item: ChecklistTemplateItemDraft;
153
+ readonly index: number;
154
+ readonly total: number;
155
+ readonly onEdit: (draftId: string) => void;
156
+ readonly onRemove: (draftId: string) => void;
157
+ readonly onReorder: (draggedDraftId: string, targetDraftId: string) => void;
158
+ readonly style?: KaafilTokenOverrides;
159
+ }
160
+ interface ChecklistTemplateEditorProps {
161
+ readonly templateId: string;
162
+ readonly onSaved?: (template: ChecklistTemplateRow) => void;
163
+ readonly onPublished?: (template: ChecklistTemplateRow) => void;
164
+ readonly components?: {
165
+ readonly TemplateEditorHeader?: ComponentType<TemplateEditorHeaderProps>;
166
+ readonly TemplateItemRow?: ComponentType<TemplateItemRowProps>;
167
+ };
168
+ readonly style?: KaafilTokenOverrides;
169
+ }
170
+
171
+ declare function ChecklistTemplateEditor({ templateId, onSaved, onPublished, components, style, }: ChecklistTemplateEditorProps): ReactNode;
172
+
173
+ interface TemplateRowProps {
174
+ readonly template: ChecklistTemplateRow;
175
+ readonly selected?: boolean;
176
+ readonly onSelect?: (template: ChecklistTemplateRow) => void;
177
+ readonly onDelete?: (template: ChecklistTemplateRow) => void;
178
+ readonly style?: KaafilTokenOverrides;
179
+ }
180
+ interface ChecklistTemplateLibraryProps {
181
+ /** Optional page-head title — rendered above the toolbar. Omit when this
182
+ * composite is mounted under a shell that already renders its own page
183
+ * title (e.g. `TemplateAuthoringFlow`'s own master column), same
184
+ * convention `ManagerDirectoryFlow` establishes. */
185
+ readonly title?: string;
186
+ /** Optional supporting copy under `title` — omitted whenever `title` is. */
187
+ readonly subtitle?: string;
188
+ /** The currently-selected template, if any — highlights that row. Purely
189
+ * presentational; this composite never owns selection state itself. */
190
+ readonly selectedTemplateId?: string;
191
+ readonly onSelectTemplate?: (template: ChecklistTemplateRow) => void;
192
+ /** Fires after a successful delete — `templateId` of the removed row. */
193
+ readonly onDeleted?: (templateId: string) => void;
194
+ /** Controlled create-dialog visibility — set when a host shell (e.g.
195
+ * `KaafilAgencyWorkspace`) renders the "New template" action as its own
196
+ * page-level primary CTA rather than duplicating a create button inside
197
+ * this composite's own card header (the mockup's own generic page-header
198
+ * pattern: every pane's `cta` sits beside its `<h1>`, never inside the
199
+ * card below it). Omit both to fall back to this composite's own
200
+ * internal button + state, for standalone/story usage. */
201
+ readonly creating?: boolean;
202
+ readonly onCreatingChange?: (next: boolean) => void;
203
+ readonly components?: {
204
+ readonly TemplateRow?: ComponentType<TemplateRowProps>;
205
+ };
206
+ readonly style?: KaafilTokenOverrides;
207
+ }
208
+
209
+ declare function ChecklistTemplateLibrary({ title, subtitle, selectedTemplateId, onSelectTemplate, onDeleted, creating: controlledCreating, onCreatingChange, components, style, }: ChecklistTemplateLibraryProps): ReactNode;
210
+
211
+ type FormFieldKind = 'HEADING' | 'INFO_BLOCK' | 'SHORT_TEXT' | 'LONG_TEXT' | 'EMAIL' | 'PHONE' | 'URL' | 'NUMBER' | 'CURRENCY' | 'RATING' | 'NPS' | 'DATE' | 'DATETIME' | 'TIME' | 'SELECT' | 'MULTISELECT' | 'CHECKBOX' | 'CONSENT' | 'SIGNATURE' | 'FILE_UPLOAD' | 'ADDRESS';
212
+
213
+ interface BuilderHeaderProps {
214
+ readonly form: FormDetailRow;
215
+ readonly title: string;
216
+ readonly onTitleChange: (title: string) => void;
217
+ readonly onTitleCommit: () => void;
218
+ readonly onDelete?: () => void;
219
+ readonly onArchive: () => void;
220
+ readonly onUnarchive: () => void;
221
+ readonly onPublish: () => void;
222
+ readonly onClose: () => void;
223
+ readonly onReopen: () => void;
224
+ readonly pending: boolean;
225
+ readonly style?: KaafilTokenOverrides;
226
+ }
227
+ interface FieldRowProps {
228
+ readonly field: FormFieldRow;
229
+ readonly kind: FormFieldKind;
230
+ /** `true` while THIS row is the one being dragged — dims it in place. */
231
+ readonly dragging: boolean;
232
+ /** `true` while a drag is hovering over this row — shows the drop-target
233
+ * indicator. */
234
+ readonly dragOver: boolean;
235
+ /** Opens `FieldEditDialog` for this field — a read-only summary row,
236
+ * mockup's own `f.edit` anatomy (`TemplateItemRow.tsx`'s established
237
+ * split: rows summarize, a dialog edits). */
238
+ readonly onOpenSettings: () => void;
239
+ readonly onDragStart: () => void;
240
+ readonly onDragOverRow: () => void;
241
+ readonly onDrop: () => void;
242
+ readonly onDragEnd: () => void;
243
+ readonly style?: KaafilTokenOverrides;
244
+ }
245
+ interface FormBuilderProps {
246
+ readonly formId: string;
247
+ readonly onBack?: () => void;
248
+ readonly components?: {
249
+ readonly BuilderHeader?: ComponentType<BuilderHeaderProps>;
250
+ readonly FieldRow?: ComponentType<FieldRowProps>;
251
+ };
252
+ readonly style?: KaafilTokenOverrides;
253
+ }
254
+
255
+ declare function FormBuilder({ formId, onBack, components, style }: FormBuilderProps): ReactNode;
256
+
257
+ interface FormsAuthoringFlowProps {
258
+ /** Deep-link: skip the library and open this form's builder directly on
259
+ * mount. Omit to start on the library. */
260
+ readonly initialFormId?: string;
261
+ readonly style?: KaafilTokenOverrides;
262
+ }
263
+
264
+ declare function FormsAuthoringFlow({ initialFormId, style }: FormsAuthoringFlowProps): ReactNode;
265
+
266
+ interface FormRowProps$1 {
267
+ readonly form: FormRow;
268
+ readonly selected?: boolean;
269
+ readonly onSelect?: (form: FormRow) => void;
270
+ readonly onArchive?: (form: FormRow) => void;
271
+ readonly onUnarchive?: (form: FormRow) => void;
272
+ readonly onPublish?: (form: FormRow) => void;
273
+ readonly onClose?: (form: FormRow) => void;
274
+ readonly onReopen?: (form: FormRow) => void;
275
+ readonly onDelete?: (form: FormRow) => void;
276
+ readonly style?: KaafilTokenOverrides;
277
+ }
278
+ interface FormsLibraryProps {
279
+ /** Optional page-head title — rendered above the toolbar. Omit when this
280
+ * composite is mounted under a shell that already renders its own page
281
+ * title, same convention `ChecklistTemplateLibrary` establishes. */
282
+ readonly title?: string;
283
+ /** Optional supporting copy under `title` — omitted whenever `title` is. */
284
+ readonly subtitle?: string;
285
+ /** The currently-selected form, if any — highlights that row. Purely
286
+ * presentational; this composite never owns selection state itself. */
287
+ readonly selectedFormId?: string;
288
+ readonly onSelectForm?: (form: FormRow) => void;
289
+ /** Controlled create-dialog visibility — set when a host shell (e.g.
290
+ * `KaafilAgencyWorkspace`) renders the "New form" action as its own
291
+ * page-level primary CTA rather than duplicating a create button inside
292
+ * this composite's own card header (the mockup's own generic page-header
293
+ * pattern: every pane's `cta` sits beside its `<h1>`, never inside the
294
+ * card below it). Omit both to fall back to this composite's own
295
+ * internal button + state, for standalone/story usage. */
296
+ readonly creating?: boolean;
297
+ readonly onCreatingChange?: (next: boolean) => void;
298
+ readonly components?: {
299
+ readonly FormRow?: ComponentType<FormRowProps$1>;
300
+ };
301
+ readonly style?: KaafilTokenOverrides;
302
+ }
303
+
304
+ declare function FormsLibrary({ title, subtitle, selectedFormId, onSelectForm, creating: controlledCreating, onCreatingChange, components, style, }: FormsLibraryProps): ReactNode;
305
+
306
+ interface ManagerResultRowProps {
307
+ readonly manager: ManagerListRowResponse;
308
+ /** This row's position in the current page of results — cycles the
309
+ * shared identity-avatar palette (`AdminAvatar`), offset by one from the
310
+ * traveller directory's own start so the two lists never coincidentally
311
+ * colour-match at the same row position. */
312
+ readonly index: number;
313
+ readonly onSelect?: (manager: ManagerListRowResponse) => void;
314
+ readonly style?: KaafilTokenOverrides;
315
+ }
316
+ interface ManagerDirectoryFlowProps {
317
+ /** Optional page-head title — rendered above the search bar. Omit when
318
+ * this flow is mounted under a shell that already renders its own page
319
+ * title (e.g. `KaafilAgencyWorkspace`'s "Managers" nav destination), same
320
+ * convention `TravellerDirectoryFlow` establishes. */
321
+ readonly title?: string;
322
+ /** Optional supporting copy under `title` — omitted whenever `title` is. */
323
+ readonly subtitle?: string;
324
+ readonly onSelectManager?: (manager: ManagerListRowResponse) => void;
325
+ readonly components?: {
326
+ readonly ManagerResultRow?: ComponentType<ManagerResultRowProps>;
327
+ };
328
+ readonly style?: KaafilTokenOverrides;
329
+ }
330
+
331
+ declare function ManagerDirectoryFlow({ title, subtitle, onSelectManager, components, style, }: ManagerDirectoryFlowProps): ReactNode;
332
+
333
+ type ManagerAgencyProfileTripRow = ManagerAgencyProfileResponse['trips'][number];
334
+ interface ManagerProfileSectionProps {
335
+ readonly managerRef: string;
336
+ /** Renders a back affordance in the hero when supplied — omitted, the
337
+ * hero shows no back control (a host embedding this without its own
338
+ * "back to directory" concept, e.g. a modal). */
339
+ readonly onBack?: () => void;
340
+ readonly components?: {
341
+ readonly Hero?: ComponentType<{
342
+ readonly profile: ManagerAgencyProfileResponse;
343
+ readonly onBack?: () => void;
344
+ }>;
345
+ readonly AssignmentsCard?: ComponentType<{
346
+ readonly trips: readonly ManagerAgencyProfileTripRow[];
347
+ }>;
348
+ };
349
+ readonly style?: KaafilTokenOverrides;
350
+ }
351
+
352
+ declare function ManagerProfileSection({ managerRef, onBack, components, style, }: ManagerProfileSectionProps): ReactNode;
353
+
354
+ interface TemplateAuthoringFlowProps {
355
+ /** Deep-link: skip the library and open this template's editor directly
356
+ * on mount. Omit to start on the library. */
357
+ readonly initialTemplateId?: string;
358
+ readonly style?: KaafilTokenOverrides;
359
+ }
360
+
361
+ declare function TemplateAuthoringFlow({ initialTemplateId, style, }: TemplateAuthoringFlowProps): ReactNode;
362
+
363
+ interface TravellerSearchBoxProps {
364
+ /** An optional client-side floor — defaults to `0` (no floor; the server
365
+ * itself no longer requires a `q` at all). Set this when a host serving an
366
+ * unusually large agency wants to hold off issuing a request until the
367
+ * caller has typed a few characters. */
368
+ readonly minQueryLength?: number;
369
+ readonly debounceMs?: number;
370
+ readonly onSelectTraveller?: (traveller: TravellerDirectoryItemResponse) => void;
371
+ /** Rendered in the same row as the search input, right-aligned —
372
+ * `TravellerDirectoryFlow`'s own "Add traveller" button uses this so the
373
+ * two sit on one row instead of the search input stacking underneath a
374
+ * separate toolbar. Omit for a bare search box with nothing beside it. */
375
+ readonly trailingAction?: ReactNode;
376
+ readonly components?: {
377
+ readonly TravellerSearchBoxUI?: ComponentType<Record<string, never>>;
378
+ };
379
+ readonly style?: KaafilTokenOverrides;
380
+ }
381
+ interface TravellerDirectoryFlowProps {
382
+ /** Optional page-head title — rendered above the search bar, boilerplate's
383
+ * own "Trips" `<h1>` rhythm (`--kf-type-heading-xl-*`). Omit when this flow
384
+ * is mounted under a shell that already renders its own page title (e.g.
385
+ * `AdminShell`'s "Traveller" nav destination) so the two never double up —
386
+ * pass one only when this flow owns its own page head. */
387
+ readonly title?: string;
388
+ /** Optional supporting copy under `title` — omitted whenever `title` is. */
389
+ readonly subtitle?: string;
390
+ /** Omits the "Add traveller" affordance — for a host whose own CRM UI is
391
+ * the sole traveller-intake surface. */
392
+ readonly hideAddTraveller?: boolean;
393
+ /** Lifts the "Add traveller" affordance OUT of this card and into the
394
+ * host's own page header, where the design puts it. Supplying this pair
395
+ * makes the flow controlled: it renders no button of its own and opens
396
+ * the modal from `adding` instead. `ChecklistTemplateLibrary`/
397
+ * `FormsLibrary` expose the identical pair for the same reason. */
398
+ readonly adding?: boolean;
399
+ readonly onAddingChange?: (adding: boolean) => void;
400
+ readonly minQueryLength?: number;
401
+ readonly debounceMs?: number;
402
+ readonly onSelectTraveller?: (traveller: TravellerDirectoryItemResponse) => void;
403
+ /** Fires once a traveller is created via `AddTravellerModal`, with the
404
+ * real row the server returned. */
405
+ readonly onTravellerAdded?: (traveller: TravellerDirectoryItemResponse) => void;
406
+ readonly components?: {
407
+ readonly TravellerSearchBox?: ComponentType<TravellerSearchBoxProps>;
408
+ readonly AddTravellerModal?: ComponentType<{
409
+ readonly onClose: () => void;
410
+ readonly onCreated: (traveller: TravellerDirectoryItemResponse) => void;
411
+ }>;
412
+ };
413
+ readonly style?: KaafilTokenOverrides;
414
+ }
415
+
416
+ declare function TravellerSearchBox({ minQueryLength, debounceMs, onSelectTraveller, trailingAction, style, }: TravellerSearchBoxProps): ReactNode;
417
+ declare function TravellerDirectoryFlow({ title, subtitle, hideAddTraveller, adding, onAddingChange, minQueryLength, debounceMs, onSelectTraveller, onTravellerAdded, components, style, }: TravellerDirectoryFlowProps): ReactNode;
418
+
419
+ type TravellerAgencyProfileTripRow = TravellerAgencyProfileResponse['trips'][number];
420
+ type TravellerAgencyProfileNoteRow = TravellerAgencyProfileResponse['notes'][number];
421
+ type TravellerAgencyProfileLifetime = TravellerAgencyProfileResponse['lifetime'];
422
+ interface TravellerProfileSectionProps {
423
+ readonly travellerRef: string;
424
+ /** Renders a back affordance in the hero when supplied — omitted, the
425
+ * hero shows no back control (a host embedding this without its own
426
+ * "back to directory" concept, e.g. a modal). */
427
+ readonly onBack?: () => void;
428
+ readonly components?: {
429
+ readonly Hero?: ComponentType<{
430
+ readonly profile: TravellerAgencyProfileResponse;
431
+ readonly onBack?: () => void;
432
+ }>;
433
+ readonly PersonalCard?: ComponentType<{
434
+ readonly profile: TravellerAgencyProfileResponse;
435
+ }>;
436
+ readonly LifetimeCard?: ComponentType<{
437
+ readonly lifetime: TravellerAgencyProfileLifetime;
438
+ }>;
439
+ readonly TripHistoryTable?: ComponentType<{
440
+ readonly trips: readonly TravellerAgencyProfileTripRow[];
441
+ }>;
442
+ readonly NotesList?: ComponentType<{
443
+ readonly notes: readonly TravellerAgencyProfileNoteRow[];
444
+ }>;
445
+ };
446
+ readonly style?: KaafilTokenOverrides;
447
+ }
448
+
449
+ declare function TravellerProfileSection({ travellerRef, onBack, components, style, }: TravellerProfileSectionProps): ReactNode;
450
+
451
+ interface TriggerDetailPanelProps {
452
+ readonly trigger: JourneyTriggerRow;
453
+ readonly saving: boolean;
454
+ /** The header toggle — `enabled` is always live, never gated behind the
455
+ * edit dialog (matches the mockup's own `selToggle` sitting in the
456
+ * "SELECTED" card head, outside `dlgOpen`'s own scope). */
457
+ readonly onToggle: (next: boolean) => void;
458
+ /** Fired by `TriggerEditDialog`'s own Save — `anchor`/`offsetHours` only,
459
+ * `enabled` never travels through this path. */
460
+ readonly onSave: (input: {
461
+ readonly anchor: 'START' | 'END';
462
+ readonly offsetHours: number;
463
+ }) => void;
464
+ readonly phaseLabel: (phase: string) => string;
465
+ readonly style?: KaafilTokenOverrides;
466
+ }
467
+ interface TriggerTemplateEditorProps {
468
+ readonly title?: string;
469
+ readonly subtitle?: string;
470
+ /** Show only this trip mode's triggers. Omit to show both. */
471
+ readonly tripModeFilter?: 'GROUP' | 'PERSONALIZED';
472
+ readonly onTriggerPatched?: (trigger: JourneyTriggerRow) => void;
473
+ readonly style?: KaafilTokenOverrides;
474
+ }
475
+
476
+ declare function TriggerTemplateEditor({ title, subtitle, tripModeFilter, onTriggerPatched, style, }: TriggerTemplateEditorProps): ReactNode;
477
+
478
+ /** A booking that is not a tombstone. `useBookings` hands both through so a
479
+ * caller can tell the difference; this tab only ever renders the live
480
+ * ones. */
481
+ type BookingLiveRow = Exclude<BookingListRow, {
482
+ readonly _tombstone: true;
483
+ }>;
484
+ type BookingKind = 'ACCOMMODATION' | 'TRANSPORT' | 'ACTIVITY';
485
+ interface TripBookingsSectionProps {
486
+ readonly tripRef: string;
487
+ /** Offered on a row that has vouchers, so an operator can get to the
488
+ * files themselves. Navigation is a callback — the UIKit ships no
489
+ * router (hard rule #9). Absent means the affordance is not offered. */
490
+ readonly onOpenDocuments?: () => void;
491
+ readonly style?: KaafilTokenOverrides;
492
+ }
493
+
494
+ declare function TripBookingsSection({ tripRef, onOpenDocuments, style, }: TripBookingsSectionProps): ReactNode;
495
+
496
+ interface ChecklistItemRowProps {
497
+ readonly item: ChecklistItemLiveRow;
498
+ readonly readOnly: boolean;
499
+ readonly busy: boolean;
500
+ readonly onToggle: () => void;
501
+ readonly onEdit: () => void;
502
+ }
503
+
504
+ interface PhasePanelProps {
505
+ readonly phase: ChecklistPhase;
506
+ readonly sections: readonly ChecklistSectionRow[];
507
+ readonly items: readonly ChecklistItemLiveRow[];
508
+ readonly readOnly: boolean;
509
+ readonly busyItemId: string | null;
510
+ readonly onToggle: (item: ChecklistItemLiveRow) => void;
511
+ readonly onEdit: (item: ChecklistItemLiveRow) => void;
512
+ readonly onAddToSection: (section: ChecklistSectionRow) => void;
513
+ readonly onAddToPhase: (phase: ChecklistPhase) => void;
514
+ readonly ItemRow?: ComponentType<ChecklistItemRowProps>;
515
+ }
516
+
517
+ /** One row of `useChecklists()`'s `items[]` — a live item or a tombstone. */
518
+ type ChecklistItemDeltaRow = ChecklistsReady['items'][number];
519
+ /** `ChecklistItemDeltaRow`, narrowed to the live shape — a
520
+ * deleted-since-last-cursor row carries no `title`/`status`/etc. at all. */
521
+ type ChecklistItemLiveRow = Exclude<ChecklistItemDeltaRow, {
522
+ readonly _tombstone: true;
523
+ }>;
524
+ type ChecklistPhase = ChecklistSectionRow['phase'];
525
+ type ChecklistGate = ChecklistItemLiveRow['gate'];
526
+ interface TripChecklistSectionProps {
527
+ /** The trip this section reads `useChecklists(tripRef)` for. */
528
+ readonly tripRef: string;
529
+ /** Forces every toggle/add/edit/delete affordance inert. The `423`
530
+ * close-out lock drives this internally too. */
531
+ readonly readOnly?: boolean;
532
+ /** Opens with one phase focused rather than all three equal-width. */
533
+ readonly initialPhase?: ChecklistPhase;
534
+ /** Multi-select bulk toggle. Gate-carrying items are excluded from a
535
+ * selection regardless — see this file's header. */
536
+ readonly enableBulkToggle?: boolean;
537
+ /** Fires after a toggle LANDS, once per item even for a bulk toggle. */
538
+ readonly onItemToggled?: (itemId: string) => void;
539
+ /** Tier-4 named-component overrides. Each receives exactly the props this
540
+ * composite's own default renders it with. */
541
+ readonly components?: {
542
+ readonly PhasePanel?: ComponentType<PhasePanelProps>;
543
+ readonly ChecklistItemRow?: ComponentType<ChecklistItemRowProps>;
544
+ };
545
+ readonly style?: KaafilTokenOverrides;
546
+ }
547
+
548
+ declare function TripChecklistSection({ tripRef, readOnly, initialPhase, onItemToggled, components, style, }: TripChecklistSectionProps): ReactNode;
549
+
550
+ /** `Trip.eventType`, derived off the row so it cannot drift from the wire. */
551
+ type TripEventType = AgencyTripRow['eventType'];
552
+ interface TripRowProps {
553
+ readonly trip: AgencyTripRow;
554
+ /** This row's position in the current page — cycles the shared
555
+ * identity-avatar palette so adjacent rows never colour-match. */
556
+ readonly index: number;
557
+ readonly onOpen: () => void;
558
+ readonly style?: KaafilTokenOverrides;
559
+ }
560
+ interface TripDirectoryFlowProps {
561
+ /** Opens one trip. Prop-presence gates the affordance: without it rows are
562
+ * inert text rather than buttons, for a host that embeds this list purely
563
+ * as a read-only overview. */
564
+ readonly onOpenTrip?: (trip: AgencyTripRow) => void;
565
+ /** Seeds the Tours/Treks chip — for a host deep-linking into the trek view.
566
+ * Uncontrolled after mount. */
567
+ readonly initialEventType?: TripEventType;
568
+ readonly components?: {
569
+ readonly TripRow?: ComponentType<TripRowProps>;
570
+ };
571
+ readonly style?: KaafilTokenOverrides;
572
+ }
573
+
574
+ declare function TripDirectoryFlow({ onOpenTrip, initialEventType, components, style, }: TripDirectoryFlowProps): ReactNode;
575
+
576
+ /**
577
+ * The spend facts a receipt row borrows. Deliberately narrow — this is what
578
+ * an expense row actually carries that helps NAME a document. Note the
579
+ * absence of a person: an expense has `category`/`amountMinor`/`currency`/
580
+ * `description`/`vendorName`/`spentAt` and no spender, so no "uploaded by"
581
+ * is claimed anywhere on this surface.
582
+ */
583
+ interface DocumentSpend {
584
+ readonly description: string;
585
+ readonly vendorName: string | null;
586
+ readonly amountMinor: number;
587
+ readonly currency: string;
588
+ readonly spentAt: string;
589
+ readonly voidedAt: string | null;
590
+ }
591
+ /** One table row: the file, plus the spend it belongs to when one is known. */
592
+ interface DocumentRowModel {
593
+ readonly file: FileListItem;
594
+ /** `undefined` for every non-receipt, and for a receipt whose spend is not
595
+ * in the ledger this page read. Never a reason to drop the row. */
596
+ readonly spend: DocumentSpend | undefined;
597
+ }
598
+ interface TripDocumentsSectionProps {
599
+ readonly tripRef: string;
600
+ readonly style?: KaafilTokenOverrides;
601
+ }
602
+
603
+ declare function TripDocumentsSection({ tripRef, style }: TripDocumentsSectionProps): ReactNode;
604
+
605
+ /** An expense that is not a tombstone. A VOID is not a tombstone — the row
606
+ * stays live with `voidedAt` set. */
607
+ type ExpenseLiveRow = Exclude<ExpenseDeltaRow, {
608
+ readonly _tombstone: true;
609
+ }>;
610
+ type ExpenseCategory = ExpenseLiveRow['category'];
611
+ type ExpensePaymentMode = ExpenseLiveRow['paymentMode'];
612
+ type ExpenseClaimStatus = NonNullable<ExpenseLiveRow['claimStatus']>;
613
+ /** What the ledger is narrowed to. All client-side: `listExpenses` takes
614
+ * `?since=` only, so there is no server filter to pass these to. */
615
+ interface ExpenseFilters {
616
+ readonly category: ExpenseCategory | null;
617
+ readonly paymentMode: ExpensePaymentMode | null;
618
+ readonly missingReceiptOnly: boolean;
619
+ }
620
+ interface TripExpensesSectionProps {
621
+ readonly tripRef: string;
622
+ readonly style?: KaafilTokenOverrides;
623
+ }
624
+
625
+ declare function TripExpensesSection({ tripRef, style }: TripExpensesSectionProps): ReactNode;
626
+
627
+ type FloatMovementType = FloatMovementRow['type'];
628
+ type FloatDirection = FloatMovementRow['direction'];
629
+ /** Which write a dialog is collecting. `adjust` carries a direction; the
630
+ * other two are fixed by their route. */
631
+ type FloatAction = 'issue' | 'return' | 'adjust';
632
+ interface TripFloatSectionProps {
633
+ readonly tripRef: string;
634
+ readonly style?: KaafilTokenOverrides;
635
+ }
636
+
637
+ declare function TripFloatSection({ tripRef, style }: TripFloatSectionProps): ReactNode;
638
+
639
+ interface FormRowProps {
640
+ readonly form: TripFormRow;
641
+ /** From `completion()`. `undefined` when that read has not landed or
642
+ * failed — the row then shows the submitted count ALONE rather than a
643
+ * fraction with an invented denominator. */
644
+ readonly total: number | undefined;
645
+ readonly readOnly: boolean;
646
+ readonly busy: boolean;
647
+ readonly onDispatch: () => void;
648
+ readonly onExport: () => void;
649
+ readonly onOpenMissing: () => void;
650
+ }
651
+
652
+ /** One line of the who-is-missing join: everyone on the manifest, with
653
+ * their response if they have one. */
654
+ interface FormParticipantRow {
655
+ readonly travellerId: string;
656
+ readonly fullName: string;
657
+ /** `undefined` for a traveller with NO response row — the point of the
658
+ * whole view, so it renders as a person who has not started, never as an
659
+ * absence from the list. */
660
+ readonly response: TripFormResponseRow | undefined;
661
+ }
662
+ interface TripFormsSectionProps {
663
+ readonly tripRef: string;
664
+ /** Forces every dispatch/capture affordance inert. */
665
+ readonly readOnly?: boolean;
666
+ readonly components?: {
667
+ readonly FormRow?: ComponentType<FormRowProps>;
668
+ };
669
+ readonly style?: KaafilTokenOverrides;
670
+ }
671
+
672
+ declare function TripFormsSection({ tripRef, readOnly, components, style, }: TripFormsSectionProps): ReactNode;
673
+
674
+ type ItineraryViewMode = 'days' | 'timeline';
675
+ interface TripItinerarySectionProps {
676
+ readonly tripRef: string;
677
+ /**
678
+ * Host-owned navigation to a vendor. Omitted when the host has no vendor
679
+ * route — the item's vendor then renders as plain text rather than as a
680
+ * link that goes nowhere (hard rule #9: this package ships no router).
681
+ */
682
+ readonly onOpenVendor?: (vendorId: string) => void;
683
+ readonly style?: KaafilTokenOverrides;
684
+ }
685
+ /** A day plus the items that belong to it, in `sortOrder`. */
686
+ interface ItineraryDayGroup {
687
+ readonly day: ItineraryDayRow;
688
+ readonly dayNumber: number;
689
+ readonly items: readonly ItineraryItemRow[];
690
+ }
691
+
692
+ declare function TripItinerarySection({ tripRef, onOpenVendor, style, }: TripItinerarySectionProps): ReactNode;
693
+
694
+ /** How the body is arranged. The reference's own two modes. */
695
+ type ManifestGroupBy = 'booking_group' | 'none';
696
+ /**
697
+ * Everything the filter panel can narrow by — a subset of what the endpoint
698
+ * accepts, holding only the axes a real control exists for.
699
+ *
700
+ * `partyId` and `sort` are endpoint parameters this panel drives from
701
+ * elsewhere (a group card's own "only this group" affordance, and the column
702
+ * head), so they are not in the panel's own state.
703
+ */
704
+ interface ManifestFilterState {
705
+ readonly bookingStatus?: 'CONFIRMED' | 'TENTATIVE' | 'CANCELLED';
706
+ readonly balanceState?: 'paid' | 'due' | 'unbilled';
707
+ readonly gender?: 'MALE' | 'FEMALE' | 'OTHER' | 'UNKNOWN';
708
+ /** `true` narrows to travellers carrying a medical flag. Never `false` —
709
+ * "not flagged" is not a filter an operator asks for. */
710
+ readonly medical?: true;
711
+ }
712
+ interface TripManifestSectionProps {
713
+ readonly tripRef: string;
714
+ /**
715
+ * Opens the agency-wide traveller profile — a DIFFERENT screen from this
716
+ * tab's own trip-scoped detail dialog (`TravellerProfileSection` reads the
717
+ * cross-trip directory profile; the dialog reads this trip's). The
718
+ * reference's row kebab links to it in a new tab; this Surface ships no
719
+ * router (hard rule #9), so it is a callback the host wires to its own
720
+ * travellers pane. Absent means the affordance is not offered.
721
+ */
722
+ readonly onOpenTravellerProfile?: (travellerId: string, fullName: string) => void;
723
+ readonly components?: {
724
+ readonly ManifestRow?: ComponentType<ManifestRowProps>;
725
+ };
726
+ readonly style?: KaafilTokenOverrides;
727
+ }
728
+ interface ManifestRowProps {
729
+ readonly row: TripManifestRow;
730
+ /** Row position, for the avatar palette cycle. */
731
+ readonly index: number;
732
+ /** The server's own "now", for deriving age from a date of birth. Threaded
733
+ * in rather than read from a local clock — hard rule #6's posture. */
734
+ readonly serverTime: string | undefined;
735
+ readonly onOpen: () => void;
736
+ readonly onRemove: () => void;
737
+ readonly onShareLink: () => void;
738
+ readonly onOpenProfile?: () => void;
739
+ readonly style?: KaafilTokenOverrides;
740
+ }
741
+
742
+ declare function TripManifestSection({ tripRef, onOpenTravellerProfile, components, style, }: TripManifestSectionProps): ReactNode;
743
+
744
+ /** A collection that is not a tombstone. A VOID is not a tombstone — the row
745
+ * stays live with `voidedAt` set. A tombstone means the row was deleted at
746
+ * the source, which this API has no path to cause. */
747
+ type CollectionLiveRow = Exclude<CollectionDeltaRow, {
748
+ readonly _tombstone: true;
749
+ }>;
750
+ type CollectionMode = CollectionLiveRow['mode'];
751
+ type EligibleStatus = 'due' | 'settled' | 'all';
752
+
753
+ interface TripPaymentsSectionProps {
754
+ readonly tripRef: string;
755
+ /**
756
+ * The trip's own money rollup, straight from the trip read
757
+ * (`balance.{collectedMinor, totalMinor, dueMinor, currency}`). A prop
758
+ * rather than a second fetch: `TripWorkspace` already holds it, and two
759
+ * reads of the same figure is how two surfaces come to disagree about it.
760
+ *
761
+ * `undefined` when the trip has no balance rows at all — rendered as
762
+ * absent, never as ₹0 (`deriveTripHead.ts`'s own rule: "a trip with no
763
+ * balance rows has not collected ₹0, it has not been billed").
764
+ */
765
+ readonly balance: {
766
+ readonly collectedMinor: number;
767
+ readonly totalMinor: number;
768
+ readonly dueMinor: number;
769
+ readonly currency: string;
770
+ } | undefined;
771
+ readonly style?: KaafilTokenOverrides;
772
+ }
773
+
774
+ declare function TripPaymentsSection({ tripRef, balance, style, }: TripPaymentsSectionProps): ReactNode;
775
+
776
+ /** A stop that is not a tombstone. */
777
+ type PickupStopLiveRow = Exclude<PickupStopDeltaRow, {
778
+ readonly _tombstone: true;
779
+ }>;
780
+ type PickupKind = PickupStopLiveRow['kind'];
781
+ type PickupRollup = PickupStopLiveRow['rollup'];
782
+ /** Which of the two runs the switcher is showing. */
783
+ type PickupView = 'stops' | 'boarding';
784
+ interface TripPickupsSectionProps {
785
+ readonly tripRef: string;
786
+ /**
787
+ * The TRIP's IANA zone. `scheduledTime` is an instant and the DTO says to
788
+ * "render in `trip.timezone` — never assume the caller's own zone", and
789
+ * `pickups.list` does not carry the trip. Passed down by `TripWorkspace`,
790
+ * which already holds the trip read, rather than fetched a second time.
791
+ */
792
+ readonly timeZone: string;
793
+ /**
794
+ * The trip's own start date, used to anchor a NEW stop's wall clock to a
795
+ * calendar day when the run is still empty and there is no sibling stop to
796
+ * take the day from.
797
+ *
798
+ * A prop rather than `new Date()`: hard rule #6 forbids a local clock in
799
+ * `/core` and the same reasoning holds one layer out — "today" on the
800
+ * operator's laptop is not a fact about this trip, and for a trip that has
801
+ * not departed it is the wrong day outright.
802
+ */
803
+ readonly tripStartIso: string;
804
+ readonly style?: KaafilTokenOverrides;
805
+ }
806
+
807
+ declare function TripPickupsSection({ tripRef, timeZone, tripStartIso, style, }: TripPickupsSectionProps): ReactNode;
808
+
809
+ /** A room that is not a tombstone. */
810
+ type RoomingRoomLiveRow = Exclude<RoomingRoomDeltaRow, {
811
+ readonly _tombstone: true;
812
+ }>;
813
+ type RoomingBed = RoomingRoomLiveRow['beds'][number];
814
+ type RoomingOccupant = NonNullable<RoomingBed['occupant']>;
815
+ /** A stay window that is not a tombstone. `stayWindows.list` is a DELTA feed
816
+ * like the rooms — with `?since=` it carries drops, so the row type is a
817
+ * union and the tombstone branch has to be narrowed away before anything
818
+ * reads a `label`. */
819
+ type StayWindowRow = Exclude<RoomingStayWindowRow, {
820
+ readonly _tombstone: true;
821
+ }>;
822
+ /** One stay window with the rooms that belong to it. */
823
+ interface RoomingWindowGroup {
824
+ readonly window: StayWindowRow;
825
+ readonly rooms: readonly RoomingRoomLiveRow[];
826
+ readonly bedCount: number;
827
+ readonly occupiedCount: number;
828
+ }
829
+ interface TripRoomingSectionProps {
830
+ readonly tripRef: string;
831
+ /**
832
+ * The TRIP's IANA zone. A stay window's `startDate`/`endDate` are instants,
833
+ * and the same rule the itinerary and pickups tabs follow applies: render
834
+ * in the trip's zone, never the reader's.
835
+ */
836
+ readonly timeZone: string;
837
+ /**
838
+ * The trip's own first and last day. A stay window is a stretch of nights
839
+ * WITHIN a trip, so its date pickers are bounded to these — an unbounded
840
+ * calendar lets an operator pick a night the trip does not have, which the
841
+ * engine would then hold as a real window nobody is on.
842
+ *
843
+ * Props rather than a second read: `TripWorkspace` already holds the trip.
844
+ */
845
+ readonly tripStartIso: string;
846
+ readonly tripEndIso: string;
847
+ readonly style?: KaafilTokenOverrides;
848
+ }
849
+
850
+ declare function TripRoomingSection({ tripRef, timeZone, tripStartIso, tripEndIso, style, }: TripRoomingSectionProps): ReactNode;
851
+
852
+ type VendorCategory = TripVendorRow['category'];
853
+ /** Where one supplier is used on this trip. A count is `undefined`, never 0,
854
+ * when its capability is dark or its read has not landed — "we cannot see"
855
+ * and "there are none" are different facts and must not render alike. */
856
+ interface SupplierUsage {
857
+ readonly vehicles: number | undefined;
858
+ readonly itineraryItems: number | undefined;
859
+ readonly expenses: number | undefined;
860
+ }
861
+ /** The rows the usage scan reads, kept as one bag so `deriveSuppliers` takes
862
+ * a single argument rather than six. */
863
+ interface UsageSources {
864
+ readonly vehicles: readonly SeatingVehicleDeltaRow[] | undefined;
865
+ readonly itineraryItems: readonly ItineraryItemRow[] | undefined;
866
+ readonly expenses: readonly ExpenseDeltaRow[] | undefined;
867
+ }
868
+ type SupplierSortKey = 'name' | 'category' | 'city';
869
+ interface TripSuppliersSectionProps {
870
+ readonly tripRef: string;
871
+ readonly style?: KaafilTokenOverrides;
872
+ }
873
+
874
+ declare function TripSuppliersSection({ tripRef, style }: TripSuppliersSectionProps): ReactNode;
875
+
876
+ /** A vehicle that is not a tombstone. */
877
+ type SeatingVehicleLiveRow = Exclude<SeatingVehicleDeltaRow, {
878
+ readonly _tombstone: true;
879
+ }>;
880
+ type SeatingSeat = SeatingVehicleLiveRow['seats'][number];
881
+ type VehicleType = SeatingVehicleLiveRow['type'];
882
+ type VehicleLayout = SeatingVehicleLiveRow['layout'];
883
+
884
+ /** One rendered row of a seat grid: the seats at one `rowIndex`, in `side`
885
+ * order, with the aisle position the layout implies. */
886
+ interface SeatRow {
887
+ readonly rowIndex: number;
888
+ readonly seats: readonly SeatingSeat[];
889
+ /** How many seats sit before the aisle. `0` means no aisle in this row —
890
+ * a bench seat spanning it, or a `FLAT` layout. */
891
+ readonly aisleAfter: number;
892
+ }
893
+ interface TripVehiclesSectionProps {
894
+ readonly tripRef: string;
895
+ /**
896
+ * The trip's day count, so `days[]` indexes can be named ("days 2–3") and
897
+ * the day picker can offer the days that exist. A prop rather than a second
898
+ * read: `TripWorkspace` already holds the trip.
899
+ */
900
+ readonly durationDays: number;
901
+ readonly style?: KaafilTokenOverrides;
902
+ }
903
+
904
+ declare function TripVehiclesSection({ tripRef, durationDays, style, }: TripVehiclesSectionProps): ReactNode;
905
+
906
+ /** Every panel this surface can show. Ordered by `TAB_ORDER` in
907
+ * `internal/tripTabRegistry.tsx`, never by this union's declaration order. */
908
+ type TripTabKey = 'overview' | 'manifest' | 'itinerary' | 'pickups' | 'rooming' | 'vehicles' | 'vendors' | 'payments' | 'expenses' | 'float' | 'checklist' | 'bookings' | 'forms' | 'feedback' | 'documents' | 'treks';
909
+ /** Why a tab is not showing a real panel. Drives the placeholder's copy, so
910
+ * the operator is told the truth rather than a generic "coming soon". */
911
+ type TripTabBlocker =
912
+ /** The module is deferred to a later pass. The API is reachable. */
913
+ 'deferred'
914
+ /** No admin-reachable endpoint exists — the read is manager-only. */
915
+ | 'managerOnly'
916
+ /** The server resolved this capability as unavailable for this trip. */
917
+ | 'capabilityDark';
918
+ interface TripWorkspaceProps {
919
+ /** Kaafil's id for the trip, or the agency's own external id — either
920
+ * resolves (`trip-directory.validation.ts`'s `tripRef` param). */
921
+ readonly tripRef: string;
922
+ /** Which tab to open on mount. An unknown or now-dark key falls back to
923
+ * `overview` rather than rendering an empty rail. */
924
+ readonly initialTab?: TripTabKey;
925
+ /** Navigation is a callback, never a route — the UIKit ships no router
926
+ * (hard rule #9). */
927
+ readonly onBack?: () => void;
928
+ /**
929
+ * Forwarded to the People-going tab, whose row kebab offers "Open full
930
+ * profile". That profile is the agency-wide `TravellerProfileSection`, a
931
+ * different screen from this tab's own trip-scoped detail dialog — so it
932
+ * belongs to whichever surface owns the travellers pane, not to this one.
933
+ * Absent means the affordance is not offered.
934
+ */
935
+ readonly onOpenTravellerProfile?: (travellerId: string, fullName: string) => void;
936
+ /** Host panel overrides, merged over the registry. A host that has built
937
+ * its own Rooming panel can drop it in without forking this composite. */
938
+ readonly panels?: Partial<Record<TripTabKey, ReactNode>>;
939
+ readonly components?: {
940
+ readonly TripWorkspaceHead?: ComponentType<TripWorkspaceHeadProps>;
941
+ };
942
+ readonly style?: KaafilTokenOverrides;
943
+ }
944
+ interface TripWorkspaceHeadProps {
945
+ readonly trip: AgencyTripRead;
946
+ readonly onBack?: () => void;
947
+ readonly style?: KaafilTokenOverrides;
948
+ }
949
+ interface TripKpiCell {
950
+ readonly key: string;
951
+ readonly labelKey: string;
952
+ readonly value: string;
953
+ /** Absent when the underlying number is genuinely absent rather than zero
954
+ * — the cell then renders a worded dash, never a fabricated `0`. */
955
+ readonly subLabel?: string;
956
+ readonly tone?: 'pos' | 'warn' | 'mute';
957
+ }
958
+
959
+ declare function TripWorkspace({ tripRef, initialTab, onBack, onOpenTravellerProfile, panels, components, style, }: TripWorkspaceProps): ReactNode;
960
+
961
+ /** A registry key (hard rule #8), never an inline SVG passed per-item —
962
+ * `AdminShell` owns its own icon set, matching `ManagerShell`'s own fixed
963
+ * icon registry; a host wanting a different glyph for one of these seven
964
+ * uses `components.NavIcon`. Extended this wave (`forms`/`templates`/
965
+ * `journey` added) to cover every real `KaafilAgencyWorkspace` pane —
966
+ * extending this union is not a breaking change since it is additive. */
967
+ type AdminShellNavIconKey = 'trips' | 'traveller' | 'manager' | 'settings' | 'forms' | 'templates' | 'journey';
968
+ interface AdminShellNavItem {
969
+ readonly key: string;
970
+ readonly label: string;
971
+ readonly icon: AdminShellNavIconKey;
972
+ /** Already-resolved group heading text (never a translation key —
973
+ * `AdminShell` itself reads no i18n context, same as `label`) — items
974
+ * sharing the same `group` string render together under one eyebrow
975
+ * header, in the order groups first appear in `items`. Omit on every
976
+ * item to render one flat, ungrouped list (fully backward compatible);
977
+ * mixing grouped and ungrouped items renders the ungrouped ones with no
978
+ * header, in their own relative position. */
979
+ readonly group?: string;
980
+ /** Real count only — never a guessed or placeholder number. Omit to
981
+ * render no badge at all. */
982
+ readonly badge?: number;
983
+ /** `'warn'` gets the warn-token treatment (e.g. an overdue/blocked
984
+ * count) — omit for the default neutral pill. */
985
+ readonly badgeVariant?: 'default' | 'warn';
986
+ /** Renders this item visibly inert — muted, `aria-disabled`, never fires
987
+ * `onSelectItem` — for a real, spec'd destination whose composite doesn't
988
+ * exist yet (`KaafilAgencyWorkspace`'s own progressive-linking posture:
989
+ * the item is present from day one, wired for real the moment its
990
+ * composite ships, never removed and re-added). Omit for a live item. */
991
+ readonly disabled?: boolean;
992
+ }
993
+ interface AdminShellBreadcrumbEntry {
994
+ readonly label: string;
995
+ /** Optional even on the last (current-page) crumb — `AdminShell` itself
996
+ * decides the last entry is never interactive and always carries
997
+ * `aria-current="page"`, ignoring any `onSelect` supplied on it, so a
998
+ * caller that (accidentally, or out of habit) supplies one on every
999
+ * entry can never make the current page read as a clickable link. */
1000
+ readonly onSelect?: () => void;
1001
+ }
1002
+ interface AdminShellHeaderConfig {
1003
+ /** Small uppercase label above `title` (e.g. "AUTOMATION", "AGENCY") —
1004
+ * omit along with `title` for the "content owns its own page head" case;
1005
+ * never shown with a `breadcrumb`-only header. */
1006
+ readonly eyebrow?: string;
1007
+ /** Omit when the mounted content already owns its own page head (e.g.
1008
+ * `TravellerProfileSection`'s own hero renders the avatar/name) — showing
1009
+ * `AdminShell`'s own `<h1>` above it would just duplicate that name.
1010
+ * `breadcrumb` still renders without a `title`. */
1011
+ readonly title?: string;
1012
+ /** Optional supporting copy directly under `title`, tightly paired with
1013
+ * it (its own small top margin, `title`'s own bottom margin shrinks to
1014
+ * match) — never the larger title-to-content gap a title-only page uses.
1015
+ * A composite mounted below (e.g. `TravellerDirectoryFlow`) should NOT
1016
+ * also render its own `title`/`subtitle` in this case — one page head per
1017
+ * screen, owned by whichever component is closest to the root; here,
1018
+ * `AdminShell` itself. */
1019
+ readonly subtitle?: string;
1020
+ readonly breadcrumb?: readonly AdminShellBreadcrumbEntry[];
1021
+ /** Collapses a longer trail to `first … lastN` (a non-interactive
1022
+ * ellipsis marker, never a caller-supplied entry) once `breadcrumb.length`
1023
+ * exceeds this — mirrors the real `maxItems` prop on this package's own
1024
+ * `Breadcrumb` primitive spec (`atomic/11-navigation.md`). Defaults to 4. */
1025
+ readonly breadcrumbMaxItems?: number;
1026
+ /** The page-level primary action (e.g. "New template", "Add traveller")
1027
+ * — rendered beside `title`, never duplicated inside the mounted
1028
+ * content's own card header. Verified against the mockup's own generic
1029
+ * page-header pattern: every pane's fixture carries a `cta` field
1030
+ * alongside `title`/`eyebrow`/`sub`, rendered in the SAME flex row as the
1031
+ * heading, not inside whatever card sits below it. */
1032
+ readonly primaryCta?: {
1033
+ readonly label: string;
1034
+ readonly onClick: () => void;
1035
+ };
1036
+ }
1037
+ interface AdminShellBrand {
1038
+ readonly name: string;
1039
+ /** The host CRM's own brand mark — this package never renders a
1040
+ * Kaafil-branded default here, matching `BrandShell`'s "host controls
1041
+ * branding" posture elsewhere in this package. */
1042
+ readonly logo?: ReactNode;
1043
+ }
1044
+ interface AdminShellUser {
1045
+ readonly name: string;
1046
+ readonly roleLabel?: string;
1047
+ /** 2-letter avatar initials — omit renders a person-less initial block
1048
+ * derived from `name`, never a "?" (same reasoning `ManagerShell`'s own
1049
+ * header documents for its avatar). */
1050
+ readonly avatarInitials?: string;
1051
+ /** Renders a sign-out affordance only when supplied — prop-presence
1052
+ * gates the button, same convention `ManagerMeSection`/`KaafilManagerApp`
1053
+ * already establish. */
1054
+ readonly onSignOut?: () => void;
1055
+ }
1056
+ interface AdminShellProps {
1057
+ readonly header: AdminShellHeaderConfig;
1058
+ /** Caller-supplied, never hardcoded (hard rule #9's own "host owns
1059
+ * navigation" extended to what destinations even exist) — this wave's
1060
+ * real value is the 4-item Trips/Traveller/Manager/Settings set, but
1061
+ * `AdminShell` itself has no opinion on that list's contents. */
1062
+ readonly items: readonly AdminShellNavItem[];
1063
+ readonly activeItemKey: string;
1064
+ readonly onSelectItem: (key: string) => void;
1065
+ readonly brand?: AdminShellBrand;
1066
+ readonly user?: AdminShellUser;
1067
+ /** The content region — `AdminShell` renders chrome only, exactly as
1068
+ * `ManagerShell` does for its own `main` region. */
1069
+ readonly children?: ReactNode;
1070
+ readonly components?: {
1071
+ readonly NavIcon?: ComponentType<{
1072
+ readonly iconKey: AdminShellNavIconKey;
1073
+ }>;
1074
+ };
1075
+ readonly style?: KaafilTokenOverrides;
1076
+ }
1077
+
1078
+ /** The spec's own `initialPane` union (`01-surface.md`), plus `settings` —
1079
+ * see this file's header for why. */
1080
+ type KaafilAgencyWorkspacePaneKey = 'trips' | 'managers' | 'travellers' | 'forms' | 'templates' | 'journey' | 'settings';
1081
+ interface KaafilAgencyWorkspaceProps {
1082
+ /** Seeds which pane is selected on first mount. Ignored once `selectedPane`
1083
+ * (below) is supplied. Defaults to `'trips'`, per spec. */
1084
+ readonly initialPane?: KaafilAgencyWorkspacePaneKey;
1085
+ /** Fully controls which pane is selected — omit to let this component own
1086
+ * its own selection state. `onPaneChange` still fires so the host can
1087
+ * react. */
1088
+ readonly selectedPane?: KaafilAgencyWorkspacePaneKey;
1089
+ /**
1090
+ * Fired alongside the internal trip-workspace push opening — the same
1091
+ * analytics/URL-sync mirror every other `onOpen*` below is, paired with
1092
+ * `onCloseTrip`.
1093
+ *
1094
+ * ITS MEANING CHANGED, AND DELIBERATELY KEEPS ITS SPEC'D NAME. It used to
1095
+ * be the ONLY way a trip opened: this Surface had no trip detail of its
1096
+ * own, so the spec had the host respond by "navigating to its own
1097
+ * `KaafilTripWorkspace`-mounting route". This Surface now mounts
1098
+ * `TripWorkspace` itself, so opening a trip no longer depends on the host
1099
+ * doing anything — a host that ignores this callback still gets a working
1100
+ * drill-down. Kept under the spec's own name rather than joined by a
1101
+ * second `onOpenTrip` prop meaning the identical thing: two doors to one
1102
+ * event is exactly the duplication the rest of this Surface avoids.
1103
+ *
1104
+ * The second argument is new. Existing handlers that take only `tripRef`
1105
+ * keep working unchanged.
1106
+ */
1107
+ readonly onSelectTrip?: (tripRef: string, name: string) => void;
1108
+ /** Fired alongside the internal trip-workspace push closing — the mirror
1109
+ * of `onSelectTrip`, matching every other pane's own pair. */
1110
+ readonly onCloseTrip?: () => void;
1111
+ /** Fires whenever the active pane changes — per spec, T2. */
1112
+ readonly onPaneChange?: (pane: KaafilAgencyWorkspacePaneKey) => void;
1113
+ /** Fired alongside the internal traveller-profile push opening/closing —
1114
+ * an analytics/URL-sync hook, never the only way this navigation happens
1115
+ * (the real trigger is always a row tap inside `TravellerDirectoryFlow`).
1116
+ * `KaafilManagerApp`'s own exact `onOpenTraveller`/`onCloseTraveller`
1117
+ * precedent. */
1118
+ readonly onOpenTraveller?: (travellerId: string, fullName: string) => void;
1119
+ readonly onCloseTraveller?: () => void;
1120
+ /** Fired alongside the internal manager-profile push opening/closing — the
1121
+ * identical `onOpenTraveller`/`onCloseTraveller` shape, for the Managers
1122
+ * pane's own directory → profile journey. */
1123
+ readonly onOpenManager?: (managerId: string, fullName: string) => void;
1124
+ readonly onCloseManager?: () => void;
1125
+ /** Fired alongside the internal template-editor push opening/closing — the
1126
+ * identical `onOpenTraveller`/`onCloseTraveller` shape, for the Checklist
1127
+ * templates pane's own library → editor journey. */
1128
+ readonly onOpenTemplate?: (templateId: string, title: string) => void;
1129
+ readonly onCloseTemplate?: () => void;
1130
+ /** Fired alongside the internal form-builder push opening/closing — the
1131
+ * identical `onOpenTraveller`/`onCloseTraveller` shape, for the Forms
1132
+ * pane's own library → builder journey. */
1133
+ readonly onOpenForm?: (formId: string, title: string) => void;
1134
+ readonly onCloseForm?: () => void;
1135
+ /** Renders "Sign out" on `AdminShell`'s own user footer only when
1136
+ * supplied (prop-presence gates the affordance, same convention
1137
+ * `KaafilManagerApp`/`ManagerMeSection` already establish) — this Surface
1138
+ * has no credential/session-teardown method of its own to call first. */
1139
+ readonly onSignOut?: () => void;
1140
+ readonly components?: {
1141
+ /** Maps onto `AdminShell`'s own existing `components.NavIcon` slot — the
1142
+ * only real nav-chrome customization point that exists today. Narrower
1143
+ * than the spec's "TabBar" name implies, the identical mapping
1144
+ * `KaafilManagerApp.types.ts` already documents for its own
1145
+ * `TabBar`→`ManagerShell.components.TabIcon`. */
1146
+ readonly TabBar?: ComponentType<{
1147
+ readonly iconKey: AdminShellNavIconKey;
1148
+ }>;
1149
+ };
1150
+ readonly style?: KaafilTokenOverrides;
1151
+ }
1152
+
1153
+ declare function KaafilAgencyWorkspace(props: KaafilAgencyWorkspaceProps): ReactNode;
1154
+
1155
+ declare function AdminShell({ header, items, activeItemKey, onSelectItem, brand, user, children, components, style, }: AdminShellProps): ReactNode;
1156
+
1157
+ export { AdminShell, type AdminShellBrand, type AdminShellBreadcrumbEntry, type AdminShellHeaderConfig, type AdminShellNavIconKey, type AdminShellNavItem, type AdminShellProps, type AdminShellUser, AgencySettingsScreen, type AgencySettingsScreenProps, type BookingKind, type BookingLiveRow, type BuilderHeaderProps, type ChecklistGate, type ChecklistPhase, ChecklistTemplateEditor, type ChecklistTemplateEditorProps, type ChecklistTemplateItemDraft, ChecklistTemplateLibrary, type ChecklistTemplateLibraryProps, ChecklistTemplateRow, type CollectionLiveRow, type CollectionMode, type DocumentRowModel, type DocumentSpend, type EligibleStatus, type ExpenseCategory, type ExpenseClaimStatus, type ExpenseFilters, type ExpenseLiveRow, type ExpensePaymentMode, type FieldDef, type FieldRowProps, type FloatAction, type FloatDirection, FloatMovementRow, type FloatMovementType, FormBuilder, type FormBuilderProps, FormDetailRow, FormFieldRow, type FormParticipantRow, FormRow, type FormRowProps$1 as FormRowProps, FormsAuthoringFlow, type FormsAuthoringFlowProps, FormsLibrary, type FormsLibraryProps, type ItineraryDayGroup, type ItineraryViewMode, JourneyTriggerRow, KaafilAgencyWorkspace, type KaafilAgencyWorkspacePaneKey, type KaafilAgencyWorkspaceProps, type ManagerAgencyProfileTripRow, ManagerDirectoryFlow, type ManagerDirectoryFlowProps, ManagerListRowResponse, ManagerProfileSection, type ManagerProfileSectionProps, type ManagerResultRowProps, type ManifestFilterState, type ManifestGroupBy, type ManifestRowProps, type PickupKind, type PickupRollup, type PickupStopLiveRow, type PickupView, type PlanLockedReason, PlanLockedScreen, type PlanLockedScreenProps, type RoomingBed, type RoomingOccupant, type RoomingRoomLiveRow, type RoomingWindowGroup, type SeatRow, type SeatingSeat, type SeatingVehicleLiveRow, type SectionCardProps, type SectionDef, type StayWindowRow, type SupplierSortKey, type SupplierUsage, TemplateAuthoringFlow, type TemplateAuthoringFlowProps, type TemplateRowProps, type TravellerAgencyProfileLifetime, type TravellerAgencyProfileNoteRow, type TravellerAgencyProfileTripRow, TravellerDirectoryFlow, type TravellerDirectoryFlowProps, TravellerDirectoryItemResponse, TravellerProfileSection, type TravellerProfileSectionProps, TravellerSearchBox, type TravellerSearchBoxProps, type TriggerDetailPanelProps, TriggerTemplateEditor, type TriggerTemplateEditorProps, TripBookingsSection, type TripBookingsSectionProps, TripChecklistSection, type TripChecklistSectionProps, TripDirectoryFlow, type TripDirectoryFlowProps, AgencyTripRow as TripDirectoryRow, type TripRowProps as TripDirectoryRowProps, TripDocumentsSection, type TripDocumentsSectionProps, TripExpensesSection, type TripExpensesSectionProps, TripFloatSection, type TripFloatSectionProps, TripFormsSection, type TripFormsSectionProps, TripItinerarySection, type TripItinerarySectionProps, type TripKpiCell, TripManifestRow, TripManifestSection, type TripManifestSectionProps, TripPaymentsSection, type TripPaymentsSectionProps, TripPickupsSection, type TripPickupsSectionProps, TripRoomingSection, type TripRoomingSectionProps, TripSuppliersSection, type TripSuppliersSectionProps, type TripTabBlocker, type TripTabKey, TripVehiclesSection, type TripVehiclesSectionProps, TripVendorRow, TripWorkspace, type TripWorkspaceHeadProps, type TripWorkspaceProps, AgencyTripRead as TripWorkspaceTrip, type UsageSources, type VehicleLayout, type VehicleType, type VendorCategory };