@medplum/react 0.9.21 → 0.9.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -1776,18 +1776,24 @@
1776
1776
  }
1777
1777
 
1778
1778
  function DiagnosticReportDisplay(props) {
1779
- var _a;
1779
+ var _a, _b;
1780
1780
  const diagnosticReport = useResource(props.value);
1781
+ const specimen = useResource((_a = diagnosticReport === null || diagnosticReport === void 0 ? void 0 : diagnosticReport.specimen) === null || _a === void 0 ? void 0 : _a[0]);
1781
1782
  if (!diagnosticReport) {
1782
1783
  return null;
1783
1784
  }
1784
- let textContent = undefined;
1785
+ let textContent = '';
1785
1786
  if (diagnosticReport.presentedForm && diagnosticReport.presentedForm.length > 0) {
1786
1787
  const pf = diagnosticReport.presentedForm[0];
1787
- if (((_a = pf.contentType) === null || _a === void 0 ? void 0 : _a.startsWith('text/plain')) && pf.data) {
1788
+ if (((_b = pf.contentType) === null || _b === void 0 ? void 0 : _b.startsWith('text/plain')) && pf.data) {
1788
1789
  textContent = window.atob(pf.data);
1789
1790
  }
1790
1791
  }
1792
+ if (specimen === null || specimen === void 0 ? void 0 : specimen.note) {
1793
+ for (const note of specimen.note) {
1794
+ textContent += note.text + '\n\n';
1795
+ }
1796
+ }
1791
1797
  return (React__default["default"].createElement("div", { className: "medplum-diagnostic-report" },
1792
1798
  React__default["default"].createElement("h1", null, "Diagnostic Report"),
1793
1799
  React__default["default"].createElement("div", { className: "medplum-diagnostic-report-header" },
@@ -1807,8 +1813,8 @@
1807
1813
  diagnosticReport.status && (React__default["default"].createElement("dl", null,
1808
1814
  React__default["default"].createElement("dt", null, "Status"),
1809
1815
  React__default["default"].createElement("dd", null, core.capitalize(diagnosticReport.status))))),
1810
- textContent && React__default["default"].createElement("pre", null, textContent),
1811
- diagnosticReport.result && React__default["default"].createElement(ObservationTable, { value: diagnosticReport.result })));
1816
+ diagnosticReport.result && React__default["default"].createElement(ObservationTable, { value: diagnosticReport.result }),
1817
+ textContent && React__default["default"].createElement("pre", null, textContent.trim())));
1812
1818
  }
1813
1819
  function ObservationTable(props) {
1814
1820
  var _a;
@@ -4904,6 +4910,176 @@
4904
4910
  return options.map((option) => (Object.assign(Object.assign({}, option), { id: option.id || generateId() })));
4905
4911
  }
4906
4912
 
