@medplum/react 0.9.32 → 0.9.35

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 (67) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/QuestionnaireForm.d.ts +4 -1
  3. package/dist/cjs/Scheduler.d.ts +2 -1
  4. package/dist/cjs/SearchControlField.d.ts +2 -3
  5. package/dist/cjs/SearchFieldEditor.d.ts +1 -2
  6. package/dist/cjs/SearchFilterEditor.d.ts +1 -2
  7. package/dist/cjs/SearchFilterValueDialog.d.ts +1 -2
  8. package/dist/cjs/SearchFilterValueInput.d.ts +0 -2
  9. package/dist/cjs/SearchPopupMenu.d.ts +1 -2
  10. package/dist/cjs/auth/AuthenticationForm.d.ts +2 -0
  11. package/dist/cjs/auth/SignInForm.d.ts +2 -0
  12. package/dist/cjs/index.js +125 -71
  13. package/dist/cjs/index.js.map +1 -1
  14. package/dist/cjs/index.min.js +1 -1
  15. package/dist/cjs/index.min.js.map +1 -1
  16. package/dist/cjs/stories/QuestionnaireForm.stories.d.ts +1 -0
  17. package/dist/cjs/styles.css +51 -51
  18. package/dist/esm/GoogleButton.js +2 -2
  19. package/dist/esm/GoogleButton.js.map +1 -1
  20. package/dist/esm/Popup.js +5 -1
  21. package/dist/esm/Popup.js.map +1 -1
  22. package/dist/esm/QuestionnaireBuilder.js +1 -1
  23. package/dist/esm/QuestionnaireBuilder.js.map +1 -1
  24. package/dist/esm/QuestionnaireForm.d.ts +4 -1
  25. package/dist/esm/QuestionnaireForm.js +49 -10
  26. package/dist/esm/QuestionnaireForm.js.map +1 -1
  27. package/dist/esm/Scheduler.d.ts +2 -1
  28. package/dist/esm/Scheduler.js +18 -24
  29. package/dist/esm/Scheduler.js.map +1 -1
  30. package/dist/esm/SearchControl.js +10 -14
  31. package/dist/esm/SearchControl.js.map +1 -1
  32. package/dist/esm/SearchControlField.d.ts +2 -3
  33. package/dist/esm/SearchControlField.js +6 -8
  34. package/dist/esm/SearchControlField.js.map +1 -1
  35. package/dist/esm/SearchFieldEditor.d.ts +1 -2
  36. package/dist/esm/SearchFieldEditor.js +2 -2
  37. package/dist/esm/SearchFieldEditor.js.map +1 -1
  38. package/dist/esm/SearchFilterEditor.d.ts +1 -2
  39. package/dist/esm/SearchFilterEditor.js +5 -6
  40. package/dist/esm/SearchFilterEditor.js.map +1 -1
  41. package/dist/esm/SearchFilterValueDialog.d.ts +1 -2
  42. package/dist/esm/SearchFilterValueDialog.js +1 -1
  43. package/dist/esm/SearchFilterValueDialog.js.map +1 -1
  44. package/dist/esm/SearchFilterValueInput.d.ts +0 -2
  45. package/dist/esm/SearchFilterValueInput.js +1 -1
  46. package/dist/esm/SearchFilterValueInput.js.map +1 -1
  47. package/dist/esm/SearchPopupMenu.d.ts +1 -2
  48. package/dist/esm/SearchPopupMenu.js.map +1 -1
  49. package/dist/esm/ServiceRequestTimeline.js +3 -3
  50. package/dist/esm/ServiceRequestTimeline.js.map +1 -1
  51. package/dist/esm/auth/AuthenticationForm.d.ts +2 -0
  52. package/dist/esm/auth/AuthenticationForm.js +4 -0
  53. package/dist/esm/auth/AuthenticationForm.js.map +1 -1
  54. package/dist/esm/auth/SignInForm.d.ts +2 -0
  55. package/dist/esm/auth/SignInForm.js +1 -1
  56. package/dist/esm/auth/SignInForm.js.map +1 -1
  57. package/dist/esm/index.js +1 -1
  58. package/dist/esm/index.min.js +1 -1
  59. package/dist/esm/index.min.js.map +1 -1
  60. package/dist/esm/stories/QuestionnaireForm.stories.d.ts +1 -0
  61. package/dist/esm/styles.css +51 -51
  62. package/dist/esm/utils/blame.js +1 -0
  63. package/dist/esm/utils/blame.js.map +1 -1
  64. package/dist/esm/utils/outcomes.js +19 -1
  65. package/dist/esm/utils/outcomes.js.map +1 -1
  66. package/package.json +13 -13
  67. package/stats.html +4034 -0
@@ -5,6 +5,7 @@ export default _default;
5
5
  export declare const Basic: () => JSX.Element;
6
6
  export declare const Groups: () => JSX.Element;
7
7
  export declare const MultipleChoice: () => JSX.Element;
8
+ export declare const EnableWhen: () => JSX.Element;
8
9
  export declare const KitchenSink: () => JSX.Element;
9
10
  export declare const KitchenSinkWithInitialValues: () => JSX.Element;
10
11
  export declare const USSurgeonGeneralFamilyHealthPortrait: () => JSX.Element;
@@ -939,6 +939,57 @@ table.medplum-diff-table td {
939
939
  margin-right: 4px;
940
940
  }
941
941
 
