djm-ui 0.72.0 → 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.
@@ -0,0 +1,58 @@
1
+ /* DJM UI · 毛玻璃 */
2
+
3
+ /* 工具类:直接加在任意容器上 */
4
+ .djm-glass {
5
+ background: var(--djm-glass-bg);
6
+ border: 1px solid var(--djm-glass-border);
7
+ box-shadow: var(--djm-glass-shadow);
8
+ -webkit-backdrop-filter: blur(var(--djm-glass-blur)) saturate(1.4);
9
+ backdrop-filter: blur(var(--djm-glass-blur)) saturate(1.4);
10
+ }
11
+
12
+ /* 模糊半径两档 */
13
+ .djm-glass-strong {
14
+ --djm-glass-blur: 26px;
15
+ }
16
+
17
+ .djm-glass-soft {
18
+ --djm-glass-blur: 8px;
19
+ }
20
+
21
+ /* 组件级开关:Modal / Drawer 的 glass 属性 */
22
+ .djm-modal.djm-is-glass,
23
+ .djm-drawer.djm-is-glass {
24
+ background: var(--djm-glass-bg);
25
+ border: 1px solid var(--djm-glass-border);
26
+ box-shadow: var(--djm-glass-shadow);
27
+ -webkit-backdrop-filter: blur(var(--djm-glass-blur)) saturate(1.4);
28
+ backdrop-filter: blur(var(--djm-glass-blur)) saturate(1.4);
29
+ }
30
+
31
+ /* 全局开关:弹窗、抽屉、浮层、面板与卡片 */
32
+ :root[data-djm-glass='on'] .djm-modal,
33
+ :root[data-djm-glass='on'] .djm-drawer,
34
+ :root[data-djm-glass='on'] .djm-popover-panel,
35
+ :root[data-djm-glass='on'] .djm-dropdown-menu,
36
+ :root[data-djm-glass='on'] .djm-panel,
37
+ :root[data-djm-glass='on'] .djm-card {
38
+ background: var(--djm-glass-bg);
39
+ border-color: var(--djm-glass-border);
40
+ box-shadow: var(--djm-glass-shadow);
41
+ -webkit-backdrop-filter: blur(var(--djm-glass-blur)) saturate(1.4);
42
+ backdrop-filter: blur(var(--djm-glass-blur)) saturate(1.4);
43
+ }
44
+
45
+ /* 浏览器不支持 backdrop-filter 时退回实心底,保证内容可读 */
46
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
47
+ .djm-glass,
48
+ .djm-modal.djm-is-glass,
49
+ .djm-drawer.djm-is-glass,
50
+ :root[data-djm-glass='on'] .djm-modal,
51
+ :root[data-djm-glass='on'] .djm-drawer,
52
+ :root[data-djm-glass='on'] .djm-popover-panel,
53
+ :root[data-djm-glass='on'] .djm-dropdown-menu,
54
+ :root[data-djm-glass='on'] .djm-panel,
55
+ :root[data-djm-glass='on'] .djm-card {
56
+ background: var(--djm-surface);
57
+ }
58
+ }
@@ -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(1px);
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
- .djm-spin-inline {
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
- gap: 8px;
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
+ }
@@ -107,4 +107,5 @@
107
107
  @import './components/grid.css';
108
108
  @import './components/frame.css';
109
109
  @import './components/charts.css';
110
+ @import './components/glass.css';
110
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;
@@ -39,6 +39,11 @@
39
39
  --djm-hover: #eef3f9;
40
40
  --djm-brand-soft: #eaf3fd;
41
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);
42
47
  --djm-loading-mask: rgba(255, 255, 255, 0.74);
43
48
  --djm-border: #dde6f0;
44
49
  --djm-border-strong: #cbd7e5;
@@ -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 = [
@@ -200,6 +203,18 @@ export function toggleTheme () {
200
203
  setTheme(theme.value === 'dark' ? 'light' : 'dark')
201
204
  }
202
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
+
203
218
  /** 应用启动时恢复上次选择;?theme=dark 可临时覆盖,方便截图与分享 */
204
219
  export function initTheme () {
205
220
  let saved = ''
@@ -220,7 +235,14 @@ export function initTheme () {
220
235
  } catch (error) {
221
236
  color = ''
222
237
  }
238
+ let glassSaved = false
239
+ try {
240
+ glassSaved = localStorage.getItem(GLASS_KEY) === '1'
241
+ } catch (error) {
242
+ glassSaved = false
243
+ }
223
244
  if (color) primaryColor.value = color
224
245
  const next = param === 'dark' || param === 'light' ? param : saved || 'light'
225
246
  setTheme(next)
247
+ setGlass(glassSaved)
226
248
  }
package/types/index.d.ts CHANGED
@@ -133,10 +133,13 @@ export const DjmCard: DefineComponent<{
133
133
 
134
134
  export const DjmProgress: DefineComponent<{
135
135
  percent?: number
136
+ type?: 'line' | 'circle'
136
137
  status?: '' | 'success' | 'error' | 'warning'
137
138
  showText?: boolean
138
139
  strokeWidth?: number
139
140
  color?: string
141
+ size?: number
142
+ label?: string
140
143
  }>
141
144
 
142
145
  export const DjmSkeleton: DefineComponent<{
@@ -312,7 +315,11 @@ export const DjmAlert: DefineComponent<{
312
315
  export const DjmSpin: DefineComponent<{
313
316
  spinning?: boolean
314
317
  size?: string
318
+ type?: 'ring' | 'dots' | 'bars' | 'pulse'
315
319
  tip?: string
320
+ delay?: number
321
+ fullscreen?: boolean
322
+ color?: string
316
323
  }>
317
324
 
318
325
  export const DjmPopconfirm: DefineComponent<{
@@ -944,6 +951,7 @@ export const DjmModal: DefineComponent<{
944
951
  showClose?: boolean
945
952
  closeOnEsc?: boolean
946
953
  fullscreen?: boolean
954
+ glass?: boolean
947
955
  }, {}, {}, {}, {}, {}, {}, DjmModalEmits>
948
956
 
949
957
  export const DjmDrawer: DefineComponent<{
@@ -954,6 +962,7 @@ export const DjmDrawer: DefineComponent<{
954
962
  maskClosable?: boolean
955
963
  showClose?: boolean
956
964
  closeOnEsc?: boolean
965
+ glass?: boolean
957
966
  }, {}, {}, {}, {}, {}, {}, DjmModalEmits>
958
967
 
959
968
  export type DjmConfirmDialogEmits = {