@mindbill/react 0.1.0 → 0.2.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,11 +1,77 @@
1
1
  # @mindbill/react
2
2
 
3
- React wrappers for the secure `@mindbill/embed` custom elements. See the [widget guide](https://github.com/incidentfox/mindbill-widgets/blob/main/docs/widgets.md).
3
+ MindBill's partner-facing React components. The package includes two integration
4
+ levels:
4
5
 
5
- > **Publication pending:** `@mindbill/react` and its `@mindbill/embed` dependency are not yet available from npm. The import below documents the post-publication interface and currently returns 404 through package registries. Clone the [source repository](https://github.com/incidentfox/mindbill-widgets) to evaluate it locally.
6
+ - Native, data-driven components for teams that want MindBill workflows to feel
7
+ like part of their own product.
8
+ - Hosted workflow wrappers for teams that want MindBill to own the secure UI and
9
+ API orchestration.
10
+
11
+ Import the stylesheet once near your application root.
6
12
 
7
13
  ```tsx
8
- import { MindBillBillTimeline } from "@mindbill/react";
14
+ import "@mindbill/react/styles.css";
9
15
  ```
10
16
 
11
- Create the short-lived embed session on your server; never send a Partner API key to React/browser code.
17
+ ## Native components
18
+
19
+ Native components render the same lifecycle, reporting, collections, and document
20
+ patterns used by the MindBill product. They never fetch data or receive API keys;
21
+ your application supplies already-authorized data and handles user actions.
22
+
23
+ ```tsx
24
+ import {
25
+ AccountsReceivableSummary,
26
+ BillStatusTimeline,
27
+ CollectionsTable,
28
+ } from "@mindbill/react";
29
+
30
+ <BillStatusTimeline
31
+ status="accepted"
32
+ message="Accepted by clearinghouse"
33
+ messageTone="success"
34
+ />
35
+
36
+ <AccountsReceivableSummary
37
+ totalOutstanding={184250}
38
+ buckets={[
39
+ { label: "0–30 days", amount: 61200, count: 24 },
40
+ { label: "31–60 days", amount: 48300, count: 17 },
41
+ { label: "61–90 days", amount: 31750, count: 9 },
42
+ { label: "90+ days", amount: 43000, count: 12 },
43
+ ]}
44
+ />
45
+ ```
46
+
47
+ Available native components:
48
+
49
+ - `BillStatusTimeline`
50
+ - `BillSummaryCard`
51
+ - `AccountsReceivableSummary`
52
+ - `CollectionsTable`
53
+ - `DocumentList`
54
+
55
+ ## Hosted workflows
56
+
57
+ Hosted wrappers render MindBill's short-lived, origin-bound embed sessions. Mint
58
+ the session on your server. Never expose a MindBill partner API key to the browser.
59
+
60
+ ```tsx
61
+ import { HostedCollections } from "@mindbill/react";
62
+
63
+ <HostedCollections
64
+ sessionToken={session.token}
65
+ embedUrl={session.embedUrl}
66
+ onMindBill={(event) => console.log(event.event, event.billId)}
67
+ />
68
+ ```
69
+
70
+ The available wrappers are `HostedBillTimeline`, `HostedBillFromReport`,
71
+ `HostedCollections`, and `HostedOnboarding`. The original names (`BillTimeline`,
72
+ `BillFromReport`, `Collections`, and `Onboarding`) remain available for backwards
73
+ compatibility.
74
+
75
+ See the [interactive component gallery](https://app.mindbill.org/developers/components),
76
+ [API documentation](https://app.mindbill.org/developers/reference), and
77
+ [reference integration](https://github.com/incidentfox/mindbill/tree/main/examples/partner-reference).
package/dist/index.d.ts CHANGED
@@ -1,19 +1,145 @@
1
- import { MindBillAppearance, MindBillEventDetail, MindBillErrorDetail } from '@mindbill/embed';
2
- export { MindBillAppearance, MindBillErrorDetail, MindBillEventDetail } from '@mindbill/embed';
3
- import { CSSProperties, ReactElement } from 'react';
4
-
5
- type MindBillWidgetProps = {
1
+ import "@mindbill/embed";
2
+ import { type CSSProperties, type ReactNode } from "react";
3
+ import type { MindBillEvent } from "@mindbill/embed";
4
+ export type MindBillWidgetProps = {
6
5
  sessionToken: string;
7
6
  embedUrl: string;
8
- appearance?: MindBillAppearance;
7
+ onMindBill?: (event: MindBillEvent) => void;
9
8
  className?: string;
10
9
  style?: CSSProperties;
11
- onMindBill?: (event: CustomEvent<MindBillEventDetail>) => void;
12
- onMindBillError?: (event: CustomEvent<MindBillErrorDetail>) => void;
13
- };
14
- declare function MindBillBillTimeline(props: MindBillWidgetProps): ReactElement;
15
- declare function MindBillBillFromReport(props: MindBillWidgetProps): ReactElement;
16
- declare function MindBillCollections(props: MindBillWidgetProps): ReactElement;
17
- declare function MindBillOnboarding(props: MindBillWidgetProps): ReactElement;
18
-
19
- export { MindBillBillFromReport, MindBillBillTimeline, MindBillCollections, MindBillOnboarding, type MindBillWidgetProps };
10
+ };
11
+ export declare const BillTimeline: ({ sessionToken, embedUrl, onMindBill, className, style }: MindBillWidgetProps) => import("react").ReactElement<{
12
+ ref: import("react").RefObject<HTMLElement | null>;
13
+ "session-token": string;
14
+ "embed-url": string;
15
+ className: string | undefined;
16
+ style: CSSProperties | undefined;
17
+ }, string | import("react").JSXElementConstructor<any>>;
18
+ export declare const BillFromReport: ({ sessionToken, embedUrl, onMindBill, className, style }: MindBillWidgetProps) => import("react").ReactElement<{
19
+ ref: import("react").RefObject<HTMLElement | null>;
20
+ "session-token": string;
21
+ "embed-url": string;
22
+ className: string | undefined;
23
+ style: CSSProperties | undefined;
24
+ }, string | import("react").JSXElementConstructor<any>>;
25
+ export declare const Collections: ({ sessionToken, embedUrl, onMindBill, className, style }: MindBillWidgetProps) => import("react").ReactElement<{
26
+ ref: import("react").RefObject<HTMLElement | null>;
27
+ "session-token": string;
28
+ "embed-url": string;
29
+ className: string | undefined;
30
+ style: CSSProperties | undefined;
31
+ }, string | import("react").JSXElementConstructor<any>>;
32
+ export declare const Onboarding: ({ sessionToken, embedUrl, onMindBill, className, style }: MindBillWidgetProps) => import("react").ReactElement<{
33
+ ref: import("react").RefObject<HTMLElement | null>;
34
+ "session-token": string;
35
+ "embed-url": string;
36
+ className: string | undefined;
37
+ style: CSSProperties | undefined;
38
+ }, string | import("react").JSXElementConstructor<any>>;
39
+ export declare const HostedBillTimeline: ({ sessionToken, embedUrl, onMindBill, className, style }: MindBillWidgetProps) => import("react").ReactElement<{
40
+ ref: import("react").RefObject<HTMLElement | null>;
41
+ "session-token": string;
42
+ "embed-url": string;
43
+ className: string | undefined;
44
+ style: CSSProperties | undefined;
45
+ }, string | import("react").JSXElementConstructor<any>>;
46
+ export declare const HostedBillFromReport: ({ sessionToken, embedUrl, onMindBill, className, style }: MindBillWidgetProps) => import("react").ReactElement<{
47
+ ref: import("react").RefObject<HTMLElement | null>;
48
+ "session-token": string;
49
+ "embed-url": string;
50
+ className: string | undefined;
51
+ style: CSSProperties | undefined;
52
+ }, string | import("react").JSXElementConstructor<any>>;
53
+ export declare const HostedCollections: ({ sessionToken, embedUrl, onMindBill, className, style }: MindBillWidgetProps) => import("react").ReactElement<{
54
+ ref: import("react").RefObject<HTMLElement | null>;
55
+ "session-token": string;
56
+ "embed-url": string;
57
+ className: string | undefined;
58
+ style: CSSProperties | undefined;
59
+ }, string | import("react").JSXElementConstructor<any>>;
60
+ export declare const HostedOnboarding: ({ sessionToken, embedUrl, onMindBill, className, style }: MindBillWidgetProps) => import("react").ReactElement<{
61
+ ref: import("react").RefObject<HTMLElement | null>;
62
+ "session-token": string;
63
+ "embed-url": string;
64
+ className: string | undefined;
65
+ style: CSSProperties | undefined;
66
+ }, string | import("react").JSXElementConstructor<any>>;
67
+ export type { MindBillEvent } from "@mindbill/embed";
68
+ export type BillLifecycleStatus = "incomplete" | "send" | "sent" | "accepted" | "accepted_no_response" | "processed" | "denied" | "appealing" | "ibr" | "lien" | "paid" | "closed";
69
+ export type BillStatusTimelineProps = {
70
+ status: BillLifecycleStatus;
71
+ label?: string;
72
+ message?: string;
73
+ messageTone?: "neutral" | "success" | "warning" | "danger";
74
+ className?: string;
75
+ };
76
+ export declare function BillStatusTimeline({ status, label, message, messageTone, className }: BillStatusTimelineProps): import("react/jsx-runtime").JSX.Element;
77
+ export type BillSummaryCardProps = {
78
+ billNumber: string;
79
+ status: BillLifecycleStatus | string;
80
+ patientLabel?: string;
81
+ serviceDate?: string;
82
+ charges: number;
83
+ paid: number;
84
+ balance: number;
85
+ currency?: string;
86
+ action?: ReactNode;
87
+ className?: string;
88
+ };
89
+ export declare function BillSummaryCard({ billNumber, status, patientLabel, serviceDate, charges, paid, balance, currency, action, className }: BillSummaryCardProps): import("react/jsx-runtime").JSX.Element;
90
+ export type AgingBucket = {
91
+ label: string;
92
+ amount: number;
93
+ count?: number;
94
+ };
95
+ export type PayerBalance = {
96
+ payer: string;
97
+ outstanding: number;
98
+ share?: number;
99
+ oldestDays?: number;
100
+ };
101
+ export type AccountsReceivableSummaryProps = {
102
+ totalOutstanding: number;
103
+ buckets: AgingBucket[];
104
+ payers?: PayerBalance[];
105
+ currency?: string;
106
+ title?: string;
107
+ className?: string;
108
+ };
109
+ export declare function AccountsReceivableSummary({ totalOutstanding, buckets, payers, currency, title, className }: AccountsReceivableSummaryProps): import("react/jsx-runtime").JSX.Element;
110
+ export type CollectionRow = {
111
+ id: string;
112
+ billNumber: string;
113
+ patientLabel?: string;
114
+ status: string;
115
+ submittedAt?: string;
116
+ charges: number;
117
+ paid: number;
118
+ balance: number;
119
+ aging: string;
120
+ hasEor?: boolean;
121
+ };
122
+ export type CollectionsTableProps = {
123
+ rows: CollectionRow[];
124
+ currency?: string;
125
+ onOpenBill?: (row: CollectionRow) => void;
126
+ onOpenEor?: (row: CollectionRow) => void;
127
+ className?: string;
128
+ };
129
+ export declare function CollectionsTable({ rows, currency, onOpenBill, onOpenEor, className }: CollectionsTableProps): import("react/jsx-runtime").JSX.Element;
130
+ export type DocumentItem = {
131
+ id: string;
132
+ name: string;
133
+ kind?: string;
134
+ createdAt?: string;
135
+ sizeLabel?: string;
136
+ status?: "ready" | "processing" | "needs_attention";
137
+ };
138
+ export type DocumentListProps = {
139
+ documents: DocumentItem[];
140
+ onOpen?: (document: DocumentItem) => void;
141
+ onUpload?: () => void;
142
+ title?: string;
143
+ className?: string;
144
+ };
145
+ export declare function DocumentList({ documents, onOpen, onUpload, title, className }: DocumentListProps): import("react/jsx-runtime").JSX.Element;
package/dist/index.js CHANGED
@@ -1,50 +1,57 @@
1
1
  "use client";
2
-
3
- // src/index.tsx
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
4
3
  import "@mindbill/embed";
5
4
  import { createElement, useEffect, useRef } from "react";
6
- function widget(tagName, props) {
7
- const ref = useRef(null);
8
- const { onMindBill, onMindBillError } = props;
9
- useEffect(() => {
10
- const element = ref.current;
11
- if (!element) return;
12
- const handleEvent = (event) => onMindBill?.(event);
13
- const handleError = (event) => onMindBillError?.(event);
14
- element.addEventListener("mindbill", handleEvent);
15
- element.addEventListener("mindbill-error", handleError);
16
- return () => {
17
- element.removeEventListener("mindbill", handleEvent);
18
- element.removeEventListener("mindbill-error", handleError);
5
+ function widget(tag) {
6
+ return function MindBillWidget({ sessionToken, embedUrl, onMindBill, className, style }) {
7
+ const ref = useRef(null);
8
+ useEffect(() => {
9
+ const element = ref.current;
10
+ if (!element || !onMindBill)
11
+ return;
12
+ const listener = (event) => onMindBill(event.detail);
13
+ element.addEventListener("mindbill", listener);
14
+ return () => element.removeEventListener("mindbill", listener);
15
+ }, [onMindBill]);
16
+ return createElement(tag, { ref, "session-token": sessionToken, "embed-url": embedUrl, className, style });
19
17
  };
20
- }, [onMindBill, onMindBillError]);
21
- return createElement(tagName, {
22
- ref,
23
- "session-token": props.sessionToken,
24
- "embed-url": props.embedUrl,
25
- theme: props.appearance?.theme,
26
- "accent-color": props.appearance?.accentColor,
27
- locale: props.appearance?.locale,
28
- class: props.className,
29
- style: props.style
30
- });
31
18
  }
32
- function MindBillBillTimeline(props) {
33
- return widget("mindbill-bill-timeline", props);
19
+ export const BillTimeline = widget("mindbill-bill-timeline");
20
+ export const BillFromReport = widget("mindbill-bill-from-report");
21
+ export const Collections = widget("mindbill-collections");
22
+ export const Onboarding = widget("mindbill-onboarding");
23
+ export const HostedBillTimeline = BillTimeline;
24
+ export const HostedBillFromReport = BillFromReport;
25
+ export const HostedCollections = Collections;
26
+ export const HostedOnboarding = Onboarding;
27
+ const LIFECYCLE_STAGES = [
28
+ { statuses: ["incomplete", "send"], label: "Incomplete" },
29
+ { statuses: ["sent"], label: "Queued" },
30
+ { statuses: ["accepted", "accepted_no_response"], label: "Accepted" },
31
+ { statuses: ["processed", "denied", "appealing"], label: "Processed" },
32
+ { statuses: ["ibr", "lien"], label: "IBR / Lien" },
33
+ { statuses: ["paid", "closed"], label: "Closed" },
34
+ ];
35
+ export function BillStatusTimeline({ status, label = "Bill payment cycle", message, messageTone = "neutral", className = "" }) {
36
+ const activeIndex = Math.max(0, LIFECYCLE_STAGES.findIndex((stage) => stage.statuses.includes(status)));
37
+ return (_jsxs("section", { className: `mb-card mb-timeline ${className}`, "aria-label": label, children: [_jsxs("div", { className: "mb-section-head", children: [_jsx("span", { className: "mb-kicker", children: label }), message ? _jsx("span", { className: `mb-badge mb-badge--${messageTone}`, children: message }) : null] }), _jsx("ol", { className: "mb-timeline__track", children: LIFECYCLE_STAGES.map((stage, index) => {
38
+ const state = index < activeIndex ? "complete" : index === activeIndex ? "current" : "upcoming";
39
+ return (_jsxs("li", { className: `mb-timeline__step mb-timeline__step--${state}`, "aria-current": state === "current" ? "step" : undefined, children: [_jsx("span", { className: "mb-timeline__dot", "aria-hidden": "true", children: state === "complete" ? "✓" : "" }), _jsx("span", { children: stage.label })] }, stage.label));
40
+ }) })] }));
34
41
  }
35
- function MindBillBillFromReport(props) {
36
- return widget("mindbill-bill-from-report", props);
42
+ function money(value, currency = "USD") {
43
+ return new Intl.NumberFormat("en-US", { style: "currency", currency, maximumFractionDigits: 2 }).format(value);
37
44
  }
38
- function MindBillCollections(props) {
39
- return widget("mindbill-collections", props);
45
+ export function BillSummaryCard({ billNumber, status, patientLabel, serviceDate, charges, paid, balance, currency = "USD", action, className = "" }) {
46
+ return (_jsxs("article", { className: `mb-card mb-bill ${className}`, children: [_jsxs("div", { className: "mb-section-head mb-bill__head", children: [_jsxs("div", { children: [_jsx("span", { className: "mb-kicker", children: "Bill" }), _jsxs("h3", { children: ["#", billNumber] })] }), _jsx("span", { className: "mb-badge mb-badge--neutral", children: status.replace(/_/g, " ") })] }), (patientLabel || serviceDate) ? _jsxs("p", { className: "mb-bill__context", children: [patientLabel, patientLabel && serviceDate ? " · " : "", serviceDate] }) : null, _jsxs("dl", { className: "mb-metrics", children: [_jsxs("div", { children: [_jsx("dt", { children: "Charges" }), _jsx("dd", { children: money(charges, currency) })] }), _jsxs("div", { children: [_jsx("dt", { children: "Paid" }), _jsx("dd", { className: "mb-positive", children: money(paid, currency) })] }), _jsxs("div", { children: [_jsx("dt", { children: "Balance" }), _jsx("dd", { children: money(balance, currency) })] })] }), action ? _jsx("div", { className: "mb-card__action", children: action }) : null] }));
40
47
  }
41
- function MindBillOnboarding(props) {
42
- return widget("mindbill-onboarding", props);
48
+ export function AccountsReceivableSummary({ totalOutstanding, buckets, payers = [], currency = "USD", title = "Accounts receivable", className = "" }) {
49
+ const max = Math.max(...buckets.map((bucket) => bucket.amount), 1);
50
+ return (_jsxs("section", { className: `mb-card mb-report ${className}`, children: [_jsxs("div", { className: "mb-section-head", children: [_jsxs("div", { children: [_jsx("span", { className: "mb-kicker", children: "Reporting" }), _jsx("h3", { children: title })] }), _jsx("strong", { className: "mb-report__total", children: money(totalOutstanding, currency) })] }), _jsx("div", { className: "mb-aging", "aria-label": "Outstanding balance by age", children: buckets.map((bucket, index) => (_jsxs("div", { className: "mb-aging__item", children: [_jsxs("div", { className: "mb-aging__label", children: [_jsx("span", { children: bucket.label }), _jsx("strong", { children: money(bucket.amount, currency) })] }), _jsx("div", { className: "mb-aging__bar", children: _jsx("i", { style: { width: `${Math.max(3, (bucket.amount / max) * 100)}%` } }) }), bucket.count == null ? null : _jsxs("small", { children: [bucket.count, " bill", bucket.count === 1 ? "" : "s"] })] }, bucket.label))) }), payers.length ? _jsxs("div", { className: "mb-payers", children: [_jsxs("div", { className: "mb-table-head", children: [_jsx("span", { children: "Payer exposure" }), _jsx("span", { children: "Outstanding" })] }), payers.map((payer) => _jsxs("div", { className: "mb-payer", children: [_jsxs("span", { children: [_jsx("strong", { children: payer.payer }), payer.oldestDays == null ? null : _jsxs("small", { children: ["Oldest ", payer.oldestDays, "d"] })] }), _jsxs("span", { children: [_jsx("strong", { children: money(payer.outstanding, currency) }), payer.share == null ? null : _jsxs("small", { children: [payer.share, "% of AR"] })] })] }, payer.payer))] }) : null] }));
51
+ }
52
+ export function CollectionsTable({ rows, currency = "USD", onOpenBill, onOpenEor, className = "" }) {
53
+ return _jsxs("section", { className: `mb-card mb-collections ${className}`, children: [_jsxs("div", { className: "mb-section-head", children: [_jsxs("div", { children: [_jsx("span", { className: "mb-kicker", children: "Collections" }), _jsx("h3", { children: "Open balances" })] }), _jsxs("span", { className: "mb-badge mb-badge--neutral", children: [rows.length, " bills"] })] }), _jsx("div", { className: "mb-table-scroll", children: _jsxs("table", { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Bill" }), _jsx("th", { children: "Patient" }), _jsx("th", { children: "Status" }), _jsx("th", { children: "Aging" }), _jsx("th", { className: "mb-numeric", children: "Charges" }), _jsx("th", { className: "mb-numeric", children: "Paid" }), _jsx("th", { className: "mb-numeric", children: "Balance" }), onOpenEor ? _jsx("th", { children: _jsx("span", { className: "mb-sr-only", children: "Actions" }) }) : null] }) }), _jsx("tbody", { children: rows.map((row) => _jsxs("tr", { children: [_jsx("td", { children: onOpenBill ? _jsxs("button", { className: "mb-link", onClick: () => onOpenBill(row), "aria-label": `Open bill ${row.billNumber}`, children: ["#", row.billNumber] }) : _jsxs(_Fragment, { children: ["#", row.billNumber] }) }), _jsx("td", { children: row.patientLabel || "—" }), _jsx("td", { children: _jsx("span", { className: "mb-badge mb-badge--neutral", children: row.status.replace(/_/g, " ") }) }), _jsx("td", { children: row.aging }), _jsx("td", { className: "mb-numeric", children: money(row.charges, currency) }), _jsx("td", { className: "mb-numeric mb-positive", children: money(row.paid, currency) }), _jsx("td", { className: "mb-numeric", children: _jsx("strong", { children: money(row.balance, currency) }) }), onOpenEor ? _jsx("td", { children: row.hasEor ? _jsx("button", { className: "mb-button mb-button--secondary", onClick: () => onOpenEor(row), "aria-label": `View EOR for bill ${row.billNumber}`, children: "View EOR" }) : null }) : null] }, row.id)) })] }) })] });
54
+ }
55
+ export function DocumentList({ documents, onOpen, onUpload, title = "Documents", className = "" }) {
56
+ return _jsxs("section", { className: `mb-card mb-documents ${className}`, children: [_jsxs("div", { className: "mb-section-head", children: [_jsxs("div", { children: [_jsx("span", { className: "mb-kicker", children: "Bill files" }), _jsx("h3", { children: title })] }), onUpload ? _jsx("button", { className: "mb-button", onClick: onUpload, children: "Upload document" }) : null] }), _jsx("ul", { children: documents.map((document) => _jsxs("li", { children: [_jsx("span", { className: "mb-file-icon", "aria-hidden": "true", children: "PDF" }), _jsxs("span", { className: "mb-file-copy", children: [_jsx("strong", { children: document.name }), _jsx("small", { children: [document.kind, document.createdAt, document.sizeLabel].filter(Boolean).join(" · ") })] }), document.status ? _jsx("span", { className: `mb-badge mb-badge--${document.status === "ready" ? "success" : document.status === "needs_attention" ? "warning" : "neutral"}`, children: document.status.replace(/_/g, " ") }) : null, onOpen ? _jsx("button", { className: "mb-button mb-button--secondary", onClick: () => onOpen(document), "aria-label": `Open ${document.name}`, children: "Open" }) : null] }, document.id)) })] });
43
57
  }
44
- export {
45
- MindBillBillFromReport,
46
- MindBillBillTimeline,
47
- MindBillCollections,
48
- MindBillOnboarding
49
- };
50
- //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ .mb-card{--mb-ink:#12211c;--mb-primary:#0e5c5e;--mb-positive:#267653;--mb-warning:#9a5b16;--mb-danger:#a52a2a;--mb-muted:#64716b;--mb-border:#d7ddd8;--mb-soft:#f2f5f1;box-sizing:border-box;border:1px solid var(--mb-border);border-radius:12px;background:#fffdf8;color:var(--mb-ink);font:14px/1.45 Inter Tight,ui-sans-serif,system-ui,-apple-system,sans-serif;box-shadow:0 1px 2px rgba(18,33,28,.04);overflow:hidden}.mb-card *{box-sizing:border-box}.mb-card h3{margin:4px 0 0;font-size:19px;line-height:1.2;letter-spacing:-.025em}.mb-section-head{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:18px 20px}.mb-kicker{color:var(--mb-muted);font-size:10px;font-weight:750;letter-spacing:.1em;text-transform:uppercase}.mb-badge{display:inline-flex;align-items:center;max-width:100%;border-radius:999px;padding:4px 8px;font-size:11px;font-weight:700;line-height:1.2;text-transform:capitalize;white-space:nowrap}.mb-badge--neutral{background:#e8f0ec;color:#31564a}.mb-badge--success{background:#e1f3e8;color:#226044}.mb-badge--warning{background:#f8ead5;color:#81501c}.mb-badge--danger{background:#f9e3e1;color:#922e2d}.mb-timeline{padding-bottom:18px}.mb-timeline__track{position:relative;display:grid;grid-template-columns:repeat(6,minmax(70px,1fr));margin:0;padding:4px 18px 0;list-style:none}.mb-timeline__track:before{position:absolute;top:16px;left:8%;right:8%;height:1px;background:var(--mb-border);content:""}.mb-timeline__step{position:relative;display:flex;z-index:1;flex-direction:column;align-items:center;gap:7px;color:#7c8983;font-size:10px;font-weight:650;text-align:center}.mb-timeline__dot{display:grid;width:25px;height:25px;place-items:center;border:2px solid var(--mb-border);border-radius:50%;background:#fffdf8;color:white;font-size:12px}.mb-timeline__step--complete{color:var(--mb-positive)}.mb-timeline__step--complete .mb-timeline__dot{border-color:var(--mb-positive);background:var(--mb-positive)}.mb-timeline__step--current{color:var(--mb-primary)}.mb-timeline__step--current .mb-timeline__dot{border:7px solid var(--mb-primary);background:white}.mb-bill__context{margin:-8px 20px 0;color:var(--mb-muted);font-size:12px}.mb-metrics{display:grid;grid-template-columns:repeat(3,1fr);margin:18px 0 0;border-top:1px solid var(--mb-border)}.mb-metrics>div{padding:15px 20px;border-right:1px solid var(--mb-border)}.mb-metrics>div:last-child{border:0}.mb-metrics dt{color:var(--mb-muted);font-size:10px;font-weight:750;letter-spacing:.08em;text-transform:uppercase}.mb-metrics dd{margin:4px 0 0;font-size:18px;font-weight:730;font-variant-numeric:tabular-nums}.mb-positive{color:var(--mb-positive)!important}.mb-card__action{border-top:1px solid var(--mb-border);padding:12px 20px}.mb-report{padding-bottom:4px}.mb-report__total{font-size:25px;letter-spacing:-.04em;font-variant-numeric:tabular-nums}.mb-aging{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;padding:5px 20px 22px}.mb-aging__label{display:flex;justify-content:space-between;gap:8px;font-size:12px}.mb-aging__label strong{font-variant-numeric:tabular-nums}.mb-aging__bar{height:7px;margin-top:8px;border-radius:999px;background:#e5ebe7;overflow:hidden}.mb-aging__bar i{display:block;height:100%;border-radius:inherit;background:var(--mb-primary)}.mb-aging__item:nth-child(3) i{background:#bf7a2e}.mb-aging__item:nth-child(4) i{background:#a3473f}.mb-aging small,.mb-payer small,.mb-file-copy small{display:block;margin-top:5px;color:var(--mb-muted);font-size:10px}.mb-payers{border-top:1px solid var(--mb-border)}.mb-table-head,.mb-payer{display:grid;grid-template-columns:1fr auto;gap:20px;padding:11px 20px}.mb-table-head{background:var(--mb-soft);color:var(--mb-muted);font-size:10px;font-weight:750;letter-spacing:.08em;text-transform:uppercase}.mb-payer{align-items:center;border-top:1px solid #e7ebe8}.mb-payer:first-of-type{border-top:0}.mb-payer>span:last-child{text-align:right;font-variant-numeric:tabular-nums}.mb-table-scroll{overflow-x:auto}.mb-collections table{width:100%;border-collapse:collapse;font-size:12px}.mb-collections th,.mb-collections td{padding:11px 13px;border-top:1px solid #e5e9e6;text-align:left;white-space:nowrap}.mb-collections th{background:var(--mb-soft);color:var(--mb-muted);font-size:9px;letter-spacing:.08em;text-transform:uppercase}.mb-numeric{text-align:right!important;font-variant-numeric:tabular-nums}.mb-button,.mb-link{border:0;font:inherit;cursor:pointer}.mb-button{min-height:31px;border-radius:7px;background:var(--mb-primary);color:#fff;padding:6px 10px;font-size:11px;font-weight:700}.mb-button--secondary{border:1px solid #b8c6bf;background:#fff;color:#244c40}.mb-button:hover,.mb-button:focus-visible,.mb-link:hover,.mb-link:focus-visible{filter:brightness(.92)}.mb-button:focus-visible,.mb-link:focus-visible{outline:3px solid rgba(14,92,94,.25);outline-offset:2px}.mb-link{background:transparent;color:var(--mb-primary);padding:0;font-weight:750;text-decoration:underline;text-decoration-color:#aac5bb;text-underline-offset:3px}.mb-documents ul{margin:0;padding:0;list-style:none}.mb-documents li{display:grid;grid-template-columns:auto minmax(0,1fr) auto auto;align-items:center;gap:12px;padding:13px 20px;border-top:1px solid #e5e9e6}.mb-file-icon{display:grid;width:34px;height:38px;place-items:center;border-radius:5px;background:#e7f0ec;color:var(--mb-primary);font-size:9px;font-weight:800;letter-spacing:.05em}.mb-file-copy{min-width:0}.mb-file-copy strong{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mb-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media(max-width:700px){.mb-section-head{align-items:flex-start}.mb-timeline__track{grid-template-columns:repeat(6,82px);overflow-x:auto;justify-content:flex-start;padding-bottom:6px}.mb-timeline__track:before{display:none}.mb-aging{grid-template-columns:repeat(2,1fr)}.mb-documents li{grid-template-columns:auto minmax(0,1fr) auto}.mb-documents li>.mb-badge{display:none}}@media(max-width:420px){.mb-metrics{grid-template-columns:1fr}.mb-metrics>div{border-right:0;border-bottom:1px solid var(--mb-border)}.mb-aging{grid-template-columns:1fr}.mb-report__total{font-size:19px}.mb-documents li{grid-template-columns:auto minmax(0,1fr)}.mb-documents li>.mb-button{grid-column:2;justify-self:start}}
package/package.json CHANGED
@@ -1,51 +1,17 @@
1
1
  {
2
2
  "name": "@mindbill/react",
3
- "version": "0.1.0",
4
- "description": "React components for MindBill hosted billing workflows",
3
+ "version": "0.2.0",
5
4
  "type": "module",
6
5
  "main": "./dist/index.js",
7
- "module": "./dist/index.js",
8
6
  "types": "./dist/index.d.ts",
9
7
  "exports": {
10
- ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js"
13
- }
8
+ ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
9
+ "./styles.css": "./dist/styles.css"
14
10
  },
15
- "files": [
16
- "dist",
17
- "README.md"
18
- ],
19
- "peerDependencies": {
20
- "react": ">=18"
21
- },
22
- "dependencies": {
23
- "@mindbill/embed": "^0.2.0"
24
- },
25
- "keywords": [
26
- "mindbill",
27
- "react",
28
- "medical-legal",
29
- "workers-compensation",
30
- "widget"
31
- ],
32
- "license": "MIT",
33
- "repository": {
34
- "type": "git",
35
- "url": "git+https://github.com/incidentfox/mindbill-widgets.git",
36
- "directory": "packages/react"
37
- },
38
- "homepage": "https://github.com/incidentfox/mindbill-widgets#readme",
39
- "bugs": {
40
- "url": "https://github.com/incidentfox/mindbill-widgets/issues"
41
- },
42
- "publishConfig": {
43
- "access": "public",
44
- "provenance": true
45
- },
46
- "sideEffects": true,
11
+ "files": ["dist", "README.md"],
47
12
  "scripts": {
48
- "build": "tsup src/index.tsx --format esm --dts --clean --sourcemap --external react --external react/jsx-runtime",
49
- "clean": "rm -rf dist"
50
- }
51
- }
13
+ "build": "tsc -p tsconfig.build.json && node -e \"require('node:fs').copyFileSync('src/styles.css','dist/styles.css')\""
14
+ },
15
+ "dependencies": { "@mindbill/embed": "^0.2.0" },
16
+ "peerDependencies": { "react": ">=18" }
17
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 IncidentFox, Inc.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["\"use client\";\n\nimport \"@mindbill/embed\";\nimport type { CSSProperties, ReactElement } from \"react\";\nimport { createElement, useEffect, useRef } from \"react\";\nimport type { MindBillAppearance, MindBillErrorDetail, MindBillEventDetail } from \"@mindbill/embed\";\n\nexport type MindBillWidgetProps = {\n sessionToken: string;\n embedUrl: string;\n appearance?: MindBillAppearance;\n className?: string;\n style?: CSSProperties;\n onMindBill?: (event: CustomEvent<MindBillEventDetail>) => void;\n onMindBillError?: (event: CustomEvent<MindBillErrorDetail>) => void;\n};\n\nfunction widget(tagName: string, props: MindBillWidgetProps): ReactElement {\n const ref = useRef<HTMLElement | null>(null);\n const { onMindBill, onMindBillError } = props;\n useEffect(() => {\n const element = ref.current;\n if (!element) return;\n const handleEvent = (event: Event) => onMindBill?.(event as CustomEvent<MindBillEventDetail>);\n const handleError = (event: Event) => onMindBillError?.(event as CustomEvent<MindBillErrorDetail>);\n element.addEventListener(\"mindbill\", handleEvent);\n element.addEventListener(\"mindbill-error\", handleError);\n return () => {\n element.removeEventListener(\"mindbill\", handleEvent);\n element.removeEventListener(\"mindbill-error\", handleError);\n };\n }, [onMindBill, onMindBillError]);\n\n return createElement(tagName, {\n ref,\n \"session-token\": props.sessionToken,\n \"embed-url\": props.embedUrl,\n theme: props.appearance?.theme,\n \"accent-color\": props.appearance?.accentColor,\n locale: props.appearance?.locale,\n class: props.className,\n style: props.style,\n });\n}\n\nexport function MindBillBillTimeline(props: MindBillWidgetProps): ReactElement {\n return widget(\"mindbill-bill-timeline\", props);\n}\nexport function MindBillBillFromReport(props: MindBillWidgetProps): ReactElement {\n return widget(\"mindbill-bill-from-report\", props);\n}\nexport function MindBillCollections(props: MindBillWidgetProps): ReactElement {\n return widget(\"mindbill-collections\", props);\n}\nexport function MindBillOnboarding(props: MindBillWidgetProps): ReactElement {\n return widget(\"mindbill-onboarding\", props);\n}\n\nexport type { MindBillAppearance, MindBillErrorDetail, MindBillEventDetail } from \"@mindbill/embed\";\n"],"mappings":";;;AAEA,OAAO;AAEP,SAAS,eAAe,WAAW,cAAc;AAajD,SAAS,OAAO,SAAiB,OAA0C;AACzE,QAAM,MAAM,OAA2B,IAAI;AAC3C,QAAM,EAAE,YAAY,gBAAgB,IAAI;AACxC,YAAU,MAAM;AACd,UAAM,UAAU,IAAI;AACpB,QAAI,CAAC,QAAS;AACd,UAAM,cAAc,CAAC,UAAiB,aAAa,KAAyC;AAC5F,UAAM,cAAc,CAAC,UAAiB,kBAAkB,KAAyC;AACjG,YAAQ,iBAAiB,YAAY,WAAW;AAChD,YAAQ,iBAAiB,kBAAkB,WAAW;AACtD,WAAO,MAAM;AACX,cAAQ,oBAAoB,YAAY,WAAW;AACnD,cAAQ,oBAAoB,kBAAkB,WAAW;AAAA,IAC3D;AAAA,EACF,GAAG,CAAC,YAAY,eAAe,CAAC;AAEhC,SAAO,cAAc,SAAS;AAAA,IAC5B;AAAA,IACA,iBAAiB,MAAM;AAAA,IACvB,aAAa,MAAM;AAAA,IACnB,OAAO,MAAM,YAAY;AAAA,IACzB,gBAAgB,MAAM,YAAY;AAAA,IAClC,QAAQ,MAAM,YAAY;AAAA,IAC1B,OAAO,MAAM;AAAA,IACb,OAAO,MAAM;AAAA,EACf,CAAC;AACH;AAEO,SAAS,qBAAqB,OAA0C;AAC7E,SAAO,OAAO,0BAA0B,KAAK;AAC/C;AACO,SAAS,uBAAuB,OAA0C;AAC/E,SAAO,OAAO,6BAA6B,KAAK;AAClD;AACO,SAAS,oBAAoB,OAA0C;AAC5E,SAAO,OAAO,wBAAwB,KAAK;AAC7C;AACO,SAAS,mBAAmB,OAA0C;AAC3E,SAAO,OAAO,uBAAuB,KAAK;AAC5C;","names":[]}