@everfur/sdk 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/CHANGELOG.md +648 -1
  2. package/README.md +58 -23
  3. package/consent/package.json +8 -0
  4. package/dist/Chat-DPUD6dnc.d.cts +128 -0
  5. package/dist/Chat-DwAC2vhB.d.ts +128 -0
  6. package/dist/DepthViews-DNEM96Se.d.ts +16 -0
  7. package/dist/DepthViews-DP0R-DhB.d.cts +19 -0
  8. package/dist/DepthViews-D_3hl4xk.d.ts +19 -0
  9. package/dist/DepthViews-DbFhR4Du.d.cts +16 -0
  10. package/dist/ErrorPolicyPort-CNf4uQZP.d.cts +22 -0
  11. package/dist/ErrorPolicyPort-CwbfmxzJ.d.ts +22 -0
  12. package/dist/{EverfurResult-D92-uL82.d.cts → EverfurResult-DN9pL2Ab.d.cts} +11 -10
  13. package/dist/{EverfurResult-D92-uL82.d.ts → EverfurResult-DN9pL2Ab.d.ts} +11 -10
  14. package/dist/{PhotoController-BItt5M7u.d.cts → PhotoController-3l7MT9jA.d.cts} +1 -1
  15. package/dist/{PhotoController-D8zMTdcW.d.ts → PhotoController-vzY5bfY_.d.ts} +1 -1
  16. package/dist/animations/index.cjs +1 -1997
  17. package/dist/animations/index.d.cts +35 -35
  18. package/dist/animations/index.d.ts +35 -35
  19. package/dist/animations/index.js +1 -1972
  20. package/dist/attachments-5NeobOCd.d.ts +256 -0
  21. package/dist/attachments-Bw3iMQgu.d.ts +146 -0
  22. package/dist/attachments-CQgFrEQ7.d.cts +146 -0
  23. package/dist/attachments-D8T5re7e.d.cts +256 -0
  24. package/dist/casesRepository-ClLv6qMl.d.ts +188 -0
  25. package/dist/casesRepository-DHwtGRYY.d.cts +188 -0
  26. package/dist/chat/index.cjs +1 -1170
  27. package/dist/chat/index.d.cts +31 -53
  28. package/dist/chat/index.d.ts +31 -53
  29. package/dist/chat/index.js +1 -1167
  30. package/dist/client/index.cjs +9 -2315
  31. package/dist/client/index.d.cts +77 -15
  32. package/dist/client/index.d.ts +77 -15
  33. package/dist/client/index.js +9 -2215
  34. package/dist/{config-CiJ0PVBB.d.ts → config-CzTZGlfF.d.cts} +63 -25
  35. package/dist/{config-BSjBdxrZ.d.cts → config-DW60uRb9.d.ts} +63 -25
  36. package/dist/consent/index.cjs +1 -0
  37. package/dist/consent/index.d.cts +33 -0
  38. package/dist/consent/index.d.ts +33 -0
  39. package/dist/consent/index.js +1 -0
  40. package/dist/context-DXhqHlPU.d.ts +159 -0
  41. package/dist/context-XvTzq1tE.d.cts +159 -0
  42. package/dist/copy-Mjoo91aS.d.ts +198 -0
  43. package/dist/copy-bKDNigLb.d.cts +198 -0
  44. package/dist/core/index.cjs +13 -3175
  45. package/dist/core/index.d.cts +58 -12
  46. package/dist/core/index.d.ts +58 -12
  47. package/dist/core/index.js +13 -3163
  48. package/dist/depth-CErXCU8J.d.cts +502 -0
  49. package/dist/depth-DjDcJ6kH.d.ts +502 -0
  50. package/dist/entitlementRepository-DKdXFgTo.d.cts +698 -0
  51. package/dist/entitlementRepository-DSbzuyAW.d.ts +698 -0
  52. package/dist/{identity-DK9zORrG.d.ts → identity-BMx2SUOM.d.ts} +19 -6
  53. package/dist/{identity-Brl-lDd6.d.cts → identity-DI4eVx9S.d.cts} +19 -6
  54. package/dist/{ids-CJ1S6adf.d.cts → ids-B2GAAifq.d.cts} +1 -1
  55. package/dist/{ids-CJ1S6adf.d.ts → ids-B2GAAifq.d.ts} +1 -1
  56. package/dist/index.cjs +12 -4488
  57. package/dist/index.d.cts +29 -121
  58. package/dist/index.d.ts +29 -121
  59. package/dist/index.js +12 -4464
  60. package/dist/models-B-Uh2LTf.d.ts +214 -0
  61. package/dist/models-D2EUxPZY.d.cts +214 -0
  62. package/dist/notifications/index.cjs +2 -0
  63. package/dist/notifications/index.d.cts +17 -0
  64. package/dist/notifications/index.d.ts +17 -0
  65. package/dist/notifications/index.js +2 -0
  66. package/dist/pets-CtQdRpWo.d.ts +92 -0
  67. package/dist/pets-aB8q0JyX.d.cts +92 -0
  68. package/dist/photo/index.cjs +1 -2189
  69. package/dist/photo/index.d.cts +6 -6
  70. package/dist/photo/index.d.ts +6 -6
  71. package/dist/photo/index.js +1 -2186
  72. package/dist/ports-BN6RHF9W.d.cts +48 -0
  73. package/dist/ports-BN6RHF9W.d.ts +48 -0
  74. package/dist/ports-DEBzEhbp.d.cts +386 -0
  75. package/dist/ports-DMolTRzU.d.ts +386 -0
  76. package/dist/profile-CSs1wlXT.d.cts +93 -0
  77. package/dist/profile-CSs1wlXT.d.ts +93 -0
  78. package/dist/records/depth/index.cjs +2 -0
  79. package/dist/records/depth/index.d.cts +13 -0
  80. package/dist/records/depth/index.d.ts +13 -0
  81. package/dist/records/depth/index.js +2 -0
  82. package/dist/records/index.cjs +3 -2839
  83. package/dist/records/index.d.cts +137 -203
  84. package/dist/records/index.d.ts +137 -203
  85. package/dist/records/index.js +3 -2833
  86. package/dist/requestFunnel-CjW7uDuA.d.ts +87 -0
  87. package/dist/requestFunnel-L-BQfi0z.d.cts +87 -0
  88. package/dist/{resolve-Dq_4_agU.d.ts → resolve-D4Ywz5OS.d.cts} +10 -4
  89. package/dist/{resolve-Dq_4_agU.d.cts → resolve-D4Ywz5OS.d.ts} +10 -4
  90. package/dist/{runtime-BgQnA594.d.cts → runtime-B8s-_hv8.d.cts} +134 -59
  91. package/dist/{runtime-CBA-LvdM.d.ts → runtime-BR9ysG0J.d.ts} +134 -59
  92. package/dist/server/events/index.cjs +2 -0
  93. package/dist/server/events/index.d.cts +550 -0
  94. package/dist/server/events/index.d.ts +550 -0
  95. package/dist/server/events/index.js +2 -0
  96. package/dist/server/index.cjs +2 -533
  97. package/dist/server/index.d.cts +73 -18
  98. package/dist/server/index.d.ts +73 -18
  99. package/dist/server/index.js +2 -530
  100. package/dist/species-BXAIMh7I.d.cts +9 -0
  101. package/dist/species-BXAIMh7I.d.ts +9 -0
  102. package/dist/televet/index.cjs +1 -0
  103. package/dist/televet/index.d.cts +60 -0
  104. package/dist/televet/index.d.ts +60 -0
  105. package/dist/televet/index.js +1 -0
  106. package/dist/testing/index.cjs +5 -823
  107. package/dist/testing/index.d.cts +17 -3
  108. package/dist/testing/index.d.ts +17 -3
  109. package/dist/testing/index.js +5 -820
  110. package/dist/testing/rn/index.cjs +1 -449
  111. package/dist/testing/rn/index.d.cts +17 -29
  112. package/dist/testing/rn/index.d.ts +17 -29
  113. package/dist/testing/rn/index.js +1 -444
  114. package/dist/testing/web/index.cjs +1 -0
  115. package/dist/testing/web/index.d.cts +131 -0
  116. package/dist/testing/web/index.d.ts +131 -0
  117. package/dist/testing/web/index.js +1 -0
  118. package/dist/timelineRows-CaohZzXS.d.cts +19 -0
  119. package/dist/timelineRows-DZed6dAM.d.ts +19 -0
  120. package/dist/typeStyle-0TydiZ1w.d.cts +19 -0
  121. package/dist/typeStyle-CWMsoe6b.d.ts +19 -0
  122. package/dist/uploadTransport-D0M0T4hN.d.ts +38 -0
  123. package/dist/uploadTransport-DKJHs3Yj.d.cts +38 -0
  124. package/dist/useRecordsDepth-BHBzJ76R.d.cts +237 -0
  125. package/dist/useRecordsDepth-BU-OhzH6.d.ts +237 -0
  126. package/dist/useVetVisit-Bc84hWUU.d.cts +187 -0
  127. package/dist/useVetVisit-CjmMa896.d.ts +187 -0
  128. package/dist/video/index.cjs +1 -1941
  129. package/dist/video/index.d.cts +4 -4
  130. package/dist/video/index.d.ts +4 -4
  131. package/dist/video/index.js +1 -1938
  132. package/dist/view-C3qPIXGX.d.cts +310 -0
  133. package/dist/view-DtSPYpKa.d.ts +310 -0
  134. package/dist/visitIntent-D7_yVp1I.d.cts +8 -0
  135. package/dist/visitIntent-D7_yVp1I.d.ts +8 -0
  136. package/dist/web/consent/index.cjs +1 -0
  137. package/dist/web/consent/index.d.cts +34 -0
  138. package/dist/web/consent/index.d.ts +34 -0
  139. package/dist/web/consent/index.js +1 -0
  140. package/dist/web/index.cjs +14 -0
  141. package/dist/web/index.d.cts +217 -0
  142. package/dist/web/index.d.ts +217 -0
  143. package/dist/web/index.js +14 -0
  144. package/dist/web/notifications/index.cjs +2 -0
  145. package/dist/web/notifications/index.d.cts +213 -0
  146. package/dist/web/notifications/index.d.ts +213 -0
  147. package/dist/web/notifications/index.js +2 -0
  148. package/dist/web/records/depth/index.cjs +2 -0
  149. package/dist/web/records/depth/index.d.cts +12 -0
  150. package/dist/web/records/depth/index.d.ts +12 -0
  151. package/dist/web/records/depth/index.js +2 -0
  152. package/dist/web/records/index.cjs +4 -0
  153. package/dist/web/records/index.d.cts +194 -0
  154. package/dist/web/records/index.d.ts +194 -0
  155. package/dist/web/records/index.js +4 -0
  156. package/dist/web/televet/index.cjs +1 -0
  157. package/dist/web/televet/index.d.cts +50 -0
  158. package/dist/web/televet/index.d.ts +50 -0
  159. package/dist/web/televet/index.js +1 -0
  160. package/notifications/package.json +8 -0
  161. package/package.json +197 -9
  162. package/records/depth/package.json +8 -0
  163. package/server/events/device-blocked.cjs +15 -0
  164. package/server/events/package.json +9 -0
  165. package/televet/package.json +8 -0
  166. package/testing/web/native-blocked.cjs +12 -0
  167. package/testing/web/package.json +8 -0
  168. package/web/consent/native-blocked.cjs +12 -0
  169. package/web/consent/package.json +8 -0
  170. package/web/native-blocked.cjs +12 -0
  171. package/web/notifications/native-blocked.cjs +12 -0
  172. package/web/notifications/package.json +8 -0
  173. package/web/package.json +8 -0
  174. package/web/records/depth/native-blocked.cjs +12 -0
  175. package/web/records/depth/package.json +8 -0
  176. package/web/records/native-blocked.cjs +12 -0
  177. package/web/records/package.json +8 -0
  178. package/web/televet/native-blocked.cjs +12 -0
  179. package/web/televet/package.json +8 -0
  180. package/dist/ChatController-CKdBvPj2.d.ts +0 -146
  181. package/dist/ChatController-CpUMvvZf.d.cts +0 -146
  182. package/dist/FilePort-BabWrv7I.d.cts +0 -22
  183. package/dist/FilePort-BabWrv7I.d.ts +0 -22
  184. package/dist/petsRepository-BEGb97M9.d.cts +0 -326
  185. package/dist/petsRepository-Bu18r2kK.d.ts +0 -326
  186. package/dist/requestFunnel-DuUH-kAe.d.cts +0 -28
  187. package/dist/requestFunnel-dio5OmR9.d.ts +0 -28