942
+ .medplum-filter-editor {
943
+ text-align: left;
944
+ width: 900px;
945
+ max-width: 900px;
946
+ }
947
+
948
+ .medplum-filter-editor-table {
949
+ width: 100%;
950
+ border-collapse: collapse;
951
+ }
952
+
953
+ .medplum-menu-separator {
954
+ border-top: 0.1px solid var(--medplum-gray-400);
955
+ margin: 4px 0;
956
+ padding: 0;
957
+ }
958
+
959
+ .medplum-submenu-arrow {
960
+ color: var(--medplum-foreground);
961
+ left: auto;
962
+ padding-right: 6px;
963
+ position: absolute;
964
+ right: 0;
965
+ text-align: right;
966
+ user-select: none;
967
+ }
968
+
969
+ .medplum-title-bar {
970
+ display: flex;
971
+ width: 100%;
972
+ height: 50px;
973
+ padding: 15px;
974
+ justify-content: space-between;
975
+ background: var(--medplum-surface);
976
+ border-bottom: 2px solid var(--medplum-gray-200);
977
+ color: var(--medplum-gray-800);
978
+ }
979
+
980
+ .medplum-title-bar > div {
981
+ display: flex;
982
+ align-items: center;
983
+ }
984
+
985
+ .medplum-title-bar h1 {
986
+ font-size: 14px;
987
+ font-weight: bold;
988
+ padding: 0 4px 0 1px;
989
+ margin: 0 4px 0 1px;
990
+ color: var(--medplum-gray-800);
991
+ }
992
+
942
993
  .medplum-search-control {
943
994
  max-width: 100%;
944
995
  overflow: auto;
@@ -1058,57 +1109,6 @@ table.medplum-diff-table td {
1058
1109
  outline: 0;
1059
1110
  }
1060
1111
 
1061
- .medplum-filter-editor {
1062
- text-align: left;
1063
- width: 900px;
1064
- max-width: 900px;
1065
- }
1066
-
1067
- .medplum-filter-editor-table {
1068
- width: 100%;
1069
- border-collapse: collapse;
1070
- }
1071
-
1072
- .medplum-menu-separator {
1073
- border-top: 0.1px solid var(--medplum-gray-400);
1074
- margin: 4px 0;
1075
- padding: 0;
1076
- }
1077
-
1078
- .medplum-submenu-arrow {
1079
- color: var(--medplum-foreground);
1080
- left: auto;
1081
- padding-right: 6px;
1082
- position: absolute;
1083
- right: 0;
1084
- text-align: right;
1085
- user-select: none;
1086
- }
1087
-
1088
- .medplum-title-bar {
1089
- display: flex;
1090
- width: 100%;
1091
- height: 50px;
1092
- padding: 15px;
1093
- justify-content: space-between;
1094
- background: var(--medplum-surface);
1095
- border-bottom: 2px solid var(--medplum-gray-200);
1096
- color: var(--medplum-gray-800);
1097
- }
1098
-
1099
- .medplum-title-bar > div {
1100
- display: flex;
1101
- align-items: center;
1102
- }
1103
-
1104
- .medplum-title-bar h1 {
1105
- font-size: 14px;
1106
- font-weight: bold;
1107
- padding: 0 4px 0 1px;
1108
- margin: 0 4px 0 1px;
1109
- color: var(--medplum-gray-800);
1110
- }
1111
-
1112
1112
  .medplum-footer {
1113
1113
  text-align: center;
1114
1114
  font-size: 12px;
@@ -37,9 +37,9 @@ function getGoogleClientId(clientId) {
37
37
  return clientId;
38
38
  }
39
39
  const origin = window.location.protocol + '//' + window.location.host;
40
- const authorizedOrigins = (_b = (_a = "undefined") === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : [];
40
+ const authorizedOrigins = (_b = (_a = "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") === null || _a === void 0 ? void 0 : _a.split(',')) !== null && _b !== void 0 ? _b : [];
41
41
  if (authorizedOrigins.includes(origin)) {
42
- return "undefined";
42
+ return "921088377005-3j1sa10vr6hj86jgmdfh2l53v3mp7lfi.apps.googleusercontent.com";
43
43
  }
44
44
  return undefined;
45
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleButton.js","sources":["../../src/GoogleButton.tsx"],"sourcesContent":["import { GoogleCredentialResponse } from '@medplum/core';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useMedplum } from './MedplumProvider';\nimport { createScriptTag } from './utils';\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,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,WAA+B,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAE,KAAK,CAAC,GAAG,CAAC,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,EAAE,CAAC;AAC5E,IAAA,IAAI,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AACtC,QAAA,OAAO,WAA4B,CAAC;AACrC,KAAA;AAED,IAAA,OAAO,SAAS,CAAC;AACnB;;;;"}
1
+ {"version":3,"file":"GoogleButton.js","sources":["../../src/GoogleButton.tsx"],"sourcesContent":["import { GoogleCredentialResponse } from '@medplum/core';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useMedplum } from './MedplumProvider';\nimport { createScriptTag } from './utils';\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,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,6NAA+B,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAE,KAAK,CAAC,GAAG,CAAC,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,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;;;;"}
package/dist/esm/Popup.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import React, { useRef, useEffect } from 'react';
2
2
  import { useLocation } from 'react-router-dom';
3
+ import { killEvent } from './utils/dom.js';
3
4
 
4
5
  function Popup(props) {
5
6
  const ref = useRef(null);
@@ -25,11 +26,14 @@ function Popup(props) {
25
26
  ((_b = propsRef.current) === null || _b === void 0 ? void 0 : _b.autoClose) &&
26
27
  (ref === null || ref === void 0 ? void 0 : ref.current) &&
27
28
  !ref.current.contains(e.target)) {
29
+ killEvent(e);
28
30
  props.onClose();
29
31
  }
30
32
  }
31
33
  document.addEventListener('click', handleClick, true);
32
- return () => document.removeEventListener('click', handleClick, true);
34
+ return () => {
35
+ document.removeEventListener('click', handleClick, true);
36
+ };
33
37
  }, [props]);
34
38
  // Listen for changes in the location
35
39
  // If the browser navigates to a new page, close the popup
@@ -1 +1 @@
1
- {"version":3,"file":"Popup.js","sources":["../../src/Popup.tsx"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\nimport { Location, useLocation } from 'react-router-dom';\nimport './Popup.css';\n\ninterface PopupProps {\n visible: boolean;\n anchor?: DOMRectReadOnly;\n modal?: boolean;\n autoClose?: boolean;\n onClose: () => void;\n activeClassName?: string;\n inactiveClassName?: string;\n children?: React.ReactNode;\n}\n\nexport function Popup(props: PopupProps): JSX.Element {\n const ref = useRef<HTMLDivElement>(null);\n\n // Track browser URL location, and the location when the popup becomes visible\n const location = useLocation();\n const locationRef = useRef<Location>();\n if (props.visible) {\n if (locationRef.current === undefined) {\n locationRef.current = location;\n }\n } else {\n locationRef.current = undefined;\n }\n\n const propsRef = useRef<PopupProps>();\n propsRef.current = props;\n\n // Listen for clicks outside of the popup\n // If the user clicks outside of the popup, close it\n useEffect(() => {\n function handleClick(e: Event): void {\n if (\n propsRef.current?.visible &&\n propsRef.current?.autoClose &&\n ref?.current &&\n !ref.current.contains(e.target as Node)\n ) {\n props.onClose();\n }\n }\n\n document.addEventListener('click', handleClick, true);\n return () => document.removeEventListener('click', handleClick, true);\n }, [props]);\n\n // Listen for changes in the location\n // If the browser navigates to a new page, close the popup\n useEffect(() => {\n if (props.visible && location !== locationRef.current) {\n props.onClose();\n }\n }, [location, props]);\n\n const style: React.CSSProperties = {\n display: props.visible ? 'block' : 'none',\n };\n\n if (props.anchor) {\n if (props.anchor.right + 250 < document.body.clientWidth) {\n style.left = props.anchor.right + 'px';\n } else {\n style.right = document.body.clientWidth - props.anchor.left + 'px';\n }\n\n if (props.anchor.top + 300 < document.body.clientHeight) {\n style.top = props.anchor.top + 'px';\n } else {\n style.bottom = document.body.clientHeight - props.anchor.top + 'px';\n }\n }\n\n return (\n <>\n {props.modal && (\n <div className={props.visible ? 'medplum-backdrop active' : 'medplum-backdrop'} onClick={props.onClose} />\n )}\n <div\n ref={ref}\n className={'medplum-popup ' + (props.visible ? props.activeClassName : props.inactiveClassName)}\n style={style}\n data-testid=\"popup\"\n >\n {props.children}\n </div>\n </>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Popup.js","sources":["../../src/Popup.tsx"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\nimport { Location, useLocation } from 'react-router-dom';\nimport './Popup.css';\nimport { killEvent } from './utils/dom';\n\ninterface PopupProps {\n visible: boolean;\n anchor?: DOMRectReadOnly;\n modal?: boolean;\n autoClose?: boolean;\n onClose: () => void;\n activeClassName?: string;\n inactiveClassName?: string;\n children?: React.ReactNode;\n}\n\nexport function Popup(props: PopupProps): JSX.Element {\n const ref = useRef<HTMLDivElement>(null);\n\n // Track browser URL location, and the location when the popup becomes visible\n const location = useLocation();\n const locationRef = useRef<Location>();\n if (props.visible) {\n if (locationRef.current === undefined) {\n locationRef.current = location;\n }\n } else {\n locationRef.current = undefined;\n }\n\n const propsRef = useRef<PopupProps>();\n propsRef.current = props;\n\n // Listen for clicks outside of the popup\n // If the user clicks outside of the popup, close it\n useEffect(() => {\n function handleClick(e: Event): void {\n if (\n propsRef.current?.visible &&\n propsRef.current?.autoClose &&\n ref?.current &&\n !ref.current.contains(e.target as Node)\n ) {\n killEvent(e);\n props.onClose();\n }\n }\n\n document.addEventListener('click', handleClick, true);\n return () => {\n document.removeEventListener('click', handleClick, true);\n };\n }, [props]);\n\n // Listen for changes in the location\n // If the browser navigates to a new page, close the popup\n useEffect(() => {\n if (props.visible && location !== locationRef.current) {\n props.onClose();\n }\n }, [location, props]);\n\n const style: React.CSSProperties = {\n display: props.visible ? 'block' : 'none',\n };\n\n if (props.anchor) {\n if (props.anchor.right + 250 < document.body.clientWidth) {\n style.left = props.anchor.right + 'px';\n } else {\n style.right = document.body.clientWidth - props.anchor.left + 'px';\n }\n\n if (props.anchor.top + 300 < document.body.clientHeight) {\n style.top = props.anchor.top + 'px';\n } else {\n style.bottom = document.body.clientHeight - props.anchor.top + 'px';\n }\n }\n\n return (\n <>\n {props.modal && (\n <div className={props.visible ? 'medplum-backdrop active' : 'medplum-backdrop'} onClick={props.onClose} />\n )}\n <div\n ref={ref}\n className={'medplum-popup ' + (props.visible ? props.activeClassName : props.inactiveClassName)}\n style={style}\n data-testid=\"popup\"\n >\n {props.children}\n </div>\n </>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -108,7 +108,7 @@ function ItemBuilder(props) {
108
108
  isChoiceQuestion(item) && (React.createElement(AnswerBuilder, { options: item.answerOption, onChange: (newOptions) => changeProperty('answerOption', newOptions) })))) : (React.createElement(React.Fragment, null,
109
109
  resource.title && React.createElement("h1", null, resource.title),
110
110
  item.text && React.createElement("p", null, item.text),
111
- !isContainer && React.createElement(QuestionnaireFormItem, { item: item, onChange: () => undefined }))),
111
+ !isContainer && React.createElement(QuestionnaireFormItem, { item: item, answers: {}, onChange: () => undefined }))),
112
112
  item.item &&
