@ews-admin/global-design-system 1.1.21 → 1.1.23
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/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 +107 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +202 -24
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +203 -22
- package/dist/index.js.map +1 -1
- package/dist/utils/env-config.d.ts +32 -0
- package/dist/utils/env-config.d.ts.map +1 -0
- package/dist/utils/index.d.ts +21 -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/ProfileImageUpload/ProfileImageUpload.tsx +231 -0
- package/src/components/ProfileImageUpload/index.ts +2 -0
- package/src/index.ts +7 -0
- package/src/utils/env-config.ts +82 -0
- package/src/utils/index.ts +38 -0
package/dist/index.js
CHANGED
|
@@ -5,6 +5,60 @@ var React = require('react');
|
|
|
5
5
|
|
|
6
6
|
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}
|
|
7
7
|
|
|
8
|
+
const LOCAL_PORTS = {
|
|
9
|
+
bff: 8082,
|
|
10
|
+
loginBff: 8080,
|
|
11
|
+
app: 3000,
|
|
12
|
+
login: 3001,
|
|
13
|
+
dashboard: 3002,
|
|
14
|
+
admin: 3008,
|
|
15
|
+
};
|
|
16
|
+
function buildUrls(environment) {
|
|
17
|
+
if (environment === "local") {
|
|
18
|
+
const base = "http://local";
|
|
19
|
+
const domain = "medecine360local.com";
|
|
20
|
+
return {
|
|
21
|
+
bffUrl: `${base}.api.${domain}:${LOCAL_PORTS.bff}/bff/api/v1`,
|
|
22
|
+
loginBffUrl: `${base}.api.${domain}:${LOCAL_PORTS.loginBff}/login-bff/api/v1`,
|
|
23
|
+
appUrl: `${base}.app.${domain}:${LOCAL_PORTS.app}`,
|
|
24
|
+
loginUrl: `${base}.login.${domain}:${LOCAL_PORTS.login}`,
|
|
25
|
+
dashboardUrl: `${base}.dashboard.${domain}:${LOCAL_PORTS.dashboard}`,
|
|
26
|
+
adminUrl: `${base}.admin.${domain}:${LOCAL_PORTS.admin}`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const prefix = environment === "prod" ? "" : `${environment}.`;
|
|
30
|
+
const domain = "medecine360.com";
|
|
31
|
+
return {
|
|
32
|
+
bffUrl: `https://${prefix}api.${domain}/bff/api/v1`,
|
|
33
|
+
loginBffUrl: `https://${prefix}api.${domain}/login-bff/api/v1`,
|
|
34
|
+
appUrl: `https://${prefix}app.${domain}`,
|
|
35
|
+
loginUrl: `https://${prefix}login.${domain}`,
|
|
36
|
+
dashboardUrl: `https://${prefix}dashboard.${domain}`,
|
|
37
|
+
adminUrl: `https://${prefix}admin.${domain}`,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates an environment configuration with all derived URLs.
|
|
42
|
+
*
|
|
43
|
+
* For deployed environments (dev, qa, prod), only the environment name is needed
|
|
44
|
+
* — all URLs follow a predictable convention.
|
|
45
|
+
*
|
|
46
|
+
* For local development, sensible defaults are provided but can be overridden
|
|
47
|
+
* (e.g. to point BFF URL at a mock server).
|
|
48
|
+
*
|
|
49
|
+
* @param env - The environment name (VITE_ENV value)
|
|
50
|
+
* @param overrides - Optional URL overrides (e.g. for local mock servers)
|
|
51
|
+
*/
|
|
52
|
+
function createEnvConfig(env, overrides) {
|
|
53
|
+
const environment = (env || "local");
|
|
54
|
+
const derived = buildUrls(environment);
|
|
55
|
+
return {
|
|
56
|
+
env: environment,
|
|
57
|
+
...derived,
|
|
58
|
+
...overrides,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
8
62
|
/**
|
|
9
63
|
* Default currency for price formatting
|
|
10
64
|
*/
|
|
@@ -86,6 +140,36 @@ function isValidPhoneNumber(value) {
|
|
|
86
140
|
const phoneRegex = /^(\+\d{1,17}|\d{1,17})$/;
|
|
87
141
|
return phoneRegex.test(trimmedValue);
|
|
88
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* Blood type enum matching backend BloodTypeEnum values
|
|
145
|
+
*/
|
|
146
|
+
exports.BloodType = void 0;
|
|
147
|
+
(function (BloodType) {
|
|
148
|
+
BloodType["A_POSITIVE"] = "A+";
|
|
149
|
+
BloodType["A_NEGATIVE"] = "A-";
|
|
150
|
+
BloodType["B_POSITIVE"] = "B+";
|
|
151
|
+
BloodType["B_NEGATIVE"] = "B-";
|
|
152
|
+
BloodType["AB_POSITIVE"] = "AB+";
|
|
153
|
+
BloodType["AB_NEGATIVE"] = "AB-";
|
|
154
|
+
BloodType["O_POSITIVE"] = "O+";
|
|
155
|
+
BloodType["O_NEGATIVE"] = "O-";
|
|
156
|
+
BloodType["UNKNOWN"] = "UNKNOWN";
|
|
157
|
+
})(exports.BloodType || (exports.BloodType = {}));
|
|
158
|
+
/**
|
|
159
|
+
* Ordered list of all blood type values.
|
|
160
|
+
* Use this to build select/dropdown options.
|
|
161
|
+
*/
|
|
162
|
+
const BLOOD_TYPES = [
|
|
163
|
+
exports.BloodType.A_POSITIVE,
|
|
164
|
+
exports.BloodType.A_NEGATIVE,
|
|
165
|
+
exports.BloodType.B_POSITIVE,
|
|
166
|
+
exports.BloodType.B_NEGATIVE,
|
|
167
|
+
exports.BloodType.AB_POSITIVE,
|
|
168
|
+
exports.BloodType.AB_NEGATIVE,
|
|
169
|
+
exports.BloodType.O_POSITIVE,
|
|
170
|
+
exports.BloodType.O_NEGATIVE,
|
|
171
|
+
exports.BloodType.UNKNOWN,
|
|
172
|
+
];
|
|
89
173
|
|
|
90
174
|
const Button = React.forwardRef(({ className, variant = "ews-primary", size = "md", loading = false, fullWidth = false, leftIcon, rightIcon, children, disabled, ...props }, ref) => {
|
|
91
175
|
const baseStyles = "inline-flex items-center justify-center font-medium rounded-md transition-colors focus:outline-none disabled:opacity-50 disabled:pointer-events-none";
|
|
@@ -229,11 +313,11 @@ const createLucideIcon = (iconName, iconNode) => {
|
|
|
229
313
|
*/
|
|
230
314
|
|
|
231
315
|
|
|
232
|
-
const __iconNode$
|
|
316
|
+
const __iconNode$e = [
|
|
233
317
|
["path", { d: "M5 12h14", key: "1ays0h" }],
|
|
234
318
|
["path", { d: "m12 5 7 7-7 7", key: "xquz4c" }]
|
|
235
319
|
];
|
|
236
|
-
const ArrowRight = createLucideIcon("arrow-right", __iconNode$
|
|
320
|
+
const ArrowRight = createLucideIcon("arrow-right", __iconNode$e);
|
|
237
321
|
|
|
238
322
|
/**
|
|
239
323
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -243,8 +327,8 @@ const ArrowRight = createLucideIcon("arrow-right", __iconNode$c);
|
|
|
243
327
|
*/
|
|
244
328
|
|
|
245
329
|
|
|
246
|
-
const __iconNode$
|
|
247
|
-
const Check = createLucideIcon("check", __iconNode$
|
|
330
|
+
const __iconNode$d = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]];
|
|
331
|
+
const Check = createLucideIcon("check", __iconNode$d);
|
|
248
332
|
|
|
249
333
|
/**
|
|
250
334
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -254,8 +338,8 @@ const Check = createLucideIcon("check", __iconNode$b);
|
|
|
254
338
|
*/
|
|
255
339
|
|
|
256
340
|
|
|
257
|
-
const __iconNode$
|
|
258
|
-
const ChevronDown = createLucideIcon("chevron-down", __iconNode$
|
|
341
|
+
const __iconNode$c = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
|
|
342
|
+
const ChevronDown = createLucideIcon("chevron-down", __iconNode$c);
|
|
259
343
|
|
|
260
344
|
/**
|
|
261
345
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -265,12 +349,12 @@ const ChevronDown = createLucideIcon("chevron-down", __iconNode$a);
|
|
|
265
349
|
*/
|
|
266
350
|
|
|
267
351
|
|
|
268
|
-
const __iconNode$
|
|
352
|
+
const __iconNode$b = [
|
|
269
353
|
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
270
354
|
["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
|
|
271
355
|
["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
|
|
272
356
|
];
|
|
273
|
-
const CircleAlert = createLucideIcon("circle-alert", __iconNode$
|
|
357
|
+
const CircleAlert = createLucideIcon("circle-alert", __iconNode$b);
|
|
274
358
|
|
|
275
359
|
/**
|
|
276
360
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -280,11 +364,11 @@ const CircleAlert = createLucideIcon("circle-alert", __iconNode$9);
|
|
|
280
364
|
*/
|
|
281
365
|
|
|
282
366
|
|
|
283
|
-
const __iconNode$
|
|
367
|
+
const __iconNode$a = [
|
|
284
368
|
["path", { d: "M21.801 10A10 10 0 1 1 17 3.335", key: "yps3ct" }],
|
|
285
369
|
["path", { d: "m9 11 3 3L22 4", key: "1pflzl" }]
|
|
286
370
|
];
|
|
287
|
-
const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$
|
|
371
|
+
const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$a);
|
|
288
372
|
|
|
289
373
|
/**
|
|
290
374
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -294,7 +378,7 @@ const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$8);
|
|
|
294
378
|
*/
|
|
295
379
|
|
|
296
380
|
|
|
297
|
-
const __iconNode$
|
|
381
|
+
const __iconNode$9 = [
|
|
298
382
|
[
|
|
299
383
|
"path",
|
|
300
384
|
{
|
|
@@ -312,7 +396,7 @@ const __iconNode$7 = [
|
|
|
312
396
|
],
|
|
313
397
|
["path", { d: "m2 2 20 20", key: "1ooewy" }]
|
|
314
398
|
];
|
|
315
|
-
const EyeOff = createLucideIcon("eye-off", __iconNode$
|
|
399
|
+
const EyeOff = createLucideIcon("eye-off", __iconNode$9);
|
|
316
400
|
|
|
317
401
|
/**
|
|
318
402
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -322,7 +406,7 @@ const EyeOff = createLucideIcon("eye-off", __iconNode$7);
|
|
|
322
406
|
*/
|
|
323
407
|
|
|
324
408
|
|
|
325
|
-
const __iconNode$
|
|
409
|
+
const __iconNode$8 = [
|
|
326
410
|
[
|
|
327
411
|
"path",
|
|
328
412
|
{
|
|
@@ -332,7 +416,7 @@ const __iconNode$6 = [
|
|
|
332
416
|
],
|
|
333
417
|
["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
|
|
334
418
|
];
|
|
335
|
-
const Eye = createLucideIcon("eye", __iconNode$
|
|
419
|
+
const Eye = createLucideIcon("eye", __iconNode$8);
|
|
336
420
|
|
|
337
421
|
/**
|
|
338
422
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -342,7 +426,7 @@ const Eye = createLucideIcon("eye", __iconNode$6);
|
|
|
342
426
|
*/
|
|
343
427
|
|
|
344
428
|
|
|
345
|
-
const __iconNode$
|
|
429
|
+
const __iconNode$7 = [
|
|
346
430
|
[
|
|
347
431
|
"path",
|
|
348
432
|
{
|
|
@@ -351,7 +435,7 @@ const __iconNode$5 = [
|
|
|
351
435
|
}
|
|
352
436
|
]
|
|
353
437
|
];
|
|
354
|
-
const Heart = createLucideIcon("heart", __iconNode$
|
|
438
|
+
const Heart = createLucideIcon("heart", __iconNode$7);
|
|
355
439
|
|
|
356
440
|
/**
|
|
357
441
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -361,11 +445,31 @@ const Heart = createLucideIcon("heart", __iconNode$5);
|
|
|
361
445
|
*/
|
|
362
446
|
|
|
363
447
|
|
|
364
|
-
const __iconNode$
|
|
448
|
+
const __iconNode$6 = [
|
|
449
|
+
[
|
|
450
|
+
"path",
|
|
451
|
+
{
|
|
452
|
+
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",
|
|
453
|
+
key: "1a8usu"
|
|
454
|
+
}
|
|
455
|
+
],
|
|
456
|
+
["path", { d: "m15 5 4 4", key: "1mk7zo" }]
|
|
457
|
+
];
|
|
458
|
+
const Pencil = createLucideIcon("pencil", __iconNode$6);
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* @license lucide-react v0.544.0 - ISC
|
|
462
|
+
*
|
|
463
|
+
* This source code is licensed under the ISC license.
|
|
464
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
465
|
+
*/
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
const __iconNode$5 = [
|
|
365
469
|
["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
|
|
366
470
|
["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
|
|
367
471
|
];
|
|
368
|
-
const Search = createLucideIcon("search", __iconNode$
|
|
472
|
+
const Search = createLucideIcon("search", __iconNode$5);
|
|
369
473
|
|
|
370
474
|
/**
|
|
371
475
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -375,14 +479,29 @@ const Search = createLucideIcon("search", __iconNode$4);
|
|
|
375
479
|
*/
|
|
376
480
|
|
|
377
481
|
|
|
378
|
-
const __iconNode$
|
|
482
|
+
const __iconNode$4 = [
|
|
379
483
|
["path", { d: "M11 2v2", key: "1539x4" }],
|
|
380
484
|
["path", { d: "M5 2v2", key: "1yf1q8" }],
|
|
381
485
|
["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" }],
|
|
382
486
|
["path", { d: "M8 15a6 6 0 0 0 12 0v-3", key: "x18d4x" }],
|
|
383
487
|
["circle", { cx: "20", cy: "10", r: "2", key: "ts1r5v" }]
|
|
384
488
|
];
|
|
385
|
-
const Stethoscope = createLucideIcon("stethoscope", __iconNode$
|
|
489
|
+
const Stethoscope = createLucideIcon("stethoscope", __iconNode$4);
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* @license lucide-react v0.544.0 - ISC
|
|
493
|
+
*
|
|
494
|
+
* This source code is licensed under the ISC license.
|
|
495
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
496
|
+
*/
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
const __iconNode$3 = [
|
|
500
|
+
["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6", key: "miytrc" }],
|
|
501
|
+
["path", { d: "M3 6h18", key: "d0wm0j" }],
|
|
502
|
+
["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2", key: "e791ji" }]
|
|
503
|
+
];
|
|
504
|
+
const Trash = createLucideIcon("trash", __iconNode$3);
|
|
386
505
|
|
|
387
506
|
/**
|
|
388
507
|
* @license lucide-react v0.544.0 - ISC
|
|
@@ -457,7 +576,7 @@ const UserIcon = ({ size = 24, color = "currentColor", className = "", ...props
|
|
|
457
576
|
return jsxRuntime.jsx(User, { size: size, color: color, className: className, ...props });
|
|
458
577
|
};
|
|
459
578
|
|
|
460
|
-
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) => {
|
|
579
|
+
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) => {
|
|
461
580
|
const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`;
|
|
462
581
|
const hasError = Boolean(error);
|
|
463
582
|
const actualVariant = hasError ? "error" : variant;
|
|
@@ -516,7 +635,7 @@ const Input = React.forwardRef(({ className, variant = "default", size = "md", l
|
|
|
516
635
|
countryCodeSelect.onChange(item.code);
|
|
517
636
|
setIsDropdownOpen(false);
|
|
518
637
|
}, 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: [jsxRuntime.jsx("span", { className: "font-medium", children: item.code }), item.country && (jsxRuntime.jsx("span", { className: cn("ml-2 text-xs", isSelected ? "text-white/80" : "text-ews-gray-500"), children: item.country }))] }, item.code));
|
|
519
|
-
}) }))] }) })), leftIcon && !countryCodeSelect && (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], countryCodeSelect && "pl-24", leftIcon && !countryCodeSelect && "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 }))] }));
|
|
638
|
+
}) }))] }) })), leftIcon && !countryCodeSelect && !leftAddon && (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 }) })), leftAddon && !countryCodeSelect && !leftIcon && (jsxRuntime.jsx("div", { className: "flex absolute inset-y-0 left-0 items-center pointer-events-none overflow-hidden rounded-l-md", children: jsxRuntime.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 }) })), jsxRuntime.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 && (jsxRuntime.jsx("div", { className: "flex absolute inset-y-0 right-0 items-center pr-3 pointer-events-none", children: jsxRuntime.jsx("span", { className: "text-sm font-medium text-ews-gray-500", children: rightAddon }) })), 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 }))] }));
|
|
520
639
|
});
|
|
521
640
|
Input.displayName = "Input";
|
|
522
641
|
|
|
@@ -1712,6 +1831,65 @@ const Modal = ({ isOpen, onClose, title, children, variant = "info", size = "md"
|
|
|
1712
1831
|
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 }))] }))] })] }));
|
|
1713
1832
|
};
|
|
1714
1833
|
|
|
1834
|
+
const SIZE_CLASSES = {
|
|
1835
|
+
sm: "h-10 w-10",
|
|
1836
|
+
md: "h-16 w-16",
|
|
1837
|
+
lg: "h-32 w-32",
|
|
1838
|
+
};
|
|
1839
|
+
const INDICATOR_CLASSES = {
|
|
1840
|
+
sm: "h-2 w-2",
|
|
1841
|
+
md: "h-4 w-4",
|
|
1842
|
+
lg: "h-8 w-8",
|
|
1843
|
+
};
|
|
1844
|
+
function UploadProgressBar({ progress, isLoading, }) {
|
|
1845
|
+
const [visible, setVisible] = React.useState(false);
|
|
1846
|
+
React.useEffect(() => {
|
|
1847
|
+
if (isLoading) {
|
|
1848
|
+
setVisible(true);
|
|
1849
|
+
return;
|
|
1850
|
+
}
|
|
1851
|
+
// isLoading just turned false
|
|
1852
|
+
if (progress >= 100) {
|
|
1853
|
+
setVisible(true);
|
|
1854
|
+
const t = setTimeout(() => setVisible(false), 1000);
|
|
1855
|
+
return () => clearTimeout(t);
|
|
1856
|
+
}
|
|
1857
|
+
// Legacy path (no isLoading prop): driven purely by progress
|
|
1858
|
+
if (progress > 0 && progress < 100) {
|
|
1859
|
+
setVisible(true);
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1862
|
+
setVisible(false);
|
|
1863
|
+
}, [progress, isLoading]);
|
|
1864
|
+
if (!visible)
|
|
1865
|
+
return null;
|
|
1866
|
+
const indeterminate = isLoading && progress === 0;
|
|
1867
|
+
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}%` } }) }));
|
|
1868
|
+
}
|
|
1869
|
+
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, }) => {
|
|
1870
|
+
const fileInputRef = React.useRef(null);
|
|
1871
|
+
const [isHovered, setIsHovered] = React.useState(false);
|
|
1872
|
+
const [showConfirm, setShowConfirm] = React.useState(false);
|
|
1873
|
+
const handleEditClick = () => fileInputRef.current?.click();
|
|
1874
|
+
const handleFileChange = (e) => {
|
|
1875
|
+
const file = e.target.files?.[0];
|
|
1876
|
+
if (!file)
|
|
1877
|
+
return;
|
|
1878
|
+
if (file.size > maxFileSizeMB * 1024 * 1024) {
|
|
1879
|
+
onFileSizeExceeded?.();
|
|
1880
|
+
e.target.value = "";
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1883
|
+
onFileSelect(file);
|
|
1884
|
+
e.target.value = ""; // allow re-selecting the same file
|
|
1885
|
+
};
|
|
1886
|
+
const handleConfirmDelete = () => {
|
|
1887
|
+
setShowConfirm(false);
|
|
1888
|
+
onDeleteConfirm();
|
|
1889
|
+
};
|
|
1890
|
+
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 }) })] }));
|
|
1891
|
+
};
|
|
1892
|
+
|
|
1715
1893
|
const DropdownMultiSelect = ({ options, name, control, placeholder = "Select options", searchPlaceholder = "Search...", onChange, value: controlledValue, defaultValue, onValidate, disabled = false, error, label, className, }) => {
|
|
1716
1894
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
1717
1895
|
const [searchTerm, setSearchTerm] = React.useState("");
|
|
@@ -1999,6 +2177,7 @@ const SpecialtySearchAutocomplete = ({ selectedSpecialties = [], onSpecialtiesCh
|
|
|
1999
2177
|
};
|
|
2000
2178
|
|
|
2001
2179
|
exports.ArrowRight = ArrowRight;
|
|
2180
|
+
exports.BLOOD_TYPES = BLOOD_TYPES;
|
|
2002
2181
|
exports.Button = Button;
|
|
2003
2182
|
exports.Check = Check;
|
|
2004
2183
|
exports.DoctorIcon = DoctorIcon;
|
|
@@ -2009,6 +2188,7 @@ exports.Logo = Logo;
|
|
|
2009
2188
|
exports.Modal = Modal;
|
|
2010
2189
|
exports.MultiSearchAutocomplete = MultiSearchAutocomplete;
|
|
2011
2190
|
exports.PatientIcon = PatientIcon;
|
|
2191
|
+
exports.ProfileImageUpload = ProfileImageUpload;
|
|
2012
2192
|
exports.Search = Search;
|
|
2013
2193
|
exports.SearchAutocomplete = SearchAutocomplete;
|
|
2014
2194
|
exports.Select = Select;
|
|
@@ -2018,6 +2198,7 @@ exports.ThemeProvider = ThemeProvider;
|
|
|
2018
2198
|
exports.ThemeToggle = ThemeToggle;
|
|
2019
2199
|
exports.UserIcon = UserIcon;
|
|
2020
2200
|
exports.cn = cn;
|
|
2201
|
+
exports.createEnvConfig = createEnvConfig;
|
|
2021
2202
|
exports.debounce = debounce;
|
|
2022
2203
|
exports.formatCurrency = formatCurrency;
|
|
2023
2204
|
exports.formatDate = formatDate;
|