proje-react-panel 1.6.0 → 1.7.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 (90) hide show
  1. package/.cursor/rules.md +11 -1
  2. package/AUTH_LAYOUT_EXAMPLE.md +343 -0
  3. package/AUTH_LAYOUT_GUIDE.md +819 -0
  4. package/COLOR_SYSTEM_GUIDE.md +296 -0
  5. package/DASHBOARD_GUIDE.md +531 -0
  6. package/IMPLEMENTATION_GUIDE.md +899 -0
  7. package/README.md +18 -1
  8. package/dist/api/ApiConfig.d.ts +11 -0
  9. package/dist/api/AuthApi.d.ts +2 -5
  10. package/dist/api/CrudApi.d.ts +11 -12
  11. package/dist/components/DashboardContainer.d.ts +7 -0
  12. package/dist/components/DashboardGrid.d.ts +9 -0
  13. package/dist/components/DashboardItem.d.ts +10 -0
  14. package/dist/components/ThemeSwitcher.d.ts +7 -0
  15. package/dist/components/dashboard/Dashboard.d.ts +7 -0
  16. package/dist/components/dashboard/DashboardGrid.d.ts +7 -0
  17. package/dist/components/dashboard/DashboardItem.d.ts +6 -0
  18. package/dist/components/dashboard/index.d.ts +3 -0
  19. package/dist/decorators/auth/DefaultLoginForm.d.ts +4 -0
  20. package/dist/index.cjs.js +15 -1
  21. package/dist/index.d.ts +6 -0
  22. package/dist/index.esm.js +15 -1
  23. package/dist/store/themeStore.d.ts +23 -0
  24. package/dist/types/Login.d.ts +8 -0
  25. package/package.json +3 -1
  26. package/src/api/ApiConfig.ts +63 -0
  27. package/src/api/AuthApi.ts +8 -0
  28. package/src/api/CrudApi.ts +96 -60
  29. package/src/components/dashboard/Dashboard.tsx +11 -0
  30. package/src/components/dashboard/DashboardGrid.tsx +14 -0
  31. package/src/components/dashboard/DashboardItem.tsx +9 -0
  32. package/src/components/dashboard/index.ts +3 -0
  33. package/src/decorators/auth/DefaultLoginForm.ts +32 -0
  34. package/src/index.ts +26 -0
  35. package/src/styles/base/_variables.scss +45 -0
  36. package/src/styles/components/button.scss +3 -3
  37. package/src/styles/components/checkbox.scss +6 -6
  38. package/src/styles/components/form-header.scss +21 -19
  39. package/src/styles/components/uploader.scss +15 -37
  40. package/src/styles/counter.scss +25 -33
  41. package/src/styles/dashboard.scss +9 -0
  42. package/src/styles/details.scss +6 -15
  43. package/src/styles/error-boundary.scss +75 -74
  44. package/src/styles/filter-popup.scss +29 -27
  45. package/src/styles/form.scss +16 -15
  46. package/src/styles/index.scss +8 -4
  47. package/src/styles/layout.scss +9 -8
  48. package/src/styles/list.scss +29 -27
  49. package/src/styles/loading-screen.scss +4 -4
  50. package/src/styles/login.scss +3 -3
  51. package/src/styles/pagination.scss +13 -13
  52. package/src/styles/sidebar.scss +24 -22
  53. package/src/styles/utils/scrollbar.scss +4 -3
  54. package/src/types/Login.ts +9 -0
  55. package/src/utils/logout.ts +2 -0
  56. package/dist/components/components/Checkbox.d.ts +0 -7
  57. package/dist/components/components/Counter.d.ts +0 -9
  58. package/dist/components/components/ErrorBoundary.d.ts +0 -16
  59. package/dist/components/components/ErrorComponent.d.ts +0 -4
  60. package/dist/components/components/FormField.d.ts +0 -17
  61. package/dist/components/components/ImageUploader.d.ts +0 -15
  62. package/dist/components/components/InnerForm.d.ts +0 -17
  63. package/dist/components/components/Label.d.ts +0 -9
  64. package/dist/components/components/LoadingScreen.d.ts +0 -2
  65. package/dist/components/components/Uploader.d.ts +0 -8
  66. package/dist/components/components/index.d.ts +0 -8
  67. package/dist/components/components/list/Datagrid.d.ts +0 -9
  68. package/dist/components/components/list/EmptyList.d.ts +0 -2
  69. package/dist/components/components/list/FilterPopup.d.ts +0 -11
  70. package/dist/components/components/list/ListPage.d.ts +0 -20
  71. package/dist/components/components/list/Pagination.d.ts +0 -11
  72. package/dist/components/components/list/index.d.ts +0 -0
  73. package/dist/components/pages/ControllerDetails.d.ts +0 -5
  74. package/dist/components/pages/FormPage.d.ts +0 -18
  75. package/dist/components/pages/ListPage.d.ts +0 -18
  76. package/dist/components/pages/Login.d.ts +0 -13
  77. package/dist/decorators/Crud.d.ts +0 -6
  78. package/dist/decorators/form/FormOptions.d.ts +0 -7
  79. package/dist/decorators/form/getFormFields.d.ts +0 -3
  80. package/dist/decorators/list/GetCellFields.d.ts +0 -2
  81. package/dist/decorators/list/ImageCell.d.ts +0 -6
  82. package/dist/decorators/list/ListData.d.ts +0 -6
  83. package/dist/decorators/list/getListFields.d.ts +0 -2
  84. package/dist/initPanel.d.ts +0 -2
  85. package/dist/types/Screen.d.ts +0 -4
  86. package/dist/types/ScreenCreatorData.d.ts +0 -13
  87. package/dist/types/getDetailsData.d.ts +0 -1
  88. package/dist/types/initPanelOptions.d.ts +0 -2
  89. package/dist/utils/createScreens.d.ts +0 -1
  90. package/dist/utils/getFields.d.ts +0 -3
