@ews-admin/global-design-system 1.1.10 → 1.1.12
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/Input/Input.d.ts.map +1 -1
- package/dist/components/MultiSearchAutocomplete/MultiSearchAutocomplete.d.ts.map +1 -1
- package/dist/index.css +2 -2
- package/dist/index.d.ts +14 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.css +2 -2
- package/dist/index.esm.js +50 -9
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +51 -8
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Input/Input.tsx +56 -0
- package/src/components/MultiSearchAutocomplete/MultiSearchAutocomplete.tsx +13 -11
- package/src/components/Select/Select.tsx +1 -1
- package/src/index.ts +9 -1
- package/src/molecules/SpecialtySearchAutocomplete/SpecialtySearchAutocomplete.tsx +1 -1
- package/src/styles/index.css +32 -0
- package/src/utils/index.ts +21 -0
package/dist/index.js
CHANGED
|
@@ -65,6 +65,25 @@ function debounce(func, wait) {
|
|
|
65
65
|
function generateId(prefix = "ews") {
|
|
66
66
|
return `${prefix}-${Math.random().toString(36).substr(2, 9)}`;
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Utility function to format numeric input by removing non-digit characters
|
|
70
|
+
* @param value - String value to format
|
|
71
|
+
* @returns String with only numeric characters
|
|
72
|
+
*/
|
|
73
|
+
const formatNumeric = (value) => {
|
|
74
|
+
return value.replace(/\D/g, "");
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Utility function to validate phone numbers
|
|
78
|
+
* Validates phone numbers with 1-15 digits, starting with a non-zero digit
|
|
79
|
+
* @param value - Phone number string to validate
|
|
80
|
+
* @returns Boolean indicating if the phone number is valid
|
|
81
|
+
*/
|
|
82
|
+
function isValidPhoneNumber(value) {
|
|
83
|
+
const trimmedValue = value.trim();
|
|
84
|
+
const phoneRegex = /^[0-9]\d{1,14}$/;
|
|
85
|
+
return phoneRegex.test(trimmedValue);
|
|
86
|
+
}
|
|
68
87
|
|
|
69
88
|
const Button = React.forwardRef(({ className, variant = "primary", size = "md", loading = false, fullWidth = false, leftIcon, rightIcon, children, disabled, ...props }, ref) => {
|
|
70
89
|
const baseStyles = "inline-flex items-center justify-center font-medium rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none";
|
|
@@ -460,6 +479,20 @@ const Input = React.forwardRef(({ className, variant = "default", size = "md", l
|
|
|
460
479
|
md: "h-5 w-5",
|
|
461
480
|
lg: "h-6 w-6",
|
|
462
481
|
};
|
|
482
|
+
const isCheckbox = type === "checkbox";
|
|
483
|
+
// For checkboxes, render with or without label based on label prop
|
|
484
|
+
if (isCheckbox) {
|
|
485
|
+
if (label) {
|
|
486
|
+
// Render checkbox with built-in label
|
|
487
|
+
return (jsxRuntime.jsx("div", { className: cn("space-y-1", fullWidth ? "w-full" : "w-auto"), children: jsxRuntime.jsxs("div", { className: "flex items-start space-x-3", children: [jsxRuntime.jsx("input", { id: inputId, type: actualType, className: cn("mt-0.5", // Slight top margin to align with first line of text
|
|
488
|
+
className), ref: ref, ...props }), jsxRuntime.jsxs("div", { className: "flex-1", children: [jsxRuntime.jsxs("label", { htmlFor: inputId, className: "block text-sm font-medium cursor-pointer text-ews-gray-700", children: [label, required && jsxRuntime.jsx("span", { className: "ml-1 text-ews-error", children: "*" })] }), (error || helperText) && (jsxRuntime.jsx("p", { className: cn("mt-1 text-sm", error ? "text-ews-error" : "text-ews-gray-500"), children: error || helperText }))] })] }) }));
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
// Render just the checkbox for external label usage
|
|
492
|
+
return (jsxRuntime.jsx("input", { id: inputId, type: actualType, className: cn(className), ref: ref, ...props }));
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
// Default rendering for non-checkbox inputs
|
|
463
496
|
return (jsxRuntime.jsxs("div", { className: cn("space-y-1", fullWidth ? "w-full" : "w-auto"), children: [label && (jsxRuntime.jsxs("label", { htmlFor: inputId, className: "block text-sm font-medium text-ews-gray-700", children: [label, required && jsxRuntime.jsx("span", { className: "ml-1 text-ews-error", children: "*" })] })), jsxRuntime.jsxs("div", { className: "relative", children: [leftIcon && (jsxRuntime.jsx("div", { className: "flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none", children: jsxRuntime.jsx("span", { className: cn("text-ews-gray-400", iconSizes[size]), children: leftIcon }) })), jsxRuntime.jsx("input", { id: inputId, type: actualType, className: cn(baseStyles, variants[actualVariant], sizes[size], leftIcon && "pl-10", (rightIcon || shouldShowPasswordToggle) && "pr-10", className), ref: ref, ...props }), rightIcon && !shouldShowPasswordToggle && (jsxRuntime.jsx("div", { className: "flex absolute inset-y-0 right-0 items-center pr-3 pointer-events-none", children: jsxRuntime.jsx("span", { className: cn("text-ews-gray-400", iconSizes[size]), children: rightIcon }) })), shouldShowPasswordToggle && (jsxRuntime.jsx("button", { type: "button", className: "flex absolute inset-y-0 right-0 items-center pr-3", onClick: () => setShowPassword(!showPassword), tabIndex: -1, children: jsxRuntime.jsx("span", { className: cn("transition-colors text-ews-gray-400 hover:text-ews-gray-600", iconSizes[size]), children: showPassword ? jsxRuntime.jsx(EyeOff, { size: 16 }) : jsxRuntime.jsx(Eye, { size: 16 }) }) }))] }), (error || helperText) && (jsxRuntime.jsx("p", { className: cn("text-sm", error ? "text-ews-error" : "text-ews-gray-500"), children: error || helperText }))] }));
|
|
464
497
|
});
|
|
465
498
|
Input.displayName = "Input";
|
|
@@ -667,7 +700,7 @@ const Select = React.forwardRef(({ options = [], value, onChange, placeholder =
|
|
|
667
700
|
md: "w-4 h-4",
|
|
668
701
|
lg: "w-5 h-5",
|
|
669
702
|
};
|
|
670
|
-
return (jsxRuntime.jsxs("div", { className: cn("w-full", containerClassName), ref: containerRef, children: [label && (jsxRuntime.jsxs("label", { htmlFor: selectId, className: cn("block text-sm font-medium mb-1",
|
|
703
|
+
return (jsxRuntime.jsxs("div", { className: cn("w-full", containerClassName), ref: containerRef, children: [label && (jsxRuntime.jsxs("label", { htmlFor: selectId, className: cn("block text-sm font-medium mb-1", "text-ews-gray-700", disabled && "text-ews-gray-400"), children: [label, required && jsxRuntime.jsx("span", { className: "ml-1 text-ews-error", children: "*" })] })), jsxRuntime.jsxs("div", { className: "relative", children: [jsxRuntime.jsx("div", { ref: ref, role: "combobox", "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-labelledby": label ? selectId : undefined, tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown, onClick: handleToggle, className: cn(
|
|
671
704
|
// Base styles
|
|
672
705
|
"ews-select-trigger w-full bg-white border rounded-md shadow-sm transition-colors cursor-pointer", "focus:outline-none focus:ring-2 focus:ring-offset-0", "disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-ews-gray-50",
|
|
673
706
|
// Size
|
|
@@ -1111,6 +1144,7 @@ function useController(props) {
|
|
|
1111
1144
|
exact: true,
|
|
1112
1145
|
});
|
|
1113
1146
|
const _props = React.useRef(props);
|
|
1147
|
+
const _previousNameRef = React.useRef(undefined);
|
|
1114
1148
|
const _registerProps = React.useRef(control.register(name, {
|
|
1115
1149
|
...props.rules,
|
|
1116
1150
|
value,
|
|
@@ -1176,6 +1210,10 @@ function useController(props) {
|
|
|
1176
1210
|
}), [name, disabled, formState.disabled, onChange, onBlur, ref, value]);
|
|
1177
1211
|
React.useEffect(() => {
|
|
1178
1212
|
const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
|
|
1213
|
+
const previousName = _previousNameRef.current;
|
|
1214
|
+
if (previousName && previousName !== name && !isArrayField) {
|
|
1215
|
+
control.unregister(previousName);
|
|
1216
|
+
}
|
|
1179
1217
|
control.register(name, {
|
|
1180
1218
|
..._props.current.rules,
|
|
1181
1219
|
...(isBoolean(_props.current.disabled)
|
|
@@ -1197,6 +1235,7 @@ function useController(props) {
|
|
|
1197
1235
|
}
|
|
1198
1236
|
}
|
|
1199
1237
|
!isArrayField && control.register(name);
|
|
1238
|
+
_previousNameRef.current = name;
|
|
1200
1239
|
return () => {
|
|
1201
1240
|
(isArrayField
|
|
1202
1241
|
? _shouldUnregisterField && !control._state.action
|
|
@@ -1475,17 +1514,19 @@ function MultiSearchAutocomplete({ items, selectedItems, onSelectionChange, onSe
|
|
|
1475
1514
|
};
|
|
1476
1515
|
}, [isOpen]);
|
|
1477
1516
|
// Default render functions
|
|
1478
|
-
const defaultRenderSelectedItem = (entity) => (jsxRuntime.jsxs("span", { className: "inline-flex items-center px-3 py-1 text-sm font-medium rounded-full bg-ews-primary/10 text-ews-primary border
|
|
1479
|
-
const defaultRenderListItem = (entity, isSelected) => (jsxRuntime.jsxs("div", { className: "flex items-center space-x-3", children: [jsxRuntime.jsx("div", { className: cn("
|
|
1517
|
+
const defaultRenderSelectedItem = (entity) => (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: [getPrimaryText(entity), jsxRuntime.jsx("button", { type: "button", onClick: () => handleRemoveItem(entity), className: "ml-2 text-ews-primary/60 hover:text-ews-primary", disabled: disabled, title: "Remove item", children: jsxRuntime.jsx(X, { className: "w-3 h-3" }) })] }));
|
|
1518
|
+
const defaultRenderListItem = (entity, 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
|
|
1519
|
+
? "bg-ews-primary border-ews-primary"
|
|
1520
|
+
: "border-ews-gray-300"), children: isSelected && jsxRuntime.jsx(Check, { className: "w-3 h-3 text-white" }) }), jsxRuntime.jsxs("div", { className: "flex flex-col", children: [jsxRuntime.jsx("span", { className: cn("font-medium", isSelected ? "text-ews-primary" : "text-gray-900"), children: getPrimaryText(entity) }), getSecondaryText && (jsxRuntime.jsx("span", { className: cn("text-sm", isSelected ? "text-ews-primary/70" : "text-gray-500"), children: getSecondaryText(entity) }))] })] }));
|
|
1480
1521
|
return (jsxRuntime.jsxs("div", { className: cn("relative", className), ref: dropdownRef, children: [selectedItems.length > 0 && (jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2 mb-3", children: selectedItems.map((item) => (jsxRuntime.jsx("div", { children: renderSelectedItem
|
|
1481
1522
|
? renderSelectedItem(item)
|
|
1482
|
-
: defaultRenderSelectedItem(item) }, item.id))) })), jsxRuntime.jsx(Input, { ref: inputRef, type: "text", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: placeholder, disabled: disabled, leftIcon: jsxRuntime.jsx(Search, { className: "w-4 h-4" }), className: "w-full" }), isOpen && !disabled && (jsxRuntime.jsx("div", { className: "absolute z-10 mt-1 w-full max-h-60 bg-white rounded-lg border border-gray-200 shadow-lg
|
|
1523
|
+
: defaultRenderSelectedItem(item) }, item.id))) })), jsxRuntime.jsx(Input, { ref: inputRef, type: "text", value: searchTerm, onChange: (e) => setSearchTerm(e.target.value), onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: placeholder, disabled: disabled, leftIcon: jsxRuntime.jsx(Search, { className: "w-4 h-4" }), className: "w-full" }), isOpen && !disabled && (jsxRuntime.jsx("div", { className: "overflow-auto absolute z-10 mt-1 w-full max-h-60 bg-white rounded-lg border border-gray-200 shadow-lg", children: loading || isSearching ? (jsxRuntime.jsxs("div", { className: "flex items-center px-4 py-3 text-sm text-gray-500", children: [jsxRuntime.jsx("div", { className: "mr-2 w-4 h-4 rounded-full border-b-2 animate-spin border-ews-primary" }), isSearching ? "Searching..." : "Loading..."] })) : searchError ? (jsxRuntime.jsx("div", { className: "px-4 py-3 text-sm text-red-600", children: jsxRuntime.jsxs("div", { className: "flex items-center", children: [jsxRuntime.jsx(X, { className: "mr-2 w-4 h-4" }), "Error: ", searchError] }) })) : error ? (jsxRuntime.jsx("div", { className: "px-4 py-3 text-sm text-red-600", children: jsxRuntime.jsxs("div", { className: "flex items-center", children: [jsxRuntime.jsx(X, { className: "mr-2 w-4 h-4" }), error] }) })) : filteredItems.length === 0 ? (jsxRuntime.jsx("div", { className: "px-4 py-3 text-sm text-gray-500", children: searchTerm.length < minSearchLength
|
|
1483
1524
|
? `Type at least ${minSearchLength} characters to search`
|
|
1484
1525
|
: "No items found" })) : (jsxRuntime.jsx("div", { className: "py-1", children: filteredItems.map((item) => {
|
|
1485
1526
|
const isSelected = selectedItems.some((selected) => selected.id === item.id);
|
|
1486
|
-
return (jsxRuntime.jsx("button", { type: "button", onClick: () => handleItemToggle(item), className: cn("
|
|
1487
|
-
? "bg-ews-primary/10 text-ews-primary border-
|
|
1488
|
-
: "hover:bg-ews-primary/5
|
|
1527
|
+
return (jsxRuntime.jsx("button", { type: "button", onClick: () => handleItemToggle(item), className: cn("flex items-center px-4 py-3 w-full text-left transition-colors", isSelected
|
|
1528
|
+
? "border-l-4 bg-ews-primary/10 text-ews-primary border-ews-primary"
|
|
1529
|
+
: "text-gray-900 hover:bg-ews-primary/5"), children: renderListItem
|
|
1489
1530
|
? renderListItem(item, isSelected)
|
|
1490
1531
|
: defaultRenderListItem(item, isSelected) }, item.id));
|
|
1491
1532
|
}) })) }))] }));
|
|
@@ -1744,7 +1785,7 @@ const SpecialtySearchAutocomplete = ({ selectedSpecialties = [], onSpecialtiesCh
|
|
|
1744
1785
|
}, [specialties]);
|
|
1745
1786
|
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: "Medical Specialties" })] }), jsxRuntime.jsx("div", { children: jsxRuntime.jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Select Specialties" }) }), jsxRuntime.jsx(MultiSearchAutocomplete, { items: specialties, 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.jsx("span", { className: "inline-flex items-center px-3 py-1 text-sm font-medium rounded-full bg-ews-primary/10 text-ews-primary border border-ews-primary/20", children: specialty.label })), renderListItem: (specialty, isSelected) => (jsxRuntime.jsxs("div", { className: "flex items-center space-x-3", children: [jsxRuntime.jsx("div", { className: cn("w-5 h-5 border-2 rounded flex items-center justify-center", isSelected
|
|
1746
1787
|
? "bg-ews-primary border-ews-primary"
|
|
1747
|
-
: "border-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.jsxs("div", { className: "flex flex-col", children: [jsxRuntime.jsx("span", { className: cn("font-medium", isSelected ? "text-ews-primary" : "text-gray-900"), children: specialty.label }), jsxRuntime.jsx("span", { className: cn("text-sm", isSelected ? "text-ews-primary/70" : "text-gray-500"), children: specialty.code })] })] })) }), showSelectedCount && selectedSpecialties.length > 0 && (jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm text-gray-600", children: [jsxRuntime.jsxs("span", { children: [selectedSpecialties.length, " specialty", selectedSpecialties.length !== 1 ? "ies" : "", " selected"] }), maxSelections && (jsxRuntime.jsxs("span", { className: "text-gray-400", children: [selectedSpecialties.length, "/", maxSelections] }))] }))] }));
|
|
1788
|
+
: "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.jsxs("div", { className: "flex flex-col", children: [jsxRuntime.jsx("span", { className: cn("font-medium", isSelected ? "text-ews-primary" : "text-gray-900"), children: specialty.label }), jsxRuntime.jsx("span", { className: cn("text-sm", isSelected ? "text-ews-primary/70" : "text-gray-500"), children: specialty.code })] })] })) }), showSelectedCount && selectedSpecialties.length > 0 && (jsxRuntime.jsxs("div", { className: "flex items-center justify-between text-sm text-gray-600", children: [jsxRuntime.jsxs("span", { children: [selectedSpecialties.length, " specialty", selectedSpecialties.length !== 1 ? "ies" : "", " selected"] }), maxSelections && (jsxRuntime.jsxs("span", { className: "text-gray-400", children: [selectedSpecialties.length, "/", maxSelections] }))] }))] }));
|
|
1748
1789
|
};
|
|
1749
1790
|
|
|
1750
1791
|
exports.ArrowRight = ArrowRight;
|
|
@@ -1769,7 +1810,9 @@ exports.cn = cn;
|
|
|
1769
1810
|
exports.debounce = debounce;
|
|
1770
1811
|
exports.formatCurrency = formatCurrency;
|
|
1771
1812
|
exports.formatDate = formatDate;
|
|
1813
|
+
exports.formatNumeric = formatNumeric;
|
|
1772
1814
|
exports.generateId = generateId;
|
|
1815
|
+
exports.isValidPhoneNumber = isValidPhoneNumber;
|
|
1773
1816
|
exports.useDebounce = useDebounce;
|
|
1774
1817
|
exports.useDebouncedCallback = useDebouncedCallback;
|
|
1775
1818
|
exports.useSelectField = useSelectField;
|