@ews-admin/global-design-system 1.13.0 → 1.17.1

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 (43) hide show
  1. package/dist/components/ProfileImageUpload/ProfileImageUpload.d.ts +18 -5
  2. package/dist/components/ProfileImageUpload/ProfileImageUpload.d.ts.map +1 -1
  3. package/dist/components/ProfileImageUpload/index.d.ts +1 -1
  4. package/dist/components/ProfileImageUpload/index.d.ts.map +1 -1
  5. package/dist/components/RegionSelect/RegionSelect.d.ts +15 -0
  6. package/dist/components/RegionSelect/RegionSelect.d.ts.map +1 -0
  7. package/dist/components/RegionSelect/index.d.ts +3 -0
  8. package/dist/components/RegionSelect/index.d.ts.map +1 -0
  9. package/dist/components/Select/Select.d.ts +7 -0
  10. package/dist/components/Select/Select.d.ts.map +1 -1
  11. package/dist/components/Tag/Tag.d.ts +8 -0
  12. package/dist/components/Tag/Tag.d.ts.map +1 -0
  13. package/dist/components/Tag/index.d.ts +3 -0
  14. package/dist/components/Tag/index.d.ts.map +1 -0
  15. package/dist/components/TagList/TagList.d.ts +14 -0
  16. package/dist/components/TagList/TagList.d.ts.map +1 -0
  17. package/dist/components/TagList/index.d.ts +3 -0
  18. package/dist/components/TagList/index.d.ts.map +1 -0
  19. package/dist/index.css +1 -1
  20. package/dist/index.d.ts +77 -7
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.esm.css +1 -1
  23. package/dist/index.esm.js +92 -24
  24. package/dist/index.esm.js.map +1 -1
  25. package/dist/index.js +97 -25
  26. package/dist/index.js.map +1 -1
  27. package/dist/utils/index.d.ts +2 -0
  28. package/dist/utils/index.d.ts.map +1 -1
  29. package/dist/utils/locations.d.ts +17 -0
  30. package/dist/utils/locations.d.ts.map +1 -0
  31. package/package.json +1 -1
  32. package/src/components/ProfileImageUpload/ProfileImageUpload.tsx +36 -9
  33. package/src/components/ProfileImageUpload/index.ts +4 -1
  34. package/src/components/RegionSelect/RegionSelect.tsx +48 -0
  35. package/src/components/RegionSelect/index.ts +2 -0
  36. package/src/components/Select/Select.tsx +48 -50
  37. package/src/components/Tag/Tag.tsx +33 -0
  38. package/src/components/Tag/index.ts +2 -0
  39. package/src/components/TagList/TagList.tsx +60 -0
  40. package/src/components/TagList/index.ts +2 -0
  41. package/src/index.ts +16 -1
  42. package/src/utils/index.ts +6 -0
  43. package/src/utils/locations.ts +51 -0
package/dist/index.js CHANGED
@@ -61,6 +61,56 @@ function createEnvConfig(env, overrides) {
61
61
  };
62
62
  }
63
63
 
64
+ exports.SupportedCountry = void 0;
65
+ (function (SupportedCountry) {
66
+ SupportedCountry["SENEGAL"] = "SENEGAL";
67
+ SupportedCountry["CHAD"] = "CHAD";
68
+ })(exports.SupportedCountry || (exports.SupportedCountry = {}));
69
+ const REGIONS_BY_COUNTRY = {
70
+ [exports.SupportedCountry.SENEGAL]: [
71
+ "Dakar",
72
+ "Thiès",
73
+ "Saint-Louis",
74
+ "Louga",
75
+ "Fatick",
76
+ "Tambacounda",
77
+ "Kolda",
78
+ "Ziguinchor",
79
+ "Matam",
80
+ "Kédougou",
81
+ "Sédhiou",
82
+ "Diourbel",
83
+ ],
84
+ [exports.SupportedCountry.CHAD]: [
85
+ "N'Djamena",
86
+ "Moundou",
87
+ "Sarh",
88
+ "Abéché",
89
+ "Doba",
90
+ "Pala",
91
+ "Am Timan",
92
+ "Mongo",
93
+ "Faya-Largeau",
94
+ ],
95
+ };
96
+ /**
97
+ * Returns the list of regions for a given country.
98
+ * Matching is case-insensitive; defaults to Senegal when country is unknown.
99
+ */
100
+ function getRegionsByCountry(country) {
101
+ const key = country?.toUpperCase();
102
+ return REGIONS_BY_COUNTRY[key] ?? REGIONS_BY_COUNTRY[exports.SupportedCountry.SENEGAL];
103
+ }
104
+ /**
105
+ * Returns regions as SelectOption-compatible objects { value, label }.
106
+ */
107
+ function getRegionOptions(country) {
108
+ return getRegionsByCountry(country).map((region) => ({
109
+ value: region,
110
+ label: region,
111
+ }));
112
+ }
113
+
64
114
  /**
65
115
  * Available country codes supported by the platform
66
116
  */
