@mindbill/react 0.41.3 → 0.42.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
@@ -191,7 +191,8 @@ The component includes the interaction model, not just the markup:
191
191
  - paste-friendly `MM/DD/YYYY` date fields and required-field asterisks;
192
192
  - ZIP-to-city/state completion through MindBill's authenticated postal directory;
193
193
  - complete, server-backed ICD-10 search with an alphabetized 100-code first page, automatic 100-code scroll paging, common-injury quick picks, and removable chips;
194
- - canonical claims-administrator matching through the authenticated MindBill payer directory: exact aliases select automatically, while fuzzy matches show up to five explicit suggestions with claim-number pattern evidence;
194
+ - an authenticated claims-administrator browser that opens to an alphabetized 50-item page, loads later pages on scroll, searches from the first character, and preserves exact-name and claim-number evidence;
195
+ - explicit routing-payer selection when the administrator requires it, with aliases, affiliated entities, claim-number hints, delivery type, clearinghouse routes, and payer identifiers shown in context;
195
196
  - QME, AME, and Psych QME evaluation modes with medical-legal modifier defaults; Psych QME also seeds `Z04.6` when no more specific diagnosis was supplied, and exposes it as a Psych quick pick;
196
197
  - a searchable rendering-provider taxonomy combobox that accepts either a human-readable specialty search or an exact 10-character taxonomy code;
197
198
  - searchable workers-comp procedure/modifier controls, medical-legal fee-schedule amounts, totals, valid manual CPT/HCPCS entry, and an automatically maintained empty line;
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, BillLifecycleDelivery, BillReviewAttachment as BillReviewAttachment$1, BillReviewPayerOption, BrowserBillSubmissionResult, BillLifecycleSessionProvider, BillReviewPayer as BillReviewPayer$1, BillClaimsAdministratorDirectory, BrowserBillSubmissionDocument, BillDeliveryOptions as BillDeliveryOptions$1, SubmitBillInput, BillTasksDashboardData, BillTasksAgingBucket, BillHistoryEntry, ReportBillStatusInput, OrganizationProfileData, BillRemittanceSummary, BillEorDocument, BillPaymentRecord, BillLifecycleAction, BillRejection, BillLifecycleData, BillLifecycleClientOptions, BillLifecycleClient } from '@mindbill/browser';
5
- export { BILL_TASKS_AGING_BUCKETS, BillActivityRecord, BillClaimsAdministratorContact, BillClaimsAdministratorDirectory, BillClaimsAdministratorMailingAddress, BillClaimsAdministratorPattern, BillClaimsAdministratorPayer, BillEorDocument, BillLifecycleAction, BillLifecycleActionId, BillLifecycleClient, BillLifecycleClientOptions, BillLifecycleData, BillLifecycleDelivery, BillLifecycleSession, BillLifecycleSessionProvider, BillLifecycleSessionRequest, BillPaymentRecord, BillRejection, BillRemittanceSummary, BillReviewPayerOption, BillTasksAgingBucket, BillTasksDashboardData, BillTasksDashboardItem, BillTasksDashboardRow, BillTasksDashboardSection, BillTasksDashboardSectionInput, BillTasksDashboardTone, BrowserBillSubmissionResult, CloseBillInput, PostBillPaymentInput, REPORT_BILL_STATUS_OPTIONS, ReopenBillInput, ReportBillStatusContacts, ReportBillStatusId, ReportBillStatusInput, SECOND_REVIEW_REASON_TEMPLATE, SECOND_REVIEW_WINDOW_DAYS, SecondReviewDeadline, SendDuplicateBillInput, SubmitSecondReviewInput, billTasksAgingBucketIndex, buildBillTasksDashboard, createBillLifecycleClient, reportBillStatusContacts, secondReviewDeadline } from '@mindbill/browser';
4
+ import { BillReviewData as BillReviewData$1, BillLifecycleDelivery, BillReviewAttachment as BillReviewAttachment$1, BillReviewPayerOption, BrowserBillSubmissionResult, BillLifecycleSessionProvider, BillReviewPayerListInput, BillReviewPayerPage, BillReviewPayer as BillReviewPayer$1, BillClaimsAdministratorDirectory, BillClaimsAdministratorSource, BrowserBillSubmissionDocument, BillDeliveryOptions as BillDeliveryOptions$1, SubmitBillInput, BillTasksDashboardData, BillTasksAgingBucket, BillHistoryEntry, ReportBillStatusInput, OrganizationProfileData, BillRemittanceSummary, BillEorDocument, BillPaymentRecord, BillLifecycleAction, BillRejection, BillLifecycleData, BillLifecycleClientOptions, BillLifecycleClient } from '@mindbill/browser';
5
+ export { BILL_TASKS_AGING_BUCKETS, BillActivityRecord, BillClaimsAdministratorContact, BillClaimsAdministratorDirectory, BillClaimsAdministratorMailingAddress, BillClaimsAdministratorPattern, BillClaimsAdministratorPayer, BillClaimsAdministratorSource, BillEorDocument, BillLifecycleAction, BillLifecycleActionId, BillLifecycleClient, BillLifecycleClientOptions, BillLifecycleData, BillLifecycleDelivery, BillLifecycleSession, BillLifecycleSessionProvider, BillLifecycleSessionRequest, BillPaymentRecord, BillRejection, BillRemittanceSummary, BillReviewPayerOption, BillReviewPayerSuggestion, BillTasksAgingBucket, BillTasksDashboardData, BillTasksDashboardItem, BillTasksDashboardRow, BillTasksDashboardSection, BillTasksDashboardSectionInput, BillTasksDashboardTone, BrowserBillSubmissionResult, CloseBillInput, PostBillPaymentInput, REPORT_BILL_STATUS_OPTIONS, ReopenBillInput, ReportBillStatusContacts, ReportBillStatusId, ReportBillStatusInput, SECOND_REVIEW_REASON_TEMPLATE, SECOND_REVIEW_WINDOW_DAYS, SecondReviewDeadline, SendDuplicateBillInput, SubmitSecondReviewInput, billTasksAgingBucketIndex, buildBillTasksDashboard, createBillLifecycleClient, reportBillStatusContacts, secondReviewDeadline } from '@mindbill/browser';
6
6
 
7
7
  type MindBillThemePreset = "mindbill" | "qme-companion" | "orange-bright" | "clinical-blue" | "midnight-cyan";
