proje-react-panel 1.2.0 → 1.3.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.
Files changed (37) hide show
  1. package/dist/__tests__/utils/PreloadCacheHelper.test.d.ts +1 -0
  2. package/dist/components/Login.d.ts +3 -12
  3. package/dist/components/Panel.d.ts +4 -1
  4. package/dist/components/form/Checkbox.d.ts +2 -1
  5. package/dist/components/form/FormPage.d.ts +2 -1
  6. package/dist/components/form/Uploader.d.ts +2 -1
  7. package/dist/decorators/form/Form.d.ts +9 -7
  8. package/dist/decorators/form/Input.d.ts +1 -1
  9. package/dist/decorators/form/inputs/SelectInput.d.ts +6 -8
  10. package/dist/index.cjs.js +1 -1
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.esm.js +1 -1
  13. package/dist/store/store.d.ts +2 -3
  14. package/dist/types/User.d.ts +3 -0
  15. package/dist/utils/PreloadCacheHelper.d.ts +15 -0
  16. package/dist/utils/login.d.ts +2 -0
  17. package/dist/utils/logout.d.ts +1 -0
  18. package/package.json +1 -1
  19. package/src/__tests__/utils/PreloadCacheHelper.test.ts +9 -20
  20. package/src/components/Login.tsx +4 -83
  21. package/src/components/Panel.tsx +13 -6
  22. package/src/components/form/Checkbox.tsx +6 -5
  23. package/src/components/form/FormField.tsx +16 -32
  24. package/src/components/form/FormPage.tsx +24 -5
  25. package/src/components/form/InnerForm.tsx +73 -72
  26. package/src/components/form/Select.tsx +4 -3
  27. package/src/components/form/Uploader.tsx +5 -4
  28. package/src/decorators/form/Form.ts +13 -10
  29. package/src/decorators/form/Input.ts +7 -3
  30. package/src/index.ts +2 -2
  31. package/src/store/store.ts +3 -4
  32. package/src/styles/form.scss +17 -6
  33. package/src/styles/login.scss +24 -93
  34. package/src/types/User.ts +3 -0
  35. package/src/utils/PreloadCacheHelper.ts +5 -12
  36. package/src/utils/login.ts +8 -0
  37. package/src/utils/logout.ts +7 -0
@@ -11,7 +11,6 @@ export type InputTypes = 'input' | 'textarea' | 'file-upload' | 'checkbox' | 'hi
11
11
  export type ExtendedInputTypes = InputTypes | 'select';
12
12
 
