elcrm 1.0.0 → 1.1.2
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/README.md +10 -0
- package/dist/index.js +2828 -425
- package/dist/vite/discover-lib.js +4 -4
- package/dist/vite/plugin-css-scoped.js +2 -2
- package/dist/vite/postbuild.d.ts +5 -0
- package/dist/vite/postbuild.js +59 -0
- package/package.json +10 -4
- package/templates/elcrm-cursor/AGENTS.md +13 -0
- package/templates/elcrm-cursor/rules/elcrm-lib.mdc +101 -0
- package/templates/elcrm-cursor/rules/elcrm-module.mdc +25 -0
- package/templates/elcrm-cursor/rules/elcrm-packages.mdc +43 -0
- package/templates/elcrm-cursor/rules/elcrm-rpc.mdc +23 -0
- package/templates/elcrm-cursor/rules/elcrm-server.mdc +30 -0
- package/templates/elcrm-cursor/rules/elcrm-theme.mdc +13 -0
- package/templates/elcrm-cursor/rules/elcrm-ui.mdc +41 -0
- package/templates/elcrm-cursor/rules/elcrm.mdc +43 -0
- package/templates/elcrm-docs/ALERT.elCRM.md +26 -0
- package/templates/elcrm-docs/API.elCRM.md +38 -0
- package/templates/elcrm-docs/BUTTON.elCRM.md +36 -0
- package/templates/elcrm-docs/CLI.elCRM.md +27 -0
- package/templates/elcrm-docs/COMPONENTS.elCRM.md +68 -0
- package/templates/elcrm-docs/FORM.elCRM.md +39 -0
- package/templates/elcrm-docs/ICONS.elCRM.md +40 -0
- package/templates/elcrm-docs/MODAL.elCRM.md +41 -0
- package/templates/elcrm-docs/NOTICE.elCRM.md +31 -0
- package/templates/elcrm-docs/NOTIFICATIONS.elCRM.md +39 -0
- package/templates/elcrm-docs/PASSKEY.elCRM.md +26 -0
- package/templates/elcrm-docs/ROUTER.elCRM.md +34 -0
- package/templates/elcrm-docs/SERVER.elCRM.md +53 -0
- package/templates/elcrm-docs/SOCKET.elCRM.md +34 -0
- package/templates/elcrm-docs/TOOLTIP.elCRM.md +25 -0
- package/templates/panel/README.md +2 -26
- package/templates/panel/api/package.json +2 -5
- package/templates/panel/api/src/index.ts +11 -20
- package/templates/panel/api/src/lib/cron.ts +10 -7
- package/templates/panel/api/src/lib/db.ts +3 -5
- package/templates/panel/api/src/lib/jwt.ts +1 -1
- package/templates/panel/api/src/routes/auth.ts +20 -8
- package/templates/panel/web/package.json +4 -4
- package/templates/panel/web/src/modules/Account/sections/Profile.tsx +0 -1
- package/templates/panel/web/src/modules/Settings/sections/General.tsx +0 -2
- package/templates/panel/web/src/modules/Settings/sections/Profile.tsx +0 -1
- package/templates/panel/web/src/pages/Auth.tsx +0 -1
- package/templates/panel/web/src/style/elcrm.css +4 -1
- package/templates/panel/web/src/style/theme-dark.css +65 -3
- package/templates/panel/web/src/style/theme-light.css +65 -3
- package/templates/panel/web/src/style/theme.css +73 -3
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createRouter,
|
|
3
|
+
rpcErr,
|
|
4
|
+
rpcLogout,
|
|
5
|
+
rpcOk,
|
|
6
|
+
type Middleware,
|
|
7
|
+
} from "@elcrm/server";
|
|
2
8
|
import { db } from "../lib/db";
|
|
3
9
|
import { jwt } from "../lib/jwt";
|
|
4
10
|
|
|
@@ -32,8 +38,19 @@ function publicUser(
|
|
|
32
38
|
};
|
|
33
39
|
}
|
|
34
40
|
|
|
41
|
+
/**
|
|
42
|
+
* createServer уже разобрал ssid → params.user.
|
|
43
|
+
* Не вызываем jwt.init повторно — только наличие user.
|
|
44
|
+
* publicMethods: pass (логин без сессии).
|
|
45
|
+
*/
|
|
46
|
+
const requireUser: Middleware = async ({ path, user }) => {
|
|
47
|
+
if (path[1] === "pass") return;
|
|
48
|
+
if (!user?.id) return rpcLogout();
|
|
49
|
+
};
|
|
50
|
+
|
|
35
51
|
export function registerAuthRoutes() {
|
|
36
52
|
createRouter("auth")
|
|
53
|
+
.use(requireUser)
|
|
37
54
|
.use("pass", async ({ body, headers, jwt: jwtCtx }) => {
|
|
38
55
|
const login = String(body?.login ?? "").trim();
|
|
39
56
|
const password = String(body?.password ?? "");
|
|
@@ -49,7 +66,7 @@ export function registerAuthRoutes() {
|
|
|
49
66
|
|
|
50
67
|
if (!data) return rpcErr("Пользователь не найден");
|
|
51
68
|
if (data.active === 0) {
|
|
52
|
-
return
|
|
69
|
+
return rpcErr("Аккаунт заблокирован", 403);
|
|
53
70
|
}
|
|
54
71
|
if (!data.password || data.password !== jwt.password(password)) {
|
|
55
72
|
return rpcErr("Данные не верны");
|
|
@@ -65,19 +82,14 @@ export function registerAuthRoutes() {
|
|
|
65
82
|
return rpcOk(pub, { ssid });
|
|
66
83
|
})
|
|
67
84
|
.use("me", async ({ user }) => {
|
|
68
|
-
if (!user?.id) return { status: "logout", data: null };
|
|
69
85
|
const row = await db.get<UserRow>(
|
|
70
86
|
`SELECT ${USER_PUBLIC_COLS} FROM users WHERE id = ?`,
|
|
71
87
|
[user.id],
|
|
72
88
|
);
|
|
73
|
-
if (!row || row.active === 0)
|
|
74
|
-
return { status: "logout", data: null };
|
|
75
|
-
}
|
|
89
|
+
if (!row || row.active === 0) return rpcLogout();
|
|
76
90
|
return rpcOk(publicUser(row));
|
|
77
91
|
})
|
|
78
92
|
.use("profile", async ({ user, body }) => {
|
|
79
|
-
if (!user?.id) return { status: "logout", data: null };
|
|
80
|
-
|
|
81
93
|
const display_name = String(
|
|
82
94
|
body?.display_name ?? body?.name ?? "",
|
|
83
95
|
).trim();
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@elcrm/alert": "0.1.1",
|
|
13
13
|
"@elcrm/api": "^0.1.55",
|
|
14
|
-
"@elcrm/button": "1.0.
|
|
14
|
+
"@elcrm/button": "1.0.2",
|
|
15
15
|
"@elcrm/components": "0.0.1",
|
|
16
16
|
"@elcrm/core": "0.1.2",
|
|
17
17
|
"@elcrm/crypto": "0.0.1",
|
|
18
18
|
"@elcrm/error-boundary": "0.0.2",
|
|
19
|
-
"@elcrm/form": "0.
|
|
20
|
-
"@elcrm/modal": "0.0.
|
|
21
|
-
"@elcrm/notice": "0.1.
|
|
19
|
+
"@elcrm/form": "0.1.2",
|
|
20
|
+
"@elcrm/modal": "0.0.34",
|
|
21
|
+
"@elcrm/notice": "0.1.3",
|
|
22
22
|
"@elcrm/notifications": "0.3.1",
|
|
23
23
|
"@elcrm/passkey": "^0.0.1",
|
|
24
24
|
"@elcrm/router": "0.0.58",
|
|
@@ -32,14 +32,12 @@ export default function General() {
|
|
|
32
32
|
form={form}
|
|
33
33
|
label="Имя"
|
|
34
34
|
placeholder="Panel"
|
|
35
|
-
native
|
|
36
35
|
/>
|
|
37
36
|
<StringField
|
|
38
37
|
name="description"
|
|
39
38
|
form={form}
|
|
40
39
|
label="Описание"
|
|
41
40
|
placeholder="Краткое описание"
|
|
42
|
-
native
|
|
43
41
|
/>
|
|
44
42
|
</Section>
|
|
45
43
|
</Section>
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* База пакетов @elcrm/* + обе темы panel.
|
|
3
3
|
* Порядок важен: сначала CSS пакетов, затем theme-* перекрывают токены.
|
|
4
|
+
*
|
|
5
|
+
* @elcrm/button@1.0.2+ — только style.css (цвета кнопок в theme-light/dark).
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
8
|
/* структура компонентов */
|
|
7
9
|
@import "@elcrm/notice/style.css";
|
|
8
10
|
@import "@elcrm/alert/style.css";
|
|
9
|
-
@import "@elcrm/button/themes.css";
|
|
10
11
|
@import "@elcrm/button/style.css";
|
|
11
12
|
@import "@elcrm/search/style.css";
|
|
12
13
|
@import "@elcrm/modal/style.css";
|
|
@@ -17,6 +18,8 @@
|
|
|
17
18
|
@import "@elcrm/form/dark.css";
|
|
18
19
|
@import "@elcrm/alert/light.css";
|
|
19
20
|
@import "@elcrm/alert/dark.css";
|
|
21
|
+
@import "@elcrm/notice/light.css";
|
|
22
|
+
@import "@elcrm/notice/dark.css";
|
|
20
23
|
|
|
21
24
|
/* общие размеры/геометрия, затем цвета light/dark */
|
|
22
25
|
@import "./theme.css";
|
|
@@ -19,6 +19,8 @@ body[data-theme="dark"] {
|
|
|
19
19
|
--shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
|
|
20
20
|
|
|
21
21
|
/* —— button —— */
|
|
22
|
+
--button-focus-ring: rgba(91, 140, 255, 0.55);
|
|
23
|
+
--button-border-primary: 1px solid transparent;
|
|
22
24
|
--button-primary-bg: var(--accent);
|
|
23
25
|
--button-primary-fg: #ffffff;
|
|
24
26
|
--button-primary-hover-bg: #7aa3ff;
|
|
@@ -29,18 +31,42 @@ body[data-theme="dark"] {
|
|
|
29
31
|
--button-secondary-fg: rgba(255, 255, 255, 0.92);
|
|
30
32
|
--button-secondary-hover-bg: rgba(255, 255, 255, 0.12);
|
|
31
33
|
--button-secondary-hover-fg: #ffffff;
|
|
34
|
+
--button-secondary-active-bg: rgba(255, 255, 255, 0.16);
|
|
35
|
+
--button-secondary-active-fg: #ffffff;
|
|
32
36
|
--button-border-secondary: 1px solid var(--line);
|
|
37
|
+
--button-positive-bg: var(--success);
|
|
38
|
+
--button-positive-fg: #0f1216;
|
|
39
|
+
--button-positive-hover-bg: #52e0a0;
|
|
40
|
+
--button-positive-hover-fg: #0f1216;
|
|
41
|
+
--button-positive-active-bg: #2bb872;
|
|
42
|
+
--button-positive-active-fg: #0f1216;
|
|
43
|
+
--button-border-positive: 1px solid transparent;
|
|
44
|
+
--button-negative-bg: var(--danger);
|
|
45
|
+
--button-negative-fg: #ffffff;
|
|
46
|
+
--button-negative-hover-bg: #ff8585;
|
|
47
|
+
--button-negative-hover-fg: #ffffff;
|
|
48
|
+
--button-negative-active-bg: #e05555;
|
|
49
|
+
--button-negative-active-fg: #ffffff;
|
|
50
|
+
--button-border-negative: 1px solid transparent;
|
|
33
51
|
--button-ghost-bg: transparent;
|
|
34
52
|
--button-ghost-fg: var(--muted);
|
|
35
53
|
--button-ghost-hover-bg: rgba(255, 255, 255, 0.06);
|
|
36
54
|
--button-ghost-hover-fg: var(--text);
|
|
55
|
+
--button-ghost-active-bg: rgba(255, 255, 255, 0.1);
|
|
56
|
+
--button-ghost-active-fg: var(--text);
|
|
37
57
|
--button-border-ghost: transparent;
|
|
58
|
+
--button-disabled-bg: rgba(255, 255, 255, 0.08);
|
|
59
|
+
--button-disabled-fg: rgba(255, 255, 255, 0.4);
|
|
60
|
+
--button-border-disabled: 1px solid transparent;
|
|
61
|
+
--button-await-bg: rgba(255, 255, 255, 0.08);
|
|
62
|
+
--button-await-fg: rgba(255, 255, 255, 0.4);
|
|
63
|
+
--button-border-await: 1px solid transparent;
|
|
38
64
|
|
|
39
65
|
/* —— form / control —— */
|
|
40
66
|
--field-border: 1px solid var(--line);
|
|
41
|
-
--field-border-hover:
|
|
42
|
-
--field-border-focus:
|
|
43
|
-
--field-border-disabled:
|
|
67
|
+
--field-border-hover: #3a4558;
|
|
68
|
+
--field-border-focus: var(--accent);
|
|
69
|
+
--field-border-disabled: var(--line);
|
|
44
70
|
--field-focus-ring: rgba(91, 140, 255, 0.28);
|
|
45
71
|
--field-focus-shadow: 0 0 0 3px var(--field-focus-ring);
|
|
46
72
|
--field-background: #0c0f14;
|
|
@@ -52,6 +78,39 @@ body[data-theme="dark"] {
|
|
|
52
78
|
--field-placeholder: var(--muted);
|
|
53
79
|
--field-label-color: var(--muted);
|
|
54
80
|
--field-icon-color: var(--muted);
|
|
81
|
+
|
|
82
|
+
/* —— search (@elcrm/search) —— */
|
|
83
|
+
--search-border: var(--field-border);
|
|
84
|
+
--search-border-focus: var(--field-border-focus);
|
|
85
|
+
--search-background: var(--field-background);
|
|
86
|
+
--search-color: var(--field-color);
|
|
87
|
+
--search-placeholder: var(--field-placeholder);
|
|
88
|
+
--search-icon-color: var(--field-icon-color);
|
|
89
|
+
--search-focus-shadow: var(--field-focus-shadow);
|
|
90
|
+
--search-clear-hover-color: var(--field-color);
|
|
91
|
+
--search-clear-hover-bg: rgba(255, 255, 255, 0.08);
|
|
92
|
+
--search-badge-border: 1px solid var(--line);
|
|
93
|
+
--search-badge-background: rgba(255, 255, 255, 0.06);
|
|
94
|
+
--search-badge-color: var(--muted);
|
|
95
|
+
--search-list-border: 1px solid var(--line);
|
|
96
|
+
--search-list-background: #12161e;
|
|
97
|
+
--search-list-color: var(--field-color);
|
|
98
|
+
--search-list-shadow: 0 10px 28px rgba(0, 0, 0, 0.45);
|
|
99
|
+
--search-option-active-bg: rgba(91, 140, 255, 0.16);
|
|
100
|
+
--search-option-active-color: var(--text);
|
|
101
|
+
--search-option-meta-color: var(--muted);
|
|
102
|
+
--search-ghost-bg: transparent;
|
|
103
|
+
--search-ghost-bg-focus: rgba(255, 255, 255, 0.06);
|
|
104
|
+
--search-ghost-fg: var(--text);
|
|
105
|
+
--search-border-ghost: 1px solid transparent;
|
|
106
|
+
--search-border-ghost-focus: 1px solid var(--line);
|
|
107
|
+
--search-ghost-focus-shadow: none;
|
|
108
|
+
--search-filled-bg: rgba(255, 255, 255, 0.08);
|
|
109
|
+
--search-filled-bg-focus: rgba(255, 255, 255, 0.12);
|
|
110
|
+
--search-filled-fg: var(--text);
|
|
111
|
+
--search-border-filled: 1px solid transparent;
|
|
112
|
+
--search-border-filled-focus: 1px solid var(--line);
|
|
113
|
+
--search-filled-focus-shadow: none;
|
|
55
114
|
--field-check-box-border: 2px solid var(--muted);
|
|
56
115
|
--field-error-border: var(--danger);
|
|
57
116
|
--field-error-color: #ff8e8e;
|
|
@@ -62,6 +121,9 @@ body[data-theme="dark"] {
|
|
|
62
121
|
--select-li-hover-bg: rgba(255, 255, 255, 0.06);
|
|
63
122
|
--select-li-selected-bg: rgba(91, 140, 255, 0.18);
|
|
64
123
|
|
|
124
|
+
/* @elcrm/form — общая тень попапов (Date / Select / Color / Time) */
|
|
125
|
+
--popup-shadow: 0 6px 24px 0 #00000040;
|
|
126
|
+
|
|
65
127
|
/* —— modal / alert / notice —— */
|
|
66
128
|
--modal-background-color: var(--panel-elevated);
|
|
67
129
|
--modal-background-overflow: rgba(0, 0, 0, 0.65);
|
|
@@ -19,6 +19,8 @@ body[data-theme="light"] {
|
|
|
19
19
|
--shadow: 0 8px 24px rgba(26, 31, 41, 0.1);
|
|
20
20
|
|
|
21
21
|
/* —— button —— */
|
|
22
|
+
--button-focus-ring: rgba(59, 110, 245, 0.55);
|
|
23
|
+
--button-border-primary: 1px solid transparent;
|
|
22
24
|
--button-primary-bg: var(--accent);
|
|
23
25
|
--button-primary-fg: #ffffff;
|
|
24
26
|
--button-primary-hover-bg: #2f5de0;
|
|
@@ -29,18 +31,42 @@ body[data-theme="light"] {
|
|
|
29
31
|
--button-secondary-fg: var(--text);
|
|
30
32
|
--button-secondary-hover-bg: #e2e7ef;
|
|
31
33
|
--button-secondary-hover-fg: var(--text);
|
|
34
|
+
--button-secondary-active-bg: #d8dee8;
|
|
35
|
+
--button-secondary-active-fg: var(--text);
|
|
32
36
|
--button-border-secondary: 1px solid var(--line);
|
|
37
|
+
--button-positive-bg: var(--success);
|
|
38
|
+
--button-positive-fg: #ffffff;
|
|
39
|
+
--button-positive-hover-bg: #198a55;
|
|
40
|
+
--button-positive-hover-fg: #ffffff;
|
|
41
|
+
--button-positive-active-bg: #157348;
|
|
42
|
+
--button-positive-active-fg: #ffffff;
|
|
43
|
+
--button-border-positive: 1px solid transparent;
|
|
44
|
+
--button-negative-bg: var(--danger);
|
|
45
|
+
--button-negative-fg: #ffffff;
|
|
46
|
+
--button-negative-hover-bg: #c03c3c;
|
|
47
|
+
--button-negative-hover-fg: #ffffff;
|
|
48
|
+
--button-negative-active-bg: #a83434;
|
|
49
|
+
--button-negative-active-fg: #ffffff;
|
|
50
|
+
--button-border-negative: 1px solid transparent;
|
|
33
51
|
--button-ghost-bg: transparent;
|
|
34
52
|
--button-ghost-fg: var(--muted);
|
|
35
53
|
--button-ghost-hover-bg: rgba(26, 31, 41, 0.06);
|
|
36
54
|
--button-ghost-hover-fg: var(--text);
|
|
55
|
+
--button-ghost-active-bg: rgba(26, 31, 41, 0.1);
|
|
56
|
+
--button-ghost-active-fg: var(--text);
|
|
37
57
|
--button-border-ghost: transparent;
|
|
58
|
+
--button-disabled-bg: #e6e6e6;
|
|
59
|
+
--button-disabled-fg: #6b6b6b;
|
|
60
|
+
--button-border-disabled: 1px solid transparent;
|
|
61
|
+
--button-await-bg: #e6e6e6;
|
|
62
|
+
--button-await-fg: #6b6b6b;
|
|
63
|
+
--button-border-await: 1px solid transparent;
|
|
38
64
|
|
|
39
65
|
/* —— form / control —— */
|
|
40
66
|
--field-border: 1px solid var(--line);
|
|
41
|
-
--field-border-hover:
|
|
42
|
-
--field-border-focus:
|
|
43
|
-
--field-border-disabled:
|
|
67
|
+
--field-border-hover: #b8c0ce;
|
|
68
|
+
--field-border-focus: var(--accent);
|
|
69
|
+
--field-border-disabled: var(--line);
|
|
44
70
|
--field-focus-ring: rgba(59, 110, 245, 0.22);
|
|
45
71
|
--field-focus-shadow: 0 0 0 3px var(--field-focus-ring);
|
|
46
72
|
--field-background: #ffffff;
|
|
@@ -52,6 +78,39 @@ body[data-theme="light"] {
|
|
|
52
78
|
--field-placeholder: var(--muted);
|
|
53
79
|
--field-label-color: var(--muted);
|
|
54
80
|
--field-icon-color: var(--muted);
|
|
81
|
+
|
|
82
|
+
/* —— search (@elcrm/search) —— */
|
|
83
|
+
--search-border: var(--field-border);
|
|
84
|
+
--search-border-focus: var(--field-border-focus);
|
|
85
|
+
--search-background: var(--field-background);
|
|
86
|
+
--search-color: var(--field-color);
|
|
87
|
+
--search-placeholder: var(--field-placeholder);
|
|
88
|
+
--search-icon-color: var(--field-icon-color);
|
|
89
|
+
--search-focus-shadow: var(--field-focus-shadow);
|
|
90
|
+
--search-clear-hover-color: var(--field-color);
|
|
91
|
+
--search-clear-hover-bg: rgba(26, 31, 41, 0.08);
|
|
92
|
+
--search-badge-border: 1px solid var(--line);
|
|
93
|
+
--search-badge-background: #eef1f6;
|
|
94
|
+
--search-badge-color: var(--muted);
|
|
95
|
+
--search-list-border: 1px solid var(--line);
|
|
96
|
+
--search-list-background: var(--field-background);
|
|
97
|
+
--search-list-color: var(--field-color);
|
|
98
|
+
--search-list-shadow: 0 8px 24px rgba(15, 18, 22, 0.12);
|
|
99
|
+
--search-option-active-bg: rgba(59, 110, 245, 0.1);
|
|
100
|
+
--search-option-active-color: var(--text);
|
|
101
|
+
--search-option-meta-color: var(--muted);
|
|
102
|
+
--search-ghost-bg: transparent;
|
|
103
|
+
--search-ghost-bg-focus: rgba(26, 31, 41, 0.04);
|
|
104
|
+
--search-ghost-fg: var(--text);
|
|
105
|
+
--search-border-ghost: 1px solid transparent;
|
|
106
|
+
--search-border-ghost-focus: 1px solid var(--line);
|
|
107
|
+
--search-ghost-focus-shadow: none;
|
|
108
|
+
--search-filled-bg: #eef1f6;
|
|
109
|
+
--search-filled-bg-focus: #e2e7ef;
|
|
110
|
+
--search-filled-fg: var(--text);
|
|
111
|
+
--search-border-filled: 1px solid transparent;
|
|
112
|
+
--search-border-filled-focus: 1px solid var(--line);
|
|
113
|
+
--search-filled-focus-shadow: none;
|
|
55
114
|
--field-check-box-border: 2px solid var(--muted);
|
|
56
115
|
--field-error-border: var(--danger);
|
|
57
116
|
--field-error-color: var(--danger);
|
|
@@ -62,6 +121,9 @@ body[data-theme="light"] {
|
|
|
62
121
|
--select-li-hover-bg: rgba(26, 31, 41, 0.05);
|
|
63
122
|
--select-li-selected-bg: rgba(59, 110, 245, 0.12);
|
|
64
123
|
|
|
124
|
+
/* @elcrm/form — общая тень попапов (Date / Select / Color / Time) */
|
|
125
|
+
--popup-shadow: 0 6px 24px 0 #00000040;
|
|
126
|
+
|
|
65
127
|
/* —— modal / alert / notice —— */
|
|
66
128
|
--modal-background-color: #ffffff;
|
|
67
129
|
--modal-background-overflow: rgba(26, 31, 41, 0.4);
|
|
@@ -3,8 +3,23 @@
|
|
|
3
3
|
* Любой цвет, color-mix, var(--text|--accent|…) — только в theme-light / theme-dark.
|
|
4
4
|
*/
|
|
5
5
|
:root {
|
|
6
|
-
/* —— button —— */
|
|
6
|
+
/* —— button (@elcrm/button: геометрия без цвета) —— */
|
|
7
|
+
--button-height: var(--control-height-m, var(--control-height));
|
|
8
|
+
--button-height-s: var(--control-height-s, 32px);
|
|
9
|
+
--button-height-m: var(--control-height-m, var(--control-height));
|
|
10
|
+
--button-height-l: var(--control-height-l, 48px);
|
|
11
|
+
--button-padding: 0.65em 1em;
|
|
12
|
+
--button-padding-s: 0 8px;
|
|
13
|
+
--button-gap: 0.5em;
|
|
7
14
|
--button-radius: 10px;
|
|
15
|
+
--button-border: 1px solid transparent;
|
|
16
|
+
--button-max-width: 100%;
|
|
17
|
+
--button-min-width-m: 200px;
|
|
18
|
+
--button-transition: 0.18s ease;
|
|
19
|
+
--button-focus-ring-offset: 2px;
|
|
20
|
+
--button-size-s: 14px;
|
|
21
|
+
--button-size-m: 16px;
|
|
22
|
+
--button-size-l: 18px;
|
|
8
23
|
--button-shadow: none;
|
|
9
24
|
--button-shadow-hover: none;
|
|
10
25
|
--button-shadow-active: none;
|
|
@@ -12,18 +27,73 @@
|
|
|
12
27
|
--button-primary-hover-shadow: none;
|
|
13
28
|
--button-primary-active-shadow: none;
|
|
14
29
|
--button-secondary-shadow: none;
|
|
30
|
+
--button-secondary-hover-shadow: none;
|
|
31
|
+
--button-secondary-active-shadow: none;
|
|
32
|
+
--button-positive-shadow: none;
|
|
33
|
+
--button-positive-hover-shadow: none;
|
|
34
|
+
--button-positive-active-shadow: none;
|
|
35
|
+
--button-negative-shadow: none;
|
|
36
|
+
--button-negative-hover-shadow: none;
|
|
37
|
+
--button-negative-active-shadow: none;
|
|
38
|
+
--button-ghost-shadow: none;
|
|
39
|
+
--button-ghost-hover-shadow: none;
|
|
40
|
+
--button-ghost-active-shadow: none;
|
|
15
41
|
|
|
16
42
|
/* —— form / control —— */
|
|
17
43
|
--control-height: 44px;
|
|
44
|
+
--control-height-s: 32px;
|
|
45
|
+
--control-height-m: var(--control-height);
|
|
46
|
+
--control-height-l: 48px;
|
|
18
47
|
--control-radius: 10px;
|
|
19
|
-
--control-side-padding: 14px;
|
|
20
48
|
--control-font-size: 15px;
|
|
21
49
|
--field-height: var(--control-height);
|
|
22
50
|
--field-width: 100%;
|
|
23
|
-
--field-
|
|
51
|
+
/* единый padding капсулы (size s|m|l → через --field-height) */
|
|
52
|
+
--field-padding-block: calc(var(--field-height) * 0.18);
|
|
53
|
+
--field-padding-inline: calc(var(--field-height) * 0.32);
|
|
54
|
+
--field-padding: var(--field-padding-block) var(--field-padding-inline);
|
|
24
55
|
--field-radius: var(--control-radius);
|
|
25
56
|
--field-label-size: 13px;
|
|
26
57
|
|
|
58
|
+
/* —— search (@elcrm/search: геометрия без цвета) —— */
|
|
59
|
+
--search-height-s: var(--control-height-s);
|
|
60
|
+
--search-height-m: var(--control-height-m);
|
|
61
|
+
--search-height-l: var(--control-height-l);
|
|
62
|
+
--search-size-s: 13px;
|
|
63
|
+
--search-size-m: var(--control-font-size);
|
|
64
|
+
--search-size-l: 17px;
|
|
65
|
+
--search-padding-x: 10px;
|
|
66
|
+
--search-padding-x-s: 8px;
|
|
67
|
+
--search-padding-x-l: 12px;
|
|
68
|
+
--search-gap: 8px;
|
|
69
|
+
--search-gap-s: 6px;
|
|
70
|
+
--search-gap-l: 10px;
|
|
71
|
+
--search-radius: var(--field-radius);
|
|
72
|
+
--search-min-width-m: 200px;
|
|
73
|
+
--search-minimal-expand-min: 180px;
|
|
74
|
+
--search-icon-size: 15px;
|
|
75
|
+
--search-icon-stroke: 1.5;
|
|
76
|
+
--search-icon-opacity: 0.85;
|
|
77
|
+
--search-clear-size: 22px;
|
|
78
|
+
--search-clear-radius: 6px;
|
|
79
|
+
--search-transition: 0.22s ease;
|
|
80
|
+
--search-disabled-opacity: 0.7;
|
|
81
|
+
--search-spinner-duration: 0.7s;
|
|
82
|
+
--search-after-gap: 4px;
|
|
83
|
+
--search-badge-font-size: 11px;
|
|
84
|
+
--search-badge-padding: 2px 5px;
|
|
85
|
+
--search-badge-radius: 6px;
|
|
86
|
+
--search-list-z: 40;
|
|
87
|
+
--search-list-offset: 6px;
|
|
88
|
+
--search-list-padding: 6px;
|
|
89
|
+
--search-list-max-height: 240px;
|
|
90
|
+
--search-list-radius: 10px;
|
|
91
|
+
--search-option-padding: 8px 10px;
|
|
92
|
+
--search-option-radius: 8px;
|
|
93
|
+
--search-option-meta-size: 12px;
|
|
94
|
+
--search-border-ghost: 1px solid transparent;
|
|
95
|
+
--search-border-filled: 1px solid transparent;
|
|
96
|
+
|
|
27
97
|
/* —— modal —— */
|
|
28
98
|
--modal-radius: 12px;
|
|
29
99
|
|