@syuttechnologies/layout 1.0.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/components/ChangePasswordModal.d.ts +24 -0
- package/dist/components/ChangePasswordModal.d.ts.map +1 -0
- package/dist/components/ChangePasswordModal.js +319 -0
- package/dist/components/EnterpriseLayout.d.ts +154 -0
- package/dist/components/EnterpriseLayout.d.ts.map +1 -0
- package/dist/components/EnterpriseLayout.js +2933 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/services/notificationService.d.ts +23 -0
- package/dist/services/notificationService.d.ts.map +1 -0
- package/dist/services/notificationService.js +72 -0
- package/package.json +27 -0
- package/src/components/ChangePasswordModal.tsx +545 -0
- package/src/components/EnterpriseLayout.tsx +4460 -0
- package/src/index.ts +53 -0
- package/src/services/notificationService.ts +101 -0
- package/tsconfig.json +20 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface ChangePasswordModalProps {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
onSubmit: (data: ChangePasswordData) => Promise<void> | void;
|
|
6
|
+
username?: string;
|
|
7
|
+
validationRules?: PasswordValidationRules;
|
|
8
|
+
isLoading?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface ChangePasswordData {
|
|
11
|
+
currentPassword: string;
|
|
12
|
+
newPassword: string;
|
|
13
|
+
confirmPassword: string;
|
|
14
|
+
}
|
|
15
|
+
export interface PasswordValidationRules {
|
|
16
|
+
minLength?: number;
|
|
17
|
+
requireUppercase?: boolean;
|
|
18
|
+
requireNumber?: boolean;
|
|
19
|
+
requireSpecialChar?: boolean;
|
|
20
|
+
preventUsernameMatch?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare const ChangePasswordModal: React.FC<ChangePasswordModalProps>;
|
|
23
|
+
export default ChangePasswordModal;
|
|
24
|
+
//# sourceMappingURL=ChangePasswordModal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChangePasswordModal.d.ts","sourceRoot":"","sources":["../../src/components/ChangePasswordModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAE9D,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAiSD,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAsOlE,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback, useMemo } from 'react';
|
|
3
|
+
const DEFAULT_VALIDATION_RULES = {
|
|
4
|
+
minLength: 6,
|
|
5
|
+
requireUppercase: true,
|
|
6
|
+
requireNumber: true,
|
|
7
|
+
requireSpecialChar: true,
|
|
8
|
+
preventUsernameMatch: true,
|
|
9
|
+
};
|
|
10
|
+
const validatePassword = (password, rules, username) => {
|
|
11
|
+
const errors = [];
|
|
12
|
+
if (password.length < rules.minLength) {
|
|
13
|
+
errors.push(`Password must be at least ${rules.minLength} characters`);
|
|
14
|
+
}
|
|
15
|
+
if (rules.requireUppercase && !/[A-Z]/.test(password)) {
|
|
16
|
+
errors.push('Password must contain at least one uppercase letter');
|
|
17
|
+
}
|
|
18
|
+
if (rules.requireNumber && !/[0-9]/.test(password)) {
|
|
19
|
+
errors.push('Password must contain at least one number');
|
|
20
|
+
}
|
|
21
|
+
if (rules.requireSpecialChar && !/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password)) {
|
|
22
|
+
errors.push('Password must contain at least one special character');
|
|
23
|
+
}
|
|
24
|
+
if (rules.preventUsernameMatch && username && password.toLowerCase() === username.toLowerCase()) {
|
|
25
|
+
errors.push('Password cannot be the same as username');
|
|
26
|
+
}
|
|
27
|
+
return errors;
|
|
28
|
+
};
|
|
29
|
+
const calculatePasswordStrength = (password) => {
|
|
30
|
+
let score = 0;
|
|
31
|
+
if (password.length >= 6)
|
|
32
|
+
score++;
|
|
33
|
+
if (password.length >= 10)
|
|
34
|
+
score++;
|
|
35
|
+
if (/[A-Z]/.test(password))
|
|
36
|
+
score++;
|
|
37
|
+
if (/[0-9]/.test(password))
|
|
38
|
+
score++;
|
|
39
|
+
if (/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password))
|
|
40
|
+
score++;
|
|
41
|
+
score = Math.min(4, Math.floor(score * 0.8));
|
|
42
|
+
const strengthMap = {
|
|
43
|
+
0: { label: 'Very Weak', color: '#ef4444' },
|
|
44
|
+
1: { label: 'Weak', color: '#f97316' },
|
|
45
|
+
2: { label: 'Fair', color: '#eab308' },
|
|
46
|
+
3: { label: 'Good', color: '#22c55e' },
|
|
47
|
+
4: { label: 'Strong', color: '#16a34a' },
|
|
48
|
+
};
|
|
49
|
+
return { score, ...strengthMap[score] };
|
|
50
|
+
};
|
|
51
|
+
const EyeIcon = () => (_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }), _jsx("circle", { cx: "12", cy: "12", r: "3" })] }));
|
|
52
|
+
const EyeOffIcon = () => (_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" }), _jsx("line", { x1: "1", y1: "1", x2: "23", y2: "23" })] }));
|
|
53
|
+
const CloseIcon = () => (_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }));
|
|
54
|
+
const LockIcon = () => (_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }), _jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })] }));
|
|
55
|
+
const CheckIcon = () => (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", children: _jsx("polyline", { points: "20 6 9 17 4 12" }) }));
|
|
56
|
+
const XIcon = () => (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }));
|
|
57
|
+
const styles = {
|
|
58
|
+
backdrop: {
|
|
59
|
+
position: 'fixed',
|
|
60
|
+
inset: 0,
|
|
61
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
62
|
+
zIndex: 9998,
|
|
63
|
+
},
|
|
64
|
+
modal: {
|
|
65
|
+
position: 'fixed',
|
|
66
|
+
top: '50%',
|
|
67
|
+
left: '50%',
|
|
68
|
+
transform: 'translate(-50%, -50%)',
|
|
69
|
+
backgroundColor: 'white',
|
|
70
|
+
borderRadius: '12px',
|
|
71
|
+
boxShadow: '0 20px 50px rgba(0, 0, 0, 0.3)',
|
|
72
|
+
width: '100%',
|
|
73
|
+
maxWidth: '440px',
|
|
74
|
+
zIndex: 9999,
|
|
75
|
+
overflow: 'hidden',
|
|
76
|
+
},
|
|
77
|
+
header: {
|
|
78
|
+
display: 'flex',
|
|
79
|
+
alignItems: 'center',
|
|
80
|
+
justifyContent: 'space-between',
|
|
81
|
+
padding: '1.25rem 1.5rem',
|
|
82
|
+
borderBottom: '1px solid #e2e8f0',
|
|
83
|
+
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
84
|
+
},
|
|
85
|
+
headerTitle: {
|
|
86
|
+
display: 'flex',
|
|
87
|
+
alignItems: 'center',
|
|
88
|
+
gap: '0.75rem',
|
|
89
|
+
color: 'white',
|
|
90
|
+
fontSize: '1.125rem',
|
|
91
|
+
fontWeight: 600,
|
|
92
|
+
margin: 0,
|
|
93
|
+
},
|
|
94
|
+
closeButton: {
|
|
95
|
+
background: 'rgba(255, 255, 255, 0.2)',
|
|
96
|
+
border: 'none',
|
|
97
|
+
borderRadius: '8px',
|
|
98
|
+
padding: '0.5rem',
|
|
99
|
+
cursor: 'pointer',
|
|
100
|
+
color: 'white',
|
|
101
|
+
display: 'flex',
|
|
102
|
+
alignItems: 'center',
|
|
103
|
+
justifyContent: 'center',
|
|
104
|
+
transition: 'background 0.2s',
|
|
105
|
+
},
|
|
106
|
+
content: {
|
|
107
|
+
padding: '1.5rem',
|
|
108
|
+
},
|
|
109
|
+
formGroup: {
|
|
110
|
+
marginBottom: '1.25rem',
|
|
111
|
+
},
|
|
112
|
+
label: {
|
|
113
|
+
display: 'block',
|
|
114
|
+
fontSize: '0.875rem',
|
|
115
|
+
fontWeight: 600,
|
|
116
|
+
color: '#334155',
|
|
117
|
+
marginBottom: '0.5rem',
|
|
118
|
+
},
|
|
119
|
+
inputWrapper: {
|
|
120
|
+
position: 'relative',
|
|
121
|
+
},
|
|
122
|
+
input: {
|
|
123
|
+
width: '100%',
|
|
124
|
+
padding: '0.75rem 2.75rem 0.75rem 1rem',
|
|
125
|
+
fontSize: '0.9375rem',
|
|
126
|
+
border: '2px solid #e2e8f0',
|
|
127
|
+
borderRadius: '8px',
|
|
128
|
+
outline: 'none',
|
|
129
|
+
transition: 'border-color 0.2s, box-shadow 0.2s',
|
|
130
|
+
boxSizing: 'border-box',
|
|
131
|
+
},
|
|
132
|
+
inputError: {
|
|
133
|
+
borderColor: '#ef4444',
|
|
134
|
+
},
|
|
135
|
+
inputFocus: {
|
|
136
|
+
borderColor: '#667eea',
|
|
137
|
+
boxShadow: '0 0 0 3px rgba(102, 126, 234, 0.1)',
|
|
138
|
+
},
|
|
139
|
+
toggleButton: {
|
|
140
|
+
position: 'absolute',
|
|
141
|
+
right: '0.75rem',
|
|
142
|
+
top: '50%',
|
|
143
|
+
transform: 'translateY(-50%)',
|
|
144
|
+
background: 'none',
|
|
145
|
+
border: 'none',
|
|
146
|
+
cursor: 'pointer',
|
|
147
|
+
color: '#64748b',
|
|
148
|
+
padding: '0.25rem',
|
|
149
|
+
display: 'flex',
|
|
150
|
+
alignItems: 'center',
|
|
151
|
+
justifyContent: 'center',
|
|
152
|
+
},
|
|
153
|
+
strengthMeter: {
|
|
154
|
+
marginTop: '0.5rem',
|
|
155
|
+
},
|
|
156
|
+
strengthBar: {
|
|
157
|
+
height: '4px',
|
|
158
|
+
backgroundColor: '#e2e8f0',
|
|
159
|
+
borderRadius: '2px',
|
|
160
|
+
overflow: 'hidden',
|
|
161
|
+
marginBottom: '0.25rem',
|
|
162
|
+
},
|
|
163
|
+
strengthFill: {
|
|
164
|
+
height: '100%',
|
|
165
|
+
transition: 'width 0.3s, background-color 0.3s',
|
|
166
|
+
borderRadius: '2px',
|
|
167
|
+
},
|
|
168
|
+
strengthLabel: {
|
|
169
|
+
fontSize: '0.75rem',
|
|
170
|
+
fontWeight: 500,
|
|
171
|
+
},
|
|
172
|
+
requirements: {
|
|
173
|
+
marginTop: '0.75rem',
|
|
174
|
+
padding: '0.75rem',
|
|
175
|
+
backgroundColor: '#f8fafc',
|
|
176
|
+
borderRadius: '8px',
|
|
177
|
+
border: '1px solid #e2e8f0',
|
|
178
|
+
},
|
|
179
|
+
requirementsTitle: {
|
|
180
|
+
fontSize: '0.75rem',
|
|
181
|
+
fontWeight: 600,
|
|
182
|
+
color: '#64748b',
|
|
183
|
+
marginBottom: '0.5rem',
|
|
184
|
+
textTransform: 'uppercase',
|
|
185
|
+
letterSpacing: '0.05em',
|
|
186
|
+
},
|
|
187
|
+
requirementItem: {
|
|
188
|
+
display: 'flex',
|
|
189
|
+
alignItems: 'center',
|
|
190
|
+
gap: '0.5rem',
|
|
191
|
+
fontSize: '0.8125rem',
|
|
192
|
+
marginBottom: '0.25rem',
|
|
193
|
+
},
|
|
194
|
+
errorText: {
|
|
195
|
+
color: '#ef4444',
|
|
196
|
+
fontSize: '0.8125rem',
|
|
197
|
+
marginTop: '0.375rem',
|
|
198
|
+
display: 'flex',
|
|
199
|
+
alignItems: 'center',
|
|
200
|
+
gap: '0.25rem',
|
|
201
|
+
},
|
|
202
|
+
footer: {
|
|
203
|
+
display: 'flex',
|
|
204
|
+
justifyContent: 'flex-end',
|
|
205
|
+
gap: '0.75rem',
|
|
206
|
+
padding: '1rem 1.5rem',
|
|
207
|
+
borderTop: '1px solid #e2e8f0',
|
|
208
|
+
backgroundColor: '#f8fafc',
|
|
209
|
+
},
|
|
210
|
+
button: {
|
|
211
|
+
padding: '0.625rem 1.25rem',
|
|
212
|
+
fontSize: '0.875rem',
|
|
213
|
+
fontWeight: 600,
|
|
214
|
+
borderRadius: '8px',
|
|
215
|
+
cursor: 'pointer',
|
|
216
|
+
transition: 'all 0.2s',
|
|
217
|
+
border: 'none',
|
|
218
|
+
},
|
|
219
|
+
cancelButton: {
|
|
220
|
+
backgroundColor: 'white',
|
|
221
|
+
color: '#64748b',
|
|
222
|
+
border: '1px solid #e2e8f0',
|
|
223
|
+
},
|
|
224
|
+
submitButton: {
|
|
225
|
+
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
226
|
+
color: 'white',
|
|
227
|
+
boxShadow: '0 2px 8px rgba(102, 126, 234, 0.3)',
|
|
228
|
+
},
|
|
229
|
+
submitButtonDisabled: {
|
|
230
|
+
background: '#cbd5e1',
|
|
231
|
+
cursor: 'not-allowed',
|
|
232
|
+
boxShadow: 'none',
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
export const ChangePasswordModal = ({ isOpen, onClose, onSubmit, username, validationRules, isLoading: externalLoading, }) => {
|
|
236
|
+
const [currentPassword, setCurrentPassword] = useState('');
|
|
237
|
+
const [newPassword, setNewPassword] = useState('');
|
|
238
|
+
const [confirmPassword, setConfirmPassword] = useState('');
|
|
239
|
+
const [showCurrentPassword, setShowCurrentPassword] = useState(false);
|
|
240
|
+
const [showNewPassword, setShowNewPassword] = useState(false);
|
|
241
|
+
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
|
|
242
|
+
const [errors, setErrors] = useState([]);
|
|
243
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
244
|
+
const [focusedField, setFocusedField] = useState(null);
|
|
245
|
+
const rules = useMemo(() => ({ ...DEFAULT_VALIDATION_RULES, ...validationRules }), [validationRules]);
|
|
246
|
+
const passwordStrength = useMemo(() => calculatePasswordStrength(newPassword), [newPassword]);
|
|
247
|
+
const requirements = useMemo(() => {
|
|
248
|
+
return [
|
|
249
|
+
{ id: 'length', label: `At least ${rules.minLength} characters`, met: newPassword.length >= rules.minLength },
|
|
250
|
+
{ id: 'uppercase', label: 'One uppercase letter', met: /[A-Z]/.test(newPassword), required: rules.requireUppercase },
|
|
251
|
+
{ id: 'number', label: 'One number', met: /[0-9]/.test(newPassword), required: rules.requireNumber },
|
|
252
|
+
{ id: 'special', label: 'One special character', met: /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(newPassword), required: rules.requireSpecialChar },
|
|
253
|
+
{ id: 'notUsername', label: 'Not same as username', met: !username || newPassword.toLowerCase() !== username.toLowerCase(), required: rules.preventUsernameMatch && !!username },
|
|
254
|
+
].filter((req) => req.required !== false);
|
|
255
|
+
}, [newPassword, rules, username]);
|
|
256
|
+
const isFormValid = useMemo(() => {
|
|
257
|
+
if (!currentPassword || !newPassword || !confirmPassword)
|
|
258
|
+
return false;
|
|
259
|
+
if (newPassword !== confirmPassword)
|
|
260
|
+
return false;
|
|
261
|
+
if (requirements.some((req) => !req.met))
|
|
262
|
+
return false;
|
|
263
|
+
return true;
|
|
264
|
+
}, [currentPassword, newPassword, confirmPassword, requirements]);
|
|
265
|
+
const getFieldError = useCallback((field) => errors.find((e) => e.field === field)?.message, [errors]);
|
|
266
|
+
const handleSubmit = useCallback(async (e) => {
|
|
267
|
+
e.preventDefault();
|
|
268
|
+
const newErrors = [];
|
|
269
|
+
if (!currentPassword) {
|
|
270
|
+
newErrors.push({ field: 'currentPassword', message: 'Current password is required' });
|
|
271
|
+
}
|
|
272
|
+
const passwordErrors = validatePassword(newPassword, rules, username);
|
|
273
|
+
if (passwordErrors.length > 0) {
|
|
274
|
+
newErrors.push({ field: 'newPassword', message: passwordErrors[0] });
|
|
275
|
+
}
|
|
276
|
+
if (!confirmPassword) {
|
|
277
|
+
newErrors.push({ field: 'confirmPassword', message: 'Please confirm your new password' });
|
|
278
|
+
}
|
|
279
|
+
else if (newPassword !== confirmPassword) {
|
|
280
|
+
newErrors.push({ field: 'confirmPassword', message: 'Passwords do not match' });
|
|
281
|
+
}
|
|
282
|
+
if (currentPassword && newPassword && currentPassword === newPassword) {
|
|
283
|
+
newErrors.push({ field: 'newPassword', message: 'New password must be different from current password' });
|
|
284
|
+
}
|
|
285
|
+
if (newErrors.length > 0) {
|
|
286
|
+
setErrors(newErrors);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
setErrors([]);
|
|
290
|
+
setIsSubmitting(true);
|
|
291
|
+
try {
|
|
292
|
+
await onSubmit({ currentPassword, newPassword, confirmPassword });
|
|
293
|
+
setCurrentPassword('');
|
|
294
|
+
setNewPassword('');
|
|
295
|
+
setConfirmPassword('');
|
|
296
|
+
onClose();
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
setErrors([{ field: 'general', message: error?.message || 'Failed to change password.' }]);
|
|
300
|
+
}
|
|
301
|
+
finally {
|
|
302
|
+
setIsSubmitting(false);
|
|
303
|
+
}
|
|
304
|
+
}, [currentPassword, newPassword, confirmPassword, rules, username, onSubmit, onClose]);
|
|
305
|
+
const handleClose = useCallback(() => {
|
|
306
|
+
if (!isSubmitting && !externalLoading) {
|
|
307
|
+
setCurrentPassword('');
|
|
308
|
+
setNewPassword('');
|
|
309
|
+
setConfirmPassword('');
|
|
310
|
+
setErrors([]);
|
|
311
|
+
onClose();
|
|
312
|
+
}
|
|
313
|
+
}, [isSubmitting, externalLoading, onClose]);
|
|
314
|
+
if (!isOpen)
|
|
315
|
+
return null;
|
|
316
|
+
const loading = isSubmitting || externalLoading;
|
|
317
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { style: styles.backdrop, onClick: handleClose }), _jsxs("div", { style: styles.modal, children: [_jsxs("div", { style: styles.header, children: [_jsxs("h2", { style: styles.headerTitle, children: [_jsx(LockIcon, {}), "Change Password"] }), _jsx("button", { style: styles.closeButton, onClick: handleClose, disabled: loading, children: _jsx(CloseIcon, {}) })] }), _jsxs("form", { onSubmit: handleSubmit, children: [_jsxs("div", { style: styles.content, children: [getFieldError('general') && (_jsx("div", { style: { padding: '0.75rem', backgroundColor: '#fef2f2', border: '1px solid #fecaca', borderRadius: '8px', marginBottom: '1rem', color: '#dc2626', fontSize: '0.875rem' }, children: getFieldError('general') })), _jsxs("div", { style: styles.formGroup, children: [_jsx("label", { style: styles.label, children: "Current Password" }), _jsxs("div", { style: styles.inputWrapper, children: [_jsx("input", { type: showCurrentPassword ? 'text' : 'password', value: currentPassword, onChange: (e) => setCurrentPassword(e.target.value), onFocus: () => setFocusedField('currentPassword'), onBlur: () => setFocusedField(null), placeholder: "Enter current password", disabled: loading, style: { ...styles.input, ...(getFieldError('currentPassword') ? styles.inputError : {}), ...(focusedField === 'currentPassword' ? styles.inputFocus : {}) } }), _jsx("button", { type: "button", style: styles.toggleButton, onClick: () => setShowCurrentPassword(!showCurrentPassword), tabIndex: -1, children: showCurrentPassword ? _jsx(EyeOffIcon, {}) : _jsx(EyeIcon, {}) })] }), getFieldError('currentPassword') && _jsx("div", { style: styles.errorText, children: getFieldError('currentPassword') })] }), _jsxs("div", { style: styles.formGroup, children: [_jsx("label", { style: styles.label, children: "New Password" }), _jsxs("div", { style: styles.inputWrapper, children: [_jsx("input", { type: showNewPassword ? 'text' : 'password', value: newPassword, onChange: (e) => setNewPassword(e.target.value), onFocus: () => setFocusedField('newPassword'), onBlur: () => setFocusedField(null), placeholder: "Enter new password", disabled: loading, style: { ...styles.input, ...(getFieldError('newPassword') ? styles.inputError : {}), ...(focusedField === 'newPassword' ? styles.inputFocus : {}) } }), _jsx("button", { type: "button", style: styles.toggleButton, onClick: () => setShowNewPassword(!showNewPassword), tabIndex: -1, children: showNewPassword ? _jsx(EyeOffIcon, {}) : _jsx(EyeIcon, {}) })] }), getFieldError('newPassword') && _jsx("div", { style: styles.errorText, children: getFieldError('newPassword') }), newPassword && (_jsxs("div", { style: styles.strengthMeter, children: [_jsx("div", { style: styles.strengthBar, children: _jsx("div", { style: { ...styles.strengthFill, width: `${(passwordStrength.score / 4) * 100}%`, backgroundColor: passwordStrength.color } }) }), _jsx("span", { style: { ...styles.strengthLabel, color: passwordStrength.color }, children: passwordStrength.label })] })), _jsxs("div", { style: styles.requirements, children: [_jsx("div", { style: styles.requirementsTitle, children: "Password Requirements" }), requirements.map((req) => (_jsxs("div", { style: { ...styles.requirementItem, color: req.met ? '#16a34a' : '#64748b' }, children: [req.met ? _jsx("span", { style: { color: '#16a34a' }, children: _jsx(CheckIcon, {}) }) : _jsx("span", { style: { color: '#cbd5e1' }, children: _jsx(XIcon, {}) }), req.label] }, req.id)))] })] }), _jsxs("div", { style: styles.formGroup, children: [_jsx("label", { style: styles.label, children: "Confirm New Password" }), _jsxs("div", { style: styles.inputWrapper, children: [_jsx("input", { type: showConfirmPassword ? 'text' : 'password', value: confirmPassword, onChange: (e) => setConfirmPassword(e.target.value), onFocus: () => setFocusedField('confirmPassword'), onBlur: () => setFocusedField(null), placeholder: "Confirm new password", disabled: loading, style: { ...styles.input, ...(getFieldError('confirmPassword') ? styles.inputError : {}), ...(focusedField === 'confirmPassword' ? styles.inputFocus : {}) } }), _jsx("button", { type: "button", style: styles.toggleButton, onClick: () => setShowConfirmPassword(!showConfirmPassword), tabIndex: -1, children: showConfirmPassword ? _jsx(EyeOffIcon, {}) : _jsx(EyeIcon, {}) })] }), getFieldError('confirmPassword') && _jsx("div", { style: styles.errorText, children: getFieldError('confirmPassword') }), confirmPassword && newPassword && confirmPassword === newPassword && (_jsxs("div", { style: { color: '#16a34a', fontSize: '0.8125rem', marginTop: '0.375rem', display: 'flex', alignItems: 'center', gap: '0.25rem' }, children: [_jsx(CheckIcon, {}), " Passwords match"] }))] })] }), _jsxs("div", { style: styles.footer, children: [_jsx("button", { type: "button", style: { ...styles.button, ...styles.cancelButton }, onClick: handleClose, disabled: loading, children: "Cancel" }), _jsx("button", { type: "submit", style: { ...styles.button, ...styles.submitButton, ...(!isFormValid || loading ? styles.submitButtonDisabled : {}) }, disabled: !isFormValid || loading, children: loading ? 'Changing...' : 'Change Password' })] })] })] })] }));
|
|
318
|
+
};
|
|
319
|
+
export default ChangePasswordModal;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @prima/layout - Enterprise React Layout Component
|
|
3
|
+
*/
|
|
4
|
+
import React from "react";
|
|
5
|
+
export type ComponentRegistry = Record<string, React.ComponentType<any>>;
|
|
6
|
+
export interface StoredModuleConfig {
|
|
7
|
+
showHeader: boolean;
|
|
8
|
+
title: string;
|
|
9
|
+
description: string;
|
|
10
|
+
componentName: string;
|
|
11
|
+
actions: string[];
|
|
12
|
+
permissions: string[];
|
|
13
|
+
breadcrumb: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface LogoConfig {
|
|
16
|
+
src?: string;
|
|
17
|
+
alt?: string;
|
|
18
|
+
width?: string;
|
|
19
|
+
height?: string;
|
|
20
|
+
showText?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface Colors {
|
|
23
|
+
primary: string;
|
|
24
|
+
secondary: string;
|
|
25
|
+
success: string;
|
|
26
|
+
warning: string;
|
|
27
|
+
danger: string;
|
|
28
|
+
info: string;
|
|
29
|
+
}
|
|
30
|
+
export interface BrandingConfig {
|
|
31
|
+
appName: string;
|
|
32
|
+
logo?: LogoConfig;
|
|
33
|
+
favicon?: string | null;
|
|
34
|
+
colors: Colors;
|
|
35
|
+
}
|
|
36
|
+
export interface LayoutConfig {
|
|
37
|
+
headerHeight: string;
|
|
38
|
+
sidebarWidth: string;
|
|
39
|
+
sidebarCollapsedWidth: string;
|
|
40
|
+
footerHeight: string;
|
|
41
|
+
tabBarHeight: string;
|
|
42
|
+
enableTabMode: boolean;
|
|
43
|
+
enableDarkMode: boolean;
|
|
44
|
+
enableFooter: boolean;
|
|
45
|
+
defaultTheme: "light" | "dark";
|
|
46
|
+
responsive: boolean;
|
|
47
|
+
collapsibleSidebar: boolean;
|
|
48
|
+
showBreadcrumbs: boolean;
|
|
49
|
+
autoCollapseSidebar: boolean;
|
|
50
|
+
compactModeStrategy: "sections-only" | "all-items" | "smart-grouping";
|
|
51
|
+
}
|
|
52
|
+
export interface FooterConfig {
|
|
53
|
+
appVersion: string;
|
|
54
|
+
environment: string;
|
|
55
|
+
copyright: string;
|
|
56
|
+
supportLink: string;
|
|
57
|
+
supportText: string;
|
|
58
|
+
}
|
|
59
|
+
export interface UserConfig {
|
|
60
|
+
name: string;
|
|
61
|
+
role: string;
|
|
62
|
+
avatar: string;
|
|
63
|
+
permissions: string[];
|
|
64
|
+
}
|
|
65
|
+
export interface NavigationItem {
|
|
66
|
+
id: string;
|
|
67
|
+
title: string;
|
|
68
|
+
icon: string;
|
|
69
|
+
badge?: string;
|
|
70
|
+
active?: boolean;
|
|
71
|
+
permissions?: string[];
|
|
72
|
+
children?: NavigationItem[];
|
|
73
|
+
isExpanded?: boolean;
|
|
74
|
+
sectionName?: string;
|
|
75
|
+
onClick?: () => void;
|
|
76
|
+
}
|
|
77
|
+
export interface NavigationSection {
|
|
78
|
+
section: string;
|
|
79
|
+
items: NavigationItem[];
|
|
80
|
+
icon?: string;
|
|
81
|
+
priority?: number;
|
|
82
|
+
}
|
|
83
|
+
export interface CompactModeItem {
|
|
84
|
+
id: string;
|
|
85
|
+
title: string;
|
|
86
|
+
icon: string;
|
|
87
|
+
sectionName: string;
|
|
88
|
+
badge?: string;
|
|
89
|
+
active?: boolean;
|
|
90
|
+
permissions?: string[];
|
|
91
|
+
children?: CompactModeItem[];
|
|
92
|
+
isSection?: boolean;
|
|
93
|
+
section?: string;
|
|
94
|
+
items?: NavigationItem[];
|
|
95
|
+
}
|
|
96
|
+
export interface ToolbarAction {
|
|
97
|
+
id: string;
|
|
98
|
+
icon: string;
|
|
99
|
+
tooltip: string;
|
|
100
|
+
permission: string;
|
|
101
|
+
variant?: "primary" | "secondary" | "danger" | "success";
|
|
102
|
+
separator?: boolean;
|
|
103
|
+
}
|
|
104
|
+
export interface ModuleConfig {
|
|
105
|
+
showHeader: boolean | true;
|
|
106
|
+
title: string;
|
|
107
|
+
description: string;
|
|
108
|
+
component: React.ComponentType<any> | null;
|
|
109
|
+
actions: string[];
|
|
110
|
+
toolbarActions?: ToolbarAction[];
|
|
111
|
+
permissions: string[];
|
|
112
|
+
breadcrumb: string[];
|
|
113
|
+
}
|
|
114
|
+
export interface ModulesConfig {
|
|
115
|
+
[key: string]: ModuleConfig;
|
|
116
|
+
}
|
|
117
|
+
export interface HooksConfig {
|
|
118
|
+
onModuleChange?: ((moduleId: string, config?: ModuleConfig) => void) | null;
|
|
119
|
+
onThemeChange?: ((theme: string) => void) | null;
|
|
120
|
+
onUserAction?: ((action: string, data: any) => void) | null;
|
|
121
|
+
onNavigate?: ((path: string, params?: any) => void) | null;
|
|
122
|
+
onChangePassword?: (() => void) | null;
|
|
123
|
+
onLogout?: (() => void) | null;
|
|
124
|
+
onToolbarAction?: ((actionId: string, moduleId: string, data?: any) => void) | null;
|
|
125
|
+
}
|
|
126
|
+
export interface EnterpriseLayoutConfig {
|
|
127
|
+
branding: BrandingConfig;
|
|
128
|
+
layout: LayoutConfig;
|
|
129
|
+
footer: FooterConfig;
|
|
130
|
+
user: UserConfig;
|
|
131
|
+
navigation: NavigationSection[];
|
|
132
|
+
modules: ModulesConfig;
|
|
133
|
+
hooks: HooksConfig;
|
|
134
|
+
}
|
|
135
|
+
export interface TabData {
|
|
136
|
+
title: string;
|
|
137
|
+
config?: ModuleConfig;
|
|
138
|
+
}
|
|
139
|
+
export interface IconSystemType {
|
|
140
|
+
[key: string]: () => React.JSX.Element;
|
|
141
|
+
}
|
|
142
|
+
export interface EnterpriseLayoutProps {
|
|
143
|
+
config: EnterpriseLayoutConfig;
|
|
144
|
+
componentRegistry: ComponentRegistry;
|
|
145
|
+
children?: React.ReactNode;
|
|
146
|
+
router?: any;
|
|
147
|
+
apiClient?: any;
|
|
148
|
+
authProvider?: any;
|
|
149
|
+
onModuleChange?: ((moduleId: string, config?: ModuleConfig) => void) | null;
|
|
150
|
+
onThemeChange?: ((theme: string) => void) | null;
|
|
151
|
+
}
|
|
152
|
+
export declare const EnterpriseLayout: React.FC<EnterpriseLayoutProps>;
|
|
153
|
+
export default EnterpriseLayout;
|
|
154
|
+
//# sourceMappingURL=EnterpriseLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EnterpriseLayout.d.ts","sourceRoot":"","sources":["../../src/components/EnterpriseLayout.tsx"],"names":[],"mappings":"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"}
|