@medplum/react 0.9.25 → 0.9.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +282 -152
- 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/styles.css +83 -79
- package/dist/{types → esm}/AddressDisplay.d.ts +0 -0
- package/dist/esm/AddressDisplay.js +13 -0
- package/dist/esm/AddressDisplay.js.map +1 -0
- package/dist/{types → esm}/AddressInput.d.ts +0 -0
- package/dist/esm/AddressInput.js +69 -0
- package/dist/esm/AddressInput.js.map +1 -0
- package/dist/{types → esm}/AnnotationInput.d.ts +0 -0
- package/dist/esm/AnnotationInput.js +28 -0
- package/dist/esm/AnnotationInput.js.map +1 -0
- package/dist/{types → esm}/AttachmentArrayDisplay.d.ts +0 -0
- package/dist/esm/AttachmentArrayDisplay.js +11 -0
- package/dist/esm/AttachmentArrayDisplay.js.map +1 -0
- package/dist/{types → esm}/AttachmentArrayInput.d.ts +0 -0
- package/dist/esm/AttachmentArrayInput.js +42 -0
- package/dist/esm/AttachmentArrayInput.js.map +1 -0
- package/dist/{types → esm}/AttachmentDisplay.d.ts +0 -0
- package/dist/esm/AttachmentDisplay.js +20 -0
- package/dist/esm/AttachmentDisplay.js.map +1 -0
- package/dist/{types → esm}/AttachmentInput.d.ts +0 -0
- package/dist/esm/AttachmentInput.js +27 -0
- package/dist/esm/AttachmentInput.js.map +1 -0
- package/dist/{types → esm}/Autocomplete.d.ts +1 -0
- package/dist/esm/Autocomplete.js +280 -0
- package/dist/esm/Autocomplete.js.map +1 -0
- package/dist/{types → esm}/Avatar.d.ts +0 -0
- package/dist/esm/Avatar.js +24 -0
- package/dist/esm/Avatar.js.map +1 -0
- package/dist/{types → esm}/BackboneElementDisplay.d.ts +0 -0
- package/dist/esm/BackboneElementDisplay.js +43 -0
- package/dist/esm/BackboneElementDisplay.js.map +1 -0
- package/dist/{types → esm}/BackboneElementInput.d.ts +0 -0
- package/dist/esm/BackboneElementInput.js +51 -0
- package/dist/esm/BackboneElementInput.js.map +1 -0
- package/dist/{types → esm}/Button.d.ts +0 -0
- package/dist/esm/Button.js +13 -0
- package/dist/esm/Button.js.map +1 -0
- package/dist/{types → esm}/CalendarInput.d.ts +0 -0
- package/dist/esm/CalendarInput.js +96 -0
- package/dist/esm/CalendarInput.js.map +1 -0
- package/dist/{types → esm}/Checkbox.d.ts +0 -0
- package/dist/esm/Checkbox.js +13 -0
- package/dist/esm/Checkbox.js.map +1 -0
- package/dist/{types → esm}/CheckboxFormSection.d.ts +0 -0
- package/dist/esm/CheckboxFormSection.js +12 -0
- package/dist/esm/CheckboxFormSection.js.map +1 -0
- package/dist/{types → esm}/CodeInput.d.ts +0 -0
- package/dist/esm/CodeInput.js +28 -0
- package/dist/esm/CodeInput.js.map +1 -0
- package/dist/{types → esm}/CodeableConceptDisplay.d.ts +0 -0
- package/dist/esm/CodeableConceptDisplay.js +21 -0
- package/dist/esm/CodeableConceptDisplay.js.map +1 -0
- package/dist/{types → esm}/CodeableConceptInput.d.ts +0 -0
- package/dist/esm/CodeableConceptInput.js +52 -0
- package/dist/esm/CodeableConceptInput.js.map +1 -0
- package/dist/{types → esm}/CodingDisplay.d.ts +0 -0
- package/dist/esm/CodingDisplay.js +9 -0
- package/dist/esm/CodingDisplay.js.map +1 -0
- package/dist/{types → esm}/CodingInput.d.ts +0 -0
- package/dist/esm/CodingInput.js +30 -0
- package/dist/esm/CodingInput.js.map +1 -0
- package/dist/{types → esm}/ContactDetailDisplay.d.ts +0 -0
- package/dist/esm/ContactDetailDisplay.js +17 -0
- package/dist/esm/ContactDetailDisplay.js.map +1 -0
- package/dist/{types → esm}/ContactDetailInput.d.ts +0 -0
- package/dist/esm/ContactDetailInput.js +37 -0
- package/dist/esm/ContactDetailInput.js.map +1 -0
- package/dist/{types → esm}/ContactPointDisplay.d.ts +0 -0
- package/dist/esm/ContactPointDisplay.js +29 -0
- package/dist/esm/ContactPointDisplay.js.map +1 -0
- package/dist/{types → esm}/ContactPointInput.d.ts +0 -0
- package/dist/esm/ContactPointInput.js +60 -0
- package/dist/esm/ContactPointInput.js.map +1 -0
- package/dist/{types → esm}/DateTimeInput.d.ts +0 -0
- package/dist/esm/DateTimeInput.js +60 -0
- package/dist/esm/DateTimeInput.js.map +1 -0
- package/dist/{types → esm}/DefaultResourceTimeline.d.ts +0 -0
- package/dist/esm/DefaultResourceTimeline.js +27 -0
- package/dist/esm/DefaultResourceTimeline.js.map +1 -0
- package/dist/{types → esm}/DescriptionList.d.ts +0 -0
- package/dist/esm/DescriptionList.js +13 -0
- package/dist/esm/DescriptionList.js.map +1 -0
- package/dist/{types → esm}/DiagnosticReportDisplay.d.ts +0 -0
- package/dist/esm/DiagnosticReportDisplay.js +101 -0
- package/dist/esm/DiagnosticReportDisplay.js.map +1 -0
- package/dist/{types → esm}/Dialog.d.ts +0 -0
- package/dist/esm/Dialog.js +43 -0
- package/dist/esm/Dialog.js.map +1 -0
- package/dist/{types → esm}/Document.d.ts +0 -0
- package/dist/esm/Document.js +9 -0
- package/dist/esm/Document.js.map +1 -0
- package/dist/{types → esm}/EncounterTimeline.d.ts +0 -0
- package/dist/esm/EncounterTimeline.js +47 -0
- package/dist/esm/EncounterTimeline.js.map +1 -0
- package/dist/{types → esm}/ErrorBoundary.d.ts +0 -0
- package/dist/esm/ErrorBoundary.js +27 -0
- package/dist/esm/ErrorBoundary.js.map +1 -0
- package/dist/{types → esm}/ExtensionInput.d.ts +0 -0
- package/dist/esm/ExtensionInput.js +14 -0
- package/dist/esm/ExtensionInput.js.map +1 -0
- package/dist/{types → esm}/FhirPathDisplay.d.ts +0 -0
- package/dist/esm/FhirPathDisplay.js +23 -0
- package/dist/esm/FhirPathDisplay.js.map +1 -0
- package/dist/{types → esm}/FhirPathTable.d.ts +0 -0
- package/dist/esm/FhirPathTable.js +117 -0
- package/dist/esm/FhirPathTable.js.map +1 -0
- package/dist/{types → esm}/FooterLinks.d.ts +0 -0
- package/dist/esm/FooterLinks.js +8 -0
- package/dist/esm/FooterLinks.js.map +1 -0
- package/dist/{types → esm}/Form.d.ts +0 -0
- package/dist/esm/Form.js +15 -0
- package/dist/esm/Form.js.map +1 -0
- package/dist/{types → esm}/FormSection.d.ts +0 -0
- package/dist/esm/FormSection.js +18 -0
- package/dist/esm/FormSection.js.map +1 -0
- package/dist/{types → esm}/FormUtils.d.ts +0 -0
- package/dist/esm/FormUtils.js +49 -0
- package/dist/esm/FormUtils.js.map +1 -0
- package/dist/{types → esm}/GoogleButton.d.ts +0 -0
- package/dist/esm/GoogleButton.js +48 -0
- package/dist/esm/GoogleButton.js.map +1 -0
- package/dist/{types → esm}/Header.d.ts +0 -0
- package/dist/esm/Header.js +95 -0
- package/dist/esm/Header.js.map +1 -0
- package/dist/{types → esm}/HeaderSearchInput.d.ts +0 -0
- package/dist/esm/HeaderSearchInput.js +181 -0
- package/dist/esm/HeaderSearchInput.js.map +1 -0
- package/dist/{types → esm}/HumanNameDisplay.d.ts +0 -0
- package/dist/esm/HumanNameDisplay.js +13 -0
- package/dist/esm/HumanNameDisplay.js.map +1 -0
- package/dist/{types → esm}/HumanNameInput.d.ts +0 -0
- package/dist/esm/HumanNameInput.js +49 -0
- package/dist/esm/HumanNameInput.js.map +1 -0
- package/dist/{types → esm}/IdentifierDisplay.d.ts +0 -0
- package/dist/esm/IdentifierDisplay.js +12 -0
- package/dist/esm/IdentifierDisplay.js.map +1 -0
- package/dist/{types → esm}/IdentifierInput.d.ts +0 -0
- package/dist/esm/IdentifierInput.js +19 -0
- package/dist/esm/IdentifierInput.js.map +1 -0
- package/dist/{types → esm}/Input.d.ts +0 -0
- package/dist/esm/Input.js +26 -0
- package/dist/esm/Input.js.map +1 -0
- package/dist/{types → esm}/InputRow.d.ts +0 -0
- package/dist/esm/InputRow.js +8 -0
- package/dist/esm/InputRow.js.map +1 -0
- package/dist/{types → esm}/Loading.d.ts +0 -0
- package/dist/esm/Loading.js +11 -0
- package/dist/esm/Loading.js.map +1 -0
- package/dist/{types → esm}/Logo.d.ts +0 -0
- package/dist/esm/Logo.js +14 -0
- package/dist/esm/Logo.js.map +1 -0
- package/dist/{types → esm}/MedplumLink.d.ts +0 -0
- package/dist/esm/MedplumLink.js +34 -0
- package/dist/esm/MedplumLink.js.map +1 -0
- package/dist/{types → esm}/MedplumProvider.d.ts +0 -0
- package/dist/esm/MedplumProvider.js +50 -0
- package/dist/esm/MedplumProvider.js.map +1 -0
- package/dist/{types → esm}/MenuItem.d.ts +0 -0
- package/dist/esm/MenuItem.js +8 -0
- package/dist/esm/MenuItem.js.map +1 -0
- package/dist/{types → esm}/MenuSeparator.d.ts +0 -0
- package/dist/esm/MenuSeparator.js +8 -0
- package/dist/esm/MenuSeparator.js.map +1 -0
- package/dist/{types → esm}/PatientTimeline.d.ts +0 -0
- package/dist/esm/PatientTimeline.js +40 -0
- package/dist/esm/PatientTimeline.js.map +1 -0
- package/dist/{types → esm}/PeriodInput.d.ts +0 -0
- package/dist/esm/PeriodInput.js +19 -0
- package/dist/esm/PeriodInput.js.map +1 -0
- package/dist/{types → esm}/PlanDefinitionBuilder.d.ts +0 -0
- package/dist/esm/PlanDefinitionBuilder.js +224 -0
- package/dist/esm/PlanDefinitionBuilder.js.map +1 -0
- package/dist/{types → esm}/Popup.d.ts +0 -0
- package/dist/esm/Popup.js +64 -0
- package/dist/esm/Popup.js.map +1 -0
- package/dist/{types → esm}/QuantityDisplay.d.ts +0 -0
- package/dist/esm/QuantityDisplay.js +28 -0
- package/dist/esm/QuantityDisplay.js.map +1 -0
- package/dist/{types → esm}/QuantityInput.d.ts +0 -0
- package/dist/esm/QuantityInput.js +33 -0
- package/dist/esm/QuantityInput.js.map +1 -0
- package/dist/{types → esm}/QuestionnaireBuilder.d.ts +0 -0
- package/dist/esm/QuestionnaireBuilder.js +217 -0
- package/dist/esm/QuestionnaireBuilder.js.map +1 -0
- package/dist/{types → esm}/QuestionnaireForm.d.ts +0 -0
- package/dist/esm/QuestionnaireForm.js +218 -0
- package/dist/esm/QuestionnaireForm.js.map +1 -0
- package/dist/{types → esm}/QuestionnaireUtils.d.ts +0 -0
- package/dist/esm/QuestionnaireUtils.js +103 -0
- package/dist/esm/QuestionnaireUtils.js.map +1 -0
- package/dist/{types → esm}/RangeDisplay.d.ts +0 -0
- package/dist/esm/RangeDisplay.js +21 -0
- package/dist/esm/RangeDisplay.js.map +1 -0
- package/dist/{types → esm}/RangeInput.d.ts +0 -0
- package/dist/esm/RangeInput.js +25 -0
- package/dist/esm/RangeInput.js.map +1 -0
- package/dist/{types → esm}/RatioDisplay.d.ts +0 -0
- package/dist/esm/RatioDisplay.js +16 -0
- package/dist/esm/RatioDisplay.js.map +1 -0
- package/dist/{types → esm}/RatioInput.d.ts +0 -0
- package/dist/esm/RatioInput.js +25 -0
- package/dist/esm/RatioInput.js.map +1 -0
- package/dist/{types → esm}/ReferenceDisplay.d.ts +0 -0
- package/dist/esm/ReferenceDisplay.js +21 -0
- package/dist/esm/ReferenceDisplay.js.map +1 -0
- package/dist/{types → esm}/ReferenceInput.d.ts +0 -0
- package/dist/esm/ReferenceInput.js +42 -0
- package/dist/esm/ReferenceInput.js.map +1 -0
- package/dist/{types → esm}/RegisterForm.d.ts +0 -0
- package/dist/esm/RegisterForm.js +121 -0
- package/dist/esm/RegisterForm.js.map +1 -0
- package/dist/{types → esm}/RequestGroupDisplay.d.ts +0 -0
- package/dist/esm/RequestGroupDisplay.js +72 -0
- package/dist/esm/RequestGroupDisplay.js.map +1 -0
- package/dist/{types → esm}/ResourceArrayDisplay.d.ts +0 -0
- package/dist/esm/ResourceArrayDisplay.js +14 -0
- package/dist/esm/ResourceArrayDisplay.js.map +1 -0
- package/dist/{types → esm}/ResourceArrayInput.d.ts +0 -0
- package/dist/esm/ResourceArrayInput.js +47 -0
- package/dist/esm/ResourceArrayInput.js.map +1 -0
- package/dist/{types → esm}/ResourceBadge.d.ts +0 -0
- package/dist/esm/ResourceBadge.js +13 -0
- package/dist/esm/ResourceBadge.js.map +1 -0
- package/dist/{types → esm}/ResourceBlame.d.ts +0 -0
- package/dist/esm/ResourceBlame.js +65 -0
- package/dist/esm/ResourceBlame.js.map +1 -0
- package/dist/{types → esm}/ResourceDiff.d.ts +0 -0
- package/dist/esm/ResourceDiff.js +28 -0
- package/dist/esm/ResourceDiff.js.map +1 -0
- package/dist/{types → esm}/ResourceDiffTable.d.ts +0 -0
- package/dist/esm/ResourceDiffTable.js +58 -0
- package/dist/esm/ResourceDiffTable.js.map +1 -0
- package/dist/{types → esm}/ResourceForm.d.ts +0 -0
- package/dist/esm/ResourceForm.js +55 -0
- package/dist/esm/ResourceForm.js.map +1 -0
- package/dist/{types → esm}/ResourceHistoryTable.d.ts +0 -0
- package/dist/esm/ResourceHistoryTable.js +45 -0
- package/dist/esm/ResourceHistoryTable.js.map +1 -0
- package/dist/{types → esm}/ResourceInput.d.ts +1 -0
- package/dist/esm/ResourceInput.js +41 -0
- package/dist/esm/ResourceInput.js.map +1 -0
- package/dist/{types → esm}/ResourceName.d.ts +0 -0
- package/dist/esm/ResourceName.js +16 -0
- package/dist/esm/ResourceName.js.map +1 -0
- package/dist/{types → esm}/ResourcePropertyDisplay.d.ts +0 -0
- package/dist/esm/ResourcePropertyDisplay.js +107 -0
- package/dist/esm/ResourcePropertyDisplay.js.map +1 -0
- package/dist/{types → esm}/ResourcePropertyInput.d.ts +0 -0
- package/dist/esm/ResourcePropertyInput.js +154 -0
- package/dist/esm/ResourcePropertyInput.js.map +1 -0
- package/dist/{types → esm}/ResourceTable.d.ts +0 -0
- package/dist/esm/ResourceTable.js +22 -0
- package/dist/esm/ResourceTable.js.map +1 -0
- package/dist/{types → esm}/ResourceTimeline.d.ts +0 -0
- package/dist/esm/ResourceTimeline.js +221 -0
- package/dist/esm/ResourceTimeline.js.map +1 -0
- package/dist/{types → esm}/Scheduler.d.ts +0 -0
- package/dist/esm/Scheduler.js +82 -0
- package/dist/esm/Scheduler.js.map +1 -0
- package/dist/{types → esm}/Scrollable.d.ts +0 -0
- package/dist/esm/Scrollable.js +12 -0
- package/dist/esm/Scrollable.js.map +1 -0
- package/dist/{types → esm}/SearchControl.d.ts +0 -0
- package/dist/esm/SearchControl.js +268 -0
- package/dist/esm/SearchControl.js.map +1 -0
- package/dist/{types → esm}/SearchControlField.d.ts +0 -0
- package/dist/esm/SearchControlField.js +98 -0
- package/dist/esm/SearchControlField.js.map +1 -0
- package/dist/{types → esm}/SearchFieldEditor.d.ts +0 -0
- package/dist/esm/SearchFieldEditor.js +192 -0
- package/dist/esm/SearchFieldEditor.js.map +1 -0
- package/dist/{types → esm}/SearchFilterEditor.d.ts +0 -0
- package/dist/esm/SearchFilterEditor.js +103 -0
- package/dist/esm/SearchFilterEditor.js.map +1 -0
- package/dist/{types → esm}/SearchFilterValueDialog.d.ts +0 -0
- package/dist/esm/SearchFilterValueDialog.js +22 -0
- package/dist/esm/SearchFilterValueDialog.js.map +1 -0
- package/dist/{types → esm}/SearchFilterValueDisplay.d.ts +0 -0
- package/dist/esm/SearchFilterValueDisplay.js +22 -0
- package/dist/esm/SearchFilterValueDisplay.js.map +1 -0
- package/dist/{types → esm}/SearchFilterValueInput.d.ts +0 -0
- package/dist/esm/SearchFilterValueInput.js +59 -0
- package/dist/esm/SearchFilterValueInput.js.map +1 -0
- package/dist/{types → esm}/SearchPopupMenu.d.ts +0 -0
- package/dist/esm/SearchPopupMenu.js +135 -0
- package/dist/esm/SearchPopupMenu.js.map +1 -0
- package/dist/{types → esm}/SearchUtils.d.ts +0 -0
- package/dist/esm/SearchUtils.js +487 -0
- package/dist/esm/SearchUtils.js.map +1 -0
- package/dist/{types → esm}/Select.d.ts +0 -0
- package/dist/esm/Select.js +16 -0
- package/dist/esm/Select.js.map +1 -0
- package/dist/{types → esm}/ServiceRequestTimeline.d.ts +0 -0
- package/dist/esm/ServiceRequestTimeline.js +53 -0
- package/dist/esm/ServiceRequestTimeline.js.map +1 -0
- package/dist/{types → esm}/SignInForm.d.ts +0 -0
- package/dist/esm/SignInForm.js +130 -0
- package/dist/esm/SignInForm.js.map +1 -0
- package/dist/{types → esm}/StatusBadge.d.ts +0 -0
- package/dist/esm/StatusBadge.js +8 -0
- package/dist/esm/StatusBadge.js.map +1 -0
- package/dist/{types → esm}/SubMenu.d.ts +0 -0
- package/dist/esm/SubMenu.js +38 -0
- package/dist/esm/SubMenu.js.map +1 -0
- package/dist/{types → esm}/Tab.d.ts +0 -0
- package/dist/esm/Tab.js +19 -0
- package/dist/esm/Tab.js.map +1 -0
- package/dist/{types → esm}/TabList.d.ts +0 -0
- package/dist/esm/TabList.js +23 -0
- package/dist/esm/TabList.js.map +1 -0
- package/dist/{types → esm}/TabPanel.d.ts +0 -0
- package/dist/esm/TabPanel.js +8 -0
- package/dist/esm/TabPanel.js.map +1 -0
- package/dist/{types → esm}/TabSwitch.d.ts +0 -0
- package/dist/esm/TabSwitch.js +16 -0
- package/dist/esm/TabSwitch.js.map +1 -0
- package/dist/{types → esm}/TextArea.d.ts +0 -0
- package/dist/esm/TextArea.js +16 -0
- package/dist/esm/TextArea.js.map +1 -0
- package/dist/{types → esm}/Timeline.d.ts +0 -0
- package/dist/esm/Timeline.js +48 -0
- package/dist/esm/Timeline.js.map +1 -0
- 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/{types → esm}/TitleBar.d.ts +0 -0
- package/dist/esm/TitleBar.js +8 -0
- package/dist/esm/TitleBar.js.map +1 -0
- package/dist/{types → esm}/UploadButton.d.ts +0 -0
- package/dist/esm/UploadButton.js +55 -0
- package/dist/esm/UploadButton.js.map +1 -0
- package/dist/{types → esm}/constants.d.ts +0 -0
- package/dist/esm/constants.js +12 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/{types → esm}/index.d.ts +0 -1
- package/dist/esm/index.js +86 -5814
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.min.js +1 -1
- package/dist/esm/index.min.js.map +1 -1
- package/dist/esm/node_modules/tslib/tslib.es6.js +27 -0
- package/dist/esm/node_modules/tslib/tslib.es6.js.map +1 -0
- package/dist/{types → esm}/stories/AddressInput.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/AttachmentArrayInput.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/AttachmentInput.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/Autocomplete.stories.d.ts +1 -0
- package/dist/{types → esm}/stories/Avatar.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/Button.stories.d.ts +0 -0
- package/dist/esm/stories/CodeableConceptDisplay.stories.d.ts +8 -0
- package/dist/{types → esm}/stories/DiagnosticReportDisplay.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/Dialog.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/EncounterTimeline.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/FhirPathDisplay.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/FormSection.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/Header.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/Input.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/Loading.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/Logo.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/PatientTimeline.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/PlanDefinitionBuilder.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/QuestionnaireBuilder.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/QuestionnaireForm.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/ReferenceInput.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/RegisterForm.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/RequestGroupDisplay.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/ResourceBlame.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/ResourceForm.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/ResourceHistoryTable.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/ResourceTable.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/Scheduler.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/SearchControl.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/Select.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/SignInForm.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/StatusBadge.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/Tabs.stories.d.ts +0 -0
- package/dist/{types → esm}/stories/Timeline.stories.d.ts +0 -0
- package/dist/esm/stories/TimingInput.stories.d.ts +6 -0
- package/dist/{types → esm}/stories/UploadButton.stories.d.ts +0 -0
- package/dist/esm/styles.css +83 -79
- package/dist/{types → esm}/test.setup.d.ts +0 -0
- package/dist/{types → esm}/useResource.d.ts +0 -0
- package/dist/esm/useResource.js +65 -0
- package/dist/esm/useResource.js.map +1 -0
- package/dist/{types → esm}/utils/blame.d.ts +0 -0
- package/dist/esm/utils/blame.js +74 -0
- package/dist/esm/utils/blame.js.map +1 -0
- package/dist/{types → esm}/utils/date.d.ts +0 -0
- package/dist/esm/utils/date.js +48 -0
- package/dist/esm/utils/date.js.map +1 -0
- package/dist/{types → esm}/utils/diff.d.ts +0 -0
- package/dist/esm/utils/diff.js +118 -0
- package/dist/esm/utils/diff.js.map +1 -0
- package/dist/{types → esm}/utils/dom.d.ts +0 -0
- package/dist/esm/utils/dom.js +34 -0
- package/dist/esm/utils/dom.js.map +1 -0
- package/dist/{types → esm}/utils/outcomes.d.ts +0 -0
- package/dist/esm/utils/outcomes.js +7 -0
- package/dist/esm/utils/outcomes.js.map +1 -0
- package/dist/{types → esm}/utils/recaptcha.d.ts +0 -0
- package/dist/esm/utils/recaptcha.js +27 -0
- package/dist/esm/utils/recaptcha.js.map +1 -0
- package/dist/{types → esm}/utils.d.ts +0 -0
- package/dist/esm/utils.js +15 -0
- package/dist/esm/utils.js.map +1 -0
- package/package.json +7 -7
- package/stats.html +4034 -0
- package/dist/types/DateTimeDisplay.d.ts +0 -5
- package/dist/types/PeriodDisplay.d.ts +0 -6
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import React, { useRef, useState, useEffect } from 'react';
|
|
2
|
+
import { killEvent } from './utils/dom.js';
|
|
3
|
+
|
|
4
|
+
function Autocomplete(props) {
|
|
5
|
+
var _a, _b;
|
|
6
|
+
const inputRef = useRef(null);
|
|
7
|
+
const [focused, setFocused] = useState(false);
|
|
8
|
+
const [lastValue, setLastValue] = useState(undefined);
|
|
9
|
+
const [timer, setTimer] = useState();
|
|
10
|
+
const [dropDownVisible, setDropDownVisible] = useState(false);
|
|
11
|
+
const [values, setValues] = useState((_a = props.defaultValue) !== null && _a !== void 0 ? _a : []);
|
|
12
|
+
const [options, setOptions] = useState([]);
|
|
13
|
+
const [selectedIndex, setSelectedIndex] = useState(-1);
|
|
14
|
+
const [abortController, setAbortController] = useState();
|
|
15
|
+
const [autoSubmit, setAutoSubmit] = useState();
|
|
16
|
+
const lastValueRef = useRef();
|
|
17
|
+
lastValueRef.current = lastValue;
|
|
18
|
+
const timerRef = useRef();
|
|
19
|
+
timerRef.current = timer;
|
|
20
|
+
const abortControllerRef = useRef();
|
|
21
|
+
abortControllerRef.current = abortController;
|
|
22
|
+
const autoSubmitRef = useRef();
|
|
23
|
+
autoSubmitRef.current = autoSubmit;
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
return () => {
|
|
26
|
+
if (abortControllerRef.current) {
|
|
27
|
+
abortControllerRef.current.abort();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}, []);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
var _a;
|
|
33
|
+
setValues((_a = props.defaultValue) !== null && _a !== void 0 ? _a : []);
|
|
34
|
+
}, [props.defaultValue]);
|
|
35
|
+
function setValuesWrapper(newValues) {
|
|
36
|
+
setValues(newValues);
|
|
37
|
+
if (props.onChange) {
|
|
38
|
+
props.onChange(newValues);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Adds an option to the list of selected options.
|
|
43
|
+
* @param option The option.
|
|
44
|
+
*/
|
|
45
|
+
function addOption(option) {
|
|
46
|
+
const inputElement = inputRef.current;
|
|
47
|
+
inputElement.value = '';
|
|
48
|
+
const newValues = props.multiple ? [...values, option] : [option];
|
|
49
|
+
setFocused(true);
|
|
50
|
+
setDropDownVisible(false);
|
|
51
|
+
setLastValue('');
|
|
52
|
+
setOptions([]);
|
|
53
|
+
setSelectedIndex(-1);
|
|
54
|
+
setValuesWrapper(newValues);
|
|
55
|
+
}
|
|
56
|
+
function handleClick() {
|
|
57
|
+
var _a;
|
|
58
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
59
|
+
}
|
|
60
|
+
function handleFocus() {
|
|
61
|
+
setFocused(true);
|
|
62
|
+
if (props.loadOnFocus) {
|
|
63
|
+
handleInput();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function handleBlur() {
|
|
67
|
+
setFocused(false);
|
|
68
|
+
dismissOnDelay();
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Handles an input event.
|
|
72
|
+
* Clears existing timers.
|
|
73
|
+
* Schedules a timer to execute the search after a short delay.
|
|
74
|
+
*/
|
|
75
|
+
function handleInput() {
|
|
76
|
+
if (abortControllerRef.current) {
|
|
77
|
+
abortControllerRef.current.abort();
|
|
78
|
+
setAbortController(undefined);
|
|
79
|
+
}
|
|
80
|
+
if (timerRef.current !== undefined) {
|
|
81
|
+
window.clearTimeout(timerRef.current);
|
|
82
|
+
}
|
|
83
|
+
const newTimer = window.setTimeout(() => handleTimer(), 100);
|
|
84
|
+
setTimer(newTimer);
|
|
85
|
+
}
|
|
86
|
+
function handleKeyDown(e) {
|
|
87
|
+
switch (e.key) {
|
|
88
|
+
case 'Enter':
|
|
89
|
+
case 'Tab':
|
|
90
|
+
handleSelectKey(e);
|
|
91
|
+
break;
|
|
92
|
+
case 'ArrowUp':
|
|
93
|
+
moveSelection(-1);
|
|
94
|
+
killEvent(e);
|
|
95
|
+
break;
|
|
96
|
+
case 'ArrowDown':
|
|
97
|
+
moveSelection(1);
|
|
98
|
+
killEvent(e);
|
|
99
|
+
break;
|
|
100
|
+
case 'Backspace':
|
|
101
|
+
handleBackspaceKey(e);
|
|
102
|
+
break;
|
|
103
|
+
case ',':
|
|
104
|
+
case ';':
|
|
105
|
+
handleSeparatorKey(e);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Handles the "enter" or "tab" keys. The enter key logic is:
|
|
110
|
+
* Try to add an option with tryAddOption. On success, cancel event.
|
|
111
|
+
* Otherwise, let the browser handle the enter key normally.
|
|
112
|
+
*
|
|
113
|
+
* @param e The key down event.
|
|
114
|
+
*/
|
|
115
|
+
function handleSelectKey(e) {
|
|
116
|
+
var _a;
|
|
117
|
+
if (!timerRef.current && !abortControllerRef.current && tryAddOption()) {
|
|
118
|
+
killEvent(e);
|
|
119
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// The user pressed enter, but we don't have results yet.
|
|
123
|
+
// We need to wait for the results to come in.
|
|
124
|
+
setAutoSubmit(true);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Handles the "backspace" key. The backspace key logic is:
|
|
129
|
+
* If the input is empty and there is at least one item, delete the last item.
|
|
130
|
+
* Otherwise, let the browser handle the backspace key normally.
|
|
131
|
+
*
|
|
132
|
+
* @param e The key down event.
|
|
133
|
+
*/
|
|
134
|
+
function handleBackspaceKey(e) {
|
|
135
|
+
var _a;
|
|
136
|
+
if ((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value) {
|
|
137
|
+
// If there is still text in the input,
|
|
138
|
+
// then handle backspace as normal.
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (values.length > 0) {
|
|
142
|
+
// If there are selected items,
|
|
143
|
+
// then delete the last item.
|
|
144
|
+
killEvent(e);
|
|
145
|
+
setValuesWrapper(values.slice(0, values.length - 1));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Handles a "separator" key (comma, semicolon, others?).
|
|
150
|
+
*
|
|
151
|
+
* The separator key logic is:
|
|
152
|
+
* If the drop down is visible and something is selected, choose that.
|
|
153
|
+
* If the drop down is visible but nothing is selected, choose the first.
|
|
154
|
+
* If there is content in the input, use that as a "gray" option.
|
|
155
|
+
* Otherwise, ignore.
|
|
156
|
+
*
|
|
157
|
+
* @param e The key down event.
|
|
158
|
+
*/
|
|
159
|
+
function handleSeparatorKey(e) {
|
|
160
|
+
var _a;
|
|
161
|
+
tryAddOption();
|
|
162
|
+
killEvent(e);
|
|
163
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Tries to capture the existing input as an option.
|
|
167
|
+
*
|
|
168
|
+
* @return True if captured an option; false otherwise.
|
|
169
|
+
*/
|
|
170
|
+
function tryAddOption() {
|
|
171
|
+
var _a;
|
|
172
|
+
let option;
|
|
173
|
+
if (selectedIndex >= 0 && selectedIndex < options.length) {
|
|
174
|
+
// Currently highlighted row
|
|
175
|
+
option = options[selectedIndex];
|
|
176
|
+
}
|
|
177
|
+
else if (selectedIndex === -1 && options.length > 0) {
|
|
178
|
+
// Default to first row
|
|
179
|
+
option = options[0];
|
|
180
|
+
}
|
|
181
|
+
else if (props.buildUnstructured && ((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value)) {
|
|
182
|
+
// Build semi-structured item
|
|
183
|
+
option = props.buildUnstructured(inputRef.current.value);
|
|
184
|
+
}
|
|
185
|
+
if (!option) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
addOption(option);
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Handles a timer tick event.
|
|
193
|
+
* If the contents of the input have changed, sends xhr to the server
|
|
194
|
+
* for updated contents.
|
|
195
|
+
*/
|
|
196
|
+
function handleTimer() {
|
|
197
|
+
var _a, _b;
|
|
198
|
+
setTimer(undefined);
|
|
199
|
+
const value = ((_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.trim()) || '';
|
|
200
|
+
if (value === lastValueRef.current) {
|
|
201
|
+
// Nothing has changed, move on
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
setLastValue(value);
|
|
205
|
+
const newAbortController = new AbortController();
|
|
206
|
+
setAbortController(newAbortController);
|
|
207
|
+
props
|
|
208
|
+
.loadOptions(value, newAbortController.signal)
|
|
209
|
+
.then((newOptions) => {
|
|
210
|
+
if (!newAbortController.signal.aborted) {
|
|
211
|
+
setDropDownVisible(newOptions.length > 0);
|
|
212
|
+
setOptions(newOptions);
|
|
213
|
+
setAbortController(undefined);
|
|
214
|
+
if (autoSubmitRef.current) {
|
|
215
|
+
addOption(newOptions[0]);
|
|
216
|
+
setAutoSubmit(false);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
.catch(console.log);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Moves the selected row.
|
|
224
|
+
* @param delta The amount to move the selection, up is negative.
|
|
225
|
+
*/
|
|
226
|
+
function moveSelection(delta) {
|
|
227
|
+
let index = selectedIndex + delta;
|
|
228
|
+
if (index < 0) {
|
|
229
|
+
index = 0;
|
|
230
|
+
}
|
|
231
|
+
else if (index >= options.length) {
|
|
232
|
+
index = options.length - 1;
|
|
233
|
+
}
|
|
234
|
+
setSelectedIndex(index);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Handles a hover event.
|
|
238
|
+
* @param _e The mouse event.
|
|
239
|
+
* @param index The drop down option index.
|
|
240
|
+
*/
|
|
241
|
+
function handleDropDownHover(_e, index) {
|
|
242
|
+
setSelectedIndex(index);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Handles a click event.
|
|
246
|
+
* @param e The mouse event.
|
|
247
|
+
* @param option The drop down option.
|
|
248
|
+
*/
|
|
249
|
+
function handleDropDownClick(e, option) {
|
|
250
|
+
killEvent(e);
|
|
251
|
+
addOption(option);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Dismisses the drop down menu after a slight delay.
|
|
255
|
+
*/
|
|
256
|
+
function dismissOnDelay() {
|
|
257
|
+
window.setTimeout(() => {
|
|
258
|
+
setDropDownVisible(false);
|
|
259
|
+
}, 200);
|
|
260
|
+
}
|
|
261
|
+
const baseClassName = (_b = props.className) !== null && _b !== void 0 ? _b : 'medplum-autocomplete-container';
|
|
262
|
+
return (React.createElement("div", { "data-testid": "autocomplete", className: baseClassName + (focused ? ' focused' : ''), onClick: () => handleClick() },
|
|
263
|
+
React.createElement("ul", { onClick: () => handleClick() },
|
|
264
|
+
values.map((value) => (React.createElement("li", { key: props.getId(value), "data-testid": "selected", className: "medplum-autocomplete-item choice" }, props.getDisplay(value)))),
|
|
265
|
+
React.createElement("li", { className: "medplum-autocomplete-item" },
|
|
266
|
+
React.createElement("input", { type: "text", autoFocus: props.autofocus, placeholder: values.length === 0 ? props.placeholder : undefined, autoComplete: "off", autoCapitalize: "off", spellCheck: "true", onFocus: () => handleFocus(), onBlur: () => handleBlur(), onChange: () => handleInput(), onInput: () => handleInput(), onKeyDown: (e) => handleKeyDown(e), ref: inputRef, "data-testid": "input-element" }))),
|
|
267
|
+
dropDownVisible && (React.createElement("div", { className: "medplum-autocomplete", "data-testid": "dropdown" },
|
|
268
|
+
options.map((option, index) => (React.createElement("div", { key: props.getId(option), className: index === selectedIndex
|
|
269
|
+
? 'medplum-autocomplete-row medplum-autocomplete-active'
|
|
270
|
+
: 'medplum-autocomplete-row', onMouseOver: (e) => handleDropDownHover(e, index), onClick: (e) => handleDropDownClick(e, option) },
|
|
271
|
+
props.getIcon && React.createElement("div", { className: "medplum-autocomplete-icon" }, props.getIcon(option)),
|
|
272
|
+
React.createElement("div", { className: "medplum-autocomplete-label" },
|
|
273
|
+
props.getDisplay(option),
|
|
274
|
+
props.getHelpText && React.createElement("div", { className: "medplum-autocomplete-help-text" }, props.getHelpText(option)))))),
|
|
275
|
+
props.onCreateNew && (React.createElement("div", { className: "medplum-autocomplete-row", onClick: props.onCreateNew },
|
|
276
|
+
React.createElement("div", { className: "medplum-autocomplete-label" }, "Create new...")))))));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export { Autocomplete };
|
|
280
|
+
//# sourceMappingURL=Autocomplete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Autocomplete.js","sources":["../../src/Autocomplete.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport './Autocomplete.css';\nimport { killEvent } from './utils/dom';\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 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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"}
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getDisplayString, getImageSrc } from '@medplum/core';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { MedplumLink } from './MedplumLink.js';
|
|
4
|
+
import { useResource } from './useResource.js';
|
|
5
|
+
|
|
6
|
+
function Avatar(props) {
|
|
7
|
+
var _a, _b;
|
|
8
|
+
const resource = useResource(props.value);
|
|
9
|
+
const className = props.size ? 'medplum-avatar ' + props.size : 'medplum-avatar';
|
|
10
|
+
const text = resource ? getDisplayString(resource) : (_a = props.alt) !== null && _a !== void 0 ? _a : '';
|
|
11
|
+
const initials = text && getInitials(text);
|
|
12
|
+
const imageUrl = (_b = (resource && getImageSrc(resource))) !== null && _b !== void 0 ? _b : props.src;
|
|
13
|
+
const innerContent = imageUrl ? React.createElement("img", { src: imageUrl, alt: text }) : initials;
|
|
14
|
+
return (React.createElement("div", { className: className, style: { backgroundColor: props.color }, "data-testid": "avatar" }, props.link && resource ? React.createElement(MedplumLink, { to: resource }, innerContent) : innerContent));
|
|
15
|
+
}
|
|
16
|
+
function getInitials(text) {
|
|
17
|
+
return text
|
|
18
|
+
.split(' ')
|
|
19
|
+
.map((n) => n[0])
|
|
20
|
+
.join('');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { Avatar };
|
|
24
|
+
//# sourceMappingURL=Avatar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Avatar.js","sources":["../../src/Avatar.tsx"],"sourcesContent":["import { getDisplayString, getImageSrc } from '@medplum/core';\nimport { Reference, Resource } from '@medplum/fhirtypes';\nimport React from 'react';\nimport { MedplumLink } from './MedplumLink';\nimport { useResource } from './useResource';\nimport './Avatar.css';\n\nexport interface AvatarProps {\n size?: 'xsmall' | 'small' | 'medium' | 'large';\n value?: Reference | Resource;\n src?: string;\n alt?: string;\n color?: string;\n link?: boolean;\n}\n\nexport function Avatar(props: AvatarProps): JSX.Element {\n const resource = useResource(props.value);\n const className = props.size ? 'medplum-avatar ' + props.size : 'medplum-avatar';\n const text = resource ? getDisplayString(resource) : props.alt ?? '';\n const initials = text && getInitials(text);\n const imageUrl = (resource && getImageSrc(resource)) ?? props.src;\n const innerContent = imageUrl ? <img src={imageUrl} alt={text} /> : initials;\n return (\n <div className={className} style={{ backgroundColor: props.color }} data-testid=\"avatar\">\n {props.link && resource ? <MedplumLink to={resource}>{innerContent}</MedplumLink> : innerContent}\n </div>\n );\n}\n\nfunction getInitials(text: string): string {\n return text\n .split(' ')\n .map((n) => n[0])\n .join('');\n}\n"],"names":[],"mappings":";;;;;AAgBM,SAAU,MAAM,CAAC,KAAkB,EAAA;;IACvC,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC1C,IAAA,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,GAAG,iBAAiB,GAAG,KAAK,CAAC,IAAI,GAAG,gBAAgB,CAAC;AACjF,IAAA,MAAM,IAAI,GAAG,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAA,EAAA,GAAA,KAAK,CAAC,GAAG,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,EAAE,CAAC;IACrE,MAAM,QAAQ,GAAG,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC;AAC3C,IAAA,MAAM,QAAQ,GAAG,CAAA,EAAA,IAAC,QAAQ,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,KAAK,CAAC,GAAG,CAAC;AAClE,IAAA,MAAM,YAAY,GAAG,QAAQ,GAAG,6BAAK,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAA,CAAI,GAAG,QAAQ,CAAC;AAC7E,IAAA,QACE,KAAK,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,eAAe,EAAE,KAAK,CAAC,KAAK,EAAE,EAAc,aAAA,EAAA,QAAQ,IACrF,KAAK,CAAC,IAAI,IAAI,QAAQ,GAAG,KAAC,CAAA,aAAA,CAAA,WAAW,IAAC,EAAE,EAAE,QAAQ,EAAG,EAAA,YAAY,CAAe,GAAG,YAAY,CAC5F,EACN;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAA;AAC/B,IAAA,OAAO,IAAI;SACR,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;SAChB,IAAI,CAAC,EAAE,CAAC,CAAC;AACd;;;;"}
|
|
File without changes
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { globalSchema, getPropertyDisplayName } from '@medplum/core';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { DEFAULT_IGNORED_PROPERTIES } from './constants.js';
|
|
4
|
+
import { DescriptionList, DescriptionListEntry } from './DescriptionList.js';
|
|
5
|
+
import { getValueAndType, ResourcePropertyDisplay } from './ResourcePropertyDisplay.js';
|
|
6
|
+
|
|
7
|
+
function BackboneElementDisplay(props) {
|
|
8
|
+
const typedValue = props.value;
|
|
9
|
+
const value = typedValue.value;
|
|
10
|
+
if (!value) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const typeName = typedValue.type;
|
|
14
|
+
const typeSchema = globalSchema.types[typeName];
|
|
15
|
+
if (!typeSchema) {
|
|
16
|
+
return React.createElement("div", null,
|
|
17
|
+
typeName,
|
|
18
|
+
"\u00A0not implemented");
|
|
19
|
+
}
|
|
20
|
+
if (typeof value === 'object' && 'name' in value && Object.keys(value).length === 1) {
|
|
21
|
+
// Special case for common BackboneElement pattern
|
|
22
|
+
// Where there is an object with a single property 'name'
|
|
23
|
+
// Just display the name value.
|
|
24
|
+
return React.createElement("div", null, value.name);
|
|
25
|
+
}
|
|
26
|
+
return (React.createElement(DescriptionList, { compact: props.compact }, Object.entries(typeSchema.properties).map((entry) => {
|
|
27
|
+
const key = entry[0];
|
|
28
|
+
if (DEFAULT_IGNORED_PROPERTIES.indexOf(key) >= 0) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const property = entry[1];
|
|
32
|
+
const [propertyValue, propertyType] = getValueAndType(typedValue, key);
|
|
33
|
+
if (props.ignoreMissingValues &&
|
|
34
|
+
(!propertyValue || (Array.isArray(propertyValue) && propertyValue.length === 0))) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return (React.createElement(DescriptionListEntry, { key: key, term: getPropertyDisplayName(key) },
|
|
38
|
+
React.createElement(ResourcePropertyDisplay, { property: property, propertyType: propertyType, value: propertyValue, ignoreMissingValues: props.ignoreMissingValues, link: props.link })));
|
|
39
|
+
})));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { BackboneElementDisplay };
|
|
43
|
+
//# sourceMappingURL=BackboneElementDisplay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BackboneElementDisplay.js","sources":["../../src/BackboneElementDisplay.tsx"],"sourcesContent":["import { getPropertyDisplayName, globalSchema, TypedValue } from '@medplum/core';\nimport React from 'react';\nimport { DEFAULT_IGNORED_PROPERTIES } from './constants';\nimport { DescriptionList, DescriptionListEntry } from './DescriptionList';\nimport { getValueAndType, ResourcePropertyDisplay } from './ResourcePropertyDisplay';\n\nexport interface BackboneElementDisplayProps {\n value: TypedValue;\n compact?: boolean;\n ignoreMissingValues?: boolean;\n link?: boolean;\n}\n\nexport function BackboneElementDisplay(props: BackboneElementDisplayProps): JSX.Element | null {\n const typedValue = props.value;\n const value = typedValue.value;\n if (!value) {\n return null;\n }\n\n const typeName = typedValue.type;\n const typeSchema = globalSchema.types[typeName];\n if (!typeSchema) {\n return <div>{typeName} not implemented</div>;\n }\n\n if (typeof value === 'object' && 'name' in value && Object.keys(value).length === 1) {\n // Special case for common BackboneElement pattern\n // Where there is an object with a single property 'name'\n // Just display the name value.\n return <div>{value.name}</div>;\n }\n\n return (\n <DescriptionList compact={props.compact}>\n {Object.entries(typeSchema.properties).map((entry) => {\n const key = entry[0];\n if (DEFAULT_IGNORED_PROPERTIES.indexOf(key) >= 0) {\n return null;\n }\n const property = entry[1];\n const [propertyValue, propertyType] = getValueAndType(typedValue, key);\n if (\n props.ignoreMissingValues &&\n (!propertyValue || (Array.isArray(propertyValue) && propertyValue.length === 0))\n ) {\n return null;\n }\n return (\n <DescriptionListEntry key={key} term={getPropertyDisplayName(key)}>\n <ResourcePropertyDisplay\n property={property}\n propertyType={propertyType}\n value={propertyValue}\n ignoreMissingValues={props.ignoreMissingValues}\n link={props.link}\n />\n </DescriptionListEntry>\n );\n })}\n </DescriptionList>\n );\n}\n"],"names":[],"mappings":";;;;;;AAaM,SAAU,sBAAsB,CAAC,KAAkC,EAAA;AACvE,IAAA,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;AAC/B,IAAA,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE;AACV,QAAA,OAAO,IAAI,CAAC;AACb,KAAA;AAED,IAAA,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC;IACjC,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,CAAC,UAAU,EAAE;QACf,OAAO,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,IAAA;YAAM,QAAQ;oCAA4B,CAAC;AACnD,KAAA;AAED,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;;;;AAInF,QAAA,OAAO,KAAM,CAAA,aAAA,CAAA,KAAA,EAAA,IAAA,EAAA,KAAK,CAAC,IAAI,CAAO,CAAC;AAChC,KAAA;IAED,QACE,KAAC,CAAA,aAAA,CAAA,eAAe,EAAC,EAAA,OAAO,EAAE,KAAK,CAAC,OAAO,EAAA,EACpC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,KAAI;AACnD,QAAA,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,0BAA0B,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAChD,YAAA,OAAO,IAAI,CAAC;AACb,SAAA;AACD,QAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1B,QAAA,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC,GAAG,eAAe,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACvE,IACE,KAAK,CAAC,mBAAmB;AACzB,aAAC,CAAC,aAAa,KAAK,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,EAChF;AACA,YAAA,OAAO,IAAI,CAAC;AACb,SAAA;AACD,QAAA,QACE,KAAA,CAAA,aAAA,CAAC,oBAAoB,EAAA,EAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,sBAAsB,CAAC,GAAG,CAAC,EAAA;AAC/D,YAAA,KAAA,CAAA,aAAA,CAAC,uBAAuB,EAAA,EACtB,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,aAAa,EACpB,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,EAC9C,IAAI,EAAE,KAAK,CAAC,IAAI,EAAA,CAChB,CACmB,EACvB;KACH,CAAC,CACc,EAClB;AACJ;;;;"}
|
|
File without changes
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { globalSchema, getPropertyDisplayName } from '@medplum/core';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import { CheckboxFormSection } from './CheckboxFormSection.js';
|
|
4
|
+
import { DEFAULT_IGNORED_PROPERTIES } from './constants.js';
|
|
5
|
+
import { FormSection } from './FormSection.js';
|
|
6
|
+
import { setPropertyValue } from './ResourceForm.js';
|
|
7
|
+
import { getValueAndType } from './ResourcePropertyDisplay.js';
|
|
8
|
+
import { ResourcePropertyInput } from './ResourcePropertyInput.js';
|
|
9
|
+
|
|
10
|
+
function BackboneElementInput(props) {
|
|
11
|
+
var _a;
|
|
12
|
+
const [value, setValue] = useState((_a = props.defaultValue) !== null && _a !== void 0 ? _a : {});
|
|
13
|
+
function setValueWrapper(newValue) {
|
|
14
|
+
setValue(newValue);
|
|
15
|
+
if (props.onChange) {
|
|
16
|
+
props.onChange(newValue);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const typeName = props.typeName;
|
|
20
|
+
const typeSchema = globalSchema.types[typeName];
|
|
21
|
+
if (!typeSchema) {
|
|
22
|
+
return React.createElement("div", null,
|
|
23
|
+
typeName,
|
|
24
|
+
"\u00A0not implemented");
|
|
25
|
+
}
|
|
26
|
+
const typedValue = { type: typeName, value };
|
|
27
|
+
return (React.createElement(React.Fragment, null, Object.entries(typeSchema.properties).map((entry) => {
|
|
28
|
+
const key = entry[0];
|
|
29
|
+
if (key === 'id' || DEFAULT_IGNORED_PROPERTIES.indexOf(key) >= 0) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const property = entry[1];
|
|
33
|
+
if (!property.type) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const [propertyValue, propertyType] = getValueAndType(typedValue, key);
|
|
37
|
+
if (property.type.length === 1 && property.type[0].code === 'boolean') {
|
|
38
|
+
return (React.createElement(CheckboxFormSection, { key: key, title: getPropertyDisplayName(key), description: property.definition, htmlFor: key },
|
|
39
|
+
React.createElement(ResourcePropertyInput, { property: property, name: key, defaultValue: propertyValue, defaultPropertyType: propertyType, outcome: props.outcome, onChange: (newValue, propName) => {
|
|
40
|
+
setValueWrapper(setPropertyValue(value, key, propName !== null && propName !== void 0 ? propName : key, entry[1], newValue));
|
|
41
|
+
} })));
|
|
42
|
+
}
|
|
43
|
+
return (React.createElement(FormSection, { key: key, title: getPropertyDisplayName(key), description: property.definition, htmlFor: key, outcome: props.outcome },
|
|
44
|
+
React.createElement(ResourcePropertyInput, { property: property, name: key, defaultValue: propertyValue, defaultPropertyType: propertyType, outcome: props.outcome, onChange: (newValue, propName) => {
|
|
45
|
+
setValueWrapper(setPropertyValue(value, key, propName !== null && propName !== void 0 ? propName : key, entry[1], newValue));
|
|
46
|
+
} })));
|
|
47
|
+
})));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { BackboneElementInput };
|
|
51
|
+
//# sourceMappingURL=BackboneElementInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BackboneElementInput.js","sources":["../../src/BackboneElementInput.tsx"],"sourcesContent":["import { getPropertyDisplayName, globalSchema } from '@medplum/core';\nimport { OperationOutcome } from '@medplum/fhirtypes';\nimport React, { useState } from 'react';\nimport { CheckboxFormSection } from './CheckboxFormSection';\nimport { DEFAULT_IGNORED_PROPERTIES } from './constants';\nimport { FormSection } from './FormSection';\nimport { setPropertyValue } from './ResourceForm';\nimport { getValueAndType } from './ResourcePropertyDisplay';\nimport { ResourcePropertyInput } from './ResourcePropertyInput';\n\nexport interface BackboneElementInputProps {\n typeName: string;\n defaultValue?: any;\n outcome?: OperationOutcome;\n onChange?: (value: any) => void;\n}\n\nexport function BackboneElementInput(props: BackboneElementInputProps): JSX.Element {\n const [value, setValue] = useState<any>(props.defaultValue ?? {});\n\n function setValueWrapper(newValue: any): void {\n setValue(newValue);\n if (props.onChange) {\n props.onChange(newValue);\n }\n }\n\n const typeName = props.typeName;\n const typeSchema = globalSchema.types[typeName];\n if (!typeSchema) {\n return <div>{typeName} not implemented</div>;\n }\n\n const typedValue = { type: typeName, value };\n\n return (\n <>\n {Object.entries(typeSchema.properties).map((entry) => {\n const key = entry[0];\n if (key === 'id' || DEFAULT_IGNORED_PROPERTIES.indexOf(key) >= 0) {\n return null;\n }\n const property = entry[1];\n if (!property.type) {\n return null;\n }\n\n const [propertyValue, propertyType] = getValueAndType(typedValue, key);\n\n if (property.type.length === 1 && property.type[0].code === 'boolean') {\n return (\n <CheckboxFormSection\n key={key}\n title={getPropertyDisplayName(key)}\n description={property.definition}\n htmlFor={key}\n >\n <ResourcePropertyInput\n property={property}\n name={key}\n defaultValue={propertyValue}\n defaultPropertyType={propertyType}\n outcome={props.outcome}\n onChange={(newValue: any, propName?: string) => {\n setValueWrapper(setPropertyValue(value, key, propName ?? key, entry[1], newValue));\n }}\n />\n </CheckboxFormSection>\n );\n }\n\n return (\n <FormSection\n key={key}\n title={getPropertyDisplayName(key)}\n description={property.definition}\n htmlFor={key}\n outcome={props.outcome}\n >\n <ResourcePropertyInput\n property={property}\n name={key}\n defaultValue={propertyValue}\n defaultPropertyType={propertyType}\n outcome={props.outcome}\n onChange={(newValue: any, propName?: string) => {\n setValueWrapper(setPropertyValue(value, key, propName ?? key, entry[1], newValue));\n }}\n />\n </FormSection>\n );\n })}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
function Button(props) {
|
|
4
|
+
const className = 'medplum-button' +
|
|
5
|
+
(props.primary || props.type === 'submit' ? ' medplum-button-primary' : '') +
|
|
6
|
+
(props.danger ? ' medplum-button-danger' : '') +
|
|
7
|
+
(props.borderless ? ' medplum-button-borderless' : '') +
|
|
8
|
+
(props.size ? ' medplum-button-' + props.size : '');
|
|
9
|
+
return (React.createElement("button", { type: props.type || 'button', className: className, style: props.style, onClick: props.onClick, "aria-label": props.label, "data-testid": props.testid }, props.children));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { Button };
|
|
13
|
+
//# sourceMappingURL=Button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Button.js","sources":["../../src/Button.tsx"],"sourcesContent":["import React from 'react';\nimport './Button.css';\n\nexport interface ButtonProps {\n type?: 'button' | 'submit';\n style?: React.CSSProperties;\n primary?: boolean;\n danger?: boolean;\n borderless?: boolean;\n size?: 'small' | 'medium' | 'large';\n onClick?: (e: React.MouseEvent) => void;\n children: React.ReactNode;\n label?: string;\n testid?: string;\n}\n\nexport function Button(props: ButtonProps): JSX.Element {\n const className =\n 'medplum-button' +\n (props.primary || props.type === 'submit' ? ' medplum-button-primary' : '') +\n (props.danger ? ' medplum-button-danger' : '') +\n (props.borderless ? ' medplum-button-borderless' : '') +\n (props.size ? ' medplum-button-' + props.size : '');\n return (\n <button\n type={props.type || 'button'}\n className={className}\n style={props.style}\n onClick={props.onClick}\n aria-label={props.label}\n data-testid={props.testid}\n >\n {props.children}\n </button>\n );\n}\n"],"names":[],"mappings":";;AAgBM,SAAU,MAAM,CAAC,KAAkB,EAAA;IACvC,MAAM,SAAS,GACb,gBAAgB;AAChB,SAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,GAAG,yBAAyB,GAAG,EAAE,CAAC;SAC1E,KAAK,CAAC,MAAM,GAAG,wBAAwB,GAAG,EAAE,CAAC;SAC7C,KAAK,CAAC,UAAU,GAAG,4BAA4B,GAAG,EAAE,CAAC;AACtD,SAAC,KAAK,CAAC,IAAI,GAAG,kBAAkB,GAAG,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;AACtD,IAAA,QACE,KACE,CAAA,aAAA,CAAA,QAAA,EAAA,EAAA,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,QAAQ,EAC5B,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,OAAO,EAAE,KAAK,CAAC,OAAO,EACV,YAAA,EAAA,KAAK,CAAC,KAAK,EAAA,aAAA,EACV,KAAK,CAAC,MAAM,EAExB,EAAA,KAAK,CAAC,QAAQ,CACR,EACT;AACJ;;;;"}
|
|
File without changes
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import React, { useState, useMemo } from 'react';
|
|
2
|
+
import { Button } from './Button.js';
|
|
3
|
+
import { InputRow } from './InputRow.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns a month display string (e.g. "January 2020").
|
|
7
|
+
* @param date Any date within the month.
|
|
8
|
+
* @returns The month display string (e.g. "January 2020")
|
|
9
|
+
*/
|
|
10
|
+
function getMonthString(date) {
|
|
11
|
+
return date.toLocaleString('default', { month: 'long' }) + ' ' + date.getFullYear();
|
|
12
|
+
}
|
|
13
|
+
function CalendarInput(props) {
|
|
14
|
+
const [month, setMonth] = useState(getStartMonth);
|
|
15
|
+
function moveMonth(delta) {
|
|
16
|
+
setMonth((currMonth) => {
|
|
17
|
+
const prevMonth = new Date(currMonth.getTime());
|
|
18
|
+
prevMonth.setMonth(currMonth.getMonth() + delta);
|
|
19
|
+
return prevMonth;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const grid = useMemo(() => buildGrid(month, props.slots), [month, props.slots]);
|
|
23
|
+
return (React.createElement("div", null,
|
|
24
|
+
React.createElement(InputRow, null,
|
|
25
|
+
React.createElement("p", { style: { flex: 1 } }, getMonthString(month)),
|
|
26
|
+
React.createElement("p", null,
|
|
27
|
+
React.createElement(Button, { label: "Previous month", onClick: () => moveMonth(-1) }, "<"),
|
|
28
|
+
React.createElement(Button, { label: "Next month", onClick: () => moveMonth(1) }, ">"))),
|
|
29
|
+
React.createElement("table", { className: "medplum-calendar-table" },
|
|
30
|
+
React.createElement("thead", null,
|
|
31
|
+
React.createElement("tr", null,
|
|
32
|
+
React.createElement("th", null, "SUN"),
|
|
33
|
+
React.createElement("th", null, "MON"),
|
|
34
|
+
React.createElement("th", null, "TUE"),
|
|
35
|
+
React.createElement("th", null, "WED"),
|
|
36
|
+
React.createElement("th", null, "THU"),
|
|
37
|
+
React.createElement("th", null, "FRI"),
|
|
38
|
+
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: () => props.onClick(day.date) }, day.date.getDate()))))))))))));
|
|
40
|
+
}
|
|
41
|
+
function getStartMonth() {
|
|
42
|
+
const result = new Date();
|
|
43
|
+
result.setDate(1);
|
|
44
|
+
result.setHours(0, 0, 0, 0);
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
function buildGrid(startDate, slots) {
|
|
48
|
+
const d = new Date(startDate.getFullYear(), startDate.getMonth());
|
|
49
|
+
const grid = [];
|
|
50
|
+
let row = [];
|
|
51
|
+
// Fill leading empty days
|
|
52
|
+
for (let i = 0; i < d.getDay(); i++) {
|
|
53
|
+
row.push(undefined);
|
|
54
|
+
}
|
|
55
|
+
while (d.getMonth() === startDate.getMonth()) {
|
|
56
|
+
row.push({
|
|
57
|
+
date: new Date(d.getTime()),
|
|
58
|
+
// available: isAvailable(d),
|
|
59
|
+
available: isDayAvailable(d, slots),
|
|
60
|
+
});
|
|
61
|
+
if (d.getDay() === 6) {
|
|
62
|
+
grid.push(row);
|
|
63
|
+
row = [];
|
|
64
|
+
}
|
|
65
|
+
d.setDate(d.getDate() + 1);
|
|
66
|
+
}
|
|
67
|
+
// Fill trailing empty days
|
|
68
|
+
if (d.getDay() !== 0) {
|
|
69
|
+
for (let i = d.getDay(); i < 7; i++) {
|
|
70
|
+
row.push(undefined);
|
|
71
|
+
}
|
|
72
|
+
grid.push(row);
|
|
73
|
+
}
|
|
74
|
+
return grid;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Returns true if the given date is available for booking.
|
|
78
|
+
* @param day The day to check.
|
|
79
|
+
* @param slots The list of available slots.
|
|
80
|
+
* @returns True if there are any available slots for the day.
|
|
81
|
+
*/
|
|
82
|
+
function isDayAvailable(day, slots) {
|
|
83
|
+
// Note that slot start and end time may or may not be in UTC.
|
|
84
|
+
for (const slot of slots) {
|
|
85
|
+
const slotStart = new Date(slot.start);
|
|
86
|
+
if (slotStart.getFullYear() === day.getFullYear() &&
|
|
87
|
+
slotStart.getMonth() === day.getMonth() &&
|
|
88
|
+
slotStart.getDate() === day.getDate()) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { CalendarInput, getMonthString, getStartMonth };
|
|
96
|
+
//# sourceMappingURL=CalendarInput.js.map
|
|
@@ -0,0 +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 { Slot } from '@medplum/fhirtypes';\nimport './CalendarInput.css';\n\nexport interface CalendarInputProps {\n slots: Slot[];\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 [month, setMonth] = useState<Date>(getStartMonth);\n\n function moveMonth(delta: number): void {\n setMonth((currMonth) => {\n const prevMonth = new Date(currMonth.getTime());\n prevMonth.setMonth(currMonth.getMonth() + delta);\n return prevMonth;\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={() => props.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: isAvailable(d),\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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"}
|
|
File without changes
|