@ews-admin/global-design-system 1.26.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.
- package/dist/components/SearchAutocomplete/SearchAutocomplete.d.ts +8 -1
- package/dist/components/SearchAutocomplete/SearchAutocomplete.d.ts.map +1 -1
- package/dist/components/SecureLoader/SecureLoader.d.ts +18 -0
- package/dist/components/SecureLoader/SecureLoader.d.ts.map +1 -0
- package/dist/components/SecureLoader/index.d.ts +3 -0
- package/dist/components/SecureLoader/index.d.ts.map +1 -0
- package/dist/components/Select/Select.d.ts +15 -0
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +47 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +22 -7
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +22 -6
- package/dist/index.js.map +1 -1
- package/dist/molecules/SpecialtySearchAutocomplete/SpecialtySearchAutocomplete.d.ts +6 -0
- package/dist/molecules/SpecialtySearchAutocomplete/SpecialtySearchAutocomplete.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/components/SearchAutocomplete/SearchAutocomplete.tsx +14 -1
- package/src/components/SecureLoader/SecureLoader.tsx +37 -0
- package/src/components/SecureLoader/index.ts +2 -0
- package/src/components/Select/Select.tsx +20 -2
- package/src/index.ts +3 -0
- package/src/molecules/SpecialtySearchAutocomplete/SpecialtySearchAutocomplete.tsx +31 -1
package/dist/index.js
CHANGED
|
@@ -32786,7 +32786,7 @@ const Input = React.forwardRef(({ className, variant = "default", size = "md", l
|
|
|
32786
32786
|
});
|
|
32787
32787
|
Input.displayName = "Input";
|
|
32788
32788
|
|
|
32789
|
-
const Select = React.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) => {
|
|
32789
|
+
const Select = React.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) => {
|
|
32790
32790
|
const generatedId = React.useId();
|
|
32791
32791
|
const selectId = `select-${generatedId}`;
|
|
32792
32792
|
const hasError = isError || !!error;
|
|
@@ -32995,7 +32995,7 @@ const Select = React.forwardRef(({ options = [], value, onChange, placeholder =
|
|
|
32995
32995
|
// Padding for icons
|
|
32996
32996
|
"pr-10", selectClassName), ...props, children: jsxRuntime.jsx("div", { className: "flex justify-between items-center", children: renderTrigger ? (renderTrigger()) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: selectedOption ? (renderValue ? (renderValue(selectedOption)) : (jsxRuntime.jsx("span", { className: "truncate", children: selectedOption.label }))) : (jsxRuntime.jsx("span", { className: "text-ews-gray-500", children: placeholder })) }), jsxRuntime.jsxs("div", { className: "flex items-center ml-2 space-x-1", children: [clearable && selectedOption && !disabled && (jsxRuntime.jsx("button", { type: "button", onClick: handleClear, className: "p-1 rounded hover:bg-ews-gray-100", children: jsxRuntime.jsx(X, { className: cn(iconSizeClasses[size], "text-ews-gray-400") }) })), jsxRuntime.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 && (jsxRuntime.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"
|
|
32997
32997
|
? "bottom-full mb-1"
|
|
32998
|
-
: "top-full mt-1", dropdownClassName), style: { maxHeight: `${maxHeight}px` }, children: [searchable && (jsxRuntime.jsx("div", { className: "p-2 border-b border-ews-gray-200", children: jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsx(Search, { className: "absolute left-3 top-1/2 w-4 h-4 transform -translate-y-1/2 text-ews-gray-400" }), jsxRuntime.jsx(Input, { ref: inputRef, type: "text", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), placeholder:
|
|
32998
|
+
: "top-full mt-1", dropdownClassName), style: { maxHeight: `${maxHeight}px` }, children: [searchable && (jsxRuntime.jsx("div", { className: "p-2 border-b border-ews-gray-200", children: jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsx(Search, { className: "absolute left-3 top-1/2 w-4 h-4 transform -translate-y-1/2 text-ews-gray-400" }), jsxRuntime.jsx(Input, { ref: inputRef, type: "text", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), placeholder: searchPlaceholder, leftIcon: jsxRuntime.jsx(Search, { className: "w-4 h-4 text-ews-gray-400" }) })] }) })), jsxRuntime.jsx("div", { className: "overflow-auto py-1", style: { maxHeight: `${maxHeight - (searchable ? 60 : 0)}px` }, children: filteredOptions.length === 0 ? (jsxRuntime.jsx("div", { className: "px-3 py-2 text-sm text-ews-gray-500", children: searchTerm ? noOptionsFoundText : noOptionsAvailableText })) : (filteredOptions.map((option, index) => {
|
|
32999
32999
|
const isSelected = option.value === value;
|
|
33000
33000
|
const isFocused = index === focusedIndex;
|
|
33001
33001
|
return (jsxRuntime.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)) : (jsxRuntime.jsx("span", { className: "truncate", children: option.label })) }, `${String(option.value)}-${index}`));
|
|
@@ -33072,7 +33072,7 @@ function useSelectField({ name, control, options: _options, rules, defaultValue,
|
|
|
33072
33072
|
};
|
|
33073
33073
|
}
|
|
33074
33074
|
|
|
33075
|
-
function SearchAutocomplete({ onSelect, selectedId, searchFunction, getEntityById, getDisplayValue, getSecondaryText, placeholder, icon = Search, disabled = false, minSearchLength = 2, debounceTime = 300, error, }) {
|
|
33075
|
+
function SearchAutocomplete({ onSelect, selectedId, searchFunction, getEntityById, getDisplayValue, getSecondaryText, placeholder, icon = Search, disabled = false, minSearchLength = 2, debounceTime = 300, error, getMinCharactersHint = (min) => `(min. ${min} characters)`, }) {
|
|
33076
33076
|
const [searchTerm, setSearchTerm] = React.useState("");
|
|
33077
33077
|
const [entities, setEntities] = React.useState([]);
|
|
33078
33078
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
@@ -33185,7 +33185,11 @@ function SearchAutocomplete({ onSelect, selectedId, searchFunction, getEntityByI
|
|
|
33185
33185
|
setSearchTerm("");
|
|
33186
33186
|
onSelect("");
|
|
33187
33187
|
};
|
|
33188
|
-
|
|
33188
|
+
const minCharactersHint = getMinCharactersHint(minSearchLength);
|
|
33189
|
+
const inputPlaceholder = minCharactersHint
|
|
33190
|
+
? `${placeholder} ${minCharactersHint}`
|
|
33191
|
+
: placeholder;
|
|
33192
|
+
return (jsxRuntime.jsxs("div", { className: "relative", ref: dropdownRef, children: [jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsx(Input, { type: "text", placeholder: inputPlaceholder, value: selectedEntity ? "" : searchTerm, onChange: handleSearchChange, onFocus: () => searchTerm.length >= minSearchLength &&
|
|
33189
33193
|
isUserSearch.current &&
|
|
33190
33194
|
setShowDropdown(true), disabled: disabled, autoComplete: "off", name: "search-autocomplete", leftIcon: React.createElement(icon, { size: 16 }) }), selectedEntity && (jsxRuntime.jsx("button", { type: "button", className: "flex absolute inset-y-0 right-0 items-center pr-3", onClick: handleClearSelection, disabled: disabled, children: jsxRuntime.jsx(X, { className: "w-5 h-5 text-gray-400 hover:text-gray-500" }) }))] }), selectedEntity && (jsxRuntime.jsx("div", { className: "p-4 mt-3 rounded-lg border bg-neutral-50 border-neutral-200", children: jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [jsxRuntime.jsxs("div", { className: "flex items-center", children: [selectedEntity.photoUrl ? (jsxRuntime.jsx("img", { src: selectedEntity.photoUrl, alt: getDisplayValue(selectedEntity), className: "object-cover mr-3 w-10 h-10 rounded-full" })) : (React.createElement(icon, {
|
|
33191
33195
|
className: "w-10 h-10 text-neutral-400 mr-3",
|
|
@@ -35250,7 +35254,13 @@ const TagList = ({ items, maxVisible = DEFAULT_MAX, showMoreLabel, showLessLabel
|
|
|
35250
35254
|
*/
|
|
35251
35255
|
const PaymentDueBanner = ({ title, subtitle, warning, ctaLabel, onCtaClick, onDismiss, dismissLabel = "Close", }) => (jsxRuntime.jsx("div", { "data-testid": "payment-banner", className: "overflow-hidden bg-gradient-to-r from-red-600 to-red-700 shadow-lg", children: jsxRuntime.jsx("div", { className: "px-6 py-8 sm:px-8", children: jsxRuntime.jsxs("div", { className: "flex flex-col space-y-6 sm:flex-row sm:items-center sm:justify-between sm:space-y-0", children: [jsxRuntime.jsxs("div", { className: "flex items-center space-x-4", children: [jsxRuntime.jsx(TriangleAlert, { className: "w-8 h-8 text-white shrink-0" }), jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntime.jsx("h3", { className: "text-2xl font-bold text-white", children: title }), subtitle && (jsxRuntime.jsx("p", { className: "mt-2 text-base text-red-100", children: subtitle })), warning && (jsxRuntime.jsx("p", { className: "mt-1 text-sm font-medium text-red-200", children: warning }))] })] }), jsxRuntime.jsxs("div", { className: "flex flex-col flex-shrink-0 gap-3 sm:flex-row sm:gap-4 sm:items-center", children: [jsxRuntime.jsx("button", { onClick: onCtaClick, className: "w-full px-8 py-3 text-base font-semibold text-red-600 bg-white rounded-lg shadow-sm transition-all duration-200 sm:w-auto hover:bg-red-50 hover:shadow-md", children: ctaLabel }), onDismiss && (jsxRuntime.jsx("button", { onClick: onDismiss, className: "self-start p-2 rounded-full transition-colors bg-white/10 hover:bg-white/20 sm:self-auto", "aria-label": dismissLabel, children: jsxRuntime.jsx(X, { className: "w-5 h-5 text-white" }) }))] })] }) }) }));
|
|
35252
35256
|
|
|
35253
|
-
|
|
35257
|
+
/**
|
|
35258
|
+
* Full-screen loader (lock icon with a spinner) shown while the user's
|
|
35259
|
+
* session is being checked.
|
|
35260
|
+
*/
|
|
35261
|
+
const SecureLoader = ({ label, description }) => (jsxRuntime.jsx("div", { "data-testid": "secure-loader", className: "flex min-h-screen items-center justify-center bg-gray-100", children: jsxRuntime.jsxs("div", { className: "flex flex-col items-center rounded-lg bg-white p-6 shadow-lg", children: [jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsx(Lock, { className: "h-16 w-16 text-gray-500" }), jsxRuntime.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" })] }), jsxRuntime.jsx("p", { className: "mt-4 text-lg text-gray-600", children: label }), description && (jsxRuntime.jsx("p", { className: "mt-2 text-sm text-gray-500", children: description }))] }) }));
|
|
35262
|
+
|
|
35263
|
+
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", }) => {
|
|
35254
35264
|
const [filteredSpecialties, setFilteredSpecialties] = React.useState([]);
|
|
35255
35265
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
35256
35266
|
// Filter specialties based on search term
|
|
@@ -35281,10 +35291,15 @@ const SpecialtySearchAutocomplete = ({ selectedSpecialties = [], onSpecialtiesCh
|
|
|
35281
35291
|
}
|
|
35282
35292
|
onSpecialtiesChange(items);
|
|
35283
35293
|
}, [onSpecialtiesChange, maxSelections]);
|
|
35294
|
+
// MED-1499: a selected specialty must be removable from its chip, not only
|
|
35295
|
+
// by toggling it off again in the dropdown list.
|
|
35296
|
+
const handleRemoveSpecialty = React.useCallback((specialtyToRemove) => {
|
|
35297
|
+
onSpecialtiesChange(selectedSpecialties.filter((specialty) => specialty.id !== specialtyToRemove.id));
|
|
35298
|
+
}, [onSpecialtiesChange, selectedSpecialties]);
|
|
35284
35299
|
const getEntityById = React.useCallback(async (id) => {
|
|
35285
35300
|
return availableSpecialties.find((specialty) => specialty.id === id);
|
|
35286
35301
|
}, [availableSpecialties]);
|
|
35287
|
-
return (jsxRuntime.jsxs("div", { className: cn("space-y-3", className), children: [jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [jsxRuntime.jsx("div", { className: "flex justify-center items-center w-8 h-8 rounded-lg bg-secondary-100", children: jsxRuntime.jsx(Stethoscope, { className: "w-4 h-4 text-secondary-600" }) }), jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900", children: title || "Medical Specialties" })] }), jsxRuntime.jsx("div", { children: jsxRuntime.jsx("label", { className: "block mb-2 text-sm font-medium text-gray-700", children: label || "Select Specialties" }) }), jsxRuntime.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) => (jsxRuntime.
|
|
35302
|
+
return (jsxRuntime.jsxs("div", { className: cn("space-y-3", className), children: [jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [jsxRuntime.jsx("div", { className: "flex justify-center items-center w-8 h-8 rounded-lg bg-secondary-100", children: jsxRuntime.jsx(Stethoscope, { className: "w-4 h-4 text-secondary-600" }) }), jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900", children: title || "Medical Specialties" })] }), jsxRuntime.jsx("div", { children: jsxRuntime.jsx("label", { className: "block mb-2 text-sm font-medium text-gray-700", children: label || "Select Specialties" }) }), jsxRuntime.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) => (jsxRuntime.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, jsxRuntime.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: jsxRuntime.jsx(X, { className: "w-3 h-3" }) })] })), renderListItem: (specialty, isSelected) => (jsxRuntime.jsxs("div", { className: "flex items-center space-x-3", children: [jsxRuntime.jsx("div", { className: cn("flex justify-center items-center w-5 h-5 rounded border-2", isSelected
|
|
35288
35303
|
? "bg-ews-primary border-ews-primary"
|
|
35289
35304
|
: "border-ews-gray-300"), children: isSelected && (jsxRuntime.jsx("svg", { className: "w-3 h-3 text-white", fill: "currentColor", viewBox: "0 0 20 20", children: jsxRuntime.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" }) })) }), jsxRuntime.jsx("span", { className: cn("font-medium", isSelected ? "text-ews-primary" : "text-gray-900"), children: specialty.label })] })) }), showSelectedCount && selectedSpecialties.length > 0 && (jsxRuntime.jsxs("div", { className: "flex justify-between items-center text-sm text-gray-600", children: [jsxRuntime.jsx("span", { children: getSelectedCountText
|
|
35290
35305
|
? getSelectedCountText(selectedSpecialties.length)
|
|
@@ -40035,6 +40050,7 @@ exports.SearchX = SearchX;
|
|
|
40035
40050
|
exports.SearchXIcon = SearchX;
|
|
40036
40051
|
exports.Section = Section;
|
|
40037
40052
|
exports.SectionIcon = Section;
|
|
40053
|
+
exports.SecureLoader = SecureLoader;
|
|
40038
40054
|
exports.Select = Select;
|
|
40039
40055
|
exports.Send = Send;
|
|
40040
40056
|
exports.SendHorizonal = SendHorizontal;
|