ml-ui-lib 1.0.4 → 1.0.6

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.
@@ -1,179 +0,0 @@
1
- import React, { useState, useEffect, useRef } from "react";
2
- import "./DatePicker2.css";
3
-
4
- export interface DateValue {
5
- month: number;
6
- day: number;
7
- year: number;
8
- }
9
-
10
- export interface DatePicker2Props {
11
- value?: DateValue;
12
- onChange?: (date: DateValue) => void;
13
- }
14
-
15
- export const DatePicker2: React.FC<DatePicker2Props> = ({ value, onChange }) => {
16
- const currentYear = new Date().getFullYear();
17
- const months = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"];
18
-
19
- const [year, setYear] = useState<number | null>(null);
20
- const [month, setMonth] = useState<number | null>(null);
21
- const [monthLabel, setMonthLabel] = useState<string | null>(null);
22
- const [day, setDay] = useState<number | null>(null);
23
- const [daysInMonth, setDaysInMonth] = useState<number[]>([]);
24
-
25
-
26
- useEffect(() => {
27
- if (month && day && year && onChange) {
28
- const newDate = { month, day, year };
29
- // Only call onChange if different
30
- if (
31
- !value ||
32
- value.month !== month ||
33
- value.day !== day ||
34
- value.year !== year
35
- ) {
36
- onChange(newDate);
37
- }
38
- }
39
- }, [month, day, year]);
40
-
41
-
42
- useEffect(() => {
43
- if (value) {
44
- setYear(value.year);
45
- setMonth(value.month);
46
- setDay(value.day);
47
- setMonthLabel(months[value.month - 1]);
48
- }
49
- }, [value]);
50
-
51
- const [yearOpen, setYearOpen] = useState(false);
52
- const [monthOpen, setMonthOpen] = useState(false);
53
- const [dayOpen, setDayOpen] = useState(false);
54
- const wrapperRef = useRef<HTMLDivElement>(null);
55
-
56
- useEffect(() => {
57
- const handleClickOutside = (e: MouseEvent) => {
58
- if (wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {
59
- setYearOpen(false);
60
- setMonthOpen(false);
61
- setDayOpen(false);
62
- }
63
- };
64
- document.addEventListener("mousedown", handleClickOutside);
65
- return () => document.removeEventListener("mousedown", handleClickOutside);
66
- }, []);
67
-
68
- // Update days in month
69
- useEffect(() => {
70
- if (month && year) {
71
- const totalDays = new Date(year, month, 0).getDate();
72
- setDaysInMonth([...Array(totalDays)].map((_, i) => i + 1));
73
- if (day && day > totalDays) setDay(totalDays);
74
- } else {
75
- setDaysInMonth([]);
76
- setDay(null);
77
- }
78
- }, [month, year]);
79
-
80
- // Trigger onChange
81
- useEffect(() => {
82
- if (year && month && day && onChange) {
83
- onChange({ year, month, day });
84
- }
85
- }, [year, month, day, onChange]);
86
-
87
- return (
88
- <div className="date-picker-wrapper" ref={wrapperRef}>
89
- {/* Year */}
90
- <div className="full-width">
91
- <div className="date-picker-dropdown" onClick={() => { setYearOpen(!yearOpen); setMonthOpen(false); setDayOpen(false); }}>
92
- <span className="readble">{year ?? "Year"}</span>
93
- <span className="date-picker-dropdown-carret">▼</span>
94
- </div>
95
- {yearOpen && (
96
- <div className="date-picker-grid-wrapper">
97
- <div className="date-picker-header">
98
- <span>Select Year</span>
99
- <button onClick={() => setYearOpen(false)}>✕</button>
100
- </div>
101
- <div className="date-picker-grid scrollbar">
102
- {[...Array(100)].map((_, i) => {
103
- const y = currentYear - i;
104
- return (
105
- <div
106
- key={y}
107
- className={`date-picker-dropdown-option ${y === year ? "selected" : ""}`}
108
- onClick={() => { setYear(y); setYearOpen(false); setMonthOpen(true); }}
109
- >
110
- {y}
111
- </div>
112
- );
113
- })}
114
- </div>
115
- </div>
116
- )}
117
- </div>
118
-
119
- {/* Month */}
120
- <div className="full-width">
121
- <div className="date-picker-dropdown" onClick={() => { setMonthOpen(!monthOpen); setYearOpen(false); setDayOpen(false); }}>
122
- <span className="readble">{monthLabel ?? "Month"}</span>
123
- <span className="date-picker-dropdown-carret">▼</span>
124
- </div>
125
- {monthOpen && (
126
- <div className="date-picker-grid-wrapper">
127
- <div className="date-picker-header">
128
- <span>Select Month</span>
129
- <button onClick={() => setMonthOpen(false)}>✕</button>
130
- </div>
131
- <div className="date-picker-grid scrollbar">
132
- {months.map((m, idx) => (
133
- <div
134
- key={idx}
135
- className={`date-picker-dropdown-option ${month === idx + 1 ? "selected" : ""}`}
136
- onClick={() => { setMonth(idx + 1); setMonthLabel(m); setMonthOpen(false); setDayOpen(true); }}
137
- >
138
- {m}
139
- </div>
140
- ))}
141
- </div>
142
- </div>
143
- )}
144
- </div>
145
-
146
- {/* Day */}
147
- <div className="full-width">
148
- <div className="date-picker-dropdown" onClick={() => { setDayOpen(!dayOpen); setMonthOpen(false); setYearOpen(false); }}>
149
- <span className="readble">{day ?? "Day"}</span>
150
- <span className="date-picker-dropdown-carret">▼</span>
151
- </div>
152
- {dayOpen && daysInMonth.length > 0 && (
153
- <div className="date-picker-grid-wrapper">
154
- <div className="date-picker-header">
155
- <span>Select Day</span>
156
- <button onClick={() => setDayOpen(false)}>✕</button>
157
- </div>
158
- <div className="date-picker-grid scrollbar">
159
- {daysInMonth.map((d) => (
160
- <div
161
- key={d}
162
- className={`date-picker-dropdown-option ${day === d ? "selected" : ""}`}
163
- onClick={() => {setDay(d); setDayOpen(false);}}
164
- >
165
- {d}
166
- </div>
167
- ))}
168
- </div>
169
- </div>
170
- )}
171
- {dayOpen && daysInMonth.length === 0 && (
172
- <div className="date-picker-empty">Select Year and Month first.</div>
173
- )}
174
- </div>
175
- </div>
176
- );
177
- };
178
-
179
- export default DatePicker2;
@@ -1,84 +0,0 @@
1
- .dropdown-wrapper {
2
- position: relative;
3
- display: flex;
4
- flex-direction: column;
5
- font-family: "Poppins", sans-serif;
6
- gap: 4px;
7
- }
8
-
9
- .dropdown-label {
10
- font-size: 14px;
11
- font-weight: 500;
12
- color: #333;
13
- }
14
-
15
- .dropdown-trigger {
16
- display: flex;
17
- justify-content: space-between;
18
- align-items: center;
19
- padding: 10px 12px;
20
- border: 1px solid #ddd;
21
- border-radius: 6px;
22
- background: #fff;
23
- cursor: pointer;
24
- transition: border-color 0.2s;
25
- }
26
-
27
- .dropdown-trigger:hover {
28
- border-color: #888;
29
- }
30
-
31
- .dropdown-value {
32
- font-size: 15px;
33
- color: #333;
34
- }
35
-
36
- .dropdown-caret {
37
- font-size: 12px;
38
- color: #666;
39
- }
40
-
41
- .dropdown-list {
42
- position: absolute;
43
- top: 100%;
44
- left: 0;
45
- width: 100%;
46
- background: #fff;
47
- border: 1px solid #ddd;
48
- border-radius: 6px;
49
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
50
- z-index: 10;
51
- max-height: 200px;
52
- overflow-y: auto;
53
- margin-top: 4px;
54
- }
55
-
56
- .dropdown-option {
57
- padding: 8px 12px;
58
- cursor: pointer;
59
- transition: background 0.2s;
60
- }
61
-
62
- .dropdown-option:hover {
63
- background: #f5f5f5;
64
- }
65
-
66
- .dropdown-option.selected {
67
- background: #ff4d4d10;
68
- font-weight: 500;
69
- }
70
-
71
- .dropdown-empty {
72
- padding: 8px 12px;
73
- color: #999;
74
- }
75
-
76
- .dropdown-error {
77
- margin-top: 4px;
78
- color: #ff4d4d;
79
- font-size: 13px;
80
- }
81
-
82
- .has-error .dropdown-trigger {
83
- border-color: #ff4d4d;
84
- }
@@ -1,76 +0,0 @@
1
- import React, { useState, useRef, useEffect } from "react";
2
- import "./Dropdown.css";
3
-
4
- export interface DropdownProps {
5
- label?: string;
6
- options: string[];
7
- value: string;
8
- onChange: (value: string) => void;
9
- placeholder?: string;
10
- className?: string;
11
- error?: string;
12
- }
13
-
14
- export const Dropdown: React.FC<DropdownProps> = ({
15
- label,
16
- value,
17
- options,
18
- onChange,
19
- placeholder = "Select",
20
- className = "",
21
- error,
22
- }) => {
23
- const [dropdownOpen, setDropdownOpen] = useState(false);
24
- const dropdownRef = useRef<HTMLDivElement>(null);
25
-
26
- useEffect(() => {
27
- const handleClickOutside = (e: MouseEvent) => {
28
- if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
29
- setDropdownOpen(false);
30
- }
31
- };
32
- document.addEventListener("mousedown", handleClickOutside);
33
- return () => document.removeEventListener("mousedown", handleClickOutside);
34
- }, []);
35
-
36
- return (
37
- <div className={`dropdown-wrapper ${className} ${error ? "has-error" : ""}`} ref={dropdownRef}>
38
- {label && <label className="dropdown-label">{label}</label>}
39
-
40
- <div
41
- className="dropdown-trigger"
42
- onClick={() => setDropdownOpen(!dropdownOpen)}
43
- >
44
- <span className="dropdown-value">
45
- {value === "" ? placeholder : value}
46
- </span>
47
- <span className="dropdown-caret">▼</span>
48
- </div>
49
-
50
- {dropdownOpen && (
51
- <div className="dropdown-list scrollbar">
52
- {options.length > 0 ? (
53
- options.map((option, i) => (
54
- <div
55
- key={i}
56
- className={`dropdown-option ${value === option ? "selected" : ""}`}
57
- onClick={() => {
58
- onChange(option);
59
- setDropdownOpen(false);
60
- }}
61
- >
62
- {option}
63
- </div>
64
- ))
65
- ) : (
66
- <div className="dropdown-empty">No options</div>
67
- )}
68
- </div>
69
- )}
70
-
71
- {error && <span className="dropdown-error">{error}</span>}
72
- </div>
73
- );
74
- };
75
-
76
- export default Dropdown;
@@ -1,36 +0,0 @@
1
- .input-wrapper {
2
- display: flex;
3
- flex-direction: column;
4
- gap: 6px;
5
- width: 100%;
6
- }
7
-
8
- .input-label {
9
- font-size: 14px;
10
- font-weight: 500;
11
- color: #333;
12
- }
13
-
14
- .input {
15
- font-family: 'Poppins', sans-serif;
16
- font-size: 15px;
17
- padding: 10px 12px;
18
- border: 1px solid #ccc;
19
- border-radius: 6px;
20
- outline: none;
21
- transition: all 0.2s ease;
22
- }
23
-
24
- .input:focus {
25
- border-color: #0070f3;
26
- box-shadow: 0 0 0 2px rgba(0, 112, 243, 0.2);
27
- }
28
-
29
- .input-error {
30
- border-color: #ff4d4f;
31
- }
32
-
33
- .input-error-text {
34
- color: #ff4d4f;
35
- font-size: 12px;
36
- }
@@ -1,24 +0,0 @@
1
- import React from "react";
2
- import "./Input.css";
3
-
4
- export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
5
- label?: string;
6
- error?: string;
7
- }
8
-
9
- export const Input: React.FC<InputProps> = ({ label, error, ...props }) => {
10
- return (
11
- <div className="input-wrapper">
12
- {label && <label className="input-label">{label}</label>}
13
- <input
14
- className={`input ${error ? "input-error" : ""}`}
15
- {...props}
16
- autoComplete="off"
17
- autoCorrect="off"
18
- autoCapitalize="off"
19
- spellCheck={false}
20
- />
21
- {error && <span className="input-error-text">{error}</span>}
22
- </div>
23
- );
24
- };
@@ -1,81 +0,0 @@
1
- .modal-overlay {
2
- position: fixed;
3
- inset: 0;
4
- background: rgba(0, 0, 0, 0.4);
5
- display: flex;
6
- justify-content: center;
7
- align-items: center;
8
- backdrop-filter: blur(4px);
9
- animation: fadeIn 0.25s ease;
10
- }
11
-
12
- .modal {
13
- background: #fff;
14
- border-radius: 10px;
15
- padding: 24px;
16
- max-width: 420px;
17
- width: 90%;
18
- box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
19
- font-family: "Poppins", sans-serif;
20
- animation: modalFadeIn 0.25s ease;
21
- border-top: 5px solid transparent;
22
- }
23
-
24
- .modal-header {
25
- display: flex;
26
- align-items: center;
27
- gap: 10px;
28
- margin-bottom: 16px;
29
- }
30
-
31
- .modal-icon {
32
- width: 26px;
33
- height: 26px;
34
- object-fit: contain;
35
- }
36
-
37
- .modal-title {
38
- font-size: 20px;
39
- font-weight: 600;
40
- }
41
-
42
- /* Variants */
43
- .modal-default {
44
- border-color: #ccc;
45
- }
46
-
47
- .modal-info {
48
- border-color: #3b82f6;
49
- }
50
-
51
- .modal-success {
52
- border-color: #22c55e;
53
- }
54
-
55
- .modal-warning {
56
- border-color: #f59e0b;
57
- }
58
-
59
- .modal-error {
60
- border-color: #ef4444;
61
- }
62
-
63
- @keyframes modalFadeIn {
64
- from {
65
- opacity: 0;
66
- transform: translateY(-10px);
67
- }
68
- to {
69
- opacity: 1;
70
- transform: translateY(0);
71
- }
72
- }
73
-
74
- @keyframes fadeIn {
75
- from {
76
- opacity: 0;
77
- }
78
- to {
79
- opacity: 1;
80
- }
81
- }
@@ -1,63 +0,0 @@
1
- import React, { useEffect } from "react";
2
- import "./Modal.css";
3
-
4
- // import DefaultIcon from "./icons/default.png";
5
- // import InfoIcon from "./icons/info.png";
6
- // import SuccessIcon from "./icons/success.png";
7
- // import WarningIcon from "./icons/error.png";
8
- import ErrorIcon from "./icons/error.png";
9
-
10
- export interface ModalProps {
11
- open: boolean;
12
- onClose: () => void;
13
- title?: string;
14
- children: React.ReactNode;
15
- zIndex?: number;
16
- variant?: "default" | "info" | "success" | "warning" | "error";
17
- }
18
-
19
- export const Modal: React.FC<ModalProps> = ({
20
- open,
21
- onClose,
22
- title,
23
- children,
24
- zIndex = 1000,
25
- variant = "default",
26
- }) => {
27
- useEffect(() => {
28
- document.body.style.overflow = open ? "hidden" : "";
29
- }, [open]);
30
-
31
- if (!open) return null;
32
-
33
- const variantIcon = {
34
- // default: DefaultIcon,
35
- // info: InfoIcon,
36
- // success: SuccessIcon,
37
- // warning: WarningIcon,
38
- error: ErrorIcon,
39
- }[variant];
40
-
41
-
42
- return (
43
- <div
44
- className="modal-overlay"
45
- onClick={onClose}
46
- style={{ zIndex }}
47
- >
48
- <div
49
- className={`modal modal-${variant}`}
50
- onClick={(e) => e.stopPropagation()}
51
- style={{ zIndex: zIndex + 1 }}
52
- >
53
- {title && (
54
- <div className="modal-header">
55
- {/* <img src={variantIcon} alt={variant} className="modal-icon" /> */}
56
- <h2 className="modal-title">{title}</h2>
57
- </div>
58
- )}
59
- <div className="modal-content">{children}</div>
60
- </div>
61
- </div>
62
- );
63
- };
@@ -1,78 +0,0 @@
1
- .phone-input-wrapper {
2
- position: relative;
3
- display: flex;
4
- align-items: center;
5
- gap: 8px;
6
- width: 100%;
7
- font-family: "Poppins", sans-serif;
8
- }
9
-
10
- .country-dropdown {
11
- display: flex;
12
- align-items: center;
13
- gap: 6px;
14
- padding: 10.5px 10px;
15
- border: 1px solid #ddd;
16
- border-radius: 6px;
17
- background: #fff;
18
- cursor: pointer;
19
- }
20
-
21
- .country-flag {
22
- width: 20px;
23
- height: 14px;
24
- border-radius: 2px;
25
- }
26
-
27
- .country-code {
28
- font-size: 15px;
29
- color: #333;
30
- }
31
-
32
- .country-dropdown-menu {
33
- position: absolute;
34
- top: 50px;
35
- left: 0;
36
- width: 180px;
37
- background: #fff;
38
- border: 1px solid #ddd;
39
- border-radius: 8px;
40
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
41
- z-index: 10;
42
- max-height: 200px;
43
- overflow-y: auto;
44
- }
45
-
46
- .country-dropdown-item {
47
- display: flex;
48
- align-items: center;
49
- justify-content: space-between;
50
- padding: 8px 10px;
51
- cursor: pointer;
52
- transition: background 0.2s;
53
- }
54
-
55
- .country-dropdown-item:hover {
56
- background: #f5f5f5;
57
- }
58
-
59
- .country-code-text {
60
- font-size: 13px;
61
- color: #777;
62
- }
63
-
64
- .phone-input {
65
- flex: 1;
66
- padding: 10px 14px;
67
- border: 1px solid #ddd;
68
- border-radius: 6px;
69
- font-size: 15px;
70
- font-family: inherit;
71
- outline: none;
72
- transition: border-color 0.2s, box-shadow 0.2s;
73
- }
74
-
75
- .phone-input:focus {
76
- border-color: #ff4d4d;
77
- box-shadow: 0 0 0 2px rgba(255, 0, 0, 0.1);
78
- }