@@ -0,0 +1,237 @@
1
+ import { R as RecordsRequestId, P as PetRef } from './ids-B2GAAifq.cjs';
2
+ import { a5 as RecordsClinicSearchInput, a6 as RecordsClinicSearchPage, a7 as RecordsRecentClinicsInput, a8 as RecordsAuthorizationCopy, a9 as CreateClinicRequestInput, aa as RecordsSignatureUploadPolicy, l as RecordsClinic, O as RecordsClinicBatch, P as RecordsClinicBatchClient, m as RecordsDepthClient } from './depth-CErXCU8J.cjs';
3
+ import { c as EverfurResult, E as EverfurError } from './EverfurResult-DN9pL2Ab.cjs';
4
+ import { f as RecordsRequestGroupView, d as RecordsRequestView } from './models-D2EUxPZY.cjs';
5
+
6
+ interface RecordsClinicController {
7
+ searchClinics(input?: RecordsClinicSearchInput): Promise<EverfurResult<RecordsClinicSearchPage>>;
8
+ /** The clinics this member requested from before, most recent first: the picker's "recent" section. */
9
+ recentClinics(input?: RecordsRecentClinicsInput): Promise<EverfurResult<RecordsClinicSearchPage>>;
10
+ /** A multi-clinic batch's rollup and members. Not found until Everfur switches the multi-clinic flag on. */
11
+ getRequestGroup(requestGroupId: string): Promise<EverfurResult<RecordsRequestGroupView>>;
12
+ getAuthorizationCopy(): Promise<EverfurResult<RecordsAuthorizationCopy>>;
13
+ createClinicRequest(input: CreateClinicRequestInput): Promise<EverfurResult<RecordsRequestView>>;
14
+ retryRequest(id: RecordsRequestId): Promise<EverfurResult<RecordsRequestView>>;
15
+ revokeRequest(id: RecordsRequestId): Promise<EverfurResult<RecordsRequestView>>;
16
+ updateClinicEmail(id: RecordsRequestId, clinicEmail: string): Promise<EverfurResult<RecordsRequestView>>;
17
+ convertToUpload(id: RecordsRequestId): Promise<EverfurResult<RecordsRequestView>>;
18
+ /** Bytes are uploaded by the host directly to the returned multipart policy; never through the API. */
19
+ initiateSignatureUpload(fileSize: number): Promise<EverfurResult<RecordsSignatureUploadPolicy>>;
20
+ completeSignatureUpload(uploadId: string): Promise<EverfurResult<string>>;
21
+ }
22
+
23
+ /** The exact owner-visible scope at the moment the owner chooses to sign. */
24
+ interface RecordsSignatureContext {
25
+ readonly petRef: PetRef;
26
+ readonly petName: string;
27
+ readonly ownerName: string;
28
+ readonly clinicName: string;
29
+ readonly authorizationVersion: string;
30
+ readonly scopeText: string;
31
+ /** Cancel native capture/upload when the signed-in user or active pet changes. */
32
+ readonly signal: AbortSignal;
33
+ }
34
+ /**
35
+ * A captured signature: a registered signature id (the PNG uploaded through the initiate/complete APIs, the
36
+ * consumer's own path, which keeps the bytes off the JSON body), or a small inline PNG (the built-in React
37
+ * Native pad's one-bit image, a few hundred bytes, under the platform's non-upload body cap).
38
+ */
39
+ type CapturedRecordsSignature = {
40
+ readonly signatureId: string;
41
+ readonly signaturePngBase64?: never;
42
+ } | {
43
+ readonly signatureId?: never;
44
+ readonly signaturePngBase64: string;
45
+ };
46
+ /**
47
+ * Capture explicitly at the moment the owner presses Send, after seeing the scope, and return the signature.
48
+ * null means the owner cancelled. Prefer the registered id for anything but a tiny PNG.
49
+ */
50
+ type CaptureRecordsSignature = (context: RecordsSignatureContext) => Promise<CapturedRecordsSignature | null>;
51
+ interface ClinicRequestBaseProps {
52
+ readonly petRef: PetRef;
53
+ /** Display name for this exact registered petRef; the server owns the final PDF identity. */
54
+ readonly petName: string;
55
+ /** Initial value only; the owner can visibly confirm or correct it before signing. */
56
+ readonly ownerName: string;
57
+ readonly onCaptureSignature?: CaptureRecordsSignature;
58
+ readonly onCreated?: (request: RecordsRequestView) => void;
59
+ readonly onClose?: () => void;
60
+ /** Host/test seam over the same signed-user controller contract. */
61
+ readonly controller?: RecordsClinicController;
62
+ }
63
+
64
+ /** One composed clinic of the batch (the consumer `ClinicRequestDraft`). */
65
+ interface ClinicDraft {
66
+ /** Stable local key for list rows and removal. */
67
+ readonly key: string;
68
+ /** The directory clinic, or null for an owner-typed clinic name. */
69
+ readonly clinic: RecordsClinic | null;
70
+ /** The owner-typed clinic name when `clinic` is null. */
71
+ readonly freeText: string | null;
72
+ /** The owner-supplied address, when the clinic needs one. */
73
+ readonly email: string;
74
+ /** Minted when the draft is added; a whole-batch retry replays it. */
75
+ readonly idempotencyKey: string;
76
+ }
77
+ interface ClinicBatchBaseProps {
78
+ readonly petRef: PetRef;
79
+ /** Display name for this exact registered petRef; the server owns the final PDF identity. */
80
+ readonly petName: string;
81
+ /** Initial value only; the owner can visibly confirm or correct it before signing. */
82
+ readonly ownerName: string;
83
+ readonly onCaptureSignature?: CaptureRecordsSignature;
84
+ /** Called once with the batch outcome (created and failed clinics alike). */
85
+ readonly onCreated?: (batch: RecordsClinicBatch) => void;
86
+ readonly onClose?: () => void;
87
+ /** Host/test seams over the same signed-user contracts. */
88
+ readonly controller?: RecordsClinicController;
89
+ readonly batchClient?: RecordsClinicBatchClient;
90
+ }
91
+ /**
92
+ * Turn the pad's inline PNG into a registered signature id, so the batch carries one small id per clinic rather
93
+ * than one PNG per clinic (the platform caps the inline bytes of a batch at one signature's worth, and the WAF
94
+ * caps the JSON body). The host supplies the byte transport; the RN and web hosts each have one.
95
+ */
96
+ type RegisterSignaturePng = (signaturePngBase64: string, signal: AbortSignal) => Promise<{
97
+ readonly signatureId: string;
98
+ }>;
99
+
100
+ type RecordsScreen = {
101
+ readonly name: 'dashboard';
102
+ } | {
103
+ readonly name: 'request';
104
+ readonly requestId: RecordsRequestId;
105
+ } | {
106
+ readonly name: 'timeline';
107
+ } | {
108
+ readonly name: 'record';
109
+ } | {
110
+ readonly name: 'document';
111
+ } | {
112
+ readonly name: 'contributions';
113
+ readonly docId: string;
114
+ } | {
115
+ readonly name: 'clinicPicker';
116
+ }
117
+ /**
118
+ * The multi-clinic composer (`EverfurClinicRequestBatch`). The consumer opens it as a SHEET from the full
119
+ * record screen's header (RequestFromClinicsAction.tsx); the SDK flow has no sheet layer of its own, so it is
120
+ * a screen of the same stack, pushed from the same control and popped by the same back.
121
+ */
122
+ | {
123
+ readonly name: 'clinicBatch';
124
+ } | {
125
+ readonly name: 'consent';
126
+ readonly clinic: ClinicDraft;
127
+ } | {
128
+ readonly name: 'upload';
129
+ };
130
+ interface RecordsNavState {
131
+ readonly stack: readonly RecordsScreen[];
132
+ }
133
+ type RecordsNavAction = {
134
+ readonly type: 'push';
135
+ readonly screen: RecordsScreen;
136
+ } | {
137
+ readonly type: 'pop';
138
+ } | {
139
+ readonly type: 'replace';
140
+ readonly screen: RecordsScreen;
141
+ } | {
142
+ readonly type: 'reset';
143
+ readonly screen: RecordsScreen;
144
+ }
145
+ /** The screen-declared edge: applies the consumer's push / replace / reset rule for the (from, to) pair. */
146
+ | {
147
+ readonly type: 'navigate';
148
+ readonly screen: RecordsScreen;
149
+ };
150
+ /** A one-screen stack at `initial` (the dashboard when omitted). */
151
+ declare function initialRecordsNav(initial?: RecordsScreen): RecordsNavState;
152
+ /** The screen on top of the stack (a stack is never empty). */
153
+ declare function currentRecordsScreen(state: RecordsNavState): RecordsScreen;
154
+ declare function pushRecordsNav(state: RecordsNavState, screen: RecordsScreen): RecordsNavState;
155
+ declare function replaceRecordsNav(state: RecordsNavState, screen: RecordsScreen): RecordsNavState;
156
+ declare function resetRecordsNav(screen: RecordsScreen): RecordsNavState;
157
+ /**
158
+ * Pop the top screen. On a one-screen stack the state is returned UNCHANGED with `handled:false`, so the RN
159
+ * flow's back handler can return `false` and let the host navigator handle the press.
160
+ */
161
+ declare function popRecordsNav(state: RecordsNavState): {
162
+ readonly state: RecordsNavState;
163
+ readonly handled: boolean;
164
+ };
165
+ /**
166
+ * The consumer's own transition rule for a screen-declared edge:
167
+ * - `dashboard` is the root: reaching it resets the stack (consent success `router.replace`s the dashboard,
168
+ * a published request pushes it; both end on one dashboard with nothing to pop back into);
169
+ * - `upload -> request` replaces (the upload screen's "Done" is a `router.replace`);
170
+ * - everything else pushes.
171
+ */
172
+ declare function transitionRecordsNav(state: RecordsNavState, to: RecordsScreen): RecordsNavState;
173
+ declare function recordsNavReducer(state: RecordsNavState, action: RecordsNavAction): RecordsNavState;
174
+
175
+ /** The entity a pill refers to: a BE-recognized `type` and `id`, plus compact display facts the host may pass on. */
176
+ interface RecordsAskEntityRef {
177
+ readonly type: string;
178
+ readonly id: string;
179
+ readonly payload?: Readonly<Record<string, string | number | boolean>>;
180
+ }
181
+ interface RecordsAsk {
182
+ readonly prompt: string;
183
+ readonly entityRef: RecordsAskEntityRef;
184
+ }
185
+ /** The host seam every Ask pill calls; pills render only when a host supplies it. */
186
+ type RecordsAskHandler = (prompt: string, entityRef: RecordsAskEntityRef) => void;
187
+
188
+ type ClinicLocation = NonNullable<RecordsClinicSearchInput['location']>;
189
+
190
+ type RecordsUrlKind = 'share_link' | 'record_pdf';
191
+ interface RecordsHostSeams {
192
+ /** Open a share link or the record PDF. Default: `Linking.openURL` on React Native, `window.open` on the web. */
193
+ readonly onOpenUrl?: (url: string, kind: RecordsUrlKind) => void | Promise<void>;
194
+ /** Copy a share link. Web default: `navigator.clipboard.writeText`; React Native has no default (see above). */
195
+ readonly onCopy?: (text: string) => Promise<void>;
196
+ /** The Ask pills' seed prompt and entity, for a host chat. Absent: no Ask pill renders. */
197
+ readonly onAsk?: RecordsAskHandler;
198
+ /** Biases the clinic search (the same input the clinic controller takes). */
199
+ readonly location?: ClinicLocation;
200
+ }
201
+ interface RecordsScreenBaseProps extends RecordsHostSeams {
202
+ readonly petRef: PetRef;
203
+ /** The pet's display name for headers and lead copy; absent, the consumer's own `your pet` forms. */
204
+ readonly petName?: string;
205
+ /** Called with the exact screen an edge leads to (see `navigation.ts`). Absent, a control that only navigates is hidden, never inert. */
206
+ readonly onNavigate?: (to: RecordsScreen) => void;
207
+ /** The header's back control; absent, no back control renders. */
208
+ readonly onBack?: () => void;
209
+ }
210
+
211
+ type RecordsDepthStatus = 'loading' | 'empty' | 'error' | 'populated';
212
+ /** One depth read as a render state. `withheld` (no consent, or a fail-closed parse) renders nothing. */
213
+ interface UseRecordsDepthState<T> {
214
+ readonly status: RecordsDepthStatus;
215
+ readonly value: T | null;
216
+ readonly error: EverfurError | null;
217
+ /**
218
+ * False once a read got the router's dark 404, which is how a tenant without `partner.records_full_depth_enabled`
219
+ * answers EVERY depth route. The state is then `empty` with no error, so the surface draws its own nothing
220
+ * instead of the generic failure leaf and its unusable `Try again`. True otherwise, including for a failure
221
+ * that never reached the server, which proves nothing about the tenant.
222
+ */
223
+ readonly available: boolean;
224
+ readonly refresh: () => void;
225
+ }
226
+ /** The signed member's depth client over the provider's auth; a surface with no user settles to accessDenied. */
227
+ declare function useEverfurRecordsDepthClient(): RecordsDepthClient;
228
+ /**
229
+ * Run one depth read for the scoped pet on mount, and again on `refresh`. `isEmpty` decides between `empty`
230
+ * and `populated`; a withheld answer is `populated` with `withheld:true`, which every depth surface renders as
231
+ * nothing (never a partial record).
232
+ */
233
+ declare function useRecordsDepthRead<T extends {
234
+ readonly withheld: boolean;
235
+ }>(petRef: PetRef, read: (client: RecordsDepthClient, petRef: PetRef) => Promise<EverfurResult<T>>, isEmpty: (value: T) => boolean, extraKey?: string): UseRecordsDepthState<T>;
236
+
237
+ export { transitionRecordsNav as A, type ClinicDraft as C, type RecordsAskEntityRef as R, type UseRecordsDepthState as U, type ClinicLocation as a, type RecordsAskHandler as b, type RecordsDepthStatus as c, type RecordsHostSeams as d, type RecordsScreen as e, type RecordsScreenBaseProps as f, type RecordsUrlKind as g, useRecordsDepthRead as h, type RecordsClinicController as i, type CaptureRecordsSignature as j, type ClinicRequestBaseProps as k, type ClinicBatchBaseProps as l, type CapturedRecordsSignature as m, type RecordsAsk as n, type RecordsNavAction as o, type RecordsNavState as p, type RecordsSignatureContext as q, type RegisterSignaturePng as r, currentRecordsScreen as s, initialRecordsNav as t, useEverfurRecordsDepthClient as u, popRecordsNav as v, pushRecordsNav as w, recordsNavReducer as x, replaceRecordsNav as y, resetRecordsNav as z };
@@ -0,0 +1,237 @@
1
+ import { R as RecordsRequestId, P as PetRef } from './ids-B2GAAifq.js';
2
+ import { a5 as RecordsClinicSearchInput, a6 as RecordsClinicSearchPage, a7 as RecordsRecentClinicsInput, a8 as RecordsAuthorizationCopy, a9 as CreateClinicRequestInput, aa as RecordsSignatureUploadPolicy, l as RecordsClinic, O as RecordsClinicBatch, P as RecordsClinicBatchClient, m as RecordsDepthClient } from './depth-DjDcJ6kH.js';
3
+ import { c as EverfurResult, E as EverfurError } from './EverfurResult-DN9pL2Ab.js';
4
+ import { f as RecordsRequestGroupView, d as RecordsRequestView } from './models-B-Uh2LTf.js';
5
+
6
+ interface RecordsClinicController {
7
+ searchClinics(input?: RecordsClinicSearchInput): Promise<EverfurResult<RecordsClinicSearchPage>>;
8
+ /** The clinics this member requested from before, most recent first: the picker's "recent" section. */
9
+ recentClinics(input?: RecordsRecentClinicsInput): Promise<EverfurResult<RecordsClinicSearchPage>>;
10
+ /** A multi-clinic batch's rollup and members. Not found until Everfur switches the multi-clinic flag on. */
11
+ getRequestGroup(requestGroupId: string): Promise<EverfurResult<RecordsRequestGroupView>>;
12
+ getAuthorizationCopy(): Promise<EverfurResult<RecordsAuthorizationCopy>>;
13
+ createClinicRequest(input: CreateClinicRequestInput): Promise<EverfurResult<RecordsRequestView>>;
14
+ retryRequest(id: RecordsRequestId): Promise<EverfurResult<RecordsRequestView>>;
15
+ revokeRequest(id: RecordsRequestId): Promise<EverfurResult<RecordsRequestView>>;
16
+ updateClinicEmail(id: RecordsRequestId, clinicEmail: string): Promise<EverfurResult<RecordsRequestView>>;
17
+ convertToUpload(id: RecordsRequestId): Promise<EverfurResult<RecordsRequestView>>;
18
+ /** Bytes are uploaded by the host directly to the returned multipart policy; never through the API. */
19
+ initiateSignatureUpload(fileSize: number): Promise<EverfurResult<RecordsSignatureUploadPolicy>>;
20
+ completeSignatureUpload(uploadId: string): Promise<EverfurResult<string>>;
21
+ }
22
+
23
+ /** The exact owner-visible scope at the moment the owner chooses to sign. */
24
+ interface RecordsSignatureContext {
25
+ readonly petRef: PetRef;
26
+ readonly petName: string;
27
+ readonly ownerName: string;
28
+ readonly clinicName: string;
29
+ readonly authorizationVersion: string;
30
+ readonly scopeText: string;
31
+ /** Cancel native capture/upload when the signed-in user or active pet changes. */
32
+ readonly signal: AbortSignal;
33
+ }
34
+ /**
35
+ * A captured signature: a registered signature id (the PNG uploaded through the initiate/complete APIs, the
36
+ * consumer's own path, which keeps the bytes off the JSON body), or a small inline PNG (the built-in React
37
+ * Native pad's one-bit image, a few hundred bytes, under the platform's non-upload body cap).
38
+ */
39
+ type CapturedRecordsSignature = {
40
+ readonly signatureId: string;
41
+ readonly signaturePngBase64?: never;
42
+ } | {
43
+ readonly signatureId?: never;
44
+ readonly signaturePngBase64: string;
45
+ };
46
+ /**
47
+ * Capture explicitly at the moment the owner presses Send, after seeing the scope, and return the signature.
48
+ * null means the owner cancelled. Prefer the registered id for anything but a tiny PNG.
49
+ */
50
+ type CaptureRecordsSignature = (context: RecordsSignatureContext) => Promise<CapturedRecordsSignature | null>;
51
+ interface ClinicRequestBaseProps {
52
+ readonly petRef: PetRef;
53
+ /** Display name for this exact registered petRef; the server owns the final PDF identity. */
54
+ readonly petName: string;
55
+ /** Initial value only; the owner can visibly confirm or correct it before signing. */
56
+ readonly ownerName: string;
57
+ readonly onCaptureSignature?: CaptureRecordsSignature;
58
+ readonly onCreated?: (request: RecordsRequestView) => void;
59
+ readonly onClose?: () => void;
60
+ /** Host/test seam over the same signed-user controller contract. */
61
+ readonly controller?: RecordsClinicController;
62
+ }
63
+
64
+ /** One composed clinic of the batch (the consumer `ClinicRequestDraft`). */
65
+ interface ClinicDraft {
66
+ /** Stable local key for list rows and removal. */
67
+ readonly key: string;
68
+ /** The directory clinic, or null for an owner-typed clinic name. */
69
+ readonly clinic: RecordsClinic | null;
70
+ /** The owner-typed clinic name when `clinic` is null. */
71
+ readonly freeText: string | null;
72
+ /** The owner-supplied address, when the clinic needs one. */
73
+ readonly email: string;
74
+ /** Minted when the draft is added; a whole-batch retry replays it. */
75
+ readonly idempotencyKey: string;
76
+ }
77
+ interface ClinicBatchBaseProps {
78
+ readonly petRef: PetRef;
79
+ /** Display name for this exact registered petRef; the server owns the final PDF identity. */
80
+ readonly petName: string;
81
+ /** Initial value only; the owner can visibly confirm or correct it before signing. */
82
+ readonly ownerName: string;
83
+ readonly onCaptureSignature?: CaptureRecordsSignature;
84
+ /** Called once with the batch outcome (created and failed clinics alike). */
85
+ readonly onCreated?: (batch: RecordsClinicBatch) => void;
86
+ readonly onClose?: () => void;
87
+ /** Host/test seams over the same signed-user contracts. */
88
+ readonly controller?: RecordsClinicController;
89
+ readonly batchClient?: RecordsClinicBatchClient;
90
+ }
91
+ /**
92
+ * Turn the pad's inline PNG into a registered signature id, so the batch carries one small id per clinic rather
93
+ * than one PNG per clinic (the platform caps the inline bytes of a batch at one signature's worth, and the WAF
94
+ * caps the JSON body). The host supplies the byte transport; the RN and web hosts each have one.
95
+ */
96
+ type RegisterSignaturePng = (signaturePngBase64: string, signal: AbortSignal) => Promise<{
97
+ readonly signatureId: string;
98
+ }>;
99
+
100
+ type RecordsScreen = {
101
+ readonly name: 'dashboard';
102
+ } | {
103
+ readonly name: 'request';
104
+ readonly requestId: RecordsRequestId;
105
+ } | {
106
+ readonly name: 'timeline';
107
+ } | {
108
+ readonly name: 'record';
109
+ } | {
110
+ readonly name: 'document';
111
+ } | {
112
+ readonly name: 'contributions';
113
+ readonly docId: string;
114
+ } | {
115
+ readonly name: 'clinicPicker';
116
+ }
117
+ /**
118
+ * The multi-clinic composer (`EverfurClinicRequestBatch`). The consumer opens it as a SHEET from the full
119
+ * record screen's header (RequestFromClinicsAction.tsx); the SDK flow has no sheet layer of its own, so it is
120
+ * a screen of the same stack, pushed from the same control and popped by the same back.
121
+ */
122
+ | {
123
+ readonly name: 'clinicBatch';
124
+ } | {
125
+ readonly name: 'consent';
126
+ readonly clinic: ClinicDraft;
127
+ } | {
128
+ readonly name: 'upload';
129
+ };
130
+ interface RecordsNavState {
131
+ readonly stack: readonly RecordsScreen[];
132
+ }
133
+ type RecordsNavAction = {
134
+ readonly type: 'push';
135
+ readonly screen: RecordsScreen;
136
+ } | {
137
+ readonly type: 'pop';
138
+ } | {
139
+ readonly type: 'replace';
140
+ readonly screen: RecordsScreen;
141
+ } | {
142
+ readonly type: 'reset';
143
+ readonly screen: RecordsScreen;
144
+ }
145
+ /** The screen-declared edge: applies the consumer's push / replace / reset rule for the (from, to) pair. */
146
+ | {
147
+ readonly type: 'navigate';
148
+ readonly screen: RecordsScreen;
149
+ };
150
+ /** A one-screen stack at `initial` (the dashboard when omitted). */
151
+ declare function initialRecordsNav(initial?: RecordsScreen): RecordsNavState;
152
+ /** The screen on top of the stack (a stack is never empty). */
153
+ declare function currentRecordsScreen(state: RecordsNavState): RecordsScreen;
154
+ declare function pushRecordsNav(state: RecordsNavState, screen: RecordsScreen): RecordsNavState;
155
+ declare function replaceRecordsNav(state: RecordsNavState, screen: RecordsScreen): RecordsNavState;
156
+ declare function resetRecordsNav(screen: RecordsScreen): RecordsNavState;
157
+ /**
158
+ * Pop the top screen. On a one-screen stack the state is returned UNCHANGED with `handled:false`, so the RN
159
+ * flow's back handler can return `false` and let the host navigator handle the press.
160
+ */
161
+ declare function popRecordsNav(state: RecordsNavState): {
162
+ readonly state: RecordsNavState;
163
+ readonly handled: boolean;
164
+ };
165
+ /**
166
+ * The consumer's own transition rule for a screen-declared edge:
167
+ * - `dashboard` is the root: reaching it resets the stack (consent success `router.replace`s the dashboard,
168
+ * a published request pushes it; both end on one dashboard with nothing to pop back into);
169
+ * - `upload -> request` replaces (the upload screen's "Done" is a `router.replace`);
170
+ * - everything else pushes.
171
+ */
172
+ declare function transitionRecordsNav(state: RecordsNavState, to: RecordsScreen): RecordsNavState;
173
+ declare function recordsNavReducer(state: RecordsNavState, action: RecordsNavAction): RecordsNavState;
174
+
175
+ /** The entity a pill refers to: a BE-recognized `type` and `id`, plus compact display facts the host may pass on. */
176
+ interface RecordsAskEntityRef {
177
+ readonly type: string;
178
+ readonly id: string;
179
+ readonly payload?: Readonly<Record<string, string | number | boolean>>;
180
+ }
181
+ interface RecordsAsk {
182
+ readonly prompt: string;
183
+ readonly entityRef: RecordsAskEntityRef;
184
+ }
185
+ /** The host seam every Ask pill calls; pills render only when a host supplies it. */
186
+ type RecordsAskHandler = (prompt: string, entityRef: RecordsAskEntityRef) => void;
187
+
188
+ type ClinicLocation = NonNullable<RecordsClinicSearchInput['location']>;
189
+
190
+ type RecordsUrlKind = 'share_link' | 'record_pdf';
191
+ interface RecordsHostSeams {
192
+ /** Open a share link or the record PDF. Default: `Linking.openURL` on React Native, `window.open` on the web. */
193
+ readonly onOpenUrl?: (url: string, kind: RecordsUrlKind) => void | Promise<void>;
194
+ /** Copy a share link. Web default: `navigator.clipboard.writeText`; React Native has no default (see above). */
195
+ readonly onCopy?: (text: string) => Promise<void>;
196
+ /** The Ask pills' seed prompt and entity, for a host chat. Absent: no Ask pill renders. */
197
+ readonly onAsk?: RecordsAskHandler;
198
+ /** Biases the clinic search (the same input the clinic controller takes). */
199
+ readonly location?: ClinicLocation;
200
+ }
201
+ interface RecordsScreenBaseProps extends RecordsHostSeams {
202
+ readonly petRef: PetRef;
203
+ /** The pet's display name for headers and lead copy; absent, the consumer's own `your pet` forms. */
204
+ readonly petName?: string;
205
+ /** Called with the exact screen an edge leads to (see `navigation.ts`). Absent, a control that only navigates is hidden, never inert. */
206
+ readonly onNavigate?: (to: RecordsScreen) => void;
207
+ /** The header's back control; absent, no back control renders. */
208
+ readonly onBack?: () => void;
209
+ }
210
+
211
+ type RecordsDepthStatus = 'loading' | 'empty' | 'error' | 'populated';
212
+ /** One depth read as a render state. `withheld` (no consent, or a fail-closed parse) renders nothing. */
213
+ interface UseRecordsDepthState<T> {
214
+ readonly status: RecordsDepthStatus;
215
+ readonly value: T | null;
216
+ readonly error: EverfurError | null;
217
+ /**
218
+ * False once a read got the router's dark 404, which is how a tenant without `partner.records_full_depth_enabled`
219
+ * answers EVERY depth route. The state is then `empty` with no error, so the surface draws its own nothing
220
+ * instead of the generic failure leaf and its unusable `Try again`. True otherwise, including for a failure
221
+ * that never reached the server, which proves nothing about the tenant.
222
+ */
223
+ readonly available: boolean;
224
+ readonly refresh: () => void;
225
+ }
226
+ /** The signed member's depth client over the provider's auth; a surface with no user settles to accessDenied. */
227
+ declare function useEverfurRecordsDepthClient(): RecordsDepthClient;
228
+ /**
229
+ * Run one depth read for the scoped pet on mount, and again on `refresh`. `isEmpty` decides between `empty`
230
+ * and `populated`; a withheld answer is `populated` with `withheld:true`, which every depth surface renders as
231
+ * nothing (never a partial record).
232
+ */
233
+ declare function useRecordsDepthRead<T extends {
234
+ readonly withheld: boolean;
235
+ }>(petRef: PetRef, read: (client: RecordsDepthClient, petRef: PetRef) => Promise<EverfurResult<T>>, isEmpty: (value: T) => boolean, extraKey?: string): UseRecordsDepthState<T>;
236
+
237
+ export { transitionRecordsNav as A, type ClinicDraft as C, type RecordsAskEntityRef as R, type UseRecordsDepthState as U, type ClinicLocation as a, type RecordsAskHandler as b, type RecordsDepthStatus as c, type RecordsHostSeams as d, type RecordsScreen as e, type RecordsScreenBaseProps as f, type RecordsUrlKind as g, useRecordsDepthRead as h, type RecordsClinicController as i, type CaptureRecordsSignature as j, type ClinicRequestBaseProps as k, type ClinicBatchBaseProps as l, type CapturedRecordsSignature as m, type RecordsAsk as n, type RecordsNavAction as o, type RecordsNavState as p, type RecordsSignatureContext as q, type RegisterSignaturePng as r, currentRecordsScreen as s, initialRecordsNav as t, useEverfurRecordsDepthClient as u, popRecordsNav as v, pushRecordsNav as w, recordsNavReducer as x, replaceRecordsNav as y, resetRecordsNav as z };
@@ -0,0 +1,187 @@
1
+ import { c as EverfurResult, E as EverfurError } from './EverfurResult-DN9pL2Ab.cjs';
2
+ import { P as PetRef } from './ids-B2GAAifq.cjs';
3
+ import { V as VetVisitIntent } from './visitIntent-D7_yVp1I.cjs';
4
+
5
+ /** What the hosted page will open for a handoff minted with `visitRef`: the platform's own echo. */
6
+ interface VetVisitHandoffVisit {
7
+ /** The visit reference the handoff was minted for, as you sent it. */
8
+ readonly visitRef: string;
9
+ /** What the hosted page opens for it. `visit` when you named no intent. */
10
+ readonly intent: VetVisitIntent;
11
+ }
12
+ /** A minted handoff. Open `url` once, promptly; it expires at `expiresAt` and is spent by the first use. */
13
+ interface VetVisitHandoff {
14
+ /** The hosted Everfur page with the single-use token in its fragment. Never log or persist it. */
15
+ readonly url: string;
16
+ /** ISO-8601 timestamp from the server; about 120 seconds after the mint. */
17
+ readonly expiresAt: string;
18
+ /**
19
+ * Present only when the handoff was minted with `returnTo`: the opaque id the user comes back with on your
20
+ * registered return destination. Keep it to match the return (`parseVetVisitReturn`). It says nothing about
21
+ * the visit.
22
+ */
23
+ readonly flowId?: string;
24
+ /**
25
+ * Present only when the handoff was minted with `visitRef`: what the hosted page will open, echoed by the
26
+ * platform from what it stored with the handoff. The reference never rides the URL, so this is the only
27
+ * place to read it back. Absent on an ordinary booking handoff.
28
+ */
29
+ readonly visit?: VetVisitHandoffVisit;
30
+ }
31
+ /** Where a vet visit was opened from. `'chat'`: the user chose it inside partner Chat, for the chat's pet. */
32
+ type VetVisitEntry = 'chat';
33
+ /** Optional handoff settings. */
34
+ interface VetVisitHandoffOptions {
35
+ /**
36
+ * The KEY of a return destination your tenant registered with Everfur. After the hosted visit flow the user
37
+ * can go back to that destination, and only that one. Never a URL.
38
+ */
39
+ readonly returnTo?: string | null;
40
+ /** `'chat'` when the user opened the visit from Chat. Requires the pet the chat is about. */
41
+ readonly entry?: VetVisitEntry | null;
42
+ /**
43
+ * TV-01. The reference of a visit this member ALREADY has (the `visit_ref` the `visit.*` events carry, and
44
+ * the one `parseEverfurNotification` reads off a tapped push). The handoff then opens that visit instead of
45
+ * the booking funnel. Everfur resolves it at the mint against this member's own live link, so a reference
46
+ * that is not theirs is refused with the same words a malformed one gets: a `validationFailed` you cannot
47
+ * probe for visits with. At most 64 characters.
48
+ */
49
+ readonly visitRef?: string | null;
50
+ /**
51
+ * What to open for `visitRef`: the visit itself, its call, its summary or its messages. Absent means
52
+ * `visit`. An intent with no `visitRef` is refused locally, because it names a route with nothing to route
53
+ * to. A tapped push already carries the right one on `target.intent`.
54
+ */
55
+ readonly intent?: VetVisitIntent | null;
56
+ }
57
+ /** The state preflight's whole answer. Nothing about the account, the plan or the price. */
58
+ interface VetVisitAvailability {
59
+ /** True when a vet visit can be booked for the state asked about. False for every other reason, alike. */
60
+ readonly available: boolean;
61
+ }
62
+ /** A partner app's return from the hosted visit flow, read by `parseVetVisitReturn`. Only the flow id. */
63
+ interface VetVisitReturn {
64
+ /** The opaque flow id from the handoff that led to this return. */
65
+ readonly flowId: string;
66
+ }
67
+ /**
68
+ * The closed set a partner branches on, derived from the route's documented outcomes.
69
+ *
70
+ * - `sessionRequired`: the integration sent no signed session. Mint one on your backend
71
+ * (`@everfur/sdk/server` mintPartnerSession) and hand the token to `EverfurUser.getToken`.
72
+ * - `authRejected`: the session token was refused after the one refresh the SDK performs.
73
+ * - `accessDenied`: a signed session whose key or plan does not include vet visits.
74
+ * - `unavailable`: vet visits are off for this partner or for Everfur right now (the route answers 404).
75
+ * - `rateLimited`: this user or this partner has opened too many visits recently. Do not retry in a loop.
76
+ * - `sdkUpdateRequired`: the API refused this SDK version.
77
+ * - `invalidRequest`: the pet reference was refused (empty, or longer than 128 characters).
78
+ * - `network`: no response arrived (offline, DNS, timeout).
79
+ * - `serverError`: the API failed, or answered with something that is not a usable Everfur visit URL.
80
+ * - `popupBlocked`: web only. The browser refused to open the new tab.
81
+ * - `openFailed`: React Native only. The host could not open the URL.
82
+ * - `cancelled`: nothing to show. The visit tab was closed before it loaded, or the signed-in user changed
83
+ * while the handoff was being minted, so it was dropped rather than opened for the previous user.
84
+ * - `unknown`: anything else.
85
+ */
86
+ type VetVisitErrorReason = 'sessionRequired' | 'authRejected' | 'accessDenied' | 'unavailable' | 'rateLimited' | 'sdkUpdateRequired' | 'invalidRequest' | 'network' | 'serverError' | 'popupBlocked' | 'openFailed' | 'cancelled' | 'unknown';
87
+ /** Map a settled handoff failure to its closed reason. Total and pure. */
88
+ declare function vetVisitErrorReasonOf(error: EverfurError): VetVisitErrorReason;
89
+ /** Mints handoffs for the current session. Built by `useVetVisit`; injectable for tests. */
90
+ interface VetVisitController {
91
+ /**
92
+ * Mint one handoff. Optional `petRef` scopes the visit to the partner's pet, shown to the user after
93
+ * sign-in. `options` names a registered return destination and where the visit was opened from. Settles;
94
+ * never throws; never retries.
95
+ */
96
+ createHandoff(petRef?: PetRef | null, options?: VetVisitHandoffOptions): Promise<EverfurResult<VetVisitHandoff>>;
97
+ /**
98
+ * Ask whether a vet visit is available for a US state (for example `'CA'`). Settles. An injected controller
99
+ * without it is treated as unavailable wherever the hook needs the answer.
100
+ */
101
+ checkAvailability?(state: string): Promise<EverfurResult<VetVisitAvailability>>;
102
+ /** True only while Everfur has the vet entry inside Chat switched on. Never throws; any failure is false. */
103
+ chatEntryOpen?(): Promise<boolean>;
104
+ }
105
+ /**
106
+ * Read an Everfur return off the URL your registered return destination was opened with. Returns the opaque
107
+ * flow id you received from the handoff, or null for any URL that does not carry exactly one well-formed
108
+ * Everfur flow id in its query. It carries nothing about the visit, the pet or the account.
109
+ */
110
+ declare function parseVetVisitReturn(url: string): VetVisitReturn | null;
111
+
112
+ /** `idle` before a tap and after a successful open; `opening` while the handoff is minted; `error` after a failure. */
113
+ type VetVisitStatus = 'idle' | 'opening' | 'error';
114
+ /** What one `open()` call settled to. The URL is deliberately absent. */
115
+ type VetVisitOpenResult = {
116
+ readonly opened: true;
117
+ readonly flowId?: string;
118
+ } | {
119
+ readonly opened: false;
120
+ readonly reason: VetVisitErrorReason;
121
+ readonly error: EverfurError | null;
122
+ };
123
+ /** Options for `useVetVisit`. */
124
+ interface UseVetVisitOptions {
125
+ /** The partner's pet reference to scope the visit to. `open(petRef)` overrides it per call. */
126
+ readonly petRef?: PetRef | null;
127
+ /** Host/test seam: inject a controller instead of building one from the provider's session. */
128
+ readonly controller?: VetVisitController;
129
+ /**
130
+ * The KEY of a return destination your tenant registered with Everfur. The visit can then send the user back
131
+ * to it, and `open()` settles with the `flowId` that return will carry.
132
+ */
133
+ readonly returnTo?: string | null;
134
+ /**
135
+ * The user's US state (for example `'CA'`). When set, `available` stays false until Everfur confirms a visit
136
+ * is available there, so the entry is never shown to a user who could not book.
137
+ */
138
+ readonly usState?: string | null;
139
+ /**
140
+ * `'chat'` for the entry inside Chat. `available` then also needs Everfur's chat entry switch and a pet (the
141
+ * one the chat is about); the visit itself is the same hosted visit.
142
+ */
143
+ readonly entry?: VetVisitEntry | null;
144
+ }
145
+ /** What `useVetVisit` returns. The handoff URL is never part of it. */
146
+ interface UseVetVisitState {
147
+ /**
148
+ * True only when the server grants the `televet` capability AND the provider is scoped to a user. A handoff
149
+ * is minted from the user's session, so a publishable-key-only context could only ever spend a blank tab on
150
+ * a `sessionRequired` failure. A surface renders nothing otherwise.
151
+ */
152
+ readonly available: boolean;
153
+ /** True while the capability verdict is still resolving. */
154
+ readonly isPending: boolean;
155
+ /** Where the last `open()` is: idle, opening, or failed. */
156
+ readonly status: VetVisitStatus;
157
+ /** The settled failure of the last `open()`, or null. `error.displayMessage` is safe to show. */
158
+ readonly error: EverfurError | null;
159
+ /** The closed reason for the last failure, or null. */
160
+ readonly errorReason: VetVisitErrorReason | null;
161
+ /**
162
+ * Mint a handoff and open the hosted Everfur visit. Call it directly from a press or click handler. A second
163
+ * call while one is in flight returns the same promise rather than minting a second handoff.
164
+ */
165
+ open(petRef?: PetRef | null): Promise<VetVisitOpenResult>;
166
+ /**
167
+ * TV-01. Open a visit this member ALREADY has, instead of the booking funnel: the recap of a finished
168
+ * visit, the thread the vet wrote in, the call a reminder is for. `visitRef` is the reference the
169
+ * `visit.*` events carry, and `intent` is what to open for it (`visit` when omitted).
170
+ *
171
+ * Hand it what a tapped push gave you, unchanged:
172
+ * ```ts
173
+ * const n = parseEverfurNotification(response);
174
+ * if (n?.target.kind === 'visit' && n.target.intent !== null) {
175
+ * await visit.openVisit(n.target.visitRef, n.target.intent);
176
+ * }
177
+ * ```
178
+ * A `null` intent on a target means the visit is over without happening (cancelled, missed): there is
179
+ * nothing left to open, so call `open()` to book a new one instead.
180
+ *
181
+ * Everfur resolves the reference at the mint against this member's own visits, so one that is not theirs
182
+ * settles `invalidRequest` and opens nothing. Shares the single-flight rule with `open`.
183
+ */
184
+ openVisit(visitRef: string, intent?: VetVisitIntent | null): Promise<VetVisitOpenResult>;
185
+ }
186
+
187
+ export { type UseVetVisitOptions as U, type VetVisitEntry as V, type UseVetVisitState as a, type VetVisitErrorReason as b, type VetVisitController as c, type VetVisitAvailability as d, type VetVisitHandoff as e, type VetVisitHandoffOptions as f, type VetVisitHandoffVisit as g, type VetVisitOpenResult as h, type VetVisitReturn as i, type VetVisitStatus as j, parseVetVisitReturn as p, vetVisitErrorReasonOf as v };