@usebridge/sdk-react 0.4.0 → 0.5.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/dist/index.d.cts CHANGED
@@ -29,7 +29,7 @@ declare function useBridgeSdk(): BridgeSdk;
29
29
  * @param query the query to search for, may be an empty string
30
30
  * @param limit the maximum number of results to return, defaults to 10
31
31
  */
32
- declare function usePayerAutocomplete(query: string, { limit, }: {
32
+ declare function usePayerAutocomplete(query: string, { limit, }?: {
33
33
  /**
34
34
  * The maximum number of results to return, defaults to 10
35
35
  */
@@ -162,7 +162,7 @@ type FieldState<F extends Field, T = EligibilityInputState[F]["value"]> = {
162
162
  /**
163
163
  * Manages the input state for each field
164
164
  */
165
- declare function useEligibilityInputField<F extends Field, T = EligibilityInputState[F]["value"]>(field: F): FieldState<F, T>;
165
+ declare function useEligibilityInputField<F extends Field, T = EligibilityInputState[F]["value"]>(field: F, defaultValue?: T): FieldState<F, T>;
166
166
 
167
167
  /**
168
168
  * Aggregated determination of whether all inputs are valid
package/dist/index.d.ts CHANGED
@@ -29,7 +29,7 @@ declare function useBridgeSdk(): BridgeSdk;
29
29
  * @param query the query to search for, may be an empty string
30
30
  * @param limit the maximum number of results to return, defaults to 10
31
31
  */
32
- declare function usePayerAutocomplete(query: string, { limit, }: {
32
+ declare function usePayerAutocomplete(query: string, { limit, }?: {
33
33
  /**
34
34
  * The maximum number of results to return, defaults to 10
35
35
  */
@@ -162,7 +162,7 @@ type FieldState<F extends Field, T = EligibilityInputState[F]["value"]> = {
162
162
  /**
163
163
  * Manages the input state for each field
164
164
  */
165
- declare function useEligibilityInputField<F extends Field, T = EligibilityInputState[F]["value"]>(field: F): FieldState<F, T>;
165
+ declare function useEligibilityInputField<F extends Field, T = EligibilityInputState[F]["value"]>(field: F, defaultValue?: T): FieldState<F, T>;
166
166
 
167
167
  /**
168
168
  * Aggregated determination of whether all inputs are valid
package/dist/index.js CHANGED
@@ -159,22 +159,44 @@ var require_lodash = __commonJS({
159
159
  });
160
160
 
161
161
  // src/sdk/index.tsx
162
- import { createContext, useContext, useRef } from "react";
162
+ import { createContext, useContext, useRef as useRef2 } from "react";
163
163
  import { BridgeSdk as BridgeSdk2 } from "@usebridge/sdk-core";
164
164
 
165
165
  // src/sdk/use-prefetch-payers.ts
166
166
  import "@usebridge/sdk-core";
167
- import { useEffect } from "react";
167
+ import { useEffect, useRef } from "react";
168
168
  function usePrefetchPayers(bridgeSdk, enabled) {
169
+ const fetched = useRef(false);
169
170
  useEffect(() => {
171
+ if (fetched.current) return;
170
172
  if (enabled) {
171
173
  void Promise.all(
172
174
  ["", "b", "u", "a"].map((query) => bridgeSdk.payerSearch({ query, limit: 10 }))
173
175
  );
176
+ fetched.current = true;
174
177
  }
175
178
  }, [bridgeSdk, enabled]);
176
179
  }
177
180
 
181
+ // src/sdk/use-analytics-lifecycle.ts
182
+ import { useEffect as useEffect2 } from "react";
183
+ function useAnalyticsLifecycle(bridgeSdk) {
184
+ useEffect2(() => {
185
+ return () => {
186
+ bridgeSdk._analytics.flush();
187
+ };
188
+ }, [bridgeSdk]);
189
+ useEffect2(() => {
190
+ const flush = () => {
191
+ if (document.visibilityState === "hidden") bridgeSdk._analytics.flush();
192
+ };
193
+ if (typeof window !== "undefined") window.addEventListener("visibilitychange", flush);
194
+ return () => {
195
+ if (typeof window !== "undefined") window.removeEventListener("visibilitychange", flush);
196
+ };
197
+ }, [bridgeSdk]);
198
+ }
199
+
178
200
  // src/sdk/index.tsx
179
201
  import { jsxs } from "react/jsx-runtime";
180
202
  var BridgeSdkContext = createContext(null);
@@ -183,8 +205,11 @@ var BridgeSdkProvider = ({
183
205
  prefetchPayers = true,
184
206
  children
185
207
  }) => {
186
- const { current } = useRef(new BridgeSdk2(config));
208
+ const sdkRef = useRef2(null);
209
+ if (!sdkRef.current) sdkRef.current = new BridgeSdk2(config);
210
+ const current = sdkRef.current;
187
211
  usePrefetchPayers(current, prefetchPayers);
212
+ useAnalyticsLifecycle(current);
188
213
  return /* @__PURE__ */ jsxs(BridgeSdkContext.Provider, { value: current, children: [
189
214
  " ",
190
215
  children,
@@ -198,14 +223,14 @@ function useBridgeSdk() {
198
223
  }
199
224
 
200
225
  // src/payer-search/use-payer-autocomplete.ts
201
- import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useState as useState2 } from "react";
226
+ import { useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState2 } from "react";
202
227
 
203
228
  // ../../node_modules/usehooks-ts/dist/index.js
204
229
  var import_lodash = __toESM(require_lodash(), 1);
205
- import { useState, useCallback, useLayoutEffect, useEffect as useEffect2, useRef as useRef2, useMemo } from "react";
230
+ import { useState, useCallback, useLayoutEffect, useEffect as useEffect3, useRef as useRef3, useMemo } from "react";
206
231
  function useIsMounted() {
207
- const isMounted = useRef2(false);
208
- useEffect2(() => {
232
+ const isMounted = useRef3(false);
233
+ useEffect3(() => {
209
234
  isMounted.current = true;
210
235
  return () => {
211
236
  isMounted.current = false;
@@ -226,7 +251,7 @@ async function retryLoop(fn, shouldRetry, delayMs = 500) {
226
251
  while (!cancelled) {
227
252
  try {
228
253
  return await fn();
229
- } catch (err) {
254
+ } catch (_) {
230
255
  if (!shouldRetry()) {
231
256
  cancelled = true;
232
257
  } else {
@@ -1780,14 +1805,14 @@ var omit_default = omit;
1780
1805
  var resultCache = /* @__PURE__ */ new Map();
1781
1806
  function usePayerAutocomplete(query, {
1782
1807
  limit = 10
1783
- }) {
1808
+ } = {}) {
1784
1809
  const payerSearch = usePayerSearch();
1785
1810
  const [isLoading, setIsLoading] = useState2(false);
1786
1811
  const [results, setResults] = useState2([]);
1787
1812
  const normalizedQuery = query.trim().toLowerCase();
1788
- const reqId = useRef3(0);
1813
+ const reqId = useRef4(0);
1789
1814
  const isMounted = useIsMounted();
1790
- useEffect3(() => {
1815
+ useEffect4(() => {
1791
1816
  const thisId = ++reqId.current;
1792
1817
  const cachedResults = resultCache.get(normalizedQuery);
1793
1818
  if (cachedResults) {
@@ -1830,7 +1855,7 @@ import { createContext as createContext2 } from "react";
1830
1855
  var SoftEligibilityContext = createContext2(null);
1831
1856
 
1832
1857
  // src/eligibility-input/eligibility-input-provider.tsx
1833
- import { useContext as useContext5, useRef as useRef4 } from "react";
1858
+ import { useContext as useContext5, useRef as useRef6 } from "react";
1834
1859
  import "zustand";
1835
1860
 
1836
1861
  // src/eligibility-input/eligibility-input-store.ts
@@ -1894,7 +1919,7 @@ var HardEligibilityProvider = ({
1894
1919
  }) => /* @__PURE__ */ jsx(HardEligibilityContext.Provider, { value: session, children: /* @__PURE__ */ jsx(EligibilityInputProvider, { children }) });
1895
1920
 
1896
1921
  // src/hard-eligibility/use-hard-eligibility-state.ts
1897
- import { useEffect as useEffect4, useState as useState3 } from "react";
1922
+ import { useEffect as useEffect5, useState as useState3 } from "react";
1898
1923
  import "@usebridge/sdk-core";
1899
1924
 
1900
1925
  // src/hard-eligibility/use-hard-eligibility.ts
@@ -1910,7 +1935,7 @@ function useHardEligibilitySession() {
1910
1935
  function useHardEligibilityState() {
1911
1936
  const session = useHardEligibilitySession();
1912
1937
  const [state, setState] = useState3(session.state);
1913
- useEffect4(() => {
1938
+ useEffect5(() => {
1914
1939
  session.on("update", setState);
1915
1940
  return () => {
1916
1941
  session.removeListener("update", setState);
@@ -1938,9 +1963,9 @@ import {
1938
1963
  } from "@usebridge/sdk-core";
1939
1964
 
1940
1965
  // src/eligibility-input/use-eligibility-input-field.ts
1941
- import { useContext as useContext4, useEffect as useEffect5, useMemo as useMemo3, useState as useState4 } from "react";
1966
+ import { useContext as useContext4, useEffect as useEffect6, useMemo as useMemo3, useRef as useRef5, useState as useState4, useLayoutEffect as useLayoutEffect2 } from "react";
1942
1967
  import { HardEligibility, SoftEligibility } from "@usebridge/sdk-core";
1943
- function useEligibilityInputField(field) {
1968
+ function useEligibilityInputField(field, defaultValue) {
1944
1969
  const input = useEligibilityInput();
1945
1970
  const inputField = input[field];
1946
1971
  const { requirePatient } = input;
@@ -1949,19 +1974,19 @@ function useEligibilityInputField(field) {
1949
1974
  let isDisabled = false;
1950
1975
  const [forceMemberId, setForceMemberId] = useState4(false);
1951
1976
  const errorForceMemberId = hardEligibilityContext?.state.error?.forceMemberId;
1952
- useEffect5(() => {
1977
+ useEffect6(() => {
1953
1978
  if (errorForceMemberId) setForceMemberId(true);
1954
1979
  }, [errorForceMemberId]);
1955
1980
  try {
1956
1981
  const { status } = useHardEligibilityState();
1957
1982
  isDisabled = !HardEligibility.canSubmit(status);
1958
1983
  if (status === "WAITING_FOR_SERVICE_ELIGIBILITY") isDisabled = true;
1959
- } catch (err) {
1984
+ } catch (_) {
1960
1985
  }
1961
1986
  try {
1962
1987
  const { status } = useSoftEligibilityState();
1963
1988
  isDisabled = !SoftEligibility.canSubmit(status);
1964
- } catch (err) {
1989
+ } catch (_) {
1965
1990
  }
1966
1991
  if (requirePatient && !hardEligibilityContext)
1967
1992
  throw new Error(`useEligibilityInputField("${field}") requires a HardEligibilityContext`);
@@ -2003,16 +2028,23 @@ function useEligibilityInputField(field) {
2003
2028
  default:
2004
2029
  throw new Error(`Unknown field: ${field}`);
2005
2030
  }
2031
+ const setValue = set;
2032
+ const hasSetDefaultValue = useRef5(false);
2033
+ useLayoutEffect2(() => {
2034
+ if (hasSetDefaultValue.current) return;
2035
+ if (defaultValue) setValue(defaultValue);
2036
+ hasSetDefaultValue.current = true;
2037
+ }, [setValue, defaultValue]);
2006
2038
  return useMemo3(
2007
2039
  () => ({
2008
2040
  value,
2009
- setValue: set,
2041
+ setValue,
2010
2042
  isVisible,
2011
2043
  isValid,
2012
2044
  isRequired,
2013
2045
  isDisabled
2014
2046
  }),
2015
- [value, set, isVisible, isValid, isRequired, isDisabled]
2047
+ [value, setValue, isVisible, isValid, isRequired, isDisabled]
2016
2048
  );
2017
2049
  }
2018
2050
 
@@ -2063,10 +2095,44 @@ function useHardEligibilitySubmit() {
2063
2095
  return useMemo4(() => ({ isDisabled, submit }), [isDisabled, submit]);
2064
2096
  }
2065
2097
 
2098
+ // src/eligibility-input/eligibility-input-analytics.tsx
2099
+ import { useEffect as useEffect7, useMemo as useMemo5 } from "react";
2100
+ function useEligibilityInputFieldState(field) {
2101
+ const fieldState = useEligibilityInputField(field);
2102
+ return useMemo5(
2103
+ () => omit_default(fieldState, "setValue"),
2104
+ [
2105
+ fieldState.value,
2106
+ fieldState.isVisible,
2107
+ fieldState.isValid,
2108
+ fieldState.isRequired,
2109
+ fieldState.isDisabled
2110
+ ]
2111
+ );
2112
+ }
2113
+ var EligibilityInputAnalytics = () => {
2114
+ const { _analytics: analytics } = useBridgeSdk();
2115
+ const firstName = useEligibilityInputFieldState("firstName");
2116
+ const lastName = useEligibilityInputFieldState("lastName");
2117
+ const dateOfBirth = useEligibilityInputFieldState("dateOfBirth");
2118
+ const memberId = useEligibilityInputFieldState("memberId");
2119
+ const payer = useEligibilityInputFieldState("payer");
2120
+ const state = useEligibilityInputFieldState("state");
2121
+ const isValid = useEligibilityInputIsValid();
2122
+ const payload = useMemo5(
2123
+ () => ({ firstName, lastName, dateOfBirth, memberId, payer, state, isValid }),
2124
+ [firstName, lastName, dateOfBirth, memberId, payer, state, isValid]
2125
+ );
2126
+ useEffect7(() => {
2127
+ analytics.event("input.state.updated", payload);
2128
+ }, [analytics, payload]);
2129
+ return null;
2130
+ };
2131
+
2066
2132
  // src/eligibility-input/eligibility-input-provider.tsx
2067
- import { jsx as jsx2 } from "react/jsx-runtime";
2133
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
2068
2134
  var EligibilityInputProvider = ({ children }) => {
2069
- const storeRef = useRef4(null);
2135
+ const storeRef = useRef6(null);
2070
2136
  const softEligibilityContext = useContext5(SoftEligibilityContext);
2071
2137
  const hardEligibilityContext = useContext5(HardEligibilityContext);
2072
2138
  if (!storeRef.current) {
@@ -2076,7 +2142,10 @@ var EligibilityInputProvider = ({ children }) => {
2076
2142
  else throw new Error("Missing SoftEligibilityContext or HardEligibilityContext");
2077
2143
  storeRef.current = createEligibilityInputStore(requirePatient);
2078
2144
  }
2079
- return /* @__PURE__ */ jsx2(EligibilityInputContext.Provider, { value: storeRef.current, children });
2145
+ return /* @__PURE__ */ jsxs2(EligibilityInputContext.Provider, { value: storeRef.current, children: [
2146
+ children,
2147
+ /* @__PURE__ */ jsx2(EligibilityInputAnalytics, {})
2148
+ ] });
2080
2149
  };
2081
2150
 
2082
2151
  // src/soft-eligibility/soft-eligibility-provider.tsx
@@ -2097,7 +2166,7 @@ function useCreateSoftEligibilitySession() {
2097
2166
  }
2098
2167
 
2099
2168
  // src/soft-eligibility/use-soft-eligibility-state.ts
2100
- import { useEffect as useEffect6, useState as useState5 } from "react";
2169
+ import { useEffect as useEffect8, useState as useState5 } from "react";
2101
2170
  import "@usebridge/sdk-core";
2102
2171
 
2103
2172
  // src/soft-eligibility/use-soft-eligibility.ts
@@ -2113,7 +2182,7 @@ function useSoftEligibilitySession() {
2113
2182
  function useSoftEligibilityState() {
2114
2183
  const session = useSoftEligibilitySession();
2115
2184
  const [state, setState] = useState5(session.state);
2116
- useEffect6(() => {
2185
+ useEffect8(() => {
2117
2186
  session.on("update", setState);
2118
2187
  return () => {
2119
2188
  session.removeListener("update", setState);
@@ -2123,7 +2192,7 @@ function useSoftEligibilityState() {
2123
2192
  }
2124
2193
 
2125
2194
  // src/soft-eligibility/use-soft-eligibility-submit.ts
2126
- import { useCallback as useCallback6, useMemo as useMemo5 } from "react";
2195
+ import { useCallback as useCallback6, useMemo as useMemo6 } from "react";
2127
2196
  import { SoftEligibility as SoftEligibility2 } from "@usebridge/sdk-core";
2128
2197
  function useSoftEligibilitySubmit() {
2129
2198
  const session = useSoftEligibilitySession();
@@ -2136,7 +2205,7 @@ function useSoftEligibilitySubmit() {
2136
2205
  if (!state.value) throw new Error("State is required");
2137
2206
  return session.submit({ payerId: payer.value.id, state: state.value });
2138
2207
  }, [session, payer, state]);
2139
- return useMemo5(
2208
+ return useMemo6(
2140
2209
  () => ({
2141
2210
  isDisabled,
2142
2211
  submit