@everfur/sdk 0.1.1 → 0.4.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.
- package/CHANGELOG.md +703 -4
- package/README.md +63 -23
- package/consent/package.json +8 -0
- package/dist/Chat-BZZ-Py5l.d.ts +128 -0
- package/dist/Chat-Dq4fffIO.d.cts +128 -0
- package/dist/DepthViews-BG3E25MD.d.ts +16 -0
- package/dist/DepthViews-B_hIypI6.d.cts +19 -0
- package/dist/DepthViews-CL75jyRA.d.cts +16 -0
- package/dist/DepthViews-CkYri51q.d.ts +19 -0
- package/dist/ErrorPolicyPort-CNf4uQZP.d.cts +22 -0
- package/dist/ErrorPolicyPort-CwbfmxzJ.d.ts +22 -0
- package/dist/{EverfurResult-D92-uL82.d.cts → EverfurResult-DN9pL2Ab.d.cts} +11 -10
- package/dist/{EverfurResult-D92-uL82.d.ts → EverfurResult-DN9pL2Ab.d.ts} +11 -10
- package/dist/{PhotoController-BItt5M7u.d.cts → PhotoController-3l7MT9jA.d.cts} +1 -1
- package/dist/{PhotoController-D8zMTdcW.d.ts → PhotoController-vzY5bfY_.d.ts} +1 -1
- package/dist/animations/index.cjs +1 -1997
- package/dist/animations/index.d.cts +35 -35
- package/dist/animations/index.d.ts +35 -35
- package/dist/animations/index.js +1 -1972
- package/dist/attachments-BorG422I.d.cts +146 -0
- package/dist/attachments-BrUWQYNK.d.ts +257 -0
- package/dist/attachments-D_SECjr1.d.cts +257 -0
- package/dist/attachments-DpldrvIW.d.ts +146 -0
- package/dist/bookingCopy-CqtDYvCR.d.ts +732 -0
- package/dist/bookingCopy-SREvkG19.d.cts +732 -0
- package/dist/branding-CsRdeNwK.d.cts +566 -0
- package/dist/branding-CsRdeNwK.d.ts +566 -0
- package/dist/callCopy-DoQKG3-L.d.cts +40 -0
- package/dist/callCopy-DoQKG3-L.d.ts +40 -0
- package/dist/casesRepository-DwtZVsbj.d.cts +51 -0
- package/dist/casesRepository-v6QczS9N.d.ts +51 -0
- package/dist/chat/index.cjs +1 -1170
- package/dist/chat/index.d.cts +32 -53
- package/dist/chat/index.d.ts +32 -53
- package/dist/chat/index.js +1 -1167
- package/dist/client/index.cjs +9 -2315
- package/dist/client/index.d.cts +80 -16
- package/dist/client/index.d.ts +80 -16
- package/dist/client/index.js +9 -2215
- package/dist/{config-CiJ0PVBB.d.ts → config--Wu1Umhd.d.cts} +64 -26
- package/dist/{config-BSjBdxrZ.d.cts → config-C7eb_IMD.d.ts} +64 -26
- package/dist/consent/index.cjs +1 -0
- package/dist/consent/index.d.cts +33 -0
- package/dist/consent/index.d.ts +33 -0
- package/dist/consent/index.js +1 -0
- package/dist/context-CL3lyuy1.d.cts +159 -0
- package/dist/context-CahAEha8.d.ts +159 -0
- package/dist/copy-DdVFDL01.d.ts +198 -0
- package/dist/copy-UeUJVk8X.d.cts +198 -0
- package/dist/core/index.cjs +13 -3178
- package/dist/core/index.d.cts +164 -29
- package/dist/core/index.d.ts +164 -29
- package/dist/core/index.js +13 -3166
- package/dist/depth-D5HwcvKC.d.cts +533 -0
- package/dist/depth-DvPwPuT_.d.ts +533 -0
- package/dist/entitlementRepository-B7egEdW6.d.ts +43 -0
- package/dist/entitlementRepository-BpJ7tiwl.d.cts +43 -0
- package/dist/{identity-Brl-lDd6.d.cts → identity-C2-08BZW.d.cts} +20 -7
- package/dist/{identity-DK9zORrG.d.ts → identity-CEi9GRFZ.d.ts} +20 -7
- package/dist/{ids-CJ1S6adf.d.cts → ids-B2GAAifq.d.cts} +1 -1
- package/dist/{ids-CJ1S6adf.d.ts → ids-B2GAAifq.d.ts} +1 -1
- package/dist/index.cjs +12 -4494
- package/dist/index.d.cts +30 -121
- package/dist/index.d.ts +30 -121
- package/dist/index.js +12 -4470
- package/dist/models-B-Uh2LTf.d.ts +214 -0
- package/dist/models-D2EUxPZY.d.cts +214 -0
- package/dist/notifications/index.cjs +2 -0
- package/dist/notifications/index.d.cts +17 -0
- package/dist/notifications/index.d.ts +17 -0
- package/dist/notifications/index.js +2 -0
- package/dist/optionalModule-DbJmsq5f.d.cts +21 -0
- package/dist/optionalModule-DbJmsq5f.d.ts +21 -0
- package/dist/pets-DJv2sj2H.d.ts +92 -0
- package/dist/pets-JVCXgRgR.d.cts +92 -0
- package/dist/petsRepository-B_gKbAzJ.d.cts +142 -0
- package/dist/petsRepository-Bk6GDwLs.d.ts +142 -0
- package/dist/photo/index.cjs +1 -2189
- package/dist/photo/index.d.cts +6 -6
- package/dist/photo/index.d.ts +6 -6
- package/dist/photo/index.js +1 -2186
- package/dist/ports-BN6RHF9W.d.cts +48 -0
- package/dist/ports-BN6RHF9W.d.ts +48 -0
- package/dist/ports-BY2ph0_y.d.cts +376 -0
- package/dist/ports-D7YW8qz9.d.ts +376 -0
- package/dist/profile-CSs1wlXT.d.cts +93 -0
- package/dist/profile-CSs1wlXT.d.ts +93 -0
- package/dist/records/depth/index.cjs +2 -0
- package/dist/records/depth/index.d.cts +13 -0
- package/dist/records/depth/index.d.ts +13 -0
- package/dist/records/depth/index.js +2 -0
- package/dist/records/index.cjs +3 -2839
- package/dist/records/index.d.cts +137 -203
- package/dist/records/index.d.ts +137 -203
- package/dist/records/index.js +3 -2833
- package/dist/requestFunnel-BjDpqqvm.d.cts +110 -0
- package/dist/requestFunnel-DFMGcluw.d.ts +110 -0
- package/dist/{resolve-Dq_4_agU.d.ts → resolve-D4Ywz5OS.d.cts} +10 -4
- package/dist/{resolve-Dq_4_agU.d.cts → resolve-D4Ywz5OS.d.ts} +10 -4
- package/dist/{runtime-Bvr8yqXm.d.cts → runtimeTypes-gZEJu-da.d.cts} +104 -132
- package/dist/{runtime-BIYzf9cK.d.ts → runtimeTypes-w5KqBMcs.d.ts} +104 -132
- package/dist/server/events/index.cjs +2 -0
- package/dist/server/events/index.d.cts +550 -0
- package/dist/server/events/index.d.ts +550 -0
- package/dist/server/events/index.js +2 -0
- package/dist/server/index.cjs +2 -533
- package/dist/server/index.d.cts +73 -18
- package/dist/server/index.d.ts +73 -18
- package/dist/server/index.js +2 -530
- package/dist/species-BXAIMh7I.d.cts +9 -0
- package/dist/species-BXAIMh7I.d.ts +9 -0
- package/dist/televet/booking/index.cjs +1 -0
- package/dist/televet/booking/index.d.cts +294 -0
- package/dist/televet/booking/index.d.ts +294 -0
- package/dist/televet/booking/index.js +1 -0
- package/dist/televet/call/index.cjs +1 -0
- package/dist/televet/call/index.d.cts +141 -0
- package/dist/televet/call/index.d.ts +141 -0
- package/dist/televet/call/index.js +1 -0
- package/dist/televet/index.cjs +1 -0
- package/dist/televet/index.d.cts +142 -0
- package/dist/televet/index.d.ts +142 -0
- package/dist/televet/index.js +1 -0
- package/dist/testing/index.cjs +5 -823
- package/dist/testing/index.d.cts +18 -4
- package/dist/testing/index.d.ts +18 -4
- package/dist/testing/index.js +5 -820
- package/dist/testing/rn/index.cjs +1 -449
- package/dist/testing/rn/index.d.cts +18 -29
- package/dist/testing/rn/index.d.ts +18 -29
- package/dist/testing/rn/index.js +1 -444
- package/dist/testing/web/index.cjs +1 -0
- package/dist/testing/web/index.d.cts +132 -0
- package/dist/testing/web/index.d.ts +132 -0
- package/dist/testing/web/index.js +1 -0
- package/dist/timelineRows-C15jxFFH.d.ts +19 -0
- package/dist/timelineRows-odO8g9r2.d.cts +19 -0
- package/dist/typeStyle-CKqVYD6L.d.cts +111 -0
- package/dist/typeStyle-DmoyacDG.d.ts +111 -0
- package/dist/uploadTransport-D0M0T4hN.d.ts +38 -0
- package/dist/uploadTransport-DKJHs3Yj.d.cts +38 -0
- package/dist/useRecordsDepth-C6rjEaLn.d.cts +237 -0
- package/dist/useRecordsDepth-crhBllQK.d.ts +237 -0
- package/dist/useVetVisit-Bc84hWUU.d.cts +187 -0
- package/dist/useVetVisit-CjmMa896.d.ts +187 -0
- package/dist/video/index.cjs +1 -1941
- package/dist/video/index.d.cts +4 -4
- package/dist/video/index.d.ts +4 -4
- package/dist/video/index.js +1 -1938
- package/dist/view-Bxwxp4xD.d.ts +310 -0
- package/dist/view-DyitEO0m.d.cts +310 -0
- package/dist/visitIntent-D7_yVp1I.d.cts +8 -0
- package/dist/visitIntent-D7_yVp1I.d.ts +8 -0
- package/dist/web/consent/index.cjs +1 -0
- package/dist/web/consent/index.d.cts +34 -0
- package/dist/web/consent/index.d.ts +34 -0
- package/dist/web/consent/index.js +1 -0
- package/dist/web/index.cjs +14 -0
- package/dist/web/index.d.cts +218 -0
- package/dist/web/index.d.ts +218 -0
- package/dist/web/index.js +14 -0
- package/dist/web/notifications/index.cjs +2 -0
- package/dist/web/notifications/index.d.cts +213 -0
- package/dist/web/notifications/index.d.ts +213 -0
- package/dist/web/notifications/index.js +2 -0
- package/dist/web/records/depth/index.cjs +2 -0
- package/dist/web/records/depth/index.d.cts +12 -0
- package/dist/web/records/depth/index.d.ts +12 -0
- package/dist/web/records/depth/index.js +2 -0
- package/dist/web/records/index.cjs +4 -0
- package/dist/web/records/index.d.cts +285 -0
- package/dist/web/records/index.d.ts +285 -0
- package/dist/web/records/index.js +4 -0
- package/dist/web/televet/booking/index.cjs +1 -0
- package/dist/web/televet/booking/index.d.cts +349 -0
- package/dist/web/televet/booking/index.d.ts +349 -0
- package/dist/web/televet/booking/index.js +1 -0
- package/dist/web/televet/call/index.cjs +1 -0
- package/dist/web/televet/call/index.d.cts +142 -0
- package/dist/web/televet/call/index.d.ts +142 -0
- package/dist/web/televet/call/index.js +1 -0
- package/dist/web/televet/index.cjs +1 -0
- package/dist/web/televet/index.d.cts +136 -0
- package/dist/web/televet/index.d.ts +136 -0
- package/dist/web/televet/index.js +1 -0
- package/notifications/package.json +8 -0
- package/package.json +266 -10
- package/records/depth/package.json +8 -0
- package/server/events/device-blocked.cjs +15 -0
- package/server/events/package.json +9 -0
- package/televet/booking/package.json +8 -0
- package/televet/call/package.json +8 -0
- package/televet/package.json +8 -0
- package/testing/web/native-blocked.cjs +12 -0
- package/testing/web/package.json +8 -0
- package/web/consent/native-blocked.cjs +12 -0
- package/web/consent/package.json +8 -0
- package/web/native-blocked.cjs +12 -0
- package/web/notifications/native-blocked.cjs +12 -0
- package/web/notifications/package.json +8 -0
- package/web/package.json +8 -0
- package/web/records/depth/native-blocked.cjs +12 -0
- package/web/records/depth/package.json +8 -0
- package/web/records/native-blocked.cjs +12 -0
- package/web/records/package.json +8 -0
- package/web/televet/booking/native-blocked.cjs +12 -0
- package/web/televet/booking/package.json +8 -0
- package/web/televet/call/native-blocked.cjs +12 -0
- package/web/televet/call/package.json +8 -0
- package/web/televet/native-blocked.cjs +12 -0
- package/web/televet/package.json +8 -0
- package/dist/ChatController-CKdBvPj2.d.ts +0 -146
- package/dist/ChatController-CpUMvvZf.d.cts +0 -146
- package/dist/FilePort-BabWrv7I.d.cts +0 -22
- package/dist/FilePort-BabWrv7I.d.ts +0 -22
- package/dist/petsRepository-BEGb97M9.d.cts +0 -326
- package/dist/petsRepository-Bu18r2kK.d.ts +0 -326
- package/dist/requestFunnel-DuUH-kAe.d.cts +0 -28
- package/dist/requestFunnel-dio5OmR9.d.ts +0 -28
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { C as ClientBranding, E as EverfurThemeInput, a as EverfurTheme, b as EverfurFontWeight, c as EverfurFontFaceKey } from './branding-CsRdeNwK.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Overlay `b` onto `base`, field by field: a non-null branding field WINS; a null field KEEPS the base. A
|
|
5
|
+
* valid brightness re-selects the matching compiled palette (light/dark); an invalid/absent brightness leaves
|
|
6
|
+
* the base palette untouched. Slots merge per slot, per key. Returns a NEW deeply-frozen theme; `base` and `b`
|
|
7
|
+
* are never mutated.
|
|
8
|
+
*
|
|
9
|
+
* The name is historical (the server was once the only overlay); `resolveTheme` applies it twice, server then
|
|
10
|
+
* client, which is how the client wins per field. NOTE: foreground legibility (onPrimary/onAccent, the slot
|
|
11
|
+
* guard) and URL hardening are applied by `resolveTheme`, the total entry point. Call this directly only when
|
|
12
|
+
* you will finalize the result yourself.
|
|
13
|
+
*/
|
|
14
|
+
declare function withServerBranding(base: EverfurTheme, b: ClientBranding | null): EverfurTheme;
|
|
15
|
+
/**
|
|
16
|
+
* Inputs to the total theme resolve. All optional; `resolveTheme(undefined)` yields the compiled Everfur
|
|
17
|
+
* default. Merge order: compiled default <- server branding (render_hints) <- client theme prop, per field, with
|
|
18
|
+
* the tenant's locked fields and the attribution kept from the server (see `resolveTheme`).
|
|
19
|
+
*/
|
|
20
|
+
interface ResolveThemeInput {
|
|
21
|
+
/** Server-driven branding from the live entitlements render_hints (the tenant's console branding). */
|
|
22
|
+
readonly branding?: ClientBranding | null;
|
|
23
|
+
/**
|
|
24
|
+
* The clamped client `theme` prop. It WINS per cosmetic field over the server branding, except the fields the
|
|
25
|
+
* server lists in `locked_fields`. Its hidePoweredBy is IGNORED: whether the Everfur attribution shows is
|
|
26
|
+
* decided by server branding alone.
|
|
27
|
+
*/
|
|
28
|
+
readonly clientOverride?: ClientBranding | null;
|
|
29
|
+
/**
|
|
30
|
+
* The device color scheme (useColorScheme / `prefers-color-scheme`). Read ONLY when the settled brightness is
|
|
31
|
+
* `auto` (an explicit opt-in); with no brightness set anywhere the theme is light, as Everfur's own apps are.
|
|
32
|
+
*/
|
|
33
|
+
readonly colorScheme?: 'light' | 'dark' | null;
|
|
34
|
+
/** AccessibilityInfo reduced-motion / `prefers-reduced-motion`: collapses the motion tokens. */
|
|
35
|
+
readonly reducedMotion?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The user's text scale as the host reads it (React Native: `PixelRatio.getFontScale()`; the browser: the
|
|
38
|
+
* browser's default font size over 16px). Floored at `TEXT_SCALE_FLOOR`; absent or junk reads as 1. Flowing
|
|
39
|
+
* content follows it uncapped; each chrome tier follows it up to that tier's cap (`type.scaleCaps`).
|
|
40
|
+
*/
|
|
41
|
+
readonly textScale?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Multiply the type sizes by the effective scale, per tier (`type.size` for content, `type.tierSizes` for every
|
|
44
|
+
* tier). A browser host passes true (CSS px do not follow the user's setting on their own); a React Native host
|
|
45
|
+
* leaves it false and lets the platform scale every Text natively, capped per tier by `maxFontSizeMultiplier`.
|
|
46
|
+
*/
|
|
47
|
+
readonly scaleTypeSizes?: boolean;
|
|
48
|
+
/** The user asked for more contrast (`prefers-contrast: more`): the palette is derived by `deriveHighContrast`. */
|
|
49
|
+
readonly highContrast?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* The family the platform's generic mono keyword (`SYSTEM_MONO_FAMILY`) maps to on this host. React Native on iOS
|
|
52
|
+
* has no family named `monospace` (a Text asking for it renders proportional, and the legacy architecture
|
|
53
|
+
* red-boxes in development), so the React Native host passes `Menlo` there. Applied to the compiled default mono
|
|
54
|
+
* only: a partner's own mono face is never touched. Absent or blank, the keyword stands (the web maps it to its
|
|
55
|
+
* mono stack in CSS).
|
|
56
|
+
*/
|
|
57
|
+
readonly platformMonoFamily?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Whether a family name is registered with the platform, when the host can tell: true or false, else null. A
|
|
60
|
+
* NAMED face (one per-weight name, rendered without a weight) that the host reports unregistered falls back to
|
|
61
|
+
* the platform font of its group WITH its numeric weight, so medium and bold survive instead of every weight
|
|
62
|
+
* collapsing to the platform's regular. Only named faces are asked about; a throw reads as null.
|
|
63
|
+
*/
|
|
64
|
+
readonly isFontRegistered?: (family: string) => boolean | null;
|
|
65
|
+
}
|
|
66
|
+
/** The smallest effective text scale the resolver will report (a device may ask for less; the surfaces stop here). */
|
|
67
|
+
declare const TEXT_SCALE_FLOOR = 0.5;
|
|
68
|
+
/**
|
|
69
|
+
* Resolve the final, legible, deeply-frozen theme. Never throws, never returns null/transparent.
|
|
70
|
+
*
|
|
71
|
+
* PRECEDENCE (per field, owner decision of 18 September 2026; the same rule EFBackend render_hint_fold states):
|
|
72
|
+
* a field in `locked_fields` (plus `hide_powered_by` always) is server-wins; every other cosmetic field is
|
|
73
|
+
* client-wins.
|
|
74
|
+
* - A server branding with an unknown `schema_version` is dropped whole (default plus client theme).
|
|
75
|
+
* - `hide_powered_by`, and every name the server lists in `locked_fields`, are SERVER-WINS: the client's value
|
|
76
|
+
* for such a field is discarded before the merge, so the server's value or the compiled default stands.
|
|
77
|
+
* `slots` in the list locks every slot; `slots.<name>` locks one.
|
|
78
|
+
* - Every other cosmetic field is CLIENT-WINS: the client `theme` prop overrides the console value, and the
|
|
79
|
+
* console fills the fields the prop leaves unset. Brightness is settled the same way; set nowhere, it is
|
|
80
|
+
* LIGHT (owner decision OD28: Everfur's own apps are light-only), and `auto` follows the device scheme.
|
|
81
|
+
* - Slots overlay slot by slot (a named slot replaces the one below it whole) in the same order, after the
|
|
82
|
+
* field precedence.
|
|
83
|
+
* Then the total-resolve guarantees: onPrimary/onAccent via WCAG, the slot contrast guard, https-only logo/font
|
|
84
|
+
* URLs, a non-empty displayName, the text scale (floored; tiered caps on the chrome), motion collapsed under reduced
|
|
85
|
+
* motion, and the high-contrast derivation when the user asked for it.
|
|
86
|
+
*/
|
|
87
|
+
declare function resolveTheme(input?: ResolveThemeInput): EverfurTheme;
|
|
88
|
+
/**
|
|
89
|
+
* The console's preview helper: resolve a draft branding exactly as the device would, from the raw shapes (the
|
|
90
|
+
* partner's `theme` prop and the server-shaped branding object the console is about to publish), with the device
|
|
91
|
+
* inputs of the preview. Pure and total: any shape is tolerated, nothing throws.
|
|
92
|
+
*/
|
|
93
|
+
declare function previewTheme(input: EverfurThemeInput | null, hints: unknown, options?: Omit<ResolveThemeInput, 'branding' | 'clientOverride'>): EverfurTheme;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The text style a surface spreads for one face. `fontWeight` is present ONLY for a base family (the platform
|
|
97
|
+
* font, the legacy `font_family`, or a `fonts` name repeated across weights); a named face carries its weight
|
|
98
|
+
* itself. The regular mono face carries no weight (code renders in the regular mono face); its medium and bold
|
|
99
|
+
* twins (`monoMedium`, `monoBold`) take theirs when the mono family is a base family.
|
|
100
|
+
*/
|
|
101
|
+
interface EverfurFaceStyle {
|
|
102
|
+
readonly fontFamily: string;
|
|
103
|
+
readonly fontWeight?: EverfurFontWeight;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The family (and, for a base family, the numeric weight) of one face of the theme. Spread it into a style:
|
|
107
|
+
* `{ ...face(theme, 'bold'), fontSize: theme.type.size.body }`. Pure and total over any resolved theme.
|
|
108
|
+
*/
|
|
109
|
+
declare function face(theme: EverfurTheme, weight: EverfurFontFaceKey): EverfurFaceStyle;
|
|
110
|
+
|
|
111
|
+
export { type EverfurFaceStyle as E, type ResolveThemeInput as R, TEXT_SCALE_FLOOR as T, face as f, previewTheme as p, resolveTheme as r, withServerBranding as w };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { F as FileHandle, U as UploadTransport } from './ports-BN6RHF9W.js';
|
|
2
|
+
|
|
3
|
+
/** The subset of `fetch` this adapter calls. */
|
|
4
|
+
type RnRecordsUploadFetch = (url: string, init: {
|
|
5
|
+
readonly method: 'POST';
|
|
6
|
+
readonly body: FormData;
|
|
7
|
+
readonly credentials: 'omit';
|
|
8
|
+
readonly signal?: AbortSignal;
|
|
9
|
+
}) => Promise<{
|
|
10
|
+
readonly ok: boolean;
|
|
11
|
+
}>;
|
|
12
|
+
interface RnRecordsUploadTransportOptions {
|
|
13
|
+
/** Test seam: the fetch to use. Defaults to the global `fetch`. A host has no reason to set it. */
|
|
14
|
+
readonly fetch?: RnRecordsUploadFetch;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A host-supplied document picker for React Native records upload. Open your own picker (for example
|
|
18
|
+
* `expo-document-picker`, which the SDK does not depend on) limited to PDF, and resolve:
|
|
19
|
+
*
|
|
20
|
+
* - `null` when the user cancels,
|
|
21
|
+
* - one `FileHandle`, or SEVERAL (a multi-select pick): each with the local `uri`, `mimeType: 'application/pdf'`
|
|
22
|
+
* and `sizeBytes`. A batch uploads one file at a time with a live row per file; a non-PDF or oversize file in
|
|
23
|
+
* it is skipped with a reason before any request is made (the single-file path refuses it the same way).
|
|
24
|
+
* `name` is optional, rendered in the rows locally, and never sent.
|
|
25
|
+
*/
|
|
26
|
+
type RecordsDocumentPicker = () => Promise<FileHandle | readonly FileHandle[] | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Create the React Native records upload transport. Pass it as `uploadTransport` on the `EverfurConfig`, or
|
|
29
|
+
* to `<EverfurRecords uploadTransport={...} />`:
|
|
30
|
+
*
|
|
31
|
+
* ```tsx
|
|
32
|
+
* const uploadTransport = createRnRecordsUploadTransport();
|
|
33
|
+
* <EverfurProvider config={{ publishableKey, apiBaseUrl, uploadTransport }} ...>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
declare function createRnRecordsUploadTransport(options?: RnRecordsUploadTransportOptions): UploadTransport;
|
|
37
|
+
|
|
38
|
+
export { type RecordsDocumentPicker as R, type RnRecordsUploadFetch as a, type RnRecordsUploadTransportOptions as b, createRnRecordsUploadTransport as c };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { F as FileHandle, U as UploadTransport } from './ports-BN6RHF9W.cjs';
|
|
2
|
+
|
|
3
|
+
/** The subset of `fetch` this adapter calls. */
|
|
4
|
+
type RnRecordsUploadFetch = (url: string, init: {
|
|
5
|
+
readonly method: 'POST';
|
|
6
|
+
readonly body: FormData;
|
|
7
|
+
readonly credentials: 'omit';
|
|
8
|
+
readonly signal?: AbortSignal;
|
|
9
|
+
}) => Promise<{
|
|
10
|
+
readonly ok: boolean;
|
|
11
|
+
}>;
|
|
12
|
+
interface RnRecordsUploadTransportOptions {
|
|
13
|
+
/** Test seam: the fetch to use. Defaults to the global `fetch`. A host has no reason to set it. */
|
|
14
|
+
readonly fetch?: RnRecordsUploadFetch;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A host-supplied document picker for React Native records upload. Open your own picker (for example
|
|
18
|
+
* `expo-document-picker`, which the SDK does not depend on) limited to PDF, and resolve:
|
|
19
|
+
*
|
|
20
|
+
* - `null` when the user cancels,
|
|
21
|
+
* - one `FileHandle`, or SEVERAL (a multi-select pick): each with the local `uri`, `mimeType: 'application/pdf'`
|
|
22
|
+
* and `sizeBytes`. A batch uploads one file at a time with a live row per file; a non-PDF or oversize file in
|
|
23
|
+
* it is skipped with a reason before any request is made (the single-file path refuses it the same way).
|
|
24
|
+
* `name` is optional, rendered in the rows locally, and never sent.
|
|
25
|
+
*/
|
|
26
|
+
type RecordsDocumentPicker = () => Promise<FileHandle | readonly FileHandle[] | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Create the React Native records upload transport. Pass it as `uploadTransport` on the `EverfurConfig`, or
|
|
29
|
+
* to `<EverfurRecords uploadTransport={...} />`:
|
|
30
|
+
*
|
|
31
|
+
* ```tsx
|
|
32
|
+
* const uploadTransport = createRnRecordsUploadTransport();
|
|
33
|
+
* <EverfurProvider config={{ publishableKey, apiBaseUrl, uploadTransport }} ...>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
declare function createRnRecordsUploadTransport(options?: RnRecordsUploadTransportOptions): UploadTransport;
|
|
37
|
+
|
|
38
|
+
export { type RecordsDocumentPicker as R, type RnRecordsUploadFetch as a, type RnRecordsUploadTransportOptions as b, createRnRecordsUploadTransport as c };
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { R as RecordsRequestId, P as PetRef } from './ids-B2GAAifq.cjs';
|
|
2
|
+
import { a6 as RecordsClinicSearchInput, a7 as RecordsClinicSearchPage, a8 as RecordsRecentClinicsInput, a9 as RecordsAuthorizationCopy, aa as CreateClinicRequestInput, ab as RecordsSignatureUploadPolicy, l as RecordsClinic, P as RecordsClinicBatch, Q as RecordsClinicBatchClient, m as RecordsDepthClient } from './depth-D5HwcvKC.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 { a6 as RecordsClinicSearchInput, a7 as RecordsClinicSearchPage, a8 as RecordsRecentClinicsInput, a9 as RecordsAuthorizationCopy, aa as CreateClinicRequestInput, ab as RecordsSignatureUploadPolicy, l as RecordsClinic, P as RecordsClinicBatch, Q as RecordsClinicBatchClient, m as RecordsDepthClient } from './depth-DvPwPuT_.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 };
|