113
113
  item.item.map((i) => (React.createElement("div", { key: i.id },
114
114
  React.createElement(ItemBuilder, { item: i, selectedKey: props.selectedKey, setSelectedKey: props.setSelectedKey, hoverKey: props.hoverKey, setHoverKey: props.setHoverKey, onChange: changeItem, onRemove: () => removeItem(i) })))),
@@ -1 +1 @@
1
- {"version":3,"file":"QuestionnaireBuilder.js","sources":["../../src/QuestionnaireBuilder.tsx"],"sourcesContent":["import { globalSchema, IndexedStructureDefinition } from '@medplum/core';\nimport { Questionnaire, QuestionnaireItem, QuestionnaireItemAnswerOption, Reference } from '@medplum/fhirtypes';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { Button } from './Button';\nimport { Form } from './Form';\nimport { Input } from './Input';\nimport { useMedplum } from './MedplumProvider';\nimport { QuestionnaireFormItem } from './QuestionnaireForm';\nimport { isChoiceQuestion, QuestionnaireItemType } from './QuestionnaireUtils';\nimport { getValueAndType } from './ResourcePropertyDisplay';\nimport { ResourcePropertyInput } from './ResourcePropertyInput';\nimport { Select } from './Select';\nimport { TextArea } from './TextArea';\nimport { useResource } from './useResource';\nimport { killEvent } from './utils/dom';\nimport './QuestionnaireBuilder.css';\n\nexport interface QuestionnaireBuilderProps {\n questionnaire: Questionnaire | Reference<Questionnaire>;\n onSubmit: (result: Questionnaire) => void;\n}\n\nexport function QuestionnaireBuilder(props: QuestionnaireBuilderProps): JSX.Element | null {\n const medplum = useMedplum();\n const defaultValue = useResource(props.questionnaire);\n const [schema, setSchema] = useState<IndexedStructureDefinition | undefined>();\n const [value, setValue] = useState<Questionnaire>();\n const [selectedKey, setSelectedKey] = useState<string>();\n const [hoverKey, setHoverKey] = useState<string>();\n\n function handleDocumentMouseOver(): void {\n setHoverKey(undefined);\n }\n\n function handleDocumentClick(): void {\n setSelectedKey(undefined);\n }\n\n useEffect(() => {\n medplum.requestSchema('Questionnaire').then(setSchema).catch(console.log);\n }, [medplum]);\n\n useEffect(() => {\n setValue(ensureQuestionnaireKeys(defaultValue ?? { resourceType: 'Questionnaire' }));\n document.addEventListener('mouseover', handleDocumentMouseOver);\n document.addEventListener('click', handleDocumentClick);\n return () => {\n document.removeEventListener('mouseover', handleDocumentMouseOver);\n document.removeEventListener('click', handleDocumentClick);\n };\n }, [defaultValue]);\n\n if (!schema || !value) {\n return null;\n }\n\n return (\n <div className=\"medplum-questionnaire-builder\">\n <Form testid=\"questionnaire-form\" onSubmit={() => props.onSubmit(value)}>\n <ItemBuilder\n item={value}\n selectedKey={selectedKey}\n setSelectedKey={setSelectedKey}\n hoverKey={hoverKey}\n setHoverKey={setHoverKey}\n onChange={setValue}\n />\n <Button type=\"submit\" size=\"large\">\n Save\n </Button>\n </Form>\n </div>\n );\n}\n\ninterface ItemBuilderProps<T extends Questionnaire | QuestionnaireItem> {\n item: T;\n selectedKey: string | undefined;\n setSelectedKey: (key: string | undefined) => void;\n hoverKey: string | undefined;\n setHoverKey: (key: string | undefined) => void;\n onChange: (item: T) => void;\n onRemove?: () => void;\n}\n\nfunction ItemBuilder<T extends Questionnaire | QuestionnaireItem>(props: ItemBuilderProps<T>): JSX.Element {\n const resource = props.item as Questionnaire;\n const item = props.item as QuestionnaireItem;\n const isResource = 'resourceType' in props.item;\n const isContainer = isResource || item.type === QuestionnaireItemType.group;\n const linkId = item.linkId ?? '[untitled]';\n const editing = props.selectedKey === props.item.id;\n const hovering = props.hoverKey === props.item.id;\n\n const itemRef = useRef<T>();\n itemRef.current = props.item;\n\n function onClick(e: React.SyntheticEvent): void {\n killEvent(e);\n props.setSelectedKey(props.item.id);\n }\n\n function onHover(e: React.SyntheticEvent): void {\n killEvent(e);\n props.setHoverKey(props.item.id);\n }\n\n function changeItem(changedItem: QuestionnaireItem): void {\n const curr = itemRef.current as T;\n props.onChange({\n ...curr,\n item: curr.item?.map((i) => (i.id === changedItem.id ? changedItem : i)),\n } as T);\n }\n\n function addItem(addedItem: QuestionnaireItem): void {\n props.onChange({\n ...props.item,\n item: [...(props.item?.item ?? []), addedItem],\n });\n }\n\n function removeItem(removedItem: QuestionnaireItem): void {\n props.onChange({\n ...props.item,\n item: props.item?.item?.filter((i) => i !== removedItem),\n });\n }\n\n function changeProperty(property: string, value: any): void {\n props.onChange({\n ...itemRef.current,\n [property]: value,\n } as T);\n }\n\n const className = editing ? 'section editing' : hovering ? 'section hovering' : 'section';\n return (\n <div data-testid={item.linkId} className={className} onClick={onClick} onMouseOver={onHover}>\n {editing ? (\n <>\n {isResource && (\n <div>\n <Input defaultValue={resource.title} onChange={(newValue) => changeProperty('title', newValue)} />\n </div>\n )}\n {!isContainer && (\n <div>\n <Select defaultValue={item.type} onChange={(newValue) => changeProperty('type', newValue)}>\n <option value=\"display\">Display</option>\n <optgroup label=\"Question\">\n <option value=\"boolean\">Boolean</option>\n <option value=\"decimal\">Decimal</option>\n <option value=\"integer\">Integer</option>\n <option value=\"date\">Date</option>\n <option value=\"dateTime\">Date/Time</option>\n <option value=\"time\">Time</option>\n <option value=\"string\">String</option>\n <option value=\"text\">Text</option>\n <option value=\"url\">URL</option>\n <option value=\"choice\">Choice</option>\n <option value=\"open-choice\">Open Choice</option>\n <option value=\"attachment\">Attachment</option>\n <option value=\"reference\">Reference</option>\n <option value=\"quantity\">Quantity</option>\n </optgroup>\n </Select>\n </div>\n )}\n {!isResource && (\n <TextArea\n style={{ width: '95%', height: '100px', minHeight: '100px', margin: '8px 4px 4px 4px' }}\n defaultValue={item.text}\n onChange={(newValue) => changeProperty('text', newValue)}\n />\n )}\n {isChoiceQuestion(item) && (\n <AnswerBuilder\n options={item.answerOption}\n onChange={(newOptions) => changeProperty('answerOption', newOptions)}\n />\n )}\n </>\n ) : (\n <>\n {resource.title && <h1>{resource.title}</h1>}\n {item.text && <p>{item.text}</p>}\n {!isContainer && <QuestionnaireFormItem item={item} onChange={() => undefined} />}\n </>\n )}\n {item.item &&\n item.item.map((i) => (\n <div key={i.id}>\n <ItemBuilder\n item={i}\n selectedKey={props.selectedKey}\n setSelectedKey={props.setSelectedKey}\n hoverKey={props.hoverKey}\n setHoverKey={props.setHoverKey}\n onChange={changeItem}\n onRemove={() => removeItem(i)}\n />\n </div>\n ))}\n {!isContainer && (\n <div className=\"top-actions\">\n {editing ? (\n <Input defaultValue={item.linkId} onChange={(newValue) => changeProperty('linkId', newValue)} size={4} />\n ) : (\n <div>{linkId}</div>\n )}\n </div>\n )}\n <div className=\"bottom-actions\">\n {isContainer && (\n <>\n <a\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n addItem({\n id: generateId(),\n linkId: generateLinkId('q'),\n type: 'string',\n text: 'Question',\n } as QuestionnaireItem);\n }}\n >\n Add item\n </a>\n <a\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n addItem({\n id: generateId(),\n linkId: generateLinkId('g'),\n type: 'group',\n text: 'Group',\n } as QuestionnaireItem);\n }}\n >\n Add group\n </a>\n </>\n )}\n {!isResource && (\n <a\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n if (props.onRemove) {\n props.onRemove();\n }\n }}\n >\n Remove\n </a>\n )}\n </div>\n </div>\n );\n}\n\ninterface AnswerBuilderProps {\n options?: QuestionnaireItemAnswerOption[];\n onChange: (newOptions: QuestionnaireItemAnswerOption[]) => void;\n}\n\nfunction AnswerBuilder(props: AnswerBuilderProps): JSX.Element {\n const property = globalSchema.types['QuestionnaireItemAnswerOption'].properties['value[x]'];\n const options = props.options ?? [];\n return (\n <div>\n {options.map((option: QuestionnaireItemAnswerOption) => {\n const [propertyValue, propertyType] = getValueAndType(\n { type: 'QuestionnaireItemAnswerOption', value: option },\n 'value'\n );\n return (\n <div\n key={option.id}\n style={{\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n width: '80%',\n }}\n >\n <div>\n <ResourcePropertyInput\n key={option.id}\n name=\"value[x]\"\n property={property}\n defaultPropertyType={propertyType}\n defaultValue={propertyValue}\n onChange={(newValue: any, propName?: string) => {\n const newOptions = [...options];\n const index = newOptions.findIndex((o) => o.id === option.id);\n newOptions[index] = { id: option.id, [propName as string]: newValue };\n props.onChange(newOptions);\n }}\n />\n </div>\n <div>\n <a\n href=\"#\"\n onClick={(e: React.SyntheticEvent) => {\n killEvent(e);\n props.onChange(options.filter((o) => o.id !== option.id));\n }}\n >\n Remove\n </a>\n </div>\n </div>\n );\n })}\n <a\n href=\"#\"\n onClick={(e: React.SyntheticEvent) => {\n killEvent(e);\n props.onChange([\n ...options,\n {\n id: generateId(),\n },\n ]);\n }}\n >\n Add choice\n </a>\n </div>\n );\n}\n\nlet nextLinkId = 1;\nlet nextId = 1;\n\n/**\n * Generates a link ID for an item.\n * Link IDs are required properties on QuestionnaireItem objects.\n * @return A unique link ID.\n */\nfunction generateLinkId(prefix: string): string {\n return prefix + nextLinkId++;\n}\n\n/**\n * Generates a unique ID.\n * React needs unique IDs for components for rendering performance.\n * All of the important components in the questionnaire builder have id properties for this:\n * Questionnaire, QuestionnaireItem, and QuestionnaireItemAnswerOption.\n * @return A unique key.\n */\nfunction generateId(): string {\n return 'id-' + nextId++;\n}\n\nfunction ensureQuestionnaireKeys(questionnaire: Questionnaire): Questionnaire {\n return {\n ...questionnaire,\n id: questionnaire.id || generateId(),\n item: ensureQuestionnaireItemKeys(questionnaire.item),\n } as Questionnaire;\n}\n\nfunction ensureQuestionnaireItemKeys(items: QuestionnaireItem[] | undefined): QuestionnaireItem[] | undefined {\n if (!items) {\n return undefined;\n }\n return items.map((item) => ({\n ...item,\n id: item.id || generateId(),\n item: ensureQuestionnaireItemKeys(item.item),\n answerOption: ensureQuestionnaireOptionKeys(item.answerOption),\n }));\n}\n\nfunction ensureQuestionnaireOptionKeys(\n options: QuestionnaireItemAnswerOption[] | undefined\n): QuestionnaireItemAnswerOption[] | undefined {\n if (!options) {\n return undefined;\n }\n return options.map((option) => ({\n ...option,\n id: option.id || generateId(),\n }));\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"QuestionnaireBuilder.js","sources":["../../src/QuestionnaireBuilder.tsx"],"sourcesContent":["import { globalSchema, IndexedStructureDefinition } from '@medplum/core';\nimport { Questionnaire, QuestionnaireItem, QuestionnaireItemAnswerOption, Reference } from '@medplum/fhirtypes';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { Button } from './Button';\nimport { Form } from './Form';\nimport { Input } from './Input';\nimport { useMedplum } from './MedplumProvider';\nimport { QuestionnaireFormItem } from './QuestionnaireForm';\nimport { isChoiceQuestion, QuestionnaireItemType } from './QuestionnaireUtils';\nimport { getValueAndType } from './ResourcePropertyDisplay';\nimport { ResourcePropertyInput } from './ResourcePropertyInput';\nimport { Select } from './Select';\nimport { TextArea } from './TextArea';\nimport { useResource } from './useResource';\nimport { killEvent } from './utils/dom';\nimport './QuestionnaireBuilder.css';\n\nexport interface QuestionnaireBuilderProps {\n questionnaire: Questionnaire | Reference<Questionnaire>;\n onSubmit: (result: Questionnaire) => void;\n}\n\nexport function QuestionnaireBuilder(props: QuestionnaireBuilderProps): JSX.Element | null {\n const medplum = useMedplum();\n const defaultValue = useResource(props.questionnaire);\n const [schema, setSchema] = useState<IndexedStructureDefinition | undefined>();\n const [value, setValue] = useState<Questionnaire>();\n const [selectedKey, setSelectedKey] = useState<string>();\n const [hoverKey, setHoverKey] = useState<string>();\n\n function handleDocumentMouseOver(): void {\n setHoverKey(undefined);\n }\n\n function handleDocumentClick(): void {\n setSelectedKey(undefined);\n }\n\n useEffect(() => {\n medplum.requestSchema('Questionnaire').then(setSchema).catch(console.log);\n }, [medplum]);\n\n useEffect(() => {\n setValue(ensureQuestionnaireKeys(defaultValue ?? { resourceType: 'Questionnaire' }));\n document.addEventListener('mouseover', handleDocumentMouseOver);\n document.addEventListener('click', handleDocumentClick);\n return () => {\n document.removeEventListener('mouseover', handleDocumentMouseOver);\n document.removeEventListener('click', handleDocumentClick);\n };\n }, [defaultValue]);\n\n if (!schema || !value) {\n return null;\n }\n\n return (\n <div className=\"medplum-questionnaire-builder\">\n <Form testid=\"questionnaire-form\" onSubmit={() => props.onSubmit(value)}>\n <ItemBuilder\n item={value}\n selectedKey={selectedKey}\n setSelectedKey={setSelectedKey}\n hoverKey={hoverKey}\n setHoverKey={setHoverKey}\n onChange={setValue}\n />\n <Button type=\"submit\" size=\"large\">\n Save\n </Button>\n </Form>\n </div>\n );\n}\n\ninterface ItemBuilderProps<T extends Questionnaire | QuestionnaireItem> {\n item: T;\n selectedKey: string | undefined;\n setSelectedKey: (key: string | undefined) => void;\n hoverKey: string | undefined;\n setHoverKey: (key: string | undefined) => void;\n onChange: (item: T) => void;\n onRemove?: () => void;\n}\n\nfunction ItemBuilder<T extends Questionnaire | QuestionnaireItem>(props: ItemBuilderProps<T>): JSX.Element {\n const resource = props.item as Questionnaire;\n const item = props.item as QuestionnaireItem;\n const isResource = 'resourceType' in props.item;\n const isContainer = isResource || item.type === QuestionnaireItemType.group;\n const linkId = item.linkId ?? '[untitled]';\n const editing = props.selectedKey === props.item.id;\n const hovering = props.hoverKey === props.item.id;\n\n const itemRef = useRef<T>();\n itemRef.current = props.item;\n\n function onClick(e: React.SyntheticEvent): void {\n killEvent(e);\n props.setSelectedKey(props.item.id);\n }\n\n function onHover(e: React.SyntheticEvent): void {\n killEvent(e);\n props.setHoverKey(props.item.id);\n }\n\n function changeItem(changedItem: QuestionnaireItem): void {\n const curr = itemRef.current as T;\n props.onChange({\n ...curr,\n item: curr.item?.map((i) => (i.id === changedItem.id ? changedItem : i)),\n } as T);\n }\n\n function addItem(addedItem: QuestionnaireItem): void {\n props.onChange({\n ...props.item,\n item: [...(props.item?.item ?? []), addedItem],\n });\n }\n\n function removeItem(removedItem: QuestionnaireItem): void {\n props.onChange({\n ...props.item,\n item: props.item?.item?.filter((i) => i !== removedItem),\n });\n }\n\n function changeProperty(property: string, value: any): void {\n props.onChange({\n ...itemRef.current,\n [property]: value,\n } as T);\n }\n\n const className = editing ? 'section editing' : hovering ? 'section hovering' : 'section';\n return (\n <div data-testid={item.linkId} className={className} onClick={onClick} onMouseOver={onHover}>\n {editing ? (\n <>\n {isResource && (\n <div>\n <Input defaultValue={resource.title} onChange={(newValue) => changeProperty('title', newValue)} />\n </div>\n )}\n {!isContainer && (\n <div>\n <Select defaultValue={item.type} onChange={(newValue) => changeProperty('type', newValue)}>\n <option value=\"display\">Display</option>\n <optgroup label=\"Question\">\n <option value=\"boolean\">Boolean</option>\n <option value=\"decimal\">Decimal</option>\n <option value=\"integer\">Integer</option>\n <option value=\"date\">Date</option>\n <option value=\"dateTime\">Date/Time</option>\n <option value=\"time\">Time</option>\n <option value=\"string\">String</option>\n <option value=\"text\">Text</option>\n <option value=\"url\">URL</option>\n <option value=\"choice\">Choice</option>\n <option value=\"open-choice\">Open Choice</option>\n <option value=\"attachment\">Attachment</option>\n <option value=\"reference\">Reference</option>\n <option value=\"quantity\">Quantity</option>\n </optgroup>\n </Select>\n </div>\n )}\n {!isResource && (\n <TextArea\n style={{ width: '95%', height: '100px', minHeight: '100px', margin: '8px 4px 4px 4px' }}\n defaultValue={item.text}\n onChange={(newValue) => changeProperty('text', newValue)}\n />\n )}\n {isChoiceQuestion(item) && (\n <AnswerBuilder\n options={item.answerOption}\n onChange={(newOptions) => changeProperty('answerOption', newOptions)}\n />\n )}\n </>\n ) : (\n <>\n {resource.title && <h1>{resource.title}</h1>}\n {item.text && <p>{item.text}</p>}\n {!isContainer && <QuestionnaireFormItem item={item} answers={{}} onChange={() => undefined} />}\n </>\n )}\n {item.item &&\n item.item.map((i) => (\n <div key={i.id}>\n <ItemBuilder\n item={i}\n selectedKey={props.selectedKey}\n setSelectedKey={props.setSelectedKey}\n hoverKey={props.hoverKey}\n setHoverKey={props.setHoverKey}\n onChange={changeItem}\n onRemove={() => removeItem(i)}\n />\n </div>\n ))}\n {!isContainer && (\n <div className=\"top-actions\">\n {editing ? (\n <Input defaultValue={item.linkId} onChange={(newValue) => changeProperty('linkId', newValue)} size={4} />\n ) : (\n <div>{linkId}</div>\n )}\n </div>\n )}\n <div className=\"bottom-actions\">\n {isContainer && (\n <>\n <a\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n addItem({\n id: generateId(),\n linkId: generateLinkId('q'),\n type: 'string',\n text: 'Question',\n } as QuestionnaireItem);\n }}\n >\n Add item\n </a>\n <a\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n addItem({\n id: generateId(),\n linkId: generateLinkId('g'),\n type: 'group',\n text: 'Group',\n } as QuestionnaireItem);\n }}\n >\n Add group\n </a>\n </>\n )}\n {!isResource && (\n <a\n href=\"#\"\n onClick={(e) => {\n e.preventDefault();\n if (props.onRemove) {\n props.onRemove();\n }\n }}\n >\n Remove\n </a>\n )}\n </div>\n </div>\n );\n}\n\ninterface AnswerBuilderProps {\n options?: QuestionnaireItemAnswerOption[];\n onChange: (newOptions: QuestionnaireItemAnswerOption[]) => void;\n}\n\nfunction AnswerBuilder(props: AnswerBuilderProps): JSX.Element {\n const property = globalSchema.types['QuestionnaireItemAnswerOption'].properties['value[x]'];\n const options = props.options ?? [];\n return (\n <div>\n {options.map((option: QuestionnaireItemAnswerOption) => {\n const [propertyValue, propertyType] = getValueAndType(\n { type: 'QuestionnaireItemAnswerOption', value: option },\n 'value'\n );\n return (\n <div\n key={option.id}\n style={{\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n width: '80%',\n }}\n >\n <div>\n <ResourcePropertyInput\n key={option.id}\n name=\"value[x]\"\n property={property}\n defaultPropertyType={propertyType}\n defaultValue={propertyValue}\n onChange={(newValue: any, propName?: string) => {\n const newOptions = [...options];\n const index = newOptions.findIndex((o) => o.id === option.id);\n newOptions[index] = { id: option.id, [propName as string]: newValue };\n props.onChange(newOptions);\n }}\n />\n </div>\n <div>\n <a\n href=\"#\"\n onClick={(e: React.SyntheticEvent) => {\n killEvent(e);\n props.onChange(options.filter((o) => o.id !== option.id));\n }}\n >\n Remove\n </a>\n </div>\n </div>\n );\n })}\n <a\n href=\"#\"\n onClick={(e: React.SyntheticEvent) => {\n killEvent(e);\n props.onChange([\n ...options,\n {\n id: generateId(),\n },\n ]);\n }}\n >\n Add choice\n </a>\n </div>\n );\n}\n\nlet nextLinkId = 1;\nlet nextId = 1;\n\n/**\n * Generates a link ID for an item.\n * Link IDs are required properties on QuestionnaireItem objects.\n * @return A unique link ID.\n */\nfunction generateLinkId(prefix: string): string {\n return prefix + nextLinkId++;\n}\n\n/**\n * Generates a unique ID.\n * React needs unique IDs for components for rendering performance.\n * All of the important components in the questionnaire builder have id properties for this:\n * Questionnaire, QuestionnaireItem, and QuestionnaireItemAnswerOption.\n * @return A unique key.\n */\nfunction generateId(): string {\n return 'id-' + nextId++;\n}\n\nfunction ensureQuestionnaireKeys(questionnaire: Questionnaire): Questionnaire {\n return {\n ...questionnaire,\n id: questionnaire.id || generateId(),\n item: ensureQuestionnaireItemKeys(questionnaire.item),\n } as Questionnaire;\n}\n\nfunction ensureQuestionnaireItemKeys(items: QuestionnaireItem[] | undefined): QuestionnaireItem[] | undefined {\n if (!items) {\n return undefined;\n }\n return items.map((item) => ({\n ...item,\n id: item.id || generateId(),\n item: ensureQuestionnaireItemKeys(item.item),\n answerOption: ensureQuestionnaireOptionKeys(item.answerOption),\n }));\n}\n\nfunction ensureQuestionnaireOptionKeys(\n options: QuestionnaireItemAnswerOption[] | undefined\n): QuestionnaireItemAnswerOption[] | undefined {\n if (!options) {\n return undefined;\n }\n return options.map((option) => ({\n ...option,\n id: option.id || generateId(),\n }));\n}\n"],"names":[],"mappings":"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"}
@@ -1,14 +1,17 @@
1
1
  /// <reference types="react" />
2
- import { Questionnaire, QuestionnaireItem, QuestionnaireResponse, QuestionnaireResponseItem, Reference } from '@medplum/fhirtypes';
2
+ import { Questionnaire, QuestionnaireItem, QuestionnaireResponse, QuestionnaireResponseItem, QuestionnaireResponseItemAnswer, Reference } from '@medplum/fhirtypes';
3
3
  import './QuestionnaireForm.css';
4
4
  export interface QuestionnaireFormProps {
5
5
  questionnaire: Questionnaire | Reference<Questionnaire>;
6
6
  subject?: Reference;
7
+ submitButtonText?: string;
7
8
  onSubmit: (response: QuestionnaireResponse) => void;
8
9
  }
9
10
  export declare function QuestionnaireForm(props: QuestionnaireFormProps): JSX.Element | null;
10
11
  export interface QuestionnaireFormItemProps {
11
12
  item: QuestionnaireItem;
13
+ answers: Record<string, QuestionnaireResponseItemAnswer>;
12
14
  onChange: (newResponseItem: QuestionnaireResponseItem) => void;
13
15
  }
14
16
  export declare function QuestionnaireFormItem(props: QuestionnaireFormItemProps): JSX.Element | null;
17
+ export declare function isQuestionEnabled(item: QuestionnaireItem, answers: Record<string, QuestionnaireResponseItemAnswer>): boolean;
@@ -1,4 +1,4 @@
1
- import { getReferenceString, createReference, globalSchema, getTypedPropertyValue, capitalize, stringify } from '@medplum/core';
1
+ import { getReferenceString, createReference, globalSchema, getTypedPropertyValue, capitalize, stringify, deepEquals, getQuestionnaireAnswers } from '@medplum/core';
2
2
  import React, { useState, useEffect } from 'react';
3
3
  import { AttachmentInput } from './AttachmentInput.js';
4
4
  import { Button } from './Button.js';
@@ -22,17 +22,24 @@ function QuestionnaireForm(props) {
22
22
  const [schema, setSchema] = useState();
23
23
  const questionnaire = useResource(props.questionnaire);
24
24
  const [response, setResponse] = useState();
25
+ const [answers, setAnswers] = useState({});
25
26
  useEffect(() => {
26
- medplum.requestSchema('Questionnaire').then(setSchema).catch(console.log);
27
+ medplum
28
+ .requestSchema('Questionnaire')
29
+ .then(() => medplum.requestSchema('QuestionnaireResponse'))
30
+ .then(setSchema)
31
+ .catch(console.log);
27
32
  }, [medplum]);
28
33
  useEffect(() => {
29
34
  setResponse(questionnaire ? buildInitialResponse(questionnaire) : undefined);
30
35
  }, [questionnaire]);
31
36
  function setItems(newResponseItems) {
32
- setResponse({
37
+ const newResponse = {
33
38
  resourceType: 'QuestionnaireResponse',
34
39
  item: newResponseItems,
35
- });
40
+ };
41
+ setResponse(newResponse);
42
+ setAnswers(getQuestionnaireAnswers(newResponse));
36
43
  }
37
44
  if (!schema || !questionnaire) {
38
45
  return null;
@@ -43,8 +50,8 @@ function QuestionnaireForm(props) {
43
50
  }
44
51
  } },
45
52
  questionnaire.title && React.createElement("h1", null, questionnaire.title),
46
- questionnaire.item && React.createElement(QuestionnaireFormItemArray, { items: questionnaire.item, onChange: setItems }),
47
- React.createElement(Button, { type: "submit", size: "large" }, "OK")));
53
+ questionnaire.item && (React.createElement(QuestionnaireFormItemArray, { items: questionnaire.item, answers: answers, onChange: setItems })),
54
+ React.createElement(Button, { type: "submit", size: "large" }, props.submitButtonText || 'OK')));
48
55
  }