@@ -0,0 +1,23 @@
1
+ export type ThemeMode = 'light' | 'dark' | 'automatic';
2
+ interface ThemeState {
3
+ theme: ThemeMode;
4
+ resolvedTheme: 'light' | 'dark';
5
+ setTheme: (theme: ThemeMode) => void;
6
+ initializeTheme: () => void;
7
+ }
8
+ export declare const useThemeStore: import("zustand/traditional").UseBoundStoreWithEqualityFn<Omit<import("zustand/vanilla").StoreApi<ThemeState>, "persist"> & {
9
+ persist: {
10
+ setOptions: (options: Partial<import("zustand/middleware").PersistOptions<ThemeState, unknown>>) => void;
11
+ clearStorage: () => void;
12
+ rehydrate: () => Promise<void> | void;
13
+ hasHydrated: () => boolean;
14
+ onHydrate: (fn: (state: ThemeState) => void) => () => void;
15
+ onFinishHydration: (fn: (state: ThemeState) => void) => () => void;
16
+ getOptions: () => Partial<import("zustand/middleware").PersistOptions<ThemeState, unknown>>;
17
+ };
18
+ }>;
19
+ export declare const getTheme: () => ThemeMode;
20
+ export declare const getResolvedTheme: () => "light" | "dark";
21
+ export declare const setTheme: (theme: ThemeMode) => void;
22
+ export declare const initializeTheme: () => void;
23
+ export {};
@@ -0,0 +1,8 @@
1
+ export interface LoginResponse<T> {
2
+ access_token: string;
3
+ admin: T;
4
+ }
5
+ export interface LoginForm {
6
+ username: string;
7
+ password: string;
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "proje-react-panel",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "author": "SEFA DEMİR",
@@ -33,6 +33,7 @@
33
33
  "@types/react": "^19.0.10",
34
34
  "@typescript-eslint/eslint-plugin": "^8.26.1",
35
35
  "@typescript-eslint/parser": "^8.29.1",
36
+ "axios": "^1.12.2",
36
37
  "class-transformer": "^0.5.1",
37
38
  "class-validator": "^0.14.1",
38
39
  "eslint": "^9.24.0",
@@ -61,6 +62,7 @@
61
62
  "zustand": "^5.0.3"
62
63
  },
