@verma-consulting/design-library 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,1016 @@
1
+ // src/index.tsx
2
+ export * from "@mui/material";
3
+
4
+ // src/ClearableSelect.tsx
5
+ import React from "react";
6
+ import {
7
+ FormControl,
8
+ InputLabel,
9
+ Select,
10
+ InputAdornment,
11
+ IconButton,
12
+ OutlinedInput,
13
+ Typography,
14
+ FormLabel
15
+ } from "@mui/material";
16
+ import { Clear } from "@mui/icons-material";
17
+ import { makeStyles } from "@mui/styles";
18
+
19
+ // src/utils/common.ts
20
+ function prettifyString(input = "") {
21
+ if (input === "") return "";
22
+ let result = input.replace(/_/g, " ");
23
+ result = result.replace(/([a-z0-9])([A-Z])/g, "$1 $2");
24
+ result = result.split(" ").filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
25
+ return result;
26
+ }
27
+ var capitalizeSentence = (value) => {
28
+ if (!value || value === "") {
29
+ return "\u2013";
30
+ }
31
+ return value == null ? void 0 : value.replace(/\w\S*/g, (txt) => {
32
+ var _a, _b;
33
+ return ((_a = txt == null ? void 0 : txt.charAt(0)) == null ? void 0 : _a.toUpperCase()) + ((_b = txt == null ? void 0 : txt.substr(1)) == null ? void 0 : _b.toLowerCase());
34
+ });
35
+ };
36
+
37
+ // src/ClearableSelect.tsx
38
+ import { jsx, jsxs } from "react/jsx-runtime";
39
+ var useStyles = makeStyles((theme) => ({
40
+ defaultMode: {
41
+ paddingTop: 14,
42
+ paddingBottom: 14,
43
+ paddingLeft: 8,
44
+ paddingRight: 8,
45
+ cursor: "pointer",
46
+ "&:hover": {
47
+ borderRadius: 10,
48
+ boxShadow: "rgba(100, 100, 111, 0.2) 0px 7px 29px 0px"
49
+ }
50
+ },
51
+ formLabel: {
52
+ cursor: "pointer"
53
+ },
54
+ formValue: {
55
+ cursor: "pointer",
56
+ wordBreak: "break-word",
57
+ whiteSpace: "pre-wrap"
58
+ }
59
+ }));
60
+ var ClearableSelect = ({
61
+ name,
62
+ label,
63
+ value = "",
64
+ onChange,
65
+ size = "small",
66
+ style,
67
+ disabled = false,
68
+ onClear,
69
+ multiple = false,
70
+ defaultEditMode = false,
71
+ renderValue,
72
+ children
73
+ }) => {
74
+ const classes = useStyles();
75
+ const wrapperRef = React.useRef(null);
76
+ const [editMode, setEditMode] = React.useState(defaultEditMode);
77
+ React.useEffect(() => {
78
+ const handleClickOutside = (event) => {
79
+ if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
80
+ setEditMode(false);
81
+ }
82
+ };
83
+ if (editMode) {
84
+ document.addEventListener("mousedown", handleClickOutside);
85
+ }
86
+ return () => {
87
+ document.removeEventListener("mousedown", handleClickOutside);
88
+ };
89
+ }, [editMode]);
90
+ const isValueEmpty = multiple && Array.isArray(value) ? value.length === 0 : value === "";
91
+ const handleClear = (event) => {
92
+ event.stopPropagation();
93
+ if (onClear) {
94
+ onClear();
95
+ setEditMode(false);
96
+ } else {
97
+ const fakeEvent = {
98
+ target: { name, value: multiple ? [] : "" }
99
+ };
100
+ onChange(fakeEvent);
101
+ }
102
+ };
103
+ if (editMode) {
104
+ return /* @__PURE__ */ jsxs(
105
+ FormControl,
106
+ {
107
+ variant: "outlined",
108
+ size,
109
+ style,
110
+ disabled,
111
+ fullWidth: true,
112
+ children: [
113
+ /* @__PURE__ */ jsx(InputLabel, { id: `${name}-select-label`, children: label }),
114
+ /* @__PURE__ */ jsx(
115
+ Select,
116
+ {
117
+ labelId: `${name}-select-label`,
118
+ id: `${name}-select`,
119
+ name,
120
+ multiple,
121
+ value: multiple ? value == null ? void 0 : value.split(", ") : value,
122
+ onChange,
123
+ onBlur: () => setEditMode(false),
124
+ onClose: () => setEditMode(false),
125
+ label,
126
+ input: /* @__PURE__ */ jsx(
127
+ OutlinedInput,
128
+ {
129
+ size,
130
+ color: "primary",
131
+ endAdornment: onClear && !isValueEmpty ? /* @__PURE__ */ jsx(InputAdornment, { position: "end", sx: { gap: 1 }, children: /* @__PURE__ */ jsx(
132
+ IconButton,
133
+ {
134
+ "aria-label": `clear ${name}`,
135
+ onClick: handleClear,
136
+ edge: "end",
137
+ size: "small",
138
+ sx: { mr: 1 },
139
+ children: /* @__PURE__ */ jsx(Clear, { fontSize: "inherit" })
140
+ }
141
+ ) }) : null,
142
+ label,
143
+ name,
144
+ sx: {
145
+ paddingRight: !isValueEmpty ? 2 : void 0
146
+ }
147
+ }
148
+ ),
149
+ renderValue,
150
+ children
151
+ }
152
+ )
153
+ ]
154
+ }
155
+ );
156
+ }
157
+ return /* @__PURE__ */ jsxs(
158
+ "div",
159
+ {
160
+ onClick: () => {
161
+ if (!disabled) {
162
+ setEditMode(true);
163
+ }
164
+ },
165
+ className: classes.defaultMode,
166
+ children: [
167
+ /* @__PURE__ */ jsx(FormLabel, { className: classes.formLabel, children: label }),
168
+ /* @__PURE__ */ jsx(Typography, { className: classes.formValue, children: renderValue ? renderValue(value) : prettifyString(value) })
169
+ ]
170
+ }
171
+ );
172
+ };
173
+ var ClearableSelect_default = ClearableSelect;
174
+
175
+ // src/TabPanel.tsx
176
+ import { Box } from "@mui/material";
177
+ import { jsx as jsx2 } from "react/jsx-runtime";
178
+ var TabPanel = (props) => {
179
+ const { children, value, index, ...other } = props;
180
+ return /* @__PURE__ */ jsx2("div", { role: "tabpanel", hidden: value !== index, id: `simple-tabpanel-${index}`, ...other, children: value === index && /* @__PURE__ */ jsx2(Box, { sx: { p: 2 }, children }) });
181
+ };
182
+ var TabPanel_default = TabPanel;
183
+
184
+ // src/index.tsx
185
+ import { useTheme as useTheme6, styled as styled5, createTheme, ThemeProvider } from "@mui/material/styles";
186
+ import { makeStyles as makeStyles5 } from "@mui/styles";
187
+
188
+ // src/Logo.tsx
189
+ import { memo } from "react";
190
+ import {
191
+ Grid,
192
+ Typography as Typography2,
193
+ Avatar,
194
+ Tooltip,
195
+ Box as Box2,
196
+ useTheme,
197
+ useMediaQuery
198
+ } from "@mui/material";
199
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
200
+ var Logo = memo(
201
+ ({
202
+ loggedIn = false,
203
+ organization = null,
204
+ defaultLogo = null,
205
+ handleClick = () => null,
206
+ companyComponent = null
207
+ }) => {
208
+ var _a, _b;
209
+ const theme = useTheme();
210
+ const mdMatches = useMediaQuery(theme.breakpoints.down("md"));
211
+ const maxWidth = mdMatches ? 160 : 320;
212
+ const companyName = capitalizeSentence((_a = organization == null ? void 0 : organization.name) != null ? _a : "");
213
+ const logoUrl = (_b = organization == null ? void 0 : organization.logo) == null ? void 0 : _b.url;
214
+ return /* @__PURE__ */ jsxs2(
215
+ Grid,
216
+ {
217
+ container: true,
218
+ alignItems: "center",
219
+ wrap: "nowrap",
220
+ sx: {
221
+ cursor: "pointer",
222
+ "&:hover": { opacity: 0.9, transition: "opacity 0.2s ease-in-out" }
223
+ },
224
+ onClick: handleClick,
225
+ children: [
226
+ (logoUrl || defaultLogo) && /* @__PURE__ */ jsx3(Box2, { sx: { mr: 1, display: "flex", alignItems: "center" }, children: logoUrl ? /* @__PURE__ */ jsx3(
227
+ Avatar,
228
+ {
229
+ alt: companyName || "avatar",
230
+ src: logoUrl,
231
+ sx: {
232
+ width: 36,
233
+ height: 36,
234
+ bgcolor: "primary.main",
235
+ fontSize: 14,
236
+ fontWeight: "bold"
237
+ },
238
+ imgProps: { loading: "lazy" },
239
+ children: (companyName == null ? void 0 : companyName.charAt(0)) || "?"
240
+ }
241
+ ) : defaultLogo }),
242
+ /* @__PURE__ */ jsx3(Box2, { sx: { maxWidth, flexShrink: 1, minWidth: 0 }, children: loggedIn ? /* @__PURE__ */ jsx3(Tooltip, { title: companyName, placement: "top", arrow: true, children: /* @__PURE__ */ jsx3(
243
+ Typography2,
244
+ {
245
+ variant: "h6",
246
+ noWrap: true,
247
+ sx: {
248
+ textOverflow: "ellipsis",
249
+ overflow: "hidden",
250
+ whiteSpace: "nowrap",
251
+ fontFamily: "Courier, monospace",
252
+ fontWeight: "bold",
253
+ color: "primary.main"
254
+ },
255
+ children: companyName
256
+ }
257
+ ) }) : companyComponent })
258
+ ]
259
+ }
260
+ );
261
+ }
262
+ );
263
+ var Logo_default = Logo;
264
+
265
+ // src/FormDialog.tsx
266
+ import { styled } from "@mui/material/styles";
267
+ import {
268
+ useTheme as useTheme2,
269
+ Dialog,
270
+ DialogTitle,
271
+ DialogContent,
272
+ DialogActions,
273
+ IconButton as IconButton2,
274
+ useMediaQuery as useMediaQuery2
275
+ } from "@mui/material";
276
+ import { useTheme as useTheme3 } from "@mui/material/styles";
277
+ import { Close } from "@mui/icons-material";
278
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
279
+ var BootstrapDialog = styled(Dialog)(({ theme }) => ({
280
+ "& .MuiDialogContent-root": {
281
+ padding: theme.spacing(4)
282
+ },
283
+ "& .MuiDialogActions-root": {
284
+ padding: theme.spacing(4)
285
+ }
286
+ }));
287
+ var BootstrapDialogTitle = (props) => {
288
+ const { children, onClose, ...other } = props;
289
+ return /* @__PURE__ */ jsxs3(DialogTitle, { sx: { m: 2, p: 2 }, ...other, children: [
290
+ children,
291
+ onClose ? /* @__PURE__ */ jsx4(
292
+ IconButton2,
293
+ {
294
+ onClick: onClose,
295
+ sx: {
296
+ position: "absolute",
297
+ right: 8,
298
+ top: 8
299
+ },
300
+ children: /* @__PURE__ */ jsx4(Close, { color: "primary" })
301
+ }
302
+ ) : null
303
+ ] });
304
+ };
305
+ var FormDialog = ({ open = false, setOpen, title = "", actions, children, maxWidth = "lg", ...props }) => {
306
+ const theme = useTheme2();
307
+ const mdMatches = useMediaQuery2(theme.breakpoints.down("md"));
308
+ return /* @__PURE__ */ jsxs3(BootstrapDialog, { fullWidth: true, onClose: () => setOpen(false), open, maxWidth, fullScreen: mdMatches, children: [
309
+ /* @__PURE__ */ jsx4(BootstrapDialogTitle, { onClose: () => setOpen(false), children: title }),
310
+ /* @__PURE__ */ jsx4(DialogContent, { dividers: true, children }),
311
+ /* @__PURE__ */ jsx4(DialogActions, { children: actions })
312
+ ] });
313
+ };
314
+ var FormDialog_default = FormDialog;
315
+
316
+ // src/InputFileUpload.tsx
317
+ import { styled as styled2 } from "@mui/material/styles";
318
+ import { Button } from "@mui/material";
319
+ import { CloudUpload } from "@mui/icons-material";
320
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
321
+ var VisuallyHiddenInput = styled2("input")({
322
+ clip: "rect(0 0 0 0)",
323
+ clipPath: "inset(50%)",
324
+ height: 1,
325
+ overflow: "hidden",
326
+ position: "absolute",
327
+ bottom: 0,
328
+ left: 0,
329
+ whiteSpace: "nowrap",
330
+ width: 1
331
+ });
332
+ var InputFileUpload = ({ name = "", onChange = () => null, title = "" }) => /* @__PURE__ */ jsxs4(
333
+ Button,
334
+ {
335
+ role: void 0,
336
+ component: "label",
337
+ size: "small",
338
+ variant: "contained",
339
+ tabIndex: -1,
340
+ startIcon: /* @__PURE__ */ jsx5(CloudUpload, { fontSize: "inherit" }),
341
+ children: [
342
+ title,
343
+ /* @__PURE__ */ jsx5(VisuallyHiddenInput, { type: "file", name, onChange })
344
+ ]
345
+ }
346
+ );
347
+ var InputFileUpload_default = InputFileUpload;
348
+
349
+ // src/ImageUploadAvatar.tsx
350
+ import { useEffect, useRef, useState } from "react";
351
+ import { Box as Box3, IconButton as IconButton3 } from "@mui/material";
352
+ import { styled as styled3 } from "@mui/material/styles";
353
+ import { CloudUpload as CloudUpload2, Close as CloseIcon } from "@mui/icons-material";
354
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
355
+ var HiddenInput = styled3("input")({
356
+ position: "absolute",
357
+ width: 1,
358
+ height: 1,
359
+ padding: 0,
360
+ margin: -1,
361
+ overflow: "hidden",
362
+ clip: "rect(0 0 0 0)",
363
+ border: 0
364
+ });
365
+ var Wrapper = styled3(Box3, {
366
+ shouldForwardProp: (prop) => prop !== "variant" && prop !== "size"
367
+ })(({ theme, size, variant }) => ({
368
+ position: "relative",
369
+ width: size,
370
+ height: size,
371
+ borderRadius: variant === "circular" ? "50%" : variant === "rounded" ? theme.shape.borderRadius * 2 : 0,
372
+ border: `1px dashed ${theme.palette.grey[400]}`,
373
+ backgroundColor: theme.palette.grey[200],
374
+ overflow: "hidden",
375
+ cursor: "pointer",
376
+ display: "flex",
377
+ alignItems: "center",
378
+ justifyContent: "center"
379
+ }));
380
+ var PreviewImg = styled3("img")({
381
+ width: "100%",
382
+ height: "100%",
383
+ objectFit: "cover",
384
+ display: "block"
385
+ });
386
+ var Overlay = styled3(Box3)(({ theme }) => ({
387
+ position: "absolute",
388
+ inset: 0,
389
+ display: "flex",
390
+ alignItems: "center",
391
+ justifyContent: "center",
392
+ transition: "background 120ms ease",
393
+ borderRadius: "inherit",
394
+ "& .uploadIcon": {
395
+ opacity: 0,
396
+ transition: "opacity 120ms ease, transform 120ms ease",
397
+ transform: "scale(0.95)"
398
+ },
399
+ "&.empty .uploadIcon": {
400
+ opacity: 0.6,
401
+ transform: "scale(1)"
402
+ },
403
+ "&.hover": {
404
+ background: "rgba(0,0,0,0.15)",
405
+ "& .uploadIcon": { opacity: 1, transform: "scale(1)" }
406
+ }
407
+ }));
408
+ var ClearButton = styled3(IconButton3)(({ theme }) => ({
409
+ position: "absolute",
410
+ top: -8,
411
+ right: -8,
412
+ background: theme.palette.background.paper,
413
+ boxShadow: theme.shadows[2],
414
+ "&:hover": { background: theme.palette.background.paper }
415
+ }));
416
+ var ImageUploadAvatar = ({
417
+ name = "image",
418
+ defaultValue = null,
419
+ onChange,
420
+ size = 128,
421
+ variant = "rounded",
422
+ accept = "image/*",
423
+ disabled,
424
+ allowClear = true
425
+ }) => {
426
+ const inputRef = useRef(null);
427
+ const [internalSrc, setInternalSrc] = useState(defaultValue != null ? defaultValue : null);
428
+ const [hover, setHover] = useState(false);
429
+ useEffect(() => {
430
+ if (!defaultValue) return;
431
+ if (!internalSrc || !internalSrc.startsWith("blob:")) {
432
+ setInternalSrc(defaultValue);
433
+ }
434
+ }, [defaultValue]);
435
+ useEffect(() => {
436
+ return () => {
437
+ if (internalSrc == null ? void 0 : internalSrc.startsWith("blob:")) {
438
+ URL.revokeObjectURL(internalSrc);
439
+ }
440
+ };
441
+ }, [internalSrc]);
442
+ const handlePick = (e) => {
443
+ var _a, _b;
444
+ const selected = (_b = (_a = e.target.files) == null ? void 0 : _a[0]) != null ? _b : null;
445
+ if (internalSrc == null ? void 0 : internalSrc.startsWith("blob:")) {
446
+ URL.revokeObjectURL(internalSrc);
447
+ }
448
+ let preview = null;
449
+ if (selected) {
450
+ preview = URL.createObjectURL(selected);
451
+ setInternalSrc(preview);
452
+ } else {
453
+ setInternalSrc(null);
454
+ }
455
+ if (inputRef.current) inputRef.current.value = "";
456
+ onChange == null ? void 0 : onChange(selected, preview);
457
+ };
458
+ const triggerPick = () => {
459
+ var _a;
460
+ if (!disabled) (_a = inputRef.current) == null ? void 0 : _a.click();
461
+ };
462
+ const handleClear = (e) => {
463
+ e.stopPropagation();
464
+ if (internalSrc == null ? void 0 : internalSrc.startsWith("blob:")) {
465
+ URL.revokeObjectURL(internalSrc);
466
+ }
467
+ setInternalSrc(null);
468
+ onChange == null ? void 0 : onChange(null, null);
469
+ };
470
+ return /* @__PURE__ */ jsxs5(
471
+ Wrapper,
472
+ {
473
+ role: "button",
474
+ size,
475
+ variant,
476
+ onPointerEnter: () => setHover(true),
477
+ onPointerLeave: () => setHover(false),
478
+ onClick: triggerPick,
479
+ children: [
480
+ internalSrc && /* @__PURE__ */ jsx6(PreviewImg, { src: internalSrc }),
481
+ /* @__PURE__ */ jsx6(Overlay, { className: `${!internalSrc ? "empty" : ""} ${hover && !disabled ? "hover" : ""}`, children: /* @__PURE__ */ jsx6(CloudUpload2, { className: "uploadIcon", fontSize: "large" }) }),
482
+ allowClear && internalSrc && !disabled && /* @__PURE__ */ jsx6(ClearButton, { size: "small", "aria-label": "Clear image", onClick: handleClear, sx: { m: 1 }, children: /* @__PURE__ */ jsx6(CloseIcon, { fontSize: "inherit" }) }),
483
+ /* @__PURE__ */ jsx6(HiddenInput, { ref: inputRef, type: "file", name, accept, onChange: handlePick, disabled })
484
+ ]
485
+ }
486
+ );
487
+ };
488
+ var ImageUploadAvatar_default = ImageUploadAvatar;
489
+
490
+ // src/FormSnackBar.tsx
491
+ import { Snackbar, Alert, AlertTitle, Slide } from "@mui/material";
492
+ import { jsx as jsx7 } from "react/jsx-runtime";
493
+ var FormSnackBar = ({ snackBar = {}, setSnackBar = () => null }) => {
494
+ const getAlertStyles = () => {
495
+ if ((snackBar == null ? void 0 : snackBar.type) === "success") {
496
+ return { backgroundColor: "#65C466", color: "white" };
497
+ }
498
+ return {};
499
+ };
500
+ return /* @__PURE__ */ jsx7(
501
+ Snackbar,
502
+ {
503
+ sx: { width: "100%" },
504
+ autoHideDuration: 1e3,
505
+ anchorOrigin: { vertical: "top", horizontal: "center" },
506
+ open: (snackBar == null ? void 0 : snackBar.open) || false,
507
+ onClose: () => setSnackBar({
508
+ open: false,
509
+ message: "",
510
+ type: ""
511
+ }),
512
+ TransitionComponent: Slide,
513
+ children: /* @__PURE__ */ jsx7(
514
+ Alert,
515
+ {
516
+ sx: {
517
+ width: "100%",
518
+ display: "flex",
519
+ alignItems: "center",
520
+ justifyContent: "center",
521
+ textAlign: "center",
522
+ ...getAlertStyles()
523
+ },
524
+ variant: "filled",
525
+ severity: snackBar == null ? void 0 : snackBar.type,
526
+ children: /* @__PURE__ */ jsx7(AlertTitle, { sx: { m: 0, p: 0 }, children: snackBar == null ? void 0 : snackBar.message })
527
+ }
528
+ )
529
+ }
530
+ );
531
+ };
532
+ var FormSnackBar_default = FormSnackBar;
533
+
534
+ // src/Loader.tsx
535
+ import { CircularProgress, Backdrop } from "@mui/material";
536
+ import { makeStyles as makeStyles2 } from "@mui/styles";
537
+ import { jsx as jsx8 } from "react/jsx-runtime";
538
+ var useStyles2 = makeStyles2({
539
+ "@keyframes pulse": {
540
+ "0%": { transform: "scale(1)", opacity: 0.9 },
541
+ "50%": { transform: "scale(1.05)", opacity: 1 },
542
+ "100%": { transform: "scale(1)", opacity: 0.9 }
543
+ },
544
+ progress: {
545
+ animation: "$pulse 1.5s ease-in-out infinite"
546
+ }
547
+ });
548
+ var Loader = ({ size = 48, color = "primary" }) => {
549
+ const classes = useStyles2();
550
+ return /* @__PURE__ */ jsx8(
551
+ Backdrop,
552
+ {
553
+ open: true,
554
+ sx: {
555
+ zIndex: (theme) => theme.zIndex.modal + 1,
556
+ backgroundColor: "rgba(255, 255, 255, 0.15)",
557
+ backdropFilter: "blur(2px)"
558
+ },
559
+ children: /* @__PURE__ */ jsx8(CircularProgress, { size, color, thickness: 3.5, className: classes.progress })
560
+ }
561
+ );
562
+ };
563
+ var Loader_default = Loader;
564
+
565
+ // src/Pill.tsx
566
+ import { Button as Button2, Typography as Typography3, Icon, useTheme as useTheme4 } from "@mui/material";
567
+ import { makeStyles as makeStyles3 } from "@mui/styles";
568
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
569
+ var useStyles3 = makeStyles3((theme) => ({
570
+ button: {
571
+ padding: "4px 8px 4px 8px",
572
+ color: "black",
573
+ borderColor: "black",
574
+ borderStyle: "solid",
575
+ border: "6px",
576
+ borderRadius: "24px !important",
577
+ "&:hover": {
578
+ color: theme.palette.primary[500]
579
+ }
580
+ }
581
+ }));
582
+ var Pill = ({
583
+ variant = "filter",
584
+ leftIcon = null,
585
+ rightIcon = null,
586
+ color = null,
587
+ isSelected = false,
588
+ onClick = () => null,
589
+ label = "",
590
+ disabled = false
591
+ }) => {
592
+ const theme = useTheme4();
593
+ const classes = useStyles3();
594
+ return /* @__PURE__ */ jsx9(
595
+ Button2,
596
+ {
597
+ variant: isSelected ? "contained" : "outlined",
598
+ color: color || "primary",
599
+ sx: {
600
+ borderRadius: "48px",
601
+ padding: "8px 24px",
602
+ textTransform: "none"
603
+ },
604
+ onClick,
605
+ children: /* @__PURE__ */ jsxs6("div", { style: { display: "flex", alignItems: "center" }, children: [
606
+ leftIcon && /* @__PURE__ */ jsx9(
607
+ Icon,
608
+ {
609
+ className: leftIcon,
610
+ fontSize: 14,
611
+ color: "inherit",
612
+ style: { paddingRight: 8 },
613
+ "data-testid": "pill-left-icon"
614
+ }
615
+ ),
616
+ /* @__PURE__ */ jsx9(Typography3, { variant: "subtitle", color: "inherit", fontWeight: "bold", children: label }),
617
+ rightIcon && /* @__PURE__ */ jsx9(
618
+ Icon,
619
+ {
620
+ className: rightIcon,
621
+ fontSize: 14,
622
+ color: "inherit",
623
+ style: { marginLeft: 8 },
624
+ "data-testid": "pill-right-icon"
625
+ }
626
+ )
627
+ ] })
628
+ }
629
+ );
630
+ };
631
+ var Pill_default = Pill;
632
+
633
+ // src/IOSSwitch.tsx
634
+ import { styled as styled4 } from "@mui/material/styles";
635
+ import Switch from "@mui/material/Switch";
636
+ import { jsx as jsx10 } from "react/jsx-runtime";
637
+ var IOSSwitch = styled4((props) => /* @__PURE__ */ jsx10(Switch, { focusVisibleClassName: ".Mui-focusVisible", disableRipple: true, ...props }))(({ theme }) => ({
638
+ width: 46,
639
+ height: 30,
640
+ padding: 0,
641
+ "& .MuiSwitch-switchBase": {
642
+ padding: 0,
643
+ margin: 2,
644
+ transitionDuration: "300ms",
645
+ "&.Mui-checked": {
646
+ transform: "translateX(16px)",
647
+ color: "#fff",
648
+ "& + .MuiSwitch-track": {
649
+ backgroundColor: theme.palette.primary.main,
650
+ opacity: 1,
651
+ border: 0
652
+ },
653
+ "&.Mui-disabled + .MuiSwitch-track": {
654
+ opacity: 0.5
655
+ }
656
+ },
657
+ "&.Mui-focusVisible .MuiSwitch-thumb": {
658
+ color: "#33cf4d",
659
+ border: "6px solid #fff"
660
+ },
661
+ "&.Mui-disabled .MuiSwitch-thumb": {
662
+ color: theme.palette.mode === "light" ? theme.palette.grey[100] : theme.palette.grey[600]
663
+ },
664
+ "&.Mui-disabled + .MuiSwitch-track": {
665
+ opacity: theme.palette.mode === "light" ? 0.7 : 0.3
666
+ }
667
+ },
668
+ "& .MuiSwitch-thumb": {
669
+ boxSizing: "border-box",
670
+ width: 26,
671
+ height: 26
672
+ },
673
+ "& .MuiSwitch-track": {
674
+ borderRadius: 30 / 2,
675
+ backgroundColor: theme.palette.mode === "light" ? "#E9E9EA" : theme.palette.grey[600],
676
+ opacity: 1,
677
+ transition: theme.transitions.create(["background-color"], {
678
+ duration: 500
679
+ })
680
+ }
681
+ }));
682
+ var IOSSwitch_default = IOSSwitch;
683
+
684
+ // src/StatusPill.tsx
685
+ import { Chip } from "@mui/material";
686
+ import { jsx as jsx11 } from "react/jsx-runtime";
687
+ var statusColorMap = {
688
+ ["Pending" /* Pending */]: "warning",
689
+ ["Active" /* Active */]: "success",
690
+ ["Inactive" /* Inactive */]: "error",
691
+ ["Invited" /* Invited */]: "info"
692
+ };
693
+ var StatusPill = ({ status }) => /* @__PURE__ */ jsx11(
694
+ Chip,
695
+ {
696
+ label: status,
697
+ color: statusColorMap[status],
698
+ variant: "outlined",
699
+ sx: { fontWeight: 600, borderRadius: "16px", px: 1.5 }
700
+ }
701
+ );
702
+ var StatusPill_default = StatusPill;
703
+
704
+ // src/FormPopover.tsx
705
+ import { useState as useState2 } from "react";
706
+ import { Tooltip as Tooltip2, IconButton as IconButton4, Popover } from "@mui/material";
707
+ import { MoreHoriz } from "@mui/icons-material";
708
+ import { Fragment, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
709
+ var FormPopover = ({ row, children, title }) => {
710
+ const [anchorEl, setAnchorEl] = useState2(null);
711
+ const handleClick = (event) => {
712
+ setAnchorEl(event.currentTarget);
713
+ };
714
+ const handleClose = () => {
715
+ setAnchorEl(null);
716
+ };
717
+ const open = Boolean(anchorEl);
718
+ return /* @__PURE__ */ jsxs7(Fragment, { children: [
719
+ /* @__PURE__ */ jsx12(Tooltip2, { title, children: /* @__PURE__ */ jsx12(
720
+ IconButton4,
721
+ {
722
+ onClick: handleClick,
723
+ size: "small",
724
+ sx: {
725
+ backgroundColor: "white",
726
+ boxShadow: 1,
727
+ borderRadius: "50%",
728
+ border: "1px solid transparent",
729
+ "&:hover": {
730
+ border: (theme) => `1px solid ${theme.palette.primary.main}`,
731
+ backgroundColor: "#f0f0f0"
732
+ }
733
+ },
734
+ children: /* @__PURE__ */ jsx12(MoreHoriz, { fontSize: "inherit", color: "primary" })
735
+ }
736
+ ) }),
737
+ /* @__PURE__ */ jsx12(
738
+ Popover,
739
+ {
740
+ open,
741
+ anchorEl,
742
+ onClose: handleClose,
743
+ anchorOrigin: {
744
+ vertical: "bottom",
745
+ horizontal: "left"
746
+ },
747
+ children: children({ row, handleClose })
748
+ }
749
+ )
750
+ ] });
751
+ };
752
+ var FormPopover_default = FormPopover;
753
+
754
+ // src/SearchableSelect.tsx
755
+ import React5, { useEffect as useEffect2, useRef as useRef2, useState as useState3, useMemo } from "react";
756
+ import {
757
+ Autocomplete,
758
+ TextField,
759
+ Typography as Typography4,
760
+ FormLabel as FormLabel2,
761
+ FormControl as FormControl2,
762
+ IconButton as IconButton5
763
+ } from "@mui/material";
764
+ import { Clear as Clear2 } from "@mui/icons-material";
765
+ import { makeStyles as makeStyles4 } from "@mui/styles";
766
+ import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
767
+ var useStyles4 = makeStyles4(() => ({
768
+ defaultMode: {
769
+ padding: "14px 8px",
770
+ cursor: "pointer",
771
+ "&:hover": {
772
+ borderRadius: 10,
773
+ boxShadow: "rgba(100, 100, 111, 0.2) 0px 7px 29px 0px"
774
+ }
775
+ },
776
+ formLabel: {
777
+ cursor: "pointer"
778
+ },
779
+ formValue: {
780
+ cursor: "pointer",
781
+ wordBreak: "break-word",
782
+ whiteSpace: "pre-wrap"
783
+ }
784
+ }));
785
+ var SearchableSelect = React5.memo(
786
+ ({
787
+ name,
788
+ label,
789
+ value,
790
+ onChange,
791
+ options,
792
+ size = "small",
793
+ style,
794
+ disabled = false,
795
+ onClear,
796
+ defaultEditMode = false,
797
+ multiple = false
798
+ }) => {
799
+ const classes = useStyles4();
800
+ const wrapperRef = useRef2(null);
801
+ const inputRef = useRef2(null);
802
+ const [editMode, setEditMode] = useState3(defaultEditMode);
803
+ const [open, setOpen] = useState3(defaultEditMode);
804
+ useEffect2(() => {
805
+ function handleClickOutside(event) {
806
+ if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
807
+ setEditMode(false);
808
+ setOpen(false);
809
+ }
810
+ }
811
+ if (editMode) {
812
+ document.addEventListener("mousedown", handleClickOutside);
813
+ }
814
+ return () => {
815
+ document.removeEventListener("mousedown", handleClickOutside);
816
+ };
817
+ }, [editMode]);
818
+ useEffect2(() => {
819
+ if (editMode && open && inputRef.current) {
820
+ inputRef.current.focus();
821
+ }
822
+ }, [editMode, open]);
823
+ const handleClear = (event) => {
824
+ event.stopPropagation();
825
+ if (onClear) {
826
+ onClear();
827
+ } else {
828
+ onChange("");
829
+ }
830
+ setEditMode(false);
831
+ setOpen(false);
832
+ };
833
+ const selected = useMemo(() => {
834
+ var _a;
835
+ if (multiple) {
836
+ if (!value.trim()) return [];
837
+ const selectedValues = value.split(", ").map((v) => v.trim());
838
+ return options.filter((opt) => selectedValues.includes(opt.value));
839
+ } else {
840
+ return (_a = options.find((opt) => opt.value === value)) != null ? _a : null;
841
+ }
842
+ }, [value, options, multiple]);
843
+ const displayValue = useMemo(() => {
844
+ var _a;
845
+ if (multiple) {
846
+ if (!Array.isArray(selected)) return "";
847
+ return selected.map((opt) => opt.label).join(", ");
848
+ } else {
849
+ return (_a = selected == null ? void 0 : selected.label) != null ? _a : "";
850
+ }
851
+ }, [selected, multiple]);
852
+ const isValueEmpty = !value.trim();
853
+ return editMode ? /* @__PURE__ */ jsx13(FormControl2, { fullWidth: true, style, disabled, size, children: /* @__PURE__ */ jsx13(
854
+ Autocomplete,
855
+ {
856
+ multiple,
857
+ disableCloseOnSelect: multiple,
858
+ options,
859
+ value: selected,
860
+ open,
861
+ onOpen: () => setOpen(true),
862
+ onClose: () => setOpen(false),
863
+ onChange: (_, newValue) => {
864
+ var _a;
865
+ if (multiple) {
866
+ if (Array.isArray(newValue)) {
867
+ let vals = newValue == null ? void 0 : newValue.map((opt) => opt == null ? void 0 : opt.value);
868
+ let val = vals == null ? void 0 : vals.join(", ");
869
+ onChange(val);
870
+ } else {
871
+ onChange("");
872
+ }
873
+ setOpen(true);
874
+ } else {
875
+ onChange((_a = newValue == null ? void 0 : newValue.value) != null ? _a : "");
876
+ setOpen(false);
877
+ }
878
+ },
879
+ disableClearable: !onClear,
880
+ autoHighlight: true,
881
+ getOptionLabel: (option) => option.label,
882
+ isOptionEqualToValue: (option, val) => option.value === val.value,
883
+ renderInput: (params) => /* @__PURE__ */ jsx13(
884
+ TextField,
885
+ {
886
+ ...params,
887
+ label,
888
+ variant: "outlined",
889
+ size,
890
+ inputRef,
891
+ InputProps: {
892
+ ...params.InputProps,
893
+ endAdornment: /* @__PURE__ */ jsx13(Fragment2, { children: !isValueEmpty && /* @__PURE__ */ jsx13(
894
+ IconButton5,
895
+ {
896
+ "aria-label": `clear ${name}`,
897
+ onClick: handleClear,
898
+ size: "small",
899
+ sx: {
900
+ backgroundColor: "transparent",
901
+ boxShadow: "none"
902
+ },
903
+ children: /* @__PURE__ */ jsx13(Clear2, { fontSize: "inherit" })
904
+ }
905
+ ) })
906
+ }
907
+ }
908
+ ),
909
+ onBlur: () => {
910
+ setEditMode(false);
911
+ setOpen(false);
912
+ }
913
+ }
914
+ ) }) : /* @__PURE__ */ jsxs8(
915
+ "div",
916
+ {
917
+ ref: wrapperRef,
918
+ onClick: () => {
919
+ if (!disabled) {
920
+ setEditMode(true);
921
+ setOpen(true);
922
+ }
923
+ },
924
+ className: classes.defaultMode,
925
+ style,
926
+ children: [
927
+ /* @__PURE__ */ jsx13(FormLabel2, { className: classes.formLabel, children: label }),
928
+ /* @__PURE__ */ jsx13(Typography4, { className: classes.formValue, children: displayValue })
929
+ ]
930
+ }
931
+ );
932
+ }
933
+ );
934
+ var SearchableSelect_default = SearchableSelect;
935
+
936
+ // src/FormDrawer.tsx
937
+ import { Drawer, Typography as Typography5, Box as Box4, IconButton as IconButton6, Grid as Grid2, useTheme as useTheme5, useMediaQuery as useMediaQuery3 } from "@mui/material";
938
+ import { Close as Close2 } from "@mui/icons-material";
939
+ import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
940
+ var FormDrawer = ({ open, setOpen, title, actions, children }) => {
941
+ const theme = useTheme5();
942
+ const mdMatches = useMediaQuery3(theme.breakpoints.down("md"));
943
+ return /* @__PURE__ */ jsxs9(
944
+ Drawer,
945
+ {
946
+ anchor: mdMatches ? "bottom" : "right",
947
+ open,
948
+ onClose: setOpen,
949
+ sx: {
950
+ "& .MuiDrawer-paper": {
951
+ width: mdMatches ? "100%" : "56%",
952
+ height: "100%",
953
+ display: "flex",
954
+ flexDirection: "column",
955
+ borderRadius: 0
956
+ }
957
+ },
958
+ children: [
959
+ /* @__PURE__ */ jsx14(Box4, { p: 3, borderBottom: "1px solid #eee", children: /* @__PURE__ */ jsxs9(Grid2, { container: true, children: [
960
+ /* @__PURE__ */ jsx14(Grid2, { item: true, children: title && /* @__PURE__ */ jsx14(Typography5, { variant: "h6", fontWeight: "bold", children: title }) }),
961
+ /* @__PURE__ */ jsx14(Grid2, { item: true, children: /* @__PURE__ */ jsx14(
962
+ IconButton6,
963
+ {
964
+ size: "medium",
965
+ onClick: setOpen,
966
+ sx: {
967
+ position: "absolute",
968
+ top: 8,
969
+ right: 8,
970
+ zIndex: 2
971
+ },
972
+ children: /* @__PURE__ */ jsx14(Close2, { fontSize: "inherit" })
973
+ }
974
+ ) })
975
+ ] }) }),
976
+ /* @__PURE__ */ jsx14(Box4, { flex: 1, overflow: "auto", p: 3, children }),
977
+ actions && /* @__PURE__ */ jsx14(
978
+ Box4,
979
+ {
980
+ p: 2,
981
+ borderTop: "1px solid #eee",
982
+ sx: {
983
+ position: "sticky",
984
+ bottom: 0,
985
+ zIndex: 1
986
+ },
987
+ children: actions
988
+ }
989
+ )
990
+ ]
991
+ }
992
+ );
993
+ };
994
+ var FormDrawer_default = FormDrawer;
995
+ export {
996
+ ClearableSelect_default as ClearableSelect,
997
+ FormDialog_default as FormDialog,
998
+ FormDrawer_default as FormDrawer,
999
+ FormPopover_default as FormPopover,
1000
+ FormSnackBar_default as FormSnackBar,
1001
+ IOSSwitch_default as IOSSwitch,
1002
+ ImageUploadAvatar_default as ImageUploadAvatar,
1003
+ InputFileUpload_default as InputFileUpload,
1004
+ Loader_default as Loader,
1005
+ Logo_default as Logo,
1006
+ Pill_default as Pill,
1007
+ SearchableSelect_default as SearchableSelect,
1008
+ StatusPill_default as StatusPill,
1009
+ TabPanel_default as TabPanel,
1010
+ ThemeProvider,
1011
+ createTheme,
1012
+ makeStyles5 as makeStyles,
1013
+ styled5 as styled,
1014
+ useTheme6 as useTheme
1015
+ };
1016
+ //# sourceMappingURL=index.mjs.map