@ews-admin/global-design-system 1.27.0 → 1.28.0

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.
@@ -17,7 +17,14 @@ interface SearchAutocompleteProps<T extends SearchableEntity> {
17
17
  minSearchLength?: number;
18
18
  debounceTime?: number;
19
19
  error?: string;
20
+ /**
21
+ * MED-1501: builds the hint appended to the placeholder while the search
22
+ * term is still too short. Return `null` (or an empty string) to suppress
23
+ * the hint entirely. Defaults to the English "(min. N characters)", so
24
+ * callers that do not pass it keep today's placeholder.
25
+ */
26
+ getMinCharactersHint?: (minSearchLength: number) => string | null;
20
27
  }
21
- export declare function SearchAutocomplete<T extends SearchableEntity>({ onSelect, selectedId, searchFunction, getEntityById, getDisplayValue, getSecondaryText, placeholder, icon, disabled, minSearchLength, debounceTime, error, }: SearchAutocompleteProps<T>): React.JSX.Element;
28
+ export declare function SearchAutocomplete<T extends SearchableEntity>({ onSelect, selectedId, searchFunction, getEntityById, getDisplayValue, getSecondaryText, placeholder, icon, disabled, minSearchLength, debounceTime, error, getMinCharactersHint, }: SearchAutocompleteProps<T>): React.JSX.Element;
22
29
  export {};
23
30
  //# sourceMappingURL=SearchAutocomplete.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SearchAutocomplete.d.ts","sourceRoot":"","sources":["../../../src/components/SearchAutocomplete/SearchAutocomplete.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,cAAc,CAAC;AACrD,OAAO,KAAsC,MAAM,OAAO,CAAC;AAK3D,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,UAAU,uBAAuB,CAAC,CAAC,SAAS,gBAAgB;IAC1D,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAClD,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IACvD,eAAe,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAC;IACvC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,GAAG,IAAI,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,gBAAgB,EAAE,EAC7D,QAAQ,EACR,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,IAAa,EACb,QAAgB,EAChB,eAAmB,EACnB,YAAkB,EAClB,KAAK,GACN,EAAE,uBAAuB,CAAC,CAAC,CAAC,qBAiR5B"}
1
+ {"version":3,"file":"SearchAutocomplete.d.ts","sourceRoot":"","sources":["../../../src/components/SearchAutocomplete/SearchAutocomplete.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,cAAc,CAAC;AACrD,OAAO,KAAsC,MAAM,OAAO,CAAC;AAK3D,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,UAAU,uBAAuB,CAAC,CAAC,SAAS,gBAAgB;IAC1D,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAClD,aAAa,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IACvD,eAAe,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAC;IACvC,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,GAAG,IAAI,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACnE;AAED,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,gBAAgB,EAAE,EAC7D,QAAQ,EACR,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,IAAa,EACb,QAAgB,EAChB,eAAmB,EACnB,YAAkB,EAClB,KAAK,EACL,oBAA0D,GAC3D,EAAE,uBAAuB,CAAC,CAAC,CAAC,qBAsR5B"}
@@ -92,6 +92,21 @@ export interface SelectProps<T = unknown> {
92
92
  * avatar menu).
93
93
  */
94
94
  renderTrigger?: () => React.ReactNode;
95
+ /**
96
+ * MED-1501: placeholder of the in-dropdown search input, so the caller can
97
+ * translate it. Defaults to the English "Search options...".
98
+ */
99
+ searchPlaceholder?: string;
100
+ /**
101
+ * MED-1501: text shown when a search matches no option, so the caller can
102
+ * translate it. Defaults to the English "No options found".
103
+ */
104
+ noOptionsFoundText?: string;
105
+ /**
106
+ * MED-1501: text shown when there is no option at all, so the caller can
107
+ * translate it. Defaults to the English "No options available".
108
+ */
109
+ noOptionsAvailableText?: string;
95
110
  }