63
64
  "peerDependencies": {
65
+ "axios": ">=1.0.0",
64
66
  "react": ">=19.0.0",
65
67
  "react-hook-form": ">=7.54.2",
66
68
  "react-router": "7.3.0",
@@ -0,0 +1,63 @@
1
+ import axios, { AxiosInstance } from 'axios';
2
+
3
+ let axiosInstance: AxiosInstance;
4
+
5
+ export interface ApiConfig {
6
+ baseUrl: string;
7
+ }
8
+
9
+ export function initApi(config: ApiConfig): void {
10
+ axiosInstance = axios.create({
11
+ baseURL: config.baseUrl,
12
+ headers: {
13
+ 'Content-Type': 'application/json',
14
+ },
15
+ });
16
+
17
+ axiosInstance.interceptors.response.use(
18
+ response => response,
19
+ error => {
20
+ if (error.response && error.response.status === 401) {
21
+ setAuthLogout();
22
+ window.location.href = '/login';
23
+ }
24
+ return Promise.reject(error);
25
+ }
26
+ );
27
+ }
28
+
29
+ export function initAuthToken(): void {
30
+ if (!axiosInstance) {
31
+ throw new Error('API not initialized. Call initApi first.');
32
+ }
33
+ const token = localStorage.getItem('token');
34
+ if (token) {
35
+ axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${token}`;
36
+ }
37
+ }
38
+
39
+ export function setAuthToken(token: string): void {
40
+ if (!axiosInstance) {
41
+ throw new Error('API not initialized. Call initApi first.');
42
+ }
43
+ axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${token}`;
44
+ localStorage.setItem('token', token);
45
+ }
46
+
47
+ export function setAuthLogout(): void {
48
+ if (!axiosInstance) {
49
+ throw new Error('API not initialized. Call initApi first.');
50
+ }
51
+ axiosInstance.defaults.headers.common['Authorization'] = null;
52
+ localStorage.removeItem('token');
53
+ }
54
+
55
+ export function getAxiosInstance(): AxiosInstance {
56
+ if (!axiosInstance) {
57
+ throw new Error('API not initialized. Call initApi first.');
58
+ }
59
+ return axiosInstance;
60
+ }
61
+
62
+ // Export the axios instance for external use
63
+ export { axiosInstance };
@@ -0,0 +1,8 @@
1
+ import { LoginForm, LoginResponse } from '../types/Login';
2
+ import { getAxiosInstance } from './ApiConfig';
3
+
4
+ export async function login<T>(data: LoginForm | FormData): Promise<LoginResponse<T>> {
5
+ const axiosInstance = getAxiosInstance();
6
+ const response = await axiosInstance.post<LoginResponse<T>>('/auth/login', data);
7
+ return response.data;
8
+ }
@@ -1,65 +1,101 @@
1
- interface FetchOptions {
2
- token: string;
3
- baseUrl: string;
4
- }
1
+ import { GetDataForList, PaginatedResponse, GetDataParams } from '../decorators/list/List';
2
+ import { OnSubmitFN } from '../decorators/form/Form';
3
+ import { GetDetailsDataFN } from '../decorators/details/Details';
4
+ import { getAxiosInstance } from './ApiConfig';
5
+ import { AxiosError } from 'axios';
5
6
 
6
- export const CrudApi = {
7
- getList: (options: FetchOptions, api: string) => {
8
- return fetch(`${options.baseUrl}/${api}`, {
9
- method: 'GET',
10
- headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${options.token}` },
11
- }).then(res => {
12
- if (res.ok) {
13
- return res.json();
14
- }
15
- throw res;
7
+ export function getAll<T>(endpoint: string): GetDataForList<T> {
8
+ return async (params: GetDataParams): Promise<PaginatedResponse<T>> => {
9
+ const axiosInstance = getAxiosInstance();
10
+ const { page = 1, limit = 10 } = params;
11
+ const response = await axiosInstance.get<{
12
+ data: T[];
13
+ total: number;
14
+ }>(`/${endpoint}`, {
15
+ params: { page, limit, ...(params.filters ?? {}) },
16
16
  });
17
- },
18
- //TODO: fix this
19
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
- create: (options: FetchOptions, api: string, data: any) => {
21
- const headers: HeadersInit = { Authorization: `Bearer ${options.token}` };
22
- // Don't set Content-Type for FormData
23
- if (!(data instanceof FormData)) {
24
- headers['Content-Type'] = 'application/json';
25
- }
17
+ return {
18
+ data: response.data.data,
19
+ total: response.data.total,
20
+ page,
21
+ limit,
22
+ };
23
+ };
24
+ }
25
+
26
+ export function getOne<T>(endpoint: string, key = 'id'): GetDetailsDataFN<T> {
27
+ return async (params: Record<string, string>): Promise<T> => {
28
+ const axiosInstance = getAxiosInstance();
29
+ const response = await axiosInstance.get<T>(`/${endpoint}/${params[key]}`);
30
+ return response.data;
31
+ };
32
+ }
26
33
 
27
- return fetch(`${options?.baseUrl ?? ''}/${api}`, {
28
- method: 'POST',
29
- headers,
30
- body: data instanceof FormData ? data : JSON.stringify(data),
31
- }).then(res => res.json());
32
- },
33
- //TODO: fix this
34
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
- details: (options: FetchOptions, api: string, id: any) => {
36
- return fetch(`${options?.baseUrl ?? ''}/${api}/${id}`, {
37
- method: 'GET',
38
- headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${options.token}` },
39
- }).then(res => {
40
- return res.json();
34
+ export function create<T>(endpoint: string): OnSubmitFN<T> {
35
+ return async (data: T | FormData): Promise<T> => {
36
+ const axiosInstance = getAxiosInstance();
37
+ const response = await axiosInstance.post<T>(`/${endpoint}`, data);
38
+ return response.data;
39
+ };
40
+ }
41
+
42
+ export function createFormData<T>(endpoint: string): OnSubmitFN<T> {
43
+ return async (data: T | FormData): Promise<T> => {
44
+ const axiosInstance = getAxiosInstance();
45
+ const response = await axiosInstance.post<T>(`/${endpoint}`, data, {
46
+ headers: {
47
+ 'Content-Type': 'multipart/form-data',
48
+ },
41
49
  });
42
- },
43
- //TODO: fix this
44
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
- edit: (options: FetchOptions, api: string, data: any) => {
46
- const headers: HeadersInit = { Authorization: `Bearer ${options.token}` };
47
- // Don't set Content-Type for FormData
48
- if (!(data instanceof FormData)) {
49
- headers['Content-Type'] = 'application/json';
50
- }
51
- return fetch(`${options?.baseUrl ?? ''}/${api}/${data.id}`, {
52
- method: 'PUT',
53
- headers,
54
- body: data instanceof FormData ? data : JSON.stringify(data),
55
- }).then(res => res.json());
56
- },
57
- delete: (options: FetchOptions, api: string, id: string) => {
58
- return fetch(`${options?.baseUrl ?? ''}/${api}/${id}`, {
59
- method: 'DELETE',
60
- headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${options.token}` },
61
- }).then(res => {
62
- return res.clone().json();
50
+ return response.data;
51
+ };
52
+ }
53
+
54
+ export function update<T>(endpoint: string, key = 'id'): OnSubmitFN<T> {
55
+ return async (data: T | FormData): Promise<T> => {
56
+ const axiosInstance = getAxiosInstance();
57
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
+ const id = (data as any)[key];
59
+ const response = await axiosInstance.put<T>(`/${endpoint}/${id}`, data);
60
+ return response.data;
61
+ };
62
+ }
63
+
64
+ export function updateFormData<T>(endpoint: string, key = 'id'): OnSubmitFN<T> {
65
+ return async (data: T | FormData): Promise<T> => {
66
+ const axiosInstance = getAxiosInstance();
67
+ const id = (data as any)[key];
68
+ const response = await axiosInstance.put<T>(`/${endpoint}/${id}`, data, {
69
+ headers: {
70
+ 'Content-Type': 'multipart/form-data',
71
+ },
63
72
  });
64
- },
65
- };
73
+ return response.data;
74
+ };
75
+ }
76
+
77
+ export function updateSimple<T>(endpoint: string): OnSubmitFN<T> {
78
+ return async (data: T | FormData): Promise<T> => {
79
+ const axiosInstance = getAxiosInstance();
80
+ const response = await axiosInstance.put<T>(`/${endpoint}`, data);
81
+ return response.data;
82
+ };
83
+ }
84
+
85
+ export function remove<T>(endpoint: string, key = 'id'): (data: T) => Promise<void> {
86
+ return async (data: T): Promise<void> => {
87
+ const axiosInstance = getAxiosInstance();
88
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
89
+ const id = (data as any)[key];
90
+ await axiosInstance
91
+ .delete<T>(`/${endpoint}/${id}`)
92
+ .then((res: any) => res.data)
93
+ .catch((err: AxiosError) => {
94
+ const messageError = err.response?.data as { message: string };
95
+ if (messageError?.message) {
96
+ throw new Error(messageError.message);
97
+ }
98
+ throw err;
99
+ });
100
+ };
101
+ }
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { DashboardGrid } from './DashboardGrid';
3
+
4
+ interface DashboardProps {
5
+ children: React.ReactNode;
6
+ columns?: number;
7
+ }
8
+
9
+ export function Dashboard({ children, columns }: DashboardProps) {
10
+ return <DashboardGrid columns={columns}>{children}</DashboardGrid>;
11
+ }
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+
3
+ interface DashboardGridProps {
4
+ children: React.ReactNode;
5
+ columns?: number;
6
+ }
7
+
8
+ export function DashboardGrid({ children, columns = 3 }: DashboardGridProps) {
9
+ return (
10
+ <div className="dashboard-grid" style={{ gridTemplateColumns: `repeat(${columns}, 1fr)` }}>
11
+ {children}
12
+ </div>
13
+ );
14
+ }
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+
3
+ interface DashboardItemProps {
4
+ children: React.ReactNode;
5
+ }
6
+
7
+ export function DashboardItem({ children }: DashboardItemProps) {
8
+ return <div className="dashboard-item">{children}</div>;
9
+ }
@@ -0,0 +1,3 @@
1
+ export { Dashboard } from './Dashboard';
2
+ export { DashboardGrid } from './DashboardGrid';
3
+ export { DashboardItem } from './DashboardItem';
@@ -0,0 +1,32 @@
1
+ import { MinLength } from 'class-validator';
2
+ import { Form } from '../form/Form';
3
+ import { Input } from '../form/Input';
4
+ import { LoginForm as LoginFormInterface, LoginResponse } from '../../types/Login';
5
+ import { setAuthToken } from '../../api/ApiConfig';
6
+ import { login } from '../../utils/login';
7
+ import { User } from '../../types/User';
8
+ import { authLogin } from '../..';
9
+
10
+ @Form<LoginFormInterface, LoginResponse<User>>({
11
+ onSubmit: authLogin,
12
+ onSubmitSuccess: (data: LoginResponse<User>) => {
13
+ setAuthToken(data.access_token);
14
+ login(data.admin as User, data.access_token, () => {
15
+ window.location.href = '/';
16
+ });
17
+ },
18
+ type: 'formData',
19
+ })
20
+ export class DefaultLoginForm {
21
+ @MinLength(3)
22
+ @Input({
23
+ label: 'Username',
24
+ })
25
+ username: string;
26
+
27
+ @Input({
28
+ label: 'Password',
29
+ inputType: 'password',
30
+ })
31
+ password: string;
32
+ }
package/src/index.ts CHANGED
@@ -29,6 +29,7 @@ export { Panel } from './components/Panel';
29
29
 
30
30
  //DASHBOARD
31
31
  export { Counter } from './components/Counter';
32
+ export { Dashboard, DashboardGrid, DashboardItem } from './components/dashboard';
32
33
 
33
34
  //LAYOUT
34
35
  export { Layout } from './components/layout';
@@ -37,6 +38,31 @@ export { Layout } from './components/layout';
37
38
  export { Login } from './components/Login';
38
39
  export { login } from './utils/login';
39
40
  export { logout } from './utils/logout';
41
+ export { DefaultLoginForm } from './decorators/auth/DefaultLoginForm';
42
+
43
+ //API
44
+ export {
45
+ initApi,
46
+ initAuthToken,
47
+ setAuthToken,
48
+ setAuthLogout,
49
+ getAxiosInstance,
50
+ axiosInstance,
51
+ } from './api/ApiConfig';
52
+ export {
53
+ getAll,
54
+ getOne,
55
+ create,
56
+ createFormData,
57
+ update,
58
+ updateFormData,
59
+ updateSimple,
60
+ remove,
61
+ } from './api/CrudApi';
62
+ export { login as authLogin } from './api/AuthApi';
63
+
64
+ //TYPES
65
+ export type { LoginForm, LoginResponse } from './types/Login';
40
66
 
41
67
  //SERVICES
42
68
  export { updateDetailsData } from './services/DataService';
@@ -0,0 +1,45 @@
1
+ // SCSS Color Variables - Dark Theme
2
+ // ⚠️ IMPORTANT: If you change any variables here, you MUST update COLOR_SYSTEM_GUIDE.md
3
+ $dark-void: #1a1a1a; // Darkest background
4
+ $dark-slate: #2b2b2b; // Dark background
5
+ $dark-mist: #333333; // Medium dark background
6
+ $dark-silver: #444444; // Lighter dark background
7
+
8
+ $dark-pearl: #ffffff; // White
9
+ $dark-ash: #e0e0e0; // Light gray
10
+ $dark-dust: #999999; // Medium gray
11
+
12
+ $dark-ocean: #007bff; // Primary blue
13
+ $dark-sky: #66b2ff; // Light blue (focus)
14
+ $dark-emerald: #4caf50; // Success green
15
+ $dark-ruby: #ff4d4f; // Error red
16
+
17
+ .layout {
18
+ // Backgrounds
19
+ --prp-bg-primary: #{$dark-void};
20
+ --prp-bg-secondary: #{$dark-slate};
21
+ --prp-bg-tertiary: #{$dark-mist};
22
+ --prp-bg-white: #{$dark-pearl};
23
+ --prp-bg-button-primary: #{$dark-ocean};
24
+ --prp-bg-button-success: #{$dark-emerald};
25
+
26
+ // Text
27
+ --prp-text-primary: #{$dark-pearl};
28
+ --prp-text-secondary: #{$dark-ash};
29
+ --prp-text-muted: #{$dark-dust};
30
+
31
+ // Borders
32
+ --prp-border-primary: #{$dark-silver};
33
+ --prp-border-light: #{$dark-ash};
34
+
35
+ // Colors
36
+ --prp-color-focus: #{$dark-sky};
37
+ --prp-color-success: #{$dark-emerald};
38
+ --prp-color-error: #{$dark-ruby};
39
+
40
+ // Shadows
41
+ --prp-shadow-light: rgba(0, 0, 0, 0.05);
42
+ --prp-shadow-medium: rgba(0, 0, 0, 0.2);
43
+ --prp-shadow-dark: rgba(0, 0, 0, 0.3);
44
+ --prp-shadow-focus: rgba(102, 178, 255, 0.2);
45
+ }
@@ -1,9 +1,9 @@
1
1
  .panel-button {
2
2
  padding: 0.5rem 1rem;
3
- border: 1px solid #444444;
3
+ border: 1px solid var(--prp-border-primary);
4
4
  border-radius: 4px;
5
- background-color: cornflowerblue;
6
- color: #ffffff;
5
+ background-color: var(--prp-bg-button-primary);
6
+ color: var(--prp-text-primary);
7
7
  font-size: 0.875rem;
8
8
  font-weight: 500;
9
9
  cursor: pointer;
@@ -13,10 +13,10 @@ input.apple-switch {
13
13
  outline: none;
14
14
  width: 50px;
15
15
  height: 30px;
16
- background-color: #fff;
16
+ background-color: var(--prp-bg-white);
17
17
  border: 1px solid #d9dadc;
18
18
  border-radius: 50px;
19
- box-shadow: inset -20px 0 0 0 #fff;
19
+ box-shadow: inset -20px 0 0 0 var(--prp-bg-white);
20
20
  }
21
21
 
22
22
  input.apple-switch:after {
@@ -28,15 +28,15 @@ input.apple-switch:after {
28
28
  width: 26px;
29
29
  height: 26px;
30
30
  border-radius: 50%;
31
- box-shadow: 2px 4px 6px rgba(0, 0, 0, 0.2);
31
+ box-shadow: 2px 4px 6px var(--prp-shadow-medium);
32
32
  }
33
33
 
34
34
  input.apple-switch:checked {
35
- box-shadow: inset 20px 0 0 0 #4ed164;
36
- border-color: #4ed164;
35
+ box-shadow: inset 20px 0 0 0 var(--prp-color-success);
36
+ border-color: var(--prp-color-success);
37
37
  }
38
38
 
39
39
  input.apple-switch:checked:after {
40
40
  left: 20px;
41
- box-shadow: -2px 4px 3px rgba(0, 0, 0, 0.05);
41
+ box-shadow: -2px 4px 3px var(--prp-shadow-light);
42
42
  }
@@ -4,14 +4,14 @@
4
4
  align-items: center;
5
5
  padding: 1rem;
6
6
  margin-bottom: 1.5rem;
7
- background-color: #333333;
7
+ background-color: var(--prp-bg-tertiary);
8
8
  border-radius: 8px 0 0 8px;
9
9
 
10
10
  .form-title {
11
11
  margin: 0;
12
12
  font-size: 1.5rem;
13
13
  font-weight: 600;
14
- color: #cccccc;
14
+ color: var(--prp-text-secondary);
15
15
  }
16
16
 
17
17
  .form-header-inner {
@@ -23,50 +23,52 @@
23
23
  .export-button,
24
24
  .import-button {
25
25
  padding: 0.5rem 1rem;
26
- border: 1px solid #444444;
26
+ border: 1px solid var(--prp-border-primary);
27
27
  border-radius: 4px;
28
- background-color: #222222;
29
- color: #cccccc;
28
+ background-color: var(--prp-bg-secondary);
29
+ color: var(--prp-text-secondary);
30
30
  font-size: 0.875rem;
31
31
  cursor: pointer;
32
32
  transition: all 0.2s ease;
33
33
 
34
34
  &:hover {
35
- background-color: #444444;
36
- border-color: #555555;
35
+ background-color: var(--prp-bg-tertiary);
36
+ border-color: var(--prp-border-primary);
37
37
  }
38
38
  }
39
39
  }
40
40
 
41
41
  &.dark-theme {
42
- background-color: black;
42
+ background-color: var(--prp-bg-primary);
43
43
  box-shadow: none;
44
44
 
45
45
  .form-title {
46
- color: white;
46
+ color: var(--prp-text-primary);
47
47
  }
48
48
 
49
49
  .form-actions {
50
50
  .export-button {
51
- background-color: black;
52
- border-color: black;
53
- color: white;
51
+ background-color: var(--prp-bg-primary);
52
+ border-color: var(--prp-bg-primary);
53
+ color: var(--prp-text-primary);
54
54
 
55
55
  &:hover {
56
- background-color: black;
57
- border-color: black;
56
+ background-color: var(--prp-bg-primary);
57
+ border-color: var(--prp-bg-primary);
58
+ opacity: 0.9;
58
59
  }
59
60
  }
60
61
 
61
62
  .import-button {
62
63
  .import-label {
63
- background-color: black;
64
- border-color: black;
65
- color: white;
64
+ background-color: var(--prp-bg-primary);
65
+ border-color: var(--prp-bg-primary);
66
+ color: var(--prp-text-primary);
66
67
 
67
68
  &:hover {
68
- background-color: black;
69
- border-color: black;
69
+ background-color: var(--prp-bg-primary);
70
+ border-color: var(--prp-bg-primary);
71
+ opacity: 0.9;
70
72
  }
71
73
  }
72
74
  }