@@ -27378,7 +27428,7 @@ const __iconNode$2X = [
27378
27428
  ],
27379
27429
  ["circle", { cx: "7.5", cy: "7.5", r: ".5", fill: "currentColor", key: "kqv944" }]
27380
27430
  ];
27381
- const Tag = createLucideIcon("tag", __iconNode$2X);
27431
+ const Tag$1 = createLucideIcon("tag", __iconNode$2X);
27382
27432
 
27383
27433
  /**
27384
27434
  * @license lucide-react v0.544.0 - ISC
@@ -32327,7 +32377,7 @@ var index = /*#__PURE__*/Object.freeze({
32327
32377
  Tablet: Tablet,
32328
32378
  TabletSmartphone: TabletSmartphone,
32329
32379
  Tablets: Tablets,
32330
- Tag: Tag,
32380
+ Tag: Tag$1,
32331
32381
  Tags: Tags,
32332
32382
  Tally1: Tally1,
32333
32383
  Tally2: Tally2,
@@ -32623,7 +32673,7 @@ const Input = React.forwardRef(({ className, variant = "default", size = "md", l
32623
32673
  });
32624
32674
  Input.displayName = "Input";
32625
32675
 
32626
- 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, ...props }, ref) => {
32676
+ 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) => {
32627
32677
  const generatedId = React.useId();
32628
32678
  const selectId = `select-${generatedId}`;
32629
32679
  const hasError = isError || !!error;
@@ -32656,15 +32706,6 @@ const Select = React.forwardRef(({ options = [], value, onChange, placeholder =
32656
32706
  const spaceAbove = containerRect.top;
32657
32707
  // Add some buffer (20px) to prevent edge cases
32658
32708
  const buffer = 20;
32659
- console.log("Position calculation:", {
32660
- spaceBelow,
32661
- spaceAbove,
32662
- dropdownHeight,
32663
- viewportHeight,
32664
- containerBottom: containerRect.bottom,
32665
- shouldOpenTop: spaceBelow < dropdownHeight + buffer &&
32666
- spaceAbove > dropdownHeight + buffer,
32667
- });
32668
32709
  // If there's not enough space below but enough space above, position on top
32669
32710
  if (spaceBelow < dropdownHeight + buffer &&
32670
32711
  spaceAbove > dropdownHeight + buffer) {
@@ -32684,13 +32725,6 @@ const Select = React.forwardRef(({ options = [], value, onChange, placeholder =
32684
32725
  const spaceBelow = viewportHeight - containerRect.bottom;
32685
32726
  const spaceAbove = containerRect.top;
32686
32727
  const actualDropdownHeight = dropdownRect.height;
32687
- console.log("Position calculation with element:", {
32688
- spaceBelow,
32689
- spaceAbove,
32690
- actualDropdownHeight,
32691
- viewportHeight,
32692
- containerBottom: containerRect.bottom,
32693
- });
32694
32728
  // If there's not enough space below but enough space above, position on top
32695
32729
  if (spaceBelow < actualDropdownHeight &&
32696
32730
  spaceAbove > actualDropdownHeight) {
@@ -32846,7 +32880,7 @@ const Select = React.forwardRef(({ options = [], value, onChange, placeholder =
32846
32880
  // Text color
32847
32881
  "text-ews-gray-900",
32848
32882
  // Padding for icons
32849
- "pr-10", selectClassName), ...props, children: jsxRuntime.jsxs("div", { className: "flex justify-between items-center", 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"
32883
+ "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"
32850
32884
  ? "bottom-full mb-1"
32851
32885
  : "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: "Search options...", 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 ? "No options found" : "No options available" })) : (filteredOptions.map((option, index) => {
32852
32886
  const isSelected = option.value === value;
@@ -33259,6 +33293,7 @@ const Modal = ({ isOpen, onClose, title, children, variant = "info", size = "md"
33259
33293
  return (jsxRuntime.jsxs("div", { className: "flex fixed inset-0 z-50 justify-center items-center", children: [jsxRuntime.jsx("div", { className: "absolute inset-0 backdrop-blur-sm bg-black/50", onClick: handleOverlayClick }), jsxRuntime.jsxs("div", { className: cn("relative w-full bg-white rounded-lg shadow-xl transition-all transform", "duration-200 animate-in fade-in-0 zoom-in-95", getSizeClasses(), "mx-4", className), role: "dialog", "aria-modal": "true", "aria-labelledby": "modal-title", children: [jsxRuntime.jsxs("div", { className: cn("flex items-center justify-between p-6 border-b", variantStyles.borderColor), children: [jsxRuntime.jsxs("div", { className: "flex items-center space-x-3", children: [jsxRuntime.jsx("div", { className: cn("p-2 rounded-full", variantStyles.iconBg), children: variantStyles.icon }), jsxRuntime.jsx("h2", { id: "modal-title", className: cn("text-lg font-semibold", variantStyles.titleColor), children: title })] }), jsxRuntime.jsx("button", { onClick: onClose, className: "p-1 text-gray-400 transition-colors hover:text-gray-600", "aria-label": "Close modal", children: jsxRuntime.jsx(X, { className: "w-5 h-5" }) })] }), jsxRuntime.jsx("div", { className: cn("p-6", contentClassName), children: jsxRuntime.jsx("div", { className: "leading-relaxed text-gray-700", children: error && variant === "error" ? (jsxRuntime.jsxs("div", { className: "space-y-3", children: [jsxRuntime.jsx("p", { children: error.message }), error.fields && error.fields.length > 0 && (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("p", { className: "font-semibold text-gray-900", children: "Erreurs de champ:" }), jsxRuntime.jsx("ul", { className: "mt-2 space-y-1", children: error.fields.map((field, index) => (jsxRuntime.jsxs("li", { className: "text-ews-error", children: ["\u2022 ", field.path, ": ", field.message] }, index))) })] }))] })) : (children) }) }), (primaryAction || secondaryAction) && (jsxRuntime.jsxs("div", { className: "flex justify-end items-center p-6 pt-0 space-x-3", children: [secondaryAction && (jsxRuntime.jsx(Button, { variant: "outline", onClick: onSecondaryAction || onClose, disabled: isLoading, children: secondaryAction })), primaryAction && (jsxRuntime.jsx(Button, { variant: variant === "error" ? "error" : "ews-primary", onClick: onPrimaryAction, loading: isLoading, children: primaryAction }))] }))] })] }));
33260
33294
  };
33261
33295
 
33296
+ const ACCEPTED_MIME_TYPES = ["image/jpeg", "image/png", "image/webp"];
33262
33297
  const SIZE_CLASSES = {
33263
33298
  sm: "h-10 w-10",
33264
33299
  md: "h-16 w-16",
@@ -33294,28 +33329,34 @@ function UploadProgressBar({ progress, isLoading, }) {
33294
33329
  const indeterminate = isLoading && progress === 0;
33295
33330
  return (jsxRuntime.jsx("div", { className: "mt-2 h-1.5 w-32 rounded-full bg-gray-200", children: jsxRuntime.jsx("div", { className: cn("h-full rounded-full bg-ews-primary transition-all duration-300", indeterminate && "animate-pulse"), style: { width: indeterminate ? "35%" : `${progress}%` } }) }));
33296
33331
  }
33297
- const ProfileImageUpload = ({ imageUrl, altText, readOnly = false, size = "lg", uploadProgress = 0, isLoading = false, showDeleteButton = true, accept = "image/*", maxFileSizeMB = 3, onFileSelect, onFileSizeExceeded, onDeleteConfirm, deleteConfirmTitle, deleteConfirmMessage, deleteConfirmLabel, cancelLabel, }) => {
33332
+ const ProfileImageUpload = ({ imageUrl, altText, readOnly = false, size = "lg", uploadProgress = 0, isLoading = false, showDeleteButton = true, acceptedFormats = [...ACCEPTED_MIME_TYPES], maxFileSizeMB = 5, aspectRatioHint, onFileSelect, onFileSizeExceeded, onInvalidFormat, onDeleteConfirm, deleteConfirmTitle, deleteConfirmMessage, deleteConfirmLabel, cancelLabel, }) => {
33298
33333
  const fileInputRef = React.useRef(null);
33299
33334
  const [isHovered, setIsHovered] = React.useState(false);
33300
33335
  const [showConfirm, setShowConfirm] = React.useState(false);
33336
+ const acceptAttr = acceptedFormats.join(",");
33301
33337
  const handleEditClick = () => fileInputRef.current?.click();
33302
33338
  const handleFileChange = (e) => {
33303
33339
  const file = e.target.files?.[0];
33304
33340
  if (!file)
33305
33341
  return;
33342
+ if (acceptedFormats.indexOf(file.type) === -1) {
33343
+ onInvalidFormat?.();
33344
+ e.target.value = "";
33345
+ return;
33346
+ }
33306
33347
  if (file.size > maxFileSizeMB * 1024 * 1024) {
33307
33348
  onFileSizeExceeded?.();
33308
33349
  e.target.value = "";
33309
33350
  return;
33310
33351
  }
33311
33352
  onFileSelect(file);
33312
- e.target.value = ""; // allow re-selecting the same file
33353
+ e.target.value = "";
33313
33354
  };
33314
33355
  const handleConfirmDelete = () => {
33315
33356
  setShowConfirm(false);
33316
33357
  onDeleteConfirm();
33317
33358
  };
33318
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "inline-flex flex-col items-center", children: [jsxRuntime.jsxs("div", { className: "relative", onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [jsxRuntime.jsx("img", { src: imageUrl, alt: altText, className: cn("rounded-full border-4 border-white object-cover", SIZE_CLASSES[size]) }), jsxRuntime.jsx("div", { className: cn("absolute bottom-0 right-0 rounded-full border-4 border-white bg-green-400", INDICATOR_CLASSES[size]) }), jsxRuntime.jsx("input", { type: "file", ref: fileInputRef, accept: accept, className: "hidden", onChange: handleFileChange }), isHovered && !readOnly && !isLoading && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { type: "button", onClick: handleEditClick, className: "absolute left-0 top-0 flex h-8 w-8 cursor-pointer items-center justify-center rounded-full bg-ews-primary transition-colors hover:bg-ews-secondary", "aria-label": "Edit profile image", children: jsxRuntime.jsx(Pencil, { className: "h-4 w-4 text-white" }) }), showDeleteButton && (jsxRuntime.jsx("button", { type: "button", onClick: () => setShowConfirm(true), className: "absolute left-0 top-10 flex h-8 w-8 cursor-pointer items-center justify-center rounded-full bg-red-600 transition-colors hover:bg-red-700", "aria-label": "Delete profile image", children: jsxRuntime.jsx(Trash, { className: "h-4 w-4 text-white" }) }))] }))] }), jsxRuntime.jsx(UploadProgressBar, { progress: uploadProgress, isLoading: isLoading })] }), jsxRuntime.jsx(Modal, { isOpen: showConfirm, onClose: () => setShowConfirm(false), title: deleteConfirmTitle, variant: "error", size: "sm", primaryAction: deleteConfirmLabel, secondaryAction: cancelLabel, onPrimaryAction: handleConfirmDelete, onSecondaryAction: () => setShowConfirm(false), children: jsxRuntime.jsx("p", { children: deleteConfirmMessage }) })] }));
33359
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "inline-flex flex-col items-center", children: [jsxRuntime.jsxs("div", { className: "relative", onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [jsxRuntime.jsx("img", { src: imageUrl, alt: altText, className: cn("rounded-full border-4 border-white object-cover", SIZE_CLASSES[size]) }), jsxRuntime.jsx("div", { className: cn("absolute bottom-0 right-0 rounded-full border-4 border-white bg-green-400", INDICATOR_CLASSES[size]) }), jsxRuntime.jsx("input", { type: "file", ref: fileInputRef, accept: acceptAttr, className: "hidden", onChange: handleFileChange }), isHovered && !readOnly && !isLoading && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("button", { type: "button", onClick: handleEditClick, className: "absolute left-0 top-0 flex h-8 w-8 cursor-pointer items-center justify-center rounded-full bg-ews-primary transition-colors hover:bg-ews-secondary", "aria-label": "Edit profile image", children: jsxRuntime.jsx(Pencil, { className: "h-4 w-4 text-white" }) }), showDeleteButton && (jsxRuntime.jsx("button", { type: "button", onClick: () => setShowConfirm(true), className: "absolute left-0 top-10 flex h-8 w-8 cursor-pointer items-center justify-center rounded-full bg-red-600 transition-colors hover:bg-red-700", "aria-label": "Delete profile image", children: jsxRuntime.jsx(Trash, { className: "h-4 w-4 text-white" }) }))] }))] }), jsxRuntime.jsx(UploadProgressBar, { progress: uploadProgress, isLoading: isLoading }), aspectRatioHint && (jsxRuntime.jsxs("p", { className: "mt-1 text-xs text-gray-400", children: ["Ratio: ", aspectRatioHint] }))] }), jsxRuntime.jsx(Modal, { isOpen: showConfirm, onClose: () => setShowConfirm(false), title: deleteConfirmTitle, variant: "error", size: "sm", primaryAction: deleteConfirmLabel, secondaryAction: cancelLabel, onPrimaryAction: handleConfirmDelete, onSecondaryAction: () => setShowConfirm(false), children: jsxRuntime.jsx("p", { children: deleteConfirmMessage }) })] }));
33319
33360
  };