96
111
  declare const Select: React.ForwardRefExoticComponent<SelectProps<unknown> & React.RefAttributes<HTMLDivElement>>;
97
112
  export { Select };
@@ -1 +1 @@
1
- {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../src/components/Select/Select.tsx"],"names":[],"mappings":"AACA,OAAO,KAON,MAAM,OAAO,CAAC;AAIf,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3B;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,CAAC;IACV;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACvD;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,YAAY,CAAC,EAAE,CACb,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EACvB,UAAU,EAAE,OAAO,KAChB,KAAK,CAAC,SAAS,CAAC;IACrB;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,CAAC,SAAS,CAAC;IAClE;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;CACvC;AAED,QAAA,MAAM,MAAM,6FAmcX,CAAC;AAIF,OAAO,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../src/components/Select/Select.tsx"],"names":[],"mappings":"AACA,OAAO,KAON,MAAM,OAAO,CAAC;AAIf,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3B;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,CAAC;IACV;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACvD;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,YAAY,CAAC,EAAE,CACb,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EACvB,UAAU,EAAE,OAAO,KAChB,KAAK,CAAC,SAAS,CAAC;IACrB;;OAEG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,CAAC,SAAS,CAAC;IAClE;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACtC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,QAAA,MAAM,MAAM,6FAscX,CAAC;AAIF,OAAO,EAAE,MAAM,EAAE,CAAC"}
package/dist/index.d.ts CHANGED
@@ -201,6 +201,21 @@ interface SelectProps<T = unknown> {
201
201
  * avatar menu).
202
202
  */
203
203
  renderTrigger?: () => React__default.ReactNode;
204
+ /**
205
+ * MED-1501: placeholder of the in-dropdown search input, so the caller can
206
+ * translate it. Defaults to the English "Search options...".
207
+ */
208
+ searchPlaceholder?: string;
209
+ /**
210
+ * MED-1501: text shown when a search matches no option, so the caller can
211
+ * translate it. Defaults to the English "No options found".
212
+ */
213
+ noOptionsFoundText?: string;
214
+ /**
215
+ * MED-1501: text shown when there is no option at all, so the caller can
216
+ * translate it. Defaults to the English "No options available".
217
+ */
218
+ noOptionsAvailableText?: string;
204
219
  }
205
220
  declare const Select: React__default.ForwardRefExoticComponent<SelectProps<unknown> & React__default.RefAttributes<HTMLDivElement>>;
206
221
 
@@ -221,8 +236,15 @@ interface SearchAutocompleteProps<T extends SearchableEntity> {
221
236
  minSearchLength?: number;
222
237
  debounceTime?: number;
223
238
  error?: string;
239
+ /**
240
+ * MED-1501: builds the hint appended to the placeholder while the search
241
+ * term is still too short. Return `null` (or an empty string) to suppress
242
+ * the hint entirely. Defaults to the English "(min. N characters)", so
243
+ * callers that do not pass it keep today's placeholder.
244
+ */
245
+ getMinCharactersHint?: (minSearchLength: number) => string | null;
224
246
  }
225
- declare function SearchAutocomplete<T extends SearchableEntity>({ onSelect, selectedId, searchFunction, getEntityById, getDisplayValue, getSecondaryText, placeholder, icon, disabled, minSearchLength, debounceTime, error, }: SearchAutocompleteProps<T>): React__default.JSX.Element;
247
+ declare function SearchAutocomplete<T extends SearchableEntity>({ onSelect, selectedId, searchFunction, getEntityById, getDisplayValue, getSecondaryText, placeholder, icon, disabled, minSearchLength, debounceTime, error, getMinCharactersHint, }: SearchAutocompleteProps<T>): React__default.JSX.Element;
226
248
 
