@medplum/react 1.0.3 → 1.0.5

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.
Files changed (96) hide show
  1. package/dist/cjs/AsyncAutocomplete/AsyncAutocomplete.d.ts +14 -0
  2. package/dist/cjs/Container/Container.d.ts +3 -0
  3. package/dist/cjs/DiagnosticReportDisplay/DiagnosticReportDisplay.stories.d.ts +1 -0
  4. package/dist/cjs/Document/Document.d.ts +3 -6
  5. package/dist/cjs/FhirPathTable/FhirPathTable.d.ts +2 -2
  6. package/dist/cjs/Panel/Panel.d.ts +11 -0
  7. package/dist/cjs/Timeline/Timeline.d.ts +2 -4
  8. package/dist/cjs/ValueSetAutocomplete/ValueSetAutocomplete.d.ts +3 -6
  9. package/dist/cjs/auth/ChooseProfileForm.d.ts +2 -1
  10. package/dist/cjs/auth/ChooseScopeForm.d.ts +2 -1
  11. package/dist/cjs/auth/MfaForm.d.ts +7 -0
  12. package/dist/cjs/auth/OktaButton.d.ts +5 -0
  13. package/dist/cjs/auth/SignInForm.d.ts +10 -0
  14. package/dist/cjs/index.d.ts +3 -0
  15. package/dist/cjs/index.js +410 -215
  16. package/dist/cjs/index.js.map +1 -1
  17. package/dist/cjs/index.min.js +1 -1
  18. package/dist/cjs/index.min.js.map +1 -1
  19. package/dist/cjs/stories/referenceLab.d.ts +3 -1
  20. package/dist/esm/AsyncAutocomplete/AsyncAutocomplete.d.ts +14 -0
  21. package/dist/esm/AsyncAutocomplete/AsyncAutocomplete.js +116 -0
  22. package/dist/esm/AsyncAutocomplete/AsyncAutocomplete.js.map +1 -0
  23. package/dist/esm/AttachmentDisplay/AttachmentDisplay.js +2 -1
  24. package/dist/esm/AttachmentDisplay/AttachmentDisplay.js.map +1 -1
  25. package/dist/esm/BackboneElementDisplay/BackboneElementDisplay.js +3 -0
  26. package/dist/esm/BackboneElementDisplay/BackboneElementDisplay.js.map +1 -1
  27. package/dist/esm/CodeInput/CodeInput.js +3 -2
  28. package/dist/esm/CodeInput/CodeInput.js.map +1 -1
  29. package/dist/esm/CodeableConceptInput/CodeableConceptInput.js +18 -18
  30. package/dist/esm/CodeableConceptInput/CodeableConceptInput.js.map +1 -1
  31. package/dist/esm/CodingInput/CodingInput.js +3 -2
  32. package/dist/esm/CodingInput/CodingInput.js.map +1 -1
  33. package/dist/esm/Container/Container.d.ts +3 -0
  34. package/dist/esm/Container/Container.js +20 -0
  35. package/dist/esm/Container/Container.js.map +1 -0
  36. package/dist/esm/DiagnosticReportDisplay/DiagnosticReportDisplay.js +8 -2
  37. package/dist/esm/DiagnosticReportDisplay/DiagnosticReportDisplay.js.map +1 -1
  38. package/dist/esm/DiagnosticReportDisplay/DiagnosticReportDisplay.stories.d.ts +1 -0
  39. package/dist/esm/Document/Document.d.ts +3 -6
  40. package/dist/esm/Document/Document.js +5 -6
  41. package/dist/esm/Document/Document.js.map +1 -1
  42. package/dist/esm/FhirPathTable/FhirPathTable.d.ts +2 -2
  43. package/dist/esm/FhirPathTable/FhirPathTable.js.map +1 -1
  44. package/dist/esm/Panel/Panel.d.ts +11 -0
  45. package/dist/esm/Panel/Panel.js +35 -0
  46. package/dist/esm/Panel/Panel.js.map +1 -0
  47. package/dist/esm/PlanDefinitionBuilder/PlanDefinitionBuilder.js +3 -3
  48. package/dist/esm/PlanDefinitionBuilder/PlanDefinitionBuilder.js.map +1 -1
  49. package/dist/esm/QuestionnaireBuilder/QuestionnaireBuilder.js +6 -6
  50. package/dist/esm/QuestionnaireBuilder/QuestionnaireBuilder.js.map +1 -1
  51. package/dist/esm/QuestionnaireForm/QuestionnaireForm.js +1 -0
  52. package/dist/esm/QuestionnaireForm/QuestionnaireForm.js.map +1 -1
  53. package/dist/esm/ReferenceRangeEditor/ReferenceRangeEditor.js +4 -3
  54. package/dist/esm/ReferenceRangeEditor/ReferenceRangeEditor.js.map +1 -1
  55. package/dist/esm/ResourceInput/ResourceInput.js +2 -1
  56. package/dist/esm/ResourceInput/ResourceInput.js.map +1 -1
  57. package/dist/esm/ResourcePropertyDisplay/ResourcePropertyDisplay.js +4 -0
  58. package/dist/esm/ResourcePropertyDisplay/ResourcePropertyDisplay.js.map +1 -1
  59. package/dist/esm/ResourcePropertyInput/ResourcePropertyInput.js +4 -0
  60. package/dist/esm/ResourcePropertyInput/ResourcePropertyInput.js.map +1 -1
  61. package/dist/esm/ResourceTimeline/ResourceTimeline.js +3 -2
  62. package/dist/esm/ResourceTimeline/ResourceTimeline.js.map +1 -1
  63. package/dist/esm/SearchControl/SearchControl.js +2 -1
  64. package/dist/esm/SearchControl/SearchControl.js.map +1 -1
  65. package/dist/esm/StatusBadge/StatusBadge.js +2 -1
  66. package/dist/esm/StatusBadge/StatusBadge.js.map +1 -1
  67. package/dist/esm/Timeline/Timeline.d.ts +2 -4
  68. package/dist/esm/Timeline/Timeline.js +14 -10
  69. package/dist/esm/Timeline/Timeline.js.map +1 -1
  70. package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.d.ts +3 -6
  71. package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.js +24 -44
  72. package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.js.map +1 -1
  73. package/dist/esm/auth/AuthenticationForm.js +2 -2
  74. package/dist/esm/auth/AuthenticationForm.js.map +1 -1
  75. package/dist/esm/auth/ChooseProfileForm.d.ts +2 -1
  76. package/dist/esm/auth/ChooseProfileForm.js.map +1 -1
  77. package/dist/esm/auth/ChooseScopeForm.d.ts +2 -1
  78. package/dist/esm/auth/ChooseScopeForm.js.map +1 -1
  79. package/dist/esm/auth/MfaForm.d.ts +7 -0
  80. package/dist/esm/auth/MfaForm.js +34 -0
  81. package/dist/esm/auth/MfaForm.js.map +1 -0
  82. package/dist/esm/auth/NewProjectForm.js +5 -4
  83. package/dist/esm/auth/NewProjectForm.js.map +1 -1
  84. package/dist/esm/auth/NewUserForm.js +7 -6
  85. package/dist/esm/auth/NewUserForm.js.map +1 -1
  86. package/dist/esm/auth/OktaButton.d.ts +5 -0
  87. package/dist/esm/auth/SignInForm.d.ts +10 -0
  88. package/dist/esm/auth/SignInForm.js +16 -0
  89. package/dist/esm/auth/SignInForm.js.map +1 -1
  90. package/dist/esm/index.d.ts +3 -0
  91. package/dist/esm/index.js +3 -0
  92. package/dist/esm/index.js.map +1 -1
  93. package/dist/esm/index.min.js +1 -1
  94. package/dist/esm/index.min.js.map +1 -1
  95. package/dist/esm/stories/referenceLab.d.ts +3 -1
  96. package/package.json +1 -1
