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.
- package/CHANGELOG.md +70 -0
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/OfflineFallbackScreen-B5dfaJBN.d.ts +37 -0
- package/dist/OfflineFallbackScreen-Ctm7nBa-.d.cts +37 -0
- package/dist/SessionExpiredScreen-CytQNuak.d.cts +50 -0
- package/dist/SessionExpiredScreen-D8GHyZc3.d.ts +50 -0
- package/dist/admin/index.cjs +23779 -0
- package/dist/admin/index.cjs.map +1 -0
- package/dist/admin/index.d.cts +1157 -0
- package/dist/admin/index.d.ts +1157 -0
- package/dist/admin/index.js +23724 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/chunk-6FPAGGFL.js +6028 -0
- package/dist/chunk-6FPAGGFL.js.map +1 -0
- package/dist/chunk-ACVU55PZ.cjs +294 -0
- package/dist/chunk-ACVU55PZ.cjs.map +1 -0
- package/dist/chunk-EM7JV3D7.cjs +6051 -0
- package/dist/chunk-EM7JV3D7.cjs.map +1 -0
- package/dist/chunk-IIPQ4JNC.js +287 -0
- package/dist/chunk-IIPQ4JNC.js.map +1 -0
- package/dist/chunk-LL243STJ.cjs +2195 -0
- package/dist/chunk-LL243STJ.cjs.map +1 -0
- package/dist/chunk-PJRZCOFF.cjs +958 -0
- package/dist/chunk-PJRZCOFF.cjs.map +1 -0
- package/dist/chunk-PTQ2CJKE.cjs +40 -0
- package/dist/chunk-PTQ2CJKE.cjs.map +1 -0
- package/dist/chunk-PZKXLQSU.js +10 -0
- package/dist/chunk-PZKXLQSU.js.map +1 -0
- package/dist/chunk-QHUDOVKW.cjs +111 -0
- package/dist/chunk-QHUDOVKW.cjs.map +1 -0
- package/dist/chunk-TOBZFADB.cjs +12 -0
- package/dist/chunk-TOBZFADB.cjs.map +1 -0
- package/dist/chunk-UUGMNP27.js +936 -0
- package/dist/chunk-UUGMNP27.js.map +1 -0
- package/dist/chunk-UYJ6LIWP.js +2154 -0
- package/dist/chunk-UYJ6LIWP.js.map +1 -0
- package/dist/chunk-VHTSTUCJ.cjs +346 -0
- package/dist/chunk-VHTSTUCJ.cjs.map +1 -0
- package/dist/chunk-WUAFL77X.js +340 -0
- package/dist/chunk-WUAFL77X.js.map +1 -0
- package/dist/chunk-XI7MK4Y7.js +38 -0
- package/dist/chunk-XI7MK4Y7.js.map +1 -0
- package/dist/chunk-YDGR7JSY.js +107 -0
- package/dist/chunk-YDGR7JSY.js.map +1 -0
- package/dist/core/index.cjs +1254 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +1267 -0
- package/dist/core/index.d.ts +1267 -0
- package/dist/core/index.js +995 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.css +1 -0
- package/dist/manager/index.cjs +13562 -0
- package/dist/manager/index.cjs.map +1 -0
- package/dist/manager/index.d.cts +1054 -0
- package/dist/manager/index.d.ts +1054 -0
- package/dist/manager/index.js +13518 -0
- package/dist/manager/index.js.map +1 -0
- package/dist/testing/index.cjs +221 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +269 -0
- package/dist/testing/index.d.ts +269 -0
- package/dist/testing/index.js +208 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/tokenStyle-CToG5oOS.d.cts +3 -0
- package/dist/tokenStyle-CToG5oOS.d.ts +3 -0
- package/dist/traveller/index.cjs +1799 -0
- package/dist/traveller/index.cjs.map +1 -0
- package/dist/traveller/index.d.cts +58 -0
- package/dist/traveller/index.d.ts +58 -0
- package/dist/traveller/index.js +1789 -0
- package/dist/traveller/index.js.map +1 -0
- package/dist/useAgencyTrip-BUYSIaC2.d.cts +454 -0
- package/dist/useAgencyTrip-BzyJB1D9.d.ts +454 -0
- package/dist/useNotifications-BZW1Z_ur.d.cts +356 -0
- package/dist/useNotifications-D262i5BQ.d.ts +356 -0
- package/dist/useVendors-DXOuZWhZ.d.cts +784 -0
- package/dist/useVendors-DXOuZWhZ.d.ts +784 -0
- package/package.json +95 -0
|
@@ -0,0 +1,1267 @@
|
|
|
1
|
+
import { D as DomainHookResult, g as CapabilityTriple, h as ErrorClassification } from '../useVendors-DXOuZWhZ.js';
|
|
2
|
+
export { i as CapabilityRow, a as ChecklistsReady, j as DarkReason, k as ERROR_HANDLING_PATH, l as ErrorHandlingPath, m as ExpensesReady, n as FilesContext, o as FilesReady, p as FloatReady, q as FormsReady, r as ItineraryReady, s as RoomingReady, t as RoomingUnassignedPool, V as VendorsReady, u as classifyError, v as useChecklists, w as useExpenses, x as useFiles, y as useFloat, z as useForms, A as useItinerary, B as useRooming, G as useVendors } from '../useVendors-DXOuZWhZ.js';
|
|
3
|
+
import { ManagerAgencyProfileResponse, BookingListRow, AgencyAdminMeResponse, OfflineEngine, OutboxOp, KaafilClient, FeedbackNpsResource, DispatchFormOptions, JourneyResource, BoundJourneyResource, TripManagersResource, OfflineEventName, OfflineEventMap, ShareTokensResource, FormsResource, TravellersResource, TreksResource, CreateTrekWalkInOptions, PostponeTrekOptions, Environment, KaafilStorageAdapter, BlobUploader, BlobSource, ConflictResolver, EntityReader } from 'kaafil-js/client';
|
|
4
|
+
export { AgencyTripFilters, AgencyTripSegmentCounts, ManagerAgencyProfileResponse, TripManifestFacets, TripManifestFilters, UnsatisfiableSchemeError } from 'kaafil-js/client';
|
|
5
|
+
export { i as AgencyChecklistTemplatesReady, j as AgencyFormsReady, k as AgencyJourneyTriggersReady, g as AgencySettingsDocument, l as AgencySettingsReady, m as AgencyTripManifestResult, f as AgencyTripRead, n as AgencyTripResult, A as AgencyTripRow, o as AgencyTripsResult, B as BindingRow, a as ChecklistTemplateItemRow, C as ChecklistTemplateRow, p as CloneFormInput, q as CollectionsReady, r as CreateFormFieldInput, s as CreateFormInput, t as CreateFormSectionInput, D as DeleteFormFieldInput, u as DeleteFormInput, v as DeleteFormSectionInput, w as DirectoriesReady, F as FormDetailRow, b as FormFieldRow, c as FormRow, h as FormSectionRow, x as FormSummaryRow, J as JourneyTriggerRow, P as PaginatedListFetch, y as PaginatedListFetchResult, z as PaginatedListOptions, E as PaginatedListResult, G as PatchAgencySettingsInput, H as PatchFormFieldInput, I as PatchFormInput, K as PatchFormSectionInput, L as PatchJourneyTriggerInput, R as ReorderFormInput, d as TripManifestRow, N as useAgencyChecklistTemplates, O as useAgencyForms, Q as useAgencyJourneyTriggers, S as useAgencySettings, U as useAgencyTrip, V as useAgencyTripManifest, W as useAgencyTrips, X as useCollections, Y as useDirectories, Z as useKaafilClient, _ as usePaginatedList } from '../useAgencyTrip-BzyJB1D9.js';
|
|
6
|
+
import { C as ConflictRecord, S as StalenessState } from '../useNotifications-D262i5BQ.js';
|
|
7
|
+
export { a as CloseoutReady, M as ManagerMeReady, b as ManagerMeResult, c as ManagerNotification, d as ManagerTodayReady, e as ManagerTodayResult, N as NotificationsReady, f as NotificationsResult, O as OutboxState, P as PartiesReady, g as PickupsReady, h as SeatingReady, i as SyncEventKind, u as useCloseout, j as useManagerMe, k as useManagerToday, l as useNotifications, m as useParties, n as usePickups, o as useSeating } from '../useNotifications-D262i5BQ.js';
|
|
8
|
+
import { ReactNode, Component } from 'react';
|
|
9
|
+
import { K as KaafilTokenOverrides } from '../tokenStyle-CToG5oOS.js';
|
|
10
|
+
|
|
11
|
+
type ManagerAgencyProfileRead = ManagerAgencyProfileResponse;
|
|
12
|
+
interface AgencyManagerProfileResult {
|
|
13
|
+
readonly read: ManagerAgencyProfileRead | undefined;
|
|
14
|
+
readonly readFailed: boolean;
|
|
15
|
+
readonly refresh: () => Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
declare function useAgencyManagerProfile(managerRef: string): AgencyManagerProfileResult;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The FULL replacement set for one booking's vouchers.
|
|
21
|
+
*
|
|
22
|
+
* `voucherFileKeys` REPLACES the stored array wholesale (`bookings FRD` R6) —
|
|
23
|
+
* there is no add-one call. A caller that sends only its new key detaches
|
|
24
|
+
* every voucher the CRM already attached, so a UI must read the booking's
|
|
25
|
+
* current list and send it back plus the addition. Named `…FileKeys` rather
|
|
26
|
+
* than `…FileIds` because that is the wire field; the values are file ids.
|
|
27
|
+
*/
|
|
28
|
+
interface ReplaceBookingVouchersInput {
|
|
29
|
+
readonly bookingRef: string;
|
|
30
|
+
readonly voucherFileKeys: readonly string[];
|
|
31
|
+
}
|
|
32
|
+
interface BookingsReady {
|
|
33
|
+
readonly bookings: readonly BookingListRow[];
|
|
34
|
+
readonly syncedAt: string | undefined;
|
|
35
|
+
/** Re-read the live list — used after a voucher write so the booking's own
|
|
36
|
+
* `voucherFileKeys` stops being stale. */
|
|
37
|
+
readonly refreshLive: () => Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* `PATCH /trips/{ref}/bookings/{bookingRef}/vouchers`. The ONE write this
|
|
40
|
+
* hook has, and the only booking field a browser may change.
|
|
41
|
+
*
|
|
42
|
+
* `ReplaceBookingVouchersOptions` declares NO `idempotencyKey`, so nothing
|
|
43
|
+
* here mints or accepts one (hard rule #4) and the desk lane is legal.
|
|
44
|
+
*/
|
|
45
|
+
readonly replaceVouchers: (input: ReplaceBookingVouchersInput) => Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
declare function useBookings(tripRef: string): DomainHookResult<BookingsReady>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Thrown by a §3 domain hook that has no implementation yet in this build.
|
|
51
|
+
*
|
|
52
|
+
* Deliberately NOT the same class as `kaafil-js`'s own `KaafilNotImplementedError`
|
|
53
|
+
* (re-exported by `./classify.ts`'s callers via `kaafil-js/client` where
|
|
54
|
+
* needed) — that one models the wire's `501 NOT_IMPLEMENTED` catalog code (a
|
|
55
|
+
* reserved server route, `architecture/10-conventions.md §7`), a fact about
|
|
56
|
+
* the API. This one is a fact about THIS PACKAGE's own build: the hook
|
|
57
|
+
* exists, type-checks, and is importable, but its body has not been
|
|
58
|
+
* authored yet. Naming it differently keeps a composite's `catch` block from
|
|
59
|
+
* ever conflating "the server hasn't shipped this route" with "the UIKit
|
|
60
|
+
* hasn't shipped this hook" — the two need different user-facing copy and
|
|
61
|
+
* the two need different fixes.
|
|
62
|
+
*/
|
|
63
|
+
declare class NotImplementedError extends Error {
|
|
64
|
+
readonly hookName: string;
|
|
65
|
+
readonly specSection: string;
|
|
66
|
+
constructor(hookName: string, specSection: string);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface AgencyAdminMeLoading {
|
|
70
|
+
readonly status: 'loading';
|
|
71
|
+
}
|
|
72
|
+
interface AgencyAdminMeError {
|
|
73
|
+
readonly status: 'error';
|
|
74
|
+
}
|
|
75
|
+
interface AgencyAdminMeReady {
|
|
76
|
+
readonly status: 'ready';
|
|
77
|
+
readonly agencyAdmin: AgencyAdminMeResponse['agencyAdmin'];
|
|
78
|
+
}
|
|
79
|
+
type AgencyAdminMeResult = AgencyAdminMeLoading | AgencyAdminMeError | AgencyAdminMeReady;
|
|
80
|
+
/**
|
|
81
|
+
* `client.agencyAdminMe.read()` behind a plain fetch-on-mount effect — this
|
|
82
|
+
* read takes no parameter (it resolves entirely off the authenticated
|
|
83
|
+
* principal, `agency-admin-me.routes.ts`'s own header, cited), so it never
|
|
84
|
+
* re-fetches on a prop change. A caller wanting "refresh now" re-mounts this
|
|
85
|
+
* hook's owning component.
|
|
86
|
+
*/
|
|
87
|
+
declare function useAgencyAdminMe(): AgencyAdminMeResult;
|
|
88
|
+
|
|
89
|
+
interface BlobStatusResult {
|
|
90
|
+
readonly status: 'pending' | 'uploading' | 'ready' | 'orphaned' | 'purged';
|
|
91
|
+
readonly progress: number | undefined;
|
|
92
|
+
}
|
|
93
|
+
declare function useBlobStatus(blobId: string): BlobStatusResult;
|
|
94
|
+
|
|
95
|
+
/** `08-core-hooks.md §1.4`. Persona restriction: unavailable to `share`. */
|
|
96
|
+
declare function useCapability(key: string): CapabilityTriple;
|
|
97
|
+
/** `08-core-hooks.md §1.4`. Omitting `keys` returns every key the last read
|
|
98
|
+
* carried. Persona restriction: unavailable to `share`. */
|
|
99
|
+
declare function useCapabilities(keys?: readonly string[]): ReadonlyMap<string, CapabilityTriple>;
|
|
100
|
+
|
|
101
|
+
interface CapabilityStatusesResult {
|
|
102
|
+
/** Capability key → the derived status, for every key the last read
|
|
103
|
+
* carried. A key that is ABSENT from this map is absent from the read —
|
|
104
|
+
* callers apply their own open-set fallback (`06 §6` point 5), which this
|
|
105
|
+
* hook deliberately does not choose for them. */
|
|
106
|
+
readonly statuses: ReadonlyMap<string, CapabilityTriple['status']>;
|
|
107
|
+
/** `false` until the first `journey.capabilities()` response for this trip
|
|
108
|
+
* has landed. A `share` session is immediately `true` with an empty map
|
|
109
|
+
* (`06 §9` — no `share.*` operation exposes this read). */
|
|
110
|
+
readonly loaded: boolean;
|
|
111
|
+
}
|
|
112
|
+
declare function useCapabilityStatuses(tripRef: string): CapabilityStatusesResult;
|
|
113
|
+
|
|
114
|
+
interface ConflictsResult {
|
|
115
|
+
readonly conflicts: readonly ConflictRecord[];
|
|
116
|
+
readonly resolve: (opId: string, choice: 'keep-queued' | 'keep-current') => Promise<void>;
|
|
117
|
+
}
|
|
118
|
+
declare function useConflicts(tripRef: string): ConflictsResult;
|
|
119
|
+
|
|
120
|
+
type OfflineMutationStatus = 'idle' | 'queued' | 'syncing' | 'synced' | 'conflicted' | 'parked';
|
|
121
|
+
interface OfflineMutationConfig<TOptions> {
|
|
122
|
+
readonly tripRef: string;
|
|
123
|
+
readonly enqueue: (engine: OfflineEngine, options: TOptions) => Promise<OutboxOp>;
|
|
124
|
+
/**
|
|
125
|
+
* The same write, awaited straight against the SDK, for a surface with no
|
|
126
|
+
* `OfflineShell` — see this file's header. Omit it and `mutate` keeps its
|
|
127
|
+
* original throw on such a surface, which is right for a domain that only
|
|
128
|
+
* a field persona ever writes.
|
|
129
|
+
*
|
|
130
|
+
* Its resolved value is deliberately unused: the caller re-reads after the
|
|
131
|
+
* write (every domain hook here already does), so a returned row would be a
|
|
132
|
+
* second, staler copy of what the refresh is about to fetch.
|
|
133
|
+
*/
|
|
134
|
+
readonly direct?: (client: KaafilClient, options: TOptions) => Promise<unknown>;
|
|
135
|
+
}
|
|
136
|
+
/** A config that HAS a direct lane — the overload below keys on this. */
|
|
137
|
+
interface OfflineMutationConfigWithDirect<TOptions> extends OfflineMutationConfig<TOptions> {
|
|
138
|
+
readonly direct: (client: KaafilClient, options: TOptions) => Promise<unknown>;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* `TQueued` is `OutboxOp` for a config with no direct lane and
|
|
142
|
+
* `OutboxOp | null` for one that has it. Parameterised rather than widened
|
|
143
|
+
* unconditionally: a hook that supplies no `direct` can never take the direct
|
|
144
|
+
* branch, so telling its callers the result might be `null` would be a lie
|
|
145
|
+
* that every one of the fourteen existing domain hooks would have to absorb
|
|
146
|
+
* into its own published `Ready` interface.
|
|
147
|
+
*/
|
|
148
|
+
interface OfflineMutationResult<TOptions, TQueued = OutboxOp> {
|
|
149
|
+
/** `null` on the direct lane — committed, with no outbox row to track. */
|
|
150
|
+
readonly mutate: (options: TOptions) => Promise<TQueued>;
|
|
151
|
+
readonly status: OfflineMutationStatus;
|
|
152
|
+
readonly op: OutboxOp | undefined;
|
|
153
|
+
}
|
|
154
|
+
declare function useOfflineMutation<TOptions>(config: OfflineMutationConfigWithDirect<TOptions>): OfflineMutationResult<TOptions, OutboxOp | null>;
|
|
155
|
+
declare function useOfflineMutation<TOptions>(config: OfflineMutationConfig<TOptions>): OfflineMutationResult<TOptions, OutboxOp>;
|
|
156
|
+
|
|
157
|
+
type FeedbackNpsScope = {
|
|
158
|
+
readonly kind: 'trip';
|
|
159
|
+
readonly tripRef: string;
|
|
160
|
+
} | {
|
|
161
|
+
readonly kind: 'agency';
|
|
162
|
+
readonly agencyRef: string;
|
|
163
|
+
};
|
|
164
|
+
type TripFeedbackSummaryData = Awaited<ReturnType<FeedbackNpsResource['trip']>>['data'];
|
|
165
|
+
type AgencyFeedbackSummaryData = Awaited<ReturnType<FeedbackNpsResource['agency']>>['data'];
|
|
166
|
+
/** One row of the `agency` read's `definitions[]` — the agency-wide rollup
|
|
167
|
+
* `manager/06-feedback-nps.md` explicitly leaves to the admin family; kept
|
|
168
|
+
* here only so this one shared hook serves both scopes uniformly. */
|
|
169
|
+
type FeedbackNpsAgencyDefinitionRow = AgencyFeedbackSummaryData['definitions'][number];
|
|
170
|
+
type DispatchFeedbackChaseInput = Omit<DispatchFormOptions, 'tripRef' | 'formId' | 'idempotencyKey' | 'signal'>;
|
|
171
|
+
interface FeedbackNpsReady {
|
|
172
|
+
readonly kind: FeedbackNpsScope['kind'];
|
|
173
|
+
/** `trip` scope only — the discriminated union verbatim off the wire.
|
|
174
|
+
* `undefined` on `agency` scope, or before the first `trip` fetch has
|
|
175
|
+
* settled (`loaded` distinguishes the two). */
|
|
176
|
+
readonly summary: TripFeedbackSummaryData | undefined;
|
|
177
|
+
/** `agency` scope only — always `[]` on `trip` scope. */
|
|
178
|
+
readonly definitions: readonly FeedbackNpsAgencyDefinitionRow[];
|
|
179
|
+
/** `true` once the first read has settled (success or failure) —
|
|
180
|
+
* distinguishes "never fetched yet" from "fetched, and this trip
|
|
181
|
+
* genuinely has no feedback form configured" (`CloseoutReady.loaded`'s
|
|
182
|
+
* own contract, reused). */
|
|
183
|
+
readonly loaded: boolean;
|
|
184
|
+
/** `true` when the MOST RECENT fetch threw. `loaded`/`summary`/
|
|
185
|
+
* `definitions` stay whatever they already were. */
|
|
186
|
+
readonly lastFetchFailed: boolean;
|
|
187
|
+
readonly syncedAt: string | undefined;
|
|
188
|
+
readonly refresh: () => Promise<void>;
|
|
189
|
+
/** `trip` scope only. Throws if called before a `configured: true`
|
|
190
|
+
* summary has resolved a `formId` to target — a caller gates the
|
|
191
|
+
* dispatch control on `summary?.configured === true` first exactly as
|
|
192
|
+
* `manager/06-feedback-nps.md`'s own `FeedbackDispatchControls` does. */
|
|
193
|
+
readonly dispatch: (input?: DispatchFeedbackChaseInput) => Promise<OutboxOp>;
|
|
194
|
+
/** The dispatch op's OWN outbox lifecycle (`useOfflineMutation`'s own
|
|
195
|
+
* `status`) — `'parked'`/`'conflicted'` is how a `423`
|
|
196
|
+
* ("this trip has been closed out") or a `402` plan-lock surfaces, via
|
|
197
|
+
* `dispatchOp?.parkReason?.userMessage` (`06-feedback-nps.md`'s own
|
|
198
|
+
* `locked (423)`/`parked (402)` States rows). */
|
|
199
|
+
readonly dispatchStatus: OfflineMutationStatus;
|
|
200
|
+
readonly dispatchOp: OutboxOp | undefined;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Two scope members, different credential sets, one shared read/refresh
|
|
204
|
+
* shape — see this file's header for why there is no `createDomainHook()`
|
|
205
|
+
* gate. `manager`'s own `FeedbackNpsFlow` only ever calls this with
|
|
206
|
+
* `{ kind: 'trip', tripRef }`; the `agency` branch exists for the admin
|
|
207
|
+
* family's own agency-wide rollup, reusing this same hook rather than a
|
|
208
|
+
* second `useAgencyFeedbackNps()` (hard rule #2).
|
|
209
|
+
*/
|
|
210
|
+
declare function useFeedbackNps(scope: FeedbackNpsScope): FeedbackNpsReady;
|
|
211
|
+
|
|
212
|
+
type JourneyReadResponse = Awaited<ReturnType<JourneyResource['get']>>;
|
|
213
|
+
interface JourneyResult {
|
|
214
|
+
readonly read: JourneyReadResponse | undefined;
|
|
215
|
+
readonly capabilities: ReadonlyMap<string, CapabilityTriple>;
|
|
216
|
+
readonly refreshCapabilities: () => Promise<void>;
|
|
217
|
+
readonly triggers: {
|
|
218
|
+
list: BoundJourneyResource['triggers']['list'];
|
|
219
|
+
patch: BoundJourneyResource['triggers']['patch'];
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
declare function useJourney(tripRef: string): JourneyResult;
|
|
223
|
+
|
|
224
|
+
/** One row of `trips.managers.list`'s result — derived structurally off the
|
|
225
|
+
* resource's own return type (`useJourney.ts`'s identical precedent for
|
|
226
|
+
* `JourneyReadResponse`), so this can never drift from what the SDK
|
|
227
|
+
* actually returns. */
|
|
228
|
+
type TripManagerRow = Awaited<ReturnType<TripManagersResource['list']>>[number];
|
|
229
|
+
type ManagersResult = {
|
|
230
|
+
readonly status: 'loading';
|
|
231
|
+
} | {
|
|
232
|
+
readonly status: 'ready';
|
|
233
|
+
readonly managers: readonly TripManagerRow[];
|
|
234
|
+
} | {
|
|
235
|
+
readonly status: 'error';
|
|
236
|
+
readonly error: ErrorClassification;
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* A trip's manager roster — every live manager assigned to the trip,
|
|
240
|
+
* lead first (`trips.managers.list`'s own doc comment). `manager`/
|
|
241
|
+
* `agencyAdmin` only, matching `useJourney()`'s identical persona
|
|
242
|
+
* restriction and identical dev-only throw on misuse.
|
|
243
|
+
*/
|
|
244
|
+
declare function useManagers(tripRef: string): ManagersResult;
|
|
245
|
+
|
|
246
|
+
/** Returns the engine instance `OfflineShell` opened via
|
|
247
|
+
* `client.openOffline(options)`. Throws outside the provider tree. */
|
|
248
|
+
declare function useOfflineEngine(): OfflineEngine;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Subscribes `handler` to `name` for as long as the calling component is
|
|
252
|
+
* mounted. `session.expired`/`share.expired`/`share.revoked` firing for the
|
|
253
|
+
* "wrong" persona's session is inert, not an error (`08-core-hooks.md
|
|
254
|
+
* §2.6`'s persona-restriction note) — this hook does not filter by persona
|
|
255
|
+
* itself, since the engine only ever emits the events its own persona can
|
|
256
|
+
* produce.
|
|
257
|
+
*/
|
|
258
|
+
declare function useOfflineEvent<TName extends OfflineEventName>(name: TName, handler: (event: OfflineEventMap[TName]) => void): void;
|
|
259
|
+
|
|
260
|
+
interface OutboxStatusOptions {
|
|
261
|
+
readonly tripRef?: string;
|
|
262
|
+
}
|
|
263
|
+
interface OutboxStatusResult {
|
|
264
|
+
readonly pending: number;
|
|
265
|
+
readonly parked: number;
|
|
266
|
+
readonly lanes: readonly string[];
|
|
267
|
+
readonly isOnline: boolean;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* `isOnline` reads `navigator.onLine` where available (every browser target
|
|
271
|
+
* this package ships to) and defaults to `true` on a runtime without a
|
|
272
|
+
* `navigator` (SSR) — the honest default for a signal that only degrades
|
|
273
|
+
* gracefully, never one this hook can source from the SDK itself: `06
|
|
274
|
+
* -offline-first.md` and `08-core-hooks.md §2.9`'s own "Wraps" line name
|
|
275
|
+
* "the transport's own online/offline signal" but `kaafil-js`'s
|
|
276
|
+
* `OfflineEngine` does not expose a queryable connectivity flag of its own
|
|
277
|
+
* (verified — `Outbox`/`Drainer` react to `online`/`offline` DOM events
|
|
278
|
+
* internally via `bindOpportunisticTriggers()`, but neither surfaces the
|
|
279
|
+
* CURRENT state as a readable property). This hook therefore reads the
|
|
280
|
+
* browser signal directly and refreshes it on the same events the engine
|
|
281
|
+
* itself listens for, rather than duplicating a connectivity tracker inside
|
|
282
|
+
* the SDK it is meant to be a thin subscription over.
|
|
283
|
+
*/
|
|
284
|
+
declare function useOutboxStatus(options?: OutboxStatusOptions): OutboxStatusResult;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* The three credential kinds a `KaafilClient` can be opened with, collapsed
|
|
288
|
+
* to the label every component downstream of the session adapter is allowed
|
|
289
|
+
* to see (`06-capability-and-personas.md §7`). Never a JWT, never which of
|
|
290
|
+
* `session.open`/`admin.open`/`share.open` produced it beyond this label.
|
|
291
|
+
*/
|
|
292
|
+
type Persona = 'manager' | 'agencyAdmin' | 'share';
|
|
293
|
+
/**
|
|
294
|
+
* `useSession()`'s return shape (`08-core-hooks.md §1.2`). `agencyRef` is
|
|
295
|
+
* `undefined` only for a `share` session — a share token carries no agency
|
|
296
|
+
* scope of its own (`client-entry.ts`'s share-session header, verified).
|
|
297
|
+
*/
|
|
298
|
+
interface SessionState {
|
|
299
|
+
readonly status: 'authenticated' | 'expired' | 'opening';
|
|
300
|
+
readonly persona: Persona;
|
|
301
|
+
readonly agencyRef: string | undefined;
|
|
302
|
+
readonly environment: 'live' | 'test';
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
declare function usePersona(): Persona;
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Returns the resolved value of `key` (`module.group.key`), or `undefined`
|
|
309
|
+
* when no rung supplied one and there is no frozen default to fall back to.
|
|
310
|
+
* There is no default parameter and none may ever be added (hard rule #5) —
|
|
311
|
+
* a component that needs to render something while this is `undefined`
|
|
312
|
+
* renders a loading/unknown state, never a guessed value.
|
|
313
|
+
*/
|
|
314
|
+
declare function useResolvedSetting<T>(key: `${string}.${string}.${string}`): T | undefined;
|
|
315
|
+
|
|
316
|
+
interface ServerTimeApi {
|
|
317
|
+
now: () => string;
|
|
318
|
+
sinceLastSync: string | undefined;
|
|
319
|
+
}
|
|
320
|
+
declare function useServerTime(): ServerTimeApi;
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Returns the open session's derived state. Reads the base value
|
|
324
|
+
* `SessionShell` provides, then layers the `session.expired` offline event
|
|
325
|
+
* (`08-core-hooks.md §1.2`'s "Wraps" paragraph) on top locally, so a
|
|
326
|
+
* `manager`/`agencyAdmin` session that expires mid-mount transitions to
|
|
327
|
+
* `status: 'expired'` without waiting on `SessionShell` to re-render this
|
|
328
|
+
* subtree itself. `OfflineShell` may not have mounted yet (or ever, for a
|
|
329
|
+
* consumer that only needs `useKaafilClient()`) — the listener attaches
|
|
330
|
+
* only when an `OfflineEngine` is actually in context, and is a no-op
|
|
331
|
+
* otherwise; this hook still throws if `SessionShell` itself is absent,
|
|
332
|
+
* since a session-derived read with no session is meaningless.
|
|
333
|
+
*/
|
|
334
|
+
declare function useSession(): SessionState;
|
|
335
|
+
|
|
336
|
+
/** One row of `GET /api/v1/share/{token}/forms` — `ShareFormsListResponse`
|
|
337
|
+
* (verified, `kaafil-js/openapi/openapi.json`). Metadata only: no prefill,
|
|
338
|
+
* no field list, no answers (`FRD:traveller-share §4.8`) — that detail
|
|
339
|
+
* arrives only from `renderForm()` below. */
|
|
340
|
+
interface ShareFormListItem {
|
|
341
|
+
readonly formId: string;
|
|
342
|
+
readonly key: string;
|
|
343
|
+
readonly title: string;
|
|
344
|
+
readonly phase: string;
|
|
345
|
+
readonly required: boolean;
|
|
346
|
+
readonly fillState: string;
|
|
347
|
+
readonly opensAt: string | null;
|
|
348
|
+
readonly closesAt: string | null;
|
|
349
|
+
readonly responseStatus: string | null;
|
|
350
|
+
readonly submittedAt: string | null;
|
|
351
|
+
}
|
|
352
|
+
/** One answer in a `save`/`submit` body — `ShareSaveFormRequest.answers[]`
|
|
353
|
+
* / `ShareSubmitFormRequest.answers[]` (verified). */
|
|
354
|
+
interface ShareFormAnswer {
|
|
355
|
+
readonly fieldKey: string;
|
|
356
|
+
readonly value: unknown;
|
|
357
|
+
}
|
|
358
|
+
interface ShareFormWriteInput {
|
|
359
|
+
readonly formId: string;
|
|
360
|
+
readonly answers: readonly ShareFormAnswer[];
|
|
361
|
+
/** This route's own de-dupe key — REQUIRED by the wire schema. See this
|
|
362
|
+
* file's header ("`clientToken` IS NOT A HOOK-MINTED IDEMPOTENCY KEY") —
|
|
363
|
+
* the caller mints this once per form-fill session and reuses it across
|
|
364
|
+
* every save/submit/retry of that session; this hook never generates it. */
|
|
365
|
+
readonly clientToken: string;
|
|
366
|
+
/** Group fill within the same `TripTraveller.partyId` — omit when the
|
|
367
|
+
* token itself already scopes to a single traveller. */
|
|
368
|
+
readonly travellerRef?: string;
|
|
369
|
+
readonly startNew?: boolean;
|
|
370
|
+
readonly isAnonymous?: boolean;
|
|
371
|
+
}
|
|
372
|
+
type ShareFormsListStatus = 'loading' | 'list-empty' | 'list-populated' | 'not-found';
|
|
373
|
+
/**
|
|
374
|
+
* The write-side status a `save()`/`submit()` call's tracked `OutboxOp`
|
|
375
|
+
* resolves to. Deliberately excludes `'filling'` (`02-forms.md`'s own
|
|
376
|
+
* `States` list also names it): `'filling'` is "the traveller is editing
|
|
377
|
+
* fields, no request in flight yet" — a pure local UI mode with no
|
|
378
|
+
* server/outbox signal behind it, so it belongs to the composite that owns
|
|
379
|
+
* the form's field state, never to this hook, which only ever reflects
|
|
380
|
+
* something async.
|
|
381
|
+
*/
|
|
382
|
+
type ShareFormsWriteStatus = 'idle' | 'saving' | 'submitting' | 'submitted' | 'conflicted' | 'subject-required' | 'queued-offline' | 'dropped-on-revoke';
|
|
383
|
+
interface ShareFormsResult {
|
|
384
|
+
readonly status: ShareFormsListStatus;
|
|
385
|
+
/** `[]` in both the `'loading'` and the `'list-empty'` states — a
|
|
386
|
+
* consumer distinguishes them via `status`, never via array emptiness
|
|
387
|
+
* alone (`02-forms.md`'s `Gating`: an empty list is a NORMAL steady
|
|
388
|
+
* state, never an error, never a placeholder). */
|
|
389
|
+
readonly forms: readonly ShareFormListItem[];
|
|
390
|
+
readonly serverTime: string | undefined;
|
|
391
|
+
/** Re-runs `share.forms.list()`. A composite calls this after a
|
|
392
|
+
* `submit()` lands, since submitting can change another form's
|
|
393
|
+
* `fillState` (e.g. an any-phase trigger opening a follow-up form). */
|
|
394
|
+
readonly refresh: () => Promise<void>;
|
|
395
|
+
/** `GET /api/v1/share/{token}/forms/{formId}` — the fully-resolved,
|
|
396
|
+
* ready-to-paint form (definition merged with any in-progress answers).
|
|
397
|
+
* An open shape (`ShareRenderResponse` has no closed schema yet,
|
|
398
|
+
* verified) — a live call, not cached, matching `save`/`submit`'s own
|
|
399
|
+
* un-cached write path. */
|
|
400
|
+
readonly renderForm: (formId: string, options?: {
|
|
401
|
+
readonly travellerRef?: string;
|
|
402
|
+
}) => Promise<Record<string, unknown>>;
|
|
403
|
+
/** An in-progress save — no required-field validation server-side. */
|
|
404
|
+
readonly save: (input: ShareFormWriteInput) => Promise<OutboxOp>;
|
|
405
|
+
/** Finalizes the response — full validation, one transaction. */
|
|
406
|
+
readonly submit: (input: ShareFormWriteInput) => Promise<OutboxOp>;
|
|
407
|
+
/** The combined save/submit write status — see `ShareFormsWriteStatus`. */
|
|
408
|
+
readonly writeStatus: ShareFormsWriteStatus;
|
|
409
|
+
/** The most recently tracked save/submit `OutboxOp`, or `undefined`
|
|
410
|
+
* before either has ever been called. */
|
|
411
|
+
readonly writeOp: OutboxOp | undefined;
|
|
412
|
+
}
|
|
413
|
+
declare function useShareForms(token: string): ShareFormsResult;
|
|
414
|
+
|
|
415
|
+
/** Metadata for one link. Never carries a plaintext token. */
|
|
416
|
+
type ShareLinkRow = Awaited<ReturnType<ShareTokensResource['list']>>[number];
|
|
417
|
+
/** A freshly minted link — the ONE shape that carries `token`. */
|
|
418
|
+
type MintedShareLink = Awaited<ReturnType<ShareTokensResource['create']>>;
|
|
419
|
+
/**
|
|
420
|
+
* The 14 sections a link can expose, in the order the engine's own
|
|
421
|
+
* `SHARE_SECTION_KEYS` declares them.
|
|
422
|
+
*
|
|
423
|
+
* Derived from the SDK's own request type rather than hand-listed, so a
|
|
424
|
+
* section added engine-side becomes a compile error here instead of a
|
|
425
|
+
* silently-missing checkbox.
|
|
426
|
+
*/
|
|
427
|
+
type ShareSectionKey = keyof NonNullable<NonNullable<Parameters<ShareTokensResource['create']>[0]['config']>['sections']>;
|
|
428
|
+
type ShareSections = Readonly<Record<ShareSectionKey, boolean>>;
|
|
429
|
+
interface MintShareLinkInput {
|
|
430
|
+
/** Omit for the whole-trip FAMILY link. */
|
|
431
|
+
readonly travellerRef?: string;
|
|
432
|
+
/**
|
|
433
|
+
* Omit entirely for the agency's own mode-based default. Supplying it turns
|
|
434
|
+
* every UNSET key OFF — a partial config does NOT inherit the defaults, so
|
|
435
|
+
* a caller that supplies this must name every section it wants visible.
|
|
436
|
+
* That is the wire's rule, not this hook's.
|
|
437
|
+
*/
|
|
438
|
+
readonly sections?: ShareSections;
|
|
439
|
+
readonly ttlDays?: number;
|
|
440
|
+
readonly expiresAt?: string;
|
|
441
|
+
}
|
|
442
|
+
interface PatchShareLinkInput {
|
|
443
|
+
readonly id: string;
|
|
444
|
+
/** The token row's own version. A stale one answers `409 CONFLICT_VERSION`. */
|
|
445
|
+
readonly version: number;
|
|
446
|
+
readonly sections?: ShareSections;
|
|
447
|
+
readonly expiresAt?: string;
|
|
448
|
+
}
|
|
449
|
+
interface ShareLinksResult {
|
|
450
|
+
/** Live links on this trip — `undefined` until the first read lands. */
|
|
451
|
+
readonly links: readonly ShareLinkRow[] | undefined;
|
|
452
|
+
readonly readFailed: boolean;
|
|
453
|
+
readonly refresh: () => Promise<void>;
|
|
454
|
+
readonly mint: (input: MintShareLinkInput) => Promise<MintedShareLink>;
|
|
455
|
+
readonly revoke: (id: string) => Promise<void>;
|
|
456
|
+
readonly patch: (input: PatchShareLinkInput) => Promise<void>;
|
|
457
|
+
readonly regenerate: (id: string) => Promise<MintedShareLink>;
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* `travellerRef` narrows the LIST to one subject; pass `null` for every link
|
|
461
|
+
* on the trip, family link included. Minting takes its own `travellerRef`
|
|
462
|
+
* independently, so one hook instance can list a traveller's links and mint
|
|
463
|
+
* a family link.
|
|
464
|
+
*/
|
|
465
|
+
declare function useShareLinks(tripRef: string, travellerRef: string | null): ShareLinksResult;
|
|
466
|
+
|
|
467
|
+
interface ShareSnapshotOptions {
|
|
468
|
+
readonly travellerRef?: string;
|
|
469
|
+
}
|
|
470
|
+
type ShareSnapshotResponse = Awaited<ReturnType<KaafilClient['share']['snapshot']>>;
|
|
471
|
+
/** The trip echo every snapshot response carries — `name`/`startDate`/
|
|
472
|
+
* `endDate` plus the two fields this hook used to throw away:
|
|
473
|
+
* `timezone` (the IANA zone every traveller-facing render must anchor to)
|
|
474
|
+
* and `phase` (server-computed `PRE_DEPARTURE`/`ON_TRIP`/`POST_TRIP`). */
|
|
475
|
+
type ShareSnapshotTrip = ShareSnapshotResponse['trip'];
|
|
476
|
+
interface ShareSnapshotResult {
|
|
477
|
+
readonly status: 'loading' | 'ready' | 'expired' | 'revoked' | 'not-found';
|
|
478
|
+
readonly sections: ReadonlyMap<string, unknown>;
|
|
479
|
+
/** The snapshot's `trip` echo, or `undefined` before any response has
|
|
480
|
+
* landed (mirrors `sections`' own "empty until ready" behaviour). NEVER a
|
|
481
|
+
* section key — see this file's header. */
|
|
482
|
+
readonly trip: ShareSnapshotTrip | undefined;
|
|
483
|
+
/** `meta.serverTime` off the most recently landed snapshot response — the
|
|
484
|
+
* only trusted clock a share composite may read (hard rule #6). Kept
|
|
485
|
+
* separate from `useServerTime()`'s own stream (which advances off
|
|
486
|
+
* `OfflineEngine`'s `snapshot.updated` event, not this hook's own fetch)
|
|
487
|
+
* so a composite that only ever calls `useShareSnapshot()` still has a
|
|
488
|
+
* real server stamp to compare against without also wiring the offline
|
|
489
|
+
* engine's event stream. `undefined` before any response has landed. */
|
|
490
|
+
readonly serverTime: string | undefined;
|
|
491
|
+
}
|
|
492
|
+
declare function useShareSnapshot(token: string, options?: ShareSnapshotOptions): ShareSnapshotResult;
|
|
493
|
+
|
|
494
|
+
interface SnapshotEntityResult<TRow> {
|
|
495
|
+
readonly row: TRow | undefined;
|
|
496
|
+
readonly syncedAt: string | undefined;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* `row` is `undefined` both when the id genuinely doesn't exist and when
|
|
500
|
+
* the list hasn't synced yet — a caller distinguishes those with
|
|
501
|
+
* `syncedAt`: absent entirely means "never pulled"; present with `row:
|
|
502
|
+
* undefined` means "pulled, and this id isn't in it" (`08-core-hooks.md
|
|
503
|
+
* §2.3`).
|
|
504
|
+
*/
|
|
505
|
+
declare function useSnapshotEntity<TRow extends Record<string, unknown>>(tripRef: string, listName: string, id: string): SnapshotEntityResult<TRow>;
|
|
506
|
+
|
|
507
|
+
interface SnapshotListOptions<TRow> {
|
|
508
|
+
/**
|
|
509
|
+
* The same list, read live, for a surface with no `OfflineShell`. Resolve
|
|
510
|
+
* the rows AND the server's own time — `syncedAt` means the same thing on
|
|
511
|
+
* both lanes ("what this reading is as of"), and deriving it from a device
|
|
512
|
+
* clock would make the two disagree.
|
|
513
|
+
*/
|
|
514
|
+
readonly live?: (client: KaafilClient, tripRef: string) => Promise<{
|
|
515
|
+
readonly rows: readonly TRow[];
|
|
516
|
+
readonly syncedAt: string | undefined;
|
|
517
|
+
}>;
|
|
518
|
+
}
|
|
519
|
+
interface SnapshotListResult<TRow> {
|
|
520
|
+
readonly rows: readonly TRow[];
|
|
521
|
+
readonly syncedAt: string | undefined;
|
|
522
|
+
/**
|
|
523
|
+
* Re-reads the live lane. A NO-OP on the snapshot lane, where the store's
|
|
524
|
+
* own `snapshot.updated` event already drives re-render and a manual
|
|
525
|
+
* refetch would be a second sync path.
|
|
526
|
+
*/
|
|
527
|
+
readonly refreshLive: () => Promise<void>;
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* At-least-once delivery is the CALLER's problem to absorb structurally
|
|
531
|
+
* (`07-offline-and-sync.md §4`) — this hook returns exactly what
|
|
532
|
+
* `SnapshotStore.list()` holds and does not de-duplicate beyond what the
|
|
533
|
+
* store itself already guarantees.
|
|
534
|
+
*/
|
|
535
|
+
declare function useSnapshotList<TRow extends Record<string, unknown>>(tripRef: string, listName: string, options?: SnapshotListOptions<TRow>): SnapshotListResult<TRow>;
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* DECISION: the catalog names "a threshold `ConfigShell` supplies" without
|
|
539
|
+
* naming the resolved-setting key. `stale.thresholdSeconds` is this hook's
|
|
540
|
+
* own choice of key, under the `stale` module namespace — the closest fit to
|
|
541
|
+
* `useResolvedSetting`'s `module.group.key` shape (`08-core-hooks.md §1.5`)
|
|
542
|
+
* for a value that isn't owned by any one of the eighteen domain modules.
|
|
543
|
+
* `isStale` is conservatively `false` (never a guessed threshold) when
|
|
544
|
+
* nothing resolved one — the honest reading of "no threshold configured"
|
|
545
|
+
* given `useResolvedSetting()` may never supply its own default (hard rule
|
|
546
|
+
* #5).
|
|
547
|
+
*/
|
|
548
|
+
declare function useStaleness(tripRef: string, listName: string): StalenessState;
|
|
549
|
+
|
|
550
|
+
type TravellerFormResponseRow = Awaited<ReturnType<FormsResource['trip']['travellerResponses']['list']>>['items'][number];
|
|
551
|
+
interface TravellerFormResponsesResult {
|
|
552
|
+
readonly responses: readonly TravellerFormResponseRow[] | undefined;
|
|
553
|
+
readonly readFailed: boolean;
|
|
554
|
+
readonly refresh: () => Promise<void>;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* `travellerRef` is nullable so a caller can mount this unconditionally while
|
|
558
|
+
* its own panel is closed — Rules of Hooks forbid calling it conditionally,
|
|
559
|
+
* and `null` reads as "nothing open yet" rather than firing a request for a
|
|
560
|
+
* traveller nobody asked for.
|
|
561
|
+
*/
|
|
562
|
+
declare function useTravellerFormResponses(tripRef: string, travellerRef: string | null): TravellerFormResponsesResult;
|
|
563
|
+
|
|
564
|
+
type TravellerProfileRead = Awaited<ReturnType<TravellersResource['getDetail']>>;
|
|
565
|
+
interface AddTravellerNoteInput {
|
|
566
|
+
readonly body: string;
|
|
567
|
+
}
|
|
568
|
+
interface TravellerProfileResult {
|
|
569
|
+
readonly read: TravellerProfileRead | undefined;
|
|
570
|
+
readonly readFailed: boolean;
|
|
571
|
+
readonly refresh: () => Promise<void>;
|
|
572
|
+
readonly addNote: (input: AddTravellerNoteInput) => Promise<OutboxOp>;
|
|
573
|
+
}
|
|
574
|
+
declare function useTravellerProfile(tripRef: string, travellerRef: string): TravellerProfileResult;
|
|
575
|
+
|
|
576
|
+
/** `TrekBoardResponse` — verified against `kaafil-js/src/generated/
|
|
577
|
+
* schema.d.ts`. `TreksResource['board']` resolves to `KaafilResponse<
|
|
578
|
+
* TrekBoardResponse>` = `TrekBoardResponse & { meta }` (`kaafil-js/src/
|
|
579
|
+
* types/meta.ts`'s own intersection, not a nested `data` field — unlike
|
|
580
|
+
* `FloatSummaryResponse`/`FloatLedgerResponse`, `TrekBoardResponse` carries
|
|
581
|
+
* `phase`/`stops`/`runningHeadCount`/`emptyState` at its own top level).
|
|
582
|
+
* `phase`/`externalTripId` are `null` only when `emptyState` is set; every
|
|
583
|
+
* other field still comes back with its empty/zero identity rather than
|
|
584
|
+
* being omitted (the schema's own doc comment). */
|
|
585
|
+
type TrekBoardData = Awaited<ReturnType<TreksResource['board']>>;
|
|
586
|
+
/** One row of `treks.walkIns.listPage()`'s page — `KaafilPagedResponse<
|
|
587
|
+
* readonly WalkInListItemResponse[]>` = the array itself, `meta` attached
|
|
588
|
+
* (`kaafil-js/src/types/meta.ts`), never a nested `.data`. */
|
|
589
|
+
type TrekWalkInRow = Awaited<ReturnType<TreksResource['walkIns']['listPage']>>[number];
|
|
590
|
+
/** `WalkInMetaResponse` — the pickup options + field-requirement hints a
|
|
591
|
+
* walk-in intake form reads, verified against the generated schema; same
|
|
592
|
+
* flat (non-`data`-nested) shape as `TrekBoardData`. */
|
|
593
|
+
type TrekWalkInMetaData = Awaited<ReturnType<TreksResource['walkIns']['meta']>>;
|
|
594
|
+
type CreateTrekWalkInInput = Omit<CreateTrekWalkInOptions, 'trekRef' | 'idempotencyKey' | 'signal'>;
|
|
595
|
+
type PostponeTrekInput = Omit<PostponeTrekOptions, 'trekRef' | 'idempotencyKey' | 'signal'>;
|
|
596
|
+
/** `ReconcileTrekWalkInOptions` — verified real (`treks.ts`'s own
|
|
597
|
+
* `walkIns.reconcile`) but NOT re-exported from `kaafil-js/client`'s public
|
|
598
|
+
* surface (verified: `client-entry.ts`'s `export type { ... } from
|
|
599
|
+
* './resources/treks'` list omits it, unlike its five siblings). Derived
|
|
600
|
+
* structurally off `TreksResource['walkIns']['reconcile']`'s own parameter
|
|
601
|
+
* rather than importing a name that does not exist on the package's public
|
|
602
|
+
* barrel — see this worker's final report for the exact export gap. */
|
|
603
|
+
type ReconcileTrekWalkInInput = Omit<Parameters<TreksResource['walkIns']['reconcile']>[0], 'trekRef' | 'walkInId' | 'idempotencyKey' | 'signal'>;
|
|
604
|
+
/**
|
|
605
|
+
* The phase-aware boarding board — a live-fetched, explicitly-refreshed
|
|
606
|
+
* state, never a snapshot subscription. See this file's header for why.
|
|
607
|
+
*/
|
|
608
|
+
interface TrekBoardState {
|
|
609
|
+
readonly data: TrekBoardData | undefined;
|
|
610
|
+
/** `true` once at least one `client.treks.board()` call has settled
|
|
611
|
+
* (success or failure) — same `loaded` contract `RoomingUnassignedPool`/
|
|
612
|
+
* `useFloat().summary` document. */
|
|
613
|
+
readonly loaded: boolean;
|
|
614
|
+
/** `true` when the MOST RECENT fetch threw — a genuine transport/server
|
|
615
|
+
* failure, distinct from the honest `emptyState` "no trek assigned"
|
|
616
|
+
* `200`. */
|
|
617
|
+
readonly lastFetchFailed: boolean;
|
|
618
|
+
readonly fetchedAt: string | undefined;
|
|
619
|
+
readonly refresh: () => Promise<void>;
|
|
620
|
+
}
|
|
621
|
+
/** The walk-in roster — live-fetched via `listPage`, one page at a time
|
|
622
|
+
* (`08-treks.md §TrekWalkInRoster`'s own prop table cites `.list`/
|
|
623
|
+
* `.listPage`, never a delta feed). `loadMore` advances the cursor; calling
|
|
624
|
+
* `refresh` resets back to the first page. */
|
|
625
|
+
interface TrekWalkInsState {
|
|
626
|
+
readonly rows: readonly TrekWalkInRow[];
|
|
627
|
+
readonly loaded: boolean;
|
|
628
|
+
readonly lastFetchFailed: boolean;
|
|
629
|
+
readonly fetchedAt: string | undefined;
|
|
630
|
+
readonly hasMore: boolean;
|
|
631
|
+
readonly refresh: () => Promise<void>;
|
|
632
|
+
readonly loadMore: () => Promise<void>;
|
|
633
|
+
}
|
|
634
|
+
interface TrekWalkInMetaState {
|
|
635
|
+
readonly data: TrekWalkInMetaData | undefined;
|
|
636
|
+
readonly loaded: boolean;
|
|
637
|
+
readonly lastFetchFailed: boolean;
|
|
638
|
+
readonly refresh: () => Promise<void>;
|
|
639
|
+
}
|
|
640
|
+
interface TreksReady {
|
|
641
|
+
readonly board: TrekBoardState;
|
|
642
|
+
readonly walkIns: TrekWalkInsState;
|
|
643
|
+
readonly walkInMeta: TrekWalkInMetaState;
|
|
644
|
+
/** `POST .../walk-ins` — lands `BOARDED` directly for a manager submitter
|
|
645
|
+
* (`D-211`). */
|
|
646
|
+
readonly createWalkIn: (input: CreateTrekWalkInInput) => Promise<OutboxOp>;
|
|
647
|
+
/** `POST .../postpone` — shifts itinerary/stay-window dates server-side;
|
|
648
|
+
* never shifts pickup `scheduledTime`s (`08-treks.md`'s own "Does NOT"). */
|
|
649
|
+
readonly postpone: (input: PostponeTrekInput) => Promise<OutboxOp>;
|
|
650
|
+
/** `POST .../walk-ins/{walkInId}/reconcile` — the human fallback for a
|
|
651
|
+
* name-only walk-in the automatic CRM-phone match can't clear on its
|
|
652
|
+
* own. See this file's header for why this is exposed beyond
|
|
653
|
+
* `08-treks.md`'s own prop tables. */
|
|
654
|
+
readonly reconcileWalkIn: (walkInId: string, input: ReconcileTrekWalkInInput) => Promise<OutboxOp>;
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* PERSONALIZED mode-dark. Returns `{ status: 'dark', reason }` before any
|
|
658
|
+
* fetch when the `'treks'` capability triple isn't `lit`
|
|
659
|
+
* (`06-capability-and-personas.md §3`).
|
|
660
|
+
*/
|
|
661
|
+
declare function useTreks(tripRef: string): DomainHookResult<TreksReady>;
|
|
662
|
+
|
|
663
|
+
interface KaafilBrandAssets {
|
|
664
|
+
readonly appName?: string;
|
|
665
|
+
readonly logo?: string | ReactNode;
|
|
666
|
+
readonly logoMark?: string | ReactNode;
|
|
667
|
+
readonly favicon?: string;
|
|
668
|
+
}
|
|
669
|
+
interface BrandShellProps extends KaafilBrandAssets {
|
|
670
|
+
readonly headStrategy?: 'none' | 'own-page';
|
|
671
|
+
readonly children?: ReactNode;
|
|
672
|
+
}
|
|
673
|
+
/** Reads the brand assets `BrandShell` forwarded, or `{}` when mounted
|
|
674
|
+
* without one (never throws — brand is presentational, not load-bearing the
|
|
675
|
+
* way a session read is). */
|
|
676
|
+
declare function useKaafilBrand(): KaafilBrandAssets;
|
|
677
|
+
interface ShareMeta {
|
|
678
|
+
readonly title: string | undefined;
|
|
679
|
+
readonly favicon: string | undefined;
|
|
680
|
+
readonly ogTitle: string | undefined;
|
|
681
|
+
readonly ogDescription: string | undefined;
|
|
682
|
+
readonly ogImage: string | undefined;
|
|
683
|
+
readonly robots: 'noindex' | 'index';
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Forwards brand assets unconditionally; enforces `headStrategy` before
|
|
687
|
+
* ever mounting `<KaafilDocumentHead>`. `'none'` is a HARD no-op — no
|
|
688
|
+
* branch below it ever touches `document.head`, even when `favicon`/
|
|
689
|
+
* `appName` are supplied. `'own-page'` is runtime-rejected under
|
|
690
|
+
* `agencyAdmin`/`manager` (dev throw, prod warning + silent `'none'`
|
|
691
|
+
* fallback — the same shape `useCapability()` uses for a wrong-persona call,
|
|
692
|
+
* `08-core-hooks.md §1.4`).
|
|
693
|
+
*/
|
|
694
|
+
declare function BrandShell({ appName, logo, logoMark, favicon, headStrategy, children, }: BrandShellProps): ReactNode;
|
|
695
|
+
/**
|
|
696
|
+
* Shell-owned read-only alternative to `<KaafilDocumentHead>` — for a host
|
|
697
|
+
* (e.g. Next.js App Router) that already owns `<head>` via its own
|
|
698
|
+
* `metadata`/`generateMetadata` export and must keep `headStrategy="none"`
|
|
699
|
+
* here. Never writes the head itself; exactly one of the two paths is
|
|
700
|
+
* active per mount (`shells/06-brand-shell.md`).
|
|
701
|
+
*/
|
|
702
|
+
declare function useKaafilShareMeta(assets: KaafilBrandAssets): ShareMeta;
|
|
703
|
+
|
|
704
|
+
/** A `module.group.key`-keyed document — the shape `seedConfig.tenant`/
|
|
705
|
+
* `seedConfig.agency` each carry (`shells/04-config-shell.md`'s `seedConfig`
|
|
706
|
+
* prop). Not exported from `../types` — this is `ConfigShell`'s own prop
|
|
707
|
+
* shape, not a `08-core-hooks.md`-catalogued type. */
|
|
708
|
+
type ConfigDocument = Readonly<Record<string, unknown>>;
|
|
709
|
+
interface ConfigShellProps {
|
|
710
|
+
readonly seedConfig?: {
|
|
711
|
+
readonly tenant?: ConfigDocument;
|
|
712
|
+
readonly agency?: ConfigDocument;
|
|
713
|
+
};
|
|
714
|
+
/** Accepted, not yet load-bearing — see this file's header DISCOVERY note. */
|
|
715
|
+
readonly refreshOn?: ReadonlyArray<'trip-load' | 'refocus' | 'snapshot-update'>;
|
|
716
|
+
readonly children?: ReactNode;
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Builds `resolveSetting` over the two rungs of the precedence ladder this
|
|
720
|
+
* package can actually reach today (`shells/04-config-shell.md §"Agency
|
|
721
|
+
* settings are unreachable"`) — Agency narrows Tenant, Tenant is the seed's
|
|
722
|
+
* outer rung; neither Kaafil-default nor Partner has a browser-reachable
|
|
723
|
+
* read at all (`⛔ GAP-002`), so this shell does not fabricate either.
|
|
724
|
+
*/
|
|
725
|
+
declare function ConfigShell({ seedConfig, children }: ConfigShellProps): ReactNode;
|
|
726
|
+
|
|
727
|
+
/** Discriminated per `00-decisions.md` U-014/U-003 — passing a `shareToken`
|
|
728
|
+
* alongside `agencyRef` is a compile error, never a shape this shell has to
|
|
729
|
+
* defensively validate at runtime. */
|
|
730
|
+
type SessionShellCredential = {
|
|
731
|
+
readonly accessToken: string;
|
|
732
|
+
readonly refreshToken: string;
|
|
733
|
+
readonly agencyRef: string;
|
|
734
|
+
readonly shareToken?: undefined;
|
|
735
|
+
readonly credentialResolver?: undefined;
|
|
736
|
+
} | {
|
|
737
|
+
readonly shareToken: string;
|
|
738
|
+
readonly accessToken?: undefined;
|
|
739
|
+
readonly refreshToken?: undefined;
|
|
740
|
+
readonly agencyRef?: undefined;
|
|
741
|
+
readonly credentialResolver?: undefined;
|
|
742
|
+
} | {
|
|
743
|
+
readonly credentialResolver: () => Promise<{
|
|
744
|
+
accessToken: string;
|
|
745
|
+
refreshToken: string;
|
|
746
|
+
agencyRef: string;
|
|
747
|
+
} | {
|
|
748
|
+
shareToken: string;
|
|
749
|
+
}>;
|
|
750
|
+
readonly accessToken?: undefined;
|
|
751
|
+
readonly refreshToken?: undefined;
|
|
752
|
+
readonly agencyRef?: undefined;
|
|
753
|
+
readonly shareToken?: undefined;
|
|
754
|
+
};
|
|
755
|
+
type SessionShellProps = SessionShellCredential & {
|
|
756
|
+
readonly environment?: Environment;
|
|
757
|
+
/** Forwarded into `session.open`'s/`admin.open`'s own `onRefresh` field —
|
|
758
|
+
* no-ops silently for a `share` credential, which has no refresh shape
|
|
759
|
+
* (`shells/02-session-shell.md`). */
|
|
760
|
+
readonly onRefresh?: (result: unknown) => void | Promise<void>;
|
|
761
|
+
readonly onSessionExpired?: (credentialKind: Persona) => void;
|
|
762
|
+
readonly children?: ReactNode;
|
|
763
|
+
};
|
|
764
|
+
/**
|
|
765
|
+
* Opens the credential the resolved value props imply, exposes
|
|
766
|
+
* `KaafilClientContext`/`SessionContext`, and latches `onSessionExpired` to
|
|
767
|
+
* fire exactly once per terminal expiry — see this file's header for why the
|
|
768
|
+
* actual event subscription happens one shell further in
|
|
769
|
+
* (`./internal/sessionExpiryBridge.ts`). `client.close()` runs on unmount and
|
|
770
|
+
* before any re-open — `KaafilClient` throws `KaafilClientAlreadyOpenError`
|
|
771
|
+
* on a second `open()` without an intervening `close()` (verified,
|
|
772
|
+
* `client-entry.ts`).
|
|
773
|
+
*/
|
|
774
|
+
declare function SessionShell(props: SessionShellProps): ReactNode;
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* The discriminated union `09-telemetry-shell.md §"Event taxonomy"` owns —
|
|
778
|
+
* every field is an opaque id, an enum, or a count, never PII, never a money
|
|
779
|
+
* amount. This is the type's one home; a new event type is added to this
|
|
780
|
+
* union and to the table in that doc, nowhere else.
|
|
781
|
+
*/
|
|
782
|
+
type TelemetryEvent = {
|
|
783
|
+
readonly type: 'session.opened';
|
|
784
|
+
readonly timestamp: string;
|
|
785
|
+
readonly persona: string;
|
|
786
|
+
} | {
|
|
787
|
+
readonly type: 'session.expired';
|
|
788
|
+
readonly timestamp: string;
|
|
789
|
+
readonly persona: string;
|
|
790
|
+
} | {
|
|
791
|
+
readonly type: 'capability.darkened';
|
|
792
|
+
readonly timestamp: string;
|
|
793
|
+
readonly capability: string;
|
|
794
|
+
readonly reason: 'mode' | 'data' | 'flag';
|
|
795
|
+
} | {
|
|
796
|
+
readonly type: 'sync.drained';
|
|
797
|
+
readonly timestamp: string;
|
|
798
|
+
readonly tripRef: string;
|
|
799
|
+
readonly pending: number;
|
|
800
|
+
} | {
|
|
801
|
+
readonly type: 'sync.error';
|
|
802
|
+
readonly timestamp: string;
|
|
803
|
+
readonly tripRef: string;
|
|
804
|
+
readonly pending: number;
|
|
805
|
+
} | {
|
|
806
|
+
readonly type: 'outbox.parked';
|
|
807
|
+
readonly timestamp: string;
|
|
808
|
+
readonly opId: string;
|
|
809
|
+
readonly code: string;
|
|
810
|
+
} | {
|
|
811
|
+
readonly type: 'conflict.surfaced';
|
|
812
|
+
readonly timestamp: string;
|
|
813
|
+
readonly opId: string;
|
|
814
|
+
} | {
|
|
815
|
+
readonly type: 'conflict.resolved';
|
|
816
|
+
readonly timestamp: string;
|
|
817
|
+
readonly opId: string;
|
|
818
|
+
readonly choice?: 'keep-queued' | 'keep-current';
|
|
819
|
+
} | {
|
|
820
|
+
readonly type: 'error.caught';
|
|
821
|
+
readonly timestamp: string;
|
|
822
|
+
readonly classification: 'retryable' | 'parked' | 'isolation';
|
|
823
|
+
readonly code: string | undefined;
|
|
824
|
+
} | {
|
|
825
|
+
readonly type: 'brand.headStrategyRejected';
|
|
826
|
+
readonly timestamp: string;
|
|
827
|
+
readonly persona: string;
|
|
828
|
+
} | {
|
|
829
|
+
readonly type: 'frame.resolved';
|
|
830
|
+
readonly timestamp: string;
|
|
831
|
+
readonly frame: string;
|
|
832
|
+
readonly overridden: boolean;
|
|
833
|
+
};
|
|
834
|
+
interface TelemetryShellProps {
|
|
835
|
+
readonly onEvent?: (event: TelemetryEvent) => void;
|
|
836
|
+
readonly children?: ReactNode;
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* Wires the taxonomy's `session.opened`/`session.expired` rows off
|
|
840
|
+
* `useSession()`'s own status transitions — `useSession()` (hooks phase)
|
|
841
|
+
* already folds the underlying `session.expired`/`share.expired`/
|
|
842
|
+
* `share.revoked` offline events into its returned `status`
|
|
843
|
+
* (`../hooks/useSession.ts`), so watching `status` here is the one signal
|
|
844
|
+
* this shell needs, without a second, competing subscription to the same
|
|
845
|
+
* underlying event. The remaining taxonomy rows
|
|
846
|
+
* (`capability.darkened`/`sync.*`/`outbox.parked`/`conflict.*`/
|
|
847
|
+
* `error.caught`/`brand.headStrategyRejected`/`frame.resolved`) are defined
|
|
848
|
+
* in the `TelemetryEvent` union above (their one home) for the
|
|
849
|
+
* component-authoring phase's composites to emit into this same sink —
|
|
850
|
+
* this shell does not synthesize them itself before the events they
|
|
851
|
+
* describe exist to observe.
|
|
852
|
+
*/
|
|
853
|
+
declare function TelemetryShell({ onEvent, children }: TelemetryShellProps): ReactNode;
|
|
854
|
+
|
|
855
|
+
type KaafilUIKitProviderCredential = SessionShellCredential;
|
|
856
|
+
/** `defaultCapabilityViews` (`shells/00-kaafil-uikit-provider.md`'s props
|
|
857
|
+
* table) — a tree-wide DEFAULT for the three capability-dark view overrides
|
|
858
|
+
* `04-customization-ladder.md §5.1` defines. No composite exists yet to
|
|
859
|
+
* consume this (component authoring is out of scope for this phase), so
|
|
860
|
+
* this context is the provider's own seam for one to read later; it never
|
|
861
|
+
* changes which of the three treatments applies, only what a composite
|
|
862
|
+
* falls back to rendering when it hasn't set its own same-named prop. */
|
|
863
|
+
interface DefaultCapabilityViews {
|
|
864
|
+
readonly modeDarkView?: ReactNode | ((ctx: unknown) => ReactNode);
|
|
865
|
+
readonly dataDarkView?: ReactNode | ((ctx: unknown) => ReactNode);
|
|
866
|
+
readonly flagDarkView?: ReactNode | ((ctx: unknown) => ReactNode);
|
|
867
|
+
}
|
|
868
|
+
/** Reads the tree-wide default set by `<KaafilUIKitProvider
|
|
869
|
+
* defaultCapabilityViews>` — `{}` when the provider didn't set one, never a
|
|
870
|
+
* required context (a missing default simply means every composite falls
|
|
871
|
+
* back to its own built-in dark treatment). */
|
|
872
|
+
declare function useDefaultCapabilityViews(): DefaultCapabilityViews;
|
|
873
|
+
interface KaafilUIKitProviderProps {
|
|
874
|
+
readonly environment?: Environment;
|
|
875
|
+
readonly onSessionExpired?: (credentialKind: Persona) => void;
|
|
876
|
+
readonly density?: 'compact' | 'default' | 'comfortable';
|
|
877
|
+
readonly theme?: 'light' | 'dark' | 'system';
|
|
878
|
+
readonly brand?: KaafilBrandAssets & {
|
|
879
|
+
readonly headStrategy?: 'none' | 'own-page';
|
|
880
|
+
};
|
|
881
|
+
readonly locale?: string;
|
|
882
|
+
readonly isolation?: 'scoped' | 'shadow';
|
|
883
|
+
readonly onEvent?: (event: TelemetryEvent) => void;
|
|
884
|
+
readonly storage?: KaafilStorageAdapter;
|
|
885
|
+
readonly blob?: {
|
|
886
|
+
readonly uploader: BlobUploader;
|
|
887
|
+
readonly source: BlobSource;
|
|
888
|
+
};
|
|
889
|
+
readonly conflictResolver?: ConflictResolver;
|
|
890
|
+
readonly readEntity?: EntityReader;
|
|
891
|
+
readonly offlineScope?: string;
|
|
892
|
+
readonly seedConfig?: {
|
|
893
|
+
readonly tenant?: ConfigDocument;
|
|
894
|
+
readonly agency?: ConfigDocument;
|
|
895
|
+
};
|
|
896
|
+
readonly defaultCapabilityViews?: DefaultCapabilityViews;
|
|
897
|
+
readonly children?: ReactNode;
|
|
898
|
+
}
|
|
899
|
+
type KaafilUIKitProviderCredentialProps = KaafilUIKitProviderCredential & KaafilUIKitProviderProps;
|
|
900
|
+
/**
|
|
901
|
+
* Composes `ErrorShell → ThemeShell → I18nShell → AppShell → SessionShell →
|
|
902
|
+
* OfflineShell → ConfigShell → BrandShell → TelemetryShell → {children}`,
|
|
903
|
+
* the locked order (`shells/README.md §2`). No `persona` prop, no `mode`
|
|
904
|
+
* prop, no `sessionEndpoint` — the credential union above is the only way
|
|
905
|
+
* in, as VALUES (`00-decisions.md` U-003, U-014).
|
|
906
|
+
*/
|
|
907
|
+
declare function KaafilUIKitProvider(props: KaafilUIKitProviderCredentialProps): ReactNode;
|
|
908
|
+
|
|
909
|
+
/**
|
|
910
|
+
* A type-keyed registry: `register`/`resolve`, resolved by lookup, never a
|
|
911
|
+
* `switch`/`if-else` chain (`09-registries.md §1` rule 1). `resolve` is
|
|
912
|
+
* documented as "internal; called by the composite that owns the registry
|
|
913
|
+
* per row/item/kind it renders" (§1's registration-signature note) — this
|
|
914
|
+
* factory does not itself enforce that a consumer never calls `resolve`
|
|
915
|
+
* from outside a composite, because there is no way to do so at the type
|
|
916
|
+
* level without either a second module boundary per registry or a runtime
|
|
917
|
+
* check with no way to tell "composite" from "integrator code" apart; the
|
|
918
|
+
* convention is enforced by which files ever call it, not by this factory.
|
|
919
|
+
*/
|
|
920
|
+
interface Registry<TKey extends string, THandler> {
|
|
921
|
+
/**
|
|
922
|
+
* Registers `handler` under `key`. Rule 2 (`09-registries.md §1`): the
|
|
923
|
+
* LAST registration for a given key wins — a custom registration
|
|
924
|
+
* overwrites a built-in one, and a re-registration of an already-custom
|
|
925
|
+
* key overwrites that too. There is no "first registration wins" mode and
|
|
926
|
+
* no error on re-registering an existing key, because tier-4/5
|
|
927
|
+
* customization (`04-customization-ladder.md`) depends on exactly this
|
|
928
|
+
* being silent and total.
|
|
929
|
+
*/
|
|
930
|
+
register(key: TKey, handler: THandler): void;
|
|
931
|
+
/**
|
|
932
|
+
* Resolves `key` to its registered handler, or the `default` fallback
|
|
933
|
+
* (rule 3) when `key` has no registration — because the engine shipped a
|
|
934
|
+
* new kind this build predates, or an integrator's custom kind rode an
|
|
935
|
+
* key nothing here anticipated. Never throws and never returns
|
|
936
|
+
* `undefined` — the fallback registration (seeded at `createRegistry()`
|
|
937
|
+
* time) guarantees a resolve is always total.
|
|
938
|
+
*/
|
|
939
|
+
resolve(key: TKey): THandler;
|
|
940
|
+
/**
|
|
941
|
+
* Every key currently registered, fallback excluded — for a composite
|
|
942
|
+
* that needs to enumerate what's registered (a settings UI listing
|
|
943
|
+
* overridable kinds), never for resolving one row's dispatch (that is
|
|
944
|
+
* always `resolve`, so a row from an unregistered kind still renders).
|
|
945
|
+
*/
|
|
946
|
+
registeredKeys(): readonly TKey[];
|
|
947
|
+
}
|
|
948
|
+
interface CreateRegistryOptions<THandler> {
|
|
949
|
+
/**
|
|
950
|
+
* The `default` registration (`09-registries.md §1` rule 3: "the fallback
|
|
951
|
+
* is itself a registration under a reserved `default` key, so it inherits
|
|
952
|
+
* the same override mechanism as every other entry rather than being
|
|
953
|
+
* special-cased in the resolver"). A consumer MAY later call
|
|
954
|
+
* `register('default' as TKey, …)` to replace it wholesale, the same way
|
|
955
|
+
* any other key can be overridden — this factory does not special-case
|
|
956
|
+
* that call either.
|
|
957
|
+
*/
|
|
958
|
+
readonly fallback: THandler;
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Builds one registry instance. `TKey` is left to the caller as a string
|
|
962
|
+
* literal union (`FormFieldKind`, `BlockerKey`, …) or a plain `string` for a
|
|
963
|
+
* genuinely open set — this factory does not require the union to be
|
|
964
|
+
* closed, which is exactly what lets a consumer "register a new key without
|
|
965
|
+
* a PR" against this package.
|
|
966
|
+
*/
|
|
967
|
+
declare function createRegistry<TKey extends string, THandler>(options: CreateRegistryOptions<THandler>): Registry<TKey, THandler>;
|
|
968
|
+
|
|
969
|
+
/** A desk/field screen scoped to one trip. `tripRef` is the host's own
|
|
970
|
+
* external id OR a Kaafil id — every `:ref` route accepts either, and the
|
|
971
|
+
* UIKit never asks a host to resolve one into the other first. */
|
|
972
|
+
interface TripScopedParams {
|
|
973
|
+
readonly tripRef: string;
|
|
974
|
+
/** One of the trip workspace's own tab keys. Optional: absent means the
|
|
975
|
+
* surface picks its own landing tab. */
|
|
976
|
+
readonly initialTab?: KaafilTripTabKey;
|
|
977
|
+
}
|
|
978
|
+
/** An agency-wide desk screen. There is deliberately no `agencyRef`: scope
|
|
979
|
+
* comes from the open credential, never a route param (`00-decisions.md`
|
|
980
|
+
* U-003). */
|
|
981
|
+
interface AgencyScopedParams {
|
|
982
|
+
readonly initialPane?: string;
|
|
983
|
+
}
|
|
984
|
+
/** The public share surface. `token` is the opaque value from the share
|
|
985
|
+
* link's own URL — never a traveller id, never a trip ref. */
|
|
986
|
+
interface ShareParams {
|
|
987
|
+
readonly token: string;
|
|
988
|
+
}
|
|
989
|
+
/** The two props introduced by the deep-link table itself. Both are bare
|
|
990
|
+
* props on the receiving screen — they carry scope and behaviour, not
|
|
991
|
+
* presentation, so neither is a `components`/`*Slot` key. */
|
|
992
|
+
interface DeepLinkParams {
|
|
993
|
+
/** The row the destination must scroll to and focus on arrival. */
|
|
994
|
+
readonly highlightId?: string;
|
|
995
|
+
/** A named filter preset the destination flow already exposes. The screen
|
|
996
|
+
* passes it straight through; the UIKit has no filter language of its
|
|
997
|
+
* own. */
|
|
998
|
+
readonly presetFilter?: string;
|
|
999
|
+
}
|
|
1000
|
+
type KaafilTripTabKey = 'itinerary' | 'pickups' | 'rooming' | 'vehicles' | 'vendors' | 'payments' | 'expenses' | 'float' | 'checklist' | 'forms';
|
|
1001
|
+
/**
|
|
1002
|
+
* The engine's own route hints (`closing-day.constants.ts#
|
|
1003
|
+
* CLOSEOUT_BLOCKER_ACTION_KEYS`), and the value a caller routes on.
|
|
1004
|
+
*
|
|
1005
|
+
* ROUTE ON `actionKey`, NEVER ON `key` OR THE COPY. The engine says so
|
|
1006
|
+
* outright — "the route hint the FE navigates on, so it never parses copy"
|
|
1007
|
+
* — and the titles are explicitly free to be reworded.
|
|
1008
|
+
*/
|
|
1009
|
+
type CloseoutActionKey = 'open_checklist' | 'open_collections' | 'open_expenses' | 'open_float' | 'open_forms' | 'open_itinerary' | 'open_mandatory_checklist' | 'open_past_itinerary' | 'open_pickups' | 'open_rooming' | 'open_seating' | 'open_vendors';
|
|
1010
|
+
/** The blocker keys the engine can emit (`CloseoutBlockerKey`). Accepted as
|
|
1011
|
+
* an optional refinement below — see `resolveBlockerDeepLink`. */
|
|
1012
|
+
type CloseoutBlockerKey = 'balance_due' | 'missing_receipt' | 'float_not_returned' | 'open_mandatory_checklist' | 'required_form_gap' | 'unassigned_rooming' | 'unseated_travellers' | 'pickup_no_show' | 'reimbursements_pending' | 'unrated_vendors' | 'open_past_itinerary';
|
|
1013
|
+
/**
|
|
1014
|
+
* `actionKey` → the tab that clears the row.
|
|
1015
|
+
*
|
|
1016
|
+
* A type-keyed record (hard rule #8), total over the union so a new engine
|
|
1017
|
+
* action key is a compile error here rather than a row whose jump silently
|
|
1018
|
+
* does nothing.
|
|
1019
|
+
*/
|
|
1020
|
+
declare const CLOSEOUT_ACTION_TAB: Readonly<Record<CloseoutActionKey, KaafilTripTabKey>>;
|
|
1021
|
+
/** What a caller should do with a blocker row's action. */
|
|
1022
|
+
interface BlockerDeepLink extends DeepLinkParams {
|
|
1023
|
+
readonly tab: KaafilTripTabKey;
|
|
1024
|
+
}
|
|
1025
|
+
interface ResolveBlockerInput {
|
|
1026
|
+
/** The engine's route hint. The one required field. */
|
|
1027
|
+
readonly actionKey: string;
|
|
1028
|
+
/** The blocker's own key, when the caller has the whole row. Refines the
|
|
1029
|
+
* filter only; it never changes the tab. */
|
|
1030
|
+
readonly key?: string;
|
|
1031
|
+
/** Passed through untouched when the caller knows which row to focus —
|
|
1032
|
+
* typically only when the blocker's `count` is 1. */
|
|
1033
|
+
readonly highlightId?: string;
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Resolve one blocker row into a destination, or `null` for a row that has
|
|
1037
|
+
* nowhere to send anyone.
|
|
1038
|
+
*
|
|
1039
|
+
* `null` IS A REAL ANSWER AND MUST BE HANDLED — render the row's own
|
|
1040
|
+
* statement with no jump, never a control that goes nowhere. It happens for
|
|
1041
|
+
* an `actionKey` this build has no tab for (a later engine adding one), and
|
|
1042
|
+
* for a tab this trip does not have.
|
|
1043
|
+
*
|
|
1044
|
+
* ── TWO ROWS THE SPEC AND THE ENGINE DISAGREE ABOUT ──────────────────────
|
|
1045
|
+
*
|
|
1046
|
+
* `shared/00-routing-and-deeplinks.md §3` says `reimbursements_pending`
|
|
1047
|
+
* "never navigates" (resolved by CRM back-office, out of band) and that
|
|
1048
|
+
* `unrated_vendors` is unbuildable (`GAP-005`). The ENGINE assigns both an
|
|
1049
|
+
* `actionKey` anyway — `open_expenses` and `open_vendors` — on its own
|
|
1050
|
+
* stated principle that "a row pointing at NO screen is a row a manager
|
|
1051
|
+
* cannot act on".
|
|
1052
|
+
*
|
|
1053
|
+
* This follows the engine, because the engine is what actually ships the
|
|
1054
|
+
* row, and both destinations are defensible: the expenses tab shows claim
|
|
1055
|
+
* status read-only, which IS where you look to see where a reimbursement
|
|
1056
|
+
* got to, and the vendors tab is where a rating would live. In practice
|
|
1057
|
+
* neither costs anything — `unrated_vendors` is never emitted at all (the
|
|
1058
|
+
* engine has no vendor-rating source to probe), and `reimbursements_pending`
|
|
1059
|
+
* lands unfiltered by the note in `BLOCKER_PRESET_FILTER`.
|
|
1060
|
+
*/
|
|
1061
|
+
declare function resolveBlockerDeepLink(input: ResolveBlockerInput): BlockerDeepLink | null;
|
|
1062
|
+
/**
|
|
1063
|
+
* A deep link → query params, for a host that wants to put one in a URL.
|
|
1064
|
+
*
|
|
1065
|
+
* Returns a FRESH `URLSearchParams` carrying only this link's own keys — it
|
|
1066
|
+
* never mutates an input, so a caller merges it into their own query string
|
|
1067
|
+
* on their own terms rather than having this decide what else survives.
|
|
1068
|
+
*/
|
|
1069
|
+
declare function toSearchParams(link: Partial<BlockerDeepLink>): URLSearchParams;
|
|
1070
|
+
/**
|
|
1071
|
+
* Query params → the props a surface takes, or `null` when the query carries
|
|
1072
|
+
* no Kaafil deep link at all.
|
|
1073
|
+
*
|
|
1074
|
+
* `null` rather than an empty object, so `if (link)` is enough to tell "this
|
|
1075
|
+
* URL addresses a Kaafil surface" from "it does not" — a host's own router
|
|
1076
|
+
* will hand this every query string it sees, most of which are none of our
|
|
1077
|
+
* business.
|
|
1078
|
+
*
|
|
1079
|
+
* AN UNKNOWN TAB IS DROPPED, not passed through. The value came from a URL,
|
|
1080
|
+
* which is user-editable; handing an arbitrary string to a surface as a tab
|
|
1081
|
+
* key would put unvalidated input into a registry lookup. `highlightId` and
|
|
1082
|
+
* `presetFilter` ARE passed through as-is — they are opaque by contract, and
|
|
1083
|
+
* the destination flow is what decides whether either matches anything.
|
|
1084
|
+
*/
|
|
1085
|
+
declare function fromSearchParams(params: URLSearchParams): (DeepLinkParams & {
|
|
1086
|
+
readonly initialTab?: KaafilTripTabKey;
|
|
1087
|
+
}) | null;
|
|
1088
|
+
/** Narrows a string off a URL to the shared tab vocabulary. Exported because
|
|
1089
|
+
* a host validating its own route params wants the same check. */
|
|
1090
|
+
declare function isTripTabKey(value: string | null | undefined): value is KaafilTripTabKey;
|
|
1091
|
+
|
|
1092
|
+
type AppShellFamily = 'admin' | 'manager' | 'traveller';
|
|
1093
|
+
type AppShellFrame = 'desk' | 'field' | 'document';
|
|
1094
|
+
interface AppShellProps {
|
|
1095
|
+
readonly frame?: AppShellFrame;
|
|
1096
|
+
readonly family?: AppShellFamily;
|
|
1097
|
+
readonly isolation?: 'scoped' | 'shadow';
|
|
1098
|
+
readonly navSlot?: ReactNode;
|
|
1099
|
+
readonly actionBarSlot?: ReactNode;
|
|
1100
|
+
readonly connectivitySlot?: ReactNode;
|
|
1101
|
+
readonly children?: ReactNode;
|
|
1102
|
+
/**
|
|
1103
|
+
* Per-instance `--kf-*` token overrides (`00-decisions.md` U-019). Layer-3
|
|
1104
|
+
* tokens are per component TYPE; this is how one INSTANCE differs from
|
|
1105
|
+
* another without restyling every sibling. On a shell this is also the
|
|
1106
|
+
* per-SUBTREE scope: custom properties inherit, so tokens set here reach
|
|
1107
|
+
* every descendant — including across the shadow-DOM boundary in
|
|
1108
|
+
* `isolation="shadow"` mode, since custom-property inheritance follows
|
|
1109
|
+
* the flat tree from a shadow host into its shadow root (unlike ordinary
|
|
1110
|
+
* selector-based CSS, which does not cross that boundary). `.kf-root`
|
|
1111
|
+
* here is either the shadow host itself, or a light-DOM ancestor of it —
|
|
1112
|
+
* both cases inherit normally, so `style` lands once, on this outermost
|
|
1113
|
+
* node, never needing to be re-applied inside `ShadowIsolationBoundary`.
|
|
1114
|
+
*/
|
|
1115
|
+
readonly style?: KaafilTokenOverrides;
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Establishes `.kf-root`, the resolved `frame` shape, the CSS-isolation
|
|
1119
|
+
* rung, and the container-query root. Renders unconditionally — never
|
|
1120
|
+
* withholds `{children}` behind a loading gate (`shells/README.md §1`).
|
|
1121
|
+
*/
|
|
1122
|
+
declare function AppShell({ frame, family, isolation, navSlot, actionBarSlot, connectivitySlot, children, style, }: AppShellProps): ReactNode;
|
|
1123
|
+
|
|
1124
|
+
type ErrorShellClassification = 'retryable' | 'parked' | 'isolation';
|
|
1125
|
+
interface ErrorShellFallbackContext {
|
|
1126
|
+
readonly classification: ErrorShellClassification;
|
|
1127
|
+
readonly code: string | undefined;
|
|
1128
|
+
}
|
|
1129
|
+
interface ErrorShellProps {
|
|
1130
|
+
readonly fallbackSlot?: (ctx: ErrorShellFallbackContext) => ReactNode;
|
|
1131
|
+
readonly children?: ReactNode;
|
|
1132
|
+
}
|
|
1133
|
+
interface ErrorShellState {
|
|
1134
|
+
readonly caught: {
|
|
1135
|
+
readonly error: unknown;
|
|
1136
|
+
} | null;
|
|
1137
|
+
readonly retryKey: number;
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Catches a thrown render error from anything beneath it. Never consumes
|
|
1141
|
+
* `ThemeShell`/`I18nShell` context in its own fallback, never retries a
|
|
1142
|
+
* `parked`/`isolation` classification, and never offers an admin override
|
|
1143
|
+
* for a classified `423`/`402`/`422`.
|
|
1144
|
+
*/
|
|
1145
|
+
declare class ErrorShell extends Component<ErrorShellProps, ErrorShellState> {
|
|
1146
|
+
state: ErrorShellState;
|
|
1147
|
+
static getDerivedStateFromError(error: unknown): Partial<ErrorShellState>;
|
|
1148
|
+
private handleRetry;
|
|
1149
|
+
render(): ReactNode;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
type HostCssHazard = 'global-box-sizing-reset' | 'global-button-input-unset' | 'tailwind-preflight-after-ours' | 'global-margin-padding-reset' | 'conflicting-layer-order' | 'global-img-max-width' | 'host-css-reset-library' | 'global-focus-outline-removed';
|
|
1153
|
+
interface HostCssCompatibilityProbeProps {
|
|
1154
|
+
/**
|
|
1155
|
+
* Per-instance `--kf-*` token overrides (`00-decisions.md` U-019). Layer-3
|
|
1156
|
+
* tokens are per component TYPE; this is how one INSTANCE differs from
|
|
1157
|
+
* another without restyling every sibling.
|
|
1158
|
+
*/
|
|
1159
|
+
readonly style?: KaafilTokenOverrides;
|
|
1160
|
+
}
|
|
1161
|
+
/** Dev-only per `05-theming-and-branding.md §7` — a no-op in production,
|
|
1162
|
+
* with a dev-only warning at the ONE other place `isDevelopment()` reads
|
|
1163
|
+
* false-negatively (a production build accidentally shipping this probe). */
|
|
1164
|
+
declare function HostCssCompatibilityProbe({ style, }?: HostCssCompatibilityProbeProps): ReactNode;
|
|
1165
|
+
|
|
1166
|
+
type ChromeLocale = 'en' | 'hi';
|
|
1167
|
+
|
|
1168
|
+
interface I18nContextValue {
|
|
1169
|
+
readonly locale: ChromeLocale;
|
|
1170
|
+
/** The host's own, possibly-unrecognised BCP-47 tag — kept alongside the
|
|
1171
|
+
* resolved `ChromeLocale` so a consumer can tell "we're rendering en
|
|
1172
|
+
* because the host asked for en" apart from "we're rendering en because
|
|
1173
|
+
* the host's tag has no shipped sibling catalog" without this context
|
|
1174
|
+
* lying about which locale is actually active. */
|
|
1175
|
+
readonly requestedLocale: string;
|
|
1176
|
+
readonly t: (key: string) => string;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
interface I18nShellProps {
|
|
1180
|
+
/** BCP-47 tag. No `Accept-Language` sniff, no `Traveller.locale` read —
|
|
1181
|
+
* the host is the one party that already knows which locale its user or
|
|
1182
|
+
* traveller wants (`13-i18n-and-formatting.md §3.3`). */
|
|
1183
|
+
readonly locale?: string;
|
|
1184
|
+
readonly children?: ReactNode;
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Resolves the active locale's chrome catalog synchronously — the catalog
|
|
1188
|
+
* ships inside the package bundle (`shells/07-i18n-shell.md`'s own "Offline"
|
|
1189
|
+
* field), so there is no loading state for a descendant to observe.
|
|
1190
|
+
*/
|
|
1191
|
+
declare function I18nShell({ locale, children }: I18nShellProps): ReactNode;
|
|
1192
|
+
/**
|
|
1193
|
+
* `I18nShell`'s own reader — shell-owned, not a `08-core-hooks.md` catalog
|
|
1194
|
+
* entry (no chrome-translation hook is named there; component authoring,
|
|
1195
|
+
* this hook's eventual consumer, is out of scope for this phase). Mirrors
|
|
1196
|
+
* `BrandShell`'s `useKaafilShareMeta()` in kind: a read-only hook a shell
|
|
1197
|
+
* exposes alongside itself. Throws outside the provider tree, the same
|
|
1198
|
+
* "no provider, no default" contract every `/core` context follows.
|
|
1199
|
+
*/
|
|
1200
|
+
declare function useKaafilChrome(): I18nContextValue;
|
|
1201
|
+
|
|
1202
|
+
interface KaafilSessionProbeProps {
|
|
1203
|
+
/** The host's own intended environment — cross-checked against the
|
|
1204
|
+
* opened credential's actual `environment` to catch "wrong environment"/
|
|
1205
|
+
* "test key on live" (`shells/00-kaafil-uikit-provider.md`). */
|
|
1206
|
+
readonly expectedEnvironment?: 'live' | 'test';
|
|
1207
|
+
/**
|
|
1208
|
+
* Per-instance `--kf-*` token overrides (`00-decisions.md` U-019). Layer-3
|
|
1209
|
+
* tokens are per component TYPE; this is how one INSTANCE differs from
|
|
1210
|
+
* another without restyling every sibling.
|
|
1211
|
+
*/
|
|
1212
|
+
readonly style?: KaafilTokenOverrides;
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* When green: a card naming credential kind, environment, and status. When
|
|
1216
|
+
* red: names exactly ONE of the five documented failure modes this probe
|
|
1217
|
+
* exists to distinguish — this build can only detect the two that are
|
|
1218
|
+
* directly readable off `useSession()`'s derived shape (an expired/rejected
|
|
1219
|
+
* credential, and an environment mismatch); "clock skew" and "CORS" need a
|
|
1220
|
+
* live network probe this component does not attempt on its own, so they
|
|
1221
|
+
* are named here as documented, undetected-by-this-build failure modes
|
|
1222
|
+
* rather than silently omitted from the contract.
|
|
1223
|
+
*/
|
|
1224
|
+
declare function KaafilSessionProbe({ expectedEnvironment, style, }: KaafilSessionProbeProps): ReactNode;
|
|
1225
|
+
|
|
1226
|
+
interface OfflineShellProps {
|
|
1227
|
+
readonly storage: KaafilStorageAdapter;
|
|
1228
|
+
readonly blob?: {
|
|
1229
|
+
readonly uploader: BlobUploader;
|
|
1230
|
+
readonly source: BlobSource;
|
|
1231
|
+
};
|
|
1232
|
+
readonly conflictResolver?: ConflictResolver;
|
|
1233
|
+
readonly readEntity?: EntityReader;
|
|
1234
|
+
/** Escalation-tier override — see `shells/03-offline-shell.md`'s own
|
|
1235
|
+
* warning about two concurrently-open credentials sharing one browser's
|
|
1236
|
+
* storage. Defaults to a scope derived from persona + agencyRef, never
|
|
1237
|
+
* the credential secret itself. */
|
|
1238
|
+
readonly scope?: string;
|
|
1239
|
+
readonly children?: ReactNode;
|
|
1240
|
+
}
|
|
1241
|
+
/**
|
|
1242
|
+
* Opens the one `OfflineEngine` for the open session's credential, once
|
|
1243
|
+
* `SessionShell`'s credential exists — `OpenOfflineOptions` cannot be shaped
|
|
1244
|
+
* before that (`shells/README.md §2` row 6's rationale). Closes the previous
|
|
1245
|
+
* engine and opens a fresh one on a genuine credential change (a different
|
|
1246
|
+
* agency, a re-minted share token); an ordinary silent token rotation never
|
|
1247
|
+
* reaches this effect at all (`shells/03-offline-shell.md`'s "Credential
|
|
1248
|
+
* binding and credential change" section).
|
|
1249
|
+
*/
|
|
1250
|
+
declare function OfflineShell({ storage, blob, conflictResolver, readEntity, scope, children, }: OfflineShellProps): ReactNode;
|
|
1251
|
+
|
|
1252
|
+
interface ThemeShellProps {
|
|
1253
|
+
readonly theme?: 'light' | 'dark' | 'system';
|
|
1254
|
+
readonly density?: 'compact' | 'default' | 'comfortable';
|
|
1255
|
+
readonly children?: ReactNode;
|
|
1256
|
+
}
|
|
1257
|
+
/**
|
|
1258
|
+
* Resolves theme/density synchronously, during render — not behind a
|
|
1259
|
+
* `useEffect`, so there is no theme-loading flash for a descendant to
|
|
1260
|
+
* observe (`05-theme-shell.md`'s "no theme-loading state" contract). Only
|
|
1261
|
+
* `theme="system"` needs a live subscription, to follow the OS preference
|
|
1262
|
+
* across a change while mounted; an explicit `"light"`/`"dark"` is used
|
|
1263
|
+
* immediately and never touches `matchMedia` at all.
|
|
1264
|
+
*/
|
|
1265
|
+
declare function ThemeShell({ theme, density, children }: ThemeShellProps): ReactNode;
|
|
1266
|
+
|
|
1267
|
+
export { type AddTravellerNoteInput, type AgencyAdminMeReady, type AgencyAdminMeResult, type AgencyManagerProfileResult, type AgencyScopedParams, AppShell, type AppShellFamily, type AppShellFrame, type AppShellProps, type BlobStatusResult, type BlockerDeepLink, type BookingsReady, BrandShell, type BrandShellProps, CLOSEOUT_ACTION_TAB, type CapabilityStatusesResult, CapabilityTriple, type CloseoutActionKey, type CloseoutBlockerKey, type ConfigDocument, ConfigShell, type ConfigShellProps, ConflictRecord, type ConflictsResult, type CreateRegistryOptions, type DeepLinkParams, type DefaultCapabilityViews, DomainHookResult, ErrorClassification, ErrorShell, type ErrorShellClassification, type ErrorShellFallbackContext, type ErrorShellProps, type FeedbackNpsReady, type FeedbackNpsScope, HostCssCompatibilityProbe, type HostCssHazard, I18nShell, type I18nShellProps, type JourneyResult, type KaafilBrandAssets, KaafilSessionProbe, type KaafilSessionProbeProps, type KaafilTripTabKey, KaafilUIKitProvider, type KaafilUIKitProviderCredential, type KaafilUIKitProviderCredentialProps, type KaafilUIKitProviderProps, type ManagerAgencyProfileRead, type ManagersResult, NotImplementedError, type OfflineMutationConfig, type OfflineMutationResult, type OfflineMutationStatus, OfflineShell, type OfflineShellProps, type OutboxStatusOptions, type OutboxStatusResult, type Persona, type Registry, type ResolveBlockerInput, type ServerTimeApi, SessionShell, type SessionShellCredential, type SessionShellProps, type SessionState, type ShareFormAnswer, type ShareFormListItem, type ShareFormWriteInput, type ShareFormsListStatus, type ShareFormsResult, type ShareFormsWriteStatus, type ShareLinkRow, type ShareLinksResult, type ShareMeta, type ShareParams, type ShareSectionKey, type ShareSections, type ShareSnapshotOptions, type ShareSnapshotResult, type ShareSnapshotTrip, type SnapshotEntityResult, type SnapshotListResult, StalenessState, type TelemetryEvent, TelemetryShell, type TelemetryShellProps, ThemeShell, type ThemeShellProps, type TravellerFormResponseRow, type TravellerProfileRead, type TravellerProfileResult, type TreksReady, type TripManagerRow, type TripScopedParams, createRegistry, fromSearchParams, isTripTabKey, resolveBlockerDeepLink, toSearchParams, useAgencyAdminMe, useAgencyManagerProfile, useBlobStatus, useBookings, useCapabilities, useCapability, useCapabilityStatuses, useConflicts, useDefaultCapabilityViews, useFeedbackNps, useJourney, useKaafilBrand, useKaafilChrome, useKaafilShareMeta, useManagers, useOfflineEngine, useOfflineEvent, useOfflineMutation, useOutboxStatus, usePersona, useResolvedSetting, useServerTime, useSession, useShareForms, useShareLinks, useShareSnapshot, useSnapshotEntity, useSnapshotList, useStaleness, useTravellerFormResponses, useTravellerProfile, useTreks };
|