@medplum/react 2.0.14 → 2.0.16
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.cjs +47 -46
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.min.cjs +1 -1
- package/dist/esm/AsyncAutocomplete/AsyncAutocomplete.mjs +6 -5
- package/dist/esm/AsyncAutocomplete/AsyncAutocomplete.mjs.map +1 -1
- package/dist/esm/CodeInput/CodeInput.mjs +1 -1
- package/dist/esm/CodeInput/CodeInput.mjs.map +1 -1
- package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.mjs +2 -2
- package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.mjs.map +1 -1
- package/dist/esm/index.min.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustmentsHorizontal.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustmentsHorizontal.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleach.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleach.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleachOff.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleachOff.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBoxMultiple.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBoxMultiple.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBracketsContain.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBracketsContain.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucket.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucket.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucketOff.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucketOff.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCalendar.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCalendar.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheckbox.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheckbox.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleMinus.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleMinus.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCirclePlus.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCirclePlus.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCloudUpload.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCloudUpload.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconColumns.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconColumns.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCurrencyDollar.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCurrencyDollar.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqual.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqual.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqualNot.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqualNot.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFileAlert.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFileAlert.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilePlus.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilePlus.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilter.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilter.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconListDetails.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconListDetails.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathGreater.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathGreater.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathLower.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathLower.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMessage.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMessage.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPin.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPin.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPinnedOff.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPinnedOff.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSettings.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSettings.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortAscending.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortAscending.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortDescending.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortDescending.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSquare.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSquare.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTableExport.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTableExport.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.mjs.map +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconX.mjs +1 -1
- package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconX.mjs.map +1 -1
- package/dist/types/AsyncAutocomplete/AsyncAutocomplete.d.ts +1 -0
- package/dist/types/CodeInput/CodeInput.d.ts +4 -0
- package/dist/types/ValueSetAutocomplete/ValueSetAutocomplete.d.ts +2 -0
- package/package.json +16 -16
|
@@ -3,7 +3,7 @@ import React, { useRef, useState, useCallback, useEffect } from 'react';
|
|
|
3
3
|
import { killEvent } from '../utils/dom.mjs';
|
|
4
4
|
|
|
5
5
|
function AsyncAutocomplete(props) {
|
|
6
|
-
const { defaultValue, toKey, toOption, loadOptions, onChange, onCreate, ...rest } = props;
|
|
6
|
+
const { defaultValue, toKey, toOption, loadOptions, onChange, onCreate, creatable, ...rest } = props;
|
|
7
7
|
const defaultItems = toDefaultItems(defaultValue);
|
|
8
8
|
const inputRef = useRef(null);
|
|
9
9
|
const [lastValue, setLastValue] = useState(undefined);
|
|
@@ -61,13 +61,14 @@ function AsyncAutocomplete(props) {
|
|
|
61
61
|
const result = [];
|
|
62
62
|
for (const value of values) {
|
|
63
63
|
let item = optionsRef.current?.find((option) => option.value === value)?.resource;
|
|
64
|
-
if (!item) {
|
|
64
|
+
if (!item && creatable !== false) {
|
|
65
65
|
item = onCreate(value);
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
if (item)
|
|
68
|
+
result.push(item);
|
|
68
69
|
}
|
|
69
70
|
onChange(result);
|
|
70
|
-
}, [onChange, onCreate]);
|
|
71
|
+
}, [creatable, onChange, onCreate]);
|
|
71
72
|
const handleKeyDown = useCallback((e) => {
|
|
72
73
|
if (e.key === 'Enter') {
|
|
73
74
|
if (!timerRef.current && !abortControllerRef.current) {
|
|
@@ -97,7 +98,7 @@ function AsyncAutocomplete(props) {
|
|
|
97
98
|
}
|
|
98
99
|
};
|
|
99
100
|
}, []);
|
|
100
|
-
return (React.createElement(MultiSelect, { ...rest, ref: inputRef, defaultValue: defaultItems.map(toKey), searchable: true, onKeyDown: handleKeyDown, onSearchChange: handleSearchChange, data: options, onFocus: handleTimer, onChange: handleChange, onCreate: handleCreate, rightSectionWidth: 40, rightSection: abortController ? React.createElement(Loader, { size: 16 }) : null, filter: handleFilter }));
|
|
101
|
+
return (React.createElement(MultiSelect, { ...rest, ref: inputRef, defaultValue: defaultItems.map(toKey), searchable: true, onKeyDown: handleKeyDown, onSearchChange: handleSearchChange, data: options, onFocus: handleTimer, onChange: handleChange, onCreate: handleCreate, rightSectionWidth: 40, rightSection: abortController ? React.createElement(Loader, { size: 16 }) : null, filter: handleFilter, creatable: true }));
|
|
101
102
|
}
|
|
102
103
|
function toDefaultItems(defaultValue) {
|
|
103
104
|
if (!defaultValue) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AsyncAutocomplete.mjs","sources":["../../../src/AsyncAutocomplete/AsyncAutocomplete.tsx"],"sourcesContent":["import { Loader, MultiSelect, MultiSelectProps, SelectItem } from '@mantine/core';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { killEvent } from '../utils/dom';\n\nexport interface AsyncAutocompleteOption<T> extends SelectItem {\n resource: T;\n}\n\nexport interface AsyncAutocompleteProps<T>\n extends Omit<MultiSelectProps, 'data' | 'defaultValue' | 'loadOptions' | 'onChange' | 'onCreate' | 'searchable'> {\n defaultValue?: T | T[];\n toKey: (item: T) => string;\n toOption: (item: T) => AsyncAutocompleteOption<T>;\n loadOptions: (input: string, signal: AbortSignal) => Promise<T[]>;\n onChange: (item: T[]) => void;\n onCreate?: (input: string) => T;\n}\n\nexport function AsyncAutocomplete<T>(props: AsyncAutocompleteProps<T>): JSX.Element {\n const { defaultValue, toKey, toOption, loadOptions, onChange, onCreate, ...rest } = props;\n const defaultItems = toDefaultItems(defaultValue);\n const inputRef = useRef<HTMLInputElement>(null);\n const [lastValue, setLastValue] = useState<string | undefined>(undefined);\n const [timer, setTimer] = useState<number>();\n const [abortController, setAbortController] = useState<AbortController>();\n const [autoSubmit, setAutoSubmit] = useState<boolean>();\n const [options, setOptions] = useState<AsyncAutocompleteOption<T>[]>(defaultItems?.map(toOption));\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 const optionsRef = useRef<AsyncAutocompleteOption<T>[]>();\n optionsRef.current = options;\n\n const handleTimer = useCallback((): 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 loadOptions(value, newAbortController.signal)\n .then((newValues: T[]) => {\n if (!newAbortController.signal.aborted) {\n setOptions(newValues.map(toOption));\n setAbortController(undefined);\n if (autoSubmitRef.current) {\n if (newValues.length > 0) {\n onChange(newValues.slice(0, 1));\n }\n setAutoSubmit(false);\n }\n }\n })\n .catch(console.log);\n }, [loadOptions, onChange, toOption]);\n\n const handleSearchChange = useCallback((): 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 }, [handleTimer]);\n\n const handleChange = useCallback(\n (values: string[]): void => {\n const result: T[] = [];\n for (const value of values) {\n let item = optionsRef.current?.find((option) => option.value === value)?.resource;\n if (!item) {\n item = (onCreate as (input: string) => T)(value);\n }\n result.push(item);\n }\n onChange(result);\n },\n [onChange, onCreate]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent): void => {\n if (e.key === 'Enter') {\n if (!timerRef.current && !abortControllerRef.current) {\n killEvent(e);\n if (optionsRef.current && optionsRef.current.length > 0) {\n setOptions(optionsRef.current.slice(0, 1));\n handleChange([optionsRef.current[0].value]);\n }\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 [handleChange]\n );\n\n const handleCreate = useCallback(\n (input: string): AsyncAutocompleteOption<T> => {\n const option = toOption((onCreate as (input: string) => T)(input));\n setOptions([...(optionsRef.current as AsyncAutocompleteOption<T>[]), option]);\n return option;\n },\n [onCreate, setOptions, toOption]\n );\n\n const handleFilter = useCallback((_value: string, selected: boolean) => !selected, []);\n\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n return (\n <MultiSelect\n {...rest}\n ref={inputRef}\n defaultValue={defaultItems.map(toKey)}\n searchable\n onKeyDown={handleKeyDown}\n onSearchChange={handleSearchChange}\n data={options}\n onFocus={handleTimer}\n onChange={handleChange}\n onCreate={handleCreate}\n rightSectionWidth={40}\n rightSection={abortController ? <Loader size={16} /> : null}\n filter={handleFilter}\n />\n );\n}\n\nfunction toDefaultItems<T>(defaultValue: T | T[] | undefined): T[] {\n if (!defaultValue) {\n return [];\n }\n if (Array.isArray(defaultValue)) {\n return defaultValue;\n }\n return [defaultValue];\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AsyncAutocomplete.mjs","sources":["../../../src/AsyncAutocomplete/AsyncAutocomplete.tsx"],"sourcesContent":["import { Loader, MultiSelect, MultiSelectProps, SelectItem } from '@mantine/core';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { killEvent } from '../utils/dom';\n\nexport interface AsyncAutocompleteOption<T> extends SelectItem {\n resource: T;\n}\n\nexport interface AsyncAutocompleteProps<T>\n extends Omit<MultiSelectProps, 'data' | 'defaultValue' | 'loadOptions' | 'onChange' | 'onCreate' | 'searchable'> {\n defaultValue?: T | T[];\n toKey: (item: T) => string;\n toOption: (item: T) => AsyncAutocompleteOption<T>;\n loadOptions: (input: string, signal: AbortSignal) => Promise<T[]>;\n onChange: (item: T[]) => void;\n onCreate?: (input: string) => T;\n creatable?: boolean;\n}\n\nexport function AsyncAutocomplete<T>(props: AsyncAutocompleteProps<T>): JSX.Element {\n const { defaultValue, toKey, toOption, loadOptions, onChange, onCreate, creatable, ...rest } = props;\n const defaultItems = toDefaultItems(defaultValue);\n const inputRef = useRef<HTMLInputElement>(null);\n const [lastValue, setLastValue] = useState<string | undefined>(undefined);\n const [timer, setTimer] = useState<number>();\n const [abortController, setAbortController] = useState<AbortController>();\n const [autoSubmit, setAutoSubmit] = useState<boolean>();\n const [options, setOptions] = useState<AsyncAutocompleteOption<T>[]>(defaultItems?.map(toOption));\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 const optionsRef = useRef<AsyncAutocompleteOption<T>[]>();\n optionsRef.current = options;\n\n const handleTimer = useCallback((): 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 loadOptions(value, newAbortController.signal)\n .then((newValues: T[]) => {\n if (!newAbortController.signal.aborted) {\n setOptions(newValues.map(toOption));\n setAbortController(undefined);\n if (autoSubmitRef.current) {\n if (newValues.length > 0) {\n onChange(newValues.slice(0, 1));\n }\n setAutoSubmit(false);\n }\n }\n })\n .catch(console.log);\n }, [loadOptions, onChange, toOption]);\n\n const handleSearchChange = useCallback((): 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 }, [handleTimer]);\n\n const handleChange = useCallback(\n (values: string[]): void => {\n const result: T[] = [];\n for (const value of values) {\n let item = optionsRef.current?.find((option) => option.value === value)?.resource;\n if (!item && creatable !== false) {\n item = (onCreate as (input: string) => T)(value);\n }\n\n if (item) result.push(item);\n }\n onChange(result);\n },\n [creatable, onChange, onCreate]\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent): void => {\n if (e.key === 'Enter') {\n if (!timerRef.current && !abortControllerRef.current) {\n killEvent(e);\n if (optionsRef.current && optionsRef.current.length > 0) {\n setOptions(optionsRef.current.slice(0, 1));\n handleChange([optionsRef.current[0].value]);\n }\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 [handleChange]\n );\n\n const handleCreate = useCallback(\n (input: string): AsyncAutocompleteOption<T> => {\n const option = toOption((onCreate as (input: string) => T)(input));\n setOptions([...(optionsRef.current as AsyncAutocompleteOption<T>[]), option]);\n return option;\n },\n [onCreate, setOptions, toOption]\n );\n\n const handleFilter = useCallback((_value: string, selected: boolean) => !selected, []);\n\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n return (\n <MultiSelect\n {...rest}\n ref={inputRef}\n defaultValue={defaultItems.map(toKey)}\n searchable\n onKeyDown={handleKeyDown}\n onSearchChange={handleSearchChange}\n data={options}\n onFocus={handleTimer}\n onChange={handleChange}\n onCreate={handleCreate}\n rightSectionWidth={40}\n rightSection={abortController ? <Loader size={16} /> : null}\n filter={handleFilter}\n creatable\n />\n );\n}\n\nfunction toDefaultItems<T>(defaultValue: T | T[] | undefined): T[] {\n if (!defaultValue) {\n return [];\n }\n if (Array.isArray(defaultValue)) {\n return defaultValue;\n }\n return [defaultValue];\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@ function CodeInput(props) {
|
|
|
11
11
|
props.onChange(newCode);
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
return (React.createElement(ValueSetAutocomplete, { elementDefinition: props.property, name: props.name, placeholder: props.placeholder, defaultValue: codeToValueSetElement(value), onChange: handleChange }));
|
|
14
|
+
return (React.createElement(ValueSetAutocomplete, { elementDefinition: props.property, name: props.name, placeholder: props.placeholder, defaultValue: codeToValueSetElement(value), onChange: handleChange, creatable: props.creatable, maxSelectedValues: props.maxSelectedValues, clearSearchOnChange: props.clearSearchOnChange, clearable: props.clearable }));
|
|
15
15
|
}
|
|
16
16
|
function codeToValueSetElement(code) {
|
|
17
17
|
return code ? { code } : undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeInput.mjs","sources":["../../../src/CodeInput/CodeInput.tsx"],"sourcesContent":["import { ElementDefinition, ValueSetExpansionContains } from '@medplum/fhirtypes';\nimport React, { useState } from 'react';\nimport { ValueSetAutocomplete } from '../ValueSetAutocomplete/ValueSetAutocomplete';\n\nexport interface CodeInputProps {\n property: ElementDefinition;\n name: string;\n placeholder?: string;\n defaultValue?: string;\n onChange?: (value: string | undefined) => void;\n}\n\nexport function CodeInput(props: CodeInputProps): JSX.Element {\n const [value, setValue] = useState<string | undefined>(props.defaultValue);\n\n function handleChange(newValues: ValueSetExpansionContains[]): void {\n const newValue = newValues[0];\n const newCode = valueSetElementToCode(newValue);\n setValue(newCode);\n if (props.onChange) {\n props.onChange(newCode);\n }\n }\n\n return (\n <ValueSetAutocomplete\n elementDefinition={props.property}\n name={props.name}\n placeholder={props.placeholder}\n defaultValue={codeToValueSetElement(value)}\n onChange={handleChange}\n />\n );\n}\n\nfunction codeToValueSetElement(code: string | undefined): ValueSetExpansionContains | undefined {\n return code ? { code } : undefined;\n}\n\nfunction valueSetElementToCode(element: ValueSetExpansionContains | undefined): string | undefined {\n return element?.code;\n}\n"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"CodeInput.mjs","sources":["../../../src/CodeInput/CodeInput.tsx"],"sourcesContent":["import { ElementDefinition, ValueSetExpansionContains } from '@medplum/fhirtypes';\nimport React, { useState } from 'react';\nimport { ValueSetAutocomplete } from '../ValueSetAutocomplete/ValueSetAutocomplete';\n\nexport interface CodeInputProps {\n property: ElementDefinition;\n name: string;\n placeholder?: string;\n defaultValue?: string;\n onChange?: (value: string | undefined) => void;\n creatable?: boolean;\n maxSelectedValues?: number;\n clearSearchOnChange?: boolean;\n clearable?: boolean;\n}\n\nexport function CodeInput(props: CodeInputProps): JSX.Element {\n const [value, setValue] = useState<string | undefined>(props.defaultValue);\n\n function handleChange(newValues: ValueSetExpansionContains[]): void {\n const newValue = newValues[0];\n const newCode = valueSetElementToCode(newValue);\n setValue(newCode);\n if (props.onChange) {\n props.onChange(newCode);\n }\n }\n\n return (\n <ValueSetAutocomplete\n elementDefinition={props.property}\n name={props.name}\n placeholder={props.placeholder}\n defaultValue={codeToValueSetElement(value)}\n onChange={handleChange}\n creatable={props.creatable}\n maxSelectedValues={props.maxSelectedValues}\n clearSearchOnChange={props.clearSearchOnChange}\n clearable={props.clearable}\n />\n );\n}\n\nfunction codeToValueSetElement(code: string | undefined): ValueSetExpansionContains | undefined {\n return code ? { code } : undefined;\n}\n\nfunction valueSetElementToCode(element: ValueSetExpansionContains | undefined): string | undefined {\n return element?.code;\n}\n"],"names":[],"mappings":";;;AAgBM,SAAU,SAAS,CAAC,KAAqB,EAAA;AAC7C,IAAA,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAqB,KAAK,CAAC,YAAY,CAAC,CAAC;IAE3E,SAAS,YAAY,CAAC,SAAsC,EAAA;AAC1D,QAAA,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;AAC9B,QAAA,MAAM,OAAO,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAChD,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClB,IAAI,KAAK,CAAC,QAAQ,EAAE;AAClB,YAAA,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACzB,SAAA;KACF;IAED,QACE,KAAC,CAAA,aAAA,CAAA,oBAAoB,EACnB,EAAA,iBAAiB,EAAE,KAAK,CAAC,QAAQ,EACjC,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,WAAW,EAAE,KAAK,CAAC,WAAW,EAC9B,YAAY,EAAE,qBAAqB,CAAC,KAAK,CAAC,EAC1C,QAAQ,EAAE,YAAY,EACtB,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAC1C,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,EAC9C,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,CAAA,EACF;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAwB,EAAA;IACrD,OAAO,IAAI,GAAG,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC;AACrC,CAAC;AAED,SAAS,qBAAqB,CAAC,OAA8C,EAAA;IAC3E,OAAO,OAAO,EAAE,IAAI,CAAC;AACvB;;;;"}
|
|
@@ -23,7 +23,7 @@ function createValue(input) {
|
|
|
23
23
|
*/
|
|
24
24
|
function ValueSetAutocomplete(props) {
|
|
25
25
|
const medplum = useMedplum();
|
|
26
|
-
const { elementDefinition, ...rest } = props;
|
|
26
|
+
const { elementDefinition, creatable, clearable, ...rest } = props;
|
|
27
27
|
const loadValues = useCallback(async (input, signal) => {
|
|
28
28
|
const system = elementDefinition.binding?.valueSet;
|
|
29
29
|
const valueSet = await medplum.searchValueSet(system, input, { signal });
|
|
@@ -36,7 +36,7 @@ function ValueSetAutocomplete(props) {
|
|
|
36
36
|
}
|
|
37
37
|
return newData;
|
|
38
38
|
}, [medplum, elementDefinition]);
|
|
39
|
-
return (React.createElement(AsyncAutocomplete, { ...rest, creatable: true, clearable: true, toKey: toKey, toOption: toOption, loadOptions: loadValues, getCreateLabel: (query) => `+ Create ${query}
|
|
39
|
+
return (React.createElement(AsyncAutocomplete, { ...rest, creatable: creatable ?? true, clearable: clearable ?? true, toKey: toKey, toOption: toOption, loadOptions: loadValues, onCreate: createValue, getCreateLabel: creatable === false ? undefined : (query) => `+ Create ${query}` }));
|
|
40
40
|
}
|
|
41
41
|
function getDisplay(item) {
|
|
42
42
|
return item.display || item.code || '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValueSetAutocomplete.mjs","sources":["../../../src/ValueSetAutocomplete/ValueSetAutocomplete.tsx"],"sourcesContent":["import { ElementDefinition, ValueSetExpansionContains } from '@medplum/fhirtypes';\nimport React, { useCallback } from 'react';\nimport {\n AsyncAutocomplete,\n AsyncAutocompleteOption,\n AsyncAutocompleteProps,\n} from '../AsyncAutocomplete/AsyncAutocomplete';\nimport { useMedplum } from '../MedplumProvider/MedplumProvider';\n\nexport interface ValueSetAutocompleteProps\n extends Omit<AsyncAutocompleteProps<ValueSetExpansionContains>, 'loadOptions' | 'toKey' | 'toOption'> {\n elementDefinition: ElementDefinition;\n}\n\nfunction toKey(element: ValueSetExpansionContains): string {\n return element.code as string;\n}\n\nfunction toOption(element: ValueSetExpansionContains): AsyncAutocompleteOption<ValueSetExpansionContains> {\n return {\n value: element.code as string,\n label: getDisplay(element),\n resource: element,\n };\n}\n\nfunction createValue(input: string): ValueSetExpansionContains {\n return {\n code: input,\n display: input,\n };\n}\n\n/**\n * A low-level component to autocomplete based on a FHIR Valueset.\n */\nexport function ValueSetAutocomplete(props: ValueSetAutocompleteProps): JSX.Element {\n const medplum = useMedplum();\n const { elementDefinition, ...rest } = props;\n\n const loadValues = useCallback(\n async (input: string, signal: AbortSignal): Promise<ValueSetExpansionContains[]> => {\n const system = elementDefinition.binding?.valueSet as string;\n const valueSet = await medplum.searchValueSet(system, input, { signal });\n const valueSetElements = valueSet.expansion?.contains as ValueSetExpansionContains[];\n const newData: ValueSetExpansionContains[] = [];\n
|
|
1
|
+
{"version":3,"file":"ValueSetAutocomplete.mjs","sources":["../../../src/ValueSetAutocomplete/ValueSetAutocomplete.tsx"],"sourcesContent":["import { ElementDefinition, ValueSetExpansionContains } from '@medplum/fhirtypes';\nimport React, { useCallback } from 'react';\nimport {\n AsyncAutocomplete,\n AsyncAutocompleteOption,\n AsyncAutocompleteProps,\n} from '../AsyncAutocomplete/AsyncAutocomplete';\nimport { useMedplum } from '../MedplumProvider/MedplumProvider';\n\nexport interface ValueSetAutocompleteProps\n extends Omit<AsyncAutocompleteProps<ValueSetExpansionContains>, 'loadOptions' | 'toKey' | 'toOption'> {\n elementDefinition: ElementDefinition;\n creatable?: boolean;\n clearable?: boolean;\n}\n\nfunction toKey(element: ValueSetExpansionContains): string {\n return element.code as string;\n}\n\nfunction toOption(element: ValueSetExpansionContains): AsyncAutocompleteOption<ValueSetExpansionContains> {\n return {\n value: element.code as string,\n label: getDisplay(element),\n resource: element,\n };\n}\n\nfunction createValue(input: string): ValueSetExpansionContains {\n return {\n code: input,\n display: input,\n };\n}\n\n/**\n * A low-level component to autocomplete based on a FHIR Valueset.\n */\nexport function ValueSetAutocomplete(props: ValueSetAutocompleteProps): JSX.Element {\n const medplum = useMedplum();\n const { elementDefinition, creatable, clearable, ...rest } = props;\n\n const loadValues = useCallback(\n async (input: string, signal: AbortSignal): Promise<ValueSetExpansionContains[]> => {\n const system = elementDefinition.binding?.valueSet as string;\n const valueSet = await medplum.searchValueSet(system, input, { signal });\n const valueSetElements = valueSet.expansion?.contains as ValueSetExpansionContains[];\n const newData: ValueSetExpansionContains[] = [];\n for (const valueSetElement of valueSetElements) {\n if (valueSetElement.code && !newData.some((item) => item.code === valueSetElement.code)) {\n newData.push(valueSetElement);\n }\n }\n\n return newData;\n },\n [medplum, elementDefinition]\n );\n\n return (\n <AsyncAutocomplete\n {...rest}\n creatable={creatable ?? true}\n clearable={clearable ?? true}\n toKey={toKey}\n toOption={toOption}\n loadOptions={loadValues}\n onCreate={createValue}\n getCreateLabel={creatable === false ? undefined : (query: any) => `+ Create ${query}`}\n />\n );\n}\n\nfunction getDisplay(item: ValueSetExpansionContains): string {\n return item.display || item.code || '';\n}\n"],"names":[],"mappings":";;;;AAgBA,SAAS,KAAK,CAAC,OAAkC,EAAA;IAC/C,OAAO,OAAO,CAAC,IAAc,CAAC;AAChC,CAAC;AAED,SAAS,QAAQ,CAAC,OAAkC,EAAA;IAClD,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,IAAc;AAC7B,QAAA,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC;AAC1B,QAAA,QAAQ,EAAE,OAAO;KAClB,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,KAAa,EAAA;IAChC,OAAO;AACL,QAAA,IAAI,EAAE,KAAK;AACX,QAAA,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC;AAED;;AAEG;AACG,SAAU,oBAAoB,CAAC,KAAgC,EAAA;AACnE,IAAA,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;AAC7B,IAAA,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAEnE,MAAM,UAAU,GAAG,WAAW,CAC5B,OAAO,KAAa,EAAE,MAAmB,KAA0C;AACjF,QAAA,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE,QAAkB,CAAC;AAC7D,QAAA,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AACzE,QAAA,MAAM,gBAAgB,GAAG,QAAQ,CAAC,SAAS,EAAE,QAAuC,CAAC;QACrF,MAAM,OAAO,GAAgC,EAAE,CAAC;AAChD,QAAA,KAAK,MAAM,eAAe,IAAI,gBAAgB,EAAE;YAC9C,IAAI,eAAe,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,IAAI,CAAC,EAAE;AACvF,gBAAA,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAC/B,aAAA;AACF,SAAA;AAED,QAAA,OAAO,OAAO,CAAC;AACjB,KAAC,EACD,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAC7B,CAAC;IAEF,QACE,KAAC,CAAA,aAAA,CAAA,iBAAiB,EACZ,EAAA,GAAA,IAAI,EACR,SAAS,EAAE,SAAS,IAAI,IAAI,EAC5B,SAAS,EAAE,SAAS,IAAI,IAAI,EAC5B,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,UAAU,EACvB,QAAQ,EAAE,WAAW,EACrB,cAAc,EAAE,SAAS,KAAK,KAAK,GAAG,SAAS,GAAG,CAAC,KAAU,KAAK,CAAA,SAAA,EAAY,KAAK,CAAA,CAAE,EACrF,CAAA,EACF;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,IAA+B,EAAA;IACjD,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;AACzC;;;;"}
|