49
56
  function QuestionnaireFormItemArray(props) {
50
57
  const [responseItems, setResponseItems] = useState(buildInitialResponseItems(props.items));
@@ -55,11 +62,14 @@ function QuestionnaireFormItemArray(props) {
55
62
  props.onChange(newResponseItems);
56
63
  }
57
64
  return (React.createElement(React.Fragment, null, props.items.map((item, index) => {
65
+ if (!isQuestionEnabled(item, props.answers)) {
66
+ return null;
67
+ }
58
68
  if (item.type === QuestionnaireItemType.display) {
59
69
  return React.createElement("p", { key: item.linkId }, item.text);
60
70
  }
61
71
  if (item.type === QuestionnaireItemType.group) {
62
- return (React.createElement(QuestionnaireFormItem, { key: item.linkId, item: item, onChange: (newResponseItem) => setResponseItem(index, newResponseItem) }));
72
+ return (React.createElement(QuestionnaireFormItem, { key: item.linkId, item: item, answers: props.answers, onChange: (newResponseItem) => setResponseItem(index, newResponseItem) }));
63
73
  }
64
74
  if (item.type === QuestionnaireItemType.boolean) {
65
75
  const initial = item.initial && item.initial.length > 0 ? item.initial[0] : undefined;
@@ -71,7 +81,7 @@ function QuestionnaireFormItemArray(props) {
71
81
  }) })));
72
82
  }
