vanilla-jui 1.7.42 → 1.7.43
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/dist/index.d.ts +1 -58
- package/dist/index.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/css/icon.css +29 -4
- package/src/css/layout.css +1 -3
- package/src/css/themes/default/accordion.css +0 -1
- package/src/css/themes/default/avatar.css +0 -1
- package/src/css/themes/default/badge.css +3 -5
- package/src/css/themes/default/breadcrumb.css +0 -1
- package/src/css/themes/default/button.css +0 -1
- package/src/css/themes/default/editor.css +5 -7
- package/src/css/themes/default/form.css +0 -8
- package/src/css/themes/default/menu.css +0 -2
- package/src/css/themes/default/offcanvas.css +1 -1
- package/src/css/themes/default/swiper.css +0 -2
- package/src/css/themes/default/toast.css +0 -1
- package/src/css/themes/default/tooltip.css +0 -1
- package/src/css/tokens.css +8 -9
- package/src/index.ts +0 -1
- package/src/utilities/compress.ts +0 -167
package/package.json
CHANGED
package/src/css/icon.css
CHANGED
|
@@ -1,14 +1,39 @@
|
|
|
1
1
|
@layer icon {
|
|
2
|
-
svg {
|
|
2
|
+
/* svg {
|
|
3
3
|
display: block;
|
|
4
|
+
} */
|
|
5
|
+
|
|
6
|
+
/* icon size */
|
|
7
|
+
[class^='icon-'] {
|
|
8
|
+
--icon-size: var(--font-size-lg);
|
|
9
|
+
width: var(--icon-size);
|
|
10
|
+
height: var(--icon-size);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.is-xs [class^='icon-'] {
|
|
14
|
+
--icon-size: var(--font-size-sm);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.is-sm [class^='icon-'] {
|
|
18
|
+
--icon-size: var(--font-size-md);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.is-md [class^='icon-'] {
|
|
22
|
+
--icon-size: var(--font-size-lg);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.is-lg [class^='icon-'] {
|
|
26
|
+
--icon-size: var(--font-size-xl);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.is-xl [class^='icon-'] {
|
|
30
|
+
--icon-size: var(--font-size-2xl);
|
|
4
31
|
}
|
|
5
32
|
|
|
6
33
|
/* close icon */
|
|
7
34
|
.icon-close {
|
|
8
35
|
position: relative;
|
|
9
36
|
display: block;
|
|
10
|
-
width: var(--font-size-xl);
|
|
11
|
-
height: var(--font-size-xl);
|
|
12
37
|
color: inherit;
|
|
13
38
|
}
|
|
14
39
|
|
|
@@ -18,7 +43,7 @@
|
|
|
18
43
|
position: absolute;
|
|
19
44
|
top: 50%;
|
|
20
45
|
left: 50%;
|
|
21
|
-
width:
|
|
46
|
+
width: 100%;
|
|
22
47
|
height: 1.5px;
|
|
23
48
|
background: currentColor;
|
|
24
49
|
border-radius: 1px;
|
package/src/css/layout.css
CHANGED
|
@@ -109,7 +109,6 @@
|
|
|
109
109
|
transparent 300%
|
|
110
110
|
);
|
|
111
111
|
pointer-events: none;
|
|
112
|
-
user-select: none;
|
|
113
112
|
}
|
|
114
113
|
|
|
115
114
|
.dark .j-background-grid {
|
|
@@ -899,7 +898,6 @@
|
|
|
899
898
|
background: var(--skeleton-bg, var(--ui-bg-muted));
|
|
900
899
|
color: transparent;
|
|
901
900
|
pointer-events: none;
|
|
902
|
-
user-select: none;
|
|
903
901
|
animation: animate-pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
904
902
|
}
|
|
905
903
|
|
|
@@ -964,7 +962,7 @@
|
|
|
964
962
|
Popup
|
|
965
963
|
============================================ */
|
|
966
964
|
.j-popup-layout {
|
|
967
|
-
background: var(--ui-popup
|
|
965
|
+
background: var(--ui-popup);
|
|
968
966
|
backdrop-filter: blur(4px);
|
|
969
967
|
padding: 16px;
|
|
970
968
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
@layer components {
|
|
2
2
|
.j-badge {
|
|
3
3
|
gap: var(--badge-gap, 4px);
|
|
4
|
-
padding: var(--badge-padding, 0
|
|
5
|
-
min-width: var(--badge-min-width,
|
|
6
|
-
height: var(--badge-height,
|
|
4
|
+
padding: var(--badge-padding, 0 4px);
|
|
5
|
+
min-width: var(--badge-min-width, 20px);
|
|
6
|
+
height: var(--badge-height, 20px);
|
|
7
7
|
font-size: var(--badge-font-size, var(--font-size-sm));
|
|
8
8
|
font-weight: 500;
|
|
9
9
|
border-radius: 48px;
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
display: inline-flex;
|
|
16
16
|
justify-content: center;
|
|
17
17
|
align-items: center;
|
|
18
|
-
user-select: none;
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
.j-badge svg {
|
|
@@ -27,7 +26,6 @@
|
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
.j-badge.is-sm {
|
|
30
|
-
--badge-padding: 0 4px;
|
|
31
29
|
--badge-min-width: 1rem;
|
|
32
30
|
--badge-height: 1rem;
|
|
33
31
|
--badge-font-size: var(--font-size-xs);
|
|
@@ -163,9 +163,8 @@
|
|
|
163
163
|
.j-editor u {
|
|
164
164
|
text-decoration: underline;
|
|
165
165
|
text-decoration-thickness: 4px;
|
|
166
|
-
|
|
167
|
-
text-
|
|
168
|
-
text-underline-offset: 0.2em;
|
|
166
|
+
text-decoration-color: var(--ui-yellow);
|
|
167
|
+
text-underline-offset: 3px;
|
|
169
168
|
}
|
|
170
169
|
|
|
171
170
|
.j-editor s,
|
|
@@ -175,8 +174,8 @@
|
|
|
175
174
|
}
|
|
176
175
|
|
|
177
176
|
.j-editor mark {
|
|
178
|
-
background: var(--
|
|
179
|
-
color: var(--
|
|
177
|
+
background: var(--ui-highlight);
|
|
178
|
+
color: var(--ui-highlight-fg);
|
|
180
179
|
padding: 0.1em 0.3em;
|
|
181
180
|
border-radius: 0.2em;
|
|
182
181
|
}
|
|
@@ -344,7 +343,6 @@
|
|
|
344
343
|
|
|
345
344
|
.j-editor ul[data-type='taskList'] li > label {
|
|
346
345
|
flex: none;
|
|
347
|
-
user-select: none;
|
|
348
346
|
}
|
|
349
347
|
|
|
350
348
|
.j-editor ul[data-type='taskList'] li div {
|
|
@@ -427,7 +425,7 @@
|
|
|
427
425
|
border: 1px solid var(--editor-border-subtle);
|
|
428
426
|
border-radius: var(--radius-sm);
|
|
429
427
|
word-break: break-word;
|
|
430
|
-
background: var(--ui-code
|
|
428
|
+
background: var(--ui-code);
|
|
431
429
|
color: var(--ui-code-fg);
|
|
432
430
|
}
|
|
433
431
|
|
|
@@ -133,7 +133,6 @@
|
|
|
133
133
|
font-size: var(--font-size-md);
|
|
134
134
|
padding: 8px;
|
|
135
135
|
border-radius: var(--radius-md);
|
|
136
|
-
user-select: none;
|
|
137
136
|
}
|
|
138
137
|
|
|
139
138
|
.j-radio label:not(:has(input[type='radio']:disabled)):hover,
|
|
@@ -200,7 +199,6 @@
|
|
|
200
199
|
justify-content: center;
|
|
201
200
|
align-items: center;
|
|
202
201
|
text-align: center;
|
|
203
|
-
user-select: none;
|
|
204
202
|
transition-property: box-shadow, color, background-color;
|
|
205
203
|
transition-duration: 0.2s;
|
|
206
204
|
transition-timing-function: ease;
|
|
@@ -460,11 +458,6 @@
|
|
|
460
458
|
border-radius: var(--radius-md);
|
|
461
459
|
}
|
|
462
460
|
|
|
463
|
-
.input-group .el-addon .icon-close,
|
|
464
|
-
.input-inner-group .el-addon .icon-close {
|
|
465
|
-
width: var(--input-height);
|
|
466
|
-
}
|
|
467
|
-
|
|
468
461
|
.input-group > *:not(:first-child) {
|
|
469
462
|
margin-left: -1px;
|
|
470
463
|
}
|
|
@@ -551,7 +544,6 @@
|
|
|
551
544
|
.input-inner-group .el-addon > .el-text {
|
|
552
545
|
display: flex;
|
|
553
546
|
align-items: center;
|
|
554
|
-
user-select: none;
|
|
555
547
|
padding: 0 8px;
|
|
556
548
|
font-size: var(--font-size-md);
|
|
557
549
|
color: var(--ui-fg-muted);
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
scroll-behavior: smooth;
|
|
14
14
|
-ms-overflow-style: none;
|
|
15
15
|
scrollbar-width: none;
|
|
16
|
-
user-select: none;
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
.j-menu::-webkit-scrollbar {
|
|
@@ -468,7 +467,6 @@
|
|
|
468
467
|
padding: 4px 8px;
|
|
469
468
|
text-decoration: none;
|
|
470
469
|
color: var(--ui-fg-muted);
|
|
471
|
-
user-select: none;
|
|
472
470
|
border-radius: var(--radius-sm);
|
|
473
471
|
transition: none;
|
|
474
472
|
}
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
display: block;
|
|
9
9
|
overflow: hidden;
|
|
10
10
|
touch-action: pan-y;
|
|
11
|
-
user-select: none;
|
|
12
11
|
width: 100%;
|
|
13
12
|
min-height: var(--swiper-min-height, 120px);
|
|
14
13
|
border-radius: var(--radius-md);
|
|
@@ -30,7 +29,6 @@
|
|
|
30
29
|
overflow: hidden;
|
|
31
30
|
color: inherit;
|
|
32
31
|
text-decoration: none;
|
|
33
|
-
user-select: none;
|
|
34
32
|
width: var(--swiper-slide-width, 100%);
|
|
35
33
|
min-width: 100%;
|
|
36
34
|
aspect-ratio: inherit;
|
package/src/css/tokens.css
CHANGED
|
@@ -84,9 +84,11 @@
|
|
|
84
84
|
--ui-raised: #ffffff;
|
|
85
85
|
|
|
86
86
|
--ui-reverse: #000;
|
|
87
|
-
--ui-popup
|
|
88
|
-
--ui-code
|
|
87
|
+
--ui-popup: rgba(0, 0, 0, 0.0625);
|
|
88
|
+
--ui-code: #f3f4f6;
|
|
89
89
|
--ui-code-fg: #374151;
|
|
90
|
+
--ui-highlight: #fef08a;
|
|
91
|
+
--ui-highlight-fg: #854d0e;
|
|
90
92
|
|
|
91
93
|
/* --- Fixed Theme Colors (15 themes) --- */
|
|
92
94
|
--ui-gray: #374151;
|
|
@@ -154,9 +156,6 @@
|
|
|
154
156
|
--tone-fg: #ffffff;
|
|
155
157
|
--tone-ring: rgba(99, 102, 241, 0.4);
|
|
156
158
|
|
|
157
|
-
--tone-highlight: #fef08a;
|
|
158
|
-
--tone-highlight-fg: #854d0e;
|
|
159
|
-
|
|
160
159
|
/* Typography */
|
|
161
160
|
--tone-heading: #111827;
|
|
162
161
|
--tone-subtitle: #374151;
|
|
@@ -250,9 +249,11 @@
|
|
|
250
249
|
--ui-raised: #151b24;
|
|
251
250
|
|
|
252
251
|
--ui-reverse: #fff;
|
|
253
|
-
--ui-popup
|
|
254
|
-
--ui-code
|
|
252
|
+
--ui-popup: rgba(0, 0, 0, 0.0375);
|
|
253
|
+
--ui-code: #181a1b;
|
|
255
254
|
--ui-code-fg: #e5e7eb;
|
|
255
|
+
--ui-highlight: #fbbf24;
|
|
256
|
+
--ui-highlight-fg: #78350f;
|
|
256
257
|
|
|
257
258
|
/* --- Fixed Theme Colors (15 themes) --- */
|
|
258
259
|
--ui-gray: #d1d5db;
|
|
@@ -319,8 +320,6 @@
|
|
|
319
320
|
--tone-text-hover: #c7d2fe;
|
|
320
321
|
--tone-fg: #1e1b4b;
|
|
321
322
|
--tone-ring: rgba(129, 140, 248, 0.4);
|
|
322
|
-
--tone-highlight: #fbbf24;
|
|
323
|
-
--tone-highlight-fg: #78350f;
|
|
324
323
|
|
|
325
324
|
/* Typography */
|
|
326
325
|
--tone-heading: #f9fafb;
|
package/src/index.ts
CHANGED
|
@@ -18,7 +18,6 @@ export * from './utilities/config.ts';
|
|
|
18
18
|
export * from './utilities/state.ts';
|
|
19
19
|
export * from './utilities/refs.ts';
|
|
20
20
|
export * from './utilities/validator.ts';
|
|
21
|
-
export * from './utilities/compress.ts';
|
|
22
21
|
export * from './core/scheduler.ts';
|
|
23
22
|
export * from './core/view.ts';
|
|
24
23
|
export * from './core/motion.ts';
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
export interface CompressOptions {
|
|
2
|
-
/** 压缩质量,范围 0-1,默认 0.7 */
|
|
3
|
-
quality?: number;
|
|
4
|
-
/** 目标宽度(像素),不指定则按原图比例缩放 */
|
|
5
|
-
width?: number;
|
|
6
|
-
/** 目标高度(像素),不指定则按原图比例缩放 */
|
|
7
|
-
height?: number;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface ImgCompressInstance {
|
|
11
|
-
/**
|
|
12
|
-
* 将图片路径转换为压缩后的 base64 数据
|
|
13
|
-
* @param path - 图片文件路径或 base64 字符串
|
|
14
|
-
* @param callback - 压缩完成后的回调函数,接收 base64 字符串作为参数
|
|
15
|
-
*/
|
|
16
|
-
canvasDataURL: (path: string, callback: (base64: string) => void) => void;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* 压缩文件对象
|
|
20
|
-
* @param file - 文件对象(Blob 或 File)
|
|
21
|
-
* @param callback - 压缩完成后的回调函数,接收 base64 字符串作为参数
|
|
22
|
-
*/
|
|
23
|
-
photoCompress: (file: Blob, callback: (base64: string) => void) => void;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 将 base64 字符串转换为 Blob 对象
|
|
27
|
-
* @param urlData - base64 数据(包含 data:image 前缀)
|
|
28
|
-
* @returns Blob 对象,如果解析失败则返回 undefined
|
|
29
|
-
*/
|
|
30
|
-
convertBase64UrlToBlob: (urlData: string) => Blob | undefined;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** 单例缓存 */
|
|
34
|
-
let singletonInstance: ImgCompressInstance | null = null;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* 将 base64 字符串转换为 Blob 对象
|
|
38
|
-
* @param urlData - base64 数据(包含 data:image 前缀)
|
|
39
|
-
* @returns Blob 对象,如果解析失败则返回 undefined
|
|
40
|
-
*/
|
|
41
|
-
function convertBase64UrlToBlob(urlData: string): Blob | undefined {
|
|
42
|
-
const arr = urlData.split(',');
|
|
43
|
-
const mimeMatch = arr[0].match(/:(.*?);/);
|
|
44
|
-
if (!mimeMatch) return;
|
|
45
|
-
|
|
46
|
-
const mime = mimeMatch[1];
|
|
47
|
-
const binaryString = atob(arr[1]);
|
|
48
|
-
const length = binaryString.length;
|
|
49
|
-
const uint8Array = new Uint8Array(length);
|
|
50
|
-
|
|
51
|
-
for (let i = 0; i < length; i++) {
|
|
52
|
-
uint8Array[i] = binaryString.charCodeAt(i);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return new Blob([uint8Array], { type: mime });
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 创建压缩实例的核心工厂函数
|
|
60
|
-
*/
|
|
61
|
-
function createCompressInstance(
|
|
62
|
-
options?: CompressOptions
|
|
63
|
-
): ImgCompressInstance {
|
|
64
|
-
const { quality = 0.7, width, height } = options ?? {};
|
|
65
|
-
const config = { quality, width, height };
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
canvasDataURL(path: string, callback: (base64: string) => void): void {
|
|
69
|
-
const img = new Image();
|
|
70
|
-
img.src = path;
|
|
71
|
-
|
|
72
|
-
img.onload = (e: Event): void => {
|
|
73
|
-
const target = e.target as HTMLImageElement;
|
|
74
|
-
const { width: originalWidth, height: originalHeight } = target;
|
|
75
|
-
const scale = originalWidth / originalHeight;
|
|
76
|
-
|
|
77
|
-
const w = config.width ?? originalWidth;
|
|
78
|
-
const h = config.height ?? w / scale;
|
|
79
|
-
|
|
80
|
-
const canvas = document.createElement('canvas');
|
|
81
|
-
const ctx = canvas.getContext('2d');
|
|
82
|
-
|
|
83
|
-
canvas.width = w;
|
|
84
|
-
canvas.height = h;
|
|
85
|
-
|
|
86
|
-
ctx?.drawImage(target, 0, 0, w, h);
|
|
87
|
-
|
|
88
|
-
const base64 = canvas.toDataURL('image/jpeg', config.quality);
|
|
89
|
-
callback(base64);
|
|
90
|
-
};
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
photoCompress(file: Blob, callback: (base64: string) => void): void {
|
|
94
|
-
const reader = new FileReader();
|
|
95
|
-
|
|
96
|
-
reader.readAsDataURL(file);
|
|
97
|
-
|
|
98
|
-
reader.onload = (event: ProgressEvent<FileReader>): void => {
|
|
99
|
-
const result = event.target?.result as string;
|
|
100
|
-
this.canvasDataURL(result, callback);
|
|
101
|
-
};
|
|
102
|
-
},
|
|
103
|
-
|
|
104
|
-
convertBase64UrlToBlob,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// ==================== public api ====================
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* 创建图片压缩实例
|
|
112
|
-
* @param options - 压缩配置选项
|
|
113
|
-
* @param singleton - 是否返回单例,默认 true
|
|
114
|
-
* @returns 图片压缩实例
|
|
115
|
-
* @example
|
|
116
|
-
* ```ts
|
|
117
|
-
* // 获取单例实例(默认)
|
|
118
|
-
* const imgzip = createImgCompress({ quality: 0.8, width: 800 });
|
|
119
|
-
*
|
|
120
|
-
* // 创建新实例
|
|
121
|
-
* const imgzip2 = createImgCompress({ quality: 0.9 }, false);
|
|
122
|
-
* ```
|
|
123
|
-
*/
|
|
124
|
-
function createImgCompress(
|
|
125
|
-
options?: CompressOptions,
|
|
126
|
-
singleton: boolean = true
|
|
127
|
-
): ImgCompressInstance {
|
|
128
|
-
if (singleton && singletonInstance) {
|
|
129
|
-
return singletonInstance;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const instance = createCompressInstance(options);
|
|
133
|
-
|
|
134
|
-
if (singleton) {
|
|
135
|
-
singletonInstance = instance;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return instance;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* 获取单例实例(如果不存在则创建)
|
|
143
|
-
* @param options - 压缩配置选项(仅在首次创建时生效)
|
|
144
|
-
* @returns 单例实例
|
|
145
|
-
* @example
|
|
146
|
-
* ```ts
|
|
147
|
-
* const imgzip = getImgCompressInstance({ quality: 0.8 });
|
|
148
|
-
* ```
|
|
149
|
-
*/
|
|
150
|
-
function getImgCompressInstance(
|
|
151
|
-
options?: CompressOptions
|
|
152
|
-
): ImgCompressInstance {
|
|
153
|
-
if (!singletonInstance) {
|
|
154
|
-
singletonInstance = createCompressInstance(options);
|
|
155
|
-
}
|
|
156
|
-
return singletonInstance;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* 重置单例实例(用于测试或重新配置)
|
|
161
|
-
*/
|
|
162
|
-
function resetImgCompressInstance(): void {
|
|
163
|
-
singletonInstance = null;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export { createImgCompress, getImgCompressInstance, resetImgCompressInstance };
|
|
167
|
-
export default createImgCompress;
|