4913
+ /**
4914
+ * Dynamically creates a script tag for the specified JavaScript file.
4915
+ * @param src The JavaScript file URL.
4916
+ */
4917
+ function createScriptTag(src, onload) {
4918
+ const head = document.getElementsByTagName('head')[0];
4919
+ const script = document.createElement('script');
4920
+ script.async = true;
4921
+ script.src = src;
4922
+ script.onload = onload || null;
4923
+ head.appendChild(script);
4924
+ }
4925
+
4926
+ function GoogleButton(props) {
4927
+ const medplum = useMedplum();
4928
+ const { googleClientId, handleGoogleCredential } = props;
4929
+ const parentRef = React.useRef(null);
4930
+ const [scriptLoaded, setScriptLoaded] = React.useState(typeof google !== 'undefined');
4931
+ const [initialized, setInitialized] = React.useState(false);
4932
+ const [buttonRendered, setButtonRendered] = React.useState(false);
4933
+ React.useEffect(() => {
4934
+ if (typeof google === 'undefined') {
4935
+ createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));
4936
+ return;
4937
+ }
4938
+ if (!initialized) {
4939
+ google.accounts.id.initialize({
4940
+ client_id: googleClientId,
4941
+ callback: handleGoogleCredential,
4942
+ });
4943
+ setInitialized(true);
4944
+ }
4945
+ if (parentRef.current && !buttonRendered) {
4946
+ google.accounts.id.renderButton(parentRef.current, {});
4947
+ setButtonRendered(true);
4948
+ }
4949
+ }, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);
4950
+ if (!googleClientId) {
4951
+ return null;
4952
+ }
4953
+ return React__default["default"].createElement("div", { ref: parentRef });
4954
+ }
4955
+ function getGoogleClientId(clientId) {
4956
+ var _a, _b;
4957
+ if (clientId) {
4958
+ return clientId;
4959
+ }
4960
+ const origin = window.location.protocol + '//' + window.location.host;
4961
+ const authorizedOrigins = (_b = (_a = "http://localhost:3000,http://localhost:6006,https://app.medplum.com,https://docs.medplum.com") === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : [];
4962
+ if (authorizedOrigins.includes(origin)) {
4963
+ return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
4964
+ }
4965
+ return undefined;
4966
+ }
4967
+
4968
+ /**
4969
+ * Dynamically loads the recaptcha script.
4970
+ * We do not want to load the script on page load unless the user needs it.
4971
+ */
4972
+ function initRecaptcha() {
4973
+ if (typeof grecaptcha === 'undefined') {
4974
+ createScriptTag('https://www.google.com/recaptcha/api.js?render=' + process.env.RECAPTCHA_SITE_KEY);
4975
+ }
4976
+ }
4977
+ /**
4978
+ * Starts a request to generate a recapcha token.
4979
+ * @returns Promise to a recaptcha token for the current user.
4980
+ */
4981
+ function getRecaptcha() {
4982
+ return new Promise((resolve) => {
4983
+ grecaptcha.ready(() => {
4984
+ grecaptcha.execute(process.env.RECAPTCHA_SITE_KEY, { action: 'submit' }).then(resolve);
4985
+ });
4986
+ });
4987
+ }
4988
+
4989
+ function RegisterForm(props) {
4990
+ const medplum = useMedplum();
4991
+ const googleClientId = getGoogleClientId(props.googleClientId);
4992
+ const [outcome, setOutcome] = React.useState();
4993
+ const issues = getIssuesForExpression(outcome, undefined);
4994
+ React.useEffect(initRecaptcha, []);
4995
+ function handleAuthResponse(registerRequest, partialLogin) {
4996
+ return __awaiter(this, void 0, void 0, function* () {
4997
+ try {
4998
+ let login;
4999
+ if (props.type === 'patient') {
5000
+ login = yield medplum.startNewPatient(registerRequest, partialLogin);
5001
+ }
5002
+ else {
5003
+ login = yield medplum.startNewProject(registerRequest, partialLogin);
5004
+ }
5005
+ yield medplum.processCode(login.code);
5006
+ props.onSuccess();
5007
+ }
5008
+ catch (err) {
5009
+ setOutcome(err);
5010
+ }
5011
+ });
5012
+ }
5013
+ return (React__default["default"].createElement(Document, { width: 450 },
5014
+ React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => __awaiter(this, void 0, void 0, function* () {
5015
+ try {
5016
+ const recaptchaToken = yield getRecaptcha();
5017
+ const registerRequest = Object.assign(Object.assign({}, formData), { recaptchaToken });
5018
+ const userLogin = yield medplum.startNewUser(registerRequest);
5019
+ handleAuthResponse(registerRequest, userLogin);
5020
+ }
5021
+ catch (err) {
5022
+ setOutcome(err);
5023
+ }
5024
+ }) },
5025
+ React__default["default"].createElement("div", { className: "medplum-center" }, props.children),
5026
+ issues && (React__default["default"].createElement("div", { className: "medplum-input-error" }, issues.map((issue) => {
5027
+ var _a, _b;
5028
+ return (React__default["default"].createElement("div", { "data-testid": "text-field-error", key: (_a = issue.details) === null || _a === void 0 ? void 0 : _a.text }, (_b = issue.details) === null || _b === void 0 ? void 0 : _b.text));
5029
+ }))),
5030
+ googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
5031
+ React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
5032
+ React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => __awaiter(this, void 0, void 0, function* () {
5033
+ try {
5034
+ const loginRequest = {
5035
+ googleClientId: response.clientId,
5036
+ googleCredential: response.credential,
5037
+ };
5038
+ const userLogin = yield medplum.startGoogleLogin(loginRequest);
5039
+ const googleClaims = core.parseJWTPayload(loginRequest.googleCredential);
5040
+ const registerRequest = {
5041
+ firstName: googleClaims.given_name,
5042
+ lastName: googleClaims.family_name,
5043
+ email: googleClaims.email,
5044
+ };
5045
+ handleAuthResponse(registerRequest, userLogin);
5046
+ }
5047
+ catch (err) {
5048
+ setOutcome(err);
5049
+ }
5050
+ }) })),
5051
+ React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
5052
+ React__default["default"].createElement(FormSection, { title: "First Name", htmlFor: "firstName", outcome: outcome },
5053
+ React__default["default"].createElement(Input, { name: "firstName", type: "text", testid: "firstName", placeholder: "First name", required: true, autoFocus: true, outcome: outcome })),
5054
+ React__default["default"].createElement(FormSection, { title: "Last Name", htmlFor: "lastName", outcome: outcome },
5055
+ React__default["default"].createElement(Input, { name: "lastName", type: "text", testid: "lastName", placeholder: "Last name", required: true, outcome: outcome })),
5056
+ props.type === 'project' && (React__default["default"].createElement(FormSection, { title: "Project Name", htmlFor: "projectName", outcome: outcome },
5057
+ React__default["default"].createElement(Input, { name: "projectName", type: "text", testid: "projectName", placeholder: "My Project", required: true, outcome: outcome }))),
5058
+ React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
5059
+ React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", placeholder: "name@domain.com", required: true, outcome: outcome })),
5060
+ React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
5061
+ React__default["default"].createElement(Input, { name: "password", type: "password", testid: "password", autoComplete: "off", required: true, outcome: outcome })),
5062
+ React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
5063
+ "By clicking submit you agree to the Medplum ",
5064
+ React__default["default"].createElement("a", { href: "https://www.medplum.com/privacy" }, "Privacy\u00A0Policy"),
5065
+ ' and ',
5066
+ React__default["default"].createElement("a", { href: "https://www.medplum.com/terms" }, "Terms\u00A0of\u00A0Service"),
5067
+ "."),
5068
+ React__default["default"].createElement("p", { style: { fontSize: '12px', color: '#888' } },
5069
+ "This site is protected by reCAPTCHA and the Google",
5070
+ ' ',
5071
+ React__default["default"].createElement("a", { href: "https://policies.google.com/privacy" }, "Privacy\u00A0Policy"),
5072
+ ' and ',
5073
+ React__default["default"].createElement("a", { href: "https://policies.google.com/terms" }, "Terms\u00A0of\u00A0Service"),
5074
+ " apply."),
5075
+ React__default["default"].createElement("div", { className: "medplum-signin-buttons" },
5076
+ React__default["default"].createElement("div", null,
5077
+ React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
5078
+ React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
5079
+ React__default["default"].createElement("div", null,
5080
+ React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Create account"))))));
5081
+ }
5082
+
4907
5083
  function StatusBadge(props) {
4908
5084
  return React__default["default"].createElement("span", { className: `medplum-status medplum-status-${props.status}` }, props.status);
4909
5085
  }
@@ -5271,6 +5447,165 @@
5271
5447
  return `/${resource.resourceType}/${resource.id}/_history/${(_a = resource.meta) === null || _a === void 0 ? void 0 : _a.versionId}`;
5272
5448
  }
5273
5449
 
5450
+ /**
5451
+ * Returns a month display string (e.g. "January 2020").
5452
+ * @param date Any date within the month.
5453
+ * @returns The month display string (e.g. "January 2020")
5454
+ */
5455
+ function getMonthString(date) {
5456
+ return date.toLocaleString('default', { month: 'long' }) + ' ' + date.getFullYear();
5457
+ }
5458
+ function CalendarInput(props) {
5459
+ const [month, setMonth] = React.useState(getStartMonth);
5460
+ function moveMonth(delta) {
5461
+ setMonth((currMonth) => {
5462
+ const prevMonth = new Date(currMonth.getTime());
5463
+ prevMonth.setMonth(currMonth.getMonth() + delta);
5464
+ return prevMonth;
5465
+ });
5466
+ }
5467
+ const grid = React.useMemo(() => buildGrid(month, props.slots), [month, props.slots]);
5468
+ return (React__default["default"].createElement("div", null,
5469
+ React__default["default"].createElement(InputRow, null,
5470
+ React__default["default"].createElement("p", { style: { flex: 1 } }, getMonthString(month)),
5471
+ React__default["default"].createElement("p", null,
5472
+ React__default["default"].createElement(Button, { label: "Previous month", onClick: () => moveMonth(-1) }, "<"),
5473
+ React__default["default"].createElement(Button, { label: "Next month", onClick: () => moveMonth(1) }, ">"))),
5474
+ React__default["default"].createElement("table", { className: "medplum-calendar-table" },
5475
+ React__default["default"].createElement("thead", null,
5476
+ React__default["default"].createElement("tr", null,
5477
+ React__default["default"].createElement("th", null, "SUN"),
5478
+ React__default["default"].createElement("th", null, "MON"),
5479
+ React__default["default"].createElement("th", null, "TUE"),
5480
+ React__default["default"].createElement("th", null, "WED"),
5481
+ React__default["default"].createElement("th", null, "THU"),
5482
+ React__default["default"].createElement("th", null, "FRI"),
5483
+ React__default["default"].createElement("th", null, "SAT"))),
5484
+ React__default["default"].createElement("tbody", null, grid.map((week, weekIndex) => (React__default["default"].createElement("tr", { key: 'week-' + weekIndex }, week.map((day, dayIndex) => (React__default["default"].createElement("td", { key: 'day-' + dayIndex }, day && (React__default["default"].createElement("button", { disabled: !day.available, onClick: () => props.onClick(day.date) }, day.date.getDate()))))))))))));
5485
+ }
5486
+ function getStartMonth() {
5487
+ const result = new Date();
5488
+ result.setDate(1);
5489
+ result.setHours(0, 0, 0, 0);
5490
+ return result;
5491
+ }
5492
+ function buildGrid(startDate, slots) {
5493
+ const d = new Date(startDate.getFullYear(), startDate.getMonth());
5494
+ const grid = [];
5495
+ let row = [];
5496
+ // Fill leading empty days
5497
+ for (let i = 0; i < d.getDay(); i++) {
5498
+ row.push(undefined);
5499
+ }
5500
+ while (d.getMonth() === startDate.getMonth()) {
5501
+ row.push({
5502
+ date: new Date(d.getTime()),
5503
+ // available: isAvailable(d),
5504
+ available: isDayAvailable(d, slots),
5505
+ });
5506
+ if (d.getDay() === 6) {
5507
+ grid.push(row);
5508
+ row = [];
5509
+ }
5510
+ d.setDate(d.getDate() + 1);
5511
+ }
5512
+ // Fill trailing empty days
5513
+ if (d.getDay() !== 0) {
5514
+ for (let i = d.getDay(); i < 7; i++) {
5515
+ row.push(undefined);
5516
+ }
5517
+ grid.push(row);
5518
+ }
5519
+ return grid;
5520
+ }
5521
+ /**
5522
+ * Returns true if the given date is available for booking.
5523
+ * @param day The day to check.
5524
+ * @param slots The list of available slots.
5525
+ * @returns True if there are any available slots for the day.
5526
+ */
5527
+ function isDayAvailable(day, slots) {
5528
+ // Note that slot start and end time may or may not be in UTC.
5529
+ for (const slot of slots) {
5530
+ const slotStart = new Date(slot.start);
5531
+ if (slotStart.getFullYear() === day.getFullYear() &&
5532
+ slotStart.getMonth() === day.getMonth() &&
5533
+ slotStart.getDate() === day.getDate()) {
5534
+ return true;
5535
+ }
5536
+ }
5537
+ return false;
5538
+ }
5539
+
5540
+ function Scheduler(props) {
5541
+ var _a;
5542
+ const medplum = useMedplum();
5543
+ const schedule = useResource(props.schedule);
5544
+ const [slots, setSlots] = React.useState();
5545
+ const slotsRef = React.useRef();
5546
+ slotsRef.current = slots;
5547
+ const [date, setDate] = React.useState();
5548
+ const [slot, setSlot] = React.useState();
5549
+ const [info, setInfo] = React.useState();
5550
+ const [form, setForm] = React.useState();
5551
+ React.useEffect(() => {
5552
+ if (schedule) {
5553
+ medplum.search('Slot', 'schedule=' + core.getReferenceString(schedule)).then((bundle) => {
5554
+ setSlots(bundle.entry.map((entry) => entry.resource));
5555
+ });
5556
+ }
5557
+ else {
5558
+ setSlots(undefined);
5559
+ }
5560
+ }, [medplum, schedule]);
5561
+ if (!schedule || !slots) {
5562
+ return null;
5563
+ }
5564
+ const actor = (_a = schedule.actor) === null || _a === void 0 ? void 0 : _a[0];
5565
+ return (React__default["default"].createElement("div", { className: "medplum-calendar-container", "data-testid": "scheduler" },
5566
+ React__default["default"].createElement("div", { className: "medplum-calendar-info-pane" },
5567
+ actor && React__default["default"].createElement(Avatar, { value: actor, size: "large" }),
5568
+ actor && (React__default["default"].createElement("h1", null,
5569
+ React__default["default"].createElement(ResourceName, { value: actor }))),
5570
+ React__default["default"].createElement("p", null, "1 hour"),
5571
+ date && React__default["default"].createElement("p", null, date.toLocaleDateString()),
5572
+ slot && React__default["default"].createElement("p", null, formatTime(new Date(slot.start)))),
5573
+ React__default["default"].createElement("div", { className: "medplum-calendar-selection-pane" },
5574
+ !date && (React__default["default"].createElement("div", null,
5575
+ React__default["default"].createElement("h3", null, "Select date"),
5576
+ React__default["default"].createElement(CalendarInput, { slots: slots, onClick: setDate }))),
5577
+ date && !slot && (React__default["default"].createElement("div", null,
5578
+ React__default["default"].createElement("h3", null, "Select time"),
5579
+ slots.map((s) => {
5580
+ const slotStart = new Date(s.start);
5581
+ return (slotStart.getTime() > date.getTime() &&
5582
+ slotStart.getTime() < date.getTime() + 24 * 3600 * 1000 && (React__default["default"].createElement("div", { key: s.id },
5583
+ React__default["default"].createElement(Button, { style: { width: 150 }, onClick: () => setSlot(s) }, formatTime(slotStart)))));
5584
+ }))),
5585
+ date && slot && !info && (React__default["default"].createElement("div", null,
5586
+ React__default["default"].createElement("h3", null, "Enter your info"),
5587
+ React__default["default"].createElement(FormSection, { title: "Name", htmlFor: "name" },
5588
+ React__default["default"].createElement(Input, { name: "name" })),
5589
+ React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email" },
5590
+ React__default["default"].createElement(Input, { name: "email" })),
5591
+ React__default["default"].createElement(Button, { primary: true, onClick: () => setInfo('info') }, "Next"))),
5592
+ date && slot && info && !form && (React__default["default"].createElement("div", null,
5593
+ React__default["default"].createElement("h3", null, "Custom questions"),
5594
+ React__default["default"].createElement(FormSection, { title: "Question 1", htmlFor: "q1" },
5595
+ React__default["default"].createElement(Input, { name: "q1" })),
5596
+ React__default["default"].createElement(FormSection, { title: "Question 2", htmlFor: "q2" },
5597
+ React__default["default"].createElement(Input, { name: "email" })),
5598
+ React__default["default"].createElement(FormSection, { title: "Question 3", htmlFor: "q3" },
5599
+ React__default["default"].createElement(Input, { name: "email" })),
5600
+ React__default["default"].createElement(Button, { primary: true, onClick: () => setForm('form') }, "Next"))),
5601
+ date && slot && info && form && (React__default["default"].createElement("div", null,
5602
+ React__default["default"].createElement("h3", null, "You're all set!"),
5603
+ React__default["default"].createElement("p", null, "Check your email for a calendar invite."))))));
5604
+ }
5605
+ function formatTime(date) {
5606
+ return date.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' });
5607
+ }
5608
+
5274
5609
  function ServiceRequestTimeline(props) {
5275
5610
  return (React__default["default"].createElement(ResourceTimeline, { value: props.serviceRequest, buildSearchRequests: (resource) => ({
5276
5611
  resourceType: 'Bundle',
@@ -5318,62 +5653,6 @@
5318
5653
  }) }));
5319
5654
  }
