@medplum/react 0.9.27 → 0.9.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/AddressDisplay.d.ts +6 -0
- package/dist/cjs/AddressInput.d.ts +8 -0
- package/dist/cjs/AnnotationInput.d.ts +8 -0
- package/dist/cjs/AttachmentArrayDisplay.d.ts +7 -0
- package/dist/cjs/AttachmentArrayInput.d.ts +9 -0
- package/dist/cjs/AttachmentDisplay.d.ts +7 -0
- package/dist/cjs/AttachmentInput.d.ts +9 -0
- package/dist/cjs/Autocomplete.d.ts +20 -0
- package/dist/cjs/Avatar.d.ts +12 -0
- package/dist/cjs/BackboneElementDisplay.d.ts +9 -0
- package/dist/cjs/BackboneElementInput.d.ts +9 -0
- package/dist/cjs/Button.d.ts +15 -0
- package/dist/cjs/CalendarInput.d.ts +16 -0
- package/dist/cjs/Checkbox.d.ts +12 -0
- package/dist/cjs/CheckboxFormSection.d.ts +9 -0
- package/dist/cjs/CodeInput.d.ts +9 -0
- package/dist/cjs/CodeableConceptDisplay.d.ts +6 -0
- package/dist/cjs/CodeableConceptInput.d.ts +9 -0
- package/dist/cjs/CodingDisplay.d.ts +6 -0
- package/dist/cjs/CodingInput.d.ts +9 -0
- package/dist/cjs/ContactDetailDisplay.d.ts +6 -0
- package/dist/cjs/ContactDetailInput.d.ts +8 -0
- package/dist/cjs/ContactPointDisplay.d.ts +6 -0
- package/dist/cjs/ContactPointInput.d.ts +8 -0
- package/dist/cjs/DateTimeInput.d.ts +23 -0
- package/dist/cjs/DefaultResourceTimeline.d.ts +6 -0
- package/dist/cjs/DescriptionList.d.ts +12 -0
- package/dist/cjs/DiagnosticReportDisplay.d.ts +12 -0
- package/dist/cjs/Dialog.d.ts +10 -0
- package/dist/cjs/Document.d.ts +7 -0
- package/dist/cjs/EncounterTimeline.d.ts +6 -0
- package/dist/cjs/ErrorBoundary.d.ts +18 -0
- package/dist/cjs/ExtensionInput.d.ts +8 -0
- package/dist/cjs/FhirPathDisplay.d.ts +9 -0
- package/dist/cjs/FhirPathTable.d.ts +29 -0
- package/dist/cjs/FooterLinks.d.ts +6 -0
- package/dist/cjs/Form.d.ts +8 -0
- package/dist/cjs/FormSection.d.ts +11 -0
- package/dist/cjs/FormUtils.d.ts +5 -0
- package/dist/cjs/GoogleButton.d.ts +8 -0
- package/dist/cjs/Header.d.ts +12 -0
- package/dist/cjs/HeaderSearchInput.d.ts +10 -0
- package/dist/cjs/HumanNameDisplay.d.ts +8 -0
- package/dist/cjs/HumanNameInput.d.ts +8 -0
- package/dist/cjs/IdentifierDisplay.d.ts +6 -0
- package/dist/cjs/IdentifierInput.d.ts +8 -0
- package/dist/cjs/Input.d.ts +22 -0
- package/dist/cjs/InputRow.d.ts +7 -0
- package/dist/cjs/Loading.d.ts +3 -0
- package/dist/cjs/Logo.d.ts +6 -0
- package/dist/cjs/MedplumLink.d.ts +13 -0
- package/dist/cjs/MedplumProvider.d.ts +34 -0
- package/dist/cjs/MenuItem.d.ts +9 -0
- package/dist/cjs/MenuSeparator.d.ts +3 -0
- package/dist/cjs/PatientTimeline.d.ts +6 -0
- package/dist/cjs/PeriodInput.d.ts +8 -0
- package/dist/cjs/PlanDefinitionBuilder.d.ts +7 -0
- package/dist/cjs/Popup.d.ts +14 -0
- package/dist/cjs/QuantityDisplay.d.ts +7 -0
- package/dist/cjs/QuantityInput.d.ts +8 -0
- package/dist/cjs/QuestionnaireBuilder.d.ts +8 -0
- package/dist/cjs/QuestionnaireForm.d.ts +14 -0
- package/dist/cjs/QuestionnaireUtils.d.ts +30 -0
- package/dist/cjs/RangeDisplay.d.ts +7 -0
- package/dist/cjs/RangeInput.d.ts +14 -0
- package/dist/cjs/RatioDisplay.d.ts +6 -0
- package/dist/cjs/RatioInput.d.ts +14 -0
- package/dist/cjs/ReferenceDisplay.d.ts +7 -0
- package/dist/cjs/ReferenceInput.d.ts +9 -0
- package/dist/cjs/RegisterForm.d.ts +18 -0
- package/dist/cjs/RequestGroupDisplay.d.ts +9 -0
- package/dist/cjs/ResourceArrayDisplay.d.ts +11 -0
- package/dist/cjs/ResourceArrayInput.d.ts +11 -0
- package/dist/cjs/ResourceBadge.d.ts +9 -0
- package/dist/cjs/ResourceBlame.d.ts +10 -0
- package/dist/cjs/ResourceDiff.d.ts +9 -0
- package/dist/cjs/ResourceDiffTable.d.ts +9 -0
- package/dist/cjs/ResourceForm.d.ts +10 -0
- package/dist/cjs/ResourceHistoryTable.d.ts +9 -0
- package/dist/cjs/ResourceInput.d.ts +12 -0
- package/dist/cjs/ResourceName.d.ts +7 -0
- package/dist/cjs/ResourcePropertyDisplay.d.ts +24 -0
- package/dist/cjs/ResourcePropertyInput.d.ts +21 -0
- package/dist/cjs/ResourceTable.d.ts +7 -0
- package/dist/cjs/ResourceTimeline.d.ts +11 -0
- package/dist/cjs/Scheduler.d.ts +7 -0
- package/dist/cjs/Scrollable.d.ts +9 -0
- package/dist/cjs/SearchControl.d.ts +40 -0
- package/dist/cjs/SearchControlField.d.ts +41 -0
- package/dist/cjs/SearchFieldEditor.d.ts +11 -0
- package/dist/cjs/SearchFilterEditor.d.ts +11 -0
- package/dist/cjs/SearchFilterValueDialog.d.ts +15 -0
- package/dist/cjs/SearchFilterValueDisplay.d.ts +7 -0
- package/dist/cjs/SearchFilterValueInput.d.ts +12 -0
- package/dist/cjs/SearchPopupMenu.d.ts +15 -0
- package/dist/cjs/SearchUtils.d.ts +174 -0
- package/dist/cjs/Select.d.ts +16 -0
- package/dist/cjs/ServiceRequestTimeline.d.ts +6 -0
- package/dist/cjs/SignInForm.d.ts +17 -0
- package/dist/cjs/StatusBadge.d.ts +6 -0
- package/dist/cjs/SubMenu.d.ts +7 -0
- package/dist/cjs/Tab.d.ts +12 -0
- package/dist/cjs/TabList.d.ts +10 -0
- package/dist/cjs/TabPanel.d.ts +6 -0
- package/dist/cjs/TabSwitch.d.ts +6 -0
- package/dist/cjs/TextArea.d.ts +18 -0
- package/dist/cjs/Timeline.d.ts +17 -0
- package/dist/cjs/TimingInput.d.ts +8 -0
- package/dist/cjs/TitleBar.d.ts +6 -0
- package/dist/cjs/UploadButton.d.ts +7 -0
- package/dist/cjs/constants.d.ts +1 -0
- package/dist/cjs/index.d.ts +87 -0
- package/dist/cjs/index.js +387 -196
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.min.js +1 -1
- package/dist/cjs/index.min.js.map +1 -1
- package/dist/cjs/stories/AddressInput.stories.d.ts +6 -0
- package/dist/cjs/stories/AttachmentArrayInput.stories.d.ts +6 -0
- package/dist/cjs/stories/AttachmentInput.stories.d.ts +6 -0
- package/dist/cjs/stories/Autocomplete.stories.d.ts +9 -0
- package/dist/cjs/stories/Avatar.stories.d.ts +10 -0
- package/dist/cjs/stories/Button.stories.d.ts +9 -0
- package/dist/cjs/stories/CodeableConceptDisplay.stories.d.ts +8 -0
- package/dist/cjs/stories/DiagnosticReportDisplay.stories.d.ts +5 -0
- package/dist/cjs/stories/Dialog.stories.d.ts +5 -0
- package/dist/cjs/stories/EncounterTimeline.stories.d.ts +5 -0
- package/dist/cjs/stories/FhirPathDisplay.stories.d.ts +7 -0
- package/dist/cjs/stories/FormSection.stories.d.ts +6 -0
- package/dist/cjs/stories/Header.stories.d.ts +8 -0
- package/dist/cjs/stories/Input.stories.d.ts +6 -0
- package/dist/cjs/stories/Loading.stories.d.ts +5 -0
- package/dist/cjs/stories/Logo.stories.d.ts +5 -0
- package/dist/cjs/stories/PatientTimeline.stories.d.ts +5 -0
- package/dist/cjs/stories/PlanDefinitionBuilder.stories.d.ts +5 -0
- package/dist/cjs/stories/QuestionnaireBuilder.stories.d.ts +7 -0
- package/dist/cjs/stories/QuestionnaireForm.stories.d.ts +11 -0
- package/dist/cjs/stories/ReferenceInput.stories.d.ts +6 -0
- package/dist/cjs/stories/RegisterForm.stories.d.ts +7 -0
- package/dist/cjs/stories/RequestGroupDisplay.stories.d.ts +5 -0
- package/dist/cjs/stories/ResourceBlame.stories.d.ts +5 -0
- package/dist/cjs/stories/ResourceForm.stories.d.ts +12 -0
- package/dist/cjs/stories/ResourceHistoryTable.stories.d.ts +5 -0
- package/dist/cjs/stories/ResourceTable.stories.d.ts +7 -0
- package/dist/cjs/stories/Scheduler.stories.d.ts +5 -0
- package/dist/cjs/stories/SearchControl.stories.d.ts +13 -0
- package/dist/cjs/stories/Select.stories.d.ts +6 -0
- package/dist/cjs/stories/SignInForm.stories.d.ts +8 -0
- package/dist/cjs/stories/StatusBadge.stories.d.ts +5 -0
- package/dist/cjs/stories/Tabs.stories.d.ts +6 -0
- package/dist/cjs/stories/Timeline.stories.d.ts +5 -0
- package/dist/cjs/stories/TimingInput.stories.d.ts +6 -0
- package/dist/cjs/stories/UploadButton.stories.d.ts +6 -0
- package/dist/cjs/styles.css +135 -130
- package/dist/cjs/test.setup.d.ts +1 -0
- package/dist/cjs/useResource.d.ts +8 -0
- package/dist/cjs/utils/blame.d.ts +8 -0
- package/dist/cjs/utils/date.d.ts +6 -0
- package/dist/cjs/utils/diff.d.ts +16 -0
- package/dist/cjs/utils/dom.d.ts +15 -0
- package/dist/cjs/utils/outcomes.d.ts +2 -0
- package/dist/cjs/utils/recaptcha.d.ts +12 -0
- package/dist/cjs/utils.d.ts +5 -0
- package/dist/esm/Autocomplete.d.ts +1 -0
- package/dist/esm/Autocomplete.js +5 -8
- package/dist/esm/Autocomplete.js.map +1 -1
- package/dist/esm/CalendarInput.d.ts +1 -0
- package/dist/esm/CalendarInput.js +6 -5
- package/dist/esm/CalendarInput.js.map +1 -1
- package/dist/esm/CodeInput.js +1 -1
- package/dist/esm/CodeInput.js.map +1 -1
- package/dist/esm/CodeableConceptDisplay.js +4 -2
- package/dist/esm/CodeableConceptDisplay.js.map +1 -1
- package/dist/esm/CodeableConceptInput.js +1 -1
- package/dist/esm/CodeableConceptInput.js.map +1 -1
- package/dist/esm/CodingInput.js +1 -1
- package/dist/esm/CodingInput.js.map +1 -1
- package/dist/esm/DateTimeInput.js +1 -3
- package/dist/esm/DateTimeInput.js.map +1 -1
- package/dist/esm/DiagnosticReportDisplay.js +2 -4
- package/dist/esm/DiagnosticReportDisplay.js.map +1 -1
- package/dist/esm/FhirPathTable.js +5 -2
- package/dist/esm/FhirPathTable.js.map +1 -1
- package/dist/esm/GoogleButton.js +2 -2
- package/dist/esm/GoogleButton.js.map +1 -1
- package/dist/esm/Header.js +7 -3
- package/dist/esm/Header.js.map +1 -1
- package/dist/esm/PlanDefinitionBuilder.js +108 -39
- package/dist/esm/PlanDefinitionBuilder.js.map +1 -1
- package/dist/esm/QuestionnaireBuilder.js +1 -1
- package/dist/esm/QuestionnaireBuilder.js.map +1 -1
- package/dist/esm/QuestionnaireForm.js +5 -1
- package/dist/esm/QuestionnaireForm.js.map +1 -1
- package/dist/esm/RegisterForm.js +2 -2
- package/dist/esm/RegisterForm.js.map +1 -1
- package/dist/esm/RequestGroupDisplay.js +3 -4
- package/dist/esm/RequestGroupDisplay.js.map +1 -1
- package/dist/esm/ResourceArrayInput.js +1 -2
- package/dist/esm/ResourceArrayInput.js.map +1 -1
- package/dist/esm/ResourceBlame.js +1 -1
- package/dist/esm/ResourceBlame.js.map +1 -1
- package/dist/esm/ResourceDiffTable.js +1 -1
- package/dist/esm/ResourceDiffTable.js.map +1 -1
- package/dist/esm/ResourceForm.js +1 -1
- package/dist/esm/ResourceForm.js.map +1 -1
- package/dist/esm/ResourceHistoryTable.js +6 -4
- package/dist/esm/ResourceHistoryTable.js.map +1 -1
- package/dist/esm/ResourceInput.d.ts +1 -0
- package/dist/esm/ResourceInput.js +4 -3
- package/dist/esm/ResourceInput.js.map +1 -1
- package/dist/esm/ResourcePropertyDisplay.js +5 -5
- package/dist/esm/ResourcePropertyDisplay.js.map +1 -1
- package/dist/esm/ResourcePropertyInput.js +3 -0
- package/dist/esm/ResourcePropertyInput.js.map +1 -1
- package/dist/esm/ResourceTable.js +1 -1
- package/dist/esm/ResourceTable.js.map +1 -1
- package/dist/esm/ResourceTimeline.js +13 -7
- package/dist/esm/ResourceTimeline.js.map +1 -1
- package/dist/esm/Scheduler.js +13 -6
- package/dist/esm/Scheduler.js.map +1 -1
- package/dist/esm/SearchControl.js +5 -2
- package/dist/esm/SearchControl.js.map +1 -1
- package/dist/esm/SearchFilterValueDisplay.js +2 -2
- package/dist/esm/SearchFilterValueDisplay.js.map +1 -1
- package/dist/esm/SearchUtils.js +2 -3
- package/dist/esm/SearchUtils.js.map +1 -1
- package/dist/esm/SignInForm.js +39 -2
- package/dist/esm/SignInForm.js.map +1 -1
- package/dist/esm/Timeline.js +2 -4
- package/dist/esm/Timeline.js.map +1 -1
- package/dist/esm/TimingInput.d.ts +8 -0
- package/dist/esm/TimingInput.js +90 -0
- package/dist/esm/TimingInput.js.map +1 -0
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/esm/stories/Autocomplete.stories.d.ts +1 -0
- package/dist/esm/stories/CodeableConceptDisplay.stories.d.ts +8 -0
- package/dist/esm/stories/TimingInput.stories.d.ts +6 -0
- package/dist/esm/styles.css +135 -130
- package/dist/esm/utils/recaptcha.js +10 -4
- package/dist/esm/utils/recaptcha.js.map +1 -1
- package/package.json +6 -6
- package/stats.html +4034 -0
- package/dist/esm/DateTimeDisplay.d.ts +0 -5
- package/dist/esm/DateTimeDisplay.js +0 -11
- package/dist/esm/DateTimeDisplay.js.map +0 -1
- package/dist/esm/PeriodDisplay.d.ts +0 -6
- package/dist/esm/PeriodDisplay.js +0 -16
- package/dist/esm/PeriodDisplay.js.map +0 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare function diff(original: string[], revised: string[]): Delta[];
|
|
2
|
+
export interface PathNode {
|
|
3
|
+
readonly i: number;
|
|
4
|
+
readonly j: number;
|
|
5
|
+
readonly prev: PathNode | undefined;
|
|
6
|
+
readonly snake: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface Delta {
|
|
9
|
+
readonly original: Chunk;
|
|
10
|
+
readonly revised: Chunk;
|
|
11
|
+
readonly type: 'change' | 'delete' | 'insert';
|
|
12
|
+
}
|
|
13
|
+
export interface Chunk {
|
|
14
|
+
readonly position: number;
|
|
15
|
+
readonly lines: string[];
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
/**
|
|
3
|
+
* Kills a browser event.
|
|
4
|
+
* Prevents default behavior.
|
|
5
|
+
* Stops event propagation.
|
|
6
|
+
* @param e The event.
|
|
7
|
+
*/
|
|
8
|
+
export declare function killEvent(e: Event | React.SyntheticEvent): void;
|
|
9
|
+
/**
|
|
10
|
+
* Returns true if the element is a checkbox or a table cell containing a checkbox.
|
|
11
|
+
* Table cells containing checkboxes are commonly accidentally clicked.
|
|
12
|
+
* @param el The HTML DOM element.
|
|
13
|
+
* @returns True if the element is a checkbox or a table cell containing a checkbox.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isCheckboxCell(el: Element): boolean;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamically loads the recaptcha script.
|
|
3
|
+
* We do not want to load the script on page load unless the user needs it.
|
|
4
|
+
* @param siteKey The reCAPTCHA site key, available from the reCAPTCHA admin page.
|
|
5
|
+
*/
|
|
6
|
+
export declare function initRecaptcha(siteKey: string): void;
|
|
7
|
+
/**
|
|
8
|
+
* Starts a request to generate a recapcha token.
|
|
9
|
+
* @param siteKey The reCAPTCHA site key, available from the reCAPTCHA admin page.
|
|
10
|
+
* @returns Promise to a recaptcha token for the current user.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getRecaptcha(siteKey: string): Promise<string>;
|
|
@@ -7,6 +7,7 @@ export interface AutocompleteProps<T> {
|
|
|
7
7
|
defaultValue?: T[];
|
|
8
8
|
className?: string;
|
|
9
9
|
placeholder?: string;
|
|
10
|
+
loadOnFocus?: boolean;
|
|
10
11
|
loadOptions: (input: string, signal: AbortSignal) => Promise<T[]>;
|
|
11
12
|
buildUnstructured?: (input: string) => T;
|
|
12
13
|
getId: (item: T) => string;
|
package/dist/esm/Autocomplete.js
CHANGED
|
@@ -5,7 +5,7 @@ function Autocomplete(props) {
|
|
|
5
5
|
var _a, _b;
|
|
6
6
|
const inputRef = useRef(null);
|
|
7
7
|
const [focused, setFocused] = useState(false);
|
|
8
|
-
const [lastValue, setLastValue] = useState(
|
|
8
|
+
const [lastValue, setLastValue] = useState(undefined);
|
|
9
9
|
const [timer, setTimer] = useState();
|
|
10
10
|
const [dropDownVisible, setDropDownVisible] = useState(false);
|
|
11
11
|
const [values, setValues] = useState((_a = props.defaultValue) !== null && _a !== void 0 ? _a : []);
|
|
@@ -59,8 +59,12 @@ function Autocomplete(props) {
|
|
|
59
59
|
}
|
|
60
60
|
function handleFocus() {
|
|
61
61
|
setFocused(true);
|
|
62
|
+
if (props.loadOnFocus) {
|
|
63
|
+
handleInput();
|
|
64
|
+
}
|
|
62
65
|
}
|
|
63
66
|
function handleBlur() {
|
|
67
|
+
tryAddOption();
|
|
64
68
|
setFocused(false);
|
|
65
69
|
dismissOnDelay();
|
|
66
70
|
}
|
|
@@ -198,13 +202,6 @@ function Autocomplete(props) {
|
|
|
198
202
|
// Nothing has changed, move on
|
|
199
203
|
return;
|
|
200
204
|
}
|
|
201
|
-
if (!value) {
|
|
202
|
-
setDropDownVisible(false);
|
|
203
|
-
setLastValue('');
|
|
204
|
-
setOptions([]);
|
|
205
|
-
setSelectedIndex(-1);
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
205
|
setLastValue(value);
|
|
209
206
|
const newAbortController = new AbortController();
|
|
210
207
|
setAbortController(newAbortController);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Autocomplete.js","sources":["../../src/Autocomplete.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { killEvent } from './utils/dom';\nimport './Autocomplete.css';\n\nexport interface AutocompleteProps<T> {\n name: string;\n multiple?: boolean;\n autofocus?: boolean;\n defaultValue?: T[];\n className?: string;\n placeholder?: string;\n loadOptions: (input: string, signal: AbortSignal) => Promise<T[]>;\n buildUnstructured?: (input: string) => T;\n getId: (item: T) => string;\n getIcon?: (item: T) => JSX.Element;\n getDisplay: (item: T) => JSX.Element;\n getHelpText?: (item: T) => string | undefined;\n onChange?: (values: T[]) => void;\n onCreateNew?: () => void;\n}\n\nexport function Autocomplete<T>(props: AutocompleteProps<T>): JSX.Element {\n const inputRef = useRef<HTMLInputElement>(null);\n const [focused, setFocused] = useState(false);\n const [lastValue, setLastValue] = useState('');\n const [timer, setTimer] = useState<number>();\n const [dropDownVisible, setDropDownVisible] = useState(false);\n const [values, setValues] = useState(props.defaultValue ?? []);\n const [options, setOptions] = useState<T[]>([]);\n const [selectedIndex, setSelectedIndex] = useState(-1);\n const [abortController, setAbortController] = useState<AbortController>();\n const [autoSubmit, setAutoSubmit] = useState<boolean>();\n\n const lastValueRef = useRef<string>();\n lastValueRef.current = lastValue;\n\n const timerRef = useRef<number>();\n timerRef.current = timer;\n\n const abortControllerRef = useRef<AbortController>();\n abortControllerRef.current = abortController;\n\n const autoSubmitRef = useRef<boolean>();\n autoSubmitRef.current = autoSubmit;\n\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n useEffect(() => {\n setValues(props.defaultValue ?? []);\n }, [props.defaultValue]);\n\n function setValuesWrapper(newValues: T[]): void {\n setValues(newValues);\n if (props.onChange) {\n props.onChange(newValues);\n }\n }\n\n /**\n * Adds an option to the list of selected options.\n * @param option The option.\n */\n function addOption(option: T): void {\n const inputElement = inputRef.current as HTMLInputElement;\n inputElement.value = '';\n\n const newValues = props.multiple ? [...values, option] : [option];\n setFocused(true);\n setDropDownVisible(false);\n setLastValue('');\n setOptions([]);\n setSelectedIndex(-1);\n setValuesWrapper(newValues);\n }\n\n function handleClick(): void {\n inputRef.current?.focus();\n }\n\n function handleFocus(): void {\n setFocused(true);\n }\n\n function handleBlur(): void {\n setFocused(false);\n dismissOnDelay();\n }\n\n /**\n * Handles an input event.\n * Clears existing timers.\n * Schedules a timer to execute the search after a short delay.\n */\n function handleInput(): void {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n setAbortController(undefined);\n }\n\n if (timerRef.current !== undefined) {\n window.clearTimeout(timerRef.current);\n }\n\n const newTimer = window.setTimeout(() => handleTimer(), 100);\n setTimer(newTimer);\n }\n\n function handleKeyDown(e: React.KeyboardEvent): void {\n switch (e.key) {\n case 'Enter':\n case 'Tab':\n handleSelectKey(e);\n break;\n\n case 'ArrowUp':\n moveSelection(-1);\n killEvent(e);\n break;\n\n case 'ArrowDown':\n moveSelection(1);\n killEvent(e);\n break;\n\n case 'Backspace':\n handleBackspaceKey(e);\n break;\n\n case ',':\n case ';':\n handleSeparatorKey(e);\n }\n }\n\n /**\n * Handles the \"enter\" or \"tab\" keys. The enter key logic is:\n * Try to add an option with tryAddOption. On success, cancel event.\n * Otherwise, let the browser handle the enter key normally.\n *\n * @param e The key down event.\n */\n function handleSelectKey(e: React.KeyboardEvent): void {\n if (!timerRef.current && !abortControllerRef.current && tryAddOption()) {\n killEvent(e);\n inputRef.current?.focus();\n } else {\n // The user pressed enter, but we don't have results yet.\n // We need to wait for the results to come in.\n setAutoSubmit(true);\n }\n }\n\n /**\n * Handles the \"backspace\" key. The backspace key logic is:\n * If the input is empty and there is at least one item, delete the last item.\n * Otherwise, let the browser handle the backspace key normally.\n *\n * @param e The key down event.\n */\n function handleBackspaceKey(e: React.KeyboardEvent): void {\n if (inputRef.current?.value) {\n // If there is still text in the input,\n // then handle backspace as normal.\n return;\n }\n\n if (values.length > 0) {\n // If there are selected items,\n // then delete the last item.\n killEvent(e);\n setValuesWrapper(values.slice(0, values.length - 1));\n }\n }\n\n /**\n * Handles a \"separator\" key (comma, semicolon, others?).\n *\n * The separator key logic is:\n * If the drop down is visible and something is selected, choose that.\n * If the drop down is visible but nothing is selected, choose the first.\n * If there is content in the input, use that as a \"gray\" option.\n * Otherwise, ignore.\n *\n * @param e The key down event.\n */\n function handleSeparatorKey(e: React.KeyboardEvent): void {\n tryAddOption();\n killEvent(e);\n inputRef.current?.focus();\n }\n\n /**\n * Tries to capture the existing input as an option.\n *\n * @return True if captured an option; false otherwise.\n */\n function tryAddOption(): boolean {\n let option: T | undefined;\n\n if (selectedIndex >= 0 && selectedIndex < options.length) {\n // Currently highlighted row\n option = options[selectedIndex];\n } else if (selectedIndex === -1 && options.length > 0) {\n // Default to first row\n option = options[0];\n } else if (props.buildUnstructured && inputRef.current?.value) {\n // Build semi-structured item\n option = props.buildUnstructured(inputRef.current.value);\n }\n\n if (!option) {\n return false;\n }\n\n addOption(option);\n return true;\n }\n\n /**\n * Handles a timer tick event.\n * If the contents of the input have changed, sends xhr to the server\n * for updated contents.\n */\n function handleTimer(): void {\n setTimer(undefined);\n\n const value = inputRef.current?.value?.trim() || '';\n if (value === lastValueRef.current) {\n // Nothing has changed, move on\n return;\n }\n\n if (!value) {\n setDropDownVisible(false);\n setLastValue('');\n setOptions([]);\n setSelectedIndex(-1);\n return;\n }\n\n setLastValue(value);\n\n const newAbortController = new AbortController();\n setAbortController(newAbortController);\n\n props\n .loadOptions(value, newAbortController.signal)\n .then((newOptions: T[]) => {\n if (!newAbortController.signal.aborted) {\n setDropDownVisible(newOptions.length > 0);\n setOptions(newOptions);\n setAbortController(undefined);\n if (autoSubmitRef.current) {\n addOption(newOptions[0]);\n setAutoSubmit(false);\n }\n }\n })\n .catch(console.log);\n }\n\n /**\n * Moves the selected row.\n * @param delta The amount to move the selection, up is negative.\n */\n function moveSelection(delta: number): void {\n let index = selectedIndex + delta;\n\n if (index < 0) {\n index = 0;\n } else if (index >= options.length) {\n index = options.length - 1;\n }\n\n setSelectedIndex(index);\n }\n\n /**\n * Handles a hover event.\n * @param _e The mouse event.\n * @param index The drop down option index.\n */\n function handleDropDownHover(_e: React.MouseEvent, index: number): void {\n setSelectedIndex(index);\n }\n\n /**\n * Handles a click event.\n * @param e The mouse event.\n * @param option The drop down option.\n */\n function handleDropDownClick(e: React.MouseEvent, option: T): void {\n killEvent(e);\n addOption(option);\n }\n\n /**\n * Dismisses the drop down menu after a slight delay.\n */\n function dismissOnDelay(): void {\n window.setTimeout(() => {\n setDropDownVisible(false);\n }, 200);\n }\n\n const baseClassName = props.className ?? 'medplum-autocomplete-container';\n\n return (\n <div\n data-testid=\"autocomplete\"\n className={baseClassName + (focused ? ' focused' : '')}\n onClick={() => handleClick()}\n >\n <ul onClick={() => handleClick()}>\n {values.map((value) => (\n <li key={props.getId(value)} data-testid=\"selected\" className=\"medplum-autocomplete-item choice\">\n {props.getDisplay(value)}\n </li>\n ))}\n <li className=\"medplum-autocomplete-item\">\n <input\n type=\"text\"\n autoFocus={props.autofocus}\n placeholder={values.length === 0 ? props.placeholder : undefined}\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n spellCheck=\"true\"\n onFocus={() => handleFocus()}\n onBlur={() => handleBlur()}\n onChange={() => handleInput()}\n onInput={() => handleInput()}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e)}\n ref={inputRef}\n data-testid=\"input-element\"\n />\n </li>\n </ul>\n {dropDownVisible && (\n <div className=\"medplum-autocomplete\" data-testid=\"dropdown\">\n {options.map((option, index) => (\n <div\n key={props.getId(option)}\n className={\n index === selectedIndex\n ? 'medplum-autocomplete-row medplum-autocomplete-active'\n : 'medplum-autocomplete-row'\n }\n onMouseOver={(e) => handleDropDownHover(e, index)}\n onClick={(e) => handleDropDownClick(e, option)}\n >\n {props.getIcon && <div className=\"medplum-autocomplete-icon\">{props.getIcon(option)}</div>}\n <div className=\"medplum-autocomplete-label\">\n {props.getDisplay(option)}\n {props.getHelpText && <div className=\"medplum-autocomplete-help-text\">{props.getHelpText(option)}</div>}\n </div>\n </div>\n ))}\n {props.onCreateNew && (\n <div className=\"medplum-autocomplete-row\" onClick={props.onCreateNew}>\n <div className=\"medplum-autocomplete-label\">Create new...</div>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Autocomplete.js","sources":["../../src/Autocomplete.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { killEvent } from './utils/dom';\nimport './Autocomplete.css';\n\nexport interface AutocompleteProps<T> {\n name: string;\n multiple?: boolean;\n autofocus?: boolean;\n defaultValue?: T[];\n className?: string;\n placeholder?: string;\n loadOnFocus?: boolean;\n loadOptions: (input: string, signal: AbortSignal) => Promise<T[]>;\n buildUnstructured?: (input: string) => T;\n getId: (item: T) => string;\n getIcon?: (item: T) => JSX.Element;\n getDisplay: (item: T) => JSX.Element;\n getHelpText?: (item: T) => string | undefined;\n onChange?: (values: T[]) => void;\n onCreateNew?: () => void;\n}\n\nexport function Autocomplete<T>(props: AutocompleteProps<T>): JSX.Element {\n const inputRef = useRef<HTMLInputElement>(null);\n const [focused, setFocused] = useState(false);\n const [lastValue, setLastValue] = useState<string | undefined>(undefined);\n const [timer, setTimer] = useState<number>();\n const [dropDownVisible, setDropDownVisible] = useState(false);\n const [values, setValues] = useState(props.defaultValue ?? []);\n const [options, setOptions] = useState<T[]>([]);\n const [selectedIndex, setSelectedIndex] = useState(-1);\n const [abortController, setAbortController] = useState<AbortController>();\n const [autoSubmit, setAutoSubmit] = useState<boolean>();\n\n const lastValueRef = useRef<string>();\n lastValueRef.current = lastValue;\n\n const timerRef = useRef<number>();\n timerRef.current = timer;\n\n const abortControllerRef = useRef<AbortController>();\n abortControllerRef.current = abortController;\n\n const autoSubmitRef = useRef<boolean>();\n autoSubmitRef.current = autoSubmit;\n\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n useEffect(() => {\n setValues(props.defaultValue ?? []);\n }, [props.defaultValue]);\n\n function setValuesWrapper(newValues: T[]): void {\n setValues(newValues);\n if (props.onChange) {\n props.onChange(newValues);\n }\n }\n\n /**\n * Adds an option to the list of selected options.\n * @param option The option.\n */\n function addOption(option: T): void {\n const inputElement = inputRef.current as HTMLInputElement;\n inputElement.value = '';\n\n const newValues = props.multiple ? [...values, option] : [option];\n setFocused(true);\n setDropDownVisible(false);\n setLastValue('');\n setOptions([]);\n setSelectedIndex(-1);\n setValuesWrapper(newValues);\n }\n\n function handleClick(): void {\n inputRef.current?.focus();\n }\n\n function handleFocus(): void {\n setFocused(true);\n if (props.loadOnFocus) {\n handleInput();\n }\n }\n\n function handleBlur(): void {\n tryAddOption();\n setFocused(false);\n dismissOnDelay();\n }\n\n /**\n * Handles an input event.\n * Clears existing timers.\n * Schedules a timer to execute the search after a short delay.\n */\n function handleInput(): void {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n setAbortController(undefined);\n }\n\n if (timerRef.current !== undefined) {\n window.clearTimeout(timerRef.current);\n }\n\n const newTimer = window.setTimeout(() => handleTimer(), 100);\n setTimer(newTimer);\n }\n\n function handleKeyDown(e: React.KeyboardEvent): void {\n switch (e.key) {\n case 'Enter':\n case 'Tab':\n handleSelectKey(e);\n break;\n\n case 'ArrowUp':\n moveSelection(-1);\n killEvent(e);\n break;\n\n case 'ArrowDown':\n moveSelection(1);\n killEvent(e);\n break;\n\n case 'Backspace':\n handleBackspaceKey(e);\n break;\n\n case ',':\n case ';':\n handleSeparatorKey(e);\n }\n }\n\n /**\n * Handles the \"enter\" or \"tab\" keys. The enter key logic is:\n * Try to add an option with tryAddOption. On success, cancel event.\n * Otherwise, let the browser handle the enter key normally.\n *\n * @param e The key down event.\n */\n function handleSelectKey(e: React.KeyboardEvent): void {\n if (!timerRef.current && !abortControllerRef.current && tryAddOption()) {\n killEvent(e);\n inputRef.current?.focus();\n } else {\n // The user pressed enter, but we don't have results yet.\n // We need to wait for the results to come in.\n setAutoSubmit(true);\n }\n }\n\n /**\n * Handles the \"backspace\" key. The backspace key logic is:\n * If the input is empty and there is at least one item, delete the last item.\n * Otherwise, let the browser handle the backspace key normally.\n *\n * @param e The key down event.\n */\n function handleBackspaceKey(e: React.KeyboardEvent): void {\n if (inputRef.current?.value) {\n // If there is still text in the input,\n // then handle backspace as normal.\n return;\n }\n\n if (values.length > 0) {\n // If there are selected items,\n // then delete the last item.\n killEvent(e);\n setValuesWrapper(values.slice(0, values.length - 1));\n }\n }\n\n /**\n * Handles a \"separator\" key (comma, semicolon, others?).\n *\n * The separator key logic is:\n * If the drop down is visible and something is selected, choose that.\n * If the drop down is visible but nothing is selected, choose the first.\n * If there is content in the input, use that as a \"gray\" option.\n * Otherwise, ignore.\n *\n * @param e The key down event.\n */\n function handleSeparatorKey(e: React.KeyboardEvent): void {\n tryAddOption();\n killEvent(e);\n inputRef.current?.focus();\n }\n\n /**\n * Tries to capture the existing input as an option.\n *\n * @return True if captured an option; false otherwise.\n */\n function tryAddOption(): boolean {\n let option: T | undefined;\n\n if (selectedIndex >= 0 && selectedIndex < options.length) {\n // Currently highlighted row\n option = options[selectedIndex];\n } else if (selectedIndex === -1 && options.length > 0) {\n // Default to first row\n option = options[0];\n } else if (props.buildUnstructured && inputRef.current?.value) {\n // Build semi-structured item\n option = props.buildUnstructured(inputRef.current.value);\n }\n\n if (!option) {\n return false;\n }\n\n addOption(option);\n return true;\n }\n\n /**\n * Handles a timer tick event.\n * If the contents of the input have changed, sends xhr to the server\n * for updated contents.\n */\n function handleTimer(): void {\n setTimer(undefined);\n\n const value = inputRef.current?.value?.trim() || '';\n if (value === lastValueRef.current) {\n // Nothing has changed, move on\n return;\n }\n\n setLastValue(value);\n\n const newAbortController = new AbortController();\n setAbortController(newAbortController);\n\n props\n .loadOptions(value, newAbortController.signal)\n .then((newOptions: T[]) => {\n if (!newAbortController.signal.aborted) {\n setDropDownVisible(newOptions.length > 0);\n setOptions(newOptions);\n setAbortController(undefined);\n if (autoSubmitRef.current) {\n addOption(newOptions[0]);\n setAutoSubmit(false);\n }\n }\n })\n .catch(console.log);\n }\n\n /**\n * Moves the selected row.\n * @param delta The amount to move the selection, up is negative.\n */\n function moveSelection(delta: number): void {\n let index = selectedIndex + delta;\n\n if (index < 0) {\n index = 0;\n } else if (index >= options.length) {\n index = options.length - 1;\n }\n\n setSelectedIndex(index);\n }\n\n /**\n * Handles a hover event.\n * @param _e The mouse event.\n * @param index The drop down option index.\n */\n function handleDropDownHover(_e: React.MouseEvent, index: number): void {\n setSelectedIndex(index);\n }\n\n /**\n * Handles a click event.\n * @param e The mouse event.\n * @param option The drop down option.\n */\n function handleDropDownClick(e: React.MouseEvent, option: T): void {\n killEvent(e);\n addOption(option);\n }\n\n /**\n * Dismisses the drop down menu after a slight delay.\n */\n function dismissOnDelay(): void {\n window.setTimeout(() => {\n setDropDownVisible(false);\n }, 200);\n }\n\n const baseClassName = props.className ?? 'medplum-autocomplete-container';\n\n return (\n <div\n data-testid=\"autocomplete\"\n className={baseClassName + (focused ? ' focused' : '')}\n onClick={() => handleClick()}\n >\n <ul onClick={() => handleClick()}>\n {values.map((value) => (\n <li key={props.getId(value)} data-testid=\"selected\" className=\"medplum-autocomplete-item choice\">\n {props.getDisplay(value)}\n </li>\n ))}\n <li className=\"medplum-autocomplete-item\">\n <input\n type=\"text\"\n autoFocus={props.autofocus}\n placeholder={values.length === 0 ? props.placeholder : undefined}\n autoComplete=\"off\"\n autoCapitalize=\"off\"\n spellCheck=\"true\"\n onFocus={() => handleFocus()}\n onBlur={() => handleBlur()}\n onChange={() => handleInput()}\n onInput={() => handleInput()}\n onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(e)}\n ref={inputRef}\n data-testid=\"input-element\"\n />\n </li>\n </ul>\n {dropDownVisible && (\n <div className=\"medplum-autocomplete\" data-testid=\"dropdown\">\n {options.map((option, index) => (\n <div\n key={props.getId(option)}\n className={\n index === selectedIndex\n ? 'medplum-autocomplete-row medplum-autocomplete-active'\n : 'medplum-autocomplete-row'\n }\n onMouseOver={(e) => handleDropDownHover(e, index)}\n onClick={(e) => handleDropDownClick(e, option)}\n >\n {props.getIcon && <div className=\"medplum-autocomplete-icon\">{props.getIcon(option)}</div>}\n <div className=\"medplum-autocomplete-label\">\n {props.getDisplay(option)}\n {props.getHelpText && <div className=\"medplum-autocomplete-help-text\">{props.getHelpText(option)}</div>}\n </div>\n </div>\n ))}\n {props.onCreateNew && (\n <div className=\"medplum-autocomplete-row\" onClick={props.onCreateNew}>\n <div className=\"medplum-autocomplete-label\">Create new...</div>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -11,12 +11,14 @@ function getMonthString(date) {
|
|
|
11
11
|
return date.toLocaleString('default', { month: 'long' }) + ' ' + date.getFullYear();
|
|
12
12
|
}
|
|
13
13
|
function CalendarInput(props) {
|
|
14
|
+
const { onChangeMonth, onClick } = props;
|
|
14
15
|
const [month, setMonth] = useState(getStartMonth);
|
|
15
16
|
function moveMonth(delta) {
|
|
16
17
|
setMonth((currMonth) => {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const newMonth = new Date(currMonth.getTime());
|
|
19
|
+
newMonth.setMonth(currMonth.getMonth() + delta);
|
|
20
|
+
onChangeMonth(newMonth);
|
|
21
|
+
return newMonth;
|
|
20
22
|
});
|
|
21
23
|
}
|
|
22
24
|
const grid = useMemo(() => buildGrid(month, props.slots), [month, props.slots]);
|
|
@@ -36,7 +38,7 @@ function CalendarInput(props) {
|
|
|
36
38
|
React.createElement("th", null, "THU"),
|
|
37
39
|
React.createElement("th", null, "FRI"),
|
|
38
40
|
React.createElement("th", null, "SAT"))),
|
|
39
|
-
React.createElement("tbody", null, grid.map((week, weekIndex) => (React.createElement("tr", { key: 'week-' + weekIndex }, week.map((day, dayIndex) => (React.createElement("td", { key: 'day-' + dayIndex }, day && (React.createElement("button", { disabled: !day.available, onClick: () =>
|
|
41
|
+
React.createElement("tbody", null, grid.map((week, weekIndex) => (React.createElement("tr", { key: 'week-' + weekIndex }, week.map((day, dayIndex) => (React.createElement("td", { key: 'day-' + dayIndex }, day && (React.createElement("button", { disabled: !day.available, onClick: () => onClick(day.date) }, day.date.getDate()))))))))))));
|
|
40
42
|
}
|
|
41
43
|
function getStartMonth() {
|
|
42
44
|
const result = new Date();
|
|
@@ -55,7 +57,6 @@ function buildGrid(startDate, slots) {
|
|
|
55
57
|
while (d.getMonth() === startDate.getMonth()) {
|
|
56
58
|
row.push({
|
|
57
59
|
date: new Date(d.getTime()),
|
|
58
|
-
// available: isAvailable(d),
|
|
59
60
|
available: isDayAvailable(d, slots),
|
|
60
61
|
});
|
|
61
62
|
if (d.getDay() === 6) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CalendarInput.js","sources":["../../src/CalendarInput.tsx"],"sourcesContent":["import React, { useMemo, useState } from 'react';\nimport { Button } from './Button';\nimport { InputRow } from './InputRow';\nimport
|
|
1
|
+
{"version":3,"file":"CalendarInput.js","sources":["../../src/CalendarInput.tsx"],"sourcesContent":["import { Slot } from '@medplum/fhirtypes';\nimport React, { useMemo, useState } from 'react';\nimport { Button } from './Button';\nimport { InputRow } from './InputRow';\nimport './CalendarInput.css';\n\nexport interface CalendarInputProps {\n slots: Slot[];\n onChangeMonth: (date: Date) => void;\n onClick: (date: Date) => void;\n}\n\n/**\n * Returns a month display string (e.g. \"January 2020\").\n * @param date Any date within the month.\n * @returns The month display string (e.g. \"January 2020\")\n */\nexport function getMonthString(date: Date): string {\n return date.toLocaleString('default', { month: 'long' }) + ' ' + date.getFullYear();\n}\n\ninterface CalendarCell {\n date: Date;\n available: boolean;\n}\n\ntype OptionalCalendarCell = CalendarCell | undefined;\n\nexport function CalendarInput(props: CalendarInputProps): JSX.Element {\n const { onChangeMonth, onClick } = props;\n const [month, setMonth] = useState<Date>(getStartMonth);\n\n function moveMonth(delta: number): void {\n setMonth((currMonth) => {\n const newMonth = new Date(currMonth.getTime());\n newMonth.setMonth(currMonth.getMonth() + delta);\n onChangeMonth(newMonth);\n return newMonth;\n });\n }\n\n const grid = useMemo(() => buildGrid(month, props.slots), [month, props.slots]);\n\n return (\n <div>\n <InputRow>\n <p style={{ flex: 1 }}>{getMonthString(month)}</p>\n <p>\n <Button label=\"Previous month\" onClick={() => moveMonth(-1)}>\n <\n </Button>\n <Button label=\"Next month\" onClick={() => moveMonth(1)}>\n >\n </Button>\n </p>\n </InputRow>\n <table className=\"medplum-calendar-table\">\n <thead>\n <tr>\n <th>SUN</th>\n <th>MON</th>\n <th>TUE</th>\n <th>WED</th>\n <th>THU</th>\n <th>FRI</th>\n <th>SAT</th>\n </tr>\n </thead>\n <tbody>\n {grid.map((week, weekIndex) => (\n <tr key={'week-' + weekIndex}>\n {week.map((day, dayIndex) => (\n <td key={'day-' + dayIndex}>\n {day && (\n <button disabled={!day.available} onClick={() => onClick(day.date)}>\n {day.date.getDate()}\n </button>\n )}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nexport function getStartMonth(): Date {\n const result = new Date();\n result.setDate(1);\n result.setHours(0, 0, 0, 0);\n return result;\n}\n\nfunction buildGrid(startDate: Date, slots: Slot[]): OptionalCalendarCell[][] {\n const d = new Date(startDate.getFullYear(), startDate.getMonth());\n const grid: OptionalCalendarCell[][] = [];\n let row: OptionalCalendarCell[] = [];\n\n // Fill leading empty days\n for (let i = 0; i < d.getDay(); i++) {\n row.push(undefined);\n }\n\n while (d.getMonth() === startDate.getMonth()) {\n row.push({\n date: new Date(d.getTime()),\n available: isDayAvailable(d, slots),\n });\n\n if (d.getDay() === 6) {\n grid.push(row);\n row = [];\n }\n\n d.setDate(d.getDate() + 1);\n }\n\n // Fill trailing empty days\n if (d.getDay() !== 0) {\n for (let i = d.getDay(); i < 7; i++) {\n row.push(undefined);\n }\n grid.push(row);\n }\n\n return grid;\n}\n\n/**\n * Returns true if the given date is available for booking.\n * @param day The day to check.\n * @param slots The list of available slots.\n * @returns True if there are any available slots for the day.\n */\nfunction isDayAvailable(day: Date, slots: Slot[]): boolean {\n // Note that slot start and end time may or may not be in UTC.\n for (const slot of slots) {\n const slotStart = new Date(slot.start as string);\n if (\n slotStart.getFullYear() === day.getFullYear() &&\n slotStart.getMonth() === day.getMonth() &&\n slotStart.getDate() === day.getDate()\n ) {\n return true;\n }\n }\n\n return false;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/CodeInput.js
CHANGED
|
@@ -17,7 +17,7 @@ function CodeInput(props) {
|
|
|
17
17
|
contains.forEach((e) => (cachedDisplayValues[e.code] = e.display));
|
|
18
18
|
return contains.map((e) => e.code);
|
|
19
19
|
});
|
|
20
|
-
}, buildUnstructured: (str) => str, getId: (item) => item, getDisplay: (item) => React.createElement(React.Fragment, null, cachedDisplayValues[item] || item), name: props.name, defaultValue: defaultValue, onChange: (values) => {
|
|
20
|
+
}, buildUnstructured: (str) => str, getId: (item) => item, getDisplay: (item) => React.createElement(React.Fragment, null, cachedDisplayValues[item] || item), name: props.name, defaultValue: defaultValue, loadOnFocus: true, onChange: (values) => {
|
|
21
21
|
if (props.onChange) {
|
|
22
22
|
props.onChange(values[0]);
|
|
23
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeInput.js","sources":["../../src/CodeInput.tsx"],"sourcesContent":["import { ElementDefinition, ValueSet, ValueSetExpansion, ValueSetExpansionContains } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { Autocomplete } from './Autocomplete';\nimport { useMedplum } from './MedplumProvider';\n\nexport interface CodeInputProps {\n property: ElementDefinition;\n name: string;\n defaultValue?: string;\n onChange?: (value: string) => void;\n}\n\nconst cachedDisplayValues: Record<string, string> = {};\n\nexport function CodeInput(props: CodeInputProps): JSX.Element {\n const medplum = useMedplum();\n\n let defaultValue = undefined;\n if (props.defaultValue) {\n defaultValue = [props.defaultValue];\n }\n\n return (\n <Autocomplete\n loadOptions={(input: string): Promise<string[]> => {\n const system = props.property.binding?.valueSet as string;\n return medplum.searchValueSet(system, input).then((valueSet: ValueSet) => {\n const contains = (valueSet.expansion as ValueSetExpansion).contains as ValueSetExpansionContains[];\n contains.forEach((e) => (cachedDisplayValues[e.code as string] = e.display as string));\n return contains.map((e) => e.code as string);\n });\n }}\n buildUnstructured={(str: string) => str}\n getId={(item: string) => item}\n getDisplay={(item: string) => <>{cachedDisplayValues[item] || item}</>}\n name={props.name}\n defaultValue={defaultValue}\n onChange={(values: string[]) => {\n if (props.onChange) {\n props.onChange(values[0]);\n }\n }}\n />\n );\n}\n"],"names":[],"mappings":";;;;AAYA,MAAM,mBAAmB,GAA2B,EAAE,CAAC;AAEjD,SAAU,SAAS,CAAC,KAAqB,EAAA;AAC7C,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,YAAY,GAAG,SAAS,CAAC;IAC7B,IAAI,KAAK,CAAC,YAAY,EAAE;AACtB,QAAA,YAAY,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AACrC,KAAA;IAED,QACE,oBAAC,YAAY,EAAA,EACX,WAAW,EAAE,CAAC,KAAa,KAAuB;;YAChD,MAAM,MAAM,GAAG,CAAA,EAAA,GAAA,KAAK,CAAC,QAAQ,CAAC,OAAO,MAAE,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,QAAkB,CAAC;AAC1D,YAAA,OAAO,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,QAAkB,KAAI;AACvE,gBAAA,MAAM,QAAQ,GAAI,QAAQ,CAAC,SAA+B,CAAC,QAAuC,CAAC;gBACnG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,mBAAmB,CAAC,CAAC,CAAC,IAAc,CAAC,GAAG,CAAC,CAAC,OAAiB,CAAC,CAAC,CAAC;AACvF,gBAAA,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAc,CAAC,CAAC;AAC/C,aAAC,CAAC,CAAC;SACJ,EACD,iBAAiB,EAAE,CAAC,GAAW,KAAK,GAAG,EACvC,KAAK,EAAE,CAAC,IAAY,KAAK,IAAI,EAC7B,UAAU,EAAE,CAAC,IAAY,KAAK,
|
|
1
|
+
{"version":3,"file":"CodeInput.js","sources":["../../src/CodeInput.tsx"],"sourcesContent":["import { ElementDefinition, ValueSet, ValueSetExpansion, ValueSetExpansionContains } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { Autocomplete } from './Autocomplete';\nimport { useMedplum } from './MedplumProvider';\n\nexport interface CodeInputProps {\n property: ElementDefinition;\n name: string;\n defaultValue?: string;\n onChange?: (value: string) => void;\n}\n\nconst cachedDisplayValues: Record<string, string> = {};\n\nexport function CodeInput(props: CodeInputProps): JSX.Element {\n const medplum = useMedplum();\n\n let defaultValue = undefined;\n if (props.defaultValue) {\n defaultValue = [props.defaultValue];\n }\n\n return (\n <Autocomplete\n loadOptions={(input: string): Promise<string[]> => {\n const system = props.property.binding?.valueSet as string;\n return medplum.searchValueSet(system, input).then((valueSet: ValueSet) => {\n const contains = (valueSet.expansion as ValueSetExpansion).contains as ValueSetExpansionContains[];\n contains.forEach((e) => (cachedDisplayValues[e.code as string] = e.display as string));\n return contains.map((e) => e.code as string);\n });\n }}\n buildUnstructured={(str: string) => str}\n getId={(item: string) => item}\n getDisplay={(item: string) => <>{cachedDisplayValues[item] || item}</>}\n name={props.name}\n defaultValue={defaultValue}\n loadOnFocus={true}\n onChange={(values: string[]) => {\n if (props.onChange) {\n props.onChange(values[0]);\n }\n }}\n />\n );\n}\n"],"names":[],"mappings":";;;;AAYA,MAAM,mBAAmB,GAA2B,EAAE,CAAC;AAEjD,SAAU,SAAS,CAAC,KAAqB,EAAA;AAC7C,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,YAAY,GAAG,SAAS,CAAC;IAC7B,IAAI,KAAK,CAAC,YAAY,EAAE;AACtB,QAAA,YAAY,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AACrC,KAAA;IAED,QACE,oBAAC,YAAY,EAAA,EACX,WAAW,EAAE,CAAC,KAAa,KAAuB;;YAChD,MAAM,MAAM,GAAG,CAAA,EAAA,GAAA,KAAK,CAAC,QAAQ,CAAC,OAAO,MAAE,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,QAAkB,CAAC;AAC1D,YAAA,OAAO,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,QAAkB,KAAI;AACvE,gBAAA,MAAM,QAAQ,GAAI,QAAQ,CAAC,SAA+B,CAAC,QAAuC,CAAC;gBACnG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,mBAAmB,CAAC,CAAC,CAAC,IAAc,CAAC,GAAG,CAAC,CAAC,OAAiB,CAAC,CAAC,CAAC;AACvF,gBAAA,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAc,CAAC,CAAC;AAC/C,aAAC,CAAC,CAAC;SACJ,EACD,iBAAiB,EAAE,CAAC,GAAW,KAAK,GAAG,EACvC,KAAK,EAAE,CAAC,IAAY,KAAK,IAAI,EAC7B,UAAU,EAAE,CAAC,IAAY,KAAK,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAI,EACtE,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,IAAI,EACjB,QAAQ,EAAE,CAAC,MAAgB,KAAI;YAC7B,IAAI,KAAK,CAAC,QAAQ,EAAE;gBAClB,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3B,aAAA;SACF,EAAA,CACD,EACF;AACJ;;;;"}
|
|
@@ -9,8 +9,10 @@ function CodeableConceptDisplay(props) {
|
|
|
9
9
|
if (value.text) {
|
|
10
10
|
return React.createElement(React.Fragment, null, value.text);
|
|
11
11
|
}
|
|
12
|
-
if (value.coding
|
|
13
|
-
return React.createElement(
|
|
12
|
+
if (value.coding) {
|
|
13
|
+
return (React.createElement(React.Fragment, null, value.coding.map((coding, index) => (React.createElement(React.Fragment, { key: 'coding-' + index },
|
|
14
|
+
index > 0 && React.createElement(React.Fragment, null, ', '),
|
|
15
|
+
React.createElement(CodingDisplay, { value: coding }))))));
|
|
14
16
|
}
|
|
15
17
|
return null;
|
|
16
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeableConceptDisplay.js","sources":["../../src/CodeableConceptDisplay.tsx"],"sourcesContent":["import { CodeableConcept } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { CodingDisplay } from './CodingDisplay';\n\nexport interface CodeableConceptDisplayProps {\n value?: CodeableConcept;\n}\n\nexport function CodeableConceptDisplay(props: CodeableConceptDisplayProps): JSX.Element | null {\n const value = props.value;\n if (!value) {\n return null;\n }\n\n if (value.text) {\n return <>{value.text}</>;\n }\n\n if (value.coding
|
|
1
|
+
{"version":3,"file":"CodeableConceptDisplay.js","sources":["../../src/CodeableConceptDisplay.tsx"],"sourcesContent":["import { CodeableConcept } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { CodingDisplay } from './CodingDisplay';\n\nexport interface CodeableConceptDisplayProps {\n value?: CodeableConcept;\n}\n\nexport function CodeableConceptDisplay(props: CodeableConceptDisplayProps): JSX.Element | null {\n const value = props.value;\n if (!value) {\n return null;\n }\n\n if (value.text) {\n return <>{value.text}</>;\n }\n\n if (value.coding) {\n return (\n <>\n {value.coding.map((coding, index) => (\n <React.Fragment key={'coding-' + index}>\n {index > 0 && <>{', '}</>}\n <CodingDisplay value={coding} />\n </React.Fragment>\n ))}\n </>\n );\n }\n\n return null;\n}\n"],"names":[],"mappings":";;;AAQM,SAAU,sBAAsB,CAAC,KAAkC,EAAA;AACvE,IAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1B,IAAI,CAAC,KAAK,EAAE;AACV,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;IAED,IAAI,KAAK,CAAC,IAAI,EAAE;AACd,QAAA,OAAO,KAAG,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAA,KAAK,CAAC,IAAI,CAAI,CAAC;AAC1B,KAAA;IAED,IAAI,KAAK,CAAC,MAAM,EAAE;QAChB,QACE,KACG,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAA,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,MAC9B,KAAA,CAAA,aAAA,CAAC,KAAK,CAAC,QAAQ,EAAA,EAAC,GAAG,EAAE,SAAS,GAAG,KAAK,EAAA;AACnC,YAAA,KAAK,GAAG,CAAC,IAAI,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAG,IAAI,CAAI;YACzB,KAAC,CAAA,aAAA,CAAA,aAAa,EAAC,EAAA,KAAK,EAAE,MAAM,EAAI,CAAA,CACjB,CAClB,CAAC,CACD,EACH;AACH,KAAA;AAED,IAAA,OAAO,IAAI,CAAC;AACd;;;;"}
|
|
@@ -15,7 +15,7 @@ function CodeableConceptInput(props) {
|
|
|
15
15
|
return medplum.searchValueSet(system, input).then((valueSet) => {
|
|
16
16
|
return valueSet.expansion.contains.map(valueSetElementToCodeableConcept);
|
|
17
17
|
});
|
|
18
|
-
}, buildUnstructured: buildUnstructured, getId: getId, getDisplay: getDisplay, name: props.name, defaultValue: defaultValue, onChange: (values) => {
|
|
18
|
+
}, buildUnstructured: buildUnstructured, getId: getId, getDisplay: getDisplay, name: props.name, defaultValue: defaultValue, loadOnFocus: true, onChange: (values) => {
|
|
19
19
|
if (props.onChange) {
|
|
20
20
|
props.onChange(values[0]);
|
|
21
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeableConceptInput.js","sources":["../../src/CodeableConceptInput.tsx"],"sourcesContent":["import { stringify } from '@medplum/core';\nimport {\n CodeableConcept,\n ElementDefinition,\n ValueSet,\n ValueSetExpansion,\n ValueSetExpansionContains,\n} from '@medplum/fhirtypes';\nimport React from 'react';\nimport { Autocomplete } from './Autocomplete';\nimport { useMedplum } from './MedplumProvider';\n\nexport interface CodeableConceptInputProps {\n property: ElementDefinition;\n name: string;\n defaultValue?: CodeableConcept;\n onChange?: (value: CodeableConcept) => void;\n}\n\nexport function CodeableConceptInput(props: CodeableConceptInputProps): JSX.Element {\n const medplum = useMedplum();\n\n let defaultValue = undefined;\n if (props.defaultValue) {\n defaultValue = [props.defaultValue];\n }\n\n return (\n <Autocomplete\n loadOptions={(input: string): Promise<CodeableConcept[]> => {\n const system = props.property.binding?.valueSet as string;\n return medplum.searchValueSet(system, input).then((valueSet: ValueSet) => {\n return ((valueSet.expansion as ValueSetExpansion).contains as ValueSetExpansionContains[]).map(\n valueSetElementToCodeableConcept\n );\n });\n }}\n buildUnstructured={buildUnstructured}\n getId={getId}\n getDisplay={getDisplay}\n name={props.name}\n defaultValue={defaultValue}\n onChange={(values: CodeableConcept[]) => {\n if (props.onChange) {\n props.onChange(values[0]);\n }\n }}\n />\n );\n}\n\nfunction valueSetElementToCodeableConcept(element: ValueSetExpansionContains): CodeableConcept {\n return {\n text: element.display,\n coding: [\n {\n system: element.system,\n code: element.code,\n display: element.display,\n },\n ],\n };\n}\n\nfunction buildUnstructured(str: string): CodeableConcept {\n return { text: str };\n}\n\nfunction getId(concept: CodeableConcept): string {\n if (concept.coding && concept.coding.length > 0) {\n return concept.coding[0].code as string;\n }\n return stringify(concept);\n}\n\nfunction getDisplay(concept: CodeableConcept): JSX.Element {\n const text = concept.coding?.[0]?.display ?? concept.coding?.[0]?.code ?? concept.text;\n return <>{text}</>;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CodeableConceptInput.js","sources":["../../src/CodeableConceptInput.tsx"],"sourcesContent":["import { stringify } from '@medplum/core';\nimport {\n CodeableConcept,\n ElementDefinition,\n ValueSet,\n ValueSetExpansion,\n ValueSetExpansionContains,\n} from '@medplum/fhirtypes';\nimport React from 'react';\nimport { Autocomplete } from './Autocomplete';\nimport { useMedplum } from './MedplumProvider';\n\nexport interface CodeableConceptInputProps {\n property: ElementDefinition;\n name: string;\n defaultValue?: CodeableConcept;\n onChange?: (value: CodeableConcept) => void;\n}\n\nexport function CodeableConceptInput(props: CodeableConceptInputProps): JSX.Element {\n const medplum = useMedplum();\n\n let defaultValue = undefined;\n if (props.defaultValue) {\n defaultValue = [props.defaultValue];\n }\n\n return (\n <Autocomplete\n loadOptions={(input: string): Promise<CodeableConcept[]> => {\n const system = props.property.binding?.valueSet as string;\n return medplum.searchValueSet(system, input).then((valueSet: ValueSet) => {\n return ((valueSet.expansion as ValueSetExpansion).contains as ValueSetExpansionContains[]).map(\n valueSetElementToCodeableConcept\n );\n });\n }}\n buildUnstructured={buildUnstructured}\n getId={getId}\n getDisplay={getDisplay}\n name={props.name}\n defaultValue={defaultValue}\n loadOnFocus={true}\n onChange={(values: CodeableConcept[]) => {\n if (props.onChange) {\n props.onChange(values[0]);\n }\n }}\n />\n );\n}\n\nfunction valueSetElementToCodeableConcept(element: ValueSetExpansionContains): CodeableConcept {\n return {\n text: element.display,\n coding: [\n {\n system: element.system,\n code: element.code,\n display: element.display,\n },\n ],\n };\n}\n\nfunction buildUnstructured(str: string): CodeableConcept {\n return { text: str };\n}\n\nfunction getId(concept: CodeableConcept): string {\n if (concept.coding && concept.coding.length > 0) {\n return concept.coding[0].code as string;\n }\n return stringify(concept);\n}\n\nfunction getDisplay(concept: CodeableConcept): JSX.Element {\n const text = concept.coding?.[0]?.display ?? concept.coding?.[0]?.code ?? concept.text;\n return <>{text}</>;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/CodingInput.js
CHANGED
|
@@ -19,7 +19,7 @@ function CodingInput(props) {
|
|
|
19
19
|
display: e.display,
|
|
20
20
|
}));
|
|
21
21
|
});
|
|
22
|
-
}, buildUnstructured: (str) => ({ code: str }), getId: (item) => item.code, getDisplay: (item) => React.createElement(CodingDisplay, { value: item }), name: props.name, defaultValue: defaultValue, onChange: (values) => {
|
|
22
|
+
}, buildUnstructured: (str) => ({ code: str }), getId: (item) => item.code, getDisplay: (item) => React.createElement(CodingDisplay, { value: item }), name: props.name, defaultValue: defaultValue, loadOnFocus: true, onChange: (values) => {
|
|
23
23
|
if (props.onChange) {
|
|
24
24
|
props.onChange(values[0]);
|
|
25
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodingInput.js","sources":["../../src/CodingInput.tsx"],"sourcesContent":["import { Coding, ElementDefinition, ValueSet, ValueSetExpansion, ValueSetExpansionContains } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { Autocomplete } from './Autocomplete';\nimport { CodingDisplay } from './CodingDisplay';\nimport { useMedplum } from './MedplumProvider';\n\nexport interface CodingInputProps {\n property: ElementDefinition;\n name: string;\n defaultValue?: Coding;\n onChange?: (value: Coding) => void;\n}\n\nexport function CodingInput(props: CodingInputProps): JSX.Element {\n const medplum = useMedplum();\n\n let defaultValue = undefined;\n if (props.defaultValue) {\n defaultValue = [props.defaultValue];\n }\n\n return (\n <Autocomplete\n loadOptions={(input: string): Promise<Coding[]> => {\n const system = props.property.binding?.valueSet as string;\n return medplum.searchValueSet(system, input).then((valueSet: ValueSet) => {\n return ((valueSet.expansion as ValueSetExpansion).contains as ValueSetExpansionContains[]).map(\n (e) =>\n ({\n system: e.system,\n code: e.code,\n display: e.display,\n } as Coding)\n );\n });\n }}\n buildUnstructured={(str: string) => ({ code: str })}\n getId={(item: Coding) => item.code as string}\n getDisplay={(item: Coding) => <CodingDisplay value={item} />}\n name={props.name}\n defaultValue={defaultValue}\n onChange={(values: Coding[]) => {\n if (props.onChange) {\n props.onChange(values[0]);\n }\n }}\n />\n );\n}\n"],"names":[],"mappings":";;;;;AAaM,SAAU,WAAW,CAAC,KAAuB,EAAA;AACjD,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,YAAY,GAAG,SAAS,CAAC;IAC7B,IAAI,KAAK,CAAC,YAAY,EAAE;AACtB,QAAA,YAAY,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AACrC,KAAA;IAED,QACE,oBAAC,YAAY,EAAA,EACX,WAAW,EAAE,CAAC,KAAa,KAAuB;;YAChD,MAAM,MAAM,GAAG,CAAA,EAAA,GAAA,KAAK,CAAC,QAAQ,CAAC,OAAO,MAAE,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,QAAkB,CAAC;AAC1D,YAAA,OAAO,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,QAAkB,KAAI;AACvE,gBAAA,OAAS,QAAQ,CAAC,SAA+B,CAAC,QAAwC,CAAC,GAAG,CAC5F,CAAC,CAAC,MACC;oBACC,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,OAAO,EAAE,CAAC,CAAC,OAAO;AACR,iBAAA,CAAA,CACf,CAAC;AACJ,aAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"CodingInput.js","sources":["../../src/CodingInput.tsx"],"sourcesContent":["import { Coding, ElementDefinition, ValueSet, ValueSetExpansion, ValueSetExpansionContains } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { Autocomplete } from './Autocomplete';\nimport { CodingDisplay } from './CodingDisplay';\nimport { useMedplum } from './MedplumProvider';\n\nexport interface CodingInputProps {\n property: ElementDefinition;\n name: string;\n defaultValue?: Coding;\n onChange?: (value: Coding) => void;\n}\n\nexport function CodingInput(props: CodingInputProps): JSX.Element {\n const medplum = useMedplum();\n\n let defaultValue = undefined;\n if (props.defaultValue) {\n defaultValue = [props.defaultValue];\n }\n\n return (\n <Autocomplete\n loadOptions={(input: string): Promise<Coding[]> => {\n const system = props.property.binding?.valueSet as string;\n return medplum.searchValueSet(system, input).then((valueSet: ValueSet) => {\n return ((valueSet.expansion as ValueSetExpansion).contains as ValueSetExpansionContains[]).map(\n (e) =>\n ({\n system: e.system,\n code: e.code,\n display: e.display,\n } as Coding)\n );\n });\n }}\n buildUnstructured={(str: string) => ({ code: str })}\n getId={(item: Coding) => item.code as string}\n getDisplay={(item: Coding) => <CodingDisplay value={item} />}\n name={props.name}\n defaultValue={defaultValue}\n loadOnFocus={true}\n onChange={(values: Coding[]) => {\n if (props.onChange) {\n props.onChange(values[0]);\n }\n }}\n />\n );\n}\n"],"names":[],"mappings":";;;;;AAaM,SAAU,WAAW,CAAC,KAAuB,EAAA;AACjD,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,YAAY,GAAG,SAAS,CAAC;IAC7B,IAAI,KAAK,CAAC,YAAY,EAAE;AACtB,QAAA,YAAY,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AACrC,KAAA;IAED,QACE,oBAAC,YAAY,EAAA,EACX,WAAW,EAAE,CAAC,KAAa,KAAuB;;YAChD,MAAM,MAAM,GAAG,CAAA,EAAA,GAAA,KAAK,CAAC,QAAQ,CAAC,OAAO,MAAE,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,QAAkB,CAAC;AAC1D,YAAA,OAAO,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,QAAkB,KAAI;AACvE,gBAAA,OAAS,QAAQ,CAAC,SAA+B,CAAC,QAAwC,CAAC,GAAG,CAC5F,CAAC,CAAC,MACC;oBACC,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,OAAO,EAAE,CAAC,CAAC,OAAO;AACR,iBAAA,CAAA,CACf,CAAC;AACJ,aAAC,CAAC,CAAC;AACL,SAAC,EACD,iBAAiB,EAAE,CAAC,GAAW,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EACnD,KAAK,EAAE,CAAC,IAAY,KAAK,IAAI,CAAC,IAAc,EAC5C,UAAU,EAAE,CAAC,IAAY,KAAK,KAAC,CAAA,aAAA,CAAA,aAAa,EAAC,EAAA,KAAK,EAAE,IAAI,EAAI,CAAA,EAC5D,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,IAAI,EACjB,QAAQ,EAAE,CAAC,MAAgB,KAAI;YAC7B,IAAI,KAAK,CAAC,QAAQ,EAAE;gBAClB,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3B,aAAA;SACF,EAAA,CACD,EACF;AACJ;;;;"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isValidDate } from '@medplum/core';
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import { Input } from './Input.js';
|
|
3
4
|
|
|
@@ -54,9 +55,6 @@ function convertLocalToIso(localString) {
|
|
|
54
55
|
}
|
|
55
56
|
return date.toISOString();
|
|
56
57
|
}
|
|
57
|
-
function isValidDate(date) {
|
|
58
|
-
return date instanceof Date && !isNaN(date.getTime());
|
|
59
|
-
}
|
|
60
58
|
|
|
61
59
|
export { DateTimeInput, convertIsoToLocal, convertLocalToIso };
|
|
62
60
|
//# sourceMappingURL=DateTimeInput.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateTimeInput.js","sources":["../../src/DateTimeInput.tsx"],"sourcesContent":["import React from 'react';\nimport { Input, InputProps } from './Input';\n\n/**\n * The DateTimeInput component is a wrapper around the HTML5 input type=\"datetime-local\".\n * The main purpose is to reconcile time zones.\n * Most of our date/time values are in ISO-8601, which includes a time zone offset.\n * The datetime-local input does not support the time zone offset.\n * @param props The Input props.\n * @returns The JSX element to render.\n */\nexport function DateTimeInput(props: InputProps): JSX.Element {\n return (\n <Input\n {...props}\n type=\"datetime-local\"\n defaultValue={convertIsoToLocal(props.defaultValue as string | undefined)}\n onChange={(newValue: string) => {\n if (props.onChange) {\n props.onChange(convertLocalToIso(newValue));\n }\n }}\n />\n );\n}\n\n/**\n * Converts an ISO-8601 date/time string to a local date/time string.\n * @param isoString The ISO-8601 date/time string to convert.\n * @returns The local date/time string.\n */\nexport function convertIsoToLocal(isoString: string | undefined): string {\n if (!isoString) {\n return '';\n }\n\n // Convert the ISO-8601 date to a local datetime-local value.\n // See: https://developer.mozilla.org/en-US/docs/Web/HTML/Date_and_time_formats#local_date_and_time_strings\n // See: https://stackoverflow.com/a/60368477\n const date = new Date(isoString);\n if (!isValidDate(date)) {\n // If the input string was malformed, return an empty string.\n return '';\n }\n\n return date.toLocaleDateString('sv') + 'T' + date.toLocaleTimeString('sv');\n}\n\n/**\n * Converts a local date/time string to an ISO-8601 date/time string.\n * @param localString The local date/time string to convert.\n * @returns The ISO-8601 date/time string.\n */\nexport function convertLocalToIso(localString: string | undefined): string {\n if (!localString) {\n return '';\n }\n\n // Try to parse the local string as a Date\n // JavaScript's Date() constructor defaults to the local time zone.\n // The Date() constructor will throw if the value is malformed.\n const date = new Date(localString);\n if (!isValidDate(date)) {\n // If the input string was malformed, return an empty string.\n return '';\n }\n\n return date.toISOString();\n}\n
|
|
1
|
+
{"version":3,"file":"DateTimeInput.js","sources":["../../src/DateTimeInput.tsx"],"sourcesContent":["import { isValidDate } from '@medplum/core';\nimport React from 'react';\nimport { Input, InputProps } from './Input';\n\n/**\n * The DateTimeInput component is a wrapper around the HTML5 input type=\"datetime-local\".\n * The main purpose is to reconcile time zones.\n * Most of our date/time values are in ISO-8601, which includes a time zone offset.\n * The datetime-local input does not support the time zone offset.\n * @param props The Input props.\n * @returns The JSX element to render.\n */\nexport function DateTimeInput(props: InputProps): JSX.Element {\n return (\n <Input\n {...props}\n type=\"datetime-local\"\n defaultValue={convertIsoToLocal(props.defaultValue as string | undefined)}\n onChange={(newValue: string) => {\n if (props.onChange) {\n props.onChange(convertLocalToIso(newValue));\n }\n }}\n />\n );\n}\n\n/**\n * Converts an ISO-8601 date/time string to a local date/time string.\n * @param isoString The ISO-8601 date/time string to convert.\n * @returns The local date/time string.\n */\nexport function convertIsoToLocal(isoString: string | undefined): string {\n if (!isoString) {\n return '';\n }\n\n // Convert the ISO-8601 date to a local datetime-local value.\n // See: https://developer.mozilla.org/en-US/docs/Web/HTML/Date_and_time_formats#local_date_and_time_strings\n // See: https://stackoverflow.com/a/60368477\n const date = new Date(isoString);\n if (!isValidDate(date)) {\n // If the input string was malformed, return an empty string.\n return '';\n }\n\n return date.toLocaleDateString('sv') + 'T' + date.toLocaleTimeString('sv');\n}\n\n/**\n * Converts a local date/time string to an ISO-8601 date/time string.\n * @param localString The local date/time string to convert.\n * @returns The ISO-8601 date/time string.\n */\nexport function convertLocalToIso(localString: string | undefined): string {\n if (!localString) {\n return '';\n }\n\n // Try to parse the local string as a Date\n // JavaScript's Date() constructor defaults to the local time zone.\n // The Date() constructor will throw if the value is malformed.\n const date = new Date(localString);\n if (!isValidDate(date)) {\n // If the input string was malformed, return an empty string.\n return '';\n }\n\n return date.toISOString();\n}\n"],"names":[],"mappings":";;;;AAIA;;;;;;;AAOG;AACG,SAAU,aAAa,CAAC,KAAiB,EAAA;IAC7C,QACE,KAAC,CAAA,aAAA,CAAA,KAAK,EACA,MAAA,CAAA,MAAA,CAAA,EAAA,EAAA,KAAK,IACT,IAAI,EAAC,gBAAgB,EACrB,YAAY,EAAE,iBAAiB,CAAC,KAAK,CAAC,YAAkC,CAAC,EACzE,QAAQ,EAAE,CAAC,QAAgB,KAAI;YAC7B,IAAI,KAAK,CAAC,QAAQ,EAAE;gBAClB,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC7C,aAAA;SACF,EAAA,CAAA,CACD,EACF;AACJ,CAAC;AAED;;;;AAIG;AACG,SAAU,iBAAiB,CAAC,SAA6B,EAAA;IAC7D,IAAI,CAAC,SAAS,EAAE;AACd,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;;;;AAKD,IAAA,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;AACjC,IAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;;AAEtB,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;AAED,IAAA,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;AAC7E,CAAC;AAED;;;;AAIG;AACG,SAAU,iBAAiB,CAAC,WAA+B,EAAA;IAC/D,IAAI,CAAC,WAAW,EAAE;AAChB,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;;;;AAKD,IAAA,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC;AACnC,IAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;;AAEtB,QAAA,OAAO,EAAE,CAAC;AACX,KAAA;AAED,IAAA,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;AAC5B;;;;"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { capitalize } from '@medplum/core';
|
|
1
|
+
import { formatDateTime, capitalize } from '@medplum/core';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { CodeableConceptDisplay } from './CodeableConceptDisplay.js';
|
|
4
|
-
import { DateTimeDisplay } from './DateTimeDisplay.js';
|
|
5
4
|
import { MedplumLink } from './MedplumLink.js';
|
|
6
5
|
import { QuantityDisplay } from './QuantityDisplay.js';
|
|
7
6
|
import { RangeDisplay } from './RangeDisplay.js';
|
|
@@ -41,8 +40,7 @@ function DiagnosticReportDisplay(props) {
|
|
|
41
40
|
React.createElement(ResourceBadge, { value: interpreter, link: true }))))),
|
|
42
41
|
diagnosticReport.issued && (React.createElement("dl", null,
|
|
43
42
|
React.createElement("dt", null, "Issued"),
|
|
44
|
-
React.createElement("dd", null,
|
|
45
|
-
React.createElement(DateTimeDisplay, { value: diagnosticReport.issued })))),
|
|
43
|
+
React.createElement("dd", null, formatDateTime(diagnosticReport.issued)))),
|
|
46
44
|
diagnosticReport.status && (React.createElement("dl", null,
|
|
47
45
|
React.createElement("dt", null, "Status"),
|
|
48
46
|
React.createElement("dd", null, capitalize(diagnosticReport.status))))),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiagnosticReportDisplay.js","sources":["../../src/DiagnosticReportDisplay.tsx"],"sourcesContent":["import { capitalize } 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';\nimport { DateTimeDisplay } from './DateTimeDisplay';\nimport { MedplumLink } from './MedplumLink';\nimport { QuantityDisplay } from './QuantityDisplay';\nimport { RangeDisplay } from './RangeDisplay';\nimport { ResourceBadge } from './ResourceBadge';\nimport { useResource } from './useResource';\nimport './DiagnosticReportDisplay.css';\nimport './Table.css';\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 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 <div className=\"medplum-diagnostic-report\">\n <h1>Diagnostic Report</h1>\n <div className=\"medplum-diagnostic-report-header\">\n {diagnosticReport.subject && (\n <dl>\n <dt>Subject</dt>\n <dd>\n <ResourceBadge value={diagnosticReport.subject} link={true} />\n </dd>\n </dl>\n )}\n {diagnosticReport.resultsInterpreter &&\n diagnosticReport.resultsInterpreter.map((interpreter) => (\n <dl key={interpreter.reference}>\n <dt>Interpreter</dt>\n <dd>\n <ResourceBadge value={interpreter} link={true} />\n </dd>\n </dl>\n ))}\n {diagnosticReport.issued && (\n <dl>\n <dt>Issued</dt>\n <dd>\n <DateTimeDisplay value={diagnosticReport.issued} />\n </dd>\n </dl>\n )}\n {diagnosticReport.status && (\n <dl>\n <dt>Status</dt>\n <dd>{capitalize(diagnosticReport.status)}</dd>\n </dl>\n )}\n </div>\n {diagnosticReport.result && <ObservationTable value={diagnosticReport.result} />}\n {textContent && <pre>{textContent.trim()}</pre>}\n </div>\n );\n}\n\nexport interface ObservationTableProps {\n value?: Observation[] | Reference<Observation>[];\n}\n\nexport function ObservationTable(props: ObservationTableProps): JSX.Element {\n return (\n <table className=\"medplum-table\">\n <thead>\n <tr>\n <th>Test</th>\n <th>Value</th>\n <th>Reference Range</th>\n <th>Interpretation</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 observation = useResource(props.value);\n if (!observation) {\n return null;\n }\n\n return (\n <tr>\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 </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\n if (obs?.valueQuantity) {\n return <QuantityDisplay value={props.value?.valueQuantity} />;\n }\n\n if (obs?.valueString) {\n return <>{obs.valueString}</>;\n }\n\n if (obs && 'component' in obs && obs?.component) {\n return (\n <>\n {obs.component\n .map<React.ReactNode>((component: ObservationComponent, index: number) => (\n <ObservationValueDisplay key={`obs-${index}`} value={component} />\n ))\n .reduce((prev, curr) => [prev, ' / ', curr])}\n </>\n );\n }\n\n return null;\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 return <RangeDisplay value={range} />;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DiagnosticReportDisplay.js","sources":["../../src/DiagnosticReportDisplay.tsx"],"sourcesContent":["import { capitalize, formatDateTime } 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';\nimport './DiagnosticReportDisplay.css';\nimport { MedplumLink } from './MedplumLink';\nimport { QuantityDisplay } from './QuantityDisplay';\nimport { RangeDisplay } from './RangeDisplay';\nimport { ResourceBadge } from './ResourceBadge';\nimport './Table.css';\nimport { useResource } from './useResource';\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 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 <div className=\"medplum-diagnostic-report\">\n <h1>Diagnostic Report</h1>\n <div className=\"medplum-diagnostic-report-header\">\n {diagnosticReport.subject && (\n <dl>\n <dt>Subject</dt>\n <dd>\n <ResourceBadge value={diagnosticReport.subject} link={true} />\n </dd>\n </dl>\n )}\n {diagnosticReport.resultsInterpreter &&\n diagnosticReport.resultsInterpreter.map((interpreter) => (\n <dl key={interpreter.reference}>\n <dt>Interpreter</dt>\n <dd>\n <ResourceBadge value={interpreter} link={true} />\n </dd>\n </dl>\n ))}\n {diagnosticReport.issued && (\n <dl>\n <dt>Issued</dt>\n <dd>{formatDateTime(diagnosticReport.issued)}</dd>\n </dl>\n )}\n {diagnosticReport.status && (\n <dl>\n <dt>Status</dt>\n <dd>{capitalize(diagnosticReport.status)}</dd>\n </dl>\n )}\n </div>\n {diagnosticReport.result && <ObservationTable value={diagnosticReport.result} />}\n {textContent && <pre>{textContent.trim()}</pre>}\n </div>\n );\n}\n\nexport interface ObservationTableProps {\n value?: Observation[] | Reference<Observation>[];\n}\n\nexport function ObservationTable(props: ObservationTableProps): JSX.Element {\n return (\n <table className=\"medplum-table\">\n <thead>\n <tr>\n <th>Test</th>\n <th>Value</th>\n <th>Reference Range</th>\n <th>Interpretation</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 observation = useResource(props.value);\n if (!observation) {\n return null;\n }\n\n return (\n <tr>\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 </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\n if (obs?.valueQuantity) {\n return <QuantityDisplay value={props.value?.valueQuantity} />;\n }\n\n if (obs?.valueString) {\n return <>{obs.valueString}</>;\n }\n\n if (obs && 'component' in obs && obs?.component) {\n return (\n <>\n {obs.component\n .map<React.ReactNode>((component: ObservationComponent, index: number) => (\n <ObservationValueDisplay key={`obs-${index}`} value={component} />\n ))\n .reduce((prev, curr) => [prev, ' / ', curr])}\n </>\n );\n }\n\n return null;\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 return <RangeDisplay value={range} />;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -81,11 +81,14 @@ function FhirPathTable(props) {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
useEffect(() => {
|
|
84
|
-
medplum
|
|
84
|
+
medplum
|
|
85
|
+
.requestSchema(props.resourceType)
|
|
86
|
+
.then((newSchema) => {
|
|
85
87
|
// The schema could have the same object identity,
|
|
86
88
|
// so need to use the spread operator to kick React re-render.
|
|
87
89
|
setSchema(Object.assign({}, newSchema));
|
|
88
|
-
})
|
|
90
|
+
})
|
|
91
|
+
.catch(console.log);
|
|
89
92
|
}, [medplum, props.resourceType]);
|
|
90
93
|
const typeSchema = (_a = schema === null || schema === void 0 ? void 0 : schema.types) === null || _a === void 0 ? void 0 : _a[props.resourceType];
|
|
91
94
|
if (!typeSchema) {
|