@mindbill/react 0.22.0 → 0.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@ npm install @mindbill/react @mindbill/node
8
8
 
9
9
  ## Connected lifecycle
10
10
 
11
- `ConnectedBillLifecycle` starts after your server atomically creates and submits an immutable bill. It owns the submitted-to-closed progress rail, a read-only rendering of the exact submitted snapshot, server-owned human-readable history, packet download, EORs, payment posting, Second Bill Review, close, and reopen. The only persistent header action is **Download packet**; status-dependent actions appear in the details view when MindBill makes them available.
11
+ `ConnectedBillLifecycle` starts after `BillSubmissionForm` atomically submits an immutable bill. It owns the submitted-to-closed progress rail, a read-only rendering of the exact submitted snapshot, server-owned human-readable history, packet download, EORs, payment posting, Second Bill Review, close, and reopen. The only persistent header action is **Download packet**; status-dependent actions appear in the details view when MindBill makes them available.
12
12
 
13
13
  ```tsx
14
14
  import { ConnectedBillLifecycle } from "@mindbill/react";
@@ -132,7 +132,7 @@ Browser callbacks such as `onChanged` are for immediate UI, navigation, optimist
132
132
 
133
133
  `BillSubmissionForm` owns the complete pre-submission experience: the bill field schema, required-field rules and red asterisks, validation, service-line editing, source-document selection, PDF uploads, and the single Submit action. Its `bill` value is structurally identical to the server SDK's `CreateBillRequest`.
134
134
 
135
- The partner application only loads initial values and sends the component's immutable snapshot to its authenticated server route. Uploaded files stay in the browser until the user submits.
135
+ The partner application only loads initial values and mints a short-lived browser session. Uploaded files stay in the browser until the user submits; the component validates and sends the immutable snapshot and PDF bytes directly to MindBill.
136
136
 
137
137
  ```tsx
138
138
  import { BillSubmissionForm } from "@mindbill/react";
@@ -142,9 +142,7 @@ import { BillSubmissionForm } from "@mindbill/react";
142
142
  attachments={bootstrap.attachments}
143
143
  getSession={() => fetch("/api/mindbill/session", { method: "POST" }).then(r => r.json())}
144
144
  appearance={{ preset: "qme-companion" }}
145
- onSubmit={({ bill, sourceAttachmentIds, uploads }) =>
146
- submitBill({ bill, sourceAttachmentIds, uploads })
147
- }
145
+ onSubmitted={({ billId }) => saveLocalBillLink(billId)}
148
146
  />
