@medplum/react 0.9.17 → 0.9.20

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
@@ -22,10 +22,10 @@
22
22
  }
23
23
 
24
24
  function Input(props) {
25
- const className = 'medplum-input'; // + (props.size ? ' ' + props.size : '');
25
+ const className = 'medplum-input';
26
26
  const issues = getIssuesForExpression(props.outcome, props.name);
27
27
  const invalid = issues && issues.length > 0;
28
- return (React__default["default"].createElement("input", { id: props.name, name: props.name, type: getInputType(props.type), size: props.size, step: props.step, className: className, defaultValue: props.defaultValue || '', required: props.required, autoCapitalize: props.autoCapitalize, autoComplete: props.autoComplete, autoFocus: props.autoFocus, ref: props.inputRef, "aria-invalid": invalid, "aria-describedby": invalid ? props.name + '-errors' : '', placeholder: props.placeholder, "data-testid": props.testid, disabled: props.disabled, onChange: (e) => {
28
+ return (React__default["default"].createElement("input", { id: props.name, name: props.name, type: getInputType(props.type), size: props.size, step: props.step, className: className, style: props.style, defaultValue: props.defaultValue || '', required: props.required, autoCapitalize: props.autoCapitalize, autoComplete: props.autoComplete, autoFocus: props.autoFocus, ref: props.inputRef, "aria-invalid": invalid, "aria-describedby": invalid ? props.name + '-errors' : '', placeholder: props.placeholder, "data-testid": props.testid, disabled: props.disabled, onChange: (e) => {
29
29
  if (props.onChange) {
30
30
  props.onChange(e.currentTarget.value);
31
31
  }
@@ -287,7 +287,7 @@
287
287
  props.onChange(newValues);
288
288
  }
289
289
  }
290
- return (React__default["default"].createElement("table", null,
290
+ return (React__default["default"].createElement("table", { style: { width: '100%' } },
291
291
  React__default["default"].createElement("colgroup", null,
292
292
  React__default["default"].createElement("col", { width: "90%" }),
293
293
  React__default["default"].createElement("col", { width: "10%" })),
@@ -621,6 +621,9 @@
621
621
  else if ('reference' in props.to) {
622
622
  href = `/${props.to.reference}`;
623
623
  }
624
+ if (props.suffix) {
625
+ href += '/' + props.suffix;
626
+ }
624
627
  }
625
628
  return (React__default["default"].createElement("a", { href: href, id: props.id, "aria-label": props.label, "data-testid": props.testid || 'link', className: props.className, onClick: (e) => {
626
629
  killEvent(e);
@@ -710,6 +713,14 @@
710
713
  .join('');
711
714
  }
712
715
 
716
+ function CheckboxFormSection(props) {
717
+ return (React__default["default"].createElement("div", { className: "medplum-checkbox-form-section" },
718
+ React__default["default"].createElement("div", { className: "medplum-checkbox-form-section-checkbox-container" }, props.children),
719
+ React__default["default"].createElement("div", { className: "medplum-checkbox-form-section-details-container" },
720
+ React__default["default"].createElement("label", { htmlFor: props.htmlFor }, props.title),
721
+ React__default["default"].createElement("p", null, props.description))));
722
+ }
723
+
713
724
  const DEFAULT_IGNORED_PROPERTIES = [
714
725
  'meta',
715
726
  'implicitRules',
@@ -723,9 +734,9 @@
723
734
  function FormSection(props) {
724
735
  const issues = getIssuesForExpression(props.outcome, props.htmlFor);
725
736
  const invalid = issues && issues.length > 0;
726
- return (React__default["default"].createElement("fieldset", null,
737
+ return (React__default["default"].createElement("fieldset", { className: "medplum-form-section" },
727
738
  props.title && React__default["default"].createElement("label", { htmlFor: props.htmlFor }, props.title),
728
- props.description && React__default["default"].createElement("small", null, props.description),
739
+ props.description && React__default["default"].createElement("p", null, props.description),
729
740
  props.children,
730
741
  invalid && (React__default["default"].createElement("div", { id: props.htmlFor + '-errors', className: "medplum-input-error" }, issues === null || issues === void 0 ? void 0 : issues.map((issue) => {
731
742
  var _a, _b;
@@ -733,6 +744,50 @@
733
744
  })))));
734
745
  }
735
746
 
747
+ function ResourceForm(props) {
748
+ const medplum = useMedplum();
749
+ const defaultValue = useResource(props.defaultValue);
750
+ const [schema, setSchema] = React.useState();
751
+ const [value, setValue] = React.useState();
752
+ React.useEffect(() => {
753
+ if (defaultValue) {
754
+ setValue(JSON.parse(JSON.stringify(defaultValue)));
755
+ medplum.requestSchema(defaultValue.resourceType).then(setSchema);
756
+ }
757
+ }, [medplum, defaultValue]);
758
+ if (!schema || !value) {
759
+ return React__default["default"].createElement("div", null, "Loading...");
760
+ }
761
+ return (React__default["default"].createElement("form", { noValidate: true, autoComplete: "off", onSubmit: (e) => {
762
+ e.preventDefault();
763
+ if (props.onSubmit) {
764
+ props.onSubmit(value);
765
+ }
766
+ } },
767
+ React__default["default"].createElement(FormSection, { title: "Resource Type" },
768
+ React__default["default"].createElement(Input, { name: "resourceType", defaultValue: value.resourceType, disabled: true })),
769
+ React__default["default"].createElement(FormSection, { title: "ID" },
770
+ React__default["default"].createElement(Input, { name: "id", defaultValue: value.id, disabled: true })),
771
+ React__default["default"].createElement(BackboneElementInput, { typeName: value.resourceType, defaultValue: value, outcome: props.outcome, onChange: setValue }),
772
+ React__default["default"].createElement(Button, { type: "submit", size: "large" }, "OK"),
773
+ props.onDelete && (React__default["default"].createElement(Button, { type: "button", size: "large", onClick: () => {
774
+ props.onDelete(value);
775
+ } }, "Delete"))));
776
+ }
777
+ function setPropertyValue(obj, key, propName, elementDefinition, value) {
778
+ const types = elementDefinition.type;
779
+ if (types.length > 1) {
780
+ for (const type of types) {
781
+ const compoundKey = key.replace('[x]', core.capitalize(type.code));
782
+ if (compoundKey in obj) {
783
+ delete obj[compoundKey];
784
+ }
785
+ }
786
+ }
787
+ obj[propName] = value;
788
+ return obj;
789
+ }
790
+
736
791
  function DescriptionList(props) {
737
792
  return React__default["default"].createElement("dl", { className: 'medplum-description-list' + (props.compact ? ' compact' : '') }, props.children);
738
793
  }
@@ -821,6 +876,18 @@
821
876
  return React__default["default"].createElement(React__default["default"].Fragment, null, builder.join('').trim());
822
877
  }
823
878
 
879
+ function ContactDetailDisplay(props) {
880
+ var _a;
881
+ const contactDetail = props.value;
882
+ if (!contactDetail) {
883
+ return null;
884
+ }
885
+ return (React__default["default"].createElement(React__default["default"].Fragment, null,
886
+ contactDetail.name,
887
+ contactDetail.name && ': ', (_a = contactDetail.telecom) === null || _a === void 0 ? void 0 :
888
+ _a.map((telecom, index) => (React__default["default"].createElement(ContactPointDisplay, { key: 'telecom-' + index, value: telecom })))));
889
+ }
890
+
824
891
  function DateTimeDisplay(props) {
825
892
  if (!props.value) {
826
893
  return null;
@@ -969,6 +1036,8 @@
969
1036
  return React__default["default"].createElement(CodeableConceptDisplay, { value: value });
970
1037
  case core.PropertyType.Coding:
971
1038
  return React__default["default"].createElement(CodingDisplay, { value: value });
1039
+ case core.PropertyType.ContactDetail:
1040
+ return React__default["default"].createElement(ContactDetailDisplay, { value: value });
972
1041
  case core.PropertyType.ContactPoint:
973
1042
  return React__default["default"].createElement(ContactPointDisplay, { value: value });
974
1043
  case core.PropertyType.HumanName:
@@ -1034,6 +1103,15 @@
1034
1103
  return (React__default["default"].createElement(Input, { name: props.name, type: "text", placeholder: "Annotation text", defaultValue: value.text, onChange: setText }));
1035
1104
  }
1036
1105
 
1106
+ function Checkbox(props) {
1107
+ const className = 'medplum-checkbox';
1108
+ return (React__default["default"].createElement("input", { id: props.name, name: props.name, className: className, type: "checkbox", value: "true", defaultChecked: !!props.defaultValue, required: props.required, ref: props.inputRef, "data-testid": props.testid, disabled: props.disabled, onChange: (e) => {
1109
+ if (props.onChange) {
1110
+ props.onChange(e.currentTarget.checked);
1111
+ }
1112
+ } }));
1113
+ }
1114
+
1037
1115
  function CodeableConceptInput(props) {
1038
1116
  const medplum = useMedplum();
1039
1117
  let defaultValue = undefined;
@@ -1129,19 +1207,34 @@
1129
1207
  const ref = React.useRef();
1130
1208
  ref.current = contactPoint;
1131
1209
  function setContactPointWrapper(newValue) {
1210
+ if (newValue && Object.keys(newValue).length === 0) {
1211
+ newValue = undefined;
1212
+ }
1132
1213
  setContactPoint(newValue);
1133
1214
  if (props.onChange) {
1134
1215
  props.onChange(newValue);
1135
1216
  }
1136
1217
  }
1137
1218
  function setSystem(system) {
1138
- setContactPointWrapper(Object.assign(Object.assign({}, ref.current), { system: system ? system : undefined }));
1219
+ const newValue = Object.assign(Object.assign({}, ref.current), { system });
1220
+ if (!system) {
1221
+ delete newValue.system;
1222
+ }
1223
+ setContactPointWrapper(newValue);
1139
1224
  }
1140
1225
  function setUse(use) {
1141
- setContactPointWrapper(Object.assign(Object.assign({}, ref.current), { use: use ? use : undefined }));
1226
+ const newValue = Object.assign(Object.assign({}, ref.current), { use });
1227
+ if (!use) {
1228
+ delete newValue.use;
1229
+ }
1230
+ setContactPointWrapper(newValue);
1142
1231
  }
1143
1232
  function setValue(value) {
1144
- setContactPointWrapper(Object.assign(Object.assign({}, ref.current), { value: value ? value : undefined }));
1233
+ const newValue = Object.assign(Object.assign({}, ref.current), { value });
1234
+ if (!value) {
1235
+ delete newValue.value;
1236
+ }
1237
+ setContactPointWrapper(newValue);
1145
1238
  }
1146
1239
  return (React__default["default"].createElement(InputRow, null,
1147
1240
  React__default["default"].createElement(Select, { defaultValue: contactPoint === null || contactPoint === void 0 ? void 0 : contactPoint.system, onChange: setSystem, testid: "system" },
@@ -1162,6 +1255,36 @@
1162
1255
  React__default["default"].createElement(Input, { placeholder: "Value", defaultValue: contactPoint === null || contactPoint === void 0 ? void 0 : contactPoint.value, onChange: setValue })));
1163
1256
  }
1164
1257
 
1258
+ function ContactDetailInput(props) {
1259
+ var _a;
1260
+ const [contactPoint, setContactDetail] = React.useState(props.defaultValue);
1261
+ const ref = React.useRef();
1262
+ ref.current = contactPoint;
1263
+ function setContactDetailWrapper(newValue) {
1264
+ setContactDetail(newValue);
1265
+ if (props.onChange) {
1266
+ props.onChange(newValue);
1267
+ }
1268
+ }
1269
+ function setName(name) {
1270
+ const newValue = Object.assign(Object.assign({}, ref.current), { name });
1271
+ if (!name) {
1272
+ delete newValue.name;
1273
+ }
1274
+ setContactDetailWrapper(newValue);
1275
+ }
1276
+ function setTelecom(telecom) {
1277
+ const newValue = Object.assign(Object.assign({}, ref.current), { telecom: telecom && [telecom] });
1278
+ if (!telecom) {
1279
+ delete newValue.telecom;
1280
+ }
1281
+ setContactDetailWrapper(newValue);
1282
+ }
1283
+ return (React__default["default"].createElement(InputRow, null,
1284
+ React__default["default"].createElement(Input, { name: props.name + '-name', placeholder: "Name", style: { width: 180 }, defaultValue: contactPoint === null || contactPoint === void 0 ? void 0 : contactPoint.name, onChange: setName }),
1285
+ React__default["default"].createElement(ContactPointInput, { name: props.name + '-telecom', defaultValue: (_a = contactPoint === null || contactPoint === void 0 ? void 0 : contactPoint.telecom) === null || _a === void 0 ? void 0 : _a[0], onChange: setTelecom })));
1286
+ }
1287
+
1165
1288
  /**
1166
1289
  * The DateTimeInput component is a wrapper around the HTML5 input type="datetime-local".
1167
1290
  * The main purpose is to reconcile time zones.
@@ -1220,7 +1343,7 @@
1220
1343
  }
1221
1344
 
1222
1345
  function TextArea(props) {
1223
- const className = 'medplum-textarea';
1346
+ const className = 'medplum-textarea' + (props.monospace ? ' monospace' : '');
1224
1347
  const issues = getIssuesForExpression(props.outcome, props.name);
1225
1348
  const invalid = issues && issues.length > 0;
1226
1349
  return (React__default["default"].createElement("textarea", { id: props.name, name: props.name, className: className, defaultValue: props.defaultValue || '', required: props.required, autoComplete: props.autoComplete, autoFocus: props.autoFocus, ref: props.inputRef, "aria-invalid": invalid, "aria-describedby": invalid ? props.name + '-errors' : '', placeholder: props.placeholder, "data-testid": props.testid, style: props.style, onChange: (e) => {
@@ -1231,7 +1354,7 @@
1231
1354
  }
1232
1355
 
1233
1356
  function ExtensionInput(props) {
1234
- return (React__default["default"].createElement(TextArea, { testid: "extension-input", name: props.name, defaultValue: core.stringify(props.defaultValue), onChange: (newValue) => {
1357
+ return (React__default["default"].createElement(TextArea, { testid: "extension-input", name: props.name, defaultValue: core.stringify(props.defaultValue), monospace: true, onChange: (newValue) => {
1235
1358
  if (props.onChange) {
1236
1359
  props.onChange(JSON.parse(newValue));
1237
1360
  }
@@ -1396,7 +1519,7 @@
1396
1519
  }
1397
1520
  return (React__default["default"].createElement(Autocomplete, { loadOptions: (input) => {
1398
1521
  return medplum
1399
- .search(resourceTypeRef.current, 'name=' + encodeURIComponent(input))
1522
+ .search(resourceTypeRef.current, 'name=' + encodeURIComponent(input) + '&_count=10')
1400
1523
  .then((bundle) => bundle.entry.map((entry) => entry.resource));
1401
1524
  }, getId: (item) => {
1402
1525
  return item.id;
@@ -1454,35 +1577,34 @@
1454
1577
  props.onChange(newValues);
1455
1578
  }
1456
1579
  }
1457
- return (React__default["default"].createElement("div", null,
1458
- React__default["default"].createElement("table", { style: { width: '100%' } },
1459
- React__default["default"].createElement("colgroup", null,
1460
- React__default["default"].createElement("col", { width: "90%" }),
1461
- React__default["default"].createElement("col", { width: "10%" })),
1462
- React__default["default"].createElement("tbody", null,
1463
- values.map((v, index) => (React__default["default"].createElement("tr", { key: `${index}-${values.length}` },
1464
- React__default["default"].createElement("td", null,
1465
- React__default["default"].createElement(ResourcePropertyInput, { arrayElement: true, property: props.property, name: props.name + '.' + index, defaultValue: v, onChange: (newValue) => {
1466
- const copy = [...valuesRef.current];
1467
- copy[index] = newValue;
1468
- setValuesWrapper(copy);
1469
- } })),
1470
- React__default["default"].createElement("td", { style: { textAlign: 'right' } },
1471
- React__default["default"].createElement(Button, { onClick: (e) => {
1472
- killEvent(e);
1473
- const copy = [...valuesRef.current];
1474
- copy.splice(index, 1);
1475
- setValuesWrapper(copy);
1476
- } }, "Remove"))))),
1477
- React__default["default"].createElement("tr", null,
1478
- React__default["default"].createElement("td", null),
1479
- React__default["default"].createElement("td", { style: { textAlign: 'right' } },
1480
- React__default["default"].createElement(Button, { onClick: (e) => {
1481
- killEvent(e);
1482
- const copy = [...valuesRef.current];
1483
- copy.push(undefined);
1484
- setValuesWrapper(copy);
1485
- } }, "Add")))))));
1580
+ return (React__default["default"].createElement("table", { style: { width: '100%', borderCollapse: 'collapse' } },
1581
+ React__default["default"].createElement("colgroup", null,
1582
+ React__default["default"].createElement("col", { width: "90%" }),
1583
+ React__default["default"].createElement("col", { width: "10%" })),
1584
+ React__default["default"].createElement("tbody", null,
1585
+ values.map((v, index) => (React__default["default"].createElement("tr", { key: `${index}-${values.length}` },
1586
+ React__default["default"].createElement("td", null,
1587
+ React__default["default"].createElement(ResourcePropertyInput, { arrayElement: true, property: props.property, name: props.name + '.' + index, defaultValue: v, onChange: (newValue) => {
1588
+ const copy = [...valuesRef.current];
1589
+ copy[index] = newValue;
1590
+ setValuesWrapper(copy);
1591
+ } })),
1592
+ React__default["default"].createElement("td", { style: { textAlign: 'right' } },
1593
+ React__default["default"].createElement(Button, { onClick: (e) => {
1594
+ killEvent(e);
1595
+ const copy = [...valuesRef.current];
1596
+ copy.splice(index, 1);
1597
+ setValuesWrapper(copy);
1598
+ } }, "Remove"))))),
1599
+ React__default["default"].createElement("tr", null,
1600
+ React__default["default"].createElement("td", null),
1601
+ React__default["default"].createElement("td", { style: { textAlign: 'right' } },
1602
+ React__default["default"].createElement(Button, { onClick: (e) => {
1603
+ killEvent(e);
1604
+ const copy = [...valuesRef.current];
1605
+ copy.push(undefined);
1606
+ setValuesWrapper(copy);
1607
+ } }, "Add"))))));
1486
1608
  }
1487
1609
 
1488
1610
  function ResourcePropertyInput(props) {
@@ -1526,6 +1648,7 @@
1526
1648
  } }))));
1527
1649
  }
1528
1650
  function ElementDefinitionTypeInput(props) {
1651
+ var _a;
1529
1652
  const property = props.property;
1530
1653
  const propertyType = props.elementDefinitionType.code;
1531
1654
  const name = props.name;
@@ -1557,7 +1680,11 @@
1557
1680
  case core.PropertyType.code:
1558
1681
  return React__default["default"].createElement(CodeInput, { property: property, name: name, defaultValue: value, onChange: props.onChange });
1559
1682
  case core.PropertyType.boolean:
1560
- return (React__default["default"].createElement("input", { type: "checkbox", name: name, "data-testid": name, defaultChecked: !!value, value: "true", onChange: (e) => props.onChange && props.onChange(e.target.value === 'true') }));
1683
+ return (React__default["default"].createElement(Checkbox, { name: name, testid: name, defaultValue: !!value, onChange: (newValue) => {
1684
+ if (props.onChange) {
1685
+ props.onChange(newValue);
1686
+ }
1687
+ } }));
1561
1688
  case core.PropertyType.markdown:
1562
1689
  return React__default["default"].createElement(TextArea, { name: name, testid: name, defaultValue: value, onChange: props.onChange });
1563
1690
  // 2.24.0.2 Complex Types
@@ -1572,6 +1699,8 @@
1572
1699
  return React__default["default"].createElement(CodeableConceptInput, { property: property, name: name, defaultValue: value, onChange: props.onChange });
1573
1700
  case core.PropertyType.Coding:
1574
1701
  return React__default["default"].createElement(CodingInput, { property: property, name: name, defaultValue: value, onChange: props.onChange });
1702
+ case core.PropertyType.ContactDetail:
1703
+ return React__default["default"].createElement(ContactDetailInput, { name: name, defaultValue: value, onChange: props.onChange });
1575
1704
  case core.PropertyType.ContactPoint:
1576
1705
  return React__default["default"].createElement(ContactPointInput, { name: name, defaultValue: value, onChange: props.onChange });
1577
1706
  case core.PropertyType.Extension:
@@ -1591,7 +1720,7 @@
1591
1720
  case core.PropertyType.Reference:
1592
1721
  return (React__default["default"].createElement(ReferenceInput, { name: name, defaultValue: value, targetTypes: getTargetTypes(property), onChange: props.onChange }));
1593
1722
  default:
1594
- return (React__default["default"].createElement(BackboneElementInput, { property: property, name: name, defaultValue: value, onChange: props.onChange, outcome: props.outcome }));
1723
+ return (React__default["default"].createElement(BackboneElementInput, { typeName: core.buildTypeName((_a = property.path) === null || _a === void 0 ? void 0 : _a.split('.')), defaultValue: value, onChange: props.onChange, outcome: props.outcome }));
1595
1724
  }
1596
1725
  }
1597
1726
  function getTargetTypes(property) {
@@ -1599,65 +1728,8 @@
1599
1728
  return (_c = (_b = (_a = property === null || property === void 0 ? void 0 : property.type) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.targetProfile) === null || _c === void 0 ? void 0 : _c.map((p) => p.split('/').pop());
1600
1729
  }
1601
1730
 
1602
- function ResourceForm(props) {
1603
- const medplum = useMedplum();
1604
- const defaultValue = useResource(props.defaultValue);
1605
- const [schema, setSchema] = React.useState();
1606
- const [value, setValue] = React.useState();
1607
- React.useEffect(() => {
1608
- if (defaultValue) {
1609
- setValue(JSON.parse(JSON.stringify(defaultValue)));
1610
- medplum.requestSchema(defaultValue.resourceType).then(setSchema);
1611
- }
1612
- }, [medplum, defaultValue]);
1613
- if (!schema || !value) {
1614
- return React__default["default"].createElement("div", null, "Loading...");
1615
- }
1616
- const typeSchema = schema.types[value.resourceType];
1617
- const typedValue = { type: value.resourceType, value };
1618
- return (React__default["default"].createElement("form", { noValidate: true, autoComplete: "off", onSubmit: (e) => {
1619
- e.preventDefault();
1620
- if (props.onSubmit) {
1621
- props.onSubmit(value);
1622
- }
1623
- } },
1624
- React__default["default"].createElement(FormSection, { title: "Resource Type" },
1625
- React__default["default"].createElement(Input, { name: "resourceType", defaultValue: value.resourceType, disabled: true })),
1626
- React__default["default"].createElement(FormSection, { title: "ID" },
1627
- React__default["default"].createElement(Input, { name: "id", defaultValue: value.id, disabled: true })),
1628
- Object.entries(typeSchema.properties).map((entry) => {
1629
- const key = entry[0];
1630
- if (key === 'id' || DEFAULT_IGNORED_PROPERTIES.indexOf(key) >= 0) {
1631
- return null;
1632
- }
1633
- const property = entry[1];
1634
- const [propertyValue, propertyType] = getValueAndType(typedValue, key);
1635
- return (React__default["default"].createElement(FormSection, { key: key, title: core.getPropertyDisplayName(key), description: property.definition, htmlFor: key, outcome: props.outcome },
1636
- React__default["default"].createElement(ResourcePropertyInput, { property: property, name: key, defaultValue: propertyValue, defaultPropertyType: propertyType, outcome: props.outcome, onChange: (newValue, propName) => {
1637
- setValue(setPropertyValue(value, key, propName !== null && propName !== void 0 ? propName : key, entry[1], newValue));
1638
- } })));
1639
- }),
1640
- React__default["default"].createElement(Button, { type: "submit", size: "large" }, "OK"),
1641
- props.onDelete && (React__default["default"].createElement(Button, { type: "button", size: "large", onClick: () => {
1642
- props.onDelete(value);
1643
- } }, "Delete"))));
1644
- }
1645
- function setPropertyValue(obj, key, propName, elementDefinition, value) {
1646
- const types = elementDefinition.type;
1647
- if (types.length > 1) {
1648
- for (const type of types) {
1649
- const compoundKey = key.replace('[x]', core.capitalize(type.code));
1650
- if (compoundKey in obj) {
1651
- delete obj[compoundKey];
1652
- }
1653
- }
1654
- }
1655
- obj[propName] = value;
1656
- return obj;
1657
- }
1658
-
1659
1731
  function BackboneElementInput(props) {
1660
- var _a, _b;
1732
+ var _a;
1661
1733
  const [value, setValue] = React.useState((_a = props.defaultValue) !== null && _a !== void 0 ? _a : {});
1662
1734
  function setValueWrapper(newValue) {
1663
1735
  setValue(newValue);
@@ -1665,13 +1737,14 @@
1665
1737
  props.onChange(newValue);
1666
1738
  }
1667
1739
  }
1668
- const typeName = core.buildTypeName((_b = props.property.path) === null || _b === void 0 ? void 0 : _b.split('.'));
1740
+ const typeName = props.typeName;
1669
1741
  const typeSchema = core.globalSchema.types[typeName];
1670
1742
  if (!typeSchema) {
1671
1743
  return React__default["default"].createElement("div", null,
1672
1744
  typeName,
1673
1745
  "\u00A0not implemented");
1674
1746
  }
1747
+ const typedValue = { type: typeName, value };
1675
1748
  return (React__default["default"].createElement(React__default["default"].Fragment, null, Object.entries(typeSchema.properties).map((entry) => {
1676
1749
  const key = entry[0];
1677
1750
  if (key === 'id' || DEFAULT_IGNORED_PROPERTIES.indexOf(key) >= 0) {
@@ -1681,7 +1754,13 @@
1681
1754
  if (!property.type) {
1682
1755
  return null;
1683
1756
  }
1684
- const [propertyValue, propertyType] = getValueAndType(value, key);
1757
+ const [propertyValue, propertyType] = getValueAndType(typedValue, key);
1758
+ if (property.type.length === 1 && property.type[0].code === 'boolean') {
1759
+ return (React__default["default"].createElement(CheckboxFormSection, { key: key, title: core.getPropertyDisplayName(key), description: property.definition, htmlFor: key },
1760
+ React__default["default"].createElement(ResourcePropertyInput, { property: property, name: key, defaultValue: propertyValue, defaultPropertyType: propertyType, outcome: props.outcome, onChange: (newValue, propName) => {
1761
+ setValueWrapper(setPropertyValue(value, key, propName !== null && propName !== void 0 ? propName : key, entry[1], newValue));
1762
+ } })));
1763
+ }
1685
1764
  return (React__default["default"].createElement(FormSection, { key: key, title: core.getPropertyDisplayName(key), description: property.definition, htmlFor: key, outcome: props.outcome },
1686
1765
  React__default["default"].createElement(ResourcePropertyInput, { property: property, name: key, defaultValue: propertyValue, defaultPropertyType: propertyType, outcome: props.outcome, onChange: (newValue, propName) => {
1687
1766
  setValueWrapper(setPropertyValue(value, key, propName !== null && propName !== void 0 ? propName : key, entry[1], newValue));
@@ -3199,7 +3278,7 @@
3199
3278
  }
3200
3279
  } }));
3201
3280
  case core.SearchParameterType.BOOLEAN:
3202
- return (React__default["default"].createElement("input", { type: "checkbox", name: name, "data-testid": name, defaultChecked: props.defaultValue === 'true', value: "true", onChange: (e) => props.onChange(e.target.checked ? 'true' : 'false') }));
3281
+ return (React__default["default"].createElement(Checkbox, { name: name, testid: name, defaultValue: props.defaultValue === 'true', onChange: (newValue) => props.onChange(newValue.toString()) }));
3203
3282
  case core.SearchParameterType.DATE:
3204
3283
  return React__default["default"].createElement(Input, { type: "date", testid: name, defaultValue: props.defaultValue, onChange: props.onChange });
3205
3284
  case core.SearchParameterType.DATETIME:
@@ -3661,7 +3740,7 @@
3661
3740
  const resources = entries === null || entries === void 0 ? void 0 : entries.map((e) => e.resource);
3662
3741
  const savedSearches = (_c = (_b = props.userConfig) === null || _b === void 0 ? void 0 : _b.search) === null || _c === void 0 ? void 0 : _c.filter((s) => { var _a; return (_a = s.criteria) === null || _a === void 0 ? void 0 : _a.startsWith(resourceType); });
3663
3742
  return (React__default["default"].createElement("div", { className: "medplum-search-control", onContextMenu: (e) => killEvent(e), "data-testid": "search-control" },
3664
- React__default["default"].createElement(TitleBar, null,
3743
+ !props.hideToolbar && (React__default["default"].createElement(TitleBar, null,
3665
3744
  React__default["default"].createElement("div", null,
3666
3745
  React__default["default"].createElement("h1", null,
3667
3746
  React__default["default"].createElement("a", { href: `https://www.hl7.org/fhir/${resourceType.toLowerCase()}.html`, target: "_blank", rel: "noopener" }, resourceType)),
@@ -3685,7 +3764,7 @@
3685
3764
  ' ', (_d = lastResult.total) === null || _d === void 0 ? void 0 :
3686
3765
  _d.toLocaleString()),
3687
3766
  React__default["default"].createElement(Button, { testid: "prev-page-button", size: "small", onClick: () => emitSearchChange(movePage(search, -1)) }, "<<"),
3688
- React__default["default"].createElement(Button, { testid: "next-page-button", size: "small", onClick: () => emitSearchChange(movePage(search, 1)) }, ">>")))),
3767
+ React__default["default"].createElement(Button, { testid: "next-page-button", size: "small", onClick: () => emitSearchChange(movePage(search, 1)) }, ">>"))))),
3689
3768
  React__default["default"].createElement("table", null,
3690
3769
  React__default["default"].createElement("thead", null,
3691
3770
  React__default["default"].createElement("tr", null,
@@ -3694,9 +3773,9 @@
3694
3773
  fields.map((field) => (React__default["default"].createElement("th", { key: field.name, onClick: (e) => handleSortClick(e, field.searchParams) },
3695
3774
  buildFieldNameString(field.name),
3696
3775
  field.searchParams && React__default["default"].createElement(FilterIcon, null))))),
3697
- React__default["default"].createElement("tr", null,
3776
+ !props.hideFilters && (React__default["default"].createElement("tr", null,
3698
3777
  checkboxColumn && React__default["default"].createElement("th", { className: "filters medplum-search-icon-cell" }),
3699
- fields.map((field) => (React__default["default"].createElement("th", { key: field.name, className: "filters" }, field.searchParams && (React__default["default"].createElement(FilterDescription, { resourceType: resourceType, searchParams: field.searchParams, filters: props.search.filters }))))))),
3778
+ fields.map((field) => (React__default["default"].createElement("th", { key: field.name, className: "filters" }, field.searchParams && (React__default["default"].createElement(FilterDescription, { resourceType: resourceType, searchParams: field.searchParams, filters: props.search.filters })))))))),
3700
3779
  React__default["default"].createElement("tbody", null, resources === null || resources === void 0 ? void 0 : resources.map((resource) => resource && (React__default["default"].createElement("tr", { key: resource.id, "data-testid": "search-control-row", onClick: (e) => handleRowClick(e, resource), onAuxClick: (e) => handleRowClick(e, resource) },
3701
3780
  checkboxColumn && (React__default["default"].createElement("td", { className: "medplum-search-icon-cell" },
3702
3781
  React__default["default"].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) }))),
@@ -3895,7 +3974,7 @@
3895
3974
  function HeaderSearchInput(props) {
3896
3975
  const medplum = useMedplum();
3897
3976
  return (React__default["default"].createElement(Autocomplete, { loadOptions: (input, signal) => __awaiter(this, void 0, void 0, function* () {
3898
- return getResourcesFromResponse((yield medplum.graphql(buildGraphQLQuery(input), { signal })), input);
3977
+ return getResourcesFromResponse((yield medplum.graphql(buildGraphQLQuery(input), undefined, undefined, { signal })), input);
3899
3978
  }), getId: (item) => {
3900
3979
  return item.id;
3901
3980
  }, getIcon: (item) => React__default["default"].createElement(Avatar, { value: item }), getDisplay: (item) => React__default["default"].createElement(ResourceName, { value: item }), getHelpText: (item) => {
@@ -4469,8 +4548,24 @@
4469
4548
  setResponseItems(newResponseItems);
4470
4549
  props.onChange(newResponseItems);
4471
4550
  }
4472
- return (React__default["default"].createElement(React__default["default"].Fragment, null, props.items.map((item, index) => item.type === exports.QuestionnaireItemType.group ? (React__default["default"].createElement(QuestionnaireFormItem, { key: item.linkId, item: item, onChange: (newResponseItem) => setResponseItem(index, newResponseItem) })) : (React__default["default"].createElement(FormSection, { key: item.linkId, htmlFor: item.linkId, title: item.text || '' },
4473
- React__default["default"].createElement(QuestionnaireFormItem, { item: item, onChange: (newResponseItem) => setResponseItem(index, newResponseItem) }))))));
4551
+ return (React__default["default"].createElement(React__default["default"].Fragment, null, props.items.map((item, index) => {
4552
+ if (item.type === exports.QuestionnaireItemType.display) {
4553
+ return React__default["default"].createElement("p", { key: item.linkId }, item.text);
4554
+ }
4555
+ if (item.type === exports.QuestionnaireItemType.group) {
4556
+ return (React__default["default"].createElement(QuestionnaireFormItem, { key: item.linkId, item: item, onChange: (newResponseItem) => setResponseItem(index, newResponseItem) }));
4557
+ }
4558
+ if (item.type === exports.QuestionnaireItemType.boolean) {
4559
+ const initial = item.initial && item.initial.length > 0 ? item.initial[0] : undefined;
4560
+ return (React__default["default"].createElement(CheckboxFormSection, { key: item.linkId, title: item.text, htmlFor: item.linkId },
4561
+ React__default["default"].createElement(Checkbox, { name: item.linkId, defaultValue: initial === null || initial === void 0 ? void 0 : initial.valueBoolean, onChange: (newValue) => setResponseItem(index, {
4562
+ linkId: item.linkId,
4563
+ answer: [{ valueBoolean: newValue }],
4564
+ }) })));
4565
+ }
4566
+ return (React__default["default"].createElement(FormSection, { key: item.linkId, htmlFor: item.linkId, title: item.text || '' },
4567
+ React__default["default"].createElement(QuestionnaireFormItem, { item: item, onChange: (newResponseItem) => setResponseItem(index, newResponseItem) })));
4568
+ })));
4474
4569
  }
4475
4570
  function QuestionnaireFormItem(props) {
4476
4571
  const item = props.item;
@@ -4501,7 +4596,7 @@
4501
4596
  React__default["default"].createElement("h3", null, item.text),
4502
4597
  item.item && React__default["default"].createElement(QuestionnaireFormItemArray, { items: item.item, onChange: onChangeItem })));
4503
4598
  case exports.QuestionnaireItemType.boolean:
4504
- return (React__default["default"].createElement("input", { type: "checkbox", id: name, name: name, value: "true", defaultChecked: initial === null || initial === void 0 ? void 0 : initial.valueBoolean, onChange: (e) => onChangeAnswer({ valueBoolean: e.currentTarget.checked }) }));
4599
+ return (React__default["default"].createElement(Checkbox, { name: name, defaultValue: initial === null || initial === void 0 ? void 0 : initial.valueBoolean, onChange: (newValue) => onChangeAnswer({ valueBoolean: newValue }) }));
4505
4600
  case exports.QuestionnaireItemType.decimal:
4506
4601
  return (React__default["default"].createElement(Input, { type: "number", step: "any", name: name, defaultValue: initial === null || initial === void 0 ? void 0 : initial.valueDecimal, onChange: (newValue) => onChangeAnswer({ valueDecimal: parseFloat(newValue) }) }));
4507
4602
  case exports.QuestionnaireItemType.integer:
@@ -4806,8 +4901,8 @@
4806
4901
  "Status: ",
4807
4902
  React__default["default"].createElement(StatusBadge, { status: (task === null || task === void 0 ? void 0 : task.status) || 'unknown' }))),
4808
4903
  React__default["default"].createElement("div", { className: "medplum-request-group-task-actions" },
4809
- taskInput && !taskOutput && (React__default["default"].createElement(MedplumLink, { className: "medplum-button", to: taskInput }, "Start")),
4810
- taskInput && taskOutput && (React__default["default"].createElement(MedplumLink, { className: "medplum-button", to: taskOutput }, "Edit")))));
4904
+ taskInput && !taskOutput && React__default["default"].createElement(Button, { onClick: () => props.onStart(task, taskInput) }, "Start"),
4905
+ taskInput && taskOutput && (React__default["default"].createElement(Button, { onClick: () => props.onEdit(task, taskInput, taskOutput) }, "Edit")))));
4811
4906
  })));
4812
4907
  function buildBatchRequest(request) {
4813
4908
  var _a;
@@ -5198,7 +5293,7 @@
5198
5293
 
5199
5294
  function GoogleButton(props) {
5200
5295
  const medplum = useMedplum();
5201
- const { handleAuthResponse } = props;
5296
+ const { handleGoogleCredential } = props;
5202
5297
  const googleClientId = getGoogleClientId(props.googleClientId);
5203
5298
  const parentRef = React.useRef(null);
5204
5299
  const [scriptLoaded, setScriptLoaded] = React.useState(typeof google !== 'undefined');
@@ -5212,7 +5307,7 @@
5212
5307
  if (!initialized) {
5213
5308
  google.accounts.id.initialize({
5214
5309
  client_id: googleClientId,
5215
- callback: (response) => medplum.startGoogleLogin(response).then(handleAuthResponse),
5310
+ callback: handleGoogleCredential,
5216
5311
  });
5217
5312
  setInitialized(true);
5218
5313
  }
@@ -5220,7 +5315,7 @@
5220
5315
  google.accounts.id.renderButton(parentRef.current, {});
5221
5316
  setButtonRendered(true);
5222
5317
  }
5223
- }, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleAuthResponse]);
5318
+ }, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);
5224
5319
  if (!googleClientId) {
5225
5320
  return null;
5226
5321
  }
@@ -5251,19 +5346,24 @@
5251
5346
  setMemberships(response.memberships);
5252
5347
  }
5253
5348
  if (response.code) {
5254
- medplum
5255
- .processCode(response.code)
5256
- .then(() => {
5257
- if (props.onSuccess) {
5258
- props.onSuccess();
5259
- }
5260
- })
5261
- .catch(console.log);
5349
+ if (props.onCode) {
5350
+ props.onCode(response.code);
5351
+ }
5352
+ else {
5353
+ medplum
5354
+ .processCode(response.code)
5355
+ .then(() => {
5356
+ if (props.onSuccess) {
5357
+ props.onSuccess();
5358
+ }
5359
+ })
5360
+ .catch(console.log);
5361
+ }
5262
5362
  }
5263
5363
  }
5264
5364
  return (React__default["default"].createElement(Document, { width: 450 }, (() => {
5265
5365
  if (!login) {
5266
- return (React__default["default"].createElement(AuthenticationForm, { googleClientId: props.googleClientId, onForgotPassword: props.onForgotPassword, onRegister: props.onRegister, handleAuthResponse: handleAuthResponse }, props.children));
5366
+ return (React__default["default"].createElement(AuthenticationForm, { clientId: props.clientId, scope: props.scope, nonce: props.nonce, googleClientId: props.googleClientId, onForgotPassword: props.onForgotPassword, onRegister: props.onRegister, handleAuthResponse: handleAuthResponse }, props.children));
5267
5367
  }
5268
5368
  else if (memberships) {
5269
5369
  return React__default["default"].createElement(ProfileForm, { login: login, memberships: memberships, handleAuthResponse: handleAuthResponse });
@@ -5280,6 +5380,9 @@
5280
5380
  return (React__default["default"].createElement(Form, { style: { maxWidth: 400 }, onSubmit: (formData) => {
5281
5381
  medplum
5282
5382
  .startLogin({
5383
+ clientId: props.clientId,
5384
+ scope: props.scope,
5385
+ nonce: props.nonce,
5283
5386
  email: formData.email,
5284
5387
  password: formData.password,
5285
5388
  remember: formData.remember === 'true',
@@ -5306,7 +5409,18 @@
5306
5409
  React__default["default"].createElement("div", null,
5307
5410
  React__default["default"].createElement(Button, { type: "submit", testid: "submit" }, "Sign in"))),
5308
5411
  React__default["default"].createElement("div", { className: "medplum-signin-google-container" },
5309
- React__default["default"].createElement(GoogleButton, { googleClientId: props.googleClientId, handleAuthResponse: props.handleAuthResponse }))));
5412
+ React__default["default"].createElement(GoogleButton, { googleClientId: props.googleClientId, handleGoogleCredential: (response) => {
5413
+ medplum
5414
+ .startGoogleLogin({
5415
+ clientId: props.clientId,
5416
+ scope: props.scope,
5417
+ nonce: props.nonce,
5418
+ googleClientId: response.clientId,
5419
+ googleCredential: response.credential,
5420
+ })
5421
+ .then(props.handleAuthResponse)
5422
+ .catch(setOutcome);
5423
+ } }))));
5310
5424
  }
5311
5425
  function ProfileForm(props) {
5312
5426
  const medplum = useMedplum();
@@ -5387,9 +5501,13 @@
5387
5501
  exports.Avatar = Avatar;
5388
5502
  exports.BackboneElementInput = BackboneElementInput;
5389
5503
  exports.Button = Button;
5504
+ exports.Checkbox = Checkbox;
5505
+ exports.CheckboxFormSection = CheckboxFormSection;
5390
5506
  exports.CodeInput = CodeInput;
5391
5507
  exports.CodeableConceptDisplay = CodeableConceptDisplay;
5392
5508
  exports.CodeableConceptInput = CodeableConceptInput;
5509
+ exports.ContactDetailDisplay = ContactDetailDisplay;
5510
+ exports.ContactDetailInput = ContactDetailInput;
5393
5511
  exports.ContactPointDisplay = ContactPointDisplay;
5394
5512
  exports.ContactPointInput = ContactPointInput;
5395
5513
  exports.DateTimeDisplay = DateTimeDisplay;