5320
5655
 
5321
- /**
5322
- * Dynamically creates a script tag for the specified JavaScript file.
5323
- * @param src The JavaScript file URL.
5324
- */
5325
- function createScriptTag(src, onload) {
5326
- const head = document.getElementsByTagName('head')[0];
5327
- const script = document.createElement('script');
5328
- script.async = true;
5329
- script.src = src;
5330
- script.onload = onload || null;
5331
- head.appendChild(script);
5332
- }
5333
-
5334
- function GoogleButton(props) {
5335
- const medplum = useMedplum();
5336
- const { handleGoogleCredential } = props;
5337
- const googleClientId = getGoogleClientId(props.googleClientId);
5338
- const parentRef = React.useRef(null);
5339
- const [scriptLoaded, setScriptLoaded] = React.useState(typeof google !== 'undefined');
5340
- const [initialized, setInitialized] = React.useState(false);
5341
- const [buttonRendered, setButtonRendered] = React.useState(false);
5342
- React.useEffect(() => {
5343
- if (typeof google === 'undefined') {
5344
- createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));
5345
- return;
5346
- }
5347
- if (!initialized) {
5348
- google.accounts.id.initialize({
5349
- client_id: googleClientId,
5350
- callback: handleGoogleCredential,
5351
- });
5352
- setInitialized(true);
5353
- }
5354
- if (parentRef.current && !buttonRendered) {
5355
- google.accounts.id.renderButton(parentRef.current, {});
5356
- setButtonRendered(true);
5357
- }
5358
- }, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);
5359
- if (!googleClientId) {
5360
- return null;
5361
- }
5362
- return React__default["default"].createElement("div", { ref: parentRef });
5363
- }
5364
- function getGoogleClientId(clientId) {
5365
- var _a, _b;
5366
- if (clientId) {
5367
- return clientId;
5368
- }
5369
- const origin = window.location.protocol + '//' + window.location.host;
5370
- const authorizedOrigins = (_b = (_a = "http://localhost:3000,http://localhost:6006,https://app.medplum.com,https://docs.medplum.com") === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : [];
5371
- if (authorizedOrigins.includes(origin)) {
5372
- return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
5373
- }
5374
- return undefined;
5375
- }
5376
-
5377
5656
  function SignInForm(props) {
5378
5657
  const medplum = useMedplum();
5379
5658
  const [login, setLogin] = React.useState(undefined);
@@ -5415,6 +5694,7 @@
5415
5694
  }
5416
5695
  function AuthenticationForm(props) {
5417
5696
  const medplum = useMedplum();
5697
+ const googleClientId = getGoogleClientId(props.googleClientId);
5418
5698
  const [outcome, setOutcome] = React.useState();
5419
5699
  const issues = getIssuesForExpression(outcome, undefined);
5420
5700
  return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
@@ -5435,6 +5715,21 @@
5435
5715
  var _a, _b;
5436
5716
  return (React__default["default"].createElement("div", { "data-testid": "text-field-error", key: (_a = issue.details) === null || _a === void 0 ? void 0 : _a.text }, (_b = issue.details) === null || _b === void 0 ? void 0 : _b.text));
5437
5717
  }))),