package/dist/cjs/index.js CHANGED
@@ -131,26 +131,41 @@
131
131
  return (React.createElement(core$1.TextInput, { name: props.name, placeholder: "Annotation text", defaultValue: value.text, onChange: (e) => setText(e.currentTarget.value) }));
132
132
  }
133
133
 
134
- function AttachmentDisplay(props) {
135
- const value = props.value;
136
- const { contentType, url, title } = value !== null && value !== void 0 ? value : {};
137
- if (!url) {
138
- return null;
139
- }
140
- return (React.createElement("div", { "data-testid": "attachment-display" },
141
- (contentType === null || contentType === void 0 ? void 0 : contentType.startsWith('image/')) && (React.createElement("img", { "data-testid": "attachment-image", style: { maxWidth: props.maxWidth }, src: url, alt: value === null || value === void 0 ? void 0 : value.title })),
142
- (contentType === null || contentType === void 0 ? void 0 : contentType.startsWith('video/')) && (React.createElement("video", { "data-testid": "attachment-video", style: { maxWidth: props.maxWidth }, controls: true },
143
- React.createElement("source", { type: contentType, src: url }))),
144
- contentType === 'application/pdf' && !(title === null || title === void 0 ? void 0 : title.endsWith('.pdf')) && (React.createElement("div", { "data-testid": "attachment-pdf", style: { maxWidth: props.maxWidth, minHeight: 400 } },
145
- React.createElement("iframe", { width: "100%", height: "400", src: url + '#navpanes=0', allowFullScreen: true, frameBorder: 0, seamless: true }))),
146
- React.createElement("div", { "data-testid": "download-link", style: { padding: '2px 16px 16px 16px' } },
147
- React.createElement("a", { href: value === null || value === void 0 ? void 0 : value.url, "data-testid": "attachment-details", target: "_blank", rel: "noopener noreferrer" }, (value === null || value === void 0 ? void 0 : value.title) || 'Download'))));
148
- }
149
-
150
- function AttachmentArrayDisplay(props) {
151
- return (React.createElement("div", null, props.values &&
152
- props.values.map((v, index) => (React.createElement("div", { key: 'attatchment-' + index },
153
- React.createElement(AttachmentDisplay, { value: v, maxWidth: props.maxWidth }))))));
134
+ /******************************************************************************
135
+ Copyright (c) Microsoft Corporation.
136
+
137
+ Permission to use, copy, modify, and/or distribute this software for any
138
+ purpose with or without fee is hereby granted.
139
+
140
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
141
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
142
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
143
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
144
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
145
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
146
+ PERFORMANCE OF THIS SOFTWARE.
147
+ ***************************************************************************** */
148
+
149
+ function __rest(s, e) {
150
+ var t = {};
151
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
152
+ t[p] = s[p];
153
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
154
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
155
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
156
+ t[p[i]] = s[p[i]];
157
+ }
158
+ return t;
159
+ }
160
+
161
+ function __awaiter(thisArg, _arguments, P, generator) {
162
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
163
+ return new (P || (P = Promise))(function (resolve, reject) {
164
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
165
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
166
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
167
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
168
+ });
154
169
  }
155
170
 
