@ews-admin/global-design-system 1.1.20 → 1.1.22
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 +8 -0
- package/dist/components/Input/Input.d.ts.map +1 -1
- package/dist/components/Modal/Modal.d.ts +5 -1
- package/dist/components/Modal/Modal.d.ts.map +1 -1
- package/dist/components/ProfileImageUpload/ProfileImageUpload.d.ts +47 -0
- package/dist/components/ProfileImageUpload/ProfileImageUpload.d.ts.map +1 -0
- package/dist/components/ProfileImageUpload/index.d.ts +3 -0
- package/dist/components/ProfileImageUpload/index.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +80 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +161 -26
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +161 -24
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +19 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Input/Input.tsx +28 -2
- package/src/components/Modal/Modal.tsx +20 -1
- package/src/components/ProfileImageUpload/ProfileImageUpload.tsx +231 -0
- package/src/components/ProfileImageUpload/index.ts +2 -0
- package/src/index.ts +5 -0
- package/src/utils/index.ts +31 -0
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
1
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import React, { forwardRef, createElement, useState, useRef, useEffect, useId, useCallback, createContext, useContext } from 'react';
|
|
3
3
|
|
|
4
4
|
function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
|
|
@@ -84,6 +84,36 @@ function isValidPhoneNumber(value) {
|
|
|
84
84
|
const phoneRegex = /^(\+\d{1,17}|\d{1,17})$/;
|
|
85
85
|
return phoneRegex.test(trimmedValue);
|
|
86
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Blood type enum matching backend BloodTypeEnum values
|
|
89
|
+
*/
|
|
90
|
+
var BloodType;
|
|
91
|
+
(function (BloodType) {
|
|
92
|
+
BloodType["A_POSITIVE"] = "A+";
|
|
93
|
+
BloodType["A_NEGATIVE"] = "A-";
|
|
94
|
+
BloodType["B_POSITIVE"] = "B+";
|
|
95
|
+
BloodType["B_NEGATIVE"] = "B-";
|
|
96
|
+
BloodType["AB_POSITIVE"] = "AB+";
|
|
97
|
+
BloodType["AB_NEGATIVE"] = "AB-";
|
|
98
|
+
BloodType["O_POSITIVE"] = "O+";
|
|
99
|
+
BloodType["O_NEGATIVE"] = "O-";
|
|
100
|
+
BloodType["UNKNOWN"] = "UNKNOWN";
|
|
101
|
+
})(BloodType || (BloodType = {}));
|
|
102
|
+
/**
|
|
103
|
+
* Ordered list of all blood type values.
|
|
104
|
+
* Use this to build select/dropdown options.
|
|
105
|
+
*/
|
|
106
|
+
const BLOOD_TYPES = [
|
|
107
|
+
BloodType.A_POSITIVE,
|
|
108
|
+
BloodType.A_NEGATIVE,
|
|
109
|
+
BloodType.B_POSITIVE,
|
|
110
|
+
BloodType.B_NEGATIVE,
|
|
111
|
+
BloodType.AB_POSITIVE,
|
|
112
|
+
BloodType.AB_NEGATIVE,
|
|
113
|
+
BloodType.O_POSITIVE,
|
|
114
|
+
BloodType.O_NEGATIVE,
|
|
115
|
+
BloodType.UNKNOWN,
|
|
116
|
+
];
|
|
87
117
|
|
|
88
118
|
const Button = React.forwardRef(({ className, variant = "ews-primary", size = "md", loading = false, fullWidth = false, leftIcon, rightIcon, children, disabled, ...props }, ref) => {
|
|
89
119
|
const baseStyles = "inline-flex items-center justify-center font-medium rounded-md transition-colors focus:outline-none disabled:opacity-50 disabled:pointer-events-none";
|
|
@@ -227,11 +257,11 @@ const createLucideIcon = (iconName, iconNode) => {
|
|
|
227
257
|
*/
|
|
228
258
|
|
|
229
259
|
|
|
230
|
-
const __iconNode$
|
|
260
|
+
const __iconNode$e = [
|
|
231
261
|
["path", { d: "M5 12h14", key: "1ays0h" }],
|
|
232
262
|
["path", { d: "m12 5 7 7-7 7", key: "xquz4c" }]
|
|
233
263
|
];
|
|
234
|
-
const ArrowRight = createLucideIcon("arrow-right", __iconNode$
|
|
264
|
+
const ArrowRight = createLucideIcon("arrow-right", __iconNode$e);
|
|
235
265
|
|
|
236
266
|
/**
|
|
237
267
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -241,8 +271,8 @@ const ArrowRight = createLucideIcon("arrow-right", __iconNode$c);
|
|
|
241
271
|
*/
|
|
242
272
|
|
|
243
273
|
|
|
244
|
-
const __iconNode$
|
|
245
|
-
const Check = createLucideIcon("check", __iconNode$
|
|
274
|
+
const __iconNode$d = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]];
|
|
275
|
+
const Check = createLucideIcon("check", __iconNode$d);
|
|
246
276
|
|
|
247
277
|
/**
|
|
248
278
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -252,8 +282,8 @@ const Check = createLucideIcon("check", __iconNode$b);
|
|
|
252
282
|
*/
|
|
253
283
|
|
|
254
284
|
|
|
255
|
-
const __iconNode$
|
|
256
|
-
const ChevronDown = createLucideIcon("chevron-down", __iconNode$
|
|
285
|
+
const __iconNode$c = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
|
|
286
|
+
const ChevronDown = createLucideIcon("chevron-down", __iconNode$c);
|
|
257
287
|
|
|
258
288
|
/**
|
|
259
289
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -263,12 +293,12 @@ const ChevronDown = createLucideIcon("chevron-down", __iconNode$a);
|
|
|
263
293
|
*/
|
|
264
294
|
|
|
265
295
|
|
|
266
|
-
const __iconNode$
|
|
296
|
+
const __iconNode$b = [
|
|
267
297
|
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
268
298
|
["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
|
|
269
299
|
["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
|
|
270
300
|
];
|
|
271
|
-
const CircleAlert = createLucideIcon("circle-alert", __iconNode$
|
|
301
|
+
const CircleAlert = createLucideIcon("circle-alert", __iconNode$b);
|
|
272
302
|
|
|
273
303
|
/**
|
|
274
304
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -278,11 +308,11 @@ const CircleAlert = createLucideIcon("circle-alert", __iconNode$9);
|
|
|
278
308
|
*/
|
|
279
309
|
|
|
280
310
|
|
|
281
|
-
const __iconNode$
|
|
311
|
+
const __iconNode$a = [
|
|
282
312
|
["path", { d: "M21.801 10A10 10 0 1 1 17 3.335", key: "yps3ct" }],
|
|
283
313
|
["path", { d: "m9 11 3 3L22 4", key: "1pflzl" }]
|
|
284
314
|
];
|
|
285
|
-
const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$
|
|
315
|
+
const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$a);
|
|
286
316
|
|
|
287
317
|
/**
|
|
288
318
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -292,7 +322,7 @@ const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$8);
|
|
|
292
322
|
*/
|
|
293
323
|
|
|
294
324
|
|
|
295
|
-
const __iconNode$
|
|
325
|
+
const __iconNode$9 = [
|
|
296
326
|
[
|
|
297
327
|
"path",
|
|
298
328
|
{
|
|
@@ -310,7 +340,7 @@ const __iconNode$7 = [
|
|
|
310
340
|
],
|
|
311
341
|
["path", { d: "m2 2 20 20", key: "1ooewy" }]
|
|
312
342
|
];
|
|
313
|
-
const EyeOff = createLucideIcon("eye-off", __iconNode$
|
|
343
|
+
const EyeOff = createLucideIcon("eye-off", __iconNode$9);
|
|
314
344
|
|
|
315
345
|
/**
|
|
316
346
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -320,7 +350,7 @@ const EyeOff = createLucideIcon("eye-off", __iconNode$7);
|
|
|
320
350
|
*/
|
|
321
351
|
|
|
322
352
|
|
|
323
|
-
const __iconNode$
|
|
353
|
+
const __iconNode$8 = [
|
|
324
354
|
[
|
|
325
355
|
"path",
|
|
326
356
|
{
|
|
@@ -330,7 +360,7 @@ const __iconNode$6 = [
|
|
|
330
360
|
],
|
|
331
361
|
["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
|
|
332
362
|
];
|
|
333
|
-
const Eye = createLucideIcon("eye", __iconNode$
|
|
363
|
+
const Eye = createLucideIcon("eye", __iconNode$8);
|
|
334
364
|
|
|
335
365
|
/**
|
|
336
366
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -340,7 +370,7 @@ const Eye = createLucideIcon("eye", __iconNode$6);
|
|
|
340
370
|
*/
|
|
341
371
|
|
|
342
372
|
|
|
343
|
-
const __iconNode$
|
|
373
|
+
const __iconNode$7 = [
|
|
344
374
|
[
|
|
345
375
|
"path",
|
|
346
376
|
{
|
|
@@ -349,7 +379,7 @@ const __iconNode$5 = [
|
|
|
349
379
|
}
|
|
350
380
|
]
|
|
351
381
|
];
|
|
352
|
-
const Heart = createLucideIcon("heart", __iconNode$
|
|
382
|
+
const Heart = createLucideIcon("heart", __iconNode$7);
|
|
353
383
|
|
|
354
384
|
/**
|
|
355
385
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -359,11 +389,31 @@ const Heart = createLucideIcon("heart", __iconNode$5);
|
|
|
359
389
|
*/
|
|
360
390
|
|
|
361
391
|
|
|
362
|
-
const __iconNode$
|
|
392
|
+
const __iconNode$6 = [
|
|
393
|
+
[
|
|
394
|
+
"path",
|
|
395
|
+
{
|
|
396
|
+
d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",
|
|
397
|
+
key: "1a8usu"
|
|
398
|
+
}
|
|
399
|
+
],
|
|
400
|
+
["path", { d: "m15 5 4 4", key: "1mk7zo" }]
|
|
401
|
+
];
|
|
402
|
+
const Pencil = createLucideIcon("pencil", __iconNode$6);
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* @license lucide-react v0.544.0 - ISC
|
|
406
|
+
*
|
|
407
|
+
* This source code is licensed under the ISC license.
|
|
408
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
409
|
+
*/
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
const __iconNode$5 = [
|
|
363
413
|
["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
|
|
364
414
|
["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
|
|
365
415
|
];
|
|
366
|
-
const Search = createLucideIcon("search", __iconNode$
|
|
416
|
+
const Search = createLucideIcon("search", __iconNode$5);
|
|
367
417
|
|
|
368
418
|
/**
|
|
369
419
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -373,14 +423,29 @@ const Search = createLucideIcon("search", __iconNode$4);
|
|
|
373
423
|
*/
|
|
374
424
|
|
|
375
425
|
|
|
376
|
-
const __iconNode$
|
|
426
|
+
const __iconNode$4 = [
|
|
377
427
|
["path", { d: "M11 2v2", key: "1539x4" }],
|
|
378
428
|
["path", { d: "M5 2v2", key: "1yf1q8" }],
|
|
379
429
|
["path", { d: "M5 3H4a2 2 0 0 0-2 2v4a6 6 0 0 0 12 0V5a2 2 0 0 0-2-2h-1", key: "rb5t3r" }],
|
|
380
430
|
["path", { d: "M8 15a6 6 0 0 0 12 0v-3", key: "x18d4x" }],
|
|
381
431
|
["circle", { cx: "20", cy: "10", r: "2", key: "ts1r5v" }]
|
|
382
432
|
];
|
|
383
|
-
const Stethoscope = createLucideIcon("stethoscope", __iconNode$
|
|
433
|
+
const Stethoscope = createLucideIcon("stethoscope", __iconNode$4);
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* @license lucide-react v0.544.0 - ISC
|
|
437
|
+
*
|
|
438
|
+
* This source code is licensed under the ISC license.
|
|
439
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
440
|
+
*/
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
const __iconNode$3 = [
|
|
444
|
+
["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6", key: "miytrc" }],
|
|
445
|
+
["path", { d: "M3 6h18", key: "d0wm0j" }],
|
|
446
|
+
["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2", key: "e791ji" }]
|
|
447
|
+
];
|
|
448
|
+
const Trash = createLucideIcon("trash", __iconNode$3);
|
|
384
449
|
|
|
385
450
|
/**
|
|
386
451
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -455,7 +520,7 @@ const UserIcon = ({ size = 24, color = "currentColor", className = "", ...props
|
|
|
455
520
|
return jsx(User, { size: size, color: color, className: className, ...props });
|
|
456
521
|
};
|
|
457
522
|
|
|
458
|
-
const Input = React.forwardRef(({ className, variant = "default", size = "md", label, helperText, error, leftIcon, rightIcon, fullWidth = false, showPasswordToggle = false, required = false, countryCodeSelect, id, type = "text", ...props }, ref) => {
|
|
523
|
+
const Input = React.forwardRef(({ className, variant = "default", size = "md", label, helperText, error, leftIcon, rightIcon, fullWidth = false, showPasswordToggle = false, required = false, countryCodeSelect, leftAddon, rightAddon, id, type = "text", ...props }, ref) => {
|
|
459
524
|
const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`;
|
|
460
525
|
const hasError = Boolean(error);
|
|
461
526
|
const actualVariant = hasError ? "error" : variant;
|
|
@@ -514,7 +579,7 @@ const Input = React.forwardRef(({ className, variant = "default", size = "md", l
|
|
|
514
579
|
countryCodeSelect.onChange(item.code);
|
|
515
580
|
setIsDropdownOpen(false);
|
|
516
581
|
}, className: cn("px-3 py-2 text-sm cursor-pointer transition-colors", isSelected && "bg-ews-primary text-white", !isSelected && "hover:bg-ews-gray-50"), children: [jsx("span", { className: "font-medium", children: item.code }), item.country && (jsx("span", { className: cn("ml-2 text-xs", isSelected ? "text-white/80" : "text-ews-gray-500"), children: item.country }))] }, item.code));
|
|
517
|
-
}) }))] }) })), leftIcon && !countryCodeSelect && (jsx("div", { className: "flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none", children: jsx("span", { className: cn("text-ews-gray-400", iconSizes[size]), children: leftIcon }) })), jsx("input", { id: inputId, type: actualType, className: cn(baseStyles, variants[actualVariant], sizes[size], countryCodeSelect && "pl-24", leftIcon && !countryCodeSelect && "pl-10", (rightIcon || shouldShowPasswordToggle) && "pr-10", className), ref: ref, ...props }), rightIcon && !shouldShowPasswordToggle && (jsx("div", { className: "flex absolute inset-y-0 right-0 items-center pr-3 pointer-events-none", children: jsx("span", { className: cn("text-ews-gray-400", iconSizes[size]), children: rightIcon }) })), shouldShowPasswordToggle && (jsx("button", { type: "button", className: "flex absolute inset-y-0 right-0 items-center pr-3", onClick: () => setShowPassword(!showPassword), tabIndex: -1, children: jsx("span", { className: cn("transition-colors text-ews-gray-400 hover:text-ews-gray-600", iconSizes[size]), children: showPassword ? jsx(EyeOff, { size: 16 }) : jsx(Eye, { size: 16 }) }) }))] }), (error || helperText) && (jsx("p", { className: cn("text-sm", error ? "text-ews-error" : "text-ews-gray-500"), children: error || helperText }))] }));
|
|
582
|
+
}) }))] }) })), leftIcon && !countryCodeSelect && !leftAddon && (jsx("div", { className: "flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none", children: jsx("span", { className: cn("text-ews-gray-400", iconSizes[size]), children: leftIcon }) })), leftAddon && !countryCodeSelect && !leftIcon && (jsx("div", { className: "flex absolute inset-y-0 left-0 items-center pointer-events-none overflow-hidden rounded-l-md", children: jsx("span", { className: "flex items-center h-full px-3 text-sm font-medium whitespace-nowrap bg-ews-gray-50 border-r border-ews-gray-300 text-ews-gray-600", children: leftAddon }) })), jsx("input", { id: inputId, type: actualType, className: cn(baseStyles, variants[actualVariant], sizes[size], countryCodeSelect && "pl-24", leftIcon && !countryCodeSelect && !leftAddon && "pl-10", leftAddon && !countryCodeSelect && !leftIcon && "pl-16", (rightIcon || shouldShowPasswordToggle) && "pr-10", rightAddon && !rightIcon && !shouldShowPasswordToggle && "pr-16", className), ref: ref, ...props }), rightAddon && !rightIcon && !shouldShowPasswordToggle && (jsx("div", { className: "flex absolute inset-y-0 right-0 items-center pr-3 pointer-events-none", children: jsx("span", { className: "text-sm font-medium text-ews-gray-500", children: rightAddon }) })), rightIcon && !shouldShowPasswordToggle && (jsx("div", { className: "flex absolute inset-y-0 right-0 items-center pr-3 pointer-events-none", children: jsx("span", { className: cn("text-ews-gray-400", iconSizes[size]), children: rightIcon }) })), shouldShowPasswordToggle && (jsx("button", { type: "button", className: "flex absolute inset-y-0 right-0 items-center pr-3", onClick: () => setShowPassword(!showPassword), tabIndex: -1, children: jsx("span", { className: cn("transition-colors text-ews-gray-400 hover:text-ews-gray-600", iconSizes[size]), children: showPassword ? jsx(EyeOff, { size: 16 }) : jsx(Eye, { size: 16 }) }) }))] }), (error || helperText) && (jsx("p", { className: cn("text-sm", error ? "text-ews-error" : "text-ews-gray-500"), children: error || helperText }))] }));
|
|
518
583
|
});
|
|
519
584
|
Input.displayName = "Input";
|
|
520
585
|
|
|
@@ -1638,7 +1703,7 @@ function MultiSearchAutocomplete({ items, selectedItems, onSelectionChange, onSe
|
|
|
1638
1703
|
}) })) }))] }));
|
|
1639
1704
|
}
|
|
1640
1705
|
|
|
1641
|
-
const Modal = ({ isOpen, onClose, title, children, variant = "info", primaryAction, secondaryAction, onPrimaryAction, onSecondaryAction, isLoading = false, closeOnOverlayClick = true, className, contentClassName, error, }) => {
|
|
1706
|
+
const Modal = ({ isOpen, onClose, title, children, variant = "info", size = "md", primaryAction, secondaryAction, onPrimaryAction, onSecondaryAction, isLoading = false, closeOnOverlayClick = true, className, contentClassName, error, }) => {
|
|
1642
1707
|
// Handle escape key press
|
|
1643
1708
|
useEffect(() => {
|
|
1644
1709
|
const handleEscape = (event) => {
|
|
@@ -1691,12 +1756,82 @@ const Modal = ({ isOpen, onClose, title, children, variant = "info", primaryActi
|
|
|
1691
1756
|
}
|
|
1692
1757
|
};
|
|
1693
1758
|
const variantStyles = getVariantStyles();
|
|
1759
|
+
const getSizeClasses = () => {
|
|
1760
|
+
const sizeMap = {
|
|
1761
|
+
sm: "max-w-sm",
|
|
1762
|
+
md: "max-w-md",
|
|
1763
|
+
lg: "max-w-lg",
|
|
1764
|
+
xl: "max-w-xl",
|
|
1765
|
+
"2xl": "max-w-2xl",
|
|
1766
|
+
full: "max-w-full",
|
|
1767
|
+
};
|
|
1768
|
+
return sizeMap[size] || sizeMap.md;
|
|
1769
|
+
};
|
|
1694
1770
|
const handleOverlayClick = (e) => {
|
|
1695
1771
|
if (e.target === e.currentTarget && closeOnOverlayClick) {
|
|
1696
1772
|
onClose();
|
|
1697
1773
|
}
|
|
1698
1774
|
};
|
|
1699
|
-
return (jsxs("div", { className: "flex fixed inset-0 z-50 justify-center items-center", children: [jsx("div", { className: "absolute inset-0 backdrop-blur-sm bg-black/50", onClick: handleOverlayClick }), jsxs("div", { className: cn("relative
|
|
1775
|
+
return (jsxs("div", { className: "flex fixed inset-0 z-50 justify-center items-center", children: [jsx("div", { className: "absolute inset-0 backdrop-blur-sm bg-black/50", onClick: handleOverlayClick }), 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: [jsxs("div", { className: cn("flex items-center justify-between p-6 border-b", variantStyles.borderColor), children: [jsxs("div", { className: "flex items-center space-x-3", children: [jsx("div", { className: cn("p-2 rounded-full", variantStyles.iconBg), children: variantStyles.icon }), jsx("h2", { id: "modal-title", className: cn("text-lg font-semibold", variantStyles.titleColor), children: title })] }), jsx("button", { onClick: onClose, className: "p-1 text-gray-400 transition-colors hover:text-gray-600", "aria-label": "Close modal", children: jsx(X, { className: "w-5 h-5" }) })] }), jsx("div", { className: cn("p-6", contentClassName), children: jsx("div", { className: "leading-relaxed text-gray-700", children: error && variant === "error" ? (jsxs("div", { className: "space-y-3", children: [jsx("p", { children: error.message }), error.fields && error.fields.length > 0 && (jsxs("div", { children: [jsx("p", { className: "font-semibold text-gray-900", children: "Erreurs de champ:" }), jsx("ul", { className: "mt-2 space-y-1", children: error.fields.map((field, index) => (jsxs("li", { className: "text-ews-error", children: ["\u2022 ", field.path, ": ", field.message] }, index))) })] }))] })) : (children) }) }), (primaryAction || secondaryAction) && (jsxs("div", { className: "flex justify-end items-center p-6 pt-0 space-x-3", children: [secondaryAction && (jsx(Button, { variant: "outline", onClick: onSecondaryAction || onClose, disabled: isLoading, children: secondaryAction })), primaryAction && (jsx(Button, { variant: variant === "error" ? "error" : "ews-primary", onClick: onPrimaryAction, loading: isLoading, children: primaryAction }))] }))] })] }));
|
|
1776
|
+
};
|
|
1777
|
+
|
|
1778
|
+
const SIZE_CLASSES = {
|
|
1779
|
+
sm: "h-10 w-10",
|
|
1780
|
+
md: "h-16 w-16",
|
|
1781
|
+
lg: "h-32 w-32",
|
|
1782
|
+
};
|
|
1783
|
+
const INDICATOR_CLASSES = {
|
|
1784
|
+
sm: "h-2 w-2",
|
|
1785
|
+
md: "h-4 w-4",
|
|
1786
|
+
lg: "h-8 w-8",
|
|
1787
|
+
};
|
|
1788
|
+
function UploadProgressBar({ progress, isLoading, }) {
|
|
1789
|
+
const [visible, setVisible] = useState(false);
|
|
1790
|
+
useEffect(() => {
|
|
1791
|
+
if (isLoading) {
|
|
1792
|
+
setVisible(true);
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
// isLoading just turned false
|
|
1796
|
+
if (progress >= 100) {
|
|
1797
|
+
setVisible(true);
|
|
1798
|
+
const t = setTimeout(() => setVisible(false), 1000);
|
|
1799
|
+
return () => clearTimeout(t);
|
|
1800
|
+
}
|
|
1801
|
+
// Legacy path (no isLoading prop): driven purely by progress
|
|
1802
|
+
if (progress > 0 && progress < 100) {
|
|
1803
|
+
setVisible(true);
|
|
1804
|
+
return;
|
|
1805
|
+
}
|
|
1806
|
+
setVisible(false);
|
|
1807
|
+
}, [progress, isLoading]);
|
|
1808
|
+
if (!visible)
|
|
1809
|
+
return null;
|
|
1810
|
+
const indeterminate = isLoading && progress === 0;
|
|
1811
|
+
return (jsx("div", { className: "mt-2 h-1.5 w-32 rounded-full bg-gray-200", children: jsx("div", { className: cn("h-full rounded-full bg-ews-primary transition-all duration-300", indeterminate && "animate-pulse"), style: { width: indeterminate ? "35%" : `${progress}%` } }) }));
|
|
1812
|
+
}
|
|
1813
|
+
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, }) => {
|
|
1814
|
+
const fileInputRef = useRef(null);
|
|
1815
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
1816
|
+
const [showConfirm, setShowConfirm] = useState(false);
|
|
1817
|
+
const handleEditClick = () => fileInputRef.current?.click();
|
|
1818
|
+
const handleFileChange = (e) => {
|
|
1819
|
+
const file = e.target.files?.[0];
|
|
1820
|
+
if (!file)
|
|
1821
|
+
return;
|
|
1822
|
+
if (file.size > maxFileSizeMB * 1024 * 1024) {
|
|
1823
|
+
onFileSizeExceeded?.();
|
|
1824
|
+
e.target.value = "";
|
|
1825
|
+
return;
|
|
1826
|
+
}
|
|
1827
|
+
onFileSelect(file);
|
|
1828
|
+
e.target.value = ""; // allow re-selecting the same file
|
|
1829
|
+
};
|
|
1830
|
+
const handleConfirmDelete = () => {
|
|
1831
|
+
setShowConfirm(false);
|
|
1832
|
+
onDeleteConfirm();
|
|
1833
|
+
};
|
|
1834
|
+
return (jsxs(Fragment, { children: [jsxs("div", { className: "inline-flex flex-col items-center", children: [jsxs("div", { className: "relative", onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [jsx("img", { src: imageUrl, alt: altText, className: cn("rounded-full border-4 border-white object-cover", SIZE_CLASSES[size]) }), jsx("div", { className: cn("absolute bottom-0 right-0 rounded-full border-4 border-white bg-green-400", INDICATOR_CLASSES[size]) }), jsx("input", { type: "file", ref: fileInputRef, accept: accept, className: "hidden", onChange: handleFileChange }), isHovered && !readOnly && !isLoading && (jsxs(Fragment, { children: [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: jsx(Pencil, { className: "h-4 w-4 text-white" }) }), showDeleteButton && (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: jsx(Trash, { className: "h-4 w-4 text-white" }) }))] }))] }), jsx(UploadProgressBar, { progress: uploadProgress, isLoading: isLoading })] }), jsx(Modal, { isOpen: showConfirm, onClose: () => setShowConfirm(false), title: deleteConfirmTitle, variant: "error", size: "sm", primaryAction: deleteConfirmLabel, secondaryAction: cancelLabel, onPrimaryAction: handleConfirmDelete, onSecondaryAction: () => setShowConfirm(false), children: jsx("p", { children: deleteConfirmMessage }) })] }));
|
|
1700
1835
|
};
|
|
1701
1836
|
|
|
1702
1837
|
const DropdownMultiSelect = ({ options, name, control, placeholder = "Select options", searchPlaceholder = "Search...", onChange, value: controlledValue, defaultValue, onValidate, disabled = false, error, label, className, }) => {
|
|
@@ -1985,5 +2120,5 @@ const SpecialtySearchAutocomplete = ({ selectedSpecialties = [], onSpecialtiesCh
|
|
|
1985
2120
|
: `${selectedSpecialties.length} specialty${selectedSpecialties.length !== 1 ? "ies" : ""} selected` }), maxSelections && (jsxs("span", { className: "text-gray-400", children: [selectedSpecialties.length, "/", maxSelections] }))] }))] }));
|
|
1986
2121
|
};
|
|
1987
2122
|
|
|
1988
|
-
export { ArrowRight, Button, Check, DoctorIcon, DropdownMultiSelect, Icon, Input, Logo, Modal, MultiSearchAutocomplete, PatientIcon, Search, SearchAutocomplete, Select, SpecialtySearchAutocomplete, ThemeDebugger, ThemeProvider, ThemeToggle, UserIcon, cn, debounce, formatCurrency, formatDate, formatNumeric, generateId, isValidPhoneNumber, useDebounce, useDebouncedCallback, useSelectField, useTheme };
|
|
2123
|
+
export { ArrowRight, BLOOD_TYPES, BloodType, Button, Check, DoctorIcon, DropdownMultiSelect, Icon, Input, Logo, Modal, MultiSearchAutocomplete, PatientIcon, ProfileImageUpload, Search, SearchAutocomplete, Select, SpecialtySearchAutocomplete, ThemeDebugger, ThemeProvider, ThemeToggle, UserIcon, cn, debounce, formatCurrency, formatDate, formatNumeric, generateId, isValidPhoneNumber, useDebounce, useDebouncedCallback, useSelectField, useTheme };
|
|
1989
2124
|
//# sourceMappingURL=index.esm.js.map
|