8
8
  type MindBillReactAppearance = MindBillAppearance & {
@@ -568,9 +568,14 @@ type BillSubmissionFormProps = {
568
568
  sessionEndpoint?: string;
569
569
  apiBaseUrl?: string;
570
570
  fetch?: typeof globalThis.fetch;
571
+ /** Paginated claims-administrator directory. Empty queries return the alphabetical first page. */
572
+ onListClaimsAdministrators?: (input?: BillReviewPayerListInput) => Promise<BillReviewPayerPage>;
573
+ /** @deprecated Prefer onListClaimsAdministrators for browse and pagination support. */
571
574
  onSearchClaimsAdministrators?: (query: string, claimNumber?: string) => Promise<BillReviewPayer$1[]>;
572
575
  onGetClaimsAdministratorDirectory?: (id: string, injuryState?: string) => Promise<BillClaimsAdministratorDirectory>;
573
- /** Free-text name from the host system, shown as a hint while choosing the canonical directory entry. */
576
+ /** Host-system evidence shown without preselecting a canonical directory entry. EAMS evidence takes precedence. */
577
+ claimsAdministratorSources?: readonly BillClaimsAdministratorSource[];
578
+ /** @deprecated Prefer claimsAdministratorSources so the source label and optional URL remain explicit. */
574
579
  claimsAdministratorHint?: ReactNode;
575
580
  diagnosisOptions?: BillSubmissionDiagnosisOption[];
576
581
  onSearchDiagnoses?: (query: string, limit?: number, offset?: number) => Promise<BillSubmissionDiagnosisOption[]>;
@@ -631,11 +636,11 @@ declare function exactClaimsAdministratorMatch(results: BillReviewPayer$1[], sup
631
636
  declare function claimsAdministratorRecommendations(results: BillReviewPayer$1[], limit?: number): BillReviewPayer$1[];
632
637
  /**
633
638
  * Form-state claims administrator for a directory pick. When the administrator
634
- * requires payer selection it carries the payer (subpayor) choices and
635
- * preselects the directory default; administrators without subpayors stay a
639
+ * requires payer selection it carries the payer (routing payer) choices and
640
+ * requires an explicit user choice; administrators without routing payers stay a
636
641
  * plain `{ id, name }` reference.
637
642
  */
638
- declare function chooseClaimsAdministrator(payer: Pick<BillReviewPayer$1, "id" | "name" | "payerSelectionRequired" | "payers">): NonNullable<BillSubmissionInput["claim"]["claimsAdministrator"]>;
643
+ declare function chooseClaimsAdministrator(payer: Pick<BillReviewPayer$1, "id" | "name" | "payerSelectionRequired" | "payers">, selectedPayerId?: string): NonNullable<BillSubmissionInput["claim"]["claimsAdministrator"]>;
639
644
  /**
640
645
  * The claims administrator reference exactly as submitted to MindBill: picker
641
646
  * metadata (payerSelectionRequired, payers) stays client-side and the chosen
@@ -654,7 +659,7 @@ declare function BillSubmissionProvidersSection(): ReactElement;
654
659
  declare function BillSubmissionServiceLinesSection(): ReactElement;
655
660
  declare function BillSubmissionAttachmentsSection(): ReactElement;
656
661
  declare function BillSubmissionActions(): ReactElement;
657
- declare function BillSubmissionForm({ initialBill, attachments, onSubmit, onSubmitted, getSession, sessionEndpoint, apiBaseUrl, fetch: fetchOverride, onSearchClaimsAdministrators, onGetClaimsAdministratorDirectory, claimsAdministratorHint, diagnosisOptions, onSearchDiagnoses, onLookupPostalCode, procedureOptions, modifierOptions, taxonomyOptions, deliveryRoutePicker, attachmentReportTypeMode, attachmentReportTypes, defaultAttachmentReportType, appearance, className, style, disabled, submitLabel, heading, description, attentionFields, attentionMessage, children, }: BillSubmissionFormProps): ReactElement;
662
+ declare function BillSubmissionForm({ initialBill, attachments, onSubmit, onSubmitted, getSession, sessionEndpoint, apiBaseUrl, fetch: fetchOverride, onListClaimsAdministrators, onSearchClaimsAdministrators, onGetClaimsAdministratorDirectory, claimsAdministratorSources, claimsAdministratorHint, diagnosisOptions, onSearchDiagnoses, onLookupPostalCode, procedureOptions, modifierOptions, taxonomyOptions, deliveryRoutePicker, attachmentReportTypeMode, attachmentReportTypes, defaultAttachmentReportType, appearance, className, style, disabled, submitLabel, heading, description, attentionFields, attentionMessage, children, }: BillSubmissionFormProps): ReactElement;
658
663
 
659
664
  /** First plausible email address inside a raw contact string, or null. */
660
665
  declare function extractSendRouteEmail(raw: string | null | undefined): string | null;
@@ -1123,6 +1128,8 @@ type ConnectedBillLifecycleProps = UseBillLifecycleOptions & {
1123
1128
  actorName?: string;
1124
1129
  /** Optional host-system claims-administrator name shown as a selection hint. */
1125
1130
  claimsAdministratorHint?: ReactNode;
1131
+ /** Host-system evidence shown without preselecting a canonical directory entry. */
1132
+ claimsAdministratorSources?: readonly BillClaimsAdministratorSource[];
1126
1133
  /**
1127
1134
  * Exposes payer-response simulation controls for an explicit sandbox
1128
1135
  * playground. Sandbox responses remain indistinguishable from live
@@ -1135,7 +1142,7 @@ type ConnectedBillLifecycleProps = UseBillLifecycleOptions & {
1135
1142
  errorFallback?: (error: Error, retry: () => Promise<void>) => ReactNode;
1136
1143
  onChanged?: (data: BillLifecycleData) => void;
1137
1144
  };
1138
- declare function ConnectedBillLifecycle({ appearance, actorName, claimsAdministratorHint, sandboxControls, className, style, loadingFallback, errorFallback, onChanged, ...options }: ConnectedBillLifecycleProps): ReactElement;
1145
+ declare function ConnectedBillLifecycle({ appearance, actorName, claimsAdministratorHint, claimsAdministratorSources, sandboxControls, className, style, loadingFallback, errorFallback, onChanged, ...options }: ConnectedBillLifecycleProps): ReactElement;
1139
1146
 
1140
1147
  type ClaimsAdministratorDirectoryDialogProps = {
1141
1148
  open: boolean;
package/dist/index.js CHANGED
@@ -1301,8 +1301,7 @@ var READ_ONLY_STYLES = `
1301
1301
  import { createContext, useCallback, useContext, useEffect as useEffect5, useMemo as useMemo3, useRef as useRef2, useState as useState5 } from "react";
1302
1302
  import {
1303
1303
  createBillReferenceClient,
1304
- createBillSubmissionClient,
1305
- defaultBillReviewPayerOption
1304
+ createBillSubmissionClient
1306
1305
  } from "@mindbill/browser";
1307
1306
 
1308
1307
  // src/send-route-dialog.tsx
@@ -1702,7 +1701,7 @@ var css2 = `
1702
1701
  .mbcad-dialog{--mbcad-accent:var(--mb-accent,#176c70);--mbcad-border:var(--mb-border,#d7e0df);--mbcad-surface:var(--mb-surface,#fff);--mbcad-text:var(--mb-text,#17282d);--mbcad-muted:var(--mb-muted,#607176);display:grid;grid-template-rows:auto auto minmax(0,1fr);width:min(1180px,100%);max-height:min(860px,92vh);overflow:hidden;border:1px solid var(--mbcad-border);border-radius:14px;background:var(--mbcad-surface);color:var(--mbcad-text);box-shadow:0 28px 80px rgba(14,31,43,.28);font-family:var(--mb-font,Inter,ui-sans-serif,system-ui,sans-serif)}
1703
1702
  .mbcad-head{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:18px 22px;border-bottom:1px solid var(--mbcad-border)}.mbcad-head h2{margin:0;font-size:24px;line-height:1.2}.mbcad-close{width:40px;height:40px;border:0;border-radius:9px;background:color-mix(in srgb,var(--mbcad-muted) 9%,var(--mbcad-surface));color:var(--mbcad-accent);font:inherit;font-size:28px;line-height:1;cursor:pointer}
1704
1703
  .mbcad-tabs{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));margin:18px 22px 0;border-radius:10px;background:color-mix(in srgb,var(--mbcad-muted) 8%,var(--mbcad-surface));overflow:hidden}.mbcad-tab{min-height:64px;padding:10px;border:0;border-right:1px solid var(--mbcad-border);border-top:4px solid transparent;background:transparent;color:var(--mbcad-muted);font:inherit;font-weight:750;cursor:pointer}.mbcad-tab:last-child{border-right:0}.mbcad-tab[aria-selected=true]{border-top-color:var(--mbcad-accent);background:var(--mbcad-surface);color:var(--mbcad-text)}
1705
- .mbcad-body{overflow:auto;padding:24px 22px 28px}.mbcad-grid{display:grid;gap:0;border:1px solid var(--mbcad-border);border-radius:10px;overflow:hidden}.mbcad-row{display:grid;grid-template-columns:minmax(180px,.8fr) minmax(0,2fr);gap:18px;padding:11px 14px;border-bottom:1px solid var(--mbcad-border)}.mbcad-row:last-child{border-bottom:0}.mbcad-row strong{font-weight:750}.mbcad-list{display:grid;gap:5px;margin:0;padding:0;list-style:none}.mbcad-list a,.mbcad-table a{color:var(--mbcad-accent);overflow-wrap:anywhere}.mbcad-table{width:100%;border-collapse:collapse;border:1px solid var(--mbcad-border);border-radius:10px;overflow:hidden}.mbcad-table th,.mbcad-table td{padding:13px 14px;border-bottom:1px solid var(--mbcad-border);text-align:left;vertical-align:top}.mbcad-table th{background:color-mix(in srgb,var(--mbcad-muted) 7%,var(--mbcad-surface));font-size:13px}.mbcad-empty{padding:36px;text-align:center;color:var(--mbcad-muted)}.mbcad-notice{padding:14px 16px;border:1px solid color-mix(in srgb,var(--mbcad-accent) 70%,var(--mbcad-border));border-radius:9px;background:color-mix(in srgb,var(--mbcad-accent) 5%,var(--mbcad-surface));font-weight:650}
1704
+ .mbcad-body{overflow:auto;padding:24px 22px 28px}.mbcad-grid{display:grid;gap:0;border:1px solid var(--mbcad-border);border-radius:10px;overflow:hidden}.mbcad-row{display:grid;grid-template-columns:minmax(180px,.8fr) minmax(0,2fr);gap:18px;padding:11px 14px;border-bottom:1px solid var(--mbcad-border)}.mbcad-row:last-child{border-bottom:0}.mbcad-row strong{font-weight:750}.mbcad-list{display:grid;gap:5px;margin:0;padding:0;list-style:none}.mbcad-list a,.mbcad-table a{color:var(--mbcad-accent);overflow-wrap:anywhere}.mbcad-payers{display:grid;gap:9px;margin:0;padding:0;list-style:none}.mbcad-payer{display:grid;gap:7px;padding:12px;border:1px solid var(--mbcad-border);border-radius:9px;background:color-mix(in srgb,var(--mbcad-muted) 3%,var(--mbcad-surface))}.mbcad-payer-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.mbcad-payer-route{color:var(--mbcad-accent);font-size:13px;font-weight:750;white-space:nowrap}.mbcad-payer-meta{display:flex;flex-wrap:wrap;gap:6px}.mbcad-payer-meta span{padding:3px 7px;border:1px solid var(--mbcad-border);border-radius:999px;color:var(--mbcad-muted);font-size:12px}.mbcad-payer-note{margin:0;color:var(--mbcad-muted);font-size:13px}.mbcad-table{width:100%;border-collapse:collapse;border:1px solid var(--mbcad-border);border-radius:10px;overflow:hidden}.mbcad-table th,.mbcad-table td{padding:13px 14px;border-bottom:1px solid var(--mbcad-border);text-align:left;vertical-align:top}.mbcad-table th{background:color-mix(in srgb,var(--mbcad-muted) 7%,var(--mbcad-surface));font-size:13px}.mbcad-empty{padding:36px;text-align:center;color:var(--mbcad-muted)}.mbcad-notice{padding:14px 16px;border:1px solid color-mix(in srgb,var(--mbcad-accent) 70%,var(--mbcad-border));border-radius:9px;background:color-mix(in srgb,var(--mbcad-accent) 5%,var(--mbcad-surface));font-weight:650}
1706
1705
  @media(max-width:760px){.mbcad-backdrop{padding:8px}.mbcad-dialog{max-height:96vh}.mbcad-head{padding:14px}.mbcad-head h2{font-size:19px}.mbcad-tabs{display:flex;overflow-x:auto;margin:10px 12px 0}.mbcad-tab{min-width:145px}.mbcad-body{padding:14px 12px 18px}.mbcad-row{grid-template-columns:1fr;gap:5px}.mbcad-table{display:block;overflow-x:auto}}
1707
1706
  `;
1708
1707
  function outbound(value, kind) {
@@ -1712,6 +1711,33 @@ function outbound(value, kind) {
1712
1711
  function list(values, kind) {
1713
1712
  return values?.length ? /* @__PURE__ */ jsx4("ul", { className: "mbcad-list", children: values.map((value, index) => /* @__PURE__ */ jsx4("li", { children: kind ? outbound(value, kind) : value }, `${value}-${index}`)) }) : "\u2014";
1714
1713
  }
1714
+ function payerDetails(payer, index) {
1715
+ const identifiers = Object.entries(payer.clearinghousePayerIds ?? {}).map(([name, id]) => `${name.replace(/_/g, " ")}: ${id}`);
1716
+ const metadata = [
1717
+ payer.optionType ? `Type: ${payer.optionType}` : null,
1718
+ payer.deliveryType ? `Delivery: ${payer.deliveryType}` : null,
1719
+ payer.clearinghouse && payer.payerId ? `${payer.clearinghouse}: ${payer.payerId}` : null,
1720
+ payer.sourceClearinghouse && payer.sourcePayerId ? `Catalog route: ${payer.sourceClearinghouse} ${payer.sourcePayerId}` : null,
1721
+ ...identifiers,
1722
+ payer.preferredClearinghouse ? `Preferred: ${payer.preferredClearinghouse}` : null
1723
+ ].filter((value) => Boolean(value));
1724
+ return /* @__PURE__ */ jsxs4("li", { className: "mbcad-payer", children: [
1725
+ /* @__PURE__ */ jsxs4("div", { className: "mbcad-payer-head", children: [
1726
+ /* @__PURE__ */ jsx4("strong", { children: payer.name }),
1727
+ payer.route ? /* @__PURE__ */ jsx4("span", { className: "mbcad-payer-route", children: payer.route }) : null
1728
+ ] }),
1729
+ payer.aliases?.length ? /* @__PURE__ */ jsxs4("p", { className: "mbcad-payer-note", children: [
1730
+ "Also known as ",
1731
+ payer.aliases.join(", ")
1732
+ ] }) : null,
1733
+ payer.hint ? /* @__PURE__ */ jsx4("p", { className: "mbcad-payer-note", children: payer.hint }) : null,
1734
+ payer.affiliatedEntities?.length ? /* @__PURE__ */ jsxs4("p", { className: "mbcad-payer-note", children: [
1735
+ "Affiliated with ",
1736
+ payer.affiliatedEntities.join(", ")
1737
+ ] }) : null,
1738
+ metadata.length ? /* @__PURE__ */ jsx4("div", { className: "mbcad-payer-meta", children: metadata.map((item) => /* @__PURE__ */ jsx4("span", { children: item }, item)) }) : null
1739
+ ] }, `${payer.name}-${index}`);
1740
+ }
1715
1741
  function Main({ directory }) {
1716
1742
  return /* @__PURE__ */ jsx4("div", { className: "mbcad-grid", children: [
1717
1743
  ["Name", directory.name ?? "\u2014"],
@@ -1724,11 +1750,7 @@ function Main({ directory }) {
1724
1750
  ["Telephone numbers", list(directory.telephoneNumbers, "phone")],
1725
1751
  ["Email addresses", list(directory.emailAddresses, "email")],
1726
1752
  ["Web portals", list(directory.webPortals, "url")],
1727
- ["Payers", directory.payers?.length ? /* @__PURE__ */ jsx4("ul", { className: "mbcad-list", children: directory.payers.map((payer, index) => /* @__PURE__ */ jsxs4("li", { children: [
1728
- /* @__PURE__ */ jsx4("strong", { children: payer.name }),
1729
- payer.route ? ` \xB7 ${payer.route}` : "",
1730
- payer.hint ? /* @__PURE__ */ jsx4("small", { children: payer.hint }) : null
1731
- ] }, `${payer.name}-${index}`)) }) : "\u2014"],
1753
+ ["Payers", directory.payers?.length ? /* @__PURE__ */ jsx4("ul", { className: "mbcad-payers", children: directory.payers.map(payerDetails) }) : "\u2014"],
1732
1754
  ["Bill processing workflow", directory.billProcessingWorkflow ?? "\u2014"],
1733
1755
  ["Bill processing workflow notes", directory.billProcessingWorkflowNotes ?? "\u2014"],
1734
1756
  ["Claim number hint", directory.claimNumberHint ?? "\u2014"]
@@ -2117,6 +2139,7 @@ var MAX_PDF_BYTES = 25 * 1024 * 1024;
2117
2139
  var MAX_UPLOAD_BYTES = 100 * 1024 * 1024;
2118
2140
  var MAX_DOCUMENTS = 25;
2119
2141
  var DIAGNOSIS_PAGE_SIZE = 100;
2142
+ var PAYER_PAGE_SIZE = 50;
2120
2143
  var EMPTY_ATTACHMENTS = [];
2121
2144
  function bytesToBase64(bytes) {
2122
2145
  let binary = "";
@@ -2316,8 +2339,9 @@ var css3 = `
2316
2339
  .mbsf-attention{padding:14px 16px;border-left:4px solid var(--mb-danger);border-radius:var(--mb-control-radius);background:color-mix(in srgb,var(--mb-danger) 8%,var(--mb-surface));color:var(--mb-text)}.mbsf [data-attention=true] .mbsf-input,.mbsf [data-attention=true] .mbsf-select,.mbsf [data-attention=true].mbsf-lines{border-color:var(--mb-danger);background:color-mix(in srgb,var(--mb-danger) 4%,var(--mb-input))}.mbsf [data-attention=true]>.mbsf-label{color:var(--mb-danger)}
2317
2340
  .mbsf-head,.mbsf-section-head,.mbsf-attach-row,.mbsf-actions{display:flex;align-items:center;justify-content:space-between;gap:16px}.mbsf-title{margin:0;font-size:24px}.mbsf-copy,.mbsf-help{color:var(--mb-muted);margin:5px 0 0}.mbsf-required{font-size:13px;color:var(--mb-muted);white-space:nowrap}.mbsf-star,.mbsf-error{color:var(--mb-danger)}
2318
2341
  .mbsf-card{min-width:0;margin:0;padding:24px;border:1px solid var(--mb-border);border-radius:var(--mb-radius);background:var(--mb-surface);box-shadow:var(--mb-shadow)}.mbsf-card[data-invalid=true]{border-color:var(--mb-danger)}.mbsf-legend{padding:0 10px;font-size:18px;font-weight:760}.mbsf-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px 24px}.mbsf-subhead{grid-column:1/-1;margin:6px 0 -2px;padding-top:14px;border-top:1px solid var(--mb-border);font-size:15px;font-weight:780;letter-spacing:.01em}.mbsf-subhead:first-child{margin-top:0;padding-top:0;border-top:0}.mbsf-span{grid-column:1/-1}.mbsf-field{display:grid;align-content:start;gap:7px;min-width:0}.mbsf-label{font-weight:680}.mbsf-input,.mbsf-select{width:100%;min-height:46px;padding:10px 12px;border:1px solid var(--mb-border);border-radius:var(--mb-control-radius);background:var(--mb-input);color:var(--mb-text);font:inherit}.mbsf-input:focus,.mbsf-select:focus{outline:3px solid color-mix(in srgb,var(--mb-accent) 22%,transparent);border-color:var(--mb-accent)}.mbsf-field[data-invalid=true] .mbsf-input,.mbsf-field[data-invalid=true] .mbsf-select,.mbsf-invalid-control .mbsf-input{border-color:var(--mb-danger);background:color-mix(in srgb,var(--mb-danger) 4%,var(--mb-input))}.mbsf-field[data-invalid=true] .mbsf-input:focus,.mbsf-field[data-invalid=true] .mbsf-select:focus{outline-color:color-mix(in srgb,var(--mb-danger) 24%,transparent)}
2319
- .mbsf-combo{position:relative}.mbsf-menu{position:absolute;z-index:20;top:calc(100% + 5px);left:0;right:0;max-height:min(360px,46vh);overflow:auto;overscroll-behavior:contain;padding:7px;border:1px solid var(--mb-border);border-radius:12px;background:var(--mb-surface);box-shadow:0 14px 35px rgba(17,38,49,.16)}.mbsf-option{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:14px;width:100%;padding:10px;border:0;border-radius:8px;background:transparent;color:var(--mb-text);font:inherit;text-align:left;cursor:pointer}.mbsf-option:hover,.mbsf-option:focus{background:color-mix(in srgb,var(--mb-accent) 9%,var(--mb-surface))}.mbsf-option-main{display:grid;gap:2px;min-width:0}.mbsf-option small{color:var(--mb-muted);overflow-wrap:anywhere}.mbsf-option-route{align-self:center;color:var(--mb-accent);font-size:13px;font-weight:750;white-space:nowrap}.mbsf-menu-status{padding:12px;text-align:center;color:var(--mb-muted);font-size:13px}.mbsf-directory-link{justify-self:start;border:0;padding:0;background:transparent;color:var(--mb-accent);font:inherit;font-weight:700;text-align:left;text-decoration:underline;cursor:pointer}
2342
+ .mbsf-combo{position:relative}.mbsf-menu{position:absolute;z-index:20;top:calc(100% + 5px);left:0;right:0;max-height:min(420px,52vh);overflow:auto;overscroll-behavior:contain;padding:7px;border:1px solid var(--mb-border);border-radius:12px;background:var(--mb-surface);box-shadow:0 14px 35px rgba(17,38,49,.16)}.mbsf-option{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:14px;width:100%;padding:11px 12px;border:0;border-radius:8px;background:transparent;color:var(--mb-text);font:inherit;text-align:left;cursor:pointer}.mbsf-option+.mbsf-option{border-top:1px solid color-mix(in srgb,var(--mb-border) 65%,transparent)}.mbsf-option:hover,.mbsf-option:focus{background:color-mix(in srgb,var(--mb-accent) 9%,var(--mb-surface));outline:0}.mbsf-option-main{display:grid;gap:5px;min-width:0}.mbsf-option small{color:var(--mb-muted);overflow-wrap:anywhere;line-height:1.35}.mbsf-option-route{align-self:start;margin-top:2px;color:var(--mb-accent);font-size:13px;font-weight:750;white-space:nowrap}.mbsf-option-badges{display:flex;flex-wrap:wrap;gap:5px}.mbsf-option-badge{padding:2px 7px;border:1px solid var(--mb-border);border-radius:999px;color:var(--mb-muted);font-size:11px;line-height:1.35}.mbsf-option-affiliates{display:block}.mbsf-option-affiliates strong{color:var(--mb-text);font-size:12px}.mbsf-menu-status{padding:12px;text-align:center;color:var(--mb-muted);font-size:13px}.mbsf-directory-link{justify-self:start;border:0;padding:0;background:transparent;color:var(--mb-accent);font:inherit;font-weight:700;text-align:left;text-decoration:underline;cursor:pointer}
2320
2343
  .mbsf-payer-status{display:flex;align-items:center;gap:7px;color:#087f5b;font-size:13px;font-weight:650}.mbsf-payer-intro{margin:4px 0 0;color:var(--mb-muted)}.mbsf-payer-list{display:grid;gap:8px}.mbsf-payer-option{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:11px 12px;border:1px solid var(--mb-border);border-radius:var(--mb-control-radius);background:color-mix(in srgb,var(--mb-accent) 3%,var(--mb-surface))}.mbsf-payer-option-main{display:grid;gap:5px;min-width:0}.mbsf-payer-option-main strong{overflow-wrap:anywhere}.mbsf-payer-signals{display:flex;flex-wrap:wrap;gap:6px}.mbsf-payer-signal{padding:2px 7px;border:1px solid var(--mb-border);border-radius:999px;color:var(--mb-muted);font-size:12px}.mbsf-payer-signal[data-state=match]{border-color:color-mix(in srgb,#159447 45%,var(--mb-border));color:#087f5b}.mbsf-payer-signal[data-state=warning]{border-color:color-mix(in srgb,#c56a00 55%,var(--mb-border));color:#9a5200}
2344
+ .mbsf-source-evidence{display:grid;gap:4px;color:var(--mb-muted);font-size:13px}.mbsf-source-evidence a{color:var(--mb-accent);font-weight:700}.mbsf-source-evidence q{color:var(--mb-text)}.mbsf-suggestions{display:flex;align-items:center;flex-wrap:wrap;gap:7px;color:var(--mb-muted);font-size:13px}.mbsf-suggestion{padding:5px 10px;border:1px solid color-mix(in srgb,var(--mb-accent) 55%,var(--mb-border));border-radius:999px;background:color-mix(in srgb,var(--mb-accent) 7%,var(--mb-surface));color:var(--mb-accent);font:inherit;font-weight:700;cursor:pointer}.mbsf-suggestion:hover,.mbsf-suggestion:focus{outline:2px solid color-mix(in srgb,var(--mb-accent) 25%,transparent)}.mbsf-claim-patterns{display:grid;gap:4px;margin-top:2px;font-size:13px}.mbsf-claim-patterns[data-state=match]{color:#087f5b}.mbsf-claim-patterns[data-state=warning]{color:#9a5200}.mbsf-claim-pattern-list{color:var(--mb-muted)}
2321
2345
  .mbsf-chips,.mbsf-quick-picks{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:8px}.mbsf-chip,.mbsf-quick-pick{display:inline-flex;align-items:center;gap:7px;padding:5px 9px;border:1px solid var(--mb-border);border-radius:999px;background:var(--mb-input)}.mbsf-chip button{border:0;background:transparent;color:var(--mb-muted);cursor:pointer;font:inherit}.mbsf-quick-pick{color:var(--mb-text);font:inherit;cursor:pointer}.mbsf-quick-pick[data-selected=true]{border-color:var(--mb-accent);color:var(--mb-accent)}
2322
2346
  .mbsf-segments{display:grid;grid-template-columns:repeat(3,1fr);border:1px solid var(--mb-border);border-radius:var(--mb-control-radius);overflow:hidden}.mbsf-segment{min-height:44px;border:0;border-right:1px solid var(--mb-border);background:var(--mb-input);color:var(--mb-text);font:inherit;font-weight:700;cursor:pointer}.mbsf-segment:last-child{border-right:0}.mbsf-segment[aria-pressed=true]{background:var(--mb-accent);color:var(--mb-accent-contrast)}
2323
2347
  .mbsf-lines{margin-top:18px;border:1px solid var(--mb-border);border-radius:var(--mb-control-radius);overflow:visible}.mbsf-lines[data-invalid=true]{border-color:var(--mb-danger)}.mbsf-line-head,.mbsf-line{display:grid;grid-template-columns:minmax(190px,1.05fr) minmax(190px,1.3fr) minmax(112px,.7fr) 100px 120px 42px;gap:12px;align-items:start;padding:12px}.mbsf-line-head{color:var(--mb-muted);font-size:13px;font-weight:700;border-bottom:1px solid var(--mb-border)}.mbsf-line{border-bottom:1px solid var(--mb-border)}.mbsf-line:last-child{border-bottom:0}.mbsf-line [data-invalid=true] .mbsf-input{border-color:var(--mb-danger);background:color-mix(in srgb,var(--mb-danger) 4%,var(--mb-input))}.mbsf-money{padding-top:12px;text-align:right;font-variant-numeric:tabular-nums}.mbsf-dx{display:flex;flex-wrap:wrap;gap:5px;padding-top:6px}.mbsf-dx-chip{width:30px;height:30px;border:1px solid var(--mb-border);border-radius:8px;background:var(--mb-surface);color:var(--mb-muted);font:inherit;font-size:13px;font-weight:750;cursor:pointer}.mbsf-dx-chip[data-active=true]{border-color:var(--mb-accent);background:color-mix(in srgb,var(--mb-accent) 10%,var(--mb-surface));color:var(--mb-accent)}.mbsf-total{display:flex;justify-content:flex-end;gap:45px;padding:16px 56px 16px 16px;font-size:17px;font-weight:760}
@@ -2356,16 +2380,16 @@ function TextDateInput({ value, onChange, disabled, required, ariaLabel }) {
2356
2380
  invalid ? /* @__PURE__ */ jsx5("small", { className: "mbsf-error", children: "Use MM/DD/YYYY" }) : null
2357
2381
  ] });
2358
2382
  }
2359
- function ComboBox({ value, placeholder, options, disabled, loading, loadingMore, invalid, preserveValueOnOpen = false, onOpen, onQuery, onEndReached, onSelect, createOption, ariaLabel }) {
2383
+ function ComboBox({ value, placeholder, options, disabled, loading, loadingMore, invalid, preserveValueOnOpen = false, filterOptions = true, onOpen, onQuery, onEndReached, onSelect, createOption, ariaLabel }) {
2360
2384
  const [open, setOpen] = useState5(false);
2361
2385
  const [query, setQuery] = useState5("");
2362
2386
  const visible = useMemo3(() => {
2363
2387
  const q = query.trim().toLowerCase();
2364
- const matches = q ? options.filter((option) => `${option.id} ${option.label} ${option.detail ?? ""} ${option.trailing ?? ""}`.toLowerCase().includes(q)) : options;
2388
+ const matches = q && filterOptions ? options.filter((option) => `${option.id} ${option.label} ${option.detail ?? ""} ${(option.badges ?? []).join(" ")} ${(option.affiliatedEntities ?? []).join(" ")} ${option.trailing ?? ""}`.toLowerCase().includes(q)) : options;
2365
2389
  const custom = createOption?.(query) ?? null;
2366
2390
  return custom && !matches.some((option) => option.id.toUpperCase() === custom.id.toUpperCase()) ? [...matches, custom] : matches;
2367
- }, [createOption, options, query]);
2368
- const showMenu = open && (loading || visible.length > 0 || query.trim().length >= 2);
2391
+ }, [createOption, filterOptions, options, query]);
2392
+ const showMenu = open;
2369
2393
  return /* @__PURE__ */ jsxs5("div", { className: "mbsf-combo", children: [
2370
2394
  /* @__PURE__ */ jsx5("input", { className: "mbsf-input", role: "combobox", "aria-label": ariaLabel, "aria-invalid": invalid, "aria-expanded": showMenu, autoComplete: "off", disabled, placeholder, value: open ? query : value, onFocus: () => {
2371
2395
  const next = preserveValueOnOpen ? value : "";
@@ -2389,7 +2413,13 @@ function ComboBox({ value, placeholder, options, disabled, loading, loadingMore,
2389
2413
  }, children: [
2390
2414
  /* @__PURE__ */ jsxs5("span", { className: "mbsf-option-main", children: [
2391
2415
  /* @__PURE__ */ jsx5("strong", { children: option.label }),
2392
- option.detail ? /* @__PURE__ */ jsx5("small", { children: option.detail }) : null
2416
+ option.detail ? /* @__PURE__ */ jsx5("small", { children: option.detail }) : null,
2417
+ option.badges?.length ? /* @__PURE__ */ jsx5("span", { className: "mbsf-option-badges", children: option.badges.map((badge) => /* @__PURE__ */ jsx5("span", { className: "mbsf-option-badge", children: badge }, badge)) }) : null,
2418
+ option.affiliatedEntities?.length ? /* @__PURE__ */ jsxs5("small", { className: "mbsf-option-affiliates", children: [
2419
+ /* @__PURE__ */ jsx5("strong", { children: "Affiliated entities:" }),
2420
+ " ",
2421
+ option.affiliatedEntities.join(", ")
2422
+ ] }) : null
2393
2423
  ] }),
2394
2424
  option.trailing ? /* @__PURE__ */ jsx5("span", { className: "mbsf-option-route", children: option.trailing }) : null
2395
2425
  ] }, option.id)) : /* @__PURE__ */ jsx5("div", { className: "mbsf-option", children: "No matches" }),
@@ -2439,16 +2469,24 @@ function exactClaimsAdministratorMatch(results, suppliedName) {
2439
2469
  function claimsAdministratorRecommendations(results, limit = 5) {
2440
2470
  return [...results].sort((left, right) => Number(Boolean(right.recommended)) - Number(Boolean(left.recommended))).slice(0, Math.max(0, limit));
2441
2471
  }
2442
- function chooseClaimsAdministrator(payer) {
2472
+ function claimNumberPatternMatches(pattern, claimNumber) {
2473
+ const example = pattern.example?.trim();
2474
+ if (example && /9{2,}/.test(example)) {
2475
+ const expression = [...example].map((character) => character === "9" ? "\\d" : character.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("");
2476
+ return new RegExp(`^${expression}$`, "i").test(claimNumber.trim());
2477
+ }
2478
+ return pattern.matches ?? null;
2479
+ }
2480
+ function chooseClaimsAdministrator(payer, selectedPayerId) {
2443
2481
  if (!payer.payerSelectionRequired) return { id: payer.id, name: payer.name };
2444
2482
  const payers = (payer.payers ?? []).map((option) => ({ ...option }));
2445
- const preselected = defaultBillReviewPayerOption(payer);
2483
+ const resolvedPayerId = selectedPayerId && payers.some((option) => option.id === selectedPayerId) ? selectedPayerId : void 0;
2446
2484
  return {
2447
2485
  id: payer.id,
2448
2486
  name: payer.name,
2449
2487
  payerSelectionRequired: true,
2450
2488
  ...payers.length ? { payers } : {},
2451
- ...preselected ? { payerId: preselected.id } : {}
2489
+ ...resolvedPayerId ? { payerId: resolvedPayerId } : {}
2452
2490
  };
2453
2491
  }
2454
2492
  function submittedClaimsAdministrator(administrator) {
@@ -2494,8 +2532,10 @@ function BillSubmissionForm({
2494
2532
  sessionEndpoint,
2495
2533
  apiBaseUrl,
2496
2534
  fetch: fetchOverride,
2535
+ onListClaimsAdministrators,
2497
2536
  onSearchClaimsAdministrators,
2498
2537
  onGetClaimsAdministratorDirectory,
2538
+ claimsAdministratorSources,
2499
2539
  claimsAdministratorHint,
2500
2540
  diagnosisOptions = [],
2501
2541
  onSearchDiagnoses,
@@ -2531,6 +2571,11 @@ function BillSubmissionForm({
2531
2571
  const [routeError, setRouteError] = useState5(null);
2532
2572
  const [payerResults, setPayerResults] = useState5([]);
2533
2573
  const [payerLoading, setPayerLoading] = useState5(false);
2574
+ const [payerSuggestions, setPayerSuggestions] = useState5([]);
2575
+ const [selectedPayerMetadata, setSelectedPayerMetadata] = useState5(null);
2576
+ const [payerLoadingMore, setPayerLoadingMore] = useState5(false);
2577
+ const [payerQuery, setPayerQuery] = useState5(null);
2578
+ const [payerHasMore, setPayerHasMore] = useState5(true);
2534
2579
  const [directoryOpen, setDirectoryOpen] = useState5(false);
2535
2580
  const [directory, setDirectory] = useState5(null);
2536
2581
  const [directoryLoading, setDirectoryLoading] = useState5(false);
@@ -2547,7 +2592,10 @@ function BillSubmissionForm({
2547
2592
  const diagnosisRequest = useRef2(0);
2548
2593
  const diagnosisAppendPending = useRef2(false);
2549
2594
  const payerRequest = useRef2(0);
2595
+ const payerAppendPending = useRef2(false);
2550
2596
  const procedures = useMemo3(() => mergeOptions(DEFAULT_BILL_SUBMISSION_PROCEDURES, procedureOptions), [procedureOptions]);
2597
+ const orderedClaimsAdministratorSources = useMemo3(() => [...claimsAdministratorSources ?? []].filter((source) => source.name.trim()).sort((left, right) => Number(right.source.toLowerCase() === "eams") - Number(left.source.toLowerCase() === "eams")), [claimsAdministratorSources]);
2598
+ const sourceClaimsAdministratorName = orderedClaimsAdministratorSources[0]?.name.trim() ?? "";
2551
2599
  const modifiers = useMemo3(() => mergeOptions(DEFAULT_BILL_SUBMISSION_MODIFIERS, modifierOptions), [modifierOptions]);
2552
2600
  const taxonomies = useMemo3(() => mergeOptions(DEFAULT_BILL_SUBMISSION_TAXONOMIES, taxonomyOptions), [taxonomyOptions]);
2553
2601
  const [evaluationType, setEvaluationType] = useState5(() => initialEvaluationType(initialBill));
@@ -2574,7 +2622,14 @@ function BillSubmissionForm({
2574
2622
  setDiagnosisHasMore(true);
2575
2623
  diagnosisRequest.current += 1;
2576
2624
  diagnosisAppendPending.current = false;
2577
- }, [initialBill, attachments]);
2625
+ setPayerResults([]);
2626
+ setPayerSuggestions([]);
2627
+ setSelectedPayerMetadata(null);
2628
+ setPayerQuery(null);
2629
+ setPayerHasMore(true);
2630
+ payerRequest.current += 1;
2631
+ payerAppendPending.current = false;
2632
+ }, [initialBill, attachments, sourceClaimsAdministratorName]);
2578
2633
  useEffect5(() => {
2579
2634
  if (!validationActive) return;
2580
2635
  const next = validateBillSubmission(bill).fieldErrors;
@@ -2648,33 +2703,50 @@ function BillSubmissionForm({
2648
2703
  return next;
2649
2704
  })) }));
2650
2705
  const text = (value, onChange, options = {}) => /* @__PURE__ */ jsx5("input", { className: "mbsf-input", disabled: locked, value: value ?? "", onChange: (event) => onChange(event.target.value), ...options });
2651
- const runPayerSearch = useCallback(async (query) => {
2706
+ const loadPayers = useCallback((query, append = false) => {
2652
2707
  const trimmed = query.trim();
2653
- if (trimmed.length < 2) {
2654
- setPayerResults([]);
2655
- return;
2656
- }
2657
- const search = onSearchClaimsAdministrators ?? referenceClient?.searchClaimsAdministrators;
2658
- if (!search) return;
2708
+ const list2 = onListClaimsAdministrators ?? referenceClient?.listClaimsAdministrators;
2709
+ const legacySearch = onSearchClaimsAdministrators ?? referenceClient?.searchClaimsAdministrators;
2710
+ if (!list2 && !legacySearch) return;
2711
+ const continuing = append && payerQuery === trimmed;
2712
+ if (continuing && (!payerHasMore || payerAppendPending.current)) return;
2713
+ const offset = continuing ? payerResults.length : 0;
2659
2714
  const request = ++payerRequest.current;
2660
- setPayerLoading(true);
2661
- try {
2662
- const results = await search(trimmed, bill.claim.claimNumber);
2715
+ if (continuing) {
2716
+ payerAppendPending.current = true;
2717
+ setPayerLoadingMore(true);
2718
+ } else {
2719
+ setPayerLoading(true);
2720
+ setPayerLoadingMore(false);
2721
+ setPayerQuery(trimmed);
2722
+ setPayerHasMore(true);
2723
+ }
2724
+ const page = list2 ? list2({ query: trimmed, claimNumber: bill.claim.claimNumber, ...sourceClaimsAdministratorName ? { sourceClaimsAdministratorName } : {}, ...bill.claim.employer ? { employerName: bill.claim.employer } : {}, limit: PAYER_PAGE_SIZE, offset }) : legacySearch(trimmed, bill.claim.claimNumber).then((results) => ({ results, total: results.length }));
2725
+ void page.then((result) => {
2663
2726
  if (request !== payerRequest.current) return;
2664
- setPayerResults(results);
2665
- } catch (caught) {
2727
+ setPayerResults((current) => {
2728
+ const combined = continuing ? [...current, ...result.results] : result.results;
2729
+ return [...new Map(combined.map((payer) => [payer.id, payer])).values()];
2730
+ });
2731
+ if (!continuing) setPayerSuggestions(result.suggestions ?? []);
2732
+ setPayerHasMore(result.nextOffset != null ? result.nextOffset > offset : offset + result.results.length < result.total);
2733
+ }).catch((caught) => {
2666
2734
  if (request === payerRequest.current) setFormError(caught instanceof Error ? caught.message : "Claims administrator search is unavailable.");
2667
- } finally {
2668
- if (request === payerRequest.current) setPayerLoading(false);
2669
- }
2670
- }, [bill.claim.claimNumber, onSearchClaimsAdministrators, referenceClient]);
2735
+ }).finally(() => {
2736
+ if (request !== payerRequest.current) return;
2737
+ payerAppendPending.current = false;
2738
+ setPayerLoading(false);
2739
+ setPayerLoadingMore(false);
2740
+ });
2741
+ }, [bill.claim.claimNumber, bill.claim.employer, onListClaimsAdministrators, onSearchClaimsAdministrators, payerHasMore, payerQuery, payerResults.length, referenceClient, sourceClaimsAdministratorName]);
2671
2742
  const searchPayers = (query) => {
2743
+ setSelectedPayerMetadata(null);
2672
2744
  setBill((current) => {
2673
2745
  const selected = current.claim.claimsAdministrator;
2674
2746
  if (selected?.id && selected.name === query) return current;
2675
2747
  return { ...current, claim: { ...current.claim, claimsAdministrator: { name: query } } };
2676
2748
  });
2677
- void runPayerSearch(query);
2749
+ loadPayers(query);
2678
2750
  };
2679
2751
  const loadDiagnoses = (query, append = false) => {
2680
2752
  const trimmed = query.trim();
@@ -2816,8 +2888,19 @@ function BillSubmissionForm({
2816
2888
  }
2817
2889
  }
2818
2890
  const claimsAdministratorError = errors["claim.claimsAdministrator"];
2819
- const choosePayer = (payer) => setBill((current) => ({ ...current, claim: { ...current.claim, claimsAdministrator: chooseClaimsAdministrator(payer) } }));
2891
+ const choosePayer = (payer, selectedPayerId) => {
2892
+ setSelectedPayerMetadata(payer);
2893
+ setBill((current) => ({ ...current, claim: { ...current.claim, claimsAdministrator: chooseClaimsAdministrator(payer, selectedPayerId) } }));
2894
+ };
2820
2895
  const administrator = bill.claim.claimsAdministrator;
2896
+ const displayedPayerMetadata = selectedPayerMetadata?.id === administrator?.id ? selectedPayerMetadata : null;
2897
+ const displayedClaimPatterns = (displayedPayerMetadata?.claimNumberPatterns ?? []).map((pattern) => ({
2898
+ ...pattern,
2899
+ matches: claimNumberPatternMatches(pattern, bill.claim.claimNumber)
2900
+ }));
2901
+ const evaluatedClaimPatterns = displayedClaimPatterns.filter((pattern) => pattern.matches != null);
2902
+ const claimNumberMatches = evaluatedClaimPatterns.some((pattern) => pattern.matches);
2903
+ const claimNumberPatternState = evaluatedClaimPatterns.length ? claimNumberMatches ? "match" : "warning" : null;
2821
2904
  const subpayorOptions = administrator?.payerSelectionRequired ? administrator.payers ?? [] : [];
2822
2905
  const subpayorError = errors["claim.claimsAdministrator.payerId"];
2823
2906
  const selectedSubpayor = subpayorOptions.find((option) => option.id === administrator?.payerId);
@@ -2875,14 +2958,40 @@ function BillSubmissionForm({
2875
2958
  ] }),
2876
2959
  /* @__PURE__ */ jsx5(Field2, { path: "claim.dateOfInjury", label: "Date of injury", required: true, error: errors["claim.dateOfInjury"], children: /* @__PURE__ */ jsx5(TextDateInput, { ariaLabel: "Date of injury", value: bill.claim.dateOfInjury, disabled: locked, required: true, onChange: (dateOfInjury) => setBill((c) => ({ ...c, claim: { ...c.claim, dateOfInjury } })) }) }),
2877
2960
  /* @__PURE__ */ jsx5(Field2, { path: "claim.employer", label: "Employer name", required: true, error: errors["claim.employer"], children: text(bill.claim.employer, (employer) => setBill((c) => ({ ...c, claim: { ...c.claim, employer } }))) }),
2878
- /* @__PURE__ */ jsx5(Field2, { path: "claim.claimNumber", label: "Claim number", required: true, error: errors["claim.claimNumber"], children: text(bill.claim.claimNumber, (claimNumber) => setBill((c) => ({ ...c, claim: { ...c.claim, claimNumber } }))) }),
2961
+ /* @__PURE__ */ jsxs5(Field2, { path: "claim.claimNumber", label: "Claim number", required: true, error: errors["claim.claimNumber"], children: [
2962
+ text(bill.claim.claimNumber, (claimNumber) => setBill((c) => ({ ...c, claim: { ...c.claim, claimNumber } }))),
2963
+ displayedClaimPatterns.length ? /* @__PURE__ */ jsxs5("div", { className: "mbsf-claim-patterns", "data-state": claimNumberPatternState ?? void 0, role: "status", children: [
2964
+ claimNumberPatternState === "match" ? /* @__PURE__ */ jsx5("strong", { children: "\u2713 Matches a known claim number pattern" }) : claimNumberPatternState === "warning" ? /* @__PURE__ */ jsx5("strong", { children: "\u26A0 Does not match the known claim number patterns" }) : /* @__PURE__ */ jsx5("strong", { children: "Known claim number patterns" }),
2965
+ /* @__PURE__ */ jsx5("span", { className: "mbsf-claim-pattern-list", children: displayedClaimPatterns.map((pattern) => `${pattern.pattern}${pattern.example ? ` (example: ${pattern.example})` : ""}`).join(" \xB7 ") })
2966
+ ] }) : null
2967
+ ] }),
2879
2968
  /* @__PURE__ */ jsx5(Field2, { label: "WCAB / ADJ number (optional)", children: text(bill.claim.adjNumber, (adjNumber) => setBill((c) => ({ ...c, claim: { ...c.claim, adjNumber } }))) }),
2880
2969
  /* @__PURE__ */ jsxs5(Field2, { path: "claim.claimsAdministrator", label: "Claims administrator", required: true, span: true, error: claimsAdministratorError, invalid: !administrator?.id, children: [
2881
- /* @__PURE__ */ jsx5(ComboBox, { ariaLabel: "Claims administrator", invalid: Boolean(claimsAdministratorError) || !administrator?.id, disabled: locked, loading: payerLoading, preserveValueOnOpen: true, value: administrator?.name ?? "", placeholder: "Search the claims administrator directory\u2026", options: payerResults.map((payer) => ({ id: payer.id, label: payer.name, detail: [payer.aliases?.length ? `Also known as ${payer.aliases.join(", ")}` : "", payer.claimNumberHint ?? "", payer.affiliatedEntities?.length ? `Affiliated with ${payer.affiliatedEntities.join(", ")}` : ""].filter(Boolean).join(" \xB7 ") || "Claims administrator", ...payer.route ? { trailing: payer.route } : {} })), onQuery: searchPayers, onSelect: (option) => choosePayer(payerResults.find((payer) => payer.id === option.id) ?? { id: option.id, name: option.label }) }),
2970
+ /* @__PURE__ */ jsx5(ComboBox, { ariaLabel: "Claims administrator", invalid: Boolean(claimsAdministratorError) || !administrator?.id, disabled: locked, loading: payerLoading, loadingMore: payerLoadingMore, filterOptions: false, value: administrator?.name ?? "", placeholder: "Browse or search claims administrators\u2026", options: payerResults.map((payer) => {
2971
+ const patternDetail = payer.claimNumberPatterns?.map((pattern) => `${pattern.pattern}${pattern.example ? ` (example: ${pattern.example})` : ""}`).join(" \xB7 ") ?? payer.claimNumberHint ?? "";
2972
+ return { id: payer.id, label: payer.name, detail: [payer.aliases?.length ? `Also known as ${payer.aliases.join(", ")}` : "", patternDetail].filter(Boolean).join(" \xB7 ") || "Claims administrator", ...payer.affiliatedEntities?.length ? { affiliatedEntities: payer.affiliatedEntities } : {}, ...payer.route ? { trailing: payer.route } : {} };
2973
+ }), onOpen: () => {
2974
+ if (payerQuery !== "") loadPayers("");
2975
+ }, onQuery: searchPayers, onEndReached: () => loadPayers(payerQuery ?? "", true), onSelect: (option) => choosePayer(payerResults.find((payer) => payer.id === option.id) ?? { id: option.id, name: option.label }) }),
2976
+ orderedClaimsAdministratorSources.length ? /* @__PURE__ */ jsx5("div", { className: "mbsf-source-evidence", children: orderedClaimsAdministratorSources.map((source, index) => /* @__PURE__ */ jsxs5("span", { children: [
2977
+ source.url ? /* @__PURE__ */ jsx5("a", { href: source.url, target: "_blank", rel: "noopener noreferrer", children: source.label }) : /* @__PURE__ */ jsx5("strong", { children: source.label }),
2978
+ ": ",
2979
+ /* @__PURE__ */ jsx5("q", { children: source.name })
2980
+ ] }, `${source.source}-${source.name}-${index}`)) }) : null,
2882
2981
  claimsAdministratorHint ? /* @__PURE__ */ jsxs5("small", { className: "mbsf-help", children: [
2883
2982
  "Claims administrator in your system: ",
2884
2983
  claimsAdministratorHint
2885
2984
  ] }) : null,
2985
+ payerSuggestions.length ? /* @__PURE__ */ jsxs5("div", { className: "mbsf-suggestions", children: [
2986
+ /* @__PURE__ */ jsx5("strong", { children: "Suggested:" }),
2987
+ payerSuggestions.slice(0, 5).map((suggestion) => {
2988
+ const suggestedSubpayor = suggestion.payers?.find((option) => option.id === suggestion.selectedPayerId);
2989
+ return /* @__PURE__ */ jsxs5("button", { className: "mbsf-suggestion", type: "button", title: suggestion.reason, onClick: () => choosePayer(suggestion, suggestion.selectedPayerId), children: [
2990
+ suggestion.name,
2991
+ suggestedSubpayor ? ` \xB7 ${suggestedSubpayor.label}` : ""
2992
+ ] }, `${suggestion.id}-${suggestion.selectedPayerId ?? "admin"}`);
2993
+ })
2994
+ ] }) : null,
2886
2995
  administrator?.id ? /* @__PURE__ */ jsxs5("button", { className: "mbsf-directory-link", type: "button", onClick: () => {
2887
2996
  void openAdministratorDirectory();
2888
2997
  }, children: [
@@ -2890,16 +2999,27 @@ function BillSubmissionForm({
2890
2999
  administrator.name
2891
3000
  ] }) : /* @__PURE__ */ jsx5("small", { className: "mbsf-help", children: "Search the directory and choose a claims administrator." })
2892
3001
  ] }),
2893
- administrator?.payerSelectionRequired && subpayorOptions.length ? /* @__PURE__ */ jsxs5(Field2, { path: "claim.claimsAdministrator.payerId", label: "Payer", required: true, span: true, error: subpayorError, children: [
2894
- /* @__PURE__ */ jsx5(ComboBox, { ariaLabel: "Payer", invalid: Boolean(subpayorError), disabled: locked, preserveValueOnOpen: true, value: selectedSubpayor?.label ?? "", placeholder: "Select the payer for this claims administrator\u2026", options: subpayorOptions.map((option) => {
2895
- const detail = [option.aliases?.length ? `Also known as ${option.aliases.join(", ")}` : "", option.hint ?? "", option.affiliatedEntities?.length ? `Affiliated with ${option.affiliatedEntities.join(", ")}` : "", option.default ? "Default" : ""].filter(Boolean).join(" \xB7 ");
2896
- return { id: option.id, label: option.label, ...detail ? { detail } : {}, ...option.route ? { trailing: option.route } : {} };
2897
- }), onSelect: (option) => chooseSubpayor(option.id) }),
3002
+ administrator?.payerSelectionRequired ? /* @__PURE__ */ jsxs5(Field2, { path: "claim.claimsAdministrator.payerId", label: "Payer", required: true, span: true, error: subpayorError, children: [
3003
+ subpayorOptions.length ? /* @__PURE__ */ jsx5(ComboBox, { ariaLabel: "Payer", invalid: Boolean(subpayorError), disabled: locked, value: selectedSubpayor?.label ?? "", placeholder: "Select the payer named on the claim or report\u2026", options: subpayorOptions.map((option) => {
3004
+ const identifiers = Object.entries(option.clearinghousePayerIds ?? {}).map(([name, id]) => `${name.replace(/_/g, " ")} ${id}`);
3005
+ const sourceRoute = option.sourceClearinghouse && option.sourcePayerId ? `Catalog: ${option.sourceClearinghouse} ${option.sourcePayerId}` : "";
3006
+ const detail = [option.aliases?.length ? `Also known as ${option.aliases.join(", ")}` : "", option.hint ?? "", sourceRoute].filter(Boolean).join(" \xB7 ");
3007
+ const badges = [option.optionType ? `Type: ${option.optionType}` : "", option.deliveryType ? `Delivery: ${option.deliveryType}` : "", option.clearinghouse && option.payerId ? `Delivered via ${option.clearinghouse} ${option.payerId}` : "", ...identifiers, option.preferredClearinghouse ? `Preferred: ${option.preferredClearinghouse}` : "", option.default ? "Directory default" : ""].filter(Boolean);
3008
+ return { id: option.id, label: option.label, ...detail ? { detail } : {}, ...badges.length ? { badges } : {}, ...option.affiliatedEntities?.length ? { affiliatedEntities: option.affiliatedEntities } : {}, ...option.route ? { trailing: option.route } : {} };
3009
+ }), onSelect: (option) => chooseSubpayor(option.id) }) : /* @__PURE__ */ jsxs5("div", { className: "mbsf-error", role: "alert", children: [
3010
+ "No routing payers are available for ",
3011
+ administrator.name,
3012
+ ". Electronic submission remains blocked; contact support to correct the payer directory."
3013
+ ] }),
2898
3014
  selectedSubpayor ? /* @__PURE__ */ jsxs5("div", { className: "mbsf-payer-status", role: "status", children: [
2899
3015
  /* @__PURE__ */ jsx5("strong", { children: "\u2713 Payer set:" }),
2900
3016
  " ",
2901
- selectedSubpayor.label
2902
- ] }) : /* @__PURE__ */ jsx5("small", { className: "mbsf-help", children: "This claims administrator routes bills per payer. Choose the payer that should receive this bill." })
3017
+ selectedSubpayor.label,
3018
+ selectedSubpayor.route ? ` \xB7 ${selectedSubpayor.route}` : ""
3019
+ ] }) : /* @__PURE__ */ jsxs5("small", { className: "mbsf-help", children: [
3020
+ administrator.name,
3021
+ " administers multiple payers. Choose the payer named on the claim or report so MindBill can route the bill correctly."
3022
+ ] })
2903
3023
  ] }) : null,
2904
3024
  /* @__PURE__ */ jsx5(Field2, { label: "Injury description (optional)", span: true, children: text(bill.claim.description, (description2) => setBill((c) => ({ ...c, claim: { ...c.claim, description: description2 } }))) }),
2905
3025
  /* @__PURE__ */ jsxs5(Field2, { path: "diagnoses", label: "Diagnosis codes (ICD-10)", required: true, span: true, error: errors.diagnoses, children: [
@@ -5403,7 +5523,7 @@ function sandboxScenarios(state) {
5403
5523
  function shouldShowSandboxControls(environment, enabled = false) {
5404
5524
  return enabled && environment === "sandbox";
5405
5525
  }
5406
- function ConnectedBillLifecycle({ appearance, actorName, claimsAdministratorHint, sandboxControls = false, className, style, loadingFallback, errorFallback, onChanged, ...options }) {
5526
+ function ConnectedBillLifecycle({ appearance, actorName, claimsAdministratorHint, claimsAdministratorSources, sandboxControls = false, className, style, loadingFallback, errorFallback, onChanged, ...options }) {
5407
5527
  const lifecycle = useBillLifecycle(options);
5408
5528
  const { data } = lifecycle;
5409
5529
  const [tab, setTab] = useState11("details");
@@ -5624,6 +5744,7 @@ function ConnectedBillLifecycle({ appearance, actorName, claimsAdministratorHint
5624
5744
  onSearchClaimsAdministrators: lifecycle.searchClaimsAdministrators,
5625
5745
  onGetClaimsAdministratorDirectory: lifecycle.getClaimsAdministratorDirectory,
5626
5746
  claimsAdministratorHint,
5747
+ ...claimsAdministratorSources ? { claimsAdministratorSources } : {},
5627
5748
  attentionFields: correctionAttentionFields,
5628
5749
  attentionMessage: correctionAttentionFields.length ? "The rejected response points to the highlighted fields. Confirm every required value before resubmitting." : "Confirm the bill information below before resubmitting.",
5629
5750
  submitLabel: lifecycle.isMutating ? "Resubmitting\u2026" : "Resubmit bill",
@@ -5660,6 +5781,7 @@ function ConnectedBillLifecycle({ appearance, actorName, claimsAdministratorHint
5660
5781
  onSearchClaimsAdministrators: lifecycle.searchClaimsAdministrators,
5661
5782
  onGetClaimsAdministratorDirectory: lifecycle.getClaimsAdministratorDirectory,
5662
5783
  claimsAdministratorHint,
5784
+ ...claimsAdministratorSources ? { claimsAdministratorSources } : {},
5663
5785
  attentionMessage: "Confirm every value carried over from the closed bill before submitting the new bill.",
5664
5786
  submitLabel: lifecycle.isMutating ? "Submitting\u2026" : "Submit New Bill",
5665
5787
  heading: "New bill information",