73
83
  return (React.createElement(FormSection, { key: item.linkId, htmlFor: item.linkId, title: item.text || '' },
74
- React.createElement(QuestionnaireFormItem, { item: item, onChange: (newResponseItem) => setResponseItem(index, newResponseItem) })));
84
+ React.createElement(QuestionnaireFormItem, { item: item, answers: props.answers, onChange: (newResponseItem) => setResponseItem(index, newResponseItem) })));
75
85
  })));
76
86
  }
77
87
  function QuestionnaireFormItem(props) {
@@ -103,7 +113,7 @@ function QuestionnaireFormItem(props) {
103
113
  case QuestionnaireItemType.group:
104
114
  return (React.createElement("div", null,
105
115
  React.createElement("h3", null, item.text),
106
- item.item && React.createElement(QuestionnaireFormItemArray, { items: item.item, onChange: onChangeItem })));
116
+ item.item && (React.createElement(QuestionnaireFormItemArray, { items: item.item, answers: props.answers, onChange: onChangeItem }))));
107
117
  case QuestionnaireItemType.boolean:
108
118
  return (React.createElement(Checkbox, { name: name, defaultValue: initial === null || initial === void 0 ? void 0 : initial.valueBoolean, onChange: (newValue) => onChangeAnswer({ valueBoolean: newValue }) }));