33320
33361
 
33321
33362
  const DropdownMultiSelect = ({ options, name, control, placeholder = "Select options", searchPlaceholder = "Search...", onChange, value: controlledValue, defaultValue, onValidate, disabled = false, error, label, className, }) => {
@@ -33662,6 +33703,33 @@ const ThemeDebugger = ({ className = "", }) => {
33662
33703
  : "bg-gray-200 text-gray-700"}`, children: "MED" })] }), jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-2 mt-4", children: [jsxRuntime.jsx("div", { className: "bg-ews-primary text-white p-2 rounded text-center", children: "Primary" }), jsxRuntime.jsx("div", { className: "bg-ews-secondary text-white p-2 rounded text-center", children: "Secondary" }), jsxRuntime.jsx("div", { className: "bg-ews-success text-white p-2 rounded text-center", children: "Success" }), jsxRuntime.jsx("div", { className: "bg-ews-warning text-white p-2 rounded text-center", children: "Warning" })] })] })] }));
33663
33704
  };
33664
33705
 
33706
+ function RegionSelect({ country = exports.SupportedCountry.SENEGAL, value, onChange, label, placeholder = "Select a region", error, isError, disabled, required, containerClassName, }) {
33707
+ const options = getRegionOptions(country);
33708
+ return (jsxRuntime.jsx(Select, { options: options, value: value, onChange: (val) => onChange?.(val), label: label, placeholder: placeholder, error: error, isError: isError, disabled: disabled, required: required, searchable: true, containerClassName: containerClassName }));
33709
+ }
33710
+
33711
+ const Tag = ({ label, variant = "plain", className, }) => {
33712
+ const variantClass = variant === "primary"
33713
+ ? "bg-ews-primary text-white"
33714
+ : variant === "secondary"
33715
+ ? "bg-ews-secondary text-white"
33716
+ : "bg-gray-200 text-gray-800";
33717
+ return (jsxRuntime.jsx("span", { className: cn("inline-block rounded-md px-2.5 py-1 text-sm font-medium", variantClass, className), children: label }));
33718
+ };
33719
+
33720
+ const DEFAULT_MAX = 3;
33721
+ const TagList = ({ items, maxVisible = DEFAULT_MAX, showMoreLabel, showLessLabel, variant = "secondary", className, renderTag, }) => {
33722
+ const [expanded, setExpanded] = React.useState(false);
33723
+ const hasMore = items.length > maxVisible;
33724
+ const visible = expanded ? items : items.slice(0, maxVisible);
33725
+ const handleToggle = (e) => {
33726
+ e.preventDefault();
33727
+ e.stopPropagation();
33728
+ setExpanded(prev => !prev);
33729
+ };
33730
+ return (jsxRuntime.jsxs("div", { className: cn("flex flex-wrap items-center gap-2", className), children: [visible.map((label, i) => renderTag ? (renderTag(label, i)) : (jsxRuntime.jsx(Tag, { label: label, variant: variant }, i))), hasMore && !expanded && (jsxRuntime.jsx("span", { className: "text-sm text-gray-400", children: "..." })), hasMore && (jsxRuntime.jsx("button", { onClick: handleToggle, className: "text-xs text-ews-primary hover:underline", children: expanded ? showLessLabel : showMoreLabel }))] }));
33731
+ };
33732
+
33665
33733
  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, }) => {
33666
33734
  const [filteredSpecialties, setFilteredSpecialties] = React.useState([]);
33667
33735
  const [isLoading, setIsLoading] = React.useState(false);
@@ -37425,7 +37493,7 @@ exports.LucideTableRowsSplit = TableRowsSplit;
37425
37493
  exports.LucideTablet = Tablet;
37426
37494
  exports.LucideTabletSmartphone = TabletSmartphone;
37427
37495
  exports.LucideTablets = Tablets;
37428
- exports.LucideTag = Tag;
37496
+ exports.LucideTag = Tag$1;
37429
37497
  exports.LucideTags = Tags;
37430
37498
  exports.LucideTally1 = Tally1;
37431
37499
  exports.LucideTally2 = Tally2;
@@ -38301,6 +38369,7 @@ exports.Refrigerator = Refrigerator;
38301
38369
  exports.RefrigeratorIcon = Refrigerator;
38302
38370
  exports.Regex = Regex;
38303
38371
  exports.RegexIcon = Regex;
38372
+ exports.RegionSelect = RegionSelect;
38304
38373
  exports.RemoveFormatting = RemoveFormatting;
38305
38374
  exports.RemoveFormattingIcon = RemoveFormatting;
38306
38375
  exports.Repeat = Repeat;
@@ -38873,7 +38942,8 @@ exports.TabletSmartphoneIcon = TabletSmartphone;
38873
38942
  exports.Tablets = Tablets;
38874
38943
  exports.TabletsIcon = Tablets;
38875
38944
  exports.Tag = Tag;
38876
- exports.TagIcon = Tag;
38945
+ exports.TagIcon = Tag$1;
38946
+ exports.TagList = TagList;
38877
38947
  exports.Tags = Tags;
38878
38948
  exports.TagsIcon = Tags;
38879
38949
  exports.Tally1 = Tally1;
@@ -39316,6 +39386,8 @@ exports.formatNumeric = formatNumeric;
39316
39386
  exports.formatPhoneNumberWithCountryCode = formatPhoneNumberWithCountryCode;
39317
39387
  exports.generateId = generateId;
39318
39388
  exports.getDefaultCountryCode = getDefaultCountryCode;
39389
+ exports.getRegionOptions = getRegionOptions;
39390
+ exports.getRegionsByCountry = getRegionsByCountry;
39319
39391
  exports.icons = index;
39320
39392
  exports.isValidPhoneNumber = isValidPhoneNumber;
39321
39393
  exports.useDebounce = useDebounce;