227
249
  interface MultiSearchAutocompleteProps<T extends SearchableEntity> {
228
250
  items: T[];
@@ -585,6 +607,12 @@ interface SpecialtySearchAutocompleteProps {
585
607
  title?: string;
586
608
  label?: string;
587
609
  getSelectedCountText?: (count: number) => React__default.ReactNode;
610
+ /**
611
+ * MED-1499: accessible label / tooltip of the button that removes a
612
+ * selected specialty from its chip. Defaults to the English
613
+ * "Remove specialty".
614
+ */
615
+ removeSpecialtyLabel?: string;
588
616
  }
589
617
  declare const SpecialtySearchAutocomplete: React__default.FC<SpecialtySearchAutocompleteProps>;
590
618
 
package/dist/index.esm.js CHANGED
@@ -32766,7 +32766,7 @@ const Input = React__default.forwardRef(({ className, variant = "default", size
32766
32766
  });
32767
32767
  Input.displayName = "Input";
32768
32768
 
32769
- const Select = forwardRef(({ options = [], value, onChange, placeholder = "Select an option...", label, helperText, error, isError = false, size = "md", disabled = false, required = false, searchable = false, multiple: _multiple = false, selectClassName, containerClassName, dropdownClassName, maxHeight = 200, clearable = false, renderOption, renderValue, renderTrigger, ...props }, ref) => {
32769
+ const Select = forwardRef(({ options = [], value, onChange, placeholder = "Select an option...", label, helperText, error, isError = false, size = "md", disabled = false, required = false, searchable = false, multiple: _multiple = false, selectClassName, containerClassName, dropdownClassName, maxHeight = 200, clearable = false, renderOption, renderValue, renderTrigger, searchPlaceholder = "Search options...", noOptionsFoundText = "No options found", noOptionsAvailableText = "No options available", ...props }, ref) => {
32770
32770
  const generatedId = useId();
32771
32771
  const selectId = `select-${generatedId}`;
32772
32772
  const hasError = isError || !!error;
@@ -32975,7 +32975,7 @@ const Select = forwardRef(({ options = [], value, onChange, placeholder = "Selec
32975
32975
  // Padding for icons
32976
32976
  "pr-10", selectClassName), ...props, children: jsx("div", { className: "flex justify-between items-center", children: renderTrigger ? (renderTrigger()) : (jsxs(Fragment, { children: [jsx("div", { className: "flex-1 min-w-0", children: selectedOption ? (renderValue ? (renderValue(selectedOption)) : (jsx("span", { className: "truncate", children: selectedOption.label }))) : (jsx("span", { className: "text-ews-gray-500", children: placeholder })) }), jsxs("div", { className: "flex items-center ml-2 space-x-1", children: [clearable && selectedOption && !disabled && (jsx("button", { type: "button", onClick: handleClear, className: "p-1 rounded hover:bg-ews-gray-100", children: jsx(X, { className: cn(iconSizeClasses[size], "text-ews-gray-400") }) })), jsx(ChevronDown, { className: cn(iconSizeClasses[size], hasError ? "text-ews-error" : "text-ews-gray-400", disabled && "text-ews-gray-300", isOpen && "rotate-180 transition-transform") })] })] })) }) }), isOpen && (jsxs("div", { ref: dropdownRef, role: "listbox", className: cn("absolute z-50 w-full bg-white rounded-md border shadow-lg border-ews-gray-300", "focus:outline-none", dropdownPosition === "top"
32977
32977
  ? "bottom-full mb-1"
32978
- : "top-full mt-1", dropdownClassName), style: { maxHeight: `${maxHeight}px` }, children: [searchable && (jsx("div", { className: "p-2 border-b border-ews-gray-200", children: jsxs("div", { className: "relative", children: [jsx(Search, { className: "absolute left-3 top-1/2 w-4 h-4 transform -translate-y-1/2 text-ews-gray-400" }), jsx(Input, { ref: inputRef, type: "text", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), placeholder: "Search options...", leftIcon: jsx(Search, { className: "w-4 h-4 text-ews-gray-400" }) })] }) })), jsx("div", { className: "overflow-auto py-1", style: { maxHeight: `${maxHeight - (searchable ? 60 : 0)}px` }, children: filteredOptions.length === 0 ? (jsx("div", { className: "px-3 py-2 text-sm text-ews-gray-500", children: searchTerm ? "No options found" : "No options available" })) : (filteredOptions.map((option, index) => {
32978
+ : "top-full mt-1", dropdownClassName), style: { maxHeight: `${maxHeight}px` }, children: [searchable && (jsx("div", { className: "p-2 border-b border-ews-gray-200", children: jsxs("div", { className: "relative", children: [jsx(Search, { className: "absolute left-3 top-1/2 w-4 h-4 transform -translate-y-1/2 text-ews-gray-400" }), jsx(Input, { ref: inputRef, type: "text", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), placeholder: searchPlaceholder, leftIcon: jsx(Search, { className: "w-4 h-4 text-ews-gray-400" }) })] }) })), jsx("div", { className: "overflow-auto py-1", style: { maxHeight: `${maxHeight - (searchable ? 60 : 0)}px` }, children: filteredOptions.length === 0 ? (jsx("div", { className: "px-3 py-2 text-sm text-ews-gray-500", children: searchTerm ? noOptionsFoundText : noOptionsAvailableText })) : (filteredOptions.map((option, index) => {
32979
32979
  const isSelected = option.value === value;
32980
32980
  const isFocused = index === focusedIndex;
32981
32981
  return (jsx("div", { ref: (el) => (optionRefs.current[index] = el), role: "option", "aria-selected": isSelected, onClick: () => handleSelect(option), className: cn("px-3 py-2 text-sm cursor-pointer transition-colors", isSelected && "bg-ews-primary text-white", !isSelected && isFocused && "bg-ews-gray-100", !isSelected && !isFocused && "hover:bg-ews-gray-50", option.disabled && "opacity-50 cursor-not-allowed"), children: renderOption ? (renderOption(option, isSelected)) : (jsx("span", { className: "truncate", children: option.label })) }, `${String(option.value)}-${index}`));
@@ -33052,7 +33052,7 @@ function useSelectField({ name, control, options: _options, rules, defaultValue,
33052
33052
  };
33053
33053
  }
33054
33054
 
33055
- function SearchAutocomplete({ onSelect, selectedId, searchFunction, getEntityById, getDisplayValue, getSecondaryText, placeholder, icon = Search, disabled = false, minSearchLength = 2, debounceTime = 300, error, }) {
33055
+ function SearchAutocomplete({ onSelect, selectedId, searchFunction, getEntityById, getDisplayValue, getSecondaryText, placeholder, icon = Search, disabled = false, minSearchLength = 2, debounceTime = 300, error, getMinCharactersHint = (min) => `(min. ${min} characters)`, }) {
33056
33056
  const [searchTerm, setSearchTerm] = useState("");
33057
33057
  const [entities, setEntities] = useState([]);
33058
33058
  const [isLoading, setIsLoading] = useState(false);
@@ -33165,7 +33165,11 @@ function SearchAutocomplete({ onSelect, selectedId, searchFunction, getEntityByI
33165
33165
  setSearchTerm("");
33166
33166
  onSelect("");
33167
33167
  };
33168
- return (jsxs("div", { className: "relative", ref: dropdownRef, children: [jsxs("div", { className: "relative", children: [jsx(Input, { type: "text", placeholder: `${placeholder} (min. ${minSearchLength} characters)`, value: selectedEntity ? "" : searchTerm, onChange: handleSearchChange, onFocus: () => searchTerm.length >= minSearchLength &&
33168
+ const minCharactersHint = getMinCharactersHint(minSearchLength);
33169
+ const inputPlaceholder = minCharactersHint
33170
+ ? `${placeholder} ${minCharactersHint}`
33171
+ : placeholder;
33172
+ return (jsxs("div", { className: "relative", ref: dropdownRef, children: [jsxs("div", { className: "relative", children: [jsx(Input, { type: "text", placeholder: inputPlaceholder, value: selectedEntity ? "" : searchTerm, onChange: handleSearchChange, onFocus: () => searchTerm.length >= minSearchLength &&
33169
33173
  isUserSearch.current &&
33170
33174
  setShowDropdown(true), disabled: disabled, autoComplete: "off", name: "search-autocomplete", leftIcon: React__default.createElement(icon, { size: 16 }) }), selectedEntity && (jsx("button", { type: "button", className: "flex absolute inset-y-0 right-0 items-center pr-3", onClick: handleClearSelection, disabled: disabled, children: jsx(X, { className: "w-5 h-5 text-gray-400 hover:text-gray-500" }) }))] }), selectedEntity && (jsx("div", { className: "p-4 mt-3 rounded-lg border bg-neutral-50 border-neutral-200", children: jsxs("div", { className: "flex justify-between items-center", children: [jsxs("div", { className: "flex items-center", children: [selectedEntity.photoUrl ? (jsx("img", { src: selectedEntity.photoUrl, alt: getDisplayValue(selectedEntity), className: "object-cover mr-3 w-10 h-10 rounded-full" })) : (React__default.createElement(icon, {
33171
33175
  className: "w-10 h-10 text-neutral-400 mr-3",
@@ -35236,7 +35240,7 @@ const PaymentDueBanner = ({ title, subtitle, warning, ctaLabel, onCtaClick, onDi
35236
35240
  */
35237
35241
  const SecureLoader = ({ label, description }) => (jsx("div", { "data-testid": "secure-loader", className: "flex min-h-screen items-center justify-center bg-gray-100", children: jsxs("div", { className: "flex flex-col items-center rounded-lg bg-white p-6 shadow-lg", children: [jsxs("div", { className: "relative", children: [jsx(Lock, { className: "h-16 w-16 text-gray-500" }), jsx("div", { className: "absolute bottom-2 right-1 h-6 w-6 animate-spin rounded-full border-4 border-gray-300 border-t-green-500" })] }), jsx("p", { className: "mt-4 text-lg text-gray-600", children: label }), description && (jsx("p", { className: "mt-2 text-sm text-gray-500", children: description }))] }) }));
35238
35242
 
35239
- const SpecialtySearchAutocomplete = ({ selectedSpecialties = [], onSpecialtiesChange, specialties: availableSpecialties, placeholder = "Search and select medical specialties...", className = "", disabled = false, maxSelections, showSelectedCount = true, title = "Medical Specialties", label = "Select Specialties", getSelectedCountText, }) => {
35243
+ const SpecialtySearchAutocomplete = ({ selectedSpecialties = [], onSpecialtiesChange, specialties: availableSpecialties, placeholder = "Search and select medical specialties...", className = "", disabled = false, maxSelections, showSelectedCount = true, title = "Medical Specialties", label = "Select Specialties", getSelectedCountText, removeSpecialtyLabel = "Remove specialty", }) => {
35240
35244
  const [filteredSpecialties, setFilteredSpecialties] = useState([]);
35241
35245
  const [isLoading, setIsLoading] = useState(false);
35242
35246
  // Filter specialties based on search term
@@ -35267,10 +35271,15 @@ const SpecialtySearchAutocomplete = ({ selectedSpecialties = [], onSpecialtiesCh
35267
35271
  }
35268
35272
  onSpecialtiesChange(items);
35269
35273
  }, [onSpecialtiesChange, maxSelections]);
35274
+ // MED-1499: a selected specialty must be removable from its chip, not only
35275
+ // by toggling it off again in the dropdown list.
35276
+ const handleRemoveSpecialty = useCallback((specialtyToRemove) => {
35277
+ onSpecialtiesChange(selectedSpecialties.filter((specialty) => specialty.id !== specialtyToRemove.id));
35278
+ }, [onSpecialtiesChange, selectedSpecialties]);
35270
35279
  const getEntityById = useCallback(async (id) => {
35271
35280
  return availableSpecialties.find((specialty) => specialty.id === id);
35272
35281
  }, [availableSpecialties]);
35273
- return (jsxs("div", { className: cn("space-y-3", className), children: [jsxs("div", { className: "flex items-center space-x-2", children: [jsx("div", { className: "flex justify-center items-center w-8 h-8 rounded-lg bg-secondary-100", children: jsx(Stethoscope, { className: "w-4 h-4 text-secondary-600" }) }), jsx("h3", { className: "text-lg font-semibold text-gray-900", children: title || "Medical Specialties" })] }), jsx("div", { children: jsx("label", { className: "block mb-2 text-sm font-medium text-gray-700", children: label || "Select Specialties" }) }), jsx(MultiSearchAutocomplete, { items: filteredSpecialties, selectedItems: selectedSpecialties, onSelectionChange: handleSelectionChange, onSearch: fetchSpecialties, getEntityById: getEntityById, getPrimaryText: (specialty) => specialty.label, getSecondaryText: (specialty) => specialty.code, placeholder: placeholder, disabled: disabled, loading: isLoading, multiple: true, keepOpenOnSelect: true, className: "w-full", renderSelectedItem: (specialty) => (jsx("span", { className: "inline-flex items-center px-3 py-1 text-sm font-medium rounded-full border bg-ews-primary/10 text-ews-primary border-ews-primary/20", children: specialty.label })), renderListItem: (specialty, isSelected) => (jsxs("div", { className: "flex items-center space-x-3", children: [jsx("div", { className: cn("flex justify-center items-center w-5 h-5 rounded border-2", isSelected
35282
+ return (jsxs("div", { className: cn("space-y-3", className), children: [jsxs("div", { className: "flex items-center space-x-2", children: [jsx("div", { className: "flex justify-center items-center w-8 h-8 rounded-lg bg-secondary-100", children: jsx(Stethoscope, { className: "w-4 h-4 text-secondary-600" }) }), jsx("h3", { className: "text-lg font-semibold text-gray-900", children: title || "Medical Specialties" })] }), jsx("div", { children: jsx("label", { className: "block mb-2 text-sm font-medium text-gray-700", children: label || "Select Specialties" }) }), jsx(MultiSearchAutocomplete, { items: filteredSpecialties, selectedItems: selectedSpecialties, onSelectionChange: handleSelectionChange, onSearch: fetchSpecialties, getEntityById: getEntityById, getPrimaryText: (specialty) => specialty.label, getSecondaryText: (specialty) => specialty.code, placeholder: placeholder, disabled: disabled, loading: isLoading, multiple: true, keepOpenOnSelect: true, className: "w-full", renderSelectedItem: (specialty) => (jsxs("span", { className: "inline-flex items-center px-3 py-1 text-sm font-medium rounded-full border bg-ews-primary/10 text-ews-primary border-ews-primary/20", children: [specialty.label, jsx("button", { type: "button", onClick: () => handleRemoveSpecialty(specialty), className: "ml-2 text-ews-primary/60 hover:text-ews-primary", disabled: disabled, title: removeSpecialtyLabel, "aria-label": removeSpecialtyLabel, children: jsx(X, { className: "w-3 h-3" }) })] })), renderListItem: (specialty, isSelected) => (jsxs("div", { className: "flex items-center space-x-3", children: [jsx("div", { className: cn("flex justify-center items-center w-5 h-5 rounded border-2", isSelected
35274
35283
  ? "bg-ews-primary border-ews-primary"
35275
35284
  : "border-ews-gray-300"), children: isSelected && (jsx("svg", { className: "w-3 h-3 text-white", fill: "currentColor", viewBox: "0 0 20 20", children: jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) })) }), jsx("span", { className: cn("font-medium", isSelected ? "text-ews-primary" : "text-gray-900"), children: specialty.label })] })) }), showSelectedCount && selectedSpecialties.length > 0 && (jsxs("div", { className: "flex justify-between items-center text-sm text-gray-600", children: [jsx("span", { children: getSelectedCountText
35276
35285
  ? getSelectedCountText(selectedSpecialties.length)