@medplum/react 2.0.1 → 2.0.3

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 (165) hide show
  1. package/dist/cjs/DiagnosticReportDisplay/DiagnosticReportDisplay.d.ts +2 -0
  2. package/dist/cjs/DiagnosticReportDisplay/DiagnosticReportDisplay.stories.d.ts +1 -0
  3. package/dist/cjs/MedplumProvider/MedplumProvider.d.ts +8 -0
  4. package/dist/cjs/NoteDisplay/NoteDisplay.d.ts +6 -0
  5. package/dist/cjs/NoteDisplay/NoteDisplay.stories.d.ts +7 -0
  6. package/dist/cjs/OperationOutcomeAlert/OperationOutcomeAlert.d.ts +2 -1
  7. package/dist/cjs/QuantityInput/QuantityInput.d.ts +1 -0
  8. package/dist/cjs/QuantityInput/QuantityInput.stories.d.ts +7 -0
  9. package/dist/cjs/ResourceTable/ResourceTable.d.ts +13 -0
  10. package/dist/cjs/ResourceTimeline/ResourceTimeline.d.ts +2 -2
  11. package/dist/cjs/index.cjs +917 -230
  12. package/dist/cjs/index.cjs.map +1 -1
  13. package/dist/cjs/index.d.ts +1 -0
  14. package/dist/cjs/index.min.cjs +1 -1
  15. package/dist/cjs/useResource/useResource.d.ts +2 -2
  16. package/dist/cjs/utils/date.d.ts +2 -1
  17. package/dist/esm/AttachmentArrayInput/AttachmentArrayInput.mjs +2 -1
  18. package/dist/esm/AttachmentArrayInput/AttachmentArrayInput.mjs.map +1 -1
  19. package/dist/esm/DefaultResourceTimeline/DefaultResourceTimeline.mjs +2 -6
  20. package/dist/esm/DefaultResourceTimeline/DefaultResourceTimeline.mjs.map +1 -1
  21. package/dist/esm/DiagnosticReportDisplay/DiagnosticReportDisplay.d.ts +2 -0
  22. package/dist/esm/DiagnosticReportDisplay/DiagnosticReportDisplay.mjs +26 -22
  23. package/dist/esm/DiagnosticReportDisplay/DiagnosticReportDisplay.mjs.map +1 -1
  24. package/dist/esm/DiagnosticReportDisplay/DiagnosticReportDisplay.stories.d.ts +1 -0
  25. package/dist/esm/EncounterTimeline/EncounterTimeline.mjs +6 -6
  26. package/dist/esm/EncounterTimeline/EncounterTimeline.mjs.map +1 -1
  27. package/dist/esm/ErrorBoundary/ErrorBoundary.mjs +1 -1
  28. package/dist/esm/ErrorBoundary/ErrorBoundary.mjs.map +1 -1
  29. package/dist/esm/GoogleButton/GoogleButton.mjs +6 -4
  30. package/dist/esm/GoogleButton/GoogleButton.mjs.map +1 -1
  31. package/dist/esm/MedplumLink/MedplumLink.mjs +2 -2
  32. package/dist/esm/MedplumLink/MedplumLink.mjs.map +1 -1
  33. package/dist/esm/MedplumProvider/MedplumProvider.d.ts +8 -0
  34. package/dist/esm/MedplumProvider/MedplumProvider.mjs +17 -1
  35. package/dist/esm/MedplumProvider/MedplumProvider.mjs.map +1 -1
  36. package/dist/esm/MoneyInput/MoneyInput.mjs +1 -1
  37. package/dist/esm/MoneyInput/MoneyInput.mjs.map +1 -1
  38. package/dist/esm/NoteDisplay/NoteDisplay.d.ts +6 -0
  39. package/dist/esm/NoteDisplay/NoteDisplay.mjs +18 -0
  40. package/dist/esm/NoteDisplay/NoteDisplay.mjs.map +1 -0
  41. package/dist/esm/NoteDisplay/NoteDisplay.stories.d.ts +7 -0
  42. package/dist/esm/OperationOutcomeAlert/OperationOutcomeAlert.d.ts +2 -1
  43. package/dist/esm/OperationOutcomeAlert/OperationOutcomeAlert.mjs +4 -3
  44. package/dist/esm/OperationOutcomeAlert/OperationOutcomeAlert.mjs.map +1 -1
  45. package/dist/esm/PatientTimeline/PatientTimeline.mjs +10 -10
  46. package/dist/esm/PatientTimeline/PatientTimeline.mjs.map +1 -1
  47. package/dist/esm/QuantityInput/QuantityInput.d.ts +1 -0
  48. package/dist/esm/QuantityInput/QuantityInput.mjs +10 -4
  49. package/dist/esm/QuantityInput/QuantityInput.mjs.map +1 -1
  50. package/dist/esm/QuantityInput/QuantityInput.stories.d.ts +7 -0
  51. package/dist/esm/QuestionnaireForm/QuestionnaireForm.mjs +2 -2
  52. package/dist/esm/QuestionnaireForm/QuestionnaireForm.mjs.map +1 -1
  53. package/dist/esm/ReferenceRangeEditor/ReferenceRangeEditor.mjs +2 -1
  54. package/dist/esm/ReferenceRangeEditor/ReferenceRangeEditor.mjs.map +1 -1
  55. package/dist/esm/RequestGroupDisplay/RequestGroupDisplay.mjs +2 -1
  56. package/dist/esm/RequestGroupDisplay/RequestGroupDisplay.mjs.map +1 -1
  57. package/dist/esm/ResourceArrayInput/ResourceArrayInput.mjs +2 -1
  58. package/dist/esm/ResourceArrayInput/ResourceArrayInput.mjs.map +1 -1
  59. package/dist/esm/ResourceTable/ResourceTable.d.ts +13 -0
  60. package/dist/esm/ResourceTable/ResourceTable.mjs +4 -1
  61. package/dist/esm/ResourceTable/ResourceTable.mjs.map +1 -1
  62. package/dist/esm/ResourceTimeline/ResourceTimeline.d.ts +2 -2
  63. package/dist/esm/ResourceTimeline/ResourceTimeline.mjs +62 -34
  64. package/dist/esm/ResourceTimeline/ResourceTimeline.mjs.map +1 -1
  65. package/dist/esm/SearchControl/SearchControl.mjs +7 -1
  66. package/dist/esm/SearchControl/SearchControl.mjs.map +1 -1
  67. package/dist/esm/SearchPopupMenu/SearchPopupMenu.mjs +14 -1
  68. package/dist/esm/SearchPopupMenu/SearchPopupMenu.mjs.map +1 -1
  69. package/dist/esm/ServiceRequestTimeline/ServiceRequestTimeline.mjs +7 -7
  70. package/dist/esm/ServiceRequestTimeline/ServiceRequestTimeline.mjs.map +1 -1
  71. package/dist/esm/Timeline/Timeline.mjs +1 -1
  72. package/dist/esm/Timeline/Timeline.mjs.map +1 -1
  73. package/dist/esm/auth/AuthenticationForm.mjs +1 -1
  74. package/dist/esm/auth/AuthenticationForm.mjs.map +1 -1
  75. package/dist/esm/auth/MfaForm.mjs +1 -1
  76. package/dist/esm/auth/MfaForm.mjs.map +1 -1
  77. package/dist/esm/index.d.ts +1 -0
  78. package/dist/esm/index.min.mjs +1 -1
  79. package/dist/esm/index.mjs +2 -1
  80. package/dist/esm/index.mjs.map +1 -1
  81. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs +69 -0
  82. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs.map +1 -0
  83. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs +18 -0
  84. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs.map +1 -0
  85. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustmentsHorizontal.mjs +24 -0
  86. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustmentsHorizontal.mjs.map +1 -0
  87. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs +14 -0
  88. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs.map +1 -0
  89. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleach.mjs +18 -0
  90. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleach.mjs.map +1 -0
  91. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleachOff.mjs +19 -0
  92. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleachOff.mjs.map +1 -0
  93. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBoxMultiple.mjs +25 -0
  94. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBoxMultiple.mjs.map +1 -0
  95. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBracketsContain.mjs +16 -0
  96. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBracketsContain.mjs.map +1 -0
  97. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucket.mjs +19 -0
  98. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucket.mjs.map +1 -0
  99. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucketOff.mjs +26 -0
  100. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucketOff.mjs.map +1 -0
  101. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCalendar.mjs +23 -0
  102. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCalendar.mjs.map +1 -0
  103. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs +12 -0
  104. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs.map +1 -0
  105. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheckbox.mjs +19 -0
  106. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheckbox.mjs.map +1 -0
  107. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleMinus.mjs +13 -0
  108. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleMinus.mjs.map +1 -0
  109. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCirclePlus.mjs +14 -0
  110. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCirclePlus.mjs.map +1 -0
  111. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCloudUpload.mjs +20 -0
  112. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCloudUpload.mjs.map +1 -0
  113. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconColumns.mjs +19 -0
  114. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconColumns.mjs.map +1 -0
  115. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCurrencyDollar.mjs +19 -0
  116. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCurrencyDollar.mjs.map +1 -0
  117. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.mjs +14 -0
  118. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.mjs.map +1 -0
  119. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.mjs +26 -0
  120. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.mjs.map +1 -0
  121. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqual.mjs +13 -0
  122. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqual.mjs.map +1 -0
  123. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqualNot.mjs +14 -0
  124. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqualNot.mjs.map +1 -0
  125. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFileAlert.mjs +21 -0
  126. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFileAlert.mjs.map +1 -0
  127. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilePlus.mjs +21 -0
  128. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilePlus.mjs.map +1 -0
  129. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilter.mjs +18 -0
  130. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilter.mjs.map +1 -0
  131. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconListDetails.mjs +29 -0
  132. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconListDetails.mjs.map +1 -0
  133. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathGreater.mjs +12 -0
  134. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathGreater.mjs.map +1 -0
  135. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathLower.mjs +12 -0
  136. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathLower.mjs.map +1 -0
  137. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMessage.mjs +20 -0
  138. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMessage.mjs.map +1 -0
  139. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPin.mjs +20 -0
  140. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPin.mjs.map +1 -0
  141. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPinnedOff.mjs +21 -0
  142. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPinnedOff.mjs.map +1 -0
  143. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSettings.mjs +19 -0
  144. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSettings.mjs.map +1 -0
  145. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortAscending.mjs +16 -0
  146. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortAscending.mjs.map +1 -0
  147. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortDescending.mjs +16 -0
  148. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortDescending.mjs.map +1 -0
  149. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSquare.mjs +18 -0
  150. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSquare.mjs.map +1 -0
  151. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTableExport.mjs +18 -0
  152. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTableExport.mjs.map +1 -0
  153. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.mjs +19 -0
  154. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.mjs.map +1 -0
  155. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconX.mjs +13 -0
  156. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconX.mjs.map +1 -0
  157. package/dist/esm/useResource/useResource.d.ts +2 -2
  158. package/dist/esm/useResource/useResource.mjs +62 -39
  159. package/dist/esm/useResource/useResource.mjs.map +1 -1
  160. package/dist/esm/utils/date.d.ts +2 -1
  161. package/dist/esm/utils/date.mjs +31 -25
  162. package/dist/esm/utils/date.mjs.map +1 -1
  163. package/icons-unique.txt +36 -0
  164. package/icons.txt +44 -0
  165. package/package.json +12 -17
@@ -1,8 +1,8 @@
1
- import { Reference, Resource } from '@medplum/fhirtypes';
1
+ import { OperationOutcome, Reference, Resource } from '@medplum/fhirtypes';
2
2
  /**
3
3
  * React Hook to use a FHIR reference.
4
4
  * Handles the complexity of resolving references and caching resources.
5
5
  * @param value The resource or reference to resource.
6
6
  * @returns The resolved resource.
7
7
  */
8
- export declare function useResource<T extends Resource>(value: Reference<T> | T | undefined): T | undefined;
8
+ export declare function useResource<T extends Resource>(value: Reference<T> | T | undefined, setOutcome?: (outcome: OperationOutcome) => void): T | undefined;
@@ -2,5 +2,6 @@ import { Resource } from '@medplum/fhirtypes';
2
2
  /**
3
3
  * Sorts an array of resources in place by meta.lastUpdated ascending.
4
4
  * @param resources Array of resources.
5
+ * @param timelineResource Optional primary resource of a timeline view. If specified, the primary resource will be sorted by meta.lastUpdated descending.
5
6
  */
6
- export declare function sortByDateAndPriority(resources: Resource[]): void;
7
+ export declare function sortByDateAndPriority(resources: Resource[], timelineResource?: Resource): void;
@@ -1,9 +1,10 @@
1
1
  import { ActionIcon } from '@mantine/core';
2
- import { IconCircleMinus, IconCloudUpload } from '@tabler/icons';
3
2
  import React, { useState, useRef } from 'react';
4
3
  import { AttachmentButton } from '../AttachmentButton/AttachmentButton.mjs';
5
4
  import { AttachmentDisplay } from '../AttachmentDisplay/AttachmentDisplay.mjs';
6
5
  import { killEvent } from '../utils/dom.mjs';
6
+ import IconCircleMinus from '../node_modules/@tabler/icons-react/dist/esm/icons/IconCircleMinus.mjs';
7
+ import IconCloudUpload from '../node_modules/@tabler/icons-react/dist/esm/icons/IconCloudUpload.mjs';
7
8
 
