@mindbill/react 0.7.0 → 0.9.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/README.md CHANGED
@@ -1,10 +1,60 @@
1
1
  # @mindbill/react
2
2
 
3
- Native React billing components plus wrappers for MindBill's secure hosted workflows. See the repository's [10-minute quickstart](https://github.com/incidentfox/mindbill-widgets#add-mindbill-billing-in-10-minutes).
3
+ Native React billing components and connected lifecycle hooks. Install with:
4
4
 
5
- Published on npm as [`@mindbill/react`](https://www.npmjs.com/package/@mindbill/react). Install it with `npm install @mindbill/react @mindbill/embed` or your preferred package manager.
5
+ ```bash
6
+ npm install @mindbill/react @mindbill/node
7
+ ```
8
+
9
+ ## Connected status
10
+
11
+ `ConnectedBillStatus` owns the status API call, loading and error states, session renewal, one-minute polling, and focus refresh.
12
+
13
+ ```tsx
14
+ import { ConnectedBillStatus } from "@mindbill/react";
15
+
16
+ <ConnectedBillStatus
17
+ billId={billId}
18
+ appearance={{ accentColor: "#32a9d6", textColor: "#203743" }}
19
+ actions={[
20
+ { id: "eor", label: "View EOR", onClick: openEor },
21
+ { id: "payment", label: "Post payment", onClick: postPayment, primary: true },
22
+ ]}
23
+ />
24
+ ```
25
+
26
+ Add one authenticated route to your app. It verifies that the signed-in user may access the bill, then mints an exact-origin, bill-scoped token. The Partner API key stays on the server.
27
+
28
+ ```ts
29
+ // app/api/mindbill/status-session/route.ts
30
+ import { mindbill } from "@/lib/mindbill";
31
+
32
+ export async function POST(request: Request) {
33
+ const user = await requireUser(request); // your existing auth
34
+ const { billId } = await request.json();
35
+ await requireBillAccess(user, billId); // your existing authorization
36
+
37
+ const session = await mindbill.createEmbedSession({
38
+ component: "bill-timeline",
39
+ billId,
40
+ allowedOrigin: new URL(request.url).origin,
41
+ expiresIn: 900,
42
+ });
43
+
44
+ return Response.json({
45
+ token: session.token,
46
+ expiresAt: session.expiresAt,
47
+ });
48
+ }
49
+ ```
50
+
51
+ Use `useBillStatus({ billId })` when you want to render your own UI. It returns `data`, `error`, `isLoading`, `isRefreshing`, and `refresh`. Use `createBillStatusClient` outside React.
52
+
53
+ This is the minimum safe browser integration. A permanent Partner API key must never enter frontend code. A completely serverless partner integration requires MindBill-hosted sign-in/SSO so MindBill can authenticate the end user itself.
54
+
55
+ ## Review and submit
6
56
 
7
- Use `BillReviewForm` when billing should feel like part of your product. Your server loads and mutates the review model with a short-lived MindBill session; the component remains controlled and never receives a Partner API key.
57
+ `BillReviewForm` is the native, controlled review surface. Known bill values and payer documents remain explicit and editable before submission.
8
58
 
9
59
  ```tsx
10
60
  import { BillReviewForm } from "@mindbill/react";
@@ -23,8 +73,7 @@ import { BillReviewForm } from "@mindbill/react";
23
73
  />
24
74
  ```
25
75
 
26
- Use `BillStatusSummary` for a compact lifecycle surface with age, last update, balance,
27
- and state-aware actions:
76
+ Use `BillStatusSummary` only when your application already owns status loading and wants a presentation-only component:
28
77
 
29
78
  ```tsx
30
79
  <BillStatusSummary
@@ -41,7 +90,6 @@ and state-aware actions:
41
90
  />
42
91
  ```
43
92
 
44
- `HostedBillReview` and `HostedBillTimeline` remain available when an origin-bound hosted
45
- flow is a better fit. Native and hosted UI paths use the same server API and bill ID.
93
+ `HostedBillReview` and `HostedBillTimeline` remain available when a hosted flow is a better fit. Native and hosted UI paths use the same bill ID.
46
94
 
47
95
  Never send a Partner API key or long-lived credential to React/browser code.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { MindBillAppearance, MindBillEventDetail, MindBillErrorDetail } from '@mindbill/embed';
2
2
  export { MindBillAppearance, MindBillErrorDetail, MindBillEventDetail } from '@mindbill/embed';
3
- import { CSSProperties, ReactElement } from 'react';
3
+ import { CSSProperties, ReactElement, ReactNode } from 'react';
4
4
 
5
5
  type BillReviewDocumentType = "final_report" | "letter_of_attestation" | "proof_of_service" | "form_122" | "return_to_work_voucher" | "w9" | "medical_records" | "appeal" | "other";
6
6
  type BillReviewBillingProvider = {
@@ -164,6 +164,188 @@ type BillStatusAction = {
164
164
  };
165
165
  declare function BillStatusSummary({ status, submittedAt, agingDays, updatedAt, totalCharge, totalPaid, balanceDue, actions, className, style, appearance }: BillStatusSummaryProps): ReactElement;
166
166
 
167
+ type BillStatusData = {
168
+ billId: string;
169
+ state: string;
170
+ nativeStatus: string;
171
+ submittedAt: string | null;
172
+ agingDays: number | null;
173
+ updatedAt: string | null;
174
+ totalCharge: number;
175
+ totalPaid: number;
176
+ balanceDue: number;
177
+ };
178
+ type BillStatusSession = {
179
+ token: string;
180
+ expiresAt?: string;
181
+ apiBaseUrl?: string;
182
+ };
183
+ type BillStatusSessionRequest = {
184
+ billId: string;
185
+ signal: AbortSignal;
186
+ };
187
+ type BillStatusSessionProvider = (request: BillStatusSessionRequest) => Promise<BillStatusSession>;
188
+ type BillStatusClientOptions = {
189
+ billId: string;
190
+ /** Same-origin route that mints a short-lived, bill-scoped browser session. */
191
+ sessionEndpoint?: string;
192
+ /** Advanced escape hatch for non-HTTP session exchange. */
193
+ getSession?: BillStatusSessionProvider;
194
+ apiBaseUrl?: string;
195
+ fetch?: typeof globalThis.fetch;
196
+ };
197
+ type BillStatusClient = {
198
+ getStatus: (signal?: AbortSignal) => Promise<BillStatusData>;
199
+ clearSession: () => void;
200
+ };
201
+ type UseBillStatusOptions = BillStatusClientOptions & {
202
+ refreshInterval?: number;
203
+ enabled?: boolean;
204
+ initialData?: BillStatusData | null;
205
+ };
206
+ type UseBillStatusResult = {
207
+ data: BillStatusData | null;
208
+ error: Error | null;
209
+ isLoading: boolean;
210
+ isRefreshing: boolean;
211
+ refresh: () => Promise<void>;
212
+ };
213
+ /**
214
+ * Browser-safe status client used by useBillStatus. It exchanges the user's
215
+ * authenticated same-origin session for a short-lived MindBill token, then
216
+ * reads status directly from MindBill. It never accepts a Partner API key.
217
+ */
218
+ declare function createBillStatusClient({ billId, sessionEndpoint, getSession, apiBaseUrl, fetch: fetchOverride, }: BillStatusClientOptions): BillStatusClient;
219
+ declare function useBillStatus({ billId, sessionEndpoint, getSession, apiBaseUrl, refreshInterval, enabled, initialData, fetch: fetchOverride, }: UseBillStatusOptions): UseBillStatusResult;
220
+ type ConnectedBillStatusProps = UseBillStatusOptions & {
221
+ actions?: BillStatusSummaryProps["actions"];
222
+ appearance?: BillStatusSummaryProps["appearance"];
223
+ className?: string;
224
+ style?: BillStatusSummaryProps["style"];
225
+ loadingFallback?: ReactNode;
226
+ errorFallback?: (error: Error, retry: () => Promise<void>) => ReactNode;
227
+ };
228
+ declare function ConnectedBillStatus({ actions, appearance, className, style, loadingFallback, errorFallback, ...options }: ConnectedBillStatusProps): ReactElement | null;
229
+
230
+ type BillLifecycleActionId = "edit_and_submit" | "correct_and_resubmit" | "second_review" | "independent_bill_review" | "view_eor" | "post_payment" | "close";
231
+ type BillLifecycleAction = {
232
+ id: BillLifecycleActionId;
233
+ label: string;
234
+ enabled: boolean;
235
+ primary?: boolean;
236
+ reason?: string;
237
+ };
238
+ type BillEorDocument = {
239
+ id: string;
240
+ filename: string;
241
+ description: string | null;
242
+ addedAt: string;
243
+ contentUrl: string;
244
+ };
245
+ type BillLifecycleData = BillReviewData & {
246
+ lifecycle: {
247
+ state: string;
248
+ nativeStatus: string;
249
+ actions: BillLifecycleAction[];
250
+ };
251
+ eors: BillEorDocument[];
252
+ };
253
+ type BillLifecycleSession = {
254
+ token: string;
255
+ expiresAt?: string;
256
+ apiBaseUrl?: string;
257
+ };
258
+ type BillLifecycleSessionRequest = {
259
+ billId: string;
260
+ component: "bill-review";
261
+ signal: AbortSignal;
262
+ };
263
+ type BillLifecycleSessionProvider = (request: BillLifecycleSessionRequest) => Promise<BillLifecycleSession>;
264
+ type CloseBillInput = {
265
+ reason: string;
266
+ };
267
+ type PostBillPaymentInput = {
268
+ amount: number;
269
+ method: "check" | "eft";
270
+ checkNumber?: string;
271
+ depositDate: string;
272
+ note?: string;
273
+ };
274
+ type SubmitSecondReviewInput = {
275
+ reason: string;
276
+ payerClaimControlNumber: string;
277
+ disputedAmount: number | undefined;
278
+ attachmentIds: string[];
279
+ route: BillSubmissionRoute;
280
+ };
281
+ type BillLifecycleClientOptions = {
282
+ billId: string;
283
+ /** Same-origin server route that mints a short-lived, bill-scoped session. */
284
+ sessionEndpoint?: string | undefined;
285
+ /** Advanced escape hatch for a custom session exchange. */
286
+ getSession?: BillLifecycleSessionProvider | undefined;
287
+ apiBaseUrl?: string | undefined;
288
+ fetch?: typeof globalThis.fetch | undefined;
289
+ };
290
+ type BillLifecycleClient = {
291
+ getLifecycle: (signal?: AbortSignal) => Promise<BillLifecycleData>;
292
+ saveReview: (input: BillReviewSaveInput) => Promise<BillLifecycleData>;
293
+ submitBill: (input: BillReviewSaveInput, route: BillSubmissionRoute) => Promise<BillLifecycleData>;
294
+ addAttachment: (file: File, documentType: BillReviewDocumentType, description?: string) => Promise<BillLifecycleData>;
295
+ removeAttachment: (attachmentId: string) => Promise<BillLifecycleData>;
296
+ getAttachment: (attachmentId: string) => Promise<Blob>;
297
+ getEor: (documentId: string) => Promise<Blob>;
298
+ closeBill: (input: CloseBillInput) => Promise<BillLifecycleData>;
299
+ postPayment: (input: PostBillPaymentInput) => Promise<BillLifecycleData>;
300
+ submitSecondReview: (input: SubmitSecondReviewInput) => Promise<BillLifecycleData>;
301
+ startCorrection: () => Promise<{
302
+ replacementBillId: string;
303
+ data: BillLifecycleData;
304
+ }>;
305
+ clearSession: () => void;
306
+ };
307
+ type UseBillLifecycleOptions = BillLifecycleClientOptions & {
308
+ refreshInterval?: number;
309
+ enabled?: boolean;
310
+ initialData?: BillLifecycleData | null;
311
+ onBillIdChange?: (billId: string, previousBillId: string) => void | Promise<void>;
312
+ };
313
+ type UseBillLifecycleResult = {
314
+ billId: string;
315
+ data: BillLifecycleData | null;
316
+ error: Error | null;
317
+ isLoading: boolean;
318
+ isRefreshing: boolean;
319
+ isMutating: boolean;
320
+ refresh: () => Promise<void>;
321
+ saveReview: BillLifecycleClient["saveReview"];
322
+ submitBill: BillLifecycleClient["submitBill"];
323
+ addAttachment: BillLifecycleClient["addAttachment"];
324
+ removeAttachment: BillLifecycleClient["removeAttachment"];
325
+ openAttachment: (attachment: BillReviewAttachment) => Promise<void>;
326
+ openEor: (document: BillEorDocument) => Promise<void>;
327
+ closeBill: BillLifecycleClient["closeBill"];
328
+ postPayment: BillLifecycleClient["postPayment"];
329
+ submitSecondReview: BillLifecycleClient["submitSecondReview"];
330
+ startCorrection: () => Promise<BillLifecycleData>;
331
+ };
332
+ /**
333
+ * Browser-safe client for the complete bill lifecycle. The only long-lived
334
+ * secret remains on the partner server; this client uses a short-lived,
335
+ * origin-bound session scoped to one bill.
336
+ */
337
+ declare function createBillLifecycleClient({ billId, sessionEndpoint, getSession, apiBaseUrl, fetch: fetchOverride, }: BillLifecycleClientOptions): BillLifecycleClient;
338
+ declare function useBillLifecycle({ billId: providedBillId, sessionEndpoint, getSession, apiBaseUrl, refreshInterval, enabled, initialData, onBillIdChange, fetch: fetchOverride, }: UseBillLifecycleOptions): UseBillLifecycleResult;
339
+ type ConnectedBillLifecycleProps = UseBillLifecycleOptions & {
340
+ appearance?: MindBillAppearance;
341
+ className?: string;
342
+ style?: CSSProperties;
343
+ loadingFallback?: ReactNode;
344
+ errorFallback?: (error: Error, retry: () => Promise<void>) => ReactNode;
345
+ onChanged?: (data: BillLifecycleData) => void;
346
+ };
347
+ declare function ConnectedBillLifecycle({ appearance, className, style, loadingFallback, errorFallback, onChanged, ...options }: ConnectedBillLifecycleProps): ReactElement;
348
+
167
349
  type MindBillWidgetProps = {
168
350
  sessionToken: string;
169
351
  embedUrl: string;
@@ -184,4 +366,4 @@ declare const HostedBillFromReport: typeof MindBillBillFromReport;
184
366
  declare const HostedCollections: typeof MindBillCollections;
185
367
  declare const HostedOnboarding: typeof MindBillOnboarding;
186
368
 
187
- export { type BillReviewAttachment, type BillReviewBillingProvider, type BillReviewClinician, type BillReviewData, type BillReviewDocumentType, type BillReviewDraft, BillReviewForm, type BillReviewFormProps, type BillReviewLineItem, type BillReviewLocation, type BillReviewSaveInput, type BillStatusAction, BillStatusSummary, type BillStatusSummaryProps, type BillSubmissionRoute, HostedBillFromReport, HostedBillReview, HostedBillTimeline, HostedCollections, HostedOnboarding, MindBillBillFromReport, MindBillBillReview, MindBillBillTimeline, MindBillCollections, MindBillOnboarding, type MindBillWidgetProps, buildBillReviewSaveInput };
369
+ export { type BillEorDocument, type BillLifecycleAction, type BillLifecycleActionId, type BillLifecycleClient, type BillLifecycleClientOptions, type BillLifecycleData, type BillLifecycleSession, type BillLifecycleSessionProvider, type BillLifecycleSessionRequest, type BillReviewAttachment, type BillReviewBillingProvider, type BillReviewClinician, type BillReviewData, type BillReviewDocumentType, type BillReviewDraft, BillReviewForm, type BillReviewFormProps, type BillReviewLineItem, type BillReviewLocation, type BillReviewSaveInput, type BillStatusAction, type BillStatusClient, type BillStatusClientOptions, type BillStatusData, type BillStatusSession, type BillStatusSessionProvider, type BillStatusSessionRequest, BillStatusSummary, type BillStatusSummaryProps, type BillSubmissionRoute, type CloseBillInput, ConnectedBillLifecycle, type ConnectedBillLifecycleProps, ConnectedBillStatus, type ConnectedBillStatusProps, HostedBillFromReport, HostedBillReview, HostedBillTimeline, HostedCollections, HostedOnboarding, MindBillBillFromReport, MindBillBillReview, MindBillBillTimeline, MindBillCollections, MindBillOnboarding, type MindBillWidgetProps, type PostBillPaymentInput, type SubmitSecondReviewInput, type UseBillLifecycleOptions, type UseBillLifecycleResult, type UseBillStatusOptions, type UseBillStatusResult, buildBillReviewSaveInput, createBillLifecycleClient, createBillStatusClient, useBillLifecycle, useBillStatus };