5718
+ googleClientId && (React__default["default"].createElement(React__default["default"].Fragment, null,
5719
+ React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
5720
+ React__default["default"].createElement(GoogleButton, { googleClientId: googleClientId, handleGoogleCredential: (response) => {
5721
+ medplum
5722
+ .startGoogleLogin({
5723
+ clientId: props.clientId,
5724
+ scope: props.scope,
5725
+ nonce: props.nonce,
5726
+ googleClientId: response.clientId,
5727
+ googleCredential: response.credential,
5728
+ })
5729
+ .then(props.handleAuthResponse)
5730
+ .catch(setOutcome);
5731
+ } })),
5732
+ React__default["default"].createElement("div", { className: "medplum-signin-separator" }, "or"))),
5438
5733
  React__default["default"].createElement(FormSection, { title: "Email", htmlFor: "email", outcome: outcome },
5439
5734
  React__default["default"].createElement(Input, { name: "email", type: "email", testid: "email", required: true, autoFocus: true, outcome: outcome })),
5440
5735
  React__default["default"].createElement(FormSection, { title: "Password", htmlFor: "password", outcome: outcome },
@@ -5447,20 +5742,7 @@
5447
5742
  React__default["default"].createElement("input", { type: "checkbox", id: "remember", name: "remember", value: "true" }),
5448
5743
  React__default["default"].createElement("label", { htmlFor: "remember" }, "Remember me")),