13
13
  export interface InputOptions {
14
- name?: string;
15
14
  type?: InputTypes;
16
15
  inputType?: 'text' | 'email' | 'tel' | 'password' | 'number' | 'date';
17
16
  label?: string;
@@ -28,6 +27,7 @@ export interface ExtendedInputOptions extends Omit<InputOptions, 'type'> {
28
27
 
29
28
  export interface InputConfiguration {
30
29
  name: string;
30
+ isNested: boolean;
31
31
  type: ExtendedInputTypes;
32
32
  inputType: 'text' | 'email' | 'tel' | 'password' | 'number' | 'date';
33
33
  label?: string;
@@ -55,7 +55,7 @@ export function ExtendedInput(options?: ExtendedInputOptions): PropertyDecorator
55
55
  const existingInputs: string[] = Reflect.getMetadata(INPUT_KEY, target) || [];
56
56
  Reflect.defineMetadata(INPUT_KEY, [...existingInputs, propertyKey.toString()], target);
57
57
  if (options) {
58
- const keyString = `${INPUT_KEY.toString()}:${propertyKey.toString()}:options`;
58
+ const keyString = `${INPUT_KEY.toString()}:${propertyKey.toString()}:options`;
59
59
  Reflect.defineMetadata(keyString, options, target);
60
60
  }
61
61
  };
@@ -70,9 +70,13 @@ export function getInputFields<T extends AnyClass>(
70
70
  const fields: InputOptions =
71
71
  Reflect.getMetadata(`${INPUT_KEY.toString()}:${field}:options`, prototype) || {};
72
72
  const inputType = fields?.inputType ?? (isFieldSensitive(field) ? 'password' : 'text');
73
+
74
+ // Check if field is in format translations[0].x
75
+ const isNested: boolean = field.match(/^[a-zA-Z]+\[\d+\]\.[a-zA-Z]+$/) !== null;
73
76
  const inputConfiguration: InputConfiguration = {
74
77
  ...fields,
75
- name: fields?.name ?? field,
78
+ name: field,
79
+ isNested,
76
80
  label: fields?.label ?? field,
77
81
  placeholder: fields?.placeholder ?? field,
78
82
  inputType: inputType,
package/src/index.ts CHANGED
@@ -34,5 +34,5 @@ export { Layout } from './components/layout';
34
34
 
35
35
  //AUTH
36
36
  export { Login } from './components/Login';
37
-
38
- //UTILS
37
+ export { login } from './utils/login';
38
+ export { logout } from './utils/logout';
@@ -1,14 +1,12 @@
1
1
  import { createJSONStorage, persist } from 'zustand/middleware';
2
2
  import { createWithEqualityFn } from 'zustand/traditional';
3
3
  import { shallow } from 'zustand/vanilla/shallow';
4
-
5
- interface User {
6
- username: string;
7
- }
4
+ import { User } from '../types/User';
8
5
 
9
6
  interface AppState {
10
7
  user: User | null;
11
8
  login: (user: User) => void;
9
+ logout: () => void;
12
10
  }
13
11
 
14
12
  export const useAppStore = createWithEqualityFn<AppState>()(
@@ -16,6 +14,7 @@ export const useAppStore = createWithEqualityFn<AppState>()(
16
14
  set => ({
17
15
  user: null,
18
16
  login: (user: User) => set({ user }),
17
+ logout: () => set({ user: null }),
19
18
  }),
20
19
  {
21
20
  name: 'app-store-1',
@@ -12,6 +12,15 @@
12
12
  .form-field {
13
13
  margin-bottom: 16px;
14
14
 
15
+ input[type='text'],
16
+ input[type='password'],
17
+ input[type='email'],
18
+ input[type='tel'],
19
+ input[type='number'],
20
+ input[type='date'] {
21
+ height: 40px;
22
+ }
23
+
15
24
  input[type='text'],
16
25
  input[type='password'],
17
26
  input[type='email'],
@@ -20,6 +29,7 @@
20
29
  input[type='date'],
21
30
  textarea,
22
31
  select {
32
+ box-sizing: border-box;
23
33
  padding: 10px;
24
34
  font-size: 16px;
25
35
  border: 1px solid #444;
@@ -71,6 +81,7 @@
71
81
  color: white;
72
82
  border: none;
73
83
  border-radius: 5px;
84
+ height: 40px;
74
85
  cursor: pointer;
75
86
  transition: background-color 0.2s;
76
87
 
@@ -78,11 +89,11 @@
78
89
  background-color: #0056b3;
79
90
  }
80
91
  }
81
- }
82
92
 
83
- .label {
84
- font-weight: bold;
85
- margin-bottom: 6px;
86
- display: block;
87
- color: #f2f2f2;
93
+ .label {
94
+ font-weight: bold;
95
+ margin-bottom: 6px;
96
+ display: block;
97
+ color: #f2f2f2;
98
+ }
88
99
  }
@@ -1,93 +1,24 @@
1
- .login-container {
2
- display: flex;
3
- justify-content: center;
4
- align-items: center;
5
- min-height: 100vh;
6
- background: linear-gradient(135deg, #1a1a1a 0%, #2d3436 100%);
7
- padding: 20px;
8
-
9
- .login-panel {
10
- width: 100%;
11
- max-width: 400px;
12
- background: #2c2c2c;
13
- border-radius: 12px;
14
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
15
- padding: 32px;
16
- }
17
-
18
- .login-header {
19
- text-align: center;
20
- margin-bottom: 32px;
21
-
22
- h1 {
23
- font-size: 24px;
24
- color: #ffffff;
25
- margin-bottom: 8px;
26
- }
27
-
28
- p {
29
- color: #b3b3b3;
30
- font-size: 14px;
31
- }
32
- }
33
-
34
- .login-form {
35
- display: flex;
36
- flex-direction: column;
37
- align-items: center;
38
-
39
- .form-field {
40
- width: 100%;
41
- margin-bottom: 16px;
42
-
43
- label {
44
- display: block;
45
- margin-bottom: 8px;
46
- color: #ffffff;
47
- font-weight: 500;
48
- }
49
-
50
- input {
51
- width: 100%;
52
- box-sizing: border-box;
53
- padding: 12px 16px;
54
- border: 1px solid #404040;
55
- border-radius: 8px;
56
- font-size: 14px;
57
- background: #363636;
58
- color: #ffffff;
59
- transition: border-color 0.2s ease;
60
- &:focus {
61
- outline: none;
62
- border-color: #0066cc;
63
- box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.2);
64
- }
65
- }
66
- }
67
-
68
- .form-actions {
69
- margin-top: 24px;
70
-
71
- .submit-button {
72
- width: 100%;
73
- padding: 12px;
74
- background: #0066cc;
75
- color: white;
76
- border: none;
77
- border-radius: 8px;
78
- font-size: 16px;
79
- font-weight: 500;
80
- cursor: pointer;
81
- transition: background-color 0.2s ease;
82
-
83
- &:hover {
84
- background: #0052a3;
85
- }
86
-
87
- &:active {
88
- transform: translateY(1px);
89
- }
90
- }
91
- }
92
- }
93
- }
1
+ .login-form {
2
+ display: flex;
3
+ justify-content: center;
4
+ align-items: center;
5
+ min-height: 100vh;
6
+ background: linear-gradient(135deg, #1a1a1a 0%, #2d3436 100%);
7
+
8
+ form {
9
+ width: 400px;
10
+ background: #1a1a1a;
11
+ border-radius: 8px;
12
+ padding: 40px;
13
+ }
14
+
15
+ .form-header {
16
+ display: none;
17
+ }
18
+
19
+ .submit-button {
20
+ display: block;
21
+ width: 100%;
22
+ margin-top: 50px;
23
+ }
24
+ }
@@ -0,0 +1,3 @@
1
+ export interface User {
2
+ username: string;
3
+ }
@@ -1,25 +1,18 @@
1
1
  import { SelectPreloader } from '../decorators/form/inputs/SelectInput';
2
2
 
3
- export type OnResult<T> = (result: { label: string; value: T }[]) => Promise<void>;
4
- export type OnPreload<T> = () => Promise<{ label: string; value: T }[]>;
3
+ export type OnResult<T> = (result: { label: string; value: T }[]) => void;
5
4
 
6
5
  class PreloadCacheHelper {
7
6
  private static instance: PreloadCacheHelper;
8
7
  private cache: Map<SelectPreloader<unknown>, { label: string; value: unknown }[]>;
9
- private asyncQueue: Map<
10
- SelectPreloader<unknown>,
11
- ((result: { label: string; value: unknown }[]) => Promise<void>)[]
12
- >;
8
+ private asyncQueue: Map<SelectPreloader<unknown>, OnResult<unknown>[]>;
13
9
 
14
10
  private constructor() {
15
11
  this.cache = new Map();
12
+ this.asyncQueue = new Map();
16
13
  }
17
14
 
18
- public async setOrGetCache<T>(
19
- key: SelectPreloader<T>,
20
- onResult: OnResult<T>,
21
- onPreload: OnPreload<T>
22
- ): Promise<void> {
15
+ public async setOrGetCache<T>(key: SelectPreloader<T>, onResult: OnResult<T>): Promise<void> {
23
16
  if (this.cache.has(key)) {
24
17
  onResult(this.cache.get(key) as { label: string; value: T }[]);
25
18
  return;
@@ -37,7 +30,7 @@ class PreloadCacheHelper {
37
30
  return;
38
31
  }
39
32
 
40
- const result = await onPreload();
33
+ const result = await key();
41
34
  this.cache.set(key, result);
42
35
  this.asyncQueue.get(key)?.forEach(onResult => onResult(result));
43
36
  this.asyncQueue.delete(key);
@@ -0,0 +1,8 @@
1
+ import { useAppStore } from '../store/store';
2
+ import { User } from '../types/User';
3
+
4
+ export function login(user: User, token: string, navigate: () => void) {
5
+ localStorage.setItem('token', token);
6
+ useAppStore.getState().login(user);
7
+ navigate();
8
+ }
@@ -0,0 +1,7 @@
1
+ import { useAppStore } from '../store/store';
2
+
3
+ export function logout(navigate: () => void) {
4
+ localStorage.removeItem('token');
5
+ useAppStore.getState().logout();
6
+ navigate();
7
+ }