149
147
  ```
150
148
 
@@ -159,11 +157,11 @@ The component includes the interaction model, not just the markup:
159
157
  - searchable workers-comp procedure/modifier controls, medical-legal fee-schedule amounts, totals, valid manual CPT/HCPCS entry, and an automatically maintained empty line;
160
158
  - removable source documents with new-tab previews, a locked auto-attached practice W-9, and a full-width click, panel-drop, or whole-page PDF upload area. Every visible source document is included until removed; uploaded PDFs do not require document-type tagging.
161
159
 
162
- Partners supply tenant-specific bootstrap data, one short-lived browser session callback, and the final server submission callback. Required fields, validation, ZIP lookup, ICD-10 and payer directories, service-line behavior, attachments, and submission UX stay inside `@mindbill/react`, so every integration receives the same billing workflow. Optional `diagnosisOptions`, `procedureOptions`, `modifierOptions`, and lookup callbacks extend or replace defaults when a partner has licensed or organization-specific data.
160
+ Partners supply tenant-specific bootstrap data, one short-lived browser session callback, and optionally an `onSubmitted` callback to persist the returned `billId`. Required fields, validation, ZIP lookup, ICD-10 and payer directories, service-line behavior, PDF encoding, wire-format serialization, atomic submission, attachments, and submission UX stay inside `@mindbill/react`, so every integration receives the same billing workflow. Optional `diagnosisOptions`, `procedureOptions`, `modifierOptions`, and lookup callbacks extend or replace defaults when a partner has licensed or organization-specific data.
163
161
 
164
162
  Validation is component-owned as well. A missing routing payer is highlighted immediately; Submit highlights every invalid control with a specific message, focuses and scrolls to the first problem, and continues validating as the user corrects the form.
165
163
 
166
- `BILL_SUBMISSION_REQUIRED_FIELDS` and `validateBillSubmission` expose the same contract for tests and non-visual integrations. The component never creates a draft; its callback fires only when the user submits a locally valid snapshot.
164
+ `BILL_SUBMISSION_REQUIRED_FIELDS` and `validateBillSubmission` expose the same contract for tests and non-visual integrations. The component never creates a draft; `onSubmitted` fires only after MindBill accepts a locally valid immutable snapshot. The legacy `onSubmit` escape hatch remains optional for unusual deployments, but connected integrations should omit it so the library owns the complete contract.
167
165
 
168
166
  `BillReviewForm` remains available for legacy integrations that already own a custom review model. New integrations should use `BillSubmissionForm`.
169
167
 
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { MindBillAppearance, MindBillEventDetail, MindBillErrorDetail } from '@mindbill/embed';
2
2
  export { MindBillAppearance, MindBillErrorDetail, MindBillEventDetail } from '@mindbill/embed';
3
3
  import { CSSProperties, ReactElement, ReactNode } from 'react';
4
- import { BillReviewData as BillReviewData$1, BillReviewAttachment as BillReviewAttachment$1, BillLifecycleSessionProvider, BillReviewPayer as BillReviewPayer$1, BillLifecycleAction, BillLifecycleDelivery, BillPaymentRecord, BillRemittanceSummary, BillLifecycleData, BillLifecycleClientOptions, BillLifecycleClient, BillEorDocument } from '@mindbill/browser';
5
- export { BillActivityRecord, BillEorDocument, BillLifecycleAction, BillLifecycleActionId, BillLifecycleClient, BillLifecycleClientOptions, BillLifecycleData, BillLifecycleDelivery, BillLifecycleSession, BillLifecycleSessionProvider, BillLifecycleSessionRequest, BillPaymentRecord, BillRemittanceSummary, CloseBillInput, PostBillPaymentInput, ReopenBillInput, SubmitSecondReviewInput, createBillLifecycleClient } from '@mindbill/browser';
4
+ import { BillReviewData as BillReviewData$1, BillReviewAttachment as BillReviewAttachment$1, BrowserBillSubmissionResult, BillLifecycleSessionProvider, BillReviewPayer as BillReviewPayer$1, BrowserBillSubmissionDocument, BillLifecycleAction, BillLifecycleDelivery, BillPaymentRecord, BillRemittanceSummary, BillLifecycleData, BillLifecycleClientOptions, BillLifecycleClient, BillEorDocument } from '@mindbill/browser';
5
+ export { BillActivityRecord, BillEorDocument, BillLifecycleAction, BillLifecycleActionId, BillLifecycleClient, BillLifecycleClientOptions, BillLifecycleData, BillLifecycleDelivery, BillLifecycleSession, BillLifecycleSessionProvider, BillLifecycleSessionRequest, BillPaymentRecord, BillRemittanceSummary, BrowserBillSubmissionResult, CloseBillInput, PostBillPaymentInput, ReopenBillInput, SubmitSecondReviewInput, createBillLifecycleClient } from '@mindbill/browser';
6
6
 
7
7
  type MindBillThemePreset = "mindbill" | "qme-companion" | "orange-bright" | "clinical-blue";
8
8
  type MindBillReactAppearance = MindBillAppearance & {
@@ -473,8 +473,14 @@ type BillSubmissionFormValue = {
473
473
  type BillSubmissionFormProps = {
474
474
  initialBill: BillSubmissionInput;
475
475
  attachments?: BillSubmissionSourceAttachment[];
476
- onSubmit: (value: BillSubmissionFormValue) => void | Promise<void>;
477
- /** Short-lived partner browser session. Enables the built-in canonical payer directory. */
476
+ /**
477
+ * Legacy custom submission escape hatch. Connected forms should omit this so
478
+ * the component owns PDF encoding and the Partner API wire contract.
479
+ */
480
+ onSubmit?: (value: BillSubmissionFormValue) => void | Promise<void>;
481
+ /** Called after the connected component atomically creates and submits the bill. */
482
+ onSubmitted?: (result: BrowserBillSubmissionResult) => void | Promise<void>;
483
+ /** Short-lived partner browser session. Enables reference data and direct submission. */
478
484
  getSession?: BillLifecycleSessionProvider;
479
485
  sessionEndpoint?: string;
480
486
  apiBaseUrl?: string;
@@ -498,11 +504,17 @@ type BillSubmissionFormProps = {
498
504
  */
499
505
  children?: ReactNode;
500
506
  };
501
- declare const BILL_SUBMISSION_REQUIRED_FIELDS: readonly ["patient.firstName", "patient.lastName", "patient.dateOfBirth", "patient.address.line1", "patient.address.city", "patient.address.state", "patient.address.postalCode", "claim.claimNumber", "claim.claimsAdministrator", "service.date", "serviceLines[].code", "serviceLines[].units"];
507
+ declare const BILL_SUBMISSION_REQUIRED_FIELDS: readonly ["patient.firstName", "patient.lastName", "patient.dateOfBirth", "patient.address.line1", "patient.address.city", "patient.address.state", "patient.address.postalCode", "claim.claimNumber", "claim.claimsAdministrator", "service.date", "diagnoses[]", "serviceLines[].code", "serviceLines[].units"];
502
508
  type BillSubmissionValidation = {
503
509
  valid: boolean;
504
510
  fieldErrors: Record<string, string>;
505
511
  };
512
+ declare function prepareBillSubmissionDocuments({ attachments, selectedIds, uploads, fetch: fetchOverride, }: {
513
+ attachments: BillSubmissionSourceAttachment[];
514
+ selectedIds: string[];
515
+ uploads: BillSubmissionUpload[];
516
+ fetch?: typeof globalThis.fetch;
517
+ }): Promise<BrowserBillSubmissionDocument[]>;
506
518
  declare function ensureTrailingBillSubmissionLine(lines: BillSubmissionInput["serviceLines"]): BillSubmissionInput["serviceLines"];
507
519
  declare function parseBillSubmissionDate(value: string): string | undefined;
508
520
  declare function formatBillSubmissionDate(value: string | null | undefined): string;
@@ -516,7 +528,7 @@ declare function BillSubmissionProvidersSection(): ReactElement;
516
528
  declare function BillSubmissionServiceLinesSection(): ReactElement;
517
529
  declare function BillSubmissionAttachmentsSection(): ReactElement;
518
530
  declare function BillSubmissionActions(): ReactElement;
519
- declare function BillSubmissionForm({ initialBill, attachments, onSubmit, getSession, sessionEndpoint, apiBaseUrl, fetch: fetchOverride, onSearchClaimsAdministrators, diagnosisOptions, onSearchDiagnoses, onLookupPostalCode, procedureOptions, modifierOptions, appearance, className, style, disabled, submitLabel, heading, description, children, }: BillSubmissionFormProps): ReactElement;
531
+ declare function BillSubmissionForm({ initialBill, attachments, onSubmit, onSubmitted, getSession, sessionEndpoint, apiBaseUrl, fetch: fetchOverride, onSearchClaimsAdministrators, diagnosisOptions, onSearchDiagnoses, onLookupPostalCode, procedureOptions, modifierOptions, appearance, className, style, disabled, submitLabel, heading, description, children, }: BillSubmissionFormProps): ReactElement;
520
532
 
521
533
  /** Public-domain and MindBill-owned metadata. CPT descriptions are intentionally limited to the curated catalog. */
522
534
  declare const DEFAULT_BILL_SUBMISSION_PROCEDURES: BillSubmissionProcedureOption[];
@@ -778,4 +790,4 @@ type MindBillWidgetProps = {
778
790
  declare function MindBillBillTimeline(props: MindBillWidgetProps): ReactElement;
779
791
  declare function MindBillBillReview(props: MindBillWidgetProps): ReactElement;
780
792
 
781
- export { BILL_SUBMISSION_DIAGNOSIS_QUICK_PICKS, BILL_SUBMISSION_DOCUMENT_TYPES, BILL_SUBMISSION_REQUIRED_FIELDS, type BillActivityEvent, BillActivityTimeline, type BillActivityTimelineProps, type BillAgingBucket, type BillAgingBucketId, BillAgingSummary, type BillAgingSummaryProps, BillLifecycleActions, type BillLifecycleActionsProps, BillLifecycleProgress, type BillLifecycleProgressProps, type BillLifecycleStage, BillList, type BillListProps, BillPayerContactCard, type BillPayerContactCardProps, BillPaymentLedger, type BillPaymentLedgerProps, BillReadOnlyForm, type BillReadOnlyFormProps, BillRemittanceCard, type BillRemittanceCardProps, type BillReviewAttachment, type BillReviewBillingProvider, type BillReviewClinician, type BillReviewData, type BillReviewDocumentType, type BillReviewDraft, type BillReviewFeatures, BillReviewForm, type BillReviewFormProps, type BillReviewLineItem, type BillReviewLocation, type BillReviewPayer, type BillReviewSaveInput, BillSnapshotSummary, type BillSnapshotSummaryProps, type BillStatusAction, type BillStatusClient, type BillStatusClientOptions, type BillStatusData, type BillStatusSession, type BillStatusSessionProvider, type BillStatusSessionRequest, BillStatusSummary, type BillStatusSummaryProps, BillSubmissionActions, type BillSubmissionAddress, BillSubmissionAttachmentsSection, BillSubmissionClaimSection, type BillSubmissionDiagnosisOption, type BillSubmissionDocumentType, type BillSubmissionEvaluationType, BillSubmissionForm, type BillSubmissionFormProps, type BillSubmissionFormValue, BillSubmissionHeader, type BillSubmissionInput, type BillSubmissionModifierOption, BillSubmissionPatientSection, type BillSubmissionPostalPlace, type BillSubmissionProcedureOption, BillSubmissionProvidersSection, type BillSubmissionRoute, type BillSubmissionSectionId, BillSubmissionServiceLinesSection, type BillSubmissionSourceAttachment, type BillSubmissionUpload, type BillSubmissionValidation, type BillingComponentProps, BillingDashboard, type BillingDashboardBill, type BillingDashboardProps, type BillingDashboardSummary, BillingReport, type BillingReportDimension, type BillingReportProps, type BillingReportRow, ConnectedBillLifecycle, type ConnectedBillLifecycleProps, ConnectedBillStatus, type ConnectedBillStatusProps, DEFAULT_BILL_SUBMISSION_MODIFIERS, DEFAULT_BILL_SUBMISSION_PROCEDURES, MindBillBillReview, MindBillBillTimeline, type MindBillReactAppearance, type MindBillThemePreset, type MindBillWidgetProps, type UseBillLifecycleOptions, type UseBillLifecycleResult, type UseBillStatusOptions, type UseBillStatusResult, applyBillSubmissionEvaluationModifiers, billActivityEventLabel, billAgingBucket, billAgingDays, billLifecycleDisplayLabel, billLifecycleStage, buildBillReviewSaveInput, buildBillingReportCsv, buildBillingReportRows, calculateBillSubmissionAllowedAmount, createBillStatusClient, ensureTrailingBillSubmissionLine, ensureTrailingProcedureLine, formatBillSubmissionDate, mindBillAppearanceStyle, mindBillThemePresets, parseBillSubmissionDate, resolveMindBillAppearance, summarizeBillingDashboard, useBillLifecycle, useBillStatus, validateBillSubmission, visibleBillLifecycleActions };
793
+ export { BILL_SUBMISSION_DIAGNOSIS_QUICK_PICKS, BILL_SUBMISSION_DOCUMENT_TYPES, BILL_SUBMISSION_REQUIRED_FIELDS, type BillActivityEvent, BillActivityTimeline, type BillActivityTimelineProps, type BillAgingBucket, type BillAgingBucketId, BillAgingSummary, type BillAgingSummaryProps, BillLifecycleActions, type BillLifecycleActionsProps, BillLifecycleProgress, type BillLifecycleProgressProps, type BillLifecycleStage, BillList, type BillListProps, BillPayerContactCard, type BillPayerContactCardProps, BillPaymentLedger, type BillPaymentLedgerProps, BillReadOnlyForm, type BillReadOnlyFormProps, BillRemittanceCard, type BillRemittanceCardProps, type BillReviewAttachment, type BillReviewBillingProvider, type BillReviewClinician, type BillReviewData, type BillReviewDocumentType, type BillReviewDraft, type BillReviewFeatures, BillReviewForm, type BillReviewFormProps, type BillReviewLineItem, type BillReviewLocation, type BillReviewPayer, type BillReviewSaveInput, BillSnapshotSummary, type BillSnapshotSummaryProps, type BillStatusAction, type BillStatusClient, type BillStatusClientOptions, type BillStatusData, type BillStatusSession, type BillStatusSessionProvider, type BillStatusSessionRequest, BillStatusSummary, type BillStatusSummaryProps, BillSubmissionActions, type BillSubmissionAddress, BillSubmissionAttachmentsSection, BillSubmissionClaimSection, type BillSubmissionDiagnosisOption, type BillSubmissionDocumentType, type BillSubmissionEvaluationType, BillSubmissionForm, type BillSubmissionFormProps, type BillSubmissionFormValue, BillSubmissionHeader, type BillSubmissionInput, type BillSubmissionModifierOption, BillSubmissionPatientSection, type BillSubmissionPostalPlace, type BillSubmissionProcedureOption, BillSubmissionProvidersSection, type BillSubmissionRoute, type BillSubmissionSectionId, BillSubmissionServiceLinesSection, type BillSubmissionSourceAttachment, type BillSubmissionUpload, type BillSubmissionValidation, type BillingComponentProps, BillingDashboard, type BillingDashboardBill, type BillingDashboardProps, type BillingDashboardSummary, BillingReport, type BillingReportDimension, type BillingReportProps, type BillingReportRow, ConnectedBillLifecycle, type ConnectedBillLifecycleProps, ConnectedBillStatus, type ConnectedBillStatusProps, DEFAULT_BILL_SUBMISSION_MODIFIERS, DEFAULT_BILL_SUBMISSION_PROCEDURES, MindBillBillReview, MindBillBillTimeline, type MindBillReactAppearance, type MindBillThemePreset, type MindBillWidgetProps, type UseBillLifecycleOptions, type UseBillLifecycleResult, type UseBillStatusOptions, type UseBillStatusResult, applyBillSubmissionEvaluationModifiers, billActivityEventLabel, billAgingBucket, billAgingDays, billLifecycleDisplayLabel, billLifecycleStage, buildBillReviewSaveInput, buildBillingReportCsv, buildBillingReportRows, calculateBillSubmissionAllowedAmount, createBillStatusClient, ensureTrailingBillSubmissionLine, ensureTrailingProcedureLine, formatBillSubmissionDate, mindBillAppearanceStyle, mindBillThemePresets, parseBillSubmissionDate, prepareBillSubmissionDocuments, resolveMindBillAppearance, summarizeBillingDashboard, useBillLifecycle, useBillStatus, validateBillSubmission, visibleBillLifecycleActions };
package/dist/index.js CHANGED
@@ -1157,7 +1157,8 @@ var READ_ONLY_STYLES = `
1157
1157
  // src/bill-submission-form.tsx
