@medplum/react 5.1.26 → 5.1.28

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.
@@ -52,8 +52,14 @@ import type { MantineColor } from '@mantine/core';
52
52
  import type { MeasureReport } from '@medplum/fhirtypes';
53
53
  import type { Media } from '@medplum/fhirtypes';
54
54
  import type { Medication } from '@medplum/fhirtypes';
55
+ import type { MedicationCartClearRequest } from '@medplum/core';
56
+ import type { MedicationCartManageResponse } from '@medplum/core';
57
+ import type { MedicationCartRemoveRequest } from '@medplum/core';
58
+ import type { MedicationCheckoutRequest } from '@medplum/core';
59
+ import type { MedicationCheckoutResponse } from '@medplum/core';
55
60
  import type { MedicationOrderRequest } from '@medplum/core';
56
61
  import type { MedicationOrderResponse } from '@medplum/core';
62
+ import type { MedicationRequest } from '@medplum/fhirtypes';
57
63
  import type { MedicationSearchParams } from '@medplum/core';
58
64
  import type { MedplumClient } from '@medplum/core';
59
65
  import { MemoExoticComponent } from 'react';
@@ -66,8 +72,10 @@ import type { ObservationDefinitionQualifiedInterval } from '@medplum/fhirtypes'
66
72
  import type { OperationOutcome } from '@medplum/fhirtypes';
67
73
  import type { OperationOutcomeIssue } from '@medplum/fhirtypes';
68
74
  import { Operator } from '@medplum/core';
75
+ import type { OrderSetSyncResponse } from '@medplum/core';
69
76
  import type { Organization } from '@medplum/fhirtypes';
70
77
  import type { PaperProps } from '@mantine/core';
78
+ import type { PasswordInputProps } from '@mantine/core';
71
79
  import type { Patient } from '@medplum/fhirtypes';
72
80
  import { PATIENT_PREFERRED_PHARMACY_URL } from '@medplum/core';
73
81
  import type { Period } from '@medplum/fhirtypes';
@@ -98,6 +106,7 @@ import { removePreferredPharmacyFromPatient } from '@medplum/core';
98
106
  import type { RequestGroup } from '@medplum/fhirtypes';
99
107
  import type { Resource } from '@medplum/fhirtypes';
100
108
  import type { ResourceArray } from '@medplum/core';
109
+ import type { ResourceModifiedEvent } from '@medplum/core';
101
110
  import type { ResourceType } from '@medplum/fhirtypes';
102
111
  import type { Schedule } from '@medplum/fhirtypes';
103
112
  import type { SearchParameter } from '@medplum/fhirtypes';
@@ -242,6 +251,7 @@ export declare interface AIRealTimeQuestionnaireFormProps extends QuestionnaireF
242
251
  readonly aiModel?: string;
243
252
  readonly onTranscript?: (fullTranscript: string, chunk: string) => void;
244
253
  readonly voiceInstructions?: ReactNode;
254
+ readonly silenceDebounceMs?: number;
245
255
  }
246
256
 
247
257
  /** Allergies section — searches for AllergyIntolerance resources. */
@@ -252,6 +262,23 @@ export declare function AnnotationInput(props: AnnotationInputProps): JSX.Elemen
252
262
  export declare interface AnnotationInputProps extends ComplexTypeInputProps<Annotation> {
253
263
  }
254
264
 
265
+ /**
266
+ * Applies the `questionnaire-optionExclusive` rule to an answer change.
267
+ *
268
+ * Given the previous and newly requested answers for an item, enforces that selecting an answer
269
+ * option marked exclusive clears every other answer, and selecting any other option clears a
270
+ * previously selected exclusive answer. Returns the new answers unchanged if the item has no
271
+ * exclusive options or the change only removed answers.
272
+ *
273
+ * See: https://hl7.org/fhir/extensions/StructureDefinition-questionnaire-optionExclusive.html
274
+ *
275
+ * @param item - The questionnaire item being answered.
276
+ * @param previousAnswers - The item's answers before the change.
277
+ * @param newAnswers - The answers requested by the change.
278
+ * @returns The reconciled answers.
279
+ */
280
+ export declare function applyOptionExclusive(item: QuestionnaireItem, previousAnswers: QuestionnaireResponseItemAnswer[] | undefined, newAnswers: QuestionnaireResponseItemAnswer[]): QuestionnaireResponseItemAnswer[];
281
+
255
282
  export declare function AppShell(props: AppShellProps): JSX.Element;
256
283
 
