@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.
Files changed (90) hide show
  1. package/dist/cjs/index.cjs +47 -46
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs/index.min.cjs +1 -1
  4. package/dist/esm/AsyncAutocomplete/AsyncAutocomplete.mjs +6 -5
  5. package/dist/esm/AsyncAutocomplete/AsyncAutocomplete.mjs.map +1 -1
  6. package/dist/esm/CodeInput/CodeInput.mjs +1 -1
  7. package/dist/esm/CodeInput/CodeInput.mjs.map +1 -1
  8. package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.mjs +2 -2
  9. package/dist/esm/ValueSetAutocomplete/ValueSetAutocomplete.mjs.map +1 -1
  10. package/dist/esm/index.min.mjs +1 -1
  11. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs +1 -1
  12. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs.map +1 -1
  13. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs +1 -1
  14. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs.map +1 -1
  15. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustmentsHorizontal.mjs +1 -1
  16. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAdjustmentsHorizontal.mjs.map +1 -1
  17. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs +1 -1
  18. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconAlertCircle.mjs.map +1 -1
  19. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleach.mjs +1 -1
  20. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleach.mjs.map +1 -1
  21. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleachOff.mjs +1 -1
  22. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBleachOff.mjs.map +1 -1
  23. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBoxMultiple.mjs +1 -1
  24. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBoxMultiple.mjs.map +1 -1
  25. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBracketsContain.mjs +1 -1
  26. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBracketsContain.mjs.map +1 -1
  27. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucket.mjs +1 -1
  28. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucket.mjs.map +1 -1
  29. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucketOff.mjs +1 -1
  30. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconBucketOff.mjs.map +1 -1
  31. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCalendar.mjs +1 -1
  32. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCalendar.mjs.map +1 -1
  33. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs +1 -1
  34. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs.map +1 -1
  35. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheckbox.mjs +1 -1
  36. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCheckbox.mjs.map +1 -1
  37. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleMinus.mjs +1 -1
  38. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCircleMinus.mjs.map +1 -1
  39. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCirclePlus.mjs +1 -1
  40. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCirclePlus.mjs.map +1 -1
  41. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCloudUpload.mjs +1 -1
  42. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCloudUpload.mjs.map +1 -1
  43. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconColumns.mjs +1 -1
  44. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconColumns.mjs.map +1 -1
  45. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCurrencyDollar.mjs +1 -1
  46. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconCurrencyDollar.mjs.map +1 -1
  47. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.mjs +1 -1
  48. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconDots.mjs.map +1 -1
  49. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.mjs +1 -1
  50. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEdit.mjs.map +1 -1
  51. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqual.mjs +1 -1
  52. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqual.mjs.map +1 -1
  53. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqualNot.mjs +1 -1
  54. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconEqualNot.mjs.map +1 -1
  55. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFileAlert.mjs +1 -1
  56. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFileAlert.mjs.map +1 -1
  57. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilePlus.mjs +1 -1
  58. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilePlus.mjs.map +1 -1
  59. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilter.mjs +1 -1
  60. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconFilter.mjs.map +1 -1
  61. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconListDetails.mjs +1 -1
  62. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconListDetails.mjs.map +1 -1
  63. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathGreater.mjs +1 -1
  64. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathGreater.mjs.map +1 -1
  65. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathLower.mjs +1 -1
  66. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMathLower.mjs.map +1 -1
  67. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMessage.mjs +1 -1
  68. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconMessage.mjs.map +1 -1
  69. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPin.mjs +1 -1
  70. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPin.mjs.map +1 -1
  71. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPinnedOff.mjs +1 -1
  72. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconPinnedOff.mjs.map +1 -1
  73. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSettings.mjs +1 -1
  74. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSettings.mjs.map +1 -1
  75. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortAscending.mjs +1 -1
  76. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortAscending.mjs.map +1 -1
  77. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortDescending.mjs +1 -1
  78. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSortDescending.mjs.map +1 -1
  79. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSquare.mjs +1 -1
  80. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconSquare.mjs.map +1 -1
  81. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTableExport.mjs +1 -1
  82. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTableExport.mjs.map +1 -1
  83. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.mjs +1 -1
  84. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconTrash.mjs.map +1 -1
  85. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconX.mjs +1 -1
  86. package/dist/esm/node_modules/@tabler/icons-react/dist/esm/icons/IconX.mjs.map +1 -1
  87. package/dist/types/AsyncAutocomplete/AsyncAutocomplete.d.ts +1 -0
  88. package/dist/types/CodeInput/CodeInput.d.ts +4 -0
  89. package/dist/types/ValueSetAutocomplete/ValueSetAutocomplete.d.ts +2 -0
  90. 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
- result.push(item);
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":";;;AAYM,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;AAED,IAAA,QACE,KAAA,CAAA,aAAA,CAAC,oBAAoB,EAAA,EACnB,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,EAAA,CACtB,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;;;;"}
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}`, onCreate: createValue }));
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\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\n clearable\n toKey={toKey}\n toOption={toOption}\n loadOptions={loadValues}\n getCreateLabel={(query) => `+ Create ${query}`}\n onCreate={createValue}\n />\n );\n}\n\nfunction getDisplay(item: ValueSetExpansionContains): string {\n return item.display || item.code || '';\n}\n"],"names":[],"mappings":";;;;AAcA,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;IAC7B,MAAM,EAAE,iBAAiB,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IAE7C,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;AAEhD,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;AAEF,IAAA,QACE,KAAC,CAAA,aAAA,CAAA,iBAAiB,EACZ,EAAA,GAAA,IAAI,EACR,SAAS,EAAA,IAAA,EACT,SAAS,EAAA,IAAA,EACT,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,UAAU,EACvB,cAAc,EAAE,CAAC,KAAK,KAAK,CAAY,SAAA,EAAA,KAAK,EAAE,EAC9C,QAAQ,EAAE,WAAW,EAAA,CACrB,EACF;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,IAA+B,EAAA;IACjD,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;AACzC;;;;"}
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;;;;"}