8
9
  function AttachmentArrayInput(props) {
9
10
  const [values, setValues] = useState(props.defaultValue ?? []);
@@ -1 +1 @@
1
- {"version":3,"file":"AttachmentArrayInput.mjs","sources":["../../../src/AttachmentArrayInput/AttachmentArrayInput.tsx"],"sourcesContent":["import { ActionIcon } from '@mantine/core';\nimport { Attachment } from '@medplum/fhirtypes';\nimport { IconCircleMinus, IconCloudUpload } from '@tabler/icons';\nimport React, { useRef, useState } from 'react';\nimport { AttachmentButton } from '../AttachmentButton/AttachmentButton';\nimport { AttachmentDisplay } from '../AttachmentDisplay/AttachmentDisplay';\nimport { killEvent } from '../utils/dom';\n\nexport interface AttachmentArrayInputProps {\n name: string;\n defaultValue?: Attachment[];\n arrayElement?: boolean;\n onChange?: (value: Attachment[]) => void;\n}\n\nexport function AttachmentArrayInput(props: AttachmentArrayInputProps): JSX.Element {\n const [values, setValues] = useState<Attachment[]>(props.defaultValue ?? []);\n\n const valuesRef = useRef<Attachment[]>();\n valuesRef.current = values;\n\n function setValuesWrapper(newValues: Attachment[]): void {\n setValues(newValues);\n if (props.onChange) {\n props.onChange(newValues);\n }\n }\n\n return (\n <table style={{ width: '100%' }}>\n <colgroup>\n <col width=\"97%\" />\n <col width=\"3%\" />\n </colgroup>\n <tbody>\n {values.map((v: Attachment, index: number) => (\n <tr key={`${index}-${values.length}`}>\n <td>\n <AttachmentDisplay value={v} maxWidth={200} />\n </td>\n <td>\n <ActionIcon\n title=\"Remove\"\n size=\"sm\"\n onClick={(e: React.MouseEvent) => {\n killEvent(e);\n const copy = values.slice();\n copy.splice(index, 1);\n setValuesWrapper(copy);\n }}\n >\n <IconCircleMinus />\n </ActionIcon>\n </td>\n </tr>\n ))}\n <tr>\n <td></td>\n <td>\n <AttachmentButton\n onUpload={(attachment: Attachment) => {\n setValuesWrapper([...(valuesRef.current as Attachment[]), attachment]);\n }}\n >\n {(props) => (\n <ActionIcon {...props} title=\"Add\" size=\"sm\" color=\"green\">\n <IconCloudUpload size={16} />\n </ActionIcon>\n )}\n </AttachmentButton>\n </td>\n </tr>\n </tbody>\n </table>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAeM,SAAU,oBAAoB,CAAC,KAAgC,EAAA;AACnE,IAAA,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAe,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;AAE7E,IAAA,MAAM,SAAS,GAAG,MAAM,EAAgB,CAAC;AACzC,IAAA,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAE3B,SAAS,gBAAgB,CAAC,SAAuB,EAAA;QAC/C,SAAS,CAAC,SAAS,CAAC,CAAC;QACrB,IAAI,KAAK,CAAC,QAAQ,EAAE;AAClB,YAAA,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC3B,SAAA;KACF;IAED,QACE,+BAAO,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAA;AAC7B,QAAA,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,IAAA;YACE,KAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,KAAK,EAAC,KAAK,EAAG,CAAA;AACnB,YAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAC,IAAI,EAAA,CAAG,CACT;AACX,QAAA,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,IAAA;YACG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAa,EAAE,KAAa,MACvC,KAAI,CAAA,aAAA,CAAA,IAAA,EAAA,EAAA,GAAG,EAAE,CAAG,EAAA,KAAK,IAAI,MAAM,CAAC,MAAM,CAAE,CAAA,EAAA;AAClC,gBAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;oBACE,KAAC,CAAA,aAAA,CAAA,iBAAiB,EAAC,EAAA,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAA,CAAI,CAC3C;AACL,gBAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;AACE,oBAAA,KAAA,CAAA,aAAA,CAAC,UAAU,EAAA,EACT,KAAK,EAAC,QAAQ,EACd,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,CAAC,CAAmB,KAAI;4BAC/B,SAAS,CAAC,CAAC,CAAC,CAAC;AACb,4BAAA,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;AAC5B,4BAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;4BACtB,gBAAgB,CAAC,IAAI,CAAC,CAAC;yBACxB,EAAA;AAED,wBAAA,KAAA,CAAA,aAAA,CAAC,eAAe,EAAG,IAAA,CAAA,CACR,CACV,CACF,CACN,CAAC;AACF,YAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;gBACE,KAAS,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,CAAA;AACT,gBAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;AACE,oBAAA,KAAA,CAAA,aAAA,CAAC,gBAAgB,EACf,EAAA,QAAQ,EAAE,CAAC,UAAsB,KAAI;4BACnC,gBAAgB,CAAC,CAAC,GAAI,SAAS,CAAC,OAAwB,EAAE,UAAU,CAAC,CAAC,CAAC;yBACxE,EAAA,EAEA,CAAC,KAAK,MACL,KAAC,CAAA,aAAA,CAAA,UAAU,EAAK,EAAA,GAAA,KAAK,EAAE,KAAK,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,OAAO,EAAA;AACxD,wBAAA,KAAA,CAAA,aAAA,CAAC,eAAe,EAAA,EAAC,IAAI,EAAE,EAAE,EAAI,CAAA,CAClB,CACd,CACgB,CAChB,CACF,CACC,CACF,EACR;AACJ;;;;"}
1
+ {"version":3,"file":"AttachmentArrayInput.mjs","sources":["../../../src/AttachmentArrayInput/AttachmentArrayInput.tsx"],"sourcesContent":["import { ActionIcon } from '@mantine/core';\nimport { Attachment } from '@medplum/fhirtypes';\nimport { IconCircleMinus, IconCloudUpload } from '@tabler/icons-react';\nimport React, { useRef, useState } from 'react';\nimport { AttachmentButton } from '../AttachmentButton/AttachmentButton';\nimport { AttachmentDisplay } from '../AttachmentDisplay/AttachmentDisplay';\nimport { killEvent } from '../utils/dom';\n\nexport interface AttachmentArrayInputProps {\n name: string;\n defaultValue?: Attachment[];\n arrayElement?: boolean;\n onChange?: (value: Attachment[]) => void;\n}\n\nexport function AttachmentArrayInput(props: AttachmentArrayInputProps): JSX.Element {\n const [values, setValues] = useState<Attachment[]>(props.defaultValue ?? []);\n\n const valuesRef = useRef<Attachment[]>();\n valuesRef.current = values;\n\n function setValuesWrapper(newValues: Attachment[]): void {\n setValues(newValues);\n if (props.onChange) {\n props.onChange(newValues);\n }\n }\n\n return (\n <table style={{ width: '100%' }}>\n <colgroup>\n <col width=\"97%\" />\n <col width=\"3%\" />\n </colgroup>\n <tbody>\n {values.map((v: Attachment, index: number) => (\n <tr key={`${index}-${values.length}`}>\n <td>\n <AttachmentDisplay value={v} maxWidth={200} />\n </td>\n <td>\n <ActionIcon\n title=\"Remove\"\n size=\"sm\"\n onClick={(e: React.MouseEvent) => {\n killEvent(e);\n const copy = values.slice();\n copy.splice(index, 1);\n setValuesWrapper(copy);\n }}\n >\n <IconCircleMinus />\n </ActionIcon>\n </td>\n </tr>\n ))}\n <tr>\n <td></td>\n <td>\n <AttachmentButton\n onUpload={(attachment: Attachment) => {\n setValuesWrapper([...(valuesRef.current as Attachment[]), attachment]);\n }}\n >\n {(props) => (\n <ActionIcon {...props} title=\"Add\" size=\"sm\" color=\"green\">\n <IconCloudUpload size={16} />\n </ActionIcon>\n )}\n </AttachmentButton>\n </td>\n </tr>\n </tbody>\n </table>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAeM,SAAU,oBAAoB,CAAC,KAAgC,EAAA;AACnE,IAAA,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAe,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;AAE7E,IAAA,MAAM,SAAS,GAAG,MAAM,EAAgB,CAAC;AACzC,IAAA,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAE3B,SAAS,gBAAgB,CAAC,SAAuB,EAAA;QAC/C,SAAS,CAAC,SAAS,CAAC,CAAC;QACrB,IAAI,KAAK,CAAC,QAAQ,EAAE;AAClB,YAAA,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC3B,SAAA;KACF;IAED,QACE,+BAAO,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAA;AAC7B,QAAA,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,IAAA;YACE,KAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,KAAK,EAAC,KAAK,EAAG,CAAA;AACnB,YAAA,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAC,IAAI,EAAA,CAAG,CACT;AACX,QAAA,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,IAAA;YACG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAa,EAAE,KAAa,MACvC,KAAI,CAAA,aAAA,CAAA,IAAA,EAAA,EAAA,GAAG,EAAE,CAAG,EAAA,KAAK,IAAI,MAAM,CAAC,MAAM,CAAE,CAAA,EAAA;AAClC,gBAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;oBACE,KAAC,CAAA,aAAA,CAAA,iBAAiB,EAAC,EAAA,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAA,CAAI,CAC3C;AACL,gBAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;AACE,oBAAA,KAAA,CAAA,aAAA,CAAC,UAAU,EAAA,EACT,KAAK,EAAC,QAAQ,EACd,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,CAAC,CAAmB,KAAI;4BAC/B,SAAS,CAAC,CAAC,CAAC,CAAC;AACb,4BAAA,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;AAC5B,4BAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;4BACtB,gBAAgB,CAAC,IAAI,CAAC,CAAC;yBACxB,EAAA;AAED,wBAAA,KAAA,CAAA,aAAA,CAAC,eAAe,EAAG,IAAA,CAAA,CACR,CACV,CACF,CACN,CAAC;AACF,YAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;gBACE,KAAS,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,CAAA;AACT,gBAAA,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA;AACE,oBAAA,KAAA,CAAA,aAAA,CAAC,gBAAgB,EACf,EAAA,QAAQ,EAAE,CAAC,UAAsB,KAAI;4BACnC,gBAAgB,CAAC,CAAC,GAAI,SAAS,CAAC,OAAwB,EAAE,UAAU,CAAC,CAAC,CAAC;yBACxE,EAAA,EAEA,CAAC,KAAK,MACL,KAAC,CAAA,aAAA,CAAA,UAAU,EAAK,EAAA,GAAA,KAAK,EAAE,KAAK,EAAC,KAAK,EAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAC,OAAO,EAAA;AACxD,wBAAA,KAAA,CAAA,aAAA,CAAC,eAAe,EAAA,EAAC,IAAI,EAAE,EAAE,EAAI,CAAA,CAClB,CACd,CACgB,CAChB,CACF,CACC,CACF,EACR;AACJ;;;;"}
@@ -1,13 +1,9 @@
1
- import { getReferenceString } from '@medplum/core';
2
1
  import React from 'react';
3
2
  import { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline.mjs';
4
3
 
5
4
  function DefaultResourceTimeline(props) {
6
- return (React.createElement(ResourceTimeline, { value: props.resource, loadTimelineResources: async (medplum, resource) => {
7
- return Promise.all([
8
- medplum.readHistory(resource.resourceType, resource.id),
9
- medplum.search('AuditEvent', '_sort=-_lastUpdated&entity=' + getReferenceString(resource)),
10
- ]);
5
+ return (React.createElement(ResourceTimeline, { value: props.resource, loadTimelineResources: async (medplum, resourceType, id) => {
6
+ return Promise.allSettled([medplum.readHistory(resourceType, id)]);
11
7
  } }));
12
8
  }
13
9
 
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultResourceTimeline.mjs","sources":["../../../src/DefaultResourceTimeline/DefaultResourceTimeline.tsx"],"sourcesContent":["import { getReferenceString, MedplumClient } from '@medplum/core';\nimport { Reference, Resource } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline';\n\nexport interface DefaultResourceTimelineProps {\n resource: Resource | Reference;\n}\n\nexport function DefaultResourceTimeline(props: DefaultResourceTimelineProps): JSX.Element {\n return (\n <ResourceTimeline\n value={props.resource}\n loadTimelineResources={async (medplum: MedplumClient, resource: Resource) => {\n return Promise.all([\n medplum.readHistory(resource.resourceType, resource.id as string),\n medplum.search('AuditEvent', '_sort=-_lastUpdated&entity=' + getReferenceString(resource)),\n ]);\n }}\n />\n );\n}\n"],"names":[],"mappings":";;;;AASM,SAAU,uBAAuB,CAAC,KAAmC,EAAA;AACzE,IAAA,QACE,KAAC,CAAA,aAAA,CAAA,gBAAgB,IACf,KAAK,EAAE,KAAK,CAAC,QAAQ,EACrB,qBAAqB,EAAE,OAAO,OAAsB,EAAE,QAAkB,KAAI;YAC1E,OAAO,OAAO,CAAC,GAAG,CAAC;gBACjB,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAY,CAAC;gBACjE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,6BAA6B,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AAC3F,aAAA,CAAC,CAAC;SACJ,EAAA,CACD,EACF;AACJ;;;;"}
1
+ {"version":3,"file":"DefaultResourceTimeline.mjs","sources":["../../../src/DefaultResourceTimeline/DefaultResourceTimeline.tsx"],"sourcesContent":["import { MedplumClient } from '@medplum/core';\nimport { Reference, Resource, ResourceType } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline';\n\nexport interface DefaultResourceTimelineProps {\n resource: Resource | Reference;\n}\n\nexport function DefaultResourceTimeline(props: DefaultResourceTimelineProps): JSX.Element {\n return (\n <ResourceTimeline\n value={props.resource}\n loadTimelineResources={async (medplum: MedplumClient, resourceType: ResourceType, id: string) => {\n return Promise.allSettled([medplum.readHistory(resourceType, id)]);\n }}\n />\n );\n}\n"],"names":[],"mappings":";;;AASM,SAAU,uBAAuB,CAAC,KAAmC,EAAA;IACzE,QACE,oBAAC,gBAAgB,EAAA,EACf,KAAK,EAAE,KAAK,CAAC,QAAQ,EACrB,qBAAqB,EAAE,OAAO,OAAsB,EAAE,YAA0B,EAAE,EAAU,KAAI;AAC9F,YAAA,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;SACpE,EAAA,CACD,EACF;AACJ;;;;"}
@@ -2,9 +2,11 @@
2
2
  import { DiagnosticReport, Observation, Reference } from '@medplum/fhirtypes';
3
3
  export interface DiagnosticReportDisplayProps {
4
4
  value?: DiagnosticReport | Reference<DiagnosticReport>;
5
+ hideObservationNotes?: boolean;
5
6
  }
6
7
  export declare function DiagnosticReportDisplay(props: DiagnosticReportDisplayProps): JSX.Element | null;
7
8
  export interface ObservationTableProps {
8
9
  value?: Observation[] | Reference<Observation>[];
10
+ hideObservationNotes?: boolean;
9
11
  }
10
12
  export declare function ObservationTable(props: ObservationTableProps): JSX.Element;
@@ -3,6 +3,7 @@ import { formatDateTime, capitalize, formatObservationValue } from '@medplum/cor
3
3
  import React from 'react';
4
4
  import { CodeableConceptDisplay } from '../CodeableConceptDisplay/CodeableConceptDisplay.mjs';
5
5
  import { MedplumLink } from '../MedplumLink/MedplumLink.mjs';
6
+ import { NoteDisplay } from '../NoteDisplay/NoteDisplay.mjs';
6
7
  import { RangeDisplay } from '../RangeDisplay/RangeDisplay.mjs';
7
8
  import { ResourceBadge } from '../ResourceBadge/ResourceBadge.mjs';
8
9
  import { StatusBadge } from '../StatusBadge/StatusBadge.mjs';
@@ -26,6 +27,9 @@ const useStyles = createStyles((theme) => ({
26
27
  border: `0.1px solid ${theme.colors.red[5]}`,
27
28
  },
28
29
  },
30
+ noteBody: { fontSize: theme.fontSizes.sm },
31
+ noteCite: { fontSize: theme.fontSizes.xs, marginBlockStart: 3 },
32
+ noteRoot: { padding: 5 },
29
33
  }));
30
34
  function DiagnosticReportDisplay(props) {
31
35
  const diagnosticReport = useResource(props.value);
@@ -33,16 +37,11 @@ function DiagnosticReportDisplay(props) {
33
37
  if (!diagnosticReport) {
34
38
  return null;
35
39
  }
36
- let textContent = '';
40
+ const specimenNotes = specimen?.note || [];
37
41
  if (diagnosticReport.presentedForm && diagnosticReport.presentedForm.length > 0) {
38
42
  const pf = diagnosticReport.presentedForm[0];
39
43
  if (pf.contentType?.startsWith('text/plain') && pf.data) {
40
- textContent = window.atob(pf.data);
41
- }
42
- }
43
- if (specimen?.note) {
44
- for (const note of specimen.note) {
45
- textContent += note.text + '\n\n';
44
+ specimenNotes.push({ text: window.atob(pf.data) });
46
45
  }
47
46
  }
48
47
  return (React.createElement(Stack, null,
@@ -63,8 +62,8 @@ function DiagnosticReportDisplay(props) {
63
62
  diagnosticReport.status && (React.createElement("div", null,
64
63
  React.createElement(Text, { size: "xs", transform: "uppercase", color: "dimmed" }, "Status"),
65
64
  React.createElement(Text, null, capitalize(diagnosticReport.status))))),
66
- diagnosticReport.result && React.createElement(ObservationTable, { value: diagnosticReport.result }),
67
- textContent && React.createElement("pre", null, textContent.trim())));
65
+ diagnosticReport.result && (React.createElement(ObservationTable, { hideObservationNotes: props.hideObservationNotes, value: diagnosticReport.result })),
66
+ specimenNotes.length > 0 && React.createElement(NoteDisplay, { value: specimenNotes })));
68
67
  }
69
68
  function ObservationTable(props) {
70
69
  const { classes } = useStyles();
@@ -77,7 +76,7 @@ function ObservationTable(props) {
77
76
  React.createElement("th", null, "Interpretation"),
78
77
  React.createElement("th", null, "Category"),
79
78
  React.createElement("th", null, "Status"))),
80
- React.createElement("tbody", null, props.value?.map((observation, index) => (React.createElement(ObservationRow, { key: 'obs-' + index, value: observation }))))));
79
+ React.createElement("tbody", null, props.value?.map((observation, index) => (React.createElement(ObservationRow, { key: `obs-${index}-${observation.id}`, hideObservationNotes: props.hideObservationNotes, value: observation }))))));
81
80
  }