156
171
  /**
@@ -185,6 +200,137 @@
185
200
  return el instanceof HTMLInputElement && el.type === 'checkbox';
186
201
  }
187
202
 
203
+ function AsyncAutocomplete(props) {
204
+ const { defaultValue, toKey, toOption, loadOptions, onChange, onCreate } = props, rest = __rest(props, ["defaultValue", "toKey", "toOption", "loadOptions", "onChange", "onCreate"]);
205
+ const defaultItems = toDefaultItems(defaultValue);
206
+ const inputRef = React.useRef(null);
207
+ const [lastValue, setLastValue] = React.useState(undefined);
208
+ const [timer, setTimer] = React.useState();
209
+ const [abortController, setAbortController] = React.useState();
210
+ const [autoSubmit, setAutoSubmit] = React.useState();
211
+ const [options, setOptions] = React.useState(defaultItems === null || defaultItems === void 0 ? void 0 : defaultItems.map(toOption));
212
+ const lastValueRef = React.useRef();
213
+ lastValueRef.current = lastValue;
214
+ const timerRef = React.useRef();
215
+ timerRef.current = timer;
216
+ const abortControllerRef = React.useRef();
217
+ abortControllerRef.current = abortController;
218
+ const autoSubmitRef = React.useRef();
219
+ autoSubmitRef.current = autoSubmit;
220
+ const optionsRef = React.useRef();
221
+ optionsRef.current = options;
222
+ const handleTimer = React.useCallback(() => {
223
+ var _a, _b;
224
+ setTimer(undefined);
225
+ const value = ((_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.trim()) || '';
226
+ if (value === lastValueRef.current) {
227
+ // Nothing has changed, move on
228
+ return;
229
+ }
230
+ setLastValue(value);
231
+ const newAbortController = new AbortController();
232
+ setAbortController(newAbortController);
233
+ loadOptions(value, newAbortController.signal)
234
+ .then((newValues) => {
235
+ if (!newAbortController.signal.aborted) {
236
+ setOptions(newValues.map(toOption));
237
+ setAbortController(undefined);
238
+ if (autoSubmitRef.current) {
239
+ if (newValues.length > 0) {
240
+ onChange(newValues.slice(0, 1));
241
+ }
242
+ setAutoSubmit(false);
243
+ }
244
+ }
245
+ })
246
+ .catch(console.log);
247
+ }, [loadOptions, onChange, toOption]);
248
+ const handleSearchChange = React.useCallback(() => {
249
+ if (abortControllerRef.current) {
250
+ abortControllerRef.current.abort();
251
+ setAbortController(undefined);
252
+ }
253
+ if (timerRef.current !== undefined) {
254
+ window.clearTimeout(timerRef.current);
255
+ }
256
+ const newTimer = window.setTimeout(() => handleTimer(), 100);
257
+ setTimer(newTimer);
258
+ }, [handleTimer]);
259
+ const handleChange = React.useCallback((values) => {
260
+ var _a, _b;
261
+ const result = [];
262
+ for (const value of values) {
263
+ let item = (_b = (_a = optionsRef.current) === null || _a === void 0 ? void 0 : _a.find((option) => option.value === value)) === null || _b === void 0 ? void 0 : _b.resource;
264
+ if (!item) {
265
+ item = onCreate(value);
266
+ }
267
+ result.push(item);
268
+ }
269
+ onChange(result);
270
+ }, [onChange, onCreate]);
271
+ const handleKeyDown = React.useCallback((e) => {
272
+ if (e.key === 'Enter') {
273
+ if (!timerRef.current && !abortControllerRef.current) {
274
+ killEvent(e);
275
+ if (optionsRef.current && optionsRef.current.length > 0) {
276
+ setOptions(optionsRef.current.slice(0, 1));
277
+ handleChange([optionsRef.current[0].value]);
278
+ }
279
+ }
280
+ else {
281
+ // The user pressed enter, but we don't have results yet.
282
+ // We need to wait for the results to come in.
283
+ setAutoSubmit(true);
284
+ }
285
+ }
286
+ }, [handleChange]);
287
+ const handleCreate = React.useCallback((input) => {
288
+ const option = toOption(onCreate(input));
289
+ setOptions([...optionsRef.current, option]);
290
+ return option;
291
+ }, [onCreate, setOptions, toOption]);
292
+ const handleFilter = React.useCallback((_value, selected) => !selected, []);
293
+ React.useEffect(() => {
294
+ return () => {
295
+ if (abortControllerRef.current) {
296
+ abortControllerRef.current.abort();
297
+ }
298
+ };
299
+ }, []);
300
+ return (React.createElement(core$1.MultiSelect, Object.assign({}, rest, { ref: inputRef, defaultValue: defaultItems.map(toKey), searchable: true, onKeyDown: handleKeyDown, onSearchChange: handleSearchChange, data: options, onFocus: handleTimer, onChange: handleChange, onCreate: handleCreate, rightSectionWidth: 40, rightSection: abortController ? React.createElement(core$1.Loader, { size: 16 }) : null, filter: handleFilter })));
301
+ }
302
+ function toDefaultItems(defaultValue) {
303
+ if (!defaultValue) {
304
+ return [];
305
+ }
306
+ if (Array.isArray(defaultValue)) {
307
+ return defaultValue;
308
+ }
309
+ return [defaultValue];
310
+ }
311
+
312
+ function AttachmentDisplay(props) {
313
+ const value = props.value;
314
+ const { contentType, url, title } = value !== null && value !== void 0 ? value : {};
315
+ if (!url) {
316
+ return null;
317
+ }
318
+ return (React.createElement("div", { "data-testid": "attachment-display" },
319
+ (contentType === null || contentType === void 0 ? void 0 : contentType.startsWith('image/')) && (React.createElement("img", { "data-testid": "attachment-image", style: { maxWidth: props.maxWidth }, src: url, alt: value === null || value === void 0 ? void 0 : value.title })),
320
+ (contentType === null || contentType === void 0 ? void 0 : contentType.startsWith('video/')) && (React.createElement("video", { "data-testid": "attachment-video", style: { maxWidth: props.maxWidth }, controls: true },
321
+ React.createElement("source", { type: contentType, src: url }))),
322
+ contentType === 'application/pdf' && !(title === null || title === void 0 ? void 0 : title.endsWith('.pdf')) && (React.createElement("div", { "data-testid": "attachment-pdf", style: { maxWidth: props.maxWidth, minHeight: 400 } },
323
+ React.createElement("iframe", { width: "100%", height: "400", src: url + '#navpanes=0', allowFullScreen: true, frameBorder: 0, seamless: true }))),
324
+ React.createElement("div", { "data-testid": "download-link", style: { padding: '2px 16px 16px 16px' } },
325
+ React.createElement(core$1.Anchor, { href: value === null || value === void 0 ? void 0 : value.url, "data-testid": "attachment-details", target: "_blank", rel: "noopener noreferrer" }, (value === null || value === void 0 ? void 0 : value.title) || 'Download'))));
326
+ }
327
+
328
+ function AttachmentArrayDisplay(props) {
329
+ return (React.createElement("div", null, props.values &&
330
+ props.values.map((v, index) => (React.createElement("div", { key: 'attatchment-' + index },
331
+ React.createElement(AttachmentDisplay, { value: v, maxWidth: props.maxWidth }))))));
332
+ }
333
+
188
334
  function AttachmentButton(props) {
189
335
  const medplum = useMedplum();
190
336
  const fileInputRef = React.useRef(null);
@@ -292,50 +438,53 @@
292
438
  return (React.createElement(AttachmentButton, { onUpload: setValueWrapper }, (props) => React.createElement(core$1.Button, Object.assign({}, props), "Upload...")));
293
439
  }
294
440
 
295
- function Document(props) {
296
- let style = undefined;
297
- if (props.width) {
298
- style = { maxWidth: props.width };
299
- }
300
- return (React.createElement(core$1.Container, null,
301
- React.createElement(core$1.Paper, { style: style, mx: "auto", my: "lg", p: "lg", shadow: "xs", radius: "sm", withBorder: true }, props.children)));
441
+ const useStyles$d = core$1.createStyles(() => ({
442
+ root: {
443
+ '@media (max-width: 800px)': {
444
+ paddingLeft: 4,
445
+ paddingRight: 4,
446
+ },
447
+ },
448
+ }));
449
+ function Container(props) {
450
+ const { children } = props, others = __rest(props, ["children"]);
451
+ const { classes } = useStyles$d();
452
+ return (React.createElement(core$1.Container, Object.assign({ className: classes.root }, others), children));
302
453
  }
303
454
 
304
- /******************************************************************************
305
- Copyright (c) Microsoft Corporation.
306
-
307
- Permission to use, copy, modify, and/or distribute this software for any
308
- purpose with or without fee is hereby granted.
309
-
310
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
311
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
312
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
313
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
314
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
315
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
316
- PERFORMANCE OF THIS SOFTWARE.
317
- ***************************************************************************** */
318
-
319
- function __rest(s, e) {
320
- var t = {};
321
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
322
- t[p] = s[p];
323
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
324
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
325
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
326
- t[p[i]] = s[p[i]];
327
- }
328
- return t;
329
- }
330
-
331
- function __awaiter(thisArg, _arguments, P, generator) {
332
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
333
- return new (P || (P = Promise))(function (resolve, reject) {
334
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
335
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
336
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
337
- step((generator = generator.apply(thisArg, _arguments || [])).next());
338
- });
455
+ const useStyles$c = core$1.createStyles((theme, { width, fill }) => ({
456
+ paper: {
457
+ maxWidth: width,
458
+ margin: `${theme.spacing.xl}px auto`,
459
+ padding: fill ? 0 : theme.spacing.md,
460
+ '@media (max-width: 800px)': {
461
+ padding: fill ? 0 : 8,
462
+ },
463
+ '& img': {
464
+ width: '100%',
465
+ maxWidth: '100%',
466
+ },
467
+ '& video': {
468
+ width: '100%',
469
+ maxWidth: '100%',
470
+ },
471
+ },
472
+ }));
473
+ const defaultProps$1 = {
474
+ shadow: 'xs',
475
+ radius: 'md',
476
+ withBorder: true,
477
+ };
478
+ function Panel(props) {
479
+ const _a = core$1.useComponentDefaultProps('Panel', defaultProps$1, props), { className, children, width, fill, unstyled } = _a, others = __rest(_a, ["className", "children", "width", "fill", "unstyled"]);
480
+ const { classes, cx } = useStyles$c({ width, fill }, { name: 'Panel', unstyled });
481
+ return (React.createElement(core$1.Paper, Object.assign({ className: cx(classes.paper, className) }, others), children));
482
+ }
483
+
484
+ function Document(props) {
485
+ const { children } = props, others = __rest(props, ["children"]);
486
+ return (React.createElement(Container, null,
487
+ React.createElement(Panel, Object.assign({}, others), children)));
339
488
  }
340
489
 
341
490
  /**
@@ -452,10 +601,11 @@
452
601
  React.createElement(core$1.Stack, { spacing: "xl" },
453
602
  React.createElement(core$1.TextInput, { name: "projectName", label: "Project Name", placeholder: "My Project", required: true, autoFocus: true, error: getErrorsForInput(outcome, 'firstName') }),
454
603
  React.createElement(core$1.Text, { color: "dimmed", size: "xs" },
455
- "By clicking submit you agree to the Medplum ",
456
- React.createElement("a", { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
604
+ "By clicking submit you agree to the Medplum",
605
+ ' ',
606
+ React.createElement(core$1.Anchor, { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
457
607
  ' and ',
458
- React.createElement("a", { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
608
+ React.createElement(core$1.Anchor, { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
459
609
  ".")),
460
610
  React.createElement(core$1.Group, { position: "right", mt: "xl", noWrap: true },
461
611
  React.createElement(core$1.Button, { type: "submit" }, "Create project"))));
@@ -596,17 +746,18 @@
596
746
  React.createElement(core$1.TextInput, { name: "email", type: "email", label: "Email", placeholder: "name@domain.com", required: true, error: getErrorsForInput(outcome, 'email') }),
597
747
  React.createElement(core$1.PasswordInput, { name: "password", label: "Password", autoComplete: "off", required: true, error: getErrorsForInput(outcome, 'password') }),
598
748
  React.createElement(core$1.Text, { color: "dimmed", size: "xs" },
599
- "By clicking submit you agree to the Medplum ",
600
- React.createElement("a", { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
749
+ "By clicking submit you agree to the Medplum",
750
+ ' ',
751
+ React.createElement(core$1.Anchor, { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
601
752
  ' and ',
602
- React.createElement("a", { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
753
+ React.createElement(core$1.Anchor, { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
603
754
  "."),
604
755
  React.createElement(core$1.Text, { color: "dimmed", size: "xs" },
605
756
  "This site is protected by reCAPTCHA and the Google",
606
757
  ' ',
607
- React.createElement("a", { href: "https://policies.google.com/privacy" }, "Privacy\u00A0Policy"),
758
+ React.createElement(core$1.Anchor, { href: "https://policies.google.com/privacy" }, "Privacy\u00A0Policy"),
608
759
  ' and ',
609
- React.createElement("a", { href: "https://policies.google.com/terms" }, "Terms\u00A0of\u00A0Service"),
760
+ React.createElement(core$1.Anchor, { href: "https://policies.google.com/terms" }, "Terms\u00A0of\u00A0Service"),
610
761
  " apply.")),
611
762
  React.createElement(core$1.Group, { position: "apart", mt: "xl", noWrap: true },
612
763
  React.createElement(core$1.Checkbox, { name: "remember", label: "Remember me", size: "xs" }),
@@ -680,10 +831,10 @@
680
831
  React.createElement(core$1.Stack, { spacing: "xl" },
681
832
  React.createElement(core$1.TextInput, { name: "email", type: "email", label: "Email", placeholder: "name@domain.com", required: true, autoFocus: true, error: getErrorsForInput(outcome, 'email') }),
682
833
  React.createElement(core$1.PasswordInput, { name: "password", type: "password", label: "Password", autoComplete: "off", required: true, error: getErrorsForInput(outcome, 'password') })),
683
- React.createElement(core$1.Group, { position: "apart", mt: "xl", noWrap: true },
834
+ React.createElement(core$1.Group, { position: "apart", mt: "xl", spacing: 0, noWrap: true },
684
835
  onForgotPassword && (React.createElement(core$1.Anchor, { component: "button", type: "button", color: "dimmed", onClick: onForgotPassword, size: "xs" }, "Forgot password")),
685
836
  onRegister && (React.createElement(core$1.Anchor, { component: "button", type: "button", color: "dimmed", onClick: onRegister, size: "xs" }, "Register")),
686
- React.createElement(core$1.Checkbox, { id: "remember", name: "remember", label: "Remember me", size: "xs" }),
837
+ React.createElement(core$1.Checkbox, { id: "remember", name: "remember", label: "Remember me", size: "xs", sx: { lineHeight: 1 } }),
687
838
  React.createElement(core$1.Button, { type: "submit" }, "Sign in"))));
688
839
  }
689
840
 
@@ -732,12 +883,48 @@
732
883
  React.createElement(core$1.Button, { type: "submit" }, "Set scope")))));
733
884
  }
734
885
 
886
+ function MfaForm(props) {
887
+ const medplum = useMedplum();
888
+ const [errorMessage, setErrorMessage] = React.useState(undefined);
889
+ return (React.createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
890
+ setErrorMessage(undefined);
891
+ medplum
892
+ .post('auth/mfa/verify', {
893
+ login: props.login,
894
+ token: formData.token,
895
+ })
896
+ .then(props.handleAuthResponse)
897
+ .catch((err) => setErrorMessage(core.normalizeErrorString(err)));
898
+ } },
899
+ React.createElement(core$1.Stack, null,
900
+ React.createElement(core$1.Center, { sx: { flexDirection: 'column' } },
901
+ React.createElement(Logo, { size: 32 }),
902
+ React.createElement(core$1.Title, null, "Enter MFA code")),
903
+ errorMessage && (React.createElement(core$1.Alert, { icon: React.createElement(icons.IconAlertCircle, { size: 16 }), title: "Error", color: "red" }, errorMessage)),
904
+ React.createElement(core$1.Stack, null,
905
+ React.createElement(core$1.TextInput, { name: "token", label: "MFA code", required: true })),
906
+ React.createElement(core$1.Group, { position: "right", mt: "xl" },
907
+ React.createElement(core$1.Button, { type: "submit" }, "Submit code")))));
908
+ }
909
+
910
+ /**
911
+ * The SignInForm component allows users to sign in to Medplum.
912
+ *
913
+ * "Signing in" is a multi-step process:
914
+ * 1) Authentication - identify the user
915
+ * 2) MFA - If MFA is enabled, prompt for MFA code
916
+ * 3) Choose profile - If the user has multiple profiles, prompt to choose one
917
+ * 4) Choose scope - If the user has multiple scopes, prompt to choose one
918
+ * 5) Success - Return to the caller with either a code or a redirect
919
+ */
735
920
  function SignInForm(props) {
736
921
  const { chooseScopes, onSuccess, onForgotPassword, onRegister, onCode } = props, baseLoginRequest = __rest(props, ["chooseScopes", "onSuccess", "onForgotPassword", "onRegister", "onCode"]);
737
922
  const medplum = useMedplum();
738
923
  const [login, setLogin] = React.useState(undefined);
924
+ const [mfaRequired, setAuthenticatorRequired] = React.useState(false);
739
925
  const [memberships, setMemberships] = React.useState(undefined);
740
926
  function handleAuthResponse(response) {
927
+ setAuthenticatorRequired(!!response.mfaRequired);
741
928
  if (response.login) {
742
929
  setLogin(response.login);
743
930
  }
@@ -775,6 +962,9 @@
775
962
  if (!login) {
776
963
  return (React.createElement(AuthenticationForm, Object.assign({ generatePkce: !onCode, onForgotPassword: onForgotPassword, onRegister: onRegister, handleAuthResponse: handleAuthResponse }, baseLoginRequest), props.children));
777
964
  }
965
+ else if (mfaRequired) {
966
+ return React.createElement(MfaForm, { login: login, handleAuthResponse: handleAuthResponse });
967
+ }
778
968
  else if (memberships) {
779
969
  return React.createElement(ChooseProfileForm, { login: login, memberships: memberships, handleAuthResponse: handleAuthResponse });
780
970
  }
@@ -1028,6 +1218,7 @@
1028
1218
  case core.PropertyType.Period:
1029
1219
  return React.createElement(React.Fragment, null, core.formatPeriod(value));
1030
1220
  case core.PropertyType.Quantity:
1221
+ case core.PropertyType.Duration:
1031
1222
  return React.createElement(QuantityDisplay, { value: value });
1032
1223
  case core.PropertyType.Range:
1033
1224
  return React.createElement(RangeDisplay, { value: value });
@@ -1037,6 +1228,9 @@
1037
1228
  return React.createElement(ReferenceDisplay, { value: value, link: props.link });
1038
1229
  case core.PropertyType.Timing:
1039
1230
  return React.createElement(React.Fragment, null, core.formatTiming(value));
1231
+ case core.PropertyType.Dosage:
1232
+ case core.PropertyType.UsageContext:
1233
+ return (React.createElement(BackboneElementDisplay, { value: { type: propertyType, value }, compact: true, ignoreMissingValues: props.ignoreMissingValues }));
1040
1234
  default:
1041
1235
  if (!(property === null || property === void 0 ? void 0 : property.path)) {
1042
1236
  throw Error(`Displaying property of type ${props.propertyType} requires element definition path`);
@@ -1093,6 +1287,9 @@
1093
1287
  return null;
1094
1288
  }
1095
1289
  const property = entry[1];
1290
+ if (!property.path) {
1291
+ property.path = typeName + '.' + key;
1292
+ }
1096
1293
  const [propertyValue, propertyType] = getValueAndType(typedValue, key);
1097
1294
  if (props.ignoreMissingValues &&
1098
1295
  (!propertyValue || (Array.isArray(propertyValue) && propertyValue.length === 0))) {
@@ -1220,59 +1417,39 @@
1220
1417
  return obj;
1221
1418
  }
1222
1419
 
1223
- function valueSetElementToAutocompleteItem(element) {
1420
+ function toKey(element) {
1421
+ return element.code;
1422
+ }
1423
+ function toOption(element) {
1224
1424
  return {
1225
1425
  value: element.code,
1226
1426
  label: getDisplay(element),
1227
- element,
1427
+ resource: element,
1428
+ };
1429
+ }
1430
+ function createValue(input) {
1431
+ return {
1432
+ code: input,
1433
+ display: input,
1228
1434
  };
1229
1435
  }
1230
1436
  function ValueSetAutocomplete(props) {
1231
1437
  const medplum = useMedplum();
1232
- const { property, defaultValue } = props;
1233
- const [textValues, setTextValues] = React.useState((defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.code) ? [defaultValue.code] : []);
1234
- const [data, setData] = React.useState((defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.code) ? [valueSetElementToAutocompleteItem(defaultValue)] : []);
1235
- const dataRef = React.useRef();
1236
- dataRef.current = data;
1237
- const loadValues = React.useCallback((input) => __awaiter(this, void 0, void 0, function* () {
1438
+ const { elementDefinition } = props, rest = __rest(props, ["elementDefinition"]);
1439
+ const loadValues = React.useCallback((input, signal) => __awaiter(this, void 0, void 0, function* () {
1238
1440
  var _a, _b;
1239
- const system = (_a = property.binding) === null || _a === void 0 ? void 0 : _a.valueSet;
1240
- const valueSet = yield medplum.searchValueSet(system, input);
1441
+ const system = (_a = elementDefinition.binding) === null || _a === void 0 ? void 0 : _a.valueSet;
1442
+ const valueSet = yield medplum.searchValueSet(system, input, { signal });
1241
1443
  const valueSetElements = (_b = valueSet.expansion) === null || _b === void 0 ? void 0 : _b.contains;
1242
- const newData = [...dataRef.current];
1444
+ const newData = [];
1243
1445
  for (const valueSetElement of valueSetElements) {
1244
- if (valueSetElement.code && !newData.some((item) => item.value === valueSetElement.code)) {
1245
- newData.push(valueSetElementToAutocompleteItem(valueSetElement));
1246
- }
1247
- }
1248
- setData(newData);
1249
- }), [medplum, property, dataRef]);
1250
- function handleChange(values) {
1251
- setTextValues(values);
1252
- const textValue = values[0];
1253
- let currentItem = undefined;
1254
- if (textValue) {
1255
- currentItem = dataRef.current.find((item) => item.value === values[0]);
1256
- if (!currentItem) {
1257
- const newElement = { code: textValue, display: textValue };
1258
- currentItem = valueSetElementToAutocompleteItem(newElement);
1259
- setData([...dataRef.current, currentItem]);
1446
+ if (valueSetElement.code && !newData.some((item) => item.code === valueSetElement.code)) {
1447
+ newData.push(valueSetElement);
1260
1448
  }
1261
1449
  }
1262
- if (props.onChange) {
1263
- props.onChange(currentItem === null || currentItem === void 0 ? void 0 : currentItem.element);
1264
- }
1265
- }
1266
- React.useEffect(() => {
1267
- loadValues('').catch(console.log);
1268
- }, [loadValues]);
1269
- return (React.createElement(core$1.MultiSelect, { data: data, placeholder: props.placeholder, searchable: true, creatable: true, clearable: true, value: textValues, filter: (value, selected, item) => {
1270
- var _a, _b;
1271
- return !!(textValues.length === 0 &&
1272
- !selected &&
1273
- (((_a = item.element.display) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(value.toLowerCase().trim())) ||
1274
- ((_b = item.element.code) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes(value.toLowerCase().trim()))));
1275
- }, onChange: handleChange, getCreateLabel: (query) => `+ Create ${query}`, onCreate: (query) => valueSetElementToAutocompleteItem({ code: query, display: query }) }));
1450
+ return newData;
1451
+ }), [medplum, elementDefinition]);
1452
+ return (React.createElement(AsyncAutocomplete, Object.assign({}, rest, { creatable: true, clearable: true, toKey: toKey, toOption: toOption, loadOptions: loadValues, getCreateLabel: (query) => `+ Create ${query}`, onCreate: createValue })));
1276
1453
  }
1277
1454
  function getDisplay(item) {
1278
1455
  return item.display || item.code || '';
@@ -1280,46 +1457,47 @@
1280
1457
 
1281
1458
  function CodeableConceptInput(props) {
1282
1459
  const [value, setValue] = React.useState(props.defaultValue);
1283
- function handleChange(newValue) {
1284
- const newConcept = newValue && valueSetElementToCodeableConcept(newValue);
1460
+ function handleChange(newValues) {
1461
+ const newConcept = valueSetElementToCodeableConcept(newValues);
1285
1462
  setValue(newConcept);
1286
1463
  if (props.onChange) {
1287
1464
  props.onChange(newConcept);
1288
1465
  }
1289
1466
  }
1290
- return (React.createElement(ValueSetAutocomplete, { property: props.property, name: props.name, placeholder: props.placeholder, defaultValue: value && codeableConceptToValueSetElement(value), onChange: handleChange }));
1467
+ return (React.createElement(ValueSetAutocomplete, { elementDefinition: props.property, name: props.name, placeholder: props.placeholder, defaultValue: value && codeableConceptToValueSetElement(value), onChange: handleChange }));
1291
1468
  }
1292
1469
  function codeableConceptToValueSetElement(concept) {
1293
- var _a, _b, _c, _d, _e, _f;
1294
- return {
1295
- system: (_b = (_a = concept.coding) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.system,
1296
- code: (_d = (_c = concept.coding) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.code,
1297
- display: (_f = (_e = concept.coding) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.display,
1298
- };
1470
+ var _a;
1471
+ return (_a = concept.coding) === null || _a === void 0 ? void 0 : _a.map((c) => ({
1472
+ system: c.system,
1473
+ code: c.code,
1474
+ display: c.display,
1475
+ }));
1299
1476
  }
1300
- function valueSetElementToCodeableConcept(element) {
1477
+ function valueSetElementToCodeableConcept(elements) {
1478
+ if (elements.length === 0) {
1479
+ return undefined;
1480
+ }
1301
1481
  return {
1302
- text: element.display,
1303
- coding: [
1304
- {
1305
- system: element.system,
1306
- code: element.code,
1307
- display: element.display,
1308
- },
1309
- ],
1482
+ coding: elements.map((e) => ({
1483
+ system: e.system,
1484
+ code: e.code,
1485
+ display: e.display,
1486
+ })),
1310
1487
  };
1311
1488
  }
1312
1489
 
1313
1490
  function CodeInput(props) {
1314
1491
  const [value, setValue] = React.useState(props.defaultValue);
1315
- function handleChange(newValue) {
1492
+ function handleChange(newValues) {
1493
+ const newValue = newValues[0];
1316
1494
  const newCode = valueSetElementToCode(newValue);
1317
1495
  setValue(newCode);
1318
1496
  if (props.onChange) {
1319
1497
  props.onChange(newCode);
1320
1498
  }
1321
1499
  }
1322
- return (React.createElement(ValueSetAutocomplete, { property: props.property, name: props.name, placeholder: props.placeholder, defaultValue: codeToValueSetElement(value), onChange: handleChange }));
1500
+ return (React.createElement(ValueSetAutocomplete, { elementDefinition: props.property, name: props.name, placeholder: props.placeholder, defaultValue: codeToValueSetElement(value), onChange: handleChange }));
1323
1501
  }
1324
1502
  function codeToValueSetElement(code) {
1325
1503
  return code ? { code } : undefined;
@@ -1330,14 +1508,15 @@
1330
1508
 
1331
1509
  function CodingInput(props) {
1332
1510
  const [value, setValue] = React.useState(props.defaultValue);
1333
- function handleChange(newValue) {
1511
+ function handleChange(newValues) {
1512
+ const newValue = newValues[0];
1334
1513
  const newConcept = newValue && valueSetElementToCoding(newValue);
1335
1514
  setValue(newConcept);
1336
1515
  if (props.onChange) {
1337
1516
  props.onChange(newConcept);
1338
1517
  }
1339
1518
  }
1340
- return (React.createElement(ValueSetAutocomplete, { property: props.property, name: props.name, placeholder: props.placeholder, defaultValue: value && codingToValueSetElement(value), onChange: handleChange }));
1519
+ return (React.createElement(ValueSetAutocomplete, { elementDefinition: props.property, name: props.name, placeholder: props.placeholder, defaultValue: value && codingToValueSetElement(value), onChange: handleChange }));
1341
1520
  }
1342
1521
  function codingToValueSetElement(coding) {
1343
1522
  return {
@@ -1645,6 +1824,7 @@
1645
1824
  Observation: 'code',
1646
1825
  RequestGroup: '_id',
1647
1826
  ActivityDefinition: 'name',
1827
+ User: 'email:contains',
1648
1828
  };
1649
1829
  function ResourceInput(props) {
1650
1830
  const medplum = useMedplum();
@@ -1662,7 +1842,7 @@
1662
1842
  setLoading(true);
1663
1843
  const searchCode = SEARCH_CODES[props.resourceType] || 'name';
1664
1844
  const searchParams = new URLSearchParams({
1665
- [searchCode]: encodeURIComponent(input),
1845
+ [searchCode]: input,
1666
1846
  _count: '10',
1667
1847
  });
1668
1848
  const resources = yield medplum.searchResources(props.resourceType, searchParams);
@@ -1968,6 +2148,7 @@
1968
2148
  return React.createElement(IdentifierInput, { name: name, defaultValue: value, onChange: props.onChange });
1969
2149
  case core.PropertyType.Period:
1970
2150
  return React.createElement(PeriodInput, { name: name, defaultValue: value, onChange: props.onChange });
2151
+ case core.PropertyType.Duration:
1971
2152
  case core.PropertyType.Quantity:
1972
2153
  return React.createElement(QuantityInput, { name: name, defaultValue: value, onChange: props.onChange });
1973
2154
  case core.PropertyType.Range:
@@ -1978,6 +2159,9 @@
1978
2159
  return (React.createElement(ReferenceInput, { name: name, defaultValue: value, targetTypes: getTargetTypes(property), onChange: props.onChange }));
1979
2160
  case core.PropertyType.Timing:
1980
2161
  return React.createElement(TimingInput, { name: name, defaultValue: value, onChange: props.onChange });
2162
+ case core.PropertyType.Dosage:
2163
+ case core.PropertyType.UsageContext:
2164
+ return (React.createElement(BackboneElementInput, { typeName: propertyType, defaultValue: value, onChange: props.onChange, outcome: props.outcome }));
1981
2165
  default:
1982
2166
  return (React.createElement(BackboneElementInput, { typeName: core.buildTypeName((_a = property.path) === null || _a === void 0 ? void 0 : _a.split('.')), defaultValue: value, onChange: props.onChange, outcome: props.outcome }));
1983
2167
  }
@@ -2171,6 +2355,64 @@
2171
2355
  React.createElement(ResourceName, { value: props.value, link: props.link })));
2172
2356
  }
2173
2357
 
2358
+ /*
2359
+ * Request status: https://hl7.org/fhir/valueset-request-status.html
2360
+ * draft, active, on-hold, revoked, completed, entered-in-error, unknown
2361
+ *
2362
+ * Publication status: https://hl7.org/fhir/valueset-publication-status.html
2363
+ * draft, active, retired, unknown
2364
+ *
2365
+ * Observation status: https://www.hl7.org/fhir/valueset-observation-status.html
2366
+ * registered, preliminary, final, amended, corrected, cancelled, entered-in-error, unknown
2367
+ *
2368
+ * DiagnosticReport status: https://hl7.org/fhir/valueset-diagnostic-report-status.html
2369
+ * registered, preliminary, final, amended, corrected, appended, cancelled, entered-in-error, unknown
2370
+ *
2371
+ * Task status: https://hl7.org/fhir/valueset-task-status.html
2372
+ * draft, requested, received, accepted, rejected, ready, cancelled, in-progress, on-hold, failed, completed, entered-in-error
2373
+ *
2374
+ * Appointment status: https://www.hl7.org/fhir/valueset-appointmentstatus.html
2375
+ * proposed, pending, booked, arrived, fulfilled, cancelled, noshow, entered-in-error, chcked-in, waitlist
2376
+ */
2377
+ const statusToColor = {
2378
+ draft: 'blue',
2379
+ active: 'blue',
2380
+ 'on-hold': 'yellow',
2381
+ revoked: 'red',
2382
+ completed: 'green',
2383
+ 'entered-in-error': 'red',
2384
+ unknown: 'gray',
2385
+ retired: 'gray',
2386
+ registered: 'blue',
2387
+ preliminary: 'blue',
2388
+ final: 'green',
2389
+ amended: 'yellow',
2390
+ corrected: 'yellow',
2391
+ cancelled: 'red',
2392
+ requested: 'blue',
2393
+ received: 'blue',
2394
+ accepted: 'blue',
2395
+ rejected: 'red',
2396
+ ready: 'blue',
2397
+ 'in-progress': 'blue',
2398
+ failed: 'red',
2399
+ proposed: 'blue',
2400
+ pending: 'blue',
2401
+ booked: 'blue',
2402
+ arrived: 'blue',
2403
+ fulfilled: 'green',
2404
+ noshow: 'red',
2405
+ 'checked-in': 'blue',
2406
+ waitlist: 'gray',
2407
+ routine: 'gray',
2408
+ urgent: 'red',
2409
+ asap: 'red',
2410
+ stat: 'red',
2411
+ };
2412
+ function StatusBadge(props) {
2413
+ return React.createElement(core$1.Badge, { color: statusToColor[props.status] }, props.status);
2414
+ }
2415
+
2174
2416
  const useStyles$9 = core$1.createStyles((theme) => ({
2175
2417
  table: {
2176
2418
  border: `0.1px solid ${theme.colors.gray[5]}`,
@@ -2239,7 +2481,9 @@
2239
2481
  React.createElement("th", null, "Test"),
2240
2482
  React.createElement("th", null, "Value"),
2241
2483
  React.createElement("th", null, "Reference Range"),
2242
- React.createElement("th", null, "Interpretation"))),
2484
+ React.createElement("th", null, "Interpretation"),
2485
+ React.createElement("th", null, "Category"),
2486
+ React.createElement("th", null, "Status"))),
2243
2487
  React.createElement("tbody", null, (_a = props.value) === null || _a === void 0 ? void 0 : _a.map((observation, index) => (React.createElement(ObservationRow, { key: 'obs-' + index, value: observation }))))));
2244
2488
  }
2245
2489
  function ObservationRow(props) {
@@ -2257,7 +2501,10 @@
2257
2501
  React.createElement(ObservationValueDisplay, { value: observation })),
2258
2502
  React.createElement("td", null,
2259
2503
  React.createElement(ReferenceRangeDisplay, { value: observation.referenceRange })),
2260
- React.createElement("td", null, observation.interpretation && observation.interpretation.length > 0 && (React.createElement(CodeableConceptDisplay, { value: observation.interpretation[0] })))));
2504
+ React.createElement("td", null, observation.interpretation && observation.interpretation.length > 0 && (React.createElement(CodeableConceptDisplay, { value: observation.interpretation[0] }))),
2505
+ React.createElement("td", null, observation.category && observation.category.length > 0 && (React.createElement("ul", null, observation.category.map((concept) => (React.createElement("li", null,
2506
+ React.createElement(CodeableConceptDisplay, { value: concept }))))))),
2507
+ React.createElement("td", null, observation.status && React.createElement(StatusBadge, { status: observation.status }))));
2261
2508
  }
2262
2509
  function ObservationValueDisplay(props) {
2263
2510
  const obs = props.value;
@@ -2396,29 +2643,30 @@
2396
2643
  }
2397
2644
 
2398
2645
  function Timeline(props) {
2399
- return React.createElement(core$1.Container, null, props.children);
2646
+ return React.createElement(Container, null, props.children);
2400
2647
  }
2401
2648
  function TimelineItem(props) {
2402
- var _a, _b, _c;
2403
- const author = (_a = props.profile) !== null && _a !== void 0 ? _a : (_b = props.resource.meta) === null || _b === void 0 ? void 0 : _b.author;
2404
- return (React.createElement(core$1.Paper, { "data-testid": "timeline-item", m: "lg", p: "sm", shadow: "xs", radius: "sm", withBorder: true, className: props.className },
2405
- React.createElement(core$1.Group, { position: "apart", spacing: 8 },
2649
+ var _a, _b;
2650
+ const { resource, profile, padding, popupMenuItems } = props, others = __rest(props, ["resource", "profile", "padding", "popupMenuItems"]);
2651
+ const author = profile !== null && profile !== void 0 ? profile : (_a = resource.meta) === null || _a === void 0 ? void 0 : _a.author;
2652
+ return (React.createElement(Panel, Object.assign({ "data-testid": "timeline-item", fill: true }, others),
2653
+ React.createElement(core$1.Group, { position: "apart", spacing: 8, mx: "xs", my: "sm" },
2406
2654
  React.createElement(ResourceAvatar, { value: author, link: true, size: "md" }),
2407
2655
  React.createElement("div", { style: { flex: 1 } },
2408
2656
  React.createElement(core$1.Text, { size: "sm" },
2409
2657
  React.createElement(ResourceName, { color: "dark", weight: 500, value: author, link: true })),
2410
2658
  React.createElement(core$1.Text, { size: "xs" },
2411
- React.createElement(MedplumLink, { color: "dimmed", to: props.resource }, core.formatDateTime((_c = props.resource.meta) === null || _c === void 0 ? void 0 : _c.lastUpdated)),
2659
+ React.createElement(MedplumLink, { color: "dimmed", to: props.resource }, core.formatDateTime((_b = props.resource.meta) === null || _b === void 0 ? void 0 : _b.lastUpdated)),
2412
2660
  React.createElement(core$1.Text, { component: "span", color: "dimmed", mx: 8 }, "\u00B7"),
2413
2661
  React.createElement(MedplumLink, { color: "dimmed", to: props.resource }, props.resource.resourceType))),
2414
- props.popupMenuItems && (React.createElement(core$1.Menu, { position: "bottom-end", shadow: "md", width: 200 },
2662
+ popupMenuItems && (React.createElement(core$1.Menu, { position: "bottom-end", shadow: "md", width: 200 },
2415
2663
  React.createElement(core$1.Menu.Target, null,
2416
2664
  React.createElement(core$1.ActionIcon, { radius: "xl", "aria-label": `Actions for ${core.getReferenceString(props.resource)}` },
2417
2665
  React.createElement(icons.IconDots, null))),
2418
- props.popupMenuItems))),
2666
+ popupMenuItems))),
2419
2667
  React.createElement(ErrorBoundary, null,
2420
- props.padding && React.createElement("div", { style: { padding: '2px 16px 16px 16px' } }, props.children),
2421
- !props.padding && React.createElement(React.Fragment, null, props.children))));
2668
+ padding && React.createElement("div", { style: { padding: '0 16px 16px 16px' } }, props.children),
2669
+ !padding && React.createElement(React.Fragment, null, props.children))));
2422
2670
  }
2423
2671
 
2424
2672
  /**
@@ -2625,7 +2873,7 @@
2625
2873
  React.createElement(core$1.Loader, null)));
2626
2874
  }
2627
2875
  return (React.createElement(Timeline, null,
2628
- props.createCommunication && (React.createElement(core$1.Paper, { m: "lg", p: "sm", shadow: "xs", radius: "sm", withBorder: true },
2876
+ props.createCommunication && (React.createElement(Panel, null,
2629
2877
  React.createElement(Form, { testid: "timeline-form", onSubmit: (formData) => {
2630
2878
  createComment(formData.text);
2631
2879
  const input = inputRef.current;
@@ -4049,7 +4297,7 @@
4049
4297
  checkboxColumn && (React.createElement("td", null,
4050
4298
  React.createElement("input", { type: "checkbox", value: "checked", "data-testid": "row-checkbox", "aria-label": `Checkbox for ${resource.id}`, checked: !!state.selected[resource.id], onChange: (e) => handleSingleCheckboxClick(e, resource.id) }))),
4051
4299
  fields.map((field) => (React.createElement("td", { key: field.name }, renderValue(resource, field))))))))),
4052
- (resources === null || resources === void 0 ? void 0 : resources.length) === 0 && (React.createElement(core$1.Container, null,
4300
+ (resources === null || resources === void 0 ? void 0 : resources.length) === 0 && (React.createElement(Container, null,
4053
4301
  React.createElement(core$1.Center, null,
4054
4302
  React.createElement(core$1.Text, { size: "xl", color: "dimmed" }, "No results")))),
4055
4303
  (lastResult === null || lastResult === void 0 ? void 0 : lastResult.total) !== undefined && lastResult.total > 0 && (React.createElement(core$1.Center, { m: "md", p: "md" },
@@ -4341,7 +4589,7 @@
4341
4589
  props.actions.map((action) => (React.createElement("div", { key: action.id },
4342
4590
  React.createElement(ActionBuilder, { action: action, selectedKey: props.selectedKey, setSelectedKey: props.setSelectedKey, hoverKey: props.hoverKey, setHoverKey: props.setHoverKey, onChange: changeAction, onRemove: () => removeAction(action) })))),
4343
4591
  React.createElement("div", { className: classes.bottomActions },
4344
- React.createElement("a", { href: "#", onClick: (e) => {
4592
+ React.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
4345
4593
  killEvent(e);
4346
4594
  addAction({ id: generateId$1() });
4347
4595
  } }, "Add action"))));
@@ -4367,7 +4615,7 @@
4367
4615
  return (React.createElement("div", { "data-testid": action.id, className: className, onClick: onClick, onMouseOver: onHover },
4368
4616
  editing ? (React.createElement(ActionEditor, { action: action, actionType: actionType, onChange: props.onChange, selectedKey: props.selectedKey, setSelectedKey: props.setSelectedKey, hoverKey: props.hoverKey, setHoverKey: props.setHoverKey, onRemove: props.onRemove })) : (React.createElement(ActionDisplay, { action: action, actionType: actionType })),
4369
4617
  React.createElement("div", { className: classes.bottomActions },
4370
- React.createElement("a", { href: "#", onClick: (e) => {
4618
+ React.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
4371
4619
  e.preventDefault();
4372
4620
  props.onRemove();
4373
4621
  } }, "Remove"))));
@@ -4531,6 +4779,7 @@
4531
4779
  function setItems(newResponseItems) {
4532
4780
  const newResponse = {
4533
4781
  resourceType: 'QuestionnaireResponse',
4782
+ status: 'completed',
4534
4783
  item: newResponseItems,
4535
4784
  };
4536
4785
  setResponse(newResponse);
@@ -4917,7 +5166,7 @@
4917
5166
  ] })))) : (React.createElement("div", null, linkId)))),
4918
5167
  React.createElement("div", { className: classes.bottomActions },
4919
5168
  isContainer && (React.createElement(React.Fragment, null,
4920
- React.createElement("a", { href: "#", onClick: (e) => {
5169
+ React.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
4921
5170
  e.preventDefault();
4922
5171
  addItem({
4923
5172
  id: generateId(),
@@ -4926,7 +5175,7 @@
4926
5175
  text: 'Question',
4927
5176
  });
4928
5177
  } }, "Add item"),
4929
- React.createElement("a", { href: "#", onClick: (e) => {
5178
+ React.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
4930
5179
  e.preventDefault();
4931
5180
  addItem({
4932
5181
  id: generateId(),
@@ -4935,7 +5184,7 @@
4935
5184
  text: 'Group',
4936
5185
  });
4937
5186
  } }, "Add group"))),
4938
- editing && !isResource && (React.createElement("a", { href: "#", onClick: (e) => {
5187
+ editing && !isResource && (React.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
4939
5188
  e.preventDefault();
4940
5189
  if (props.onRemove) {
4941
5190
  props.onRemove();
@@ -4964,12 +5213,12 @@
4964
5213
  props.onChange(newOptions);
4965
5214
  } })),
4966
5215
  React.createElement("div", null,
4967
- React.createElement("a", { href: "#", onClick: (e) => {
5216
+ React.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
4968
5217
  killEvent(e);
4969
5218
  props.onChange(options.filter((o) => o.id !== option.id));
4970
5219
  } }, "Remove"))));
4971
5220
  }),
4972
- React.createElement("a", { href: "#", onClick: (e) => {
5221
+ React.createElement(core$1.Anchor, { href: "#", onClick: (e) => {
4973
5222
  killEvent(e);
4974
5223
  props.onChange([
4975
5224
  ...options,
@@ -5129,7 +5378,7 @@
5129
5378
  function ReferenceRangeGroupEditor(props) {
5130
5379
  const { intervalGroup, unit } = props;
5131
5380
  const { classes } = useStyles$3();
5132
- return (React.createElement(core$1.Container, { "data-testid": intervalGroup.id, className: classes.section },
5381
+ return (React.createElement(Container, { "data-testid": intervalGroup.id, className: classes.section },
5133
5382
  React.createElement(core$1.Stack, { spacing: 'lg' },
5134
5383
  React.createElement(core$1.Group, { position: "right" },
5135
5384
  React.createElement(core$1.ActionIcon, { title: "Remove Group", "data-testid": `remove-group-button-${intervalGroup.id}`, key: `remove-group-button-${intervalGroup.id}`, size: "sm", onClick: (e) => {
@@ -5284,63 +5533,6 @@
5284
5533
  return ((_b = (_a = interval.range) === null || _a === void 0 ? void 0 : _a.low) === null || _b === void 0 ? void 0 : _b.value) === undefined && ((_d = (_c = interval.range) === null || _c === void 0 ? void 0 : _c.high) === null || _d === void 0 ? void 0 : _d.value) === undefined;
5285
5534
  }
5286
5535
 
5287
- /*
5288
- * Request status: https://hl7.org/fhir/valueset-request-status.html
5289
- * draft, active, on-hold, revoked, completed, entered-in-error, unknown
5290
- *
5291
- * Publication status: https://hl7.org/fhir/valueset-publication-status.html
5292
- * draft, active, retired, unknown
5293
- *
5294
- * Observation status: https://www.hl7.org/fhir/valueset-observation-status.html
5295
- * registered, preliminary, final, amended, cancelled, entered-in-error, unknown
5296
- *
5297
- * DiagnosticReport status: https://hl7.org/fhir/valueset-diagnostic-report-status.html
5298
- * registered, preliminary, final, amended, corrected, appended, cancelled, entered-in-error, unknown
5299
- *
5300
- * Task status: https://hl7.org/fhir/valueset-task-status.html
5301
- * draft, requested, received, accepted, rejected, ready, cancelled, in-progress, on-hold, failed, completed, entered-in-error
5302
- *
5303
- * Appointment status: https://www.hl7.org/fhir/valueset-appointmentstatus.html
5304
- * proposed, pending, booked, arrived, fulfilled, cancelled, noshow, entered-in-error, chcked-in, waitlist
5305
- */
5306
- const statusToColor = {
5307
- draft: 'blue',
5308
- active: 'blue',
5309
- 'on-hold': 'yellow',
5310
- revoked: 'red',
5311
- completed: 'green',
5312
- 'entered-in-error': 'red',
5313
- unknown: 'gray',
5314
- retired: 'gray',
5315
- registered: 'blue',
5316
- preliminary: 'blue',
5317
- final: 'green',
5318
- amended: 'yellow',
5319
- cancelled: 'red',
5320
- requested: 'blue',
5321
- received: 'blue',
5322
- accepted: 'blue',
5323
- rejected: 'red',
5324
- ready: 'blue',
5325
- 'in-progress': 'blue',
5326
- failed: 'red',
5327
- proposed: 'blue',
5328
- pending: 'blue',
5329
- booked: 'blue',
5330
- arrived: 'blue',
5331
- fulfilled: 'green',
5332
- noshow: 'red',
5333
- 'checked-in': 'blue',
5334
- waitlist: 'gray',
5335
- routine: 'gray',
5336
- urgent: 'red',
5337
- asap: 'red',
5338
- stat: 'red',
5339
- };
5340
- function StatusBadge(props) {
5341
- return React.createElement(core$1.Badge, { color: statusToColor[props.status] }, props.status);
5342
- }
5343
-
5344
5536
  function RequestGroupDisplay(props) {
5345
5537
  var _a;
5346
5538
  const medplum = useMedplum();
@@ -5910,6 +6102,7 @@
5910
6102
  exports.AddressDisplay = AddressDisplay;
5911
6103
  exports.AddressInput = AddressInput;
5912
6104
  exports.AnnotationInput = AnnotationInput;
6105
+ exports.AsyncAutocomplete = AsyncAutocomplete;
5913
6106
  exports.AttachmentArrayDisplay = AttachmentArrayDisplay;
5914
6107
  exports.AttachmentArrayInput = AttachmentArrayInput;
5915
6108
  exports.AttachmentButton = AttachmentButton;
@@ -5928,6 +6121,7 @@
5928
6121
  exports.ContactDetailInput = ContactDetailInput;
5929
6122
  exports.ContactPointDisplay = ContactPointDisplay;
5930
6123
  exports.ContactPointInput = ContactPointInput;
6124
+ exports.Container = Container;
5931
6125
  exports.DateTimeInput = DateTimeInput;
5932
6126
  exports.DefaultResourceTimeline = DefaultResourceTimeline;
5933
6127
  exports.DescriptionList = DescriptionList;
@@ -5951,6 +6145,7 @@
5951
6145
  exports.MemoizedFhirPathTable = MemoizedFhirPathTable;
5952
6146
  exports.MemoizedSearchControl = MemoizedSearchControl;
5953
6147
  exports.ObservationTable = ObservationTable;
6148
+ exports.Panel = Panel;
5954
6149
  exports.PatientTimeline = PatientTimeline;
5955
6150
  exports.PlanDefinitionBuilder = PlanDefinitionBuilder;
5956
6151
  exports.QuantityDisplay = QuantityDisplay;