257
284
  export declare interface AppShellAnnouncement {
@@ -469,6 +496,16 @@ export declare function buildInitialResponse(questionnaire: Questionnaire, quest
469
496
 
470
497
  export declare function buildInitialResponseItem(item: QuestionnaireItem): QuestionnaireResponseItem;
471
498
 
499
+ /**
500
+ * Returns a display label for a search parameter code.
501
+ *
502
+ * Meta fields keep their underscore-prefixed code so they don't collide with same-named
503
+ * elements (e.g. `ProjectMembership.project` vs `_project`).
504
+ * @param code - The search parameter code.
505
+ * @returns The display label for the search parameter.
506
+ */
507
+ export declare function buildSearchParamFieldLabel(code: string): string;
508
+
472
509
  export declare function CalendarDateInput(props: CalendarDateInputProps): JSX.Element;
473
510
 
474
511
  export declare interface CalendarDateInputProps {
@@ -1048,6 +1085,13 @@ export declare function isCheckboxCell(el: Element): boolean;
1048
1085
  */
1049
1086
  export declare function isChoiceQuestion(item: QuestionnaireItem): boolean;
1050
1087
 
1088
+ /**
1089
+ * Returns true if the given search parameter code refers to a resource metadata field.
1090
+ * @param code - The search parameter code.
1091
+ * @returns True if the code is a meta search parameter.
1092
+ */
1093
+ export declare function isMetaSearchParam(code: string): boolean;
1094
+
1051
1095
  export { isOrganizationArray }
1052
1096
 
1053
1097
  /**
@@ -1062,6 +1106,15 @@ export declare function isSortDescending(definition: SearchRequest): boolean;
1062
1106
 
1063
1107
  export declare function isSupportedProfileStructureDefinition(profile?: StructureDefinition): profile is SupportedProfileStructureDefinition;
1064
1108
 
1109
+ /**
1110
+ * Returns true if an error thrown while expanding a ValueSet means the value set itself is
1111
+ * unavailable — a permanent 400/404 (e.g. "ValueSet not found"). Transient failures (429 rate
1112
+ * limit, 401, 5xx, network) return false so a blip never disables a field.
1113
+ * @param err - The error thrown by `valueSetExpand`.
1114
+ * @returns True for a permanent 400/404, false for a transient failure.
1115
+ */
1116
+ export declare function isValueSetUnavailableError(err: unknown): boolean;
1117
+
1065
1118
  /**
1066
1119
  * Kills a browser event.
1067
1120
  * Prevents default behavior.
@@ -1084,14 +1137,14 @@ export declare interface LinkTabsProps extends Omit<TabsProps, 'value' | 'onChan
1084
1137
  /**
1085
1138
  * ListWithDetailPane is a generic, presentational master-detail shell: a left sidebar
1086
1139
  * with optional pill tabs, header actions, a scrollable list, and pagination, plus a
1087
- * detail area for the selected item. It does no data fetching or routing it renders
1088
- * what it is given and emits `onTabChange` / `onPageChange` callbacks.
1140
+ * detail area for the selected item. It does no data fetching it renders what it is
1141
+ * given, navigates via links, and emits `onPageChange` / `onSelectFirst` callbacks.
1089
1142
  * @param props - The ListWithDetailPane React props.
1090
1143
  * @returns The ListWithDetailPane React node.
1091
1144
  */
1092
1145
  export declare function ListWithDetailPane<T extends {
1093
- id: string;
1094
- } = WithId<Resource>>(props: ListWithDetailPaneProps<T>): JSX.Element;
1146
+ id?: string;
1147
+ } = Resource>(props: ListWithDetailPaneProps<T>): JSX.Element;
1095
1148
 
1096
1149
  export declare interface ListWithDetailPaneDetailContext {
1097
1150
  readonly refresh: () => Promise<void>;
@@ -1101,48 +1154,58 @@ export declare interface ListWithDetailPaneDetailContext {
1101
1154
  export declare type ListWithDetailPaneHeaderProps = ListWithDetailPaneTextHeaderProps | ListWithDetailPaneTabsHeaderProps;
1102
1155
 
1103
1156
  export declare interface ListWithDetailPaneItemContext<T extends {
1104
- id: string;
1105
- } = WithId<Resource>> {
1157
+ id?: string;
1158
+ } = Resource> {
1106
1159
  readonly selected: boolean;
1107
1160
  readonly index: number;
1108
1161
  readonly items: T[];
1109
1162
  }
1110
1163
 
1111
1164
  export declare type ListWithDetailPaneProps<T extends {
1112
- id: string;
1113
- } = WithId<Resource>> = ListWithDetailPanePropsBase<T> & ListWithDetailPaneHeaderProps;
1114
-
1115
- /** Props shared by every ListWithDetailPane, independent of the header style. */
1165
+ id?: string;
1166
+ } = Resource> = ListWithDetailPanePropsBase<T> & ListWithDetailPaneHeaderProps;
1167
+
1168
+ /**
1169
+ * Props shared by every ListWithDetailPane, independent of the header style.
1170
+ * @param items - The current page of items to render in the list.
1171
+ * @param loading - When true, the list area shows the skeleton instead of items.
1172
+ * @param selectedKey - Id of the highlighted row.
1173
+ * @param renderItem - Renders one row of the list sidebar.
1174
+ * @param emptyList - Shown when the list is empty. Default: dimmed "No items found".
1175
+ * @param skeleton - Shown while loading. Default: built-in skeleton rows.
1176
+ * @param listWidth - Sidebar width in pixels. Default 350.
1177
+ * @param headerActions - Right-aligned slot in the sidebar header row: action buttons, filter popovers.
1178
+ * @param selected - The resolved selected item, or undefined when nothing is selected.
1179
+ * @param renderDetail - Renders the detail pane for the selected item.
1180
+ * @param emptyDetail - Shown when nothing is selected. Default: dimmed prompt.
1181
+ * @param refresh - Passed through to the detail render context.
1182
+ * @param onSelectFirst - Auto-select escape hatch. Fired with the first item when the list has finished loading
1183
+ * (`loading` false) with items while nothing is selected (`selectedKey` undefined). The consumer decides how to
1184
+ * navigate (typically with history replace). Pass an id-driven `selectedKey` (e.g. the URL route param) so a
1185
+ * selection that is still resolving does not read as "nothing selected", and keep `loading` true from the render a
1186
+ * new search starts on, so this never fires against a stale list.
1187
+ * @param page - Current 1-based page. Pagination is hidden unless this, `pageCount`, and `onPageChange` are set.
1188
+ * @param pageCount - Total number of pages. Pagination is hidden when this is less than or equal to 1.
1189
+ * @param onPageChange - Fired by the built-in pagination with the new 1-based page.
1190
+ */
1116
1191
  export declare interface ListWithDetailPanePropsBase<T extends {
1117
- id: string;
1118
- } = WithId<Resource>> {
1119
- /** The current page of items to render in the list. */
1192
+ id?: string;
1193
+ } = Resource> {
1120
1194
  readonly items: T[];
1121
- /** When true, the list area shows the skeleton instead of items. */
1122
1195
  readonly loading: boolean;
1123
- /** Id of the highlighted row. */
1124
1196
  readonly selectedKey?: string;
1125
1197
  readonly renderItem: (item: T, ctx: ListWithDetailPaneItemContext<T>) => ReactNode;
1126
- /** Shown when the list is empty. Default: dimmed "No items found". */
1127
1198
  readonly emptyList?: ReactNode;
1128
- /** Shown while loading. Default: built-in skeleton rows. */
1129
1199
  readonly skeleton?: ReactNode;
1130
- /** Sidebar width in pixels. Default 350. */
1131
1200
  readonly listWidth?: number;
1132
- /** Right-aligned slot in the sidebar header row: action buttons, filter popovers. */
1133
1201
  readonly headerActions?: ReactNode;
1134
- /** The resolved selected item, or undefined when nothing is selected. */
1135
1202
  readonly selected: T | undefined;
1136
1203
  readonly renderDetail: (selected: T, ctx: ListWithDetailPaneDetailContext) => ReactNode;
1137
- /** Shown when nothing is selected. Default: dimmed prompt. */
1138
1204
  readonly emptyDetail?: ReactNode;
1139
- /** Passed through to the detail render context. */
1140
1205
  readonly refresh: () => Promise<void>;
1141
- /** Current 1-based page. Pagination is hidden unless this, `pageCount`, and `onPageChange` are set. */
1206
+ readonly onSelectFirst?: (item: T) => void;
1142
1207
  readonly page?: number;
1143
- /** Total number of pages. Pagination is hidden when this is less than or equal to 1. */
1144
1208
  readonly pageCount?: number;
1145
- /** Fired by the built-in pagination with the new 1-based page. */
1146
1209
  readonly onPageChange?: (page: number) => void;
1147
1210
  }
1148
1211
 
@@ -1154,24 +1217,25 @@ export declare interface ListWithDetailPaneTab {
1154
1217
 
1155
1218
  /**
1156
1219
  * Pill-tab header. Declares `headerText` as `never` so tabs can't be mixed with a title.
1220
+ * Each tab renders as a link to its `uri`, so tab switching needs no change callback.
1221
+ * @param tabs - Sidebar header tabs. Selecting a tab navigates to its URI.
1222
+ * @param activeTab - Controlled active tab value; consumers derive it from the URL.
1157
1223
  */
1158
1224
  export declare interface ListWithDetailPaneTabsHeaderProps {
1159
1225
  readonly tabs: ListWithDetailPaneTab[];
1160
1226
  readonly activeTab?: string;
1161
- readonly onTabChange?: (value: string) => void;
1162
1227
  readonly headerText?: never;
1163
1228
  }
1164
1229
 
1165
1230
  /**
1166
1231
  * Plain-text header (or no header at all). Declares the tab fields as `never` so a title
1167
1232
  * can't be mixed with tabs.
1233
+ * @param headerText - Plain title shown at the left of the header.
1168
1234
  */
1169
1235
  export declare interface ListWithDetailPaneTextHeaderProps {
1170
- /** Plain title shown at the left of the header. */
1171
1236
  readonly headerText?: ReactNode;
1172
1237
  readonly tabs?: never;
1173
1238
  readonly activeTab?: never;
1174
- readonly onTabChange?: never;
1175
1239
  }
1176
1240
 
1177
1241
  export declare function Loading(): JSX.Element;
@@ -1189,8 +1253,13 @@ export declare interface MeasureReportDisplayProps {
1189
1253
  readonly measureReport: MeasureReport | Reference<MeasureReport>;
1190
1254
  }
1191
1255
 
1256
+ /** Thrown by {@link UseMedicationCartReturn.checkout} when an {@link UseMedicationCartReturn.addToCart} call is still in flight. */
1257
+ export declare const MEDICATION_CART_ADD_IN_PROGRESS = "Cannot checkout while a medication is still being added to the cart";
1258
+
1192
1259
  export declare interface MedicationIFrameOptions {
1193
1260
  readonly patientId?: string;
1261
+ /** Selected practice location for multi-practice deployments. */
1262
+ readonly organization?: Reference<Organization>;
1194
1263
  readonly onPatientSyncSuccess?: () => void;
1195
1264
  readonly onIframeSuccess?: (url: string) => void;
1196
1265
  readonly onError?: (err: unknown) => void;
@@ -1439,6 +1508,7 @@ export declare function OperationOutcomeAlert(props: OperationOutcomeAlertProps)
1439
1508
  export declare interface OperationOutcomeAlertProps extends AlertProps {
1440
1509
  readonly outcome?: OperationOutcome;
1441
1510
  readonly issues?: OperationOutcomeIssue[];
1511
+ readonly displayOkOutcomes?: boolean;
1442
1512
  }
1443
1513
 
1444
1514
  export declare function Panel(props: PanelProps): JSX.Element;
@@ -1463,6 +1533,15 @@ export declare interface ParticipantFilterProps {
1463
1533
  readonly onFilterChange: (participants: Reference<Patient | Practitioner>[]) => void;
1464
1534
  }
1465
1535
 
1536
+ /**
1537
+ * Mantine's `PasswordInput` sets `tabIndex={-1}` and `aria-hidden` on the visibility toggle button
1538
+ * unless `visibilityToggleButtonProps` is provided, which removes it from the keyboard tab order and
1539
+ * hides it from assistive technology. This wrapper defaults the toggle to be keyboard accessible.
1540
+ * @param props - The password input props.
1541
+ * @returns The password input component.
1542
+ */
1543
+ export declare function PasswordInput(props: PasswordInputProps): JSX.Element;
1544
+
1466
1545
  export { PATIENT_PREFERRED_PHARMACY_URL }
1467
1546
 
1468
1547
  export declare function PatientAccountsForm(props: PatientAccountsFormProps): JSX.Element;
@@ -1645,6 +1724,8 @@ export declare const QUESTIONNAIRE_HIDDEN_URL = "http://hl7.org/fhir/StructureDe
1645
1724
 
1646
1725
  export declare const QUESTIONNAIRE_ITEM_CONTROL_URL = "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl";
1647
1726
 
1727
+ export declare const QUESTIONNAIRE_OPTION_EXCLUSIVE_URL = "http://hl7.org/fhir/StructureDefinition/questionnaire-optionExclusive";
1728
+
1648
1729
  export declare const QUESTIONNAIRE_REFERENCE_FILTER_URL = "http://hl7.org/fhir/StructureDefinition/questionnaire-referenceFilter";
1649
1730
 
1650
1731
  export declare const QUESTIONNAIRE_REFERENCE_RESOURCE_URL = "http://hl7.org/fhir/StructureDefinition/questionnaire-referenceResource";
@@ -1862,6 +1943,7 @@ export declare interface RegisterFormProps {
1862
1943
  readonly recaptchaSiteKey?: string;
1863
1944
  readonly children?: ReactNode;
1864
1945
  readonly onSuccess: () => void;
1946
+ readonly onSignIn?: () => void;
1865
1947
  }
1866
1948
 
1867
1949
  /**
@@ -1973,61 +2055,54 @@ export declare interface ResourceBoardLoadResult<T extends Resource = Resource>
1973
2055
  readonly total?: number;
1974
2056
  }
1975
2057
 
2058
+ /**
2059
+ * Props for the ResourceBoard component.
2060
+ * @param search - The search definition (resourceType + filters + count/offset), like SearchControl. Default
2061
+ * fetching searches with `_total=accurate` and `cache: 'no-cache'`. Deep-equality memoized internally, so parents
2062
+ * may pass object literals.
2063
+ * @param selectedId - Selected resource id, typically driven by the URL route param.
2064
+ * @param loadItems - Custom fetcher replacing the default search (e.g. GraphQL batching, client-side filtering).
2065
+ * Re-runs whenever its identity or the search changes — wrap in useCallback.
2066
+ * @param resolveSelected - Selected-resource resolution. Default: find in items by id, else
2067
+ * `medplum.readResource(search.resourceType, id)`.
2068
+ * @param reloadKey - Manual refresh trigger: change this value (e.g. a counter) to re-run the load without changing
2069
+ * the search. Reloads in place — no skeleton.
2070
+ * @param headerText - Plain title shown at the left of the header when no `tabs` are provided.
2071
+ * @param tabs - Sidebar header tabs. Selecting a tab navigates to its URI.
2072
+ * @param activeTab - Controlled active tab value; consumers derive it from the URL.
2073
+ * @param headerActions - Right-aligned slot in the sidebar header row: action buttons, filter popovers.
2074
+ * @param renderItem - Renders one row of the list sidebar.
2075
+ * @param emptyList - Shown when the list loads empty. Default: dimmed "No items found".
2076
+ * @param skeleton - Shown while the initial or search-change load is in flight. Default: built-in skeleton rows.
2077
+ * @param listWidth - Sidebar width in pixels. Default 350.
2078
+ * @param renderDetail - Renders the detail pane for the resolved selection.
2079
+ * @param emptyDetail - Shown when nothing is selected or the selection cannot be resolved.
2080
+ * @param onChange - Fired by the built-in pagination with the updated offset.
2081
+ * @param onSelectFirst - Auto-select escape hatch. Fired with the first item when a load for the current search
2082
+ * settles with items while nothing is selected (owned by ListWithDetailPane). The consumer decides how to navigate
2083
+ * (e.g. with history replace).
2084
+ * @param onLoad - Fired after every successful load.
2085
+ * @param onError - List-load and selection-resolution errors. Default: console.error.
2086
+ */
1976
2087
  export declare interface ResourceBoardProps<T extends Resource = Resource> {
1977
- /**
1978
- * The search definition (resourceType + filters + count/offset), like SearchControl.
1979
- * Default fetching searches with `_total=accurate` and `cache: 'no-cache'`.
1980
- * Deep-equality memoized internally, so parents may pass object literals.
1981
- */
1982
2088
  readonly search: SearchRequest;
1983
- /** Selected resource id, typically driven by the URL route param. */
1984
2089
  readonly selectedId?: string;
1985
- /**
1986
- * Custom fetcher replacing the default search (e.g. GraphQL batching, client-side
1987
- * filtering). Re-runs whenever its identity or the search changes — wrap in useCallback.
1988
- */
1989
2090
  readonly loadItems?: (search: SearchRequest, medplum: MedplumClient) => Promise<ResourceBoardLoadResult<T>>;
1990
- /**
1991
- * Selected-resource resolution. Default: find in items by id, else
1992
- * `medplum.readResource(search.resourceType, id)`.
1993
- */
1994
2091
  readonly resolveSelected?: (id: string, items: WithId<T>[], medplum: MedplumClient) => Promise<WithId<T> | undefined>;
1995
- /**
1996
- * Manual refresh trigger: change this value (e.g. a counter) to re-run the load
1997
- * without changing the search. Reloads in place — no skeleton.
1998
- */
1999
2092
  readonly reloadKey?: unknown;
2000
- /** Plain title shown at the left of the header when no `tabs` are provided. */
2001
2093
  readonly headerText?: ReactNode;
2002
- /** Sidebar header tabs. Selecting a tab navigates to its URI. */
2003
2094
  readonly tabs?: ResourceBoardTab[];
2004
- /** Controlled active tab value; consumers derive it from the URL. */
2005
2095
  readonly activeTab?: string;
2006
- /** Right-aligned slot in the sidebar header row: action buttons, filter popovers. */
2007
2096
  readonly headerActions?: ReactNode;
2008
2097
  readonly renderItem: (item: WithId<T>, ctx: ResourceBoardItemContext<T>) => ReactNode;
2009
- /** Shown when the list loads empty. Default: dimmed "No items found". */
2010
2098
  readonly emptyList?: ReactNode;
2011
- /** Shown while the initial or search-change load is in flight. Default: built-in skeleton rows. */
2012
2099
  readonly skeleton?: ReactNode;
2013
- /** Sidebar width in pixels. Default 350. */
2014
2100
  readonly listWidth?: number;
2015
2101
  readonly renderDetail: (selected: WithId<T>, ctx: ResourceBoardDetailContext) => ReactNode;
2016
- /** Shown when nothing is selected or the selection cannot be resolved. */
2017
2102
  readonly emptyDetail?: ReactNode;
2018
- /**
2019
- * Fired by the built-in pagination with the updated offset.
2020
- */
2021
2103
  readonly onChange?: (search: SearchRequest) => void;
2022
- /**
2023
- * Auto-select escape hatch. Called with the first item when a load for the
2024
- * current search completes with items while `selectedId` is undefined.
2025
- * The consumer decides how to navigate (e.g. with history replace).
2026
- */
2027
2104
  readonly onSelectFirst?: (item: WithId<T>) => void;
2028
- /** Fired after every successful load. */
2029
2105
  readonly onLoad?: (items: WithId<T>[], total: number | undefined) => void;
2030
- /** List-load and selection-resolution errors. Default: console.error. */
2031
2106
  readonly onError?: (error: unknown) => void;
2032
2107
  }
2033
2108
 
@@ -2209,6 +2284,22 @@ export declare class SearchClickEvent extends Event {
2209
2284
  */
2210
2285
  export declare function SearchControl(props: SearchControlProps): JSX.Element;
2211
2286
 
2287
+ /**
2288
+ * An additional, computed column appended after the search-result columns.
2289
+ *
2290
+ * Unlike the columns derived from {@link SearchControlProps.search} fields, an
2291
+ * additional column is not backed by a search parameter and has no sort/filter
2292
+ * menu: it renders arbitrary content per row. Use it for values that must be
2293
+ * computed or fetched separately from the searched resource (e.g. a related
2294
+ * resource's status).
2295
+ */
2296
+ export declare interface SearchControlAdditionalColumn {
2297
+ /** The column header text. */
2298
+ readonly name: string;
2299
+ /** Renders the cell contents for the given row resource. */
2300
+ readonly renderCell: (resource: Resource) => ReactNode;
2301
+ }
2302
+
2212
2303
  /**
2213
2304
  * The SearchControlField type describes a field in the search control.
2214
2305
  *
@@ -2245,6 +2336,8 @@ export declare interface SearchControlField {
2245
2336
  export declare interface SearchControlProps {
2246
2337
  readonly search: SearchRequest;
2247
2338
  readonly checkboxesEnabled?: boolean;
2339
+ /** Additional computed columns rendered after the search-result columns. */
2340
+ readonly additionalColumns?: readonly SearchControlAdditionalColumn[];
2248
2341
  readonly hideToolbar?: boolean;
2249
2342
  readonly hideFilters?: boolean;
2250
2343
  readonly onLoad?: (e: SearchLoadEvent) => void;
@@ -2523,10 +2616,14 @@ export declare function ThreadInbox(props: ThreadInboxProps): JSX.Element;
2523
2616
  * @param showPatientSummary - Whether to show the patient summary.
2524
2617
  * @param sections - Optional sections configuration for the patient summary.
2525
2618
  * @param onNew - A function to handle a new thread.
2619
+ * @param onSelectFirst - Fired with the first thread when the list loads with nothing selected; use it to navigate to that thread (with replace) so the inbox auto-selects it.
2526
2620
  * @param getThreadUri - A function to build thread URIs.
2527
2621
  * @param onChange - A function to handle search changes.
2528
2622
  * @param inProgressUri - The URI for in-progress threads.
2529
2623
  * @param completedUri - The URI for completed threads.
2624
+ * @param newTopicOpened - Controlled open state for the new topic dialog. When provided, use `onNewTopicOpen` and `onNewTopicClose` to update it.
2625
+ * @param onNewTopicOpen - Called when the user clicks the new message button. Required when `newTopicOpened` is provided.
2626
+ * @param onNewTopicClose - Called when the new topic dialog is closed. Required when `newTopicOpened` is provided.
2530
2627
  */
2531
2628
  export declare interface ThreadInboxProps {
2532
2629
  readonly query: string;
@@ -2535,6 +2632,7 @@ export declare interface ThreadInboxProps {
2535
2632
  readonly showPatientSummary?: boolean;
2536
2633
  readonly sections?: PatientSummarySectionConfig[];
2537
2634
  readonly onNew: (message: Communication) => void;
2635
+ readonly onSelectFirst?: (thread: Communication) => void;
2538
2636
  readonly getThreadUri: (topic: Communication) => string;
2539
2637
  readonly onChange: (search: SearchRequest) => void;
2540
2638
  readonly inProgressUri: string;
@@ -2542,6 +2640,9 @@ export declare interface ThreadInboxProps {
2542
2640
  readonly uploadEnabled?: boolean;
2543
2641
  readonly onViewInDocuments?: (reference: Reference<DocumentReference>) => void;
2544
2642
  readonly allowPatientSelection?: boolean;
2643
+ readonly newTopicOpened?: boolean;
2644
+ readonly onNewTopicOpen?: () => void;
2645
+ readonly onNewTopicClose?: () => void;
2545
2646
  }
2546
2647
 
2547
2648
  export declare function Timeline(props: TimelineProps): JSX.Element;
@@ -2583,8 +2684,63 @@ export declare type TranscriptItem = {
2583
2684
 
2584
2685
  export declare function typedValueToResponseItem(item: QuestionnaireItem, value: TypedValue): QuestionnaireResponseItemAnswer | undefined;
2585
2686
 
2687
+ export declare function UnavailableNote({ text, color, message }: UnavailableNoteProps): JSX.Element;
2688
+
2689
+ export declare interface UnavailableNoteProps {
2690
+ readonly text: string;
2691
+ readonly color: string;
2692
+ readonly message: string;
2693
+ }
2694
+
2586
2695
  export declare const useCachedBinaryUrl: (binaryUrl: string | undefined) => string | undefined;
2587
2696
 
2697
+ /**
2698
+ * Vendor-neutral hook for the full **medication cart** lifecycle: add a draft
2699
+ * line (`createResource`), check out a set of drafts into the vendor's batch
2700
+ * approval queue (`$checkout-medications`), and remove/clear cart lines
2701
+ * (`$remove-cart-medication` / `$clear-cart`).
2702
+ *
2703
+ * Cart checkout / remove / clear hit project-scoped **FHIR custom operations**
2704
+ * whose backing Bot is chosen at deploy time via an `OperationDefinition`
2705
+ * carrying the `operationDefinition-implementation` extension — see
2706
+ * [bot operations docs](https://www.medplum.com/docs/bots/custom-fhir-operations).
2707
+ * The server's `tryCustomOperation` dispatch handles the OD → Bot lookup, so
2708
+ * projects swap vendors by deploying a different bot under the same code.
2709
+ *
2710
+ * `addToCart` is plain FHIR `createResource` (no `$add-cart` operation): the
2711
+ * Medplum-side cart is the set of draft `MedicationRequest`s. Vendor staging
2712
+ * (e.g. ScriptSure MedCart) happens at checkout. Vendors without a batch
2713
+ * approval queue (e.g. DoseSpot iframe-first) simply never call `checkout` /
2714
+ * `removeFromCart` / `clearCart`.
2715
+ *
2716
+ * Requests for the custom operations are encoded as `Parameters` bodies and
2717
+ * decoded by the matching `@medplum/core` helpers. Per-line outcomes arrive in
2718
+ * `response.items`.
2719
+ *
2720
+ * @returns Cart add / checkout / remove / clear callbacks plus `adding` state.
2721
+ */
2722
+ export declare function useMedicationCart(): UseMedicationCartReturn;
2723
+
2724
+ export declare interface UseMedicationCartReturn {
2725
+ /**
2726
+ * Persist a draft `MedicationRequest` as a cart line via plain FHIR
2727
+ * `createResource` (no custom operation). Vendor staging happens later at
2728
+ * {@link UseMedicationCartReturn.checkout}.
2729
+ */
2730
+ addToCart: (medicationRequest: MedicationRequest) => Promise<MedicationRequest>;
2731
+ /** True while one or more {@link UseMedicationCartReturn.addToCart} calls are in flight. */
2732
+ adding: boolean;
2733
+ /**
2734
+ * Submit draft cart lines to the vendor's batch approval queue and return an
2735
+ * embeddable approval-widget URL. Refuses while {@link UseMedicationCartReturn.adding} is true.
2736
+ */
2737
+ checkout: (input: MedicationCheckoutRequest) => Promise<MedicationCheckoutResponse>;
2738
+ /** Remove a single draft `MedicationRequest` from the patient's vendor cart. */
2739
+ removeFromCart: (input: MedicationCartRemoveRequest) => Promise<MedicationCartManageResponse>;
2740
+ /** Remove every item from the patient's vendor cart. */
2741
+ clearCart: (input: MedicationCartClearRequest) => Promise<MedicationCartManageResponse>;
2742
+ }
2743
+
2588
2744
  /**
2589
2745
  * Generic React hook that syncs a patient to a medication-order vendor and
2590
2746
  * returns the chart iframe URL.
@@ -2668,6 +2824,8 @@ export declare interface UseMedicationOrderSetOptions {
2668
2824
  /** Vendor-side order set id, when picked directly (escape hatch when no synced PD exists yet). */
2669
2825
  readonly vendorOrderSetId?: number | string;
2670
2826
  readonly appId?: string;
2827
+ /** Selected practice location for multi-practice deployments. */
2828
+ readonly organization?: Reference<Organization>;
2671
2829
  }
2672
2830
 
2673
2831
  export declare interface UseMedicationOrderSetReturn {
@@ -2812,7 +2970,6 @@ export declare interface UseResourceBoardProps<T extends Resource = Resource> {
2812
2970
  * without changing the search. Reloads in place — no skeleton — like `refresh()`.
2813
2971
  */
2814
2972
  readonly reloadKey?: unknown;
2815
- readonly onSelectFirst?: (item: WithId<T>) => void;
2816
2973
  readonly onLoad?: (items: WithId<T>[], total: number | undefined) => void;
2817
2974
  readonly onError?: (error: unknown) => void;
2818
2975
  }
@@ -2831,6 +2988,30 @@ export declare interface UseResourceBoardResult<T extends Resource = Resource> {
2831
2988
  readonly refresh: () => Promise<void>;
2832
2989
  }
2833
2990
 
2991
+ /**
2992
+ * React hook for observing FHIR resource modifications made through the Medplum client.
2993
+ *
2994
+ * The callback is invoked whenever this client instance creates, updates, patches, or deletes
2995
+ * a resource of one of the given types, including modifications announced with
2996
+ * `MedplumClient.notifyResourceModified`. Use it to keep local component state in sync with
2997
+ * mutations made elsewhere in the application. Subscribing to a single resource type narrows
2998
+ * the event so `event.resource` is typed to that resource, no type guard required:
2999
+ *
3000
+ * ```tsx
3001
+ * useResourceModified('Slot', (event) => {
3002
+ * // event.resource is `WithId<Slot> | undefined`
3003
+ * });
3004
+ * useResourceModified(['Slot', 'Appointment'], () => refreshSchedule());
3005
+ * ```
3006
+ *
3007
+ * Modifications made by other clients (or other users) are not observed;
3008
+ * use `useSubscription` for server-side change notifications.
3009
+ *
3010
+ * @param resourceType - The resource type or types to observe.
3011
+ * @param callback - Invoked with the event payload for each matching modification.
3012
+ */
3013
+ export declare function useResourceModified<K extends ResourceType>(resourceType: K | K[], callback: (event: ResourceModifiedEvent<ExtractResource<K>>) => void): void;
3014
+
2834
3015
  /**
2835
3016
  * React hook for searching FHIR resources.
2836
3017
  *
@@ -2904,13 +3085,18 @@ export declare type UseSubscriptionOptions = {
2904
3085
  * to the configured e-prescribing vendor via the `$sync-orderset` custom FHIR operation
2905
3086
  * (`POST /fhir/R4/PlanDefinition/$sync-orderset`).
2906
3087
  *
2907
- * Silently no-ops when the operation is not deployed (i.e. no e-prescribing vendor
2908
- * is configured for the project), so callers do not need to guard against missing
2909
- * integrations.
3088
+ * Resolves with the decoded `OrderSetSyncResponse` so callers can surface
3089
+ * per-action failures (`results[i].status === 'failed'` / `failedCount > 0`)
3090
+ * without this, an order set that only partially synced would silently apply
3091
+ * with fewer meds than the PlanDefinition requested.
3092
+ *
3093
+ * Resolves with `undefined` when the operation is not deployed (i.e. no
3094
+ * e-prescribing vendor is configured for the project), so callers do not need to
3095
+ * guard against missing integrations.
2910
3096
  *
2911
- * @returns A stable `syncOrderSet(planDefinitionId)` callback.
3097
+ * @returns A stable `syncOrderSet(planDefinitionId, organization?)` callback.
2912
3098
  */
2913
- export declare function useSyncOrderSet(): (planDefinitionId: string) => Promise<void>;
3099
+ export declare function useSyncOrderSet(): (planDefinitionId: string, organization?: Reference<Organization>) => Promise<OrderSetSyncResponse | undefined>;
2914
3100
 
2915
3101
  export declare function useThreadInbox({ query, threadId }: UseThreadInboxOptions): UseThreadInboxReturn;
2916
3102
 
@@ -2930,6 +3116,30 @@ export declare interface UseThreadInboxReturn {
2930
3116
  refreshThreadMessages: () => Promise<void>;
2931
3117
  }
2932
3118
 
3119
+ /**
3120
+ * Probes a set of ValueSet URLs for availability, each with a filter-free, count-limited expansion.
3121
+ *
3122
+ * A filter-free probe means a 400/404 unambiguously describes the value set itself (unlike a
3123
+ * user-typed search, whose 400 can be filter-specific), so the verdict is safe to act on. Repeated
3124
+ * probes of the same URL are deduplicated by the `MedplumClient` request cache, which caches
3125
+ * rejections too, so many fields bound to the same missing value set cost one request. Recovery
3126
+ * after a value set is imported happens on the next mount (i.e. a page refresh) — there is no live
3127
+ * subscription. Transient failures (429/5xx/network) resolve as available so a blip never disables
3128
+ * a field; only a permanent 400/404 marks a URL unavailable.
3129
+ * @param urls - The ValueSet URLs to probe. Falsy entries are ignored, and duplicates collapse to a
3130
+ * single probe.
3131
+ * @returns The availability verdict, with `loading` true until every requested URL has settled.
3132
+ */
3133
+ export declare function useValueSetAvailabilities(urls: readonly (string | undefined)[]): ValueSetAvailability;
3134
+
3135
+ /**
3136
+ * Probes a single ValueSet's availability once on mount. A thin wrapper around
3137
+ * {@link useValueSetAvailabilities} for the common single-value-set case.
3138
+ * @param url - The ValueSet URL, or undefined for unbound inputs (always available).
3139
+ * @returns undefined while the probe is in flight, true if available, false if unavailable.
3140
+ */
3141
+ export declare function useValueSetAvailability(url: string | undefined): boolean | undefined;
3142
+
2933
3143
  export declare function useWhisper({ language, model, onTranscript, idleTimeoutMs, }: UseWhisperOptions): UseWhisperResult;
2934
3144
 
2935
3145
  export declare type UseWhisperOptions = {
@@ -2971,6 +3181,18 @@ export declare interface ValueSetAutocompleteProps extends Omit<AsyncAutocomplet
2971
3181
  readonly withHelpText?: boolean;
2972
3182
  }
2973
3183
 
3184
+ /**
3185
+ * The result of probing one or more ValueSet URLs for availability.
3186
+ */
3187
+ export declare interface ValueSetAvailability {
3188
+ /** True while at least one requested URL is still being probed. */
3189
+ readonly loading: boolean;
3190
+ /** The subset of requested URLs known to be available. */
3191
+ readonly available: string[];
3192
+ /** The subset of requested URLs known to be unavailable (a permanent 400/404). */
3193
+ readonly unavailable: string[];
3194
+ }
3195
+
2974
3196
  export declare function valueSetElementToCoding(element: ValueSetExpansionContains): Coding;
2975
3197
 
2976
3198
  /** Vitals section — searches for Observation resources with category vital-signs. */