djm-ui 0.67.4 → 0.73.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/CHANGELOG.md +116 -0
- package/README.md +38 -2
- package/dist/djm-ui.cjs +1625 -803
- package/dist/djm-ui.cjs.map +4 -4
- package/dist/djm-ui.css +1043 -41
- package/dist/djm-ui.esm.js +1581 -761
- package/dist/djm-ui.esm.js.map +4 -4
- package/dist/djm-ui.esm.min.js +439 -247
- package/dist/djm-ui.min.cjs +439 -247
- package/dist/djm-ui.min.css +2 -2
- package/dist/djm-ui.umd.js +1104 -285
- package/dist/djm-ui.umd.min.js +439 -247
- package/dist/mcp/manifest.json +12300 -0
- package/dist/mcp/server.js +90 -0
- package/package.json +12 -4
- package/src/components/drawer/index.js +4 -2
- package/src/components/icon/index.js +13 -1
- package/src/components/modal/index.js +4 -2
- package/src/components/progress/index.js +72 -3
- package/src/components/rich-editor/index.js +724 -61
- package/src/components/spin/index.js +69 -22
- package/src/index.js +2 -1
- package/src/locale/en-US.js +33 -1
- package/src/locale/zh-CN.js +33 -1
- package/src/styles/base.css +2 -3
- package/src/styles/components/button.css +2 -1
- package/src/styles/components/console.css +5 -0
- package/src/styles/components/content.css +517 -0
- package/src/styles/components/feedback.css +46 -0
- package/src/styles/components/form.css +5 -0
- package/src/styles/components/glass.css +58 -0
- package/src/styles/components/layout.css +326 -0
- package/src/styles/components/media-picker.css +3 -3
- package/src/styles/components/menu.css +2 -1
- package/src/styles/components/org-picker.css +1 -1
- package/src/styles/components/responsive.css +86 -0
- package/src/styles/components/rich-editor.css +206 -7
- package/src/styles/components/skin.css +54 -0
- package/src/styles/components/spin.css +156 -4
- package/src/styles/components/template.css +5 -0
- package/src/styles/index.css +2 -0
- package/src/styles/theme-dark.css +5 -0
- package/src/styles/tokens.css +13 -0
- package/src/theme/index.js +62 -0
- package/src/utils/sanitize-html.js +44 -6
- package/types/index.d.ts +17 -0
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
/* ---------------- 富文本编辑器 ---------------- */
|
|
4
4
|
|
|
5
5
|
.djm-rich-editor {
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
6
8
|
border: 1px solid var(--djm-border-strong);
|
|
7
9
|
border-radius: 4px;
|
|
8
10
|
overflow: hidden;
|
|
@@ -14,11 +16,26 @@
|
|
|
14
16
|
box-shadow: var(--djm-ring);
|
|
15
17
|
}
|
|
16
18
|
|
|
19
|
+
/* 全屏:铺满视口,内容区自己滚动 */
|
|
20
|
+
.djm-rich-editor.djm-is-fullscreen {
|
|
21
|
+
position: fixed;
|
|
22
|
+
inset: 0;
|
|
23
|
+
z-index: 1200;
|
|
24
|
+
border: 0;
|
|
25
|
+
border-radius: 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.djm-rich-editor.djm-is-fullscreen .djm-rich-editor-content,
|
|
29
|
+
.djm-rich-editor.djm-is-fullscreen .djm-rich-editor-source {
|
|
30
|
+
flex: 1;
|
|
31
|
+
max-height: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
17
34
|
.djm-rich-editor-toolbar {
|
|
18
35
|
display: flex;
|
|
19
36
|
align-items: center;
|
|
20
37
|
flex-wrap: wrap;
|
|
21
|
-
gap:
|
|
38
|
+
gap: 2px;
|
|
22
39
|
padding: 5px 6px;
|
|
23
40
|
border-bottom: 1px solid var(--djm-border);
|
|
24
41
|
background: var(--djm-surface-2);
|
|
@@ -26,9 +43,9 @@
|
|
|
26
43
|
|
|
27
44
|
.djm-rich-editor-group {
|
|
28
45
|
display: flex;
|
|
29
|
-
gap:
|
|
30
|
-
padding-right:
|
|
31
|
-
margin-right:
|
|
46
|
+
gap: 1px;
|
|
47
|
+
padding-right: 4px;
|
|
48
|
+
margin-right: 2px;
|
|
32
49
|
border-right: 1px solid var(--djm-border);
|
|
33
50
|
}
|
|
34
51
|
|
|
@@ -36,10 +53,92 @@
|
|
|
36
53
|
border-right: 0;
|
|
37
54
|
}
|
|
38
55
|
|
|
56
|
+
/* 段落格式 / 字号下拉 */
|
|
57
|
+
.djm-rich-editor-select {
|
|
58
|
+
height: 26px;
|
|
59
|
+
padding: 0 2px;
|
|
60
|
+
border: 1px solid var(--djm-border);
|
|
61
|
+
border-radius: 3px;
|
|
62
|
+
background: var(--djm-surface);
|
|
63
|
+
color: var(--djm-text-2);
|
|
64
|
+
font: inherit;
|
|
65
|
+
font-size: 11.5px;
|
|
66
|
+
cursor: pointer;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.djm-rich-editor-select-size {
|
|
70
|
+
width: 64px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.djm-rich-editor-select:focus-visible {
|
|
74
|
+
outline: 2px solid var(--djm-brand-500);
|
|
75
|
+
outline-offset: -1px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.djm-rich-editor-select:disabled {
|
|
79
|
+
opacity: 0.5;
|
|
80
|
+
cursor: not-allowed;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* 颜色按钮:字母底部带当前色,背景色按钮直接把颜色铺在字母上 */
|
|
84
|
+
.djm-rich-editor-color {
|
|
85
|
+
position: relative;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.djm-rich-editor-letter {
|
|
89
|
+
display: inline-block;
|
|
90
|
+
padding-bottom: 1px;
|
|
91
|
+
border-bottom: 2px solid var(--djm-text);
|
|
92
|
+
font-size: 12px;
|
|
93
|
+
font-weight: 600;
|
|
94
|
+
line-height: 1;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.djm-rich-editor-letter-bg {
|
|
98
|
+
padding: 0 3px;
|
|
99
|
+
border-bottom: 0;
|
|
100
|
+
border-radius: 2px;
|
|
101
|
+
color: var(--djm-text);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.djm-rich-editor-panel {
|
|
105
|
+
position: absolute;
|
|
106
|
+
top: calc(100% + 4px);
|
|
107
|
+
left: 0;
|
|
108
|
+
z-index: 5;
|
|
109
|
+
display: grid;
|
|
110
|
+
grid-template-columns: repeat(4, 20px);
|
|
111
|
+
gap: 4px;
|
|
112
|
+
padding: 6px;
|
|
113
|
+
border: 1px solid var(--djm-border);
|
|
114
|
+
border-radius: 6px;
|
|
115
|
+
background: var(--djm-surface);
|
|
116
|
+
box-shadow: var(--djm-shadow-md);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.djm-rich-editor-swatch {
|
|
120
|
+
width: 20px;
|
|
121
|
+
height: 20px;
|
|
122
|
+
padding: 0;
|
|
123
|
+
border: 1px solid var(--djm-border);
|
|
124
|
+
border-radius: 4px;
|
|
125
|
+
cursor: pointer;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.djm-rich-editor-swatch:hover {
|
|
129
|
+
border-color: var(--djm-brand-500);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* 素材库按钮:媒体选择器默认是块级 span,塞进工具栏里要收成行内 */
|
|
133
|
+
.djm-rich-editor-picker {
|
|
134
|
+
display: inline-flex;
|
|
135
|
+
align-items: center;
|
|
136
|
+
}
|
|
137
|
+
|
|
39
138
|
.djm-rich-editor-btn {
|
|
40
|
-
min-width:
|
|
139
|
+
min-width: 24px;
|
|
41
140
|
height: 26px;
|
|
42
|
-
padding: 0
|
|
141
|
+
padding: 0 4px;
|
|
43
142
|
display: inline-flex;
|
|
44
143
|
align-items: center;
|
|
45
144
|
justify-content: center;
|
|
@@ -122,11 +221,93 @@
|
|
|
122
221
|
color: var(--djm-text-3);
|
|
123
222
|
}
|
|
124
223
|
|
|
125
|
-
.djm-rich-editor-content
|
|
224
|
+
.djm-rich-editor-content h1,
|
|
225
|
+
.djm-rich-editor-content h2,
|
|
226
|
+
.djm-rich-editor-content h3 {
|
|
126
227
|
margin: 0 0 8px;
|
|
228
|
+
color: var(--djm-text);
|
|
229
|
+
line-height: 1.5;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.djm-rich-editor-content h1 {
|
|
233
|
+
font-size: 20px;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.djm-rich-editor-content h2 {
|
|
127
237
|
font-size: 16px;
|
|
128
238
|
}
|
|
129
239
|
|
|
240
|
+
.djm-rich-editor-content h3 {
|
|
241
|
+
font-size: 14px;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.djm-rich-editor-content blockquote {
|
|
245
|
+
margin: 0 0 8px;
|
|
246
|
+
padding: 4px 10px;
|
|
247
|
+
border-left: 3px solid var(--djm-brand-500);
|
|
248
|
+
background: var(--djm-surface-2);
|
|
249
|
+
color: var(--djm-text-2);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.djm-rich-editor-content pre {
|
|
253
|
+
margin: 0 0 8px;
|
|
254
|
+
padding: 10px 12px;
|
|
255
|
+
overflow: auto;
|
|
256
|
+
border-radius: 4px;
|
|
257
|
+
background: var(--djm-surface-3);
|
|
258
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
259
|
+
font-size: 12px;
|
|
260
|
+
line-height: 1.7;
|
|
261
|
+
white-space: pre-wrap;
|
|
262
|
+
word-break: break-word;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.djm-rich-editor-content code {
|
|
266
|
+
padding: 1px 4px;
|
|
267
|
+
border-radius: 3px;
|
|
268
|
+
background: var(--djm-surface-3);
|
|
269
|
+
color: var(--djm-brand-700);
|
|
270
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
271
|
+
font-size: 12px;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.djm-rich-editor-content pre code {
|
|
275
|
+
padding: 0;
|
|
276
|
+
background: none;
|
|
277
|
+
color: inherit;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.djm-rich-editor-content hr {
|
|
281
|
+
margin: 12px 0;
|
|
282
|
+
border: 0;
|
|
283
|
+
border-top: 1px solid var(--djm-border);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* 图片:单图、多图统一限宽,避免撑破内容区 */
|
|
287
|
+
.djm-rich-editor-content img {
|
|
288
|
+
max-width: 100%;
|
|
289
|
+
height: auto;
|
|
290
|
+
border-radius: 4px;
|
|
291
|
+
vertical-align: bottom;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/* 上传插入的图片之间留一点间距,多图并排时不粘在一起 */
|
|
295
|
+
.djm-rich-editor-img {
|
|
296
|
+
margin: 2px 4px 2px 0;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/* 上传中的占位块,上传完成后被图片替换 */
|
|
300
|
+
.djm-rich-editor-uploading {
|
|
301
|
+
display: inline-flex;
|
|
302
|
+
align-items: center;
|
|
303
|
+
padding: 4px 10px;
|
|
304
|
+
border: 1px dashed var(--djm-border-strong);
|
|
305
|
+
border-radius: 4px;
|
|
306
|
+
background: var(--djm-surface-2);
|
|
307
|
+
color: var(--djm-text-3);
|
|
308
|
+
font-size: 12px;
|
|
309
|
+
}
|
|
310
|
+
|
|
130
311
|
.djm-rich-editor-content p {
|
|
131
312
|
margin: 0 0 8px;
|
|
132
313
|
}
|
|
@@ -154,6 +335,24 @@
|
|
|
154
335
|
line-height: 1.7;
|
|
155
336
|
}
|
|
156
337
|
|
|
338
|
+
/* 底部状态:上传提示与字数 */
|
|
339
|
+
.djm-rich-editor-foot {
|
|
340
|
+
display: flex;
|
|
341
|
+
align-items: center;
|
|
342
|
+
justify-content: flex-end;
|
|
343
|
+
gap: 12px;
|
|
344
|
+
padding: 4px 12px;
|
|
345
|
+
border-top: 1px solid var(--djm-border);
|
|
346
|
+
background: var(--djm-surface-2);
|
|
347
|
+
color: var(--djm-text-3);
|
|
348
|
+
font-size: 11px;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/* 文件选择框只作为上传入口,不显示 */
|
|
352
|
+
.djm-rich-editor-file {
|
|
353
|
+
display: none;
|
|
354
|
+
}
|
|
355
|
+
|
|
157
356
|
.djm-editor-bar {
|
|
158
357
|
display: flex;
|
|
159
358
|
align-items: center;
|
|
@@ -18,6 +18,60 @@
|
|
|
18
18
|
color: var(--djm-text-3);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
/* 预设方案:一排小卡片,配色条直接预览效果 */
|
|
22
|
+
.djm-skin-presets {
|
|
23
|
+
display: grid;
|
|
24
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
25
|
+
gap: 6px;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.djm-skin-preset {
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
gap: 5px;
|
|
32
|
+
padding: 5px;
|
|
33
|
+
border: 1px solid var(--djm-border);
|
|
34
|
+
border-radius: var(--djm-radius);
|
|
35
|
+
background: var(--djm-surface);
|
|
36
|
+
color: var(--djm-text-2);
|
|
37
|
+
font-size: 11.5px;
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.djm-skin-preset:hover {
|
|
42
|
+
border-color: var(--djm-border-strong);
|
|
43
|
+
color: var(--djm-text);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.djm-skin-preset.djm-is-active {
|
|
47
|
+
border-color: var(--djm-brand-500);
|
|
48
|
+
box-shadow: var(--djm-ring);
|
|
49
|
+
color: var(--djm-brand-700);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.djm-skin-swatch {
|
|
53
|
+
height: 22px;
|
|
54
|
+
border: 1px solid var(--djm-border);
|
|
55
|
+
border-radius: 3px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.djm-skin-preset-label {
|
|
59
|
+
text-align: center;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.djm-skin-hint {
|
|
63
|
+
margin: 0;
|
|
64
|
+
font-size: 11.5px;
|
|
65
|
+
color: var(--djm-text-3);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.djm-skin-preset:focus-visible,
|
|
69
|
+
.djm-skin-seg-btn:focus-visible,
|
|
70
|
+
.djm-skin-color:focus-visible {
|
|
71
|
+
outline: 2px solid var(--djm-brand-500);
|
|
72
|
+
outline-offset: 1px;
|
|
73
|
+
}
|
|
74
|
+
|
|
21
75
|
/* 分段按钮:用两个按钮表达互斥选择,避免额外角色语义 */
|
|
22
76
|
.djm-skin-seg {
|
|
23
77
|
display: flex;
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
/* DJM UI · 加载中 */
|
|
2
2
|
|
|
3
|
+
.djm-spin {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
color: var(--djm-brand-600);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* 包裹模式:内容上方盖一层遮罩 */
|
|
3
10
|
.djm-spin-wrap {
|
|
4
11
|
position: relative;
|
|
12
|
+
display: block;
|
|
5
13
|
min-height: 60px;
|
|
6
14
|
}
|
|
7
15
|
|
|
8
|
-
/* 遮罩铺满被包裹内容,圆角跟随容器 */
|
|
9
16
|
.djm-spin-mask {
|
|
10
17
|
position: absolute;
|
|
11
18
|
inset: 0;
|
|
@@ -17,13 +24,35 @@
|
|
|
17
24
|
gap: 8px;
|
|
18
25
|
border-radius: inherit;
|
|
19
26
|
background: var(--djm-loading-mask);
|
|
20
|
-
backdrop-filter: blur(
|
|
27
|
+
-webkit-backdrop-filter: blur(2px);
|
|
28
|
+
backdrop-filter: blur(2px);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* 内联模式:指示器与文字并排,不铺底 */
|
|
32
|
+
.djm-spin-inline .djm-spin-mask {
|
|
33
|
+
position: static;
|
|
34
|
+
flex-direction: row;
|
|
35
|
+
gap: 8px;
|
|
36
|
+
border-radius: 0;
|
|
37
|
+
background: none;
|
|
38
|
+
-webkit-backdrop-filter: none;
|
|
39
|
+
backdrop-filter: none;
|
|
21
40
|
}
|
|
22
41
|
|
|
23
|
-
|
|
42
|
+
/* 全屏模式:遮罩铺满视口 */
|
|
43
|
+
.djm-spin-fullscreen {
|
|
44
|
+
position: fixed;
|
|
45
|
+
inset: 0;
|
|
46
|
+
z-index: var(--djm-z-toast);
|
|
47
|
+
display: flex;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.djm-spin-indicator {
|
|
24
51
|
display: inline-flex;
|
|
25
52
|
align-items: center;
|
|
26
|
-
|
|
53
|
+
justify-content: center;
|
|
54
|
+
gap: 4px;
|
|
55
|
+
color: inherit;
|
|
27
56
|
}
|
|
28
57
|
|
|
29
58
|
.djm-spin-tip {
|
|
@@ -31,6 +60,8 @@
|
|
|
31
60
|
color: var(--djm-text-2);
|
|
32
61
|
}
|
|
33
62
|
|
|
63
|
+
/* ---------------- 尺寸 ---------------- */
|
|
64
|
+
|
|
34
65
|
.djm-spin-sm .djm-spinner {
|
|
35
66
|
width: 11px;
|
|
36
67
|
height: 11px;
|
|
@@ -42,3 +73,124 @@
|
|
|
42
73
|
height: 22px;
|
|
43
74
|
border-width: 2.5px;
|
|
44
75
|
}
|
|
76
|
+
|
|
77
|
+
/* ---------------- 形态 ---------------- */
|
|
78
|
+
|
|
79
|
+
/* 环形:颜色跟随 color 属性 */
|
|
80
|
+
.djm-spin-ring .djm-spinner {
|
|
81
|
+
border-top-color: currentColor;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* 点状:三点依次弹起 */
|
|
85
|
+
.djm-spin-dots i {
|
|
86
|
+
width: 6px;
|
|
87
|
+
height: 6px;
|
|
88
|
+
border-radius: 50%;
|
|
89
|
+
background: currentColor;
|
|
90
|
+
animation: djm-spin-dot 1s ease-in-out infinite;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.djm-spin-dots i:nth-child(2) {
|
|
94
|
+
animation-delay: 0.15s;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.djm-spin-dots i:nth-child(3) {
|
|
98
|
+
animation-delay: 0.3s;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.djm-spin-sm .djm-spin-dots i {
|
|
102
|
+
width: 4px;
|
|
103
|
+
height: 4px;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.djm-spin-lg .djm-spin-dots i {
|
|
107
|
+
width: 8px;
|
|
108
|
+
height: 8px;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@keyframes djm-spin-dot {
|
|
112
|
+
0%,
|
|
113
|
+
80%,
|
|
114
|
+
100% {
|
|
115
|
+
transform: scale(0.55);
|
|
116
|
+
opacity: 0.45;
|
|
117
|
+
}
|
|
118
|
+
40% {
|
|
119
|
+
transform: scale(1);
|
|
120
|
+
opacity: 1;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* 柱状:四根竖条错峰伸缩 */
|
|
125
|
+
.djm-spin-bars i {
|
|
126
|
+
width: 3px;
|
|
127
|
+
height: 14px;
|
|
128
|
+
border-radius: 2px;
|
|
129
|
+
background: currentColor;
|
|
130
|
+
animation: djm-spin-bar 1s ease-in-out infinite;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.djm-spin-bars i:nth-child(2) {
|
|
134
|
+
animation-delay: 0.12s;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.djm-spin-bars i:nth-child(3) {
|
|
138
|
+
animation-delay: 0.24s;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.djm-spin-bars i:nth-child(4) {
|
|
142
|
+
animation-delay: 0.36s;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.djm-spin-sm .djm-spin-bars i {
|
|
146
|
+
width: 2.5px;
|
|
147
|
+
height: 10px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.djm-spin-lg .djm-spin-bars i {
|
|
151
|
+
width: 4px;
|
|
152
|
+
height: 18px;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@keyframes djm-spin-bar {
|
|
156
|
+
0%,
|
|
157
|
+
100% {
|
|
158
|
+
transform: scaleY(0.45);
|
|
159
|
+
opacity: 0.5;
|
|
160
|
+
}
|
|
161
|
+
50% {
|
|
162
|
+
transform: scaleY(1);
|
|
163
|
+
opacity: 1;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* 脉冲:实心圆呼吸 */
|
|
168
|
+
.djm-spin-pulse .djm-spin-core {
|
|
169
|
+
width: 16px;
|
|
170
|
+
height: 16px;
|
|
171
|
+
border-radius: 50%;
|
|
172
|
+
background: currentColor;
|
|
173
|
+
animation: djm-spin-pulse 1.2s ease-in-out infinite;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.djm-spin-sm .djm-spin-pulse .djm-spin-core {
|
|
177
|
+
width: 12px;
|
|
178
|
+
height: 12px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.djm-spin-lg .djm-spin-pulse .djm-spin-core {
|
|
182
|
+
width: 22px;
|
|
183
|
+
height: 22px;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
@keyframes djm-spin-pulse {
|
|
187
|
+
0%,
|
|
188
|
+
100% {
|
|
189
|
+
transform: scale(0.65);
|
|
190
|
+
opacity: 0.45;
|
|
191
|
+
}
|
|
192
|
+
50% {
|
|
193
|
+
transform: scale(1);
|
|
194
|
+
opacity: 1;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -194,6 +194,11 @@
|
|
|
194
194
|
color: #fff;
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
/* 暗色下品牌色阶整体提亮,白字压不住,单独换深蓝渐变 */
|
|
198
|
+
[data-djm-theme="dark"] .djm-login-brand {
|
|
199
|
+
background: linear-gradient(150deg, #0d2236, #123c5f 62%, #17527f);
|
|
200
|
+
}
|
|
201
|
+
|
|
197
202
|
.djm-login-brand-inner {
|
|
198
203
|
max-width: 380px;
|
|
199
204
|
display: flex;
|
package/src/styles/index.css
CHANGED
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
@import './components/query-filter.css';
|
|
76
76
|
@import './components/filter-tags.css';
|
|
77
77
|
@import './components/media-picker.css';
|
|
78
|
+
@import './components/content.css';
|
|
78
79
|
@import './components/kanban.css';
|
|
79
80
|
@import './components/attachment-list.css';
|
|
80
81
|
@import './components/notification.css';
|
|
@@ -106,4 +107,5 @@
|
|
|
106
107
|
@import './components/grid.css';
|
|
107
108
|
@import './components/frame.css';
|
|
108
109
|
@import './components/charts.css';
|
|
110
|
+
@import './components/glass.css';
|
|
109
111
|
@import './components/responsive.css';
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
--djm-hover: #262e38;
|
|
30
30
|
--djm-brand-soft: #1a3049;
|
|
31
31
|
--djm-glass: rgba(20, 25, 31, 0.94);
|
|
32
|
+
--djm-glass-bg: rgba(25, 31, 38, 0.72);
|
|
33
|
+
--djm-glass-border: rgba(255, 255, 255, 0.12);
|
|
34
|
+
--djm-glass-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.6);
|
|
32
35
|
--djm-loading-mask: rgba(25, 31, 38, 0.78);
|
|
33
36
|
--djm-border: #2b333d;
|
|
34
37
|
--djm-border-strong: #3c4652;
|
|
@@ -38,6 +41,8 @@
|
|
|
38
41
|
--djm-text-side: #c2ccd8;
|
|
39
42
|
--djm-text-2: #a6b2c0;
|
|
40
43
|
--djm-text-3: #8492a1;
|
|
44
|
+
/* 暗色下提示框比页面背景亮一档,白字仍有足够对比 */
|
|
45
|
+
--djm-tooltip-bg: #3a4652;
|
|
41
46
|
/* 暗色下水印改用浅色,保持可辨识 */
|
|
42
47
|
--djm-watermark: rgba(232, 237, 243, 0.12);
|
|
43
48
|
|
package/src/styles/tokens.css
CHANGED
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
:root {
|
|
16
16
|
color-scheme: light;
|
|
17
17
|
|
|
18
|
+
/* 字体族:宿主页面可通过覆盖这两个变量统一换字体 */
|
|
19
|
+
--djm-font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
|
|
20
|
+
"Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
|
21
|
+
--djm-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
22
|
+
|
|
18
23
|
--djm-brand-50: #eef6fe;
|
|
19
24
|
--djm-brand-100: #dcebfb;
|
|
20
25
|
--djm-brand-200: #b9d7f6;
|
|
@@ -34,6 +39,11 @@
|
|
|
34
39
|
--djm-hover: #eef3f9;
|
|
35
40
|
--djm-brand-soft: #eaf3fd;
|
|
36
41
|
--djm-glass: rgba(248, 250, 253, 0.96);
|
|
42
|
+
/* 毛玻璃:默认关闭,data-djm-glass="on" 或 .djm-glass 时生效 */
|
|
43
|
+
--djm-glass-bg: rgba(255, 255, 255, 0.72);
|
|
44
|
+
--djm-glass-border: rgba(255, 255, 255, 0.6);
|
|
45
|
+
--djm-glass-blur: 16px;
|
|
46
|
+
--djm-glass-shadow: 0 10px 30px -12px rgba(16, 40, 70, 0.28);
|
|
37
47
|
--djm-loading-mask: rgba(255, 255, 255, 0.74);
|
|
38
48
|
--djm-border: #dde6f0;
|
|
39
49
|
--djm-border-strong: #cbd7e5;
|
|
@@ -66,6 +76,9 @@
|
|
|
66
76
|
/* 彩色底上的文字(两主题均为白色) */
|
|
67
77
|
--djm-text-inverse: #fff;
|
|
68
78
|
|
|
79
|
+
/* 文字提示的深底:暗色主题改用略亮的灰,避免和页面背景糊在一起 */
|
|
80
|
+
--djm-tooltip-bg: #1f2a37;
|
|
81
|
+
|
|
69
82
|
/* 盖在图片等媒体内容上的蒙层,不随主题变化 */
|
|
70
83
|
--djm-media-mask: rgba(9, 20, 33, 0.55);
|
|
71
84
|
|
package/src/theme/index.js
CHANGED
|
@@ -2,8 +2,11 @@ import { ref } from 'vue'
|
|
|
2
2
|
|
|
3
3
|
const KEY = 'djm-theme'
|
|
4
4
|
const COLOR_KEY = 'djm-primary'
|
|
5
|
+
const GLASS_KEY = 'djm-glass'
|
|
5
6
|
|
|
6
7
|
export const theme = ref('light')
|
|
8
|
+
// 毛玻璃开关:写入 data-djm-glass,组件样式按需切换
|
|
9
|
+
export const glass = ref(false)
|
|
7
10
|
|
|
8
11
|
/** 预设主题色:色值取自常见后台品牌色 */
|
|
9
12
|
export const PRESET_COLORS = [
|
|
@@ -139,6 +142,46 @@ export function setPrimaryColor (hex) {
|
|
|
139
142
|
}
|
|
140
143
|
}
|
|
141
144
|
|
|
145
|
+
/* 相对亮度与对比度:侧栏选中态按色相自动找合适的明度 */
|
|
146
|
+
function luminance (hex) {
|
|
147
|
+
const text = String(hex).replace('#', '')
|
|
148
|
+
const rgb = [0, 2, 4].map((i) => parseInt(text.slice(i, i + 2), 16) / 255)
|
|
149
|
+
const [r, g, b] = rgb.map((v) => (v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4))
|
|
150
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function contrastRatio (a, b) {
|
|
154
|
+
const l1 = luminance(a)
|
|
155
|
+
const l2 = luminance(b)
|
|
156
|
+
return (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 侧栏单独配色时用:按主色生成一套色阶
|
|
161
|
+
* 侧栏可能和页面主题反向(浅色页 + 深色侧栏),所以由调用方指定明暗
|
|
162
|
+
*/
|
|
163
|
+
export function sidebarShades (hex, dark) {
|
|
164
|
+
const shades = buildShades(hex || '#1a6fc4', dark)
|
|
165
|
+
if (dark) {
|
|
166
|
+
const { h, s } = hexToHsl(hex || '#1a6fc4')
|
|
167
|
+
const sat = Math.min(Math.max(s, 20), 92)
|
|
168
|
+
const bgSat = Math.min(78, sat * 0.85)
|
|
169
|
+
// 选中文字固定在亮档,背景从 36% 明度往下压,直到对比度过 4.5
|
|
170
|
+
// 这样青碧、橙、墨绿不会再选出一团看不清的深色
|
|
171
|
+
const text = hslToHex(h, Math.min(90, sat), 86)
|
|
172
|
+
let bgL = 36
|
|
173
|
+
let bg = hslToHex(h, bgSat, bgL)
|
|
174
|
+
while (bgL > 18 && contrastRatio(bg, text) < 4.6) {
|
|
175
|
+
bgL -= 2
|
|
176
|
+
bg = hslToHex(h, bgSat, bgL)
|
|
177
|
+
}
|
|
178
|
+
shades['--djm-sider-active'] = bg
|
|
179
|
+
shades['--djm-sider-active-hover'] = hslToHex(h, bgSat, Math.max(14, bgL - 4))
|
|
180
|
+
shades['--djm-sider-active-text'] = text
|
|
181
|
+
}
|
|
182
|
+
return shades
|
|
183
|
+
}
|
|
184
|
+
|
|
142
185
|
export function resetPrimaryColor () {
|
|
143
186
|
setPrimaryColor('')
|
|
144
187
|
}
|
|
@@ -160,6 +203,18 @@ export function toggleTheme () {
|
|
|
160
203
|
setTheme(theme.value === 'dark' ? 'light' : 'dark')
|
|
161
204
|
}
|
|
162
205
|
|
|
206
|
+
/** 毛玻璃开关:默认关闭,开启后弹窗、抽屉、浮层与卡片换半透明底 */
|
|
207
|
+
export function setGlass (enabled) {
|
|
208
|
+
glass.value = !!enabled
|
|
209
|
+
document.documentElement.dataset.djmGlass = glass.value ? 'on' : ''
|
|
210
|
+
try {
|
|
211
|
+
if (glass.value) localStorage.setItem(GLASS_KEY, '1')
|
|
212
|
+
else localStorage.removeItem(GLASS_KEY)
|
|
213
|
+
} catch (error) {
|
|
214
|
+
// localStorage 不可用时只影响持久化
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
163
218
|
/** 应用启动时恢复上次选择;?theme=dark 可临时覆盖,方便截图与分享 */
|
|
164
219
|
export function initTheme () {
|
|
165
220
|
let saved = ''
|
|
@@ -180,7 +235,14 @@ export function initTheme () {
|
|
|
180
235
|
} catch (error) {
|
|
181
236
|
color = ''
|
|
182
237
|
}
|
|
238
|
+
let glassSaved = false
|
|
239
|
+
try {
|
|
240
|
+
glassSaved = localStorage.getItem(GLASS_KEY) === '1'
|
|
241
|
+
} catch (error) {
|
|
242
|
+
glassSaved = false
|
|
243
|
+
}
|
|
183
244
|
if (color) primaryColor.value = color
|
|
184
245
|
const next = param === 'dark' || param === 'light' ? param : saved || 'light'
|
|
185
246
|
setTheme(next)
|
|
247
|
+
setGlass(glassSaved)
|
|
186
248
|
}
|