5449
5744
  React__default["default"].createElement("div", null,
5450
- React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in"))),
5451
- React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
5452
- React__default["default"].createElement(GoogleButton, { googleClientId: props.googleClientId, handleGoogleCredential: (response) => {
5453
- medplum
5454
- .startGoogleLogin({
5455
- clientId: props.clientId,
5456
- scope: props.scope,
5457
- nonce: props.nonce,
5458
- googleClientId: response.clientId,
5459
- googleCredential: response.credential,
5460
- })
5461
- .then(props.handleAuthResponse)
5462
- .catch(setOutcome);
5463
- } }))));
5745
+ React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in")))));
5464
5746
  }
5465
5747
  function ProfileForm(props) {
5466
5748
  const medplum = useMedplum();
@@ -5585,6 +5867,7 @@
5585
5867
  exports.RangeDisplay = RangeDisplay;
5586
5868
  exports.RangeInput = RangeInput;
5587
5869
  exports.ReferenceInput = ReferenceInput;
5870
+ exports.RegisterForm = RegisterForm;
5588
5871
  exports.RequestGroupDisplay = RequestGroupDisplay;
5589
5872
  exports.ResourceArrayDisplay = ResourceArrayDisplay;
5590
5873
  exports.ResourceArrayInput = ResourceArrayInput;
@@ -5599,6 +5882,7 @@
5599
5882
  exports.ResourcePropertyInput = ResourcePropertyInput;
5600
5883
  exports.ResourceTable = ResourceTable;
5601
5884
  exports.ResourceTimeline = ResourceTimeline;
5885
+ exports.Scheduler = Scheduler;
5602
5886
  exports.Scrollable = Scrollable;
5603
5887
  exports.SearchChangeEvent = SearchChangeEvent;
5604
5888
  exports.SearchClickEvent = SearchClickEvent;
@@ -5642,11 +5926,13 @@
5642
5926
  exports.deleteFilter = deleteFilter;
5643
5927
  exports.formatRangeString = formatRangeString;
5644
5928
  exports.getOpString = getOpString;
5929
+ exports.getRecaptcha = getRecaptcha;
5645
5930
  exports.getSearchOperators = getSearchOperators;
5646
5931
  exports.getSortField = getSortField;
5647
5932
  exports.getTimeString = getTimeString;
5648
5933
  exports.getValueAndType = getValueAndType;
5649
5934
  exports.hasFilterOnField = hasFilterOnField;
5935
+ exports.initRecaptcha = initRecaptcha;
5650
5936
  exports.isChoiceQuestion = isChoiceQuestion;
5651
5937
  exports.isSortDescending = isSortDescending;
5652
5938
  exports.movePage = movePage;