1158
1158
  import { createContext, useCallback, useContext, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
1159
1159
  import {
1160
- createBillReferenceClient
1160
+ createBillReferenceClient,
1161
+ createBillSubmissionClient
1161
1162
  } from "@mindbill/browser";
1162
1163
 
1163
1164
  // src/billing-catalog.ts
@@ -1303,6 +1304,7 @@ var BILL_SUBMISSION_REQUIRED_FIELDS = [
1303
1304
  "claim.claimNumber",
1304
1305
  "claim.claimsAdministrator",
1305
1306
  "service.date",
1307
+ "diagnoses[]",
1306
1308
  "serviceLines[].code",
1307
1309
  "serviceLines[].units"
1308
1310
  ];
@@ -1322,6 +1324,48 @@ var MAX_UPLOAD_BYTES = 100 * 1024 * 1024;
1322
1324
  var MAX_DOCUMENTS = 25;
1323
1325
  var DIAGNOSIS_PAGE_SIZE = 100;
1324
1326
  var EMPTY_ATTACHMENTS = [];
1327
+ function bytesToBase64(bytes) {
1328
+ let binary = "";
1329
+ for (let offset = 0; offset < bytes.length; offset += 32768) {
1330
+ binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
1331
+ }
1332
+ return globalThis.btoa(binary);
1333
+ }
1334
+ async function pdfDocument(blob, input) {
1335
+ if (blob.size > MAX_PDF_BYTES) throw new Error(`${input.filename} is larger than 25 MB.`);
1336
+ const bytes = new Uint8Array(await blob.arrayBuffer());
1337
+ if (bytes.length < 5 || bytes[0] !== 37 || bytes[1] !== 80 || bytes[2] !== 68 || bytes[3] !== 70 || bytes[4] !== 45) {
1338
+ throw new Error(`${input.filename} is not a valid PDF.`);
1339
+ }
1340
+ return { ...input, contentBase64: bytesToBase64(bytes) };
1341
+ }
1342
+ async function prepareBillSubmissionDocuments({
1343
+ attachments,
1344
+ selectedIds,
1345
+ uploads,
1346
+ fetch: fetchOverride
1347
+ }) {
1348
+ const fetcher = fetchOverride ?? globalThis.fetch;
1349
+ if (typeof fetcher !== "function") throw new Error("A Fetch API implementation is required.");
1350
+ const selected = selectedIds.map((id) => attachments.find((item) => item.id === id)).filter((item) => Boolean(item));
1351
+ const sourceDocuments = await Promise.all(selected.map(async (attachment) => {
1352
+ if (!attachment.previewUrl) throw new Error(`${attachment.fileName} cannot be submitted because its document URL is missing.`);
1353
+ const response = await fetcher(attachment.previewUrl, { credentials: "same-origin" });
1354
+ if (!response.ok) throw new Error(`${attachment.fileName} could not be loaded for submission.`);
1355
+ return pdfDocument(await response.blob(), {
1356
+ externalId: attachment.id,
1357
+ filename: attachment.fileName,
1358
+ documentType: attachment.documentType,
1359
+ ...attachment.description ? { description: attachment.description } : {}
1360
+ });
1361
+ }));
1362
+ const uploadedDocuments = await Promise.all(uploads.map(({ file, documentType, description }) => pdfDocument(file, {
1363
+ filename: file.name,
1364
+ documentType,
1365
+ ...description ? { description } : {}
1366
+ })));
1367
+ return [...sourceDocuments, ...uploadedDocuments];
1368
+ }
1325
1369
  function previewUploadedPdf(file) {
1326
1370
  const url = URL.createObjectURL(file);
1327
1371
  window.open(url, "_blank", "noopener,noreferrer");
@@ -1403,6 +1447,9 @@ function validateBillSubmission(bill) {
1403
1447
  required("claim.claimNumber", bill.claim.claimNumber, "Enter the claim number.");
1404
1448
  required("claim.claimsAdministrator", bill.claim.claimsAdministrator?.name, "Select a claims administrator so MindBill can route this bill.");
1405
1449
  required("service.date", bill.service.date, "Enter the date of service.");
1450
+ if (!(bill.diagnoses ?? []).some((code) => code.trim())) {
1451
+ errors.diagnoses = "Select at least one ICD-10 diagnosis code.";
1452
+ }
1406
1453
  if (bill.claim.claimsAdministrator?.name && !bill.claim.claimsAdministrator.id) {
1407
1454
  errors["claim.claimsAdministrator"] = "Select a claims administrator from the payer directory.";
1408
1455
  }
@@ -1559,6 +1606,7 @@ function BillSubmissionForm({
1559
1606
  initialBill,
1560
1607
  attachments = EMPTY_ATTACHMENTS,
1561
1608
  onSubmit,
1609
+ onSubmitted,
1562
1610
  getSession,
1563
1611
  sessionEndpoint,
1564
1612
  apiBaseUrl,
@@ -1602,7 +1650,9 @@ function BillSubmissionForm({
1602
1650
  const procedures = useMemo2(() => mergeOptions(DEFAULT_BILL_SUBMISSION_PROCEDURES, procedureOptions), [procedureOptions]);
1603
1651
  const modifiers = useMemo2(() => mergeOptions(DEFAULT_BILL_SUBMISSION_MODIFIERS, modifierOptions), [modifierOptions]);
1604
1652
  const [evaluationType, setEvaluationType] = useState2(() => initialBill.renderingProvider?.isAme ? "ame" : initialBill.renderingProvider?.specialty?.toLowerCase().includes("psych") ? "psych_qme" : "qme");
1605
- const referenceClient = useMemo2(() => getSession ? createBillReferenceClient({ getSession, sessionEndpoint, apiBaseUrl, fetch: fetchOverride }) : null, [getSession, sessionEndpoint, apiBaseUrl, fetchOverride]);
1653
+ const connected = !onSubmit;
1654
+ const referenceClient = useMemo2(() => getSession || sessionEndpoint || connected ? createBillReferenceClient({ getSession, sessionEndpoint, apiBaseUrl, fetch: fetchOverride }) : null, [getSession, sessionEndpoint, apiBaseUrl, fetchOverride, connected]);
1655
+ const submissionClient = useMemo2(() => connected ? createBillSubmissionClient({ getSession, sessionEndpoint, apiBaseUrl, fetch: fetchOverride }) : null, [getSession, sessionEndpoint, apiBaseUrl, fetchOverride, connected]);
1606
1656
  const locked = disabled || submitting;
1607
1657
  useEffect2(() => {
1608
1658
  setBill(cloneBill(initialBill));
@@ -1760,7 +1810,19 @@ function BillSubmissionForm({
1760
1810
  if (selectedIds.length + uploads.length > MAX_DOCUMENTS) return setFormError(`A bill can include at most ${MAX_DOCUMENTS} attachments.`);
1761
1811
  setSubmitting(true);
1762
1812
  try {
1763
- await onSubmit({ bill: clean, sourceAttachmentIds: selectedIds, uploads });
1813
+ if (onSubmit) {
1814
+ await onSubmit({ bill: clean, sourceAttachmentIds: selectedIds, uploads });
1815
+ } else {
1816
+ if (!submissionClient) throw new Error("The connected billing client is unavailable.");
1817
+ const documents = await prepareBillSubmissionDocuments({
1818
+ attachments,
1819
+ selectedIds,
1820
+ uploads,
1821
+ ...fetchOverride ? { fetch: fetchOverride } : {}
1822
+ });
1823
+ const result = await submissionClient.submitBill({ bill: clean, documents });
1824
+ await onSubmitted?.(result);
1825
+ }
1764
1826
  } catch (caught) {
1765
1827
  setFormError(caught instanceof Error ? caught.message : "Unable to submit the bill.");
1766
1828
  } finally {
@@ -1805,7 +1867,7 @@ function BillSubmissionForm({
1805
1867
  /* @__PURE__ */ jsx3(Field2, { label: "WCAB / ADJ number (optional)", children: text(bill.claim.adjNumber, (adjNumber) => setBill((c) => ({ ...c, claim: { ...c.claim, adjNumber } }))) }),
1806
1868
  /* @__PURE__ */ jsx3(Field2, { path: "claim.claimsAdministrator", label: "Claims administrator", required: true, span: true, error: claimsAdministratorError, children: /* @__PURE__ */ jsx3(ComboBox, { ariaLabel: "Claims administrator", invalid: Boolean(claimsAdministratorError), disabled: locked, loading: payerLoading, value: bill.claim.claimsAdministrator?.name ?? "", placeholder: "Search the payer directory\u2026", options: payerResults.map((payer) => ({ id: payer.id, label: payer.name, detail: [payer.hasElectronic ? "Electronic" : "Work comp", ...payer.states ?? []].join(" \xB7 ") })), onQuery: searchPayers, onSelect: (option) => setBill((c) => ({ ...c, claim: { ...c.claim, claimsAdministrator: { id: option.id, name: option.label } } })) }) }),
1807
1869
  /* @__PURE__ */ jsx3(Field2, { label: "Injury description (optional)", span: true, children: text(bill.claim.description, (description2) => setBill((c) => ({ ...c, claim: { ...c.claim, description: description2 } }))) }),
1808
- /* @__PURE__ */ jsxs3(Field2, { label: "Diagnosis codes (ICD-10)", span: true, children: [
1870
+ /* @__PURE__ */ jsxs3(Field2, { path: "diagnoses", label: "Diagnosis codes (ICD-10)", required: true, span: true, error: errors.diagnoses, children: [
1809
1871
  /* @__PURE__ */ jsx3("div", { className: "mbsf-quick-picks", "aria-label": "Common diagnosis codes", children: BILL_SUBMISSION_DIAGNOSIS_QUICK_PICKS.map((option) => {
1810
1872
  const selected = (bill.diagnoses ?? []).includes(option.code);
1811
1873
  return /* @__PURE__ */ jsxs3("button", { className: "mbsf-quick-pick", "data-selected": selected, type: "button", "aria-pressed": selected, title: `${option.code} \u2014 ${option.description}`, onClick: () => setBill((current) => ({ ...current, diagnoses: selected ? (current.diagnoses ?? []).filter((code) => code !== option.code) : [.../* @__PURE__ */ new Set([...current.diagnoses ?? [], option.code])] })), children: [
@@ -1822,7 +1884,7 @@ function BillSubmissionForm({
1822
1884
  /* @__PURE__ */ jsx3("button", { type: "button", "aria-label": `Remove ${code}`, onClick: () => setBill((c) => ({ ...c, diagnoses: (c.diagnoses ?? []).filter((item) => item !== code) })), children: "\xD7" })
1823
1885
  ] }, code);
1824
1886
  }) }),
1825
- /* @__PURE__ */ jsx3(ComboBox, { ariaLabel: "Add diagnosis code", disabled: locked, loading: diagnosisLoading, loadingMore: diagnosisLoadingMore, value: "", placeholder: bill.diagnoses?.length ?? 0 ? `${bill.diagnoses.length} selected \u2014 add more\u2026` : "Search ICD-10 codes\u2026", options: diagnosisChoices.filter((item) => !(bill.diagnoses ?? []).includes(item.code)).map((item) => ({ id: item.code, label: item.code, detail: item.description })), onOpen: () => {
1887
+ /* @__PURE__ */ jsx3(ComboBox, { ariaLabel: "Add diagnosis code", invalid: Boolean(errors.diagnoses), disabled: locked, loading: diagnosisLoading, loadingMore: diagnosisLoadingMore, value: "", placeholder: bill.diagnoses?.length ?? 0 ? `${bill.diagnoses.length} selected \u2014 add more\u2026` : "Search ICD-10 codes\u2026", options: diagnosisChoices.filter((item) => !(bill.diagnoses ?? []).includes(item.code)).map((item) => ({ id: item.code, label: item.code, detail: item.description })), onOpen: () => {
1826
1888
  if (diagnosisQuery !== "") loadDiagnoses("");
1827
1889
  }, onQuery: searchDiagnoses, onEndReached: () => loadDiagnoses(diagnosisQuery ?? "", true), onSelect: (option) => setBill((c) => ({ ...c, diagnoses: [.../* @__PURE__ */ new Set([...c.diagnoses ?? [], option.id])] })) })
1828
1890
  ] })
@@ -3225,6 +3287,7 @@ export {
3225
3287
  mindBillAppearanceStyle,
3226
3288
  mindBillThemePresets,
3227
3289
  parseBillSubmissionDate,
3290
+ prepareBillSubmissionDocuments,
3228
3291
  resolveMindBillAppearance,
3229
3292
  summarizeBillingDashboard,
3230
3293
  useBillLifecycle,