82
81
  function ObservationRow(props) {
83
82
  const { classes, cx } = useStyles();
@@ -85,19 +84,24 @@ function ObservationRow(props) {
85
84
  if (!observation) {
86
85
  return null;
87
86
  }
87
+ const displayNotes = !props.hideObservationNotes && observation?.note;
88
88
  const critical = isCritical(observation);
89
- return (React.createElement("tr", { className: cx({ [classes.criticalRow]: critical }) },
90
- React.createElement("td", null,
91
- React.createElement(MedplumLink, { to: observation },
92
- React.createElement(CodeableConceptDisplay, { value: observation.code }))),
93
- React.createElement("td", null,
94
- React.createElement(ObservationValueDisplay, { value: observation })),
95
- React.createElement("td", null,
96
- React.createElement(ReferenceRangeDisplay, { value: observation.referenceRange })),
97
- React.createElement("td", null, observation.interpretation && observation.interpretation.length > 0 && (React.createElement(CodeableConceptDisplay, { value: observation.interpretation[0] }))),
98
- React.createElement("td", null, observation.category && observation.category.length > 0 && (React.createElement("ul", null, observation.category.map((concept, index) => (React.createElement("li", { key: `category-${index}` },
99
- React.createElement(CodeableConceptDisplay, { value: concept }))))))),
100
- React.createElement("td", null, observation.status && React.createElement(StatusBadge, { status: observation.status }))));
89
+ return (React.createElement(React.Fragment, null,
90
+ React.createElement("tr", { className: cx({ [classes.criticalRow]: critical }) },
91
+ React.createElement("td", { rowSpan: displayNotes ? 2 : 1 },
92
+ React.createElement(MedplumLink, { to: observation },
93
+ React.createElement(CodeableConceptDisplay, { value: observation.code }))),
94
+ React.createElement("td", null,
95
+ React.createElement(ObservationValueDisplay, { value: observation })),
96
+ React.createElement("td", null,
97
+ React.createElement(ReferenceRangeDisplay, { value: observation.referenceRange })),
98
+ React.createElement("td", null, observation.interpretation && observation.interpretation.length > 0 && (React.createElement(CodeableConceptDisplay, { value: observation.interpretation[0] }))),
99
+ React.createElement("td", null, observation.category && observation.category.length > 0 && (React.createElement("ul", null, observation.category.map((concept, index) => (React.createElement("li", { key: `category-${index}` },
100
+ React.createElement(CodeableConceptDisplay, { value: concept }))))))),
101
+ React.createElement("td", null, observation.status && React.createElement(StatusBadge, { status: observation.status }))),
102
+ displayNotes && (React.createElement("tr", null,
103
+ React.createElement("td", { colSpan: 5 },
104
+ React.createElement(NoteDisplay, { value: observation.note }))))));
101
105
  }
102
106
  function ObservationValueDisplay(props) {
103
107
  const obs = props.value;
@@ -1 +1 @@
1
- {"version":3,"file":"DiagnosticReportDisplay.mjs","sources":["../../../src/DiagnosticReportDisplay/DiagnosticReportDisplay.tsx"],"sourcesContent":["import { createStyles, Group, Stack, Text, Title } from '@mantine/core';\nimport { capitalize, formatDateTime, formatObservationValue } from '@medplum/core';\nimport {\n DiagnosticReport,\n Observation,\n ObservationComponent,\n ObservationReferenceRange,\n Reference,\n} from '@medplum/fhirtypes';\nimport React from 'react';\nimport { CodeableConceptDisplay } from '../CodeableConceptDisplay/CodeableConceptDisplay';\nimport { MedplumLink } from '../MedplumLink/MedplumLink';\nimport { RangeDisplay } from '../RangeDisplay/RangeDisplay';\nimport { ResourceBadge } from '../ResourceBadge/ResourceBadge';\nimport { StatusBadge } from '../StatusBadge/StatusBadge';\nimport { useResource } from '../useResource/useResource';\n\nconst useStyles = createStyles((theme) => ({\n table: {\n border: `0.1px solid ${theme.colors.gray[5]}`,\n borderCollapse: 'collapse',\n\n '& td, & th': {\n border: `0.1px solid ${theme.colors.gray[5]}`,\n padding: 4,\n },\n },\n\n criticalRow: {\n background: theme.colorScheme === 'dark' ? theme.colors.red[7] : theme.colors.red[1],\n border: `0.1px solid ${theme.colors.red[5]}`,\n color: theme.colors.red[5],\n fontWeight: 500,\n\n '& td': {\n border: `0.1px solid ${theme.colors.red[5]}`,\n },\n },\n}));\n\nexport interface DiagnosticReportDisplayProps {\n value?: DiagnosticReport | Reference<DiagnosticReport>;\n}\n\nexport function DiagnosticReportDisplay(props: DiagnosticReportDisplayProps): JSX.Element | null {\n const diagnosticReport = useResource(props.value);\n const specimen = useResource(diagnosticReport?.specimen?.[0]);\n\n if (!diagnosticReport) {\n return null;\n }\n\n let textContent = '';\n\n if (diagnosticReport.presentedForm && diagnosticReport.presentedForm.length > 0) {\n const pf = diagnosticReport.presentedForm[0];\n if (pf.contentType?.startsWith('text/plain') && pf.data) {\n textContent = window.atob(pf.data);\n }\n }\n\n if (specimen?.note) {\n for (const note of specimen.note) {\n textContent += note.text + '\\n\\n';\n }\n }\n\n return (\n <Stack>\n <Title>Diagnostic Report</Title>\n <Group mt=\"md\" spacing={30}>\n {diagnosticReport.subject && (\n <div>\n <Text size=\"xs\" transform=\"uppercase\" color=\"dimmed\">\n Subject\n </Text>\n <Text>\n <ResourceBadge value={diagnosticReport.subject} link={true} />\n </Text>\n </div>\n )}\n {diagnosticReport.resultsInterpreter &&\n diagnosticReport.resultsInterpreter.map((interpreter) => (\n <div key={interpreter.reference}>\n <Text size=\"xs\" transform=\"uppercase\" color=\"dimmed\">\n Interpreter\n </Text>\n <Text>\n <ResourceBadge value={interpreter} link={true} />\n </Text>\n </div>\n ))}\n {diagnosticReport.issued && (\n <div>\n <Text size=\"xs\" transform=\"uppercase\" color=\"dimmed\">\n Issued\n </Text>\n <Text>{formatDateTime(diagnosticReport.issued)}</Text>\n </div>\n )}\n {diagnosticReport.status && (\n <div>\n <Text size=\"xs\" transform=\"uppercase\" color=\"dimmed\">\n Status\n </Text>\n <Text>{capitalize(diagnosticReport.status)}</Text>\n </div>\n )}\n </Group>\n {diagnosticReport.result && <ObservationTable value={diagnosticReport.result} />}\n {textContent && <pre>{textContent.trim()}</pre>}\n </Stack>\n );\n}\n\nexport interface ObservationTableProps {\n value?: Observation[] | Reference<Observation>[];\n}\n\nexport function ObservationTable(props: ObservationTableProps): JSX.Element {\n const { classes } = useStyles();\n return (\n <table className={classes.table}>\n <thead>\n <tr>\n <th>Test</th>\n <th>Value</th>\n <th>Reference Range</th>\n <th>Interpretation</th>\n <th>Category</th>\n <th>Status</th>\n </tr>\n </thead>\n <tbody>\n {props.value?.map((observation, index) => (\n <ObservationRow key={'obs-' + index} value={observation} />\n ))}\n </tbody>\n </table>\n );\n}\n\ninterface ObservationRowProps {\n value: Observation | Reference<Observation>;\n}\n\nfunction ObservationRow(props: ObservationRowProps): JSX.Element | null {\n const { classes, cx } = useStyles();\n const observation = useResource(props.value);\n if (!observation) {\n return null;\n }\n\n const critical = isCritical(observation);\n\n return (\n <tr className={cx({ [classes.criticalRow]: critical })}>\n <td>\n <MedplumLink to={observation}>\n <CodeableConceptDisplay value={observation.code} />\n </MedplumLink>\n </td>\n <td>\n <ObservationValueDisplay value={observation} />\n </td>\n <td>\n <ReferenceRangeDisplay value={observation.referenceRange} />\n </td>\n <td>\n {observation.interpretation && observation.interpretation.length > 0 && (\n <CodeableConceptDisplay value={observation.interpretation[0]} />\n )}\n </td>\n <td>\n {observation.category && observation.category.length > 0 && (\n <ul>\n {observation.category.map((concept, index) => (\n <li key={`category-${index}`}>\n <CodeableConceptDisplay value={concept} />\n </li>\n ))}\n </ul>\n )}\n </td>\n <td>{observation.status && <StatusBadge status={observation.status} />}</td>\n </tr>\n );\n}\n\ninterface ObservationValueDisplayProps {\n value?: Observation | ObservationComponent;\n}\n\nfunction ObservationValueDisplay(props: ObservationValueDisplayProps): JSX.Element | null {\n const obs = props.value;\n return <>{formatObservationValue(obs)}</>;\n}\n\ninterface ReferenceRangeProps {\n value?: ObservationReferenceRange[];\n}\n\nfunction ReferenceRangeDisplay(props: ReferenceRangeProps): JSX.Element | null {\n const range = props.value && props.value.length > 0 && props.value[0];\n if (!range) {\n return null;\n }\n if (range.text) {\n return <>{range.text}</>;\n }\n return <RangeDisplay value={range} />;\n}\n\n/**\n * Returns true if the observation is critical.\n * See: https://www.hl7.org/fhir/valueset-observation-interpretation.html\n * @param observation The FHIR observation.\n * @returns True if the FHIR observation is a critical value.\n */\nfunction isCritical(observation: Observation): boolean {\n const code = observation.interpretation?.[0]?.coding?.[0]?.code;\n return code === 'AA' || code === 'LL' || code === 'HH' || code === 'A';\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DiagnosticReportDisplay.mjs","sources":["../../../src/DiagnosticReportDisplay/DiagnosticReportDisplay.tsx"],"sourcesContent":["import { createStyles, Group, Stack, Text, Title } from '@mantine/core';\nimport { capitalize, formatDateTime, formatObservationValue } from '@medplum/core';\nimport {\n Annotation,\n DiagnosticReport,\n Observation,\n ObservationComponent,\n ObservationReferenceRange,\n Reference,\n} from '@medplum/fhirtypes';\nimport React from 'react';\nimport { CodeableConceptDisplay } from '../CodeableConceptDisplay/CodeableConceptDisplay';\nimport { MedplumLink } from '../MedplumLink/MedplumLink';\nimport { NoteDisplay } from '../NoteDisplay/NoteDisplay';\nimport { RangeDisplay } from '../RangeDisplay/RangeDisplay';\nimport { ResourceBadge } from '../ResourceBadge/ResourceBadge';\nimport { StatusBadge } from '../StatusBadge/StatusBadge';\nimport { useResource } from '../useResource/useResource';\n\nconst useStyles = createStyles((theme) => ({\n table: {\n border: `0.1px solid ${theme.colors.gray[5]}`,\n borderCollapse: 'collapse',\n\n '& td, & th': {\n border: `0.1px solid ${theme.colors.gray[5]}`,\n padding: 4,\n },\n },\n\n criticalRow: {\n background: theme.colorScheme === 'dark' ? theme.colors.red[7] : theme.colors.red[1],\n border: `0.1px solid ${theme.colors.red[5]}`,\n color: theme.colors.red[5],\n fontWeight: 500,\n\n '& td': {\n border: `0.1px solid ${theme.colors.red[5]}`,\n },\n },\n\n noteBody: { fontSize: theme.fontSizes.sm },\n noteCite: { fontSize: theme.fontSizes.xs, marginBlockStart: 3 },\n noteRoot: { padding: 5 },\n}));\n\nexport interface DiagnosticReportDisplayProps {\n value?: DiagnosticReport | Reference<DiagnosticReport>;\n hideObservationNotes?: boolean;\n}\n\nexport function DiagnosticReportDisplay(props: DiagnosticReportDisplayProps): JSX.Element | null {\n const diagnosticReport = useResource(props.value);\n const specimen = useResource(diagnosticReport?.specimen?.[0]);\n\n if (!diagnosticReport) {\n return null;\n }\n\n const specimenNotes: Annotation[] = specimen?.note || [];\n\n if (diagnosticReport.presentedForm && diagnosticReport.presentedForm.length > 0) {\n const pf = diagnosticReport.presentedForm[0];\n if (pf.contentType?.startsWith('text/plain') && pf.data) {\n specimenNotes.push({ text: window.atob(pf.data) });\n }\n }\n\n return (\n <Stack>\n <Title>Diagnostic Report</Title>\n <Group mt=\"md\" spacing={30}>\n {diagnosticReport.subject && (\n <div>\n <Text size=\"xs\" transform=\"uppercase\" color=\"dimmed\">\n Subject\n </Text>\n <Text>\n <ResourceBadge value={diagnosticReport.subject} link={true} />\n </Text>\n </div>\n )}\n {diagnosticReport.resultsInterpreter &&\n diagnosticReport.resultsInterpreter.map((interpreter) => (\n <div key={interpreter.reference}>\n <Text size=\"xs\" transform=\"uppercase\" color=\"dimmed\">\n Interpreter\n </Text>\n <Text>\n <ResourceBadge value={interpreter} link={true} />\n </Text>\n </div>\n ))}\n {diagnosticReport.issued && (\n <div>\n <Text size=\"xs\" transform=\"uppercase\" color=\"dimmed\">\n Issued\n </Text>\n <Text>{formatDateTime(diagnosticReport.issued)}</Text>\n </div>\n )}\n {diagnosticReport.status && (\n <div>\n <Text size=\"xs\" transform=\"uppercase\" color=\"dimmed\">\n Status\n </Text>\n <Text>{capitalize(diagnosticReport.status)}</Text>\n </div>\n )}\n </Group>\n {diagnosticReport.result && (\n <ObservationTable hideObservationNotes={props.hideObservationNotes} value={diagnosticReport.result} />\n )}\n {specimenNotes.length > 0 && <NoteDisplay value={specimenNotes} />}\n </Stack>\n );\n}\n\nexport interface ObservationTableProps {\n value?: Observation[] | Reference<Observation>[];\n hideObservationNotes?: boolean;\n}\n\nexport function ObservationTable(props: ObservationTableProps): JSX.Element {\n const { classes } = useStyles();\n return (\n <table className={classes.table}>\n <thead>\n <tr>\n <th>Test</th>\n <th>Value</th>\n <th>Reference Range</th>\n <th>Interpretation</th>\n <th>Category</th>\n <th>Status</th>\n </tr>\n </thead>\n <tbody>\n {props.value?.map((observation, index) => (\n <ObservationRow\n key={`obs-${index}-${observation.id}`}\n hideObservationNotes={props.hideObservationNotes}\n value={observation}\n />\n ))}\n </tbody>\n </table>\n );\n}\n\ninterface ObservationRowProps {\n value: Observation | Reference<Observation>;\n hideObservationNotes?: boolean;\n}\n\nfunction ObservationRow(props: ObservationRowProps): JSX.Element | null {\n const { classes, cx } = useStyles();\n const observation = useResource(props.value);\n\n if (!observation) {\n return null;\n }\n const displayNotes = !props.hideObservationNotes && observation?.note;\n\n const critical = isCritical(observation);\n\n return (\n <>\n <tr className={cx({ [classes.criticalRow]: critical })}>\n <td rowSpan={displayNotes ? 2 : 1}>\n <MedplumLink to={observation}>\n <CodeableConceptDisplay value={observation.code} />\n </MedplumLink>\n </td>\n <td>\n <ObservationValueDisplay value={observation} />\n </td>\n <td>\n <ReferenceRangeDisplay value={observation.referenceRange} />\n </td>\n <td>\n {observation.interpretation && observation.interpretation.length > 0 && (\n <CodeableConceptDisplay value={observation.interpretation[0]} />\n )}\n </td>\n <td>\n {observation.category && observation.category.length > 0 && (\n <ul>\n {observation.category.map((concept, index) => (\n <li key={`category-${index}`}>\n <CodeableConceptDisplay value={concept} />\n </li>\n ))}\n </ul>\n )}\n </td>\n <td>{observation.status && <StatusBadge status={observation.status} />}</td>\n </tr>\n {displayNotes && (\n <tr>\n <td colSpan={5}>\n <NoteDisplay value={observation.note} />\n </td>\n </tr>\n )}\n </>\n );\n}\n\ninterface ObservationValueDisplayProps {\n value?: Observation | ObservationComponent;\n}\n\nfunction ObservationValueDisplay(props: ObservationValueDisplayProps): JSX.Element | null {\n const obs = props.value;\n return <>{formatObservationValue(obs)}</>;\n}\n\ninterface ReferenceRangeProps {\n value?: ObservationReferenceRange[];\n}\n\nfunction ReferenceRangeDisplay(props: ReferenceRangeProps): JSX.Element | null {\n const range = props.value && props.value.length > 0 && props.value[0];\n if (!range) {\n return null;\n }\n if (range.text) {\n return <>{range.text}</>;\n }\n return <RangeDisplay value={range} />;\n}\n\n/**\n * Returns true if the observation is critical.\n * See: https://www.hl7.org/fhir/valueset-observation-interpretation.html\n * @param observation The FHIR observation.\n * @returns True if the FHIR observation is a critical value.\n */\nfunction isCritical(observation: Observation): boolean {\n const code = observation.interpretation?.[0]?.coding?.[0]?.code;\n return code === 'AA' || code === 'LL' || code === 'HH' || code === 'A';\n}\n"],"names":[],"mappings":"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"}
@@ -4,3 +4,4 @@ declare const _default: Meta<import("@storybook/react").Args>;
4
4
  export default _default;
5
5
  export declare const Simple: () => JSX.Element;
6
6
  export declare const WithCategories: () => JSX.Element;
7
+ export declare const HideNotes: () => JSX.Element;
@@ -1,13 +1,13 @@
1
- import { getReferenceString, createReference } from '@medplum/core';
1
+ import { createReference } from '@medplum/core';
2
2
  import React from 'react';
3
3
  import { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline.mjs';
4
4
 
5
5
  function EncounterTimeline(props) {
6
- return (React.createElement(ResourceTimeline, { value: props.encounter, loadTimelineResources: async (medplum, resource) => {
7
- return Promise.all([
8
- medplum.readHistory('Encounter', resource.id),
9
- medplum.search('Communication', 'encounter=' + getReferenceString(resource)),
10
- medplum.search('Media', 'encounter=' + getReferenceString(resource)),
6
+ return (React.createElement(ResourceTimeline, { value: props.encounter, loadTimelineResources: async (medplum, _resourceType, id) => {
7
+ return Promise.allSettled([
8
+ medplum.readHistory('Encounter', id),
9
+ medplum.search('Communication', 'encounter=Encounter/' + id),
10
+ medplum.search('Media', 'encounter=Encounter/' + id),
11
11
  ]);
12
12
  }, createCommunication: (resource, sender, text) => ({
13
13
  resourceType: 'Communication',
@@ -1 +1 @@
1
- {"version":3,"file":"EncounterTimeline.mjs","sources":["../../../src/EncounterTimeline/EncounterTimeline.tsx"],"sourcesContent":["import { createReference, getReferenceString, MedplumClient, ProfileResource } from '@medplum/core';\nimport { Attachment, Encounter, Reference } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline';\n\nexport interface EncounterTimelineProps {\n encounter: Encounter | Reference<Encounter>;\n}\n\nexport function EncounterTimeline(props: EncounterTimelineProps): JSX.Element {\n return (\n <ResourceTimeline\n value={props.encounter}\n loadTimelineResources={async (medplum: MedplumClient, resource: Encounter) => {\n return Promise.all([\n medplum.readHistory('Encounter', resource.id as string),\n medplum.search('Communication', 'encounter=' + getReferenceString(resource)),\n medplum.search('Media', 'encounter=' + getReferenceString(resource)),\n ]);\n }}\n createCommunication={(resource: Encounter, sender: ProfileResource, text: string) => ({\n resourceType: 'Communication',\n status: 'completed',\n encounter: createReference(resource),\n subject: resource.subject,\n sender: createReference(sender),\n sent: new Date().toISOString(),\n payload: [{ contentString: text }],\n })}\n createMedia={(resource: Encounter, operator: ProfileResource, content: Attachment) => ({\n resourceType: 'Media',\n status: 'completed',\n encounter: createReference(resource),\n subject: resource.subject,\n operator: createReference(operator),\n issued: new Date().toISOString(),\n content,\n })}\n />\n );\n}\n"],"names":[],"mappings":";;;;AASM,SAAU,iBAAiB,CAAC,KAA6B,EAAA;AAC7D,IAAA,QACE,KAAC,CAAA,aAAA,CAAA,gBAAgB,IACf,KAAK,EAAE,KAAK,CAAC,SAAS,EACtB,qBAAqB,EAAE,OAAO,OAAsB,EAAE,QAAmB,KAAI;YAC3E,OAAO,OAAO,CAAC,GAAG,CAAC;gBACjB,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAY,CAAC;gBACvD,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,YAAY,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;gBAC5E,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACrE,aAAA,CAAC,CAAC;AACL,SAAC,EACD,mBAAmB,EAAE,CAAC,QAAmB,EAAE,MAAuB,EAAE,IAAY,MAAM;AACpF,YAAA,YAAY,EAAE,eAAe;AAC7B,YAAA,MAAM,EAAE,WAAW;AACnB,YAAA,SAAS,EAAE,eAAe,CAAC,QAAQ,CAAC;YACpC,OAAO,EAAE,QAAQ,CAAC,OAAO;AACzB,YAAA,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC;AAC/B,YAAA,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AAC9B,YAAA,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AACnC,SAAA,CAAC,EACF,WAAW,EAAE,CAAC,QAAmB,EAAE,QAAyB,EAAE,OAAmB,MAAM;AACrF,YAAA,YAAY,EAAE,OAAO;AACrB,YAAA,MAAM,EAAE,WAAW;AACnB,YAAA,SAAS,EAAE,eAAe,CAAC,QAAQ,CAAC;YACpC,OAAO,EAAE,QAAQ,CAAC,OAAO;AACzB,YAAA,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC;AACnC,YAAA,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAChC,OAAO;SACR,CAAC,EAAA,CACF,EACF;AACJ;;;;"}
1
+ {"version":3,"file":"EncounterTimeline.mjs","sources":["../../../src/EncounterTimeline/EncounterTimeline.tsx"],"sourcesContent":["import { createReference, MedplumClient, ProfileResource } from '@medplum/core';\nimport { Attachment, Encounter, Reference, ResourceType } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { ResourceTimeline } from '../ResourceTimeline/ResourceTimeline';\n\nexport interface EncounterTimelineProps {\n encounter: Encounter | Reference<Encounter>;\n}\n\nexport function EncounterTimeline(props: EncounterTimelineProps): JSX.Element {\n return (\n <ResourceTimeline\n value={props.encounter}\n loadTimelineResources={async (medplum: MedplumClient, _resourceType: ResourceType, id: string) => {\n return Promise.allSettled([\n medplum.readHistory('Encounter', id),\n medplum.search('Communication', 'encounter=Encounter/' + id),\n medplum.search('Media', 'encounter=Encounter/' + id),\n ]);\n }}\n createCommunication={(resource: Encounter, sender: ProfileResource, text: string) => ({\n resourceType: 'Communication',\n status: 'completed',\n encounter: createReference(resource),\n subject: resource.subject,\n sender: createReference(sender),\n sent: new Date().toISOString(),\n payload: [{ contentString: text }],\n })}\n createMedia={(resource: Encounter, operator: ProfileResource, content: Attachment) => ({\n resourceType: 'Media',\n status: 'completed',\n encounter: createReference(resource),\n subject: resource.subject,\n operator: createReference(operator),\n issued: new Date().toISOString(),\n content,\n })}\n />\n );\n}\n"],"names":[],"mappings":";;;;AASM,SAAU,iBAAiB,CAAC,KAA6B,EAAA;IAC7D,QACE,oBAAC,gBAAgB,EAAA,EACf,KAAK,EAAE,KAAK,CAAC,SAAS,EACtB,qBAAqB,EAAE,OAAO,OAAsB,EAAE,aAA2B,EAAE,EAAU,KAAI;YAC/F,OAAO,OAAO,CAAC,UAAU,CAAC;AACxB,gBAAA,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;gBACpC,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,sBAAsB,GAAG,EAAE,CAAC;gBAC5D,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,EAAE,CAAC;AACrD,aAAA,CAAC,CAAC;AACL,SAAC,EACD,mBAAmB,EAAE,CAAC,QAAmB,EAAE,MAAuB,EAAE,IAAY,MAAM;AACpF,YAAA,YAAY,EAAE,eAAe;AAC7B,YAAA,MAAM,EAAE,WAAW;AACnB,YAAA,SAAS,EAAE,eAAe,CAAC,QAAQ,CAAC;YACpC,OAAO,EAAE,QAAQ,CAAC,OAAO;AACzB,YAAA,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC;AAC/B,YAAA,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AAC9B,YAAA,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AACnC,SAAA,CAAC,EACF,WAAW,EAAE,CAAC,QAAmB,EAAE,QAAyB,EAAE,OAAmB,MAAM;AACrF,YAAA,YAAY,EAAE,OAAO;AACrB,YAAA,MAAM,EAAE,WAAW;AACnB,YAAA,SAAS,EAAE,eAAe,CAAC,QAAQ,CAAC;YACpC,OAAO,EAAE,QAAQ,CAAC,OAAO;AACzB,YAAA,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC;AACnC,YAAA,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAChC,OAAO;SACR,CAAC,EAAA,CACF,EACF;AACJ;;;;"}
@@ -1,7 +1,7 @@
1
1
  import { Alert } from '@mantine/core';
2
2
  import { normalizeErrorString } from '@medplum/core';
3
- import { IconAlertCircle } from '@tabler/icons';
4
3
  import React from 'react';
4
+ import IconAlertCircle from '../node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs';
5
5
 
6
6
  /**
7
7
  * ErrorBoundary is a React component that handles errors in its child components.
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorBoundary.mjs","sources":["../../../src/ErrorBoundary/ErrorBoundary.tsx"],"sourcesContent":["import { Alert } from '@mantine/core';\nimport { normalizeErrorString } from '@medplum/core';\nimport { IconAlertCircle } from '@tabler/icons';\nimport React, { ErrorInfo, ReactNode } from 'react';\n\nexport interface ErrorBoundaryProps {\n children: ReactNode;\n}\n\nexport interface ErrorBoundaryState {\n error?: any;\n}\n\n/**\n * ErrorBoundary is a React component that handles errors in its child components.\n * See: https://reactjs.org/docs/error-boundaries.html\n */\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n state: ErrorBoundaryState;\n\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = {};\n }\n\n static getDerivedStateFromError(error: any): ErrorBoundaryState {\n return { error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n console.error('Uncaught error:', error, errorInfo);\n }\n\n render(): ReactNode {\n if (this.state.error) {\n return (\n <Alert icon={<IconAlertCircle size={16} />} title=\"Something went wrong\" color=\"red\">\n {normalizeErrorString(this.state.error)}\n </Alert>\n );\n }\n\n return this.props.children;\n }\n}\n"],"names":[],"mappings":";;;;;AAaA;;;AAGG;AACU,MAAA,aAAc,SAAQ,KAAK,CAAC,SAAiD,CAAA;AAGxF,IAAA,WAAA,CAAY,KAAyB,EAAA;QACnC,KAAK,CAAC,KAAK,CAAC,CAAC;AACb,QAAA,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;KACjB;IAED,OAAO,wBAAwB,CAAC,KAAU,EAAA;QACxC,OAAO,EAAE,KAAK,EAAE,CAAC;KAClB;IAED,iBAAiB,CAAC,KAAY,EAAE,SAAoB,EAAA;QAClD,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;KACpD;IAED,MAAM,GAAA;AACJ,QAAA,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;AACpB,YAAA,QACE,KAAA,CAAA,aAAA,CAAC,KAAK,EAAA,EAAC,IAAI,EAAE,KAAA,CAAA,aAAA,CAAC,eAAe,EAAA,EAAC,IAAI,EAAE,EAAE,EAAA,CAAI,EAAE,KAAK,EAAC,sBAAsB,EAAC,KAAK,EAAC,KAAK,EAAA,EACjF,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CACjC,EACR;AACH,SAAA;AAED,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;KAC5B;AACF;;;;"}
1
+ {"version":3,"file":"ErrorBoundary.mjs","sources":["../../../src/ErrorBoundary/ErrorBoundary.tsx"],"sourcesContent":["import { Alert } from '@mantine/core';\nimport { normalizeErrorString } from '@medplum/core';\nimport { IconAlertCircle } from '@tabler/icons-react';\nimport React, { ErrorInfo, ReactNode } from 'react';\n\nexport interface ErrorBoundaryProps {\n children: ReactNode;\n}\n\nexport interface ErrorBoundaryState {\n error?: any;\n}\n\n/**\n * ErrorBoundary is a React component that handles errors in its child components.\n * See: https://reactjs.org/docs/error-boundaries.html\n */\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n state: ErrorBoundaryState;\n\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = {};\n }\n\n static getDerivedStateFromError(error: any): ErrorBoundaryState {\n return { error };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo): void {\n console.error('Uncaught error:', error, errorInfo);\n }\n\n render(): ReactNode {\n if (this.state.error) {\n return (\n <Alert icon={<IconAlertCircle size={16} />} title=\"Something went wrong\" color=\"red\">\n {normalizeErrorString(this.state.error)}\n </Alert>\n );\n }\n\n return this.props.children;\n }\n}\n"],"names":[],"mappings":";;;;;AAaA;;;AAGG;AACU,MAAA,aAAc,SAAQ,KAAK,CAAC,SAAiD,CAAA;AAGxF,IAAA,WAAA,CAAY,KAAyB,EAAA;QACnC,KAAK,CAAC,KAAK,CAAC,CAAC;AACb,QAAA,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;KACjB;IAED,OAAO,wBAAwB,CAAC,KAAU,EAAA;QACxC,OAAO,EAAE,KAAK,EAAE,CAAC;KAClB;IAED,iBAAiB,CAAC,KAAY,EAAE,SAAoB,EAAA;QAClD,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;KACpD;IAED,MAAM,GAAA;AACJ,QAAA,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;AACpB,YAAA,QACE,KAAA,CAAA,aAAA,CAAC,KAAK,EAAA,EAAC,IAAI,EAAE,KAAA,CAAA,aAAA,CAAC,eAAe,EAAA,EAAC,IAAI,EAAE,EAAE,EAAA,CAAI,EAAE,KAAK,EAAC,sBAAsB,EAAC,KAAK,EAAC,KAAK,EAAA,EACjF,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CACjC,EACR;AACH,SAAA;AAED,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;KAC5B;AACF;;;;"}
@@ -35,10 +35,12 @@ function getGoogleClientId(clientId) {
35
35
  if (clientId) {
36
36
  return clientId;
37
37
  }
38
- const origin = window.location.protocol + '//' + window.location.host;
39
- const authorizedOrigins = "http://localhost:3000,http://127.0.0.1:3000,http://localhost:6006,http://127.0.0.1:6006,https://app.medplum.com,https://docs.medplum.com,https://storybook.medplum.com,https://graphiql.medplum.com,https://www.medplum.com"?.split(',') ?? [];
40
- if (authorizedOrigins.includes(origin)) {
41
- return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
38
+ if (typeof window !== 'undefined') {
39
+ const origin = window.location.protocol + '//' + window.location.host;
40
+ const authorizedOrigins = "http://localhost:3000,http://127.0.0.1:3000,http://localhost:6006,http://127.0.0.1:6006,https://app.medplum.com,https://docs.medplum.com,https://storybook.medplum.com,https://graphiql.medplum.com,https://www.medplum.com"?.split(',') ?? [];
41
+ if (authorizedOrigins.includes(origin)) {
42
+ return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
43
+ }
42
44
  }
43
45
  return undefined;
44
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleButton.mjs","sources":["../../../src/GoogleButton/GoogleButton.tsx"],"sourcesContent":["import { GoogleCredentialResponse } from '@medplum/core';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useMedplum } from '../MedplumProvider/MedplumProvider';\nimport { createScriptTag } from '../utils/script';\n\ninterface GoogleApi {\n accounts: {\n id: {\n initialize: (args: any) => void;\n renderButton: (parent: HTMLElement, args: any) => void;\n };\n };\n}\n\ndeclare const google: GoogleApi;\n\nexport interface GoogleButtonProps {\n readonly googleClientId?: string;\n readonly handleGoogleCredential: (response: GoogleCredentialResponse) => void;\n}\n\nexport function GoogleButton(props: GoogleButtonProps): JSX.Element | null {\n const medplum = useMedplum();\n const { googleClientId, handleGoogleCredential } = props;\n const parentRef = useRef<HTMLDivElement>(null);\n const [scriptLoaded, setScriptLoaded] = useState<boolean>(typeof google !== 'undefined');\n const [initialized, setInitialized] = useState<boolean>(false);\n const [buttonRendered, setButtonRendered] = useState<boolean>(false);\n\n useEffect(() => {\n if (typeof google === 'undefined') {\n createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));\n return;\n }\n\n if (!initialized) {\n google.accounts.id.initialize({\n client_id: googleClientId,\n callback: handleGoogleCredential,\n });\n setInitialized(true);\n }\n\n if (parentRef.current && !buttonRendered) {\n google.accounts.id.renderButton(parentRef.current, {});\n setButtonRendered(true);\n }\n }, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);\n\n if (!googleClientId) {\n return null;\n }\n\n return <div ref={parentRef} />;\n}\n\nexport function getGoogleClientId(clientId: string | undefined): string | undefined {\n if (clientId) {\n return clientId;\n }\n\n const origin = window.location.protocol + '//' + window.location.host;\n const authorizedOrigins = process.env.GOOGLE_AUTH_ORIGINS?.split(',') ?? [];\n if (authorizedOrigins.includes(origin)) {\n return process.env.GOOGLE_CLIENT_ID;\n }\n\n return undefined;\n}\n"],"names":[],"mappings":";;;;AAqBM,SAAU,YAAY,CAAC,KAAwB,EAAA;AACnD,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;AAC7B,IAAA,MAAM,EAAE,cAAc,EAAE,sBAAsB,EAAE,GAAG,KAAK,CAAC;AACzD,IAAA,MAAM,SAAS,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;AAC/C,IAAA,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAU,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC;IACzF,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC/D,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAErE,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;YACjC,eAAe,CAAC,wCAAwC,EAAE,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;YACvF,OAAO;AACR,SAAA;QAED,IAAI,CAAC,WAAW,EAAE;AAChB,YAAA,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC;AAC5B,gBAAA,SAAS,EAAE,cAAc;AACzB,gBAAA,QAAQ,EAAE,sBAAsB;AACjC,aAAA,CAAC,CAAC;YACH,cAAc,CAAC,IAAI,CAAC,CAAC;AACtB,SAAA;AAED,QAAA,IAAI,SAAS,CAAC,OAAO,IAAI,CAAC,cAAc,EAAE;AACxC,YAAA,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACvD,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACzB,SAAA;AACH,KAAC,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAE5G,IAAI,CAAC,cAAc,EAAE;AACnB,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;AAED,IAAA,OAAO,KAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,GAAG,EAAE,SAAS,GAAI,CAAC;AACjC,CAAC;AAEK,SAAU,iBAAiB,CAAC,QAA4B,EAAA;AAC5D,IAAA,IAAI,QAAQ,EAAE;AACZ,QAAA,OAAO,QAAQ,CAAC;AACjB,KAAA;AAED,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;AACtE,IAAA,MAAM,iBAAiB,GAAG,6NAA+B,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;AAC5E,IAAA,IAAI,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AACtC,QAAA,OAAO,0EAA4B,CAAC;AACrC,KAAA;AAED,IAAA,OAAO,SAAS,CAAC;AACnB;;;;"}
1
+ {"version":3,"file":"GoogleButton.mjs","sources":["../../../src/GoogleButton/GoogleButton.tsx"],"sourcesContent":["import { GoogleCredentialResponse } from '@medplum/core';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useMedplum } from '../MedplumProvider/MedplumProvider';\nimport { createScriptTag } from '../utils/script';\n\ninterface GoogleApi {\n accounts: {\n id: {\n initialize: (args: any) => void;\n renderButton: (parent: HTMLElement, args: any) => void;\n };\n };\n}\n\ndeclare const google: GoogleApi;\n\nexport interface GoogleButtonProps {\n readonly googleClientId?: string;\n readonly handleGoogleCredential: (response: GoogleCredentialResponse) => void;\n}\n\nexport function GoogleButton(props: GoogleButtonProps): JSX.Element | null {\n const medplum = useMedplum();\n const { googleClientId, handleGoogleCredential } = props;\n const parentRef = useRef<HTMLDivElement>(null);\n const [scriptLoaded, setScriptLoaded] = useState<boolean>(typeof google !== 'undefined');\n const [initialized, setInitialized] = useState<boolean>(false);\n const [buttonRendered, setButtonRendered] = useState<boolean>(false);\n\n useEffect(() => {\n if (typeof google === 'undefined') {\n createScriptTag('https://accounts.google.com/gsi/client', () => setScriptLoaded(true));\n return;\n }\n\n if (!initialized) {\n google.accounts.id.initialize({\n client_id: googleClientId,\n callback: handleGoogleCredential,\n });\n setInitialized(true);\n }\n\n if (parentRef.current && !buttonRendered) {\n google.accounts.id.renderButton(parentRef.current, {});\n setButtonRendered(true);\n }\n }, [medplum, googleClientId, initialized, scriptLoaded, parentRef, buttonRendered, handleGoogleCredential]);\n\n if (!googleClientId) {\n return null;\n }\n\n return <div ref={parentRef} />;\n}\n\nexport function getGoogleClientId(clientId: string | undefined): string | undefined {\n if (clientId) {\n return clientId;\n }\n\n if (typeof window !== 'undefined') {\n const origin = window.location.protocol + '//' + window.location.host;\n const authorizedOrigins = process.env.GOOGLE_AUTH_ORIGINS?.split(',') ?? [];\n if (authorizedOrigins.includes(origin)) {\n return process.env.GOOGLE_CLIENT_ID;\n }\n }\n\n return undefined;\n}\n"],"names":[],"mappings":";;;;AAqBM,SAAU,YAAY,CAAC,KAAwB,EAAA;AACnD,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;AAC7B,IAAA,MAAM,EAAE,cAAc,EAAE,sBAAsB,EAAE,GAAG,KAAK,CAAC;AACzD,IAAA,MAAM,SAAS,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;AAC/C,IAAA,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAU,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC;IACzF,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC/D,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAErE,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;YACjC,eAAe,CAAC,wCAAwC,EAAE,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;YACvF,OAAO;AACR,SAAA;QAED,IAAI,CAAC,WAAW,EAAE;AAChB,YAAA,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC;AAC5B,gBAAA,SAAS,EAAE,cAAc;AACzB,gBAAA,QAAQ,EAAE,sBAAsB;AACjC,aAAA,CAAC,CAAC;YACH,cAAc,CAAC,IAAI,CAAC,CAAC;AACtB,SAAA;AAED,QAAA,IAAI,SAAS,CAAC,OAAO,IAAI,CAAC,cAAc,EAAE;AACxC,YAAA,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACvD,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACzB,SAAA;AACH,KAAC,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAE5G,IAAI,CAAC,cAAc,EAAE;AACnB,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;AAED,IAAA,OAAO,KAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,GAAG,EAAE,SAAS,GAAI,CAAC;AACjC,CAAC;AAEK,SAAU,iBAAiB,CAAC,QAA4B,EAAA;AAC5D,IAAA,IAAI,QAAQ,EAAE;AACZ,QAAA,OAAO,QAAQ,CAAC;AACjB,KAAA;AAED,IAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACjC,QAAA,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;AACtE,QAAA,MAAM,iBAAiB,GAAG,6NAA+B,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;AAC5E,QAAA,IAAI,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AACtC,YAAA,OAAO,0EAA4B,CAAC;AACrC,SAAA;AACF,KAAA;AAED,IAAA,OAAO,SAAS,CAAC;AACnB;;;;"}
@@ -1,10 +1,10 @@
1
1
  import { Anchor } from '@mantine/core';
2
2
  import React from 'react';
3
- import { useNavigate } from 'react-router-dom';
3
+ import { useMedplumNavigate } from '../MedplumProvider/MedplumProvider.mjs';
4
4
  import { killEvent } from '../utils/dom.mjs';
5
5
 
6
6
  function MedplumLink(props) {
7
- const navigate = useNavigate();
7
+ const navigate = useMedplumNavigate();
8
8
  const { to, suffix, label, onClick, children, ...rest } = props;
9
9
  let href = getHref(to);
10
10
  if (suffix) {
@@ -1 +1 @@
1
- {"version":3,"file":"MedplumLink.mjs","sources":["../../../src/MedplumLink/MedplumLink.tsx"],"sourcesContent":["import { Anchor, TextProps } from '@mantine/core';\nimport { Reference, Resource } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { killEvent } from '../utils/dom';\n\nexport interface MedplumLinkProps extends TextProps {\n to?: Resource | Reference | string;\n suffix?: string;\n label?: string;\n onClick?: () => void;\n children: React.ReactNode;\n}\n\nexport function MedplumLink(props: MedplumLinkProps): JSX.Element {\n const navigate = useNavigate();\n const { to, suffix, label, onClick, children, ...rest } = props;\n\n let href = getHref(to);\n if (suffix) {\n href += '/' + suffix;\n }\n\n return (\n <Anchor\n href={href}\n aria-label={label}\n onClick={(e: React.SyntheticEvent) => {\n killEvent(e);\n if (onClick) {\n onClick();\n } else if (to) {\n navigate(href);\n }\n }}\n {...rest}\n >\n {children}\n </Anchor>\n );\n}\n\nfunction getHref(to: Resource | Reference | string | undefined): string {\n if (to) {\n if (typeof to === 'string') {\n return getStringHref(to);\n } else if ('resourceType' in to) {\n return getResourceHref(to);\n } else if ('reference' in to) {\n return getReferenceHref(to);\n }\n }\n return '#';\n}\n\nfunction getStringHref(to: string): string {\n if (to.startsWith('http://') || to.startsWith('https://') || to.startsWith('/')) {\n return to;\n }\n return '/' + to;\n}\n\nfunction getResourceHref(to: Resource): string {\n return `/${to.resourceType}/${to.id}`;\n}\n\nfunction getReferenceHref(to: Reference): string {\n return `/${to.reference}`;\n}\n"],"names":[],"mappings":";;;;;AAcM,SAAU,WAAW,CAAC,KAAuB,EAAA;AACjD,IAAA,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;AAC/B,IAAA,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;AAEhE,IAAA,IAAI,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;AACvB,IAAA,IAAI,MAAM,EAAE;AACV,QAAA,IAAI,IAAI,GAAG,GAAG,MAAM,CAAC;AACtB,KAAA;AAED,IAAA,QACE,KAAA,CAAA,aAAA,CAAC,MAAM,EAAA,EACL,IAAI,EAAE,IAAI,EACE,YAAA,EAAA,KAAK,EACjB,OAAO,EAAE,CAAC,CAAuB,KAAI;YACnC,SAAS,CAAC,CAAC,CAAC,CAAC;AACb,YAAA,IAAI,OAAO,EAAE;AACX,gBAAA,OAAO,EAAE,CAAC;AACX,aAAA;AAAM,iBAAA,IAAI,EAAE,EAAE;gBACb,QAAQ,CAAC,IAAI,CAAC,CAAC;AAChB,aAAA;AACH,SAAC,KACG,IAAI,EAAA,EAEP,QAAQ,CACF,EACT;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,EAA6C,EAAA;AAC5D,IAAA,IAAI,EAAE,EAAE;AACN,QAAA,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE;AAC1B,YAAA,OAAO,aAAa,CAAC,EAAE,CAAC,CAAC;AAC1B,SAAA;aAAM,IAAI,cAAc,IAAI,EAAE,EAAE;AAC/B,YAAA,OAAO,eAAe,CAAC,EAAE,CAAC,CAAC;AAC5B,SAAA;aAAM,IAAI,WAAW,IAAI,EAAE,EAAE;AAC5B,YAAA,OAAO,gBAAgB,CAAC,EAAE,CAAC,CAAC;AAC7B,SAAA;AACF,KAAA;AACD,IAAA,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CAAC,EAAU,EAAA;IAC/B,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AAC/E,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;IACD,OAAO,GAAG,GAAG,EAAE,CAAC;AAClB,CAAC;AAED,SAAS,eAAe,CAAC,EAAY,EAAA;IACnC,OAAO,CAAA,CAAA,EAAI,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,CAAA,CAAE,CAAC;AACxC,CAAC;AAED,SAAS,gBAAgB,CAAC,EAAa,EAAA;AACrC,IAAA,OAAO,CAAI,CAAA,EAAA,EAAE,CAAC,SAAS,EAAE,CAAC;AAC5B;;;;"}
1
+ {"version":3,"file":"MedplumLink.mjs","sources":["../../../src/MedplumLink/MedplumLink.tsx"],"sourcesContent":["import { Anchor, TextProps } from '@mantine/core';\nimport { Reference, Resource } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { useMedplumNavigate } from '../MedplumProvider/MedplumProvider';\nimport { killEvent } from '../utils/dom';\n\nexport interface MedplumLinkProps extends TextProps {\n to?: Resource | Reference | string;\n suffix?: string;\n label?: string;\n onClick?: () => void;\n children: React.ReactNode;\n}\n\nexport function MedplumLink(props: MedplumLinkProps): JSX.Element {\n const navigate = useMedplumNavigate();\n const { to, suffix, label, onClick, children, ...rest } = props;\n\n let href = getHref(to);\n if (suffix) {\n href += '/' + suffix;\n }\n\n return (\n <Anchor\n href={href}\n aria-label={label}\n onClick={(e: React.SyntheticEvent) => {\n killEvent(e);\n if (onClick) {\n onClick();\n } else if (to) {\n navigate(href);\n }\n }}\n {...rest}\n >\n {children}\n </Anchor>\n );\n}\n\nfunction getHref(to: Resource | Reference | string | undefined): string {\n if (to) {\n if (typeof to === 'string') {\n return getStringHref(to);\n } else if ('resourceType' in to) {\n return getResourceHref(to);\n } else if ('reference' in to) {\n return getReferenceHref(to);\n }\n }\n return '#';\n}\n\nfunction getStringHref(to: string): string {\n if (to.startsWith('http://') || to.startsWith('https://') || to.startsWith('/')) {\n return to;\n }\n return '/' + to;\n}\n\nfunction getResourceHref(to: Resource): string {\n return `/${to.resourceType}/${to.id}`;\n}\n\nfunction getReferenceHref(to: Reference): string {\n return `/${to.reference}`;\n}\n"],"names":[],"mappings":";;;;;AAcM,SAAU,WAAW,CAAC,KAAuB,EAAA;AACjD,IAAA,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAC;AACtC,IAAA,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;AAEhE,IAAA,IAAI,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;AACvB,IAAA,IAAI,MAAM,EAAE;AACV,QAAA,IAAI,IAAI,GAAG,GAAG,MAAM,CAAC;AACtB,KAAA;AAED,IAAA,QACE,KAAA,CAAA,aAAA,CAAC,MAAM,EAAA,EACL,IAAI,EAAE,IAAI,EACE,YAAA,EAAA,KAAK,EACjB,OAAO,EAAE,CAAC,CAAuB,KAAI;YACnC,SAAS,CAAC,CAAC,CAAC,CAAC;AACb,YAAA,IAAI,OAAO,EAAE;AACX,gBAAA,OAAO,EAAE,CAAC;AACX,aAAA;AAAM,iBAAA,IAAI,EAAE,EAAE;gBACb,QAAQ,CAAC,IAAI,CAAC,CAAC;AAChB,aAAA;AACH,SAAC,KACG,IAAI,EAAA,EAEP,QAAQ,CACF,EACT;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,EAA6C,EAAA;AAC5D,IAAA,IAAI,EAAE,EAAE;AACN,QAAA,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE;AAC1B,YAAA,OAAO,aAAa,CAAC,EAAE,CAAC,CAAC;AAC1B,SAAA;aAAM,IAAI,cAAc,IAAI,EAAE,EAAE;AAC/B,YAAA,OAAO,eAAe,CAAC,EAAE,CAAC,CAAC;AAC5B,SAAA;aAAM,IAAI,WAAW,IAAI,EAAE,EAAE;AAC5B,YAAA,OAAO,gBAAgB,CAAC,EAAE,CAAC,CAAC;AAC7B,SAAA;AACF,KAAA;AACD,IAAA,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,aAAa,CAAC,EAAU,EAAA;IAC/B,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AAC/E,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;IACD,OAAO,GAAG,GAAG,EAAE,CAAC;AAClB,CAAC;AAED,SAAS,eAAe,CAAC,EAAY,EAAA;IACnC,OAAO,CAAA,CAAA,EAAI,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,CAAA,CAAE,CAAC;AACxC,CAAC;AAED,SAAS,gBAAgB,CAAC,EAAa,EAAA;AACrC,IAAA,OAAO,CAAI,CAAA,EAAA,EAAE,CAAC,SAAS,EAAE,CAAC;AAC5B;;;;"}
@@ -1,11 +1,14 @@
1
1
  import { MedplumClient, ProfileResource } from '@medplum/core';
2
2
  import React from 'react';
3
+ export type MepdlumNavigateFunction = (path: string) => void;
3
4
  export interface MedplumProviderProps {
4
5
  medplum: MedplumClient;
6
+ navigate?: MepdlumNavigateFunction;
5
7
  children: React.ReactNode;
6
8
  }
7
9
  export interface MedplumContext {
8
10
  medplum: MedplumClient;
11
+ navigate: MepdlumNavigateFunction;
9
12
  profile?: ProfileResource;
10
13
  loading: boolean;
11
14
  }
@@ -26,6 +29,11 @@ export declare function useMedplumContext(): MedplumContext;
26
29
  * This is a shortcut for useMedplumContext().medplum.
27
30
  */
28
31
  export declare function useMedplum(): MedplumClient;
32
+ /**
33
+ * Returns the Medplum navigate function.
34
+ * @returns The Medplum navigate function.
35
+ */
36
+ export declare function useMedplumNavigate(): MepdlumNavigateFunction;
29
37
  /**
30
38
  * Returns the current Medplum user profile (if signed in).
31
39
  * This is a shortcut for useMedplumContext().profile.
@@ -10,6 +10,7 @@ const reactContext = createContext(undefined);
10
10
  */
11
11
  function MedplumProvider(props) {
12
12
  const medplum = props.medplum;
13
+ const navigate = props.navigate || defaultNavigate;
13
14
  const [state, setState] = useState({
14
15
  profile: medplum.getProfile(),
15
16
  loading: false,
@@ -27,6 +28,7 @@ function MedplumProvider(props) {
27
28
  const medplumContext = {
28
29
  ...state,
29
30
  medplum,
31
+ navigate,
30
32
  };
31
33
  return React.createElement(reactContext.Provider, { value: medplumContext }, props.children);
32
34
  }
@@ -43,6 +45,13 @@ function useMedplumContext() {
43
45
  function useMedplum() {
44
46
  return useMedplumContext().medplum;
45
47
  }
48
+ /**
49
+ * Returns the Medplum navigate function.
50
+ * @returns The Medplum navigate function.
51
+ */
52
+ function useMedplumNavigate() {
53
+ return useMedplumContext().navigate;
54
+ }
46
55
  /**
47
56
  * Returns the current Medplum user profile (if signed in).
48
57
  * This is a shortcut for useMedplumContext().profile.
@@ -51,6 +60,13 @@ function useMedplum() {
51
60
  function useMedplumProfile() {
52
61
  return useMedplumContext().profile;
53
62
  }
63
+ /**
64
+ * The default "navigate" function which simply uses window.location.href.
65
+ * @param path The path to navigate to.
66
+ */
67
+ function defaultNavigate(path) {
68
+ window.location.assign(path);
69
+ }
54
70
 
55
- export { MedplumProvider, useMedplum, useMedplumContext, useMedplumProfile };
71
+ export { MedplumProvider, useMedplum, useMedplumContext, useMedplumNavigate, useMedplumProfile };
56
72
  //# sourceMappingURL=MedplumProvider.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"MedplumProvider.mjs","sources":["../../../src/MedplumProvider/MedplumProvider.tsx"],"sourcesContent":["import { MedplumClient, ProfileResource } from '@medplum/core';\nimport React, { createContext, useContext, useEffect, useState } from 'react';\n\nconst reactContext = createContext(undefined as MedplumContext | undefined);\n\nexport interface MedplumProviderProps {\n medplum: MedplumClient;\n children: React.ReactNode;\n}\n\nexport interface MedplumContext {\n medplum: MedplumClient;\n profile?: ProfileResource;\n loading: boolean;\n}\n\n/**\n * The MedplumProvider component provides Medplum context state.\n *\n * Medplum context includes:\n * 1) medplum - Medplum client library\n * 2) profile - The current user profile (if signed in)\n */\nexport function MedplumProvider(props: MedplumProviderProps): JSX.Element {\n const medplum = props.medplum;\n\n const [state, setState] = useState({\n profile: medplum.getProfile(),\n loading: false,\n });\n\n useEffect(() => {\n function eventListener(): void {\n setState({\n ...state,\n profile: medplum.getProfile(),\n });\n }\n\n medplum.addEventListener('change', eventListener);\n return () => medplum.removeEventListeneer('change', eventListener);\n }, [medplum, state]);\n\n const medplumContext = {\n ...state,\n medplum,\n };\n\n return <reactContext.Provider value={medplumContext}>{props.children}</reactContext.Provider>;\n}\n\n/**\n * Returns the MedplumContext instance.\n */\nexport function useMedplumContext(): MedplumContext {\n return useContext(reactContext) as MedplumContext;\n}\n\n/**\n * Returns the MedplumClient instance.\n * This is a shortcut for useMedplumContext().medplum.\n */\nexport function useMedplum(): MedplumClient {\n return useMedplumContext().medplum;\n}\n\n/**\n * Returns the current Medplum user profile (if signed in).\n * This is a shortcut for useMedplumContext().profile.\n * @returns The current user profile.\n */\nexport function useMedplumProfile(): ProfileResource | undefined {\n return useMedplumContext().profile;\n}\n"],"names":[],"mappings":";;AAGA,MAAM,YAAY,GAAG,aAAa,CAAC,SAAuC,CAAC,CAAC;AAa5E;;;;;;AAMG;AACG,SAAU,eAAe,CAAC,KAA2B,EAAA;AACzD,IAAA,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;AAE9B,IAAA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC;AACjC,QAAA,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;AAC7B,QAAA,OAAO,EAAE,KAAK;AACf,KAAA,CAAC,CAAC;IAEH,SAAS,CAAC,MAAK;AACb,QAAA,SAAS,aAAa,GAAA;AACpB,YAAA,QAAQ,CAAC;AACP,gBAAA,GAAG,KAAK;AACR,gBAAA,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;AAC9B,aAAA,CAAC,CAAC;SACJ;AAED,QAAA,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAClD,OAAO,MAAM,OAAO,CAAC,oBAAoB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AACrE,KAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;AAErB,IAAA,MAAM,cAAc,GAAG;AACrB,QAAA,GAAG,KAAK;QACR,OAAO;KACR,CAAC;AAEF,IAAA,OAAO,KAAC,CAAA,aAAA,CAAA,YAAY,CAAC,QAAQ,EAAC,EAAA,KAAK,EAAE,cAAc,EAAG,EAAA,KAAK,CAAC,QAAQ,CAAyB,CAAC;AAChG,CAAC;AAED;;AAEG;SACa,iBAAiB,GAAA;AAC/B,IAAA,OAAO,UAAU,CAAC,YAAY,CAAmB,CAAC;AACpD,CAAC;AAED;;;AAGG;SACa,UAAU,GAAA;AACxB,IAAA,OAAO,iBAAiB,EAAE,CAAC,OAAO,CAAC;AACrC,CAAC;AAED;;;;AAIG;SACa,iBAAiB,GAAA;AAC/B,IAAA,OAAO,iBAAiB,EAAE,CAAC,OAAO,CAAC;AACrC;;;;"}
1
+ {"version":3,"file":"MedplumProvider.mjs","sources":["../../../src/MedplumProvider/MedplumProvider.tsx"],"sourcesContent":["import { MedplumClient, ProfileResource } from '@medplum/core';\nimport React, { createContext, useContext, useEffect, useState } from 'react';\n\nconst reactContext = createContext(undefined as MedplumContext | undefined);\n\nexport type MepdlumNavigateFunction = (path: string) => void;\n\nexport interface MedplumProviderProps {\n medplum: MedplumClient;\n navigate?: MepdlumNavigateFunction;\n children: React.ReactNode;\n}\n\nexport interface MedplumContext {\n medplum: MedplumClient;\n navigate: MepdlumNavigateFunction;\n profile?: ProfileResource;\n loading: boolean;\n}\n\n/**\n * The MedplumProvider component provides Medplum context state.\n *\n * Medplum context includes:\n * 1) medplum - Medplum client library\n * 2) profile - The current user profile (if signed in)\n */\nexport function MedplumProvider(props: MedplumProviderProps): JSX.Element {\n const medplum = props.medplum;\n const navigate = props.navigate || defaultNavigate;\n\n const [state, setState] = useState({\n profile: medplum.getProfile(),\n loading: false,\n });\n\n useEffect(() => {\n function eventListener(): void {\n setState({\n ...state,\n profile: medplum.getProfile(),\n });\n }\n\n medplum.addEventListener('change', eventListener);\n return () => medplum.removeEventListeneer('change', eventListener);\n }, [medplum, state]);\n\n const medplumContext = {\n ...state,\n medplum,\n navigate,\n };\n\n return <reactContext.Provider value={medplumContext}>{props.children}</reactContext.Provider>;\n}\n\n/**\n * Returns the MedplumContext instance.\n */\nexport function useMedplumContext(): MedplumContext {\n return useContext(reactContext) as MedplumContext;\n}\n\n/**\n * Returns the MedplumClient instance.\n * This is a shortcut for useMedplumContext().medplum.\n */\nexport function useMedplum(): MedplumClient {\n return useMedplumContext().medplum;\n}\n\n/**\n * Returns the Medplum navigate function.\n * @returns The Medplum navigate function.\n */\nexport function useMedplumNavigate(): MepdlumNavigateFunction {\n return useMedplumContext().navigate;\n}\n\n/**\n * Returns the current Medplum user profile (if signed in).\n * This is a shortcut for useMedplumContext().profile.\n * @returns The current user profile.\n */\nexport function useMedplumProfile(): ProfileResource | undefined {\n return useMedplumContext().profile;\n}\n\n/**\n * The default \"navigate\" function which simply uses window.location.href.\n * @param path The path to navigate to.\n */\nfunction defaultNavigate(path: string): void {\n window.location.assign(path);\n}\n"],"names":[],"mappings":";;AAGA,MAAM,YAAY,GAAG,aAAa,CAAC,SAAuC,CAAC,CAAC;AAiB5E;;;;;;AAMG;AACG,SAAU,eAAe,CAAC,KAA2B,EAAA;AACzD,IAAA,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;AAC9B,IAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,eAAe,CAAC;AAEnD,IAAA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC;AACjC,QAAA,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;AAC7B,QAAA,OAAO,EAAE,KAAK;AACf,KAAA,CAAC,CAAC;IAEH,SAAS,CAAC,MAAK;AACb,QAAA,SAAS,aAAa,GAAA;AACpB,YAAA,QAAQ,CAAC;AACP,gBAAA,GAAG,KAAK;AACR,gBAAA,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;AAC9B,aAAA,CAAC,CAAC;SACJ;AAED,QAAA,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAClD,OAAO,MAAM,OAAO,CAAC,oBAAoB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AACrE,KAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;AAErB,IAAA,MAAM,cAAc,GAAG;AACrB,QAAA,GAAG,KAAK;QACR,OAAO;QACP,QAAQ;KACT,CAAC;AAEF,IAAA,OAAO,KAAC,CAAA,aAAA,CAAA,YAAY,CAAC,QAAQ,EAAC,EAAA,KAAK,EAAE,cAAc,EAAG,EAAA,KAAK,CAAC,QAAQ,CAAyB,CAAC;AAChG,CAAC;AAED;;AAEG;SACa,iBAAiB,GAAA;AAC/B,IAAA,OAAO,UAAU,CAAC,YAAY,CAAmB,CAAC;AACpD,CAAC;AAED;;;AAGG;SACa,UAAU,GAAA;AACxB,IAAA,OAAO,iBAAiB,EAAE,CAAC,OAAO,CAAC;AACrC,CAAC;AAED;;;AAGG;SACa,kBAAkB,GAAA;AAChC,IAAA,OAAO,iBAAiB,EAAE,CAAC,QAAQ,CAAC;AACtC,CAAC;AAED;;;;AAIG;SACa,iBAAiB,GAAA;AAC/B,IAAA,OAAO,iBAAiB,EAAE,CAAC,OAAO,CAAC;AACrC,CAAC;AAED;;;AAGG;AACH,SAAS,eAAe,CAAC,IAAY,EAAA;AACnC,IAAA,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC/B;;;;"}
@@ -1,6 +1,6 @@
1
1
  import { NativeSelect, TextInput } from '@mantine/core';
2
- import { IconCurrencyDollar } from '@tabler/icons';
3
2
  import React, { useState, useCallback } from 'react';
3
+ import IconCurrencyDollar from '../node_modules/@tabler/icons-react/dist/esm/icons/IconCurrencyDollar.mjs';
4
4
 
5
5
  /*
6
6
  * Based on: https://github.com/mantinedev/ui.mantine.dev/blob/master/components/CurrencyInput/CurrencyInput.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"MoneyInput.mjs","sources":["../../../src/MoneyInput/MoneyInput.tsx"],"sourcesContent":["import { NativeSelect, TextInput } from '@mantine/core';\nimport { Money } from '@medplum/fhirtypes';\nimport { IconCurrencyDollar } from '@tabler/icons';\nimport React, { useCallback, useState } from 'react';\n\n/*\n * Based on: https://github.com/mantinedev/ui.mantine.dev/blob/master/components/CurrencyInput/CurrencyInput.tsx\n */\n\n/**\n * List of currencies.\n *\n * Full list of currencies:\n * https://www.hl7.org/fhir/valueset-currencies.html\n *\n * Latest browsers can report list of supported currencies, but it's not widely supported:\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/supportedValuesOf\n *\n * Using a short list for simplicity for now.\n */\nconst data = ['USD', 'EUR', 'CAD', 'GBP', 'AUD'];\n\nexport interface MoneyInputProps {\n name: string;\n label?: string;\n placeholder?: string;\n defaultValue?: Money;\n onChange?: (value: Money) => void;\n}\n\nexport function MoneyInput(props: MoneyInputProps): JSX.Element {\n const { onChange } = props;\n const [value, setValue] = useState(props.defaultValue);\n\n const setValueWrapper = useCallback(\n (newValue: Money): void => {\n setValue(newValue);\n if (onChange) {\n onChange(newValue);\n }\n },\n [onChange]\n );\n\n const handleCurrencyChange = useCallback(\n (e: React.ChangeEvent<HTMLSelectElement>) => {\n setValueWrapper({\n ...value,\n currency: e.currentTarget.value,\n });\n },\n [value, setValueWrapper]\n );\n\n const handleValueChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n setValueWrapper({\n ...value,\n value: e.currentTarget.valueAsNumber,\n });\n },\n [value, setValueWrapper]\n );\n\n const select = (\n <NativeSelect\n defaultValue={value?.currency}\n data={data}\n styles={{\n input: {\n fontWeight: 500,\n borderTopLeftRadius: 0,\n borderBottomLeftRadius: 0,\n width: 92,\n },\n }}\n onChange={handleCurrencyChange}\n />\n );\n\n return (\n <TextInput\n type=\"number\"\n label={props.label}\n placeholder={props.placeholder || 'Value'}\n defaultValue={value?.value?.toString() || 'USD'}\n icon={<IconCurrencyDollar size={14} />}\n rightSection={select}\n rightSectionWidth={92}\n onChange={handleValueChange}\n />\n );\n}\n"],"names":[],"mappings":";;;;AAKA;;AAEG;AAEH;;;;;;;;;;AAUG;AACH,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAU3C,SAAU,UAAU,CAAC,KAAsB,EAAA;AAC/C,IAAA,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;AAC3B,IAAA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AAEvD,IAAA,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,QAAe,KAAU;QACxB,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACnB,QAAA,IAAI,QAAQ,EAAE;YACZ,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACpB,SAAA;AACH,KAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;AAEF,IAAA,MAAM,oBAAoB,GAAG,WAAW,CACtC,CAAC,CAAuC,KAAI;AAC1C,QAAA,eAAe,CAAC;AACd,YAAA,GAAG,KAAK;AACR,YAAA,QAAQ,EAAE,CAAC,CAAC,aAAa,CAAC,KAAK;AAChC,SAAA,CAAC,CAAC;AACL,KAAC,EACD,CAAC,KAAK,EAAE,eAAe,CAAC,CACzB,CAAC;AAEF,IAAA,MAAM,iBAAiB,GAAG,WAAW,CACnC,CAAC,CAAsC,KAAI;AACzC,QAAA,eAAe,CAAC;AACd,YAAA,GAAG,KAAK;AACR,YAAA,KAAK,EAAE,CAAC,CAAC,aAAa,CAAC,aAAa;AACrC,SAAA,CAAC,CAAC;AACL,KAAC,EACD,CAAC,KAAK,EAAE,eAAe,CAAC,CACzB,CAAC;AAEF,IAAA,MAAM,MAAM,IACV,KAAC,CAAA,aAAA,CAAA,YAAY,IACX,YAAY,EAAE,KAAK,EAAE,QAAQ,EAC7B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE;AACN,YAAA,KAAK,EAAE;AACL,gBAAA,UAAU,EAAE,GAAG;AACf,gBAAA,mBAAmB,EAAE,CAAC;AACtB,gBAAA,sBAAsB,EAAE,CAAC;AACzB,gBAAA,KAAK,EAAE,EAAE;AACV,aAAA;AACF,SAAA,EACD,QAAQ,EAAE,oBAAoB,EAAA,CAC9B,CACH,CAAC;IAEF,QACE,KAAC,CAAA,aAAA,CAAA,SAAS,EACR,EAAA,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,OAAO,EACzC,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,KAAK,EAC/C,IAAI,EAAE,KAAC,CAAA,aAAA,CAAA,kBAAkB,EAAC,EAAA,IAAI,EAAE,EAAE,EAAI,CAAA,EACtC,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,EAAE,EACrB,QAAQ,EAAE,iBAAiB,EAC3B,CAAA,EACF;AACJ;;;;"}
1
+ {"version":3,"file":"MoneyInput.mjs","sources":["../../../src/MoneyInput/MoneyInput.tsx"],"sourcesContent":["import { NativeSelect, TextInput } from '@mantine/core';\nimport { Money } from '@medplum/fhirtypes';\nimport { IconCurrencyDollar } from '@tabler/icons-react';\nimport React, { useCallback, useState } from 'react';\n\n/*\n * Based on: https://github.com/mantinedev/ui.mantine.dev/blob/master/components/CurrencyInput/CurrencyInput.tsx\n */\n\n/**\n * List of currencies.\n *\n * Full list of currencies:\n * https://www.hl7.org/fhir/valueset-currencies.html\n *\n * Latest browsers can report list of supported currencies, but it's not widely supported:\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/supportedValuesOf\n *\n * Using a short list for simplicity for now.\n */\nconst data = ['USD', 'EUR', 'CAD', 'GBP', 'AUD'];\n\nexport interface MoneyInputProps {\n name: string;\n label?: string;\n placeholder?: string;\n defaultValue?: Money;\n onChange?: (value: Money) => void;\n}\n\nexport function MoneyInput(props: MoneyInputProps): JSX.Element {\n const { onChange } = props;\n const [value, setValue] = useState(props.defaultValue);\n\n const setValueWrapper = useCallback(\n (newValue: Money): void => {\n setValue(newValue);\n if (onChange) {\n onChange(newValue);\n }\n },\n [onChange]\n );\n\n const handleCurrencyChange = useCallback(\n (e: React.ChangeEvent<HTMLSelectElement>) => {\n setValueWrapper({\n ...value,\n currency: e.currentTarget.value,\n });\n },\n [value, setValueWrapper]\n );\n\n const handleValueChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n setValueWrapper({\n ...value,\n value: e.currentTarget.valueAsNumber,\n });\n },\n [value, setValueWrapper]\n );\n\n const select = (\n <NativeSelect\n defaultValue={value?.currency}\n data={data}\n styles={{\n input: {\n fontWeight: 500,\n borderTopLeftRadius: 0,\n borderBottomLeftRadius: 0,\n width: 92,\n },\n }}\n onChange={handleCurrencyChange}\n />\n );\n\n return (\n <TextInput\n type=\"number\"\n label={props.label}\n placeholder={props.placeholder || 'Value'}\n defaultValue={value?.value?.toString() || 'USD'}\n icon={<IconCurrencyDollar size={14} />}\n rightSection={select}\n rightSectionWidth={92}\n onChange={handleValueChange}\n />\n );\n}\n"],"names":[],"mappings":";;;;AAKA;;AAEG;AAEH;;;;;;;;;;AAUG;AACH,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAU3C,SAAU,UAAU,CAAC,KAAsB,EAAA;AAC/C,IAAA,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;AAC3B,IAAA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AAEvD,IAAA,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,QAAe,KAAU;QACxB,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACnB,QAAA,IAAI,QAAQ,EAAE;YACZ,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACpB,SAAA;AACH,KAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;AAEF,IAAA,MAAM,oBAAoB,GAAG,WAAW,CACtC,CAAC,CAAuC,KAAI;AAC1C,QAAA,eAAe,CAAC;AACd,YAAA,GAAG,KAAK;AACR,YAAA,QAAQ,EAAE,CAAC,CAAC,aAAa,CAAC,KAAK;AAChC,SAAA,CAAC,CAAC;AACL,KAAC,EACD,CAAC,KAAK,EAAE,eAAe,CAAC,CACzB,CAAC;AAEF,IAAA,MAAM,iBAAiB,GAAG,WAAW,CACnC,CAAC,CAAsC,KAAI;AACzC,QAAA,eAAe,CAAC;AACd,YAAA,GAAG,KAAK;AACR,YAAA,KAAK,EAAE,CAAC,CAAC,aAAa,CAAC,aAAa;AACrC,SAAA,CAAC,CAAC;AACL,KAAC,EACD,CAAC,KAAK,EAAE,eAAe,CAAC,CACzB,CAAC;AAEF,IAAA,MAAM,MAAM,IACV,KAAC,CAAA,aAAA,CAAA,YAAY,IACX,YAAY,EAAE,KAAK,EAAE,QAAQ,EAC7B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE;AACN,YAAA,KAAK,EAAE;AACL,gBAAA,UAAU,EAAE,GAAG;AACf,gBAAA,mBAAmB,EAAE,CAAC;AACtB,gBAAA,sBAAsB,EAAE,CAAC;AACzB,gBAAA,KAAK,EAAE,EAAE;AACV,aAAA;AACF,SAAA,EACD,QAAQ,EAAE,oBAAoB,EAAA,CAC9B,CACH,CAAC;IAEF,QACE,KAAC,CAAA,aAAA,CAAA,SAAS,EACR,EAAA,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,OAAO,EACzC,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,KAAK,EAC/C,IAAI,EAAE,KAAC,CAAA,aAAA,CAAA,kBAAkB,EAAC,EAAA,IAAI,EAAE,EAAE,EAAI,CAAA,EACtC,YAAY,EAAE,MAAM,EACpB,iBAAiB,EAAE,EAAE,EACrB,QAAQ,EAAE,iBAAiB,EAC3B,CAAA,EACF;AACJ;;;;"}
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ import { Annotation } from '@medplum/fhirtypes';
3
+ export interface NoteDisplayProps {
4
+ value?: Annotation[];
5
+ }
6
+ export declare function NoteDisplay({ value }: NoteDisplayProps): JSX.Element | null;
@@ -0,0 +1,18 @@
1
+ import { createStyles, Stack, Blockquote } from '@mantine/core';
2
+ import React from 'react';
3
+
4
+ const useStyles = createStyles((theme) => ({
5
+ noteBody: { fontSize: theme.fontSizes.sm },
6
+ noteCite: { fontSize: theme.fontSizes.xs, marginBlockStart: 3 },
7
+ noteRoot: { padding: 5 },
8
+ }));
9
+ function NoteDisplay({ value }) {
10
+ const { classes } = useStyles();
11
+ if (!value) {
12
+ return null;
13
+ }
14
+ return (React.createElement(Stack, { justify: "flex-start", spacing: "xs" }, value.map((note, index) => note.text && (React.createElement(Blockquote, { key: `note-${index}`, classNames: { cite: classes.noteCite, body: classes.noteBody, root: classes.noteRoot }, cite: note.authorReference?.display || note.authorString, icon: null }, note.text)))));
15
+ }
16
+
17
+ export { NoteDisplay };
18
+ //# sourceMappingURL=NoteDisplay.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoteDisplay.mjs","sources":["../../../src/NoteDisplay/NoteDisplay.tsx"],"sourcesContent":["import { Blockquote, createStyles, Stack } from '@mantine/core';\nimport { Annotation } from '@medplum/fhirtypes';\nimport React from 'react';\n\nconst useStyles = createStyles((theme) => ({\n noteBody: { fontSize: theme.fontSizes.sm },\n noteCite: { fontSize: theme.fontSizes.xs, marginBlockStart: 3 },\n noteRoot: { padding: 5 },\n}));\n\nexport interface NoteDisplayProps {\n value?: Annotation[];\n}\n\nexport function NoteDisplay({ value }: NoteDisplayProps): JSX.Element | null {\n const { classes } = useStyles();\n if (!value) {\n return null;\n }\n\n return (\n <Stack justify=\"flex-start\" spacing=\"xs\">\n {value.map(\n (note, index) =>\n note.text && (\n <Blockquote\n key={`note-${index}`}\n classNames={{ cite: classes.noteCite, body: classes.noteBody, root: classes.noteRoot }}\n cite={note.authorReference?.display || note.authorString}\n icon={null}\n >\n {note.text}\n </Blockquote>\n )\n )}\n </Stack>\n );\n}\n"],"names":[],"mappings":";;;AAIA,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,KAAK,MAAM;IACzC,QAAQ,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE;AAC1C,IAAA,QAAQ,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE;AAC/D,IAAA,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE;AACzB,CAAA,CAAC,CAAC,CAAC;AAMY,SAAA,WAAW,CAAC,EAAE,KAAK,EAAoB,EAAA;AACrD,IAAA,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE;AACV,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;AAED,IAAA,QACE,KAAC,CAAA,aAAA,CAAA,KAAK,EAAC,EAAA,OAAO,EAAC,YAAY,EAAC,OAAO,EAAC,IAAI,EACrC,EAAA,KAAK,CAAC,GAAG,CACR,CAAC,IAAI,EAAE,KAAK,KACV,IAAI,CAAC,IAAI,KACP,KAAC,CAAA,aAAA,CAAA,UAAU,EACT,EAAA,GAAG,EAAE,CAAQ,KAAA,EAAA,KAAK,EAAE,EACpB,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,EACtF,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,IAAI,IAAI,CAAC,YAAY,EACxD,IAAI,EAAE,IAAI,EAET,EAAA,IAAI,CAAC,IAAI,CACC,CACd,CACJ,CACK,EACR;AACJ;;;;"}
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import { Meta } from '@storybook/react';
3
+ declare const _default: Meta<import("@storybook/react").Args>;
4
+ export default _default;
5
+ export declare const Simple: () => JSX.Element;
6
+ export declare const WithAuthor: () => JSX.Element;
7
+ export declare const MultipleNotes: () => JSX.Element;
@@ -1,6 +1,7 @@
1
1
  /// <reference types="react" />
2
- import { OperationOutcomeIssue } from '@medplum/fhirtypes';
2
+ import { OperationOutcome, OperationOutcomeIssue } from '@medplum/fhirtypes';
3
3
  export interface OperationOutcomeAlertProps {
4
+ outcome?: OperationOutcome;
4
5
  issues?: OperationOutcomeIssue[];
5
6
  }
6
7
  export declare function OperationOutcomeAlert(props: OperationOutcomeAlertProps): JSX.Element | null;