109
119
  case QuestionnaireItemType.decimal:
@@ -214,6 +224,35 @@ function isDropDownChoice(item) {
214
224
  ((_c = (_b = (_a = e.valueCodeableConcept) === null || _a === void 0 ? void 0 : _a.coding) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.code) === 'drop-down';
215
225
  }));
216
226
  }
227
+ function isQuestionEnabled(item, answers) {
228
+ if (!item.enableWhen) {
229
+ return true;
230
+ }
231
+ const enableBehavior = item.enableBehavior || 'any';
232
+ for (const enableWhen of item.enableWhen) {
233
+ const expectedAnswer = getTypedPropertyValue({
234
+ type: 'QuestionnaireItemEnableWhen',
235
+ value: enableWhen,
236
+ }, 'answer[x]');
237
+ const actualAnswer = getTypedPropertyValue({
238
+ type: 'QuestionnaireResponseItemAnswer',
239
+ value: answers[enableWhen.question],
240
+ }, 'value[x]');
241
+ const match = deepEquals(expectedAnswer, actualAnswer);
242
+ if (enableBehavior === 'any' && match) {
243
+ return true;
244
+ }
245
+ if (enableBehavior === 'all' && !match) {
246
+ return false;
247
+ }
248
+ }
249
+ if (enableBehavior === 'any') {
250
+ return false;
251
+ }
252
+ else {
253
+ return true;
254
+ }
255
+ }
217
256
 
218
- export { QuestionnaireForm, QuestionnaireFormItem };
257
+ export { QuestionnaireForm, QuestionnaireFormItem, isQuestionEnabled };
219
258
  //# sourceMappingURL=QuestionnaireForm.js.map