lupine.components 1.0.5 → 1.0.7
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/package.json +1 -4
- package/src/components/drag-refresh.tsx +1 -1
- package/src/components/editable-label.tsx +1 -1
- package/src/components/html-var.tsx +8 -5
- package/src/components/panel.tsx +1 -1
- package/src/components/progress.tsx +1 -1
- package/src/components/redirect.tsx +1 -1
- package/src/components/select-with-title.tsx +1 -1
- package/src/components/text-glow.tsx +1 -1
- package/src/components/text-wave.tsx +1 -1
- package/src/lib/drag-util.ts +118 -0
- package/src/lib/index.ts +1 -0
- package/src/lib/upload-file.ts +19 -13
- package/src/styles/dark-themes.ts +6 -4
- package/src/styles/light-themes.ts +5 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lupine.components",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "uuware.com",
|
|
6
6
|
"homepage": "https://uuware.com/",
|
|
@@ -33,8 +33,5 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"lupine.web": "^1.0.0"
|
|
36
|
-
},
|
|
37
|
-
"devDependencies": {
|
|
38
|
-
"@types/node": "^22.10.5"
|
|
39
36
|
}
|
|
40
37
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RefProps, VNode, mountComponents } from 'lupine.web';
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export type HtmlVarResult = { value: string | VNode<any>; ref: RefProps; node: VNode<any> };
|
|
4
|
+
export const HtmlVar = (initial?: string | VNode<any>): HtmlVarResult => {
|
|
4
5
|
let _value: string | VNode<any> = initial || '';
|
|
5
6
|
let _dirty = false;
|
|
6
7
|
const waitUpdate = async (value: string | VNode<any>) => {
|
|
@@ -11,10 +12,12 @@ export const HtmlVar = (initial?: string | VNode<any>) => {
|
|
|
11
12
|
ref.current.innerHTML = value;
|
|
12
13
|
}
|
|
13
14
|
_dirty = false;
|
|
14
|
-
}
|
|
15
|
-
const ref: RefProps = {
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
};
|
|
16
|
+
const ref: RefProps = {
|
|
17
|
+
onLoad: async (el: Element) => {
|
|
18
|
+
_dirty && waitUpdate(_value);
|
|
19
|
+
},
|
|
20
|
+
};
|
|
18
21
|
const FragmentRef = (props: any) => {
|
|
19
22
|
return <>{props.children}</>;
|
|
20
23
|
};
|
package/src/components/panel.tsx
CHANGED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/*
|
|
2
|
+
const moveFn = createDragUtil();
|
|
3
|
+
moveFn.setOnMoveCallback((clientX: number, clientY: number, movedX: number, movedY: number) => {
|
|
4
|
+
const dragDom = moveFn.getDraggingDom();
|
|
5
|
+
if (dragDom?.classList.contains('xxx')) {
|
|
6
|
+
updateRangeMMove(clientX, true, dragDom, _saved.stopDoms);
|
|
7
|
+
} else if (dragDom?.classList.contains('yyy')) {
|
|
8
|
+
updatePicMMove(clientX);
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
<div
|
|
12
|
+
onMouseMove={moveFn.onMouseMove}
|
|
13
|
+
onMouseUp={moveFn.onMouseUp}
|
|
14
|
+
onTouchMove={moveFn.onTouchMove}
|
|
15
|
+
onTouchEnd={moveFn.onTouchEnd}
|
|
16
|
+
>
|
|
17
|
+
<div onMouseDown={moveFn.onMouseDown} onTouchStart={moveFn.onTouchStart}></div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
// when zooming an image, the way to scale slowly
|
|
21
|
+
const slowDelta = 1 + (scale - 1) * 0.2;
|
|
22
|
+
tempScale = lastScale * slowDelta;
|
|
23
|
+
*/
|
|
24
|
+
export const createDragUtil = () => {
|
|
25
|
+
let isDragging = false;
|
|
26
|
+
let initialX = 0;
|
|
27
|
+
let initialY = 0;
|
|
28
|
+
let draggingDom: HTMLDivElement | null = null;
|
|
29
|
+
let onMoveCallback: (clientX: number, clientY: number, movedX: number, movedY: number) => void = () => {};
|
|
30
|
+
let onScaleCallback: (scale: number) => void = () => {};
|
|
31
|
+
|
|
32
|
+
let isZooming = false;
|
|
33
|
+
let initialDistance = 0;
|
|
34
|
+
|
|
35
|
+
const getDistance = (t1: Touch, t2: Touch) => {
|
|
36
|
+
const dx = t2.clientX - t1.clientX;
|
|
37
|
+
const dy = t2.clientY - t1.clientY;
|
|
38
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
setOnMoveCallback: (callback: (clientX: number, clientY: number, movedX: number, movedY: number) => void) => {
|
|
42
|
+
onMoveCallback = callback;
|
|
43
|
+
},
|
|
44
|
+
setOnScaleCallback: (callback: (scale: number) => void) => {
|
|
45
|
+
onScaleCallback = callback;
|
|
46
|
+
},
|
|
47
|
+
getDistance,
|
|
48
|
+
getDraggingDom: () => draggingDom,
|
|
49
|
+
onMouseDown: (event: MouseEvent) => {
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
if (event.buttons !== 1) {
|
|
52
|
+
isDragging = false;
|
|
53
|
+
draggingDom = null;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
isDragging = true;
|
|
57
|
+
draggingDom = event.currentTarget as HTMLDivElement;
|
|
58
|
+
initialX = event.clientX;
|
|
59
|
+
initialY = event.clientY;
|
|
60
|
+
},
|
|
61
|
+
onMouseMove: (event: MouseEvent) => {
|
|
62
|
+
if (event.buttons === 0 || !draggingDom) {
|
|
63
|
+
isDragging = false;
|
|
64
|
+
draggingDom = null;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
onMoveCallback(event.clientX, event.clientY, event.clientX - initialX, event.clientY - initialY);
|
|
68
|
+
},
|
|
69
|
+
onMouseUp: () => {
|
|
70
|
+
isDragging = false;
|
|
71
|
+
isZooming = false;
|
|
72
|
+
draggingDom = null;
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
onTouchStart: (event: TouchEvent) => {
|
|
76
|
+
if (event.touches.length === 1) {
|
|
77
|
+
isDragging = true;
|
|
78
|
+
draggingDom = event.currentTarget as HTMLDivElement;
|
|
79
|
+
initialX = event.touches[0].clientX;
|
|
80
|
+
initialY = event.touches[0].clientY;
|
|
81
|
+
} else if (event.touches.length === 2) {
|
|
82
|
+
initialDistance = getDistance(event.touches[0], event.touches[1]);
|
|
83
|
+
isZooming = true;
|
|
84
|
+
} else {
|
|
85
|
+
isDragging = false;
|
|
86
|
+
draggingDom = null;
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
onTouchMove: (event: TouchEvent) => {
|
|
90
|
+
if (isZooming) {
|
|
91
|
+
if (event.touches.length === 2) {
|
|
92
|
+
event.preventDefault(); // 防止页面滚动
|
|
93
|
+
const newDistance = getDistance(event.touches[0], event.touches[1]);
|
|
94
|
+
const delta = newDistance / initialDistance;
|
|
95
|
+
// const newScale = Math.min(Math.max(1, scale * delta), 4); // 限制缩放范围
|
|
96
|
+
onScaleCallback(delta);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!isDragging || event.touches.length === 0 || !draggingDom) {
|
|
101
|
+
isDragging = false;
|
|
102
|
+
draggingDom = null;
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
onMoveCallback(
|
|
106
|
+
event.touches[0].clientX,
|
|
107
|
+
event.touches[0].clientY,
|
|
108
|
+
event.touches[0].clientX - initialX,
|
|
109
|
+
event.touches[0].clientY - initialY
|
|
110
|
+
);
|
|
111
|
+
},
|
|
112
|
+
onTouchEnd: () => {
|
|
113
|
+
isDragging = false;
|
|
114
|
+
isZooming = false;
|
|
115
|
+
draggingDom = null;
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
};
|
package/src/lib/index.ts
CHANGED
package/src/lib/upload-file.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getRenderPageProps } from "lupine.web";
|
|
2
|
+
|
|
1
3
|
const _saveChunkSize = {
|
|
2
4
|
size: 1024 * 500,
|
|
3
5
|
};
|
|
@@ -8,10 +10,11 @@ export const getChunkSize = () => {
|
|
|
8
10
|
return _saveChunkSize.size;
|
|
9
11
|
};
|
|
10
12
|
export const checkUploadedFileSize = async (uploadUrl: string) => {
|
|
11
|
-
const response = await fetch(uploadUrl + '?check-size=1', {
|
|
12
|
-
|
|
13
|
-
});
|
|
14
|
-
const json = await response.json();
|
|
13
|
+
// const response = await fetch(uploadUrl + '?check-size=1', {
|
|
14
|
+
// method: 'POST',
|
|
15
|
+
// });
|
|
16
|
+
// const json = await response.json();
|
|
17
|
+
const json = await getRenderPageProps().renderPageFunctions.fetchData(uploadUrl + '?check-size=1');
|
|
15
18
|
return json && json.size ? json.size : 0;
|
|
16
19
|
};
|
|
17
20
|
|
|
@@ -30,30 +33,33 @@ export const uploadFileChunk = async (
|
|
|
30
33
|
if (key) {
|
|
31
34
|
url += `&key=${key}`;
|
|
32
35
|
}
|
|
33
|
-
const response = await fetch(url, {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
});
|
|
37
|
-
const json = await response.json();
|
|
36
|
+
// const response = await fetch(url, {
|
|
37
|
+
// method: 'POST',
|
|
38
|
+
// body: chunk,
|
|
39
|
+
// });
|
|
40
|
+
// const json = await response.json();
|
|
41
|
+
console.log(`uploadFileChunk, ${uploadUrl}, index: ${chunkNumber}, total: ${totalChunks}, len: ${chunk.length}`);
|
|
42
|
+
const json = await getRenderPageProps().renderPageFunctions.fetchData(url, chunk);
|
|
38
43
|
return json;
|
|
39
44
|
};
|
|
40
45
|
|
|
41
46
|
export const uploadFile = async (
|
|
42
|
-
file: File,
|
|
47
|
+
file: File | string,
|
|
43
48
|
uploadUrl: string,
|
|
44
49
|
progressFn?: (percentage: number, chunkNumber: number, totalChunks: number) => void,
|
|
45
50
|
chunkSize = _saveChunkSize.size
|
|
46
51
|
) => {
|
|
47
52
|
// const uploadedSize = await checkUploadedFileSize(uploadUrl);
|
|
48
53
|
let key = '';
|
|
49
|
-
|
|
54
|
+
const len = file instanceof File ? file.size : file.length;
|
|
55
|
+
if (len <= chunkSize) {
|
|
50
56
|
return await uploadFileChunk(file, 0, 1, uploadUrl, key);
|
|
51
57
|
}
|
|
52
58
|
|
|
53
|
-
const totalChunks = Math.ceil(
|
|
59
|
+
const totalChunks = Math.ceil(len / chunkSize);
|
|
54
60
|
for (let i = 0; i < totalChunks; i++) {
|
|
55
61
|
const start = i * chunkSize;
|
|
56
|
-
const end = Math.min((i + 1) * chunkSize,
|
|
62
|
+
const end = Math.min((i + 1) * chunkSize, len);
|
|
57
63
|
const chunk = file.slice(start, end);
|
|
58
64
|
const uploaded = await uploadFileChunk(chunk, i, totalChunks, uploadUrl, key);
|
|
59
65
|
if (!uploaded || uploaded.chunkNumber === i.toString() || !uploaded.key) {
|
|
@@ -9,18 +9,20 @@ export const darkThemes: ThemeProps = {
|
|
|
9
9
|
'--scrollbar-thumb-bg': '#373636',
|
|
10
10
|
'--scrollbar-active-thumb-bg': '#5b5b5b',
|
|
11
11
|
|
|
12
|
-
'--primary-color': '#
|
|
12
|
+
'--primary-color': '#e5e5e5',
|
|
13
13
|
'--primary-color-disabled': '#7d7d7d',
|
|
14
14
|
'--primary-bg-color': '#000000',
|
|
15
15
|
'--primary-border-color': '#aeaeae',
|
|
16
16
|
'--primary-border': '1px solid var(--primary-border-color)',
|
|
17
|
-
// '--secondary-color': '#b3b3b3',
|
|
18
|
-
// '--secondary-bg-color': '#151515',
|
|
19
|
-
// '--secondary-border': '1px solid #303030',
|
|
20
17
|
'--primary-opacity': '0.5', // used for dark theme
|
|
21
18
|
'--primary-disabled-opacity': '0.7', // used for dark theme
|
|
22
19
|
'--primary-accent-color': '#1a588a', // used for radio and checkbox's background color
|
|
23
20
|
|
|
21
|
+
'--secondary-color': '#747474',
|
|
22
|
+
'--secondary-bg-color': '#1c1c1c',
|
|
23
|
+
'--secondary-border-color': '#494949',
|
|
24
|
+
'--secondary-border': '1px solid var(--secondary-border-color)',
|
|
25
|
+
|
|
24
26
|
// including menus, tabs
|
|
25
27
|
'--activatable-color-normal': 'var(--primary-color)',
|
|
26
28
|
'--activatable-bg-color-normal': 'var(--primary-bg-color)',
|
|
@@ -15,13 +15,15 @@ export const lightThemes: ThemeProps = {
|
|
|
15
15
|
'--primary-bg-color': '#ffffff',
|
|
16
16
|
'--primary-border-color': '#858585',
|
|
17
17
|
'--primary-border': '1px solid var(--primary-border-color)',
|
|
18
|
-
// '--secondary-color': '#505050',
|
|
19
|
-
// '--secondary-bg-color': '#ffffff',
|
|
20
|
-
// '--secondary-border': '1px solid #858585',
|
|
21
18
|
'--primary-opacity': 'unset', // used for dark theme
|
|
22
19
|
'--primary-disabled-opacity': '0.5', // used for dark theme
|
|
23
20
|
'--primary-accent-color': '#0a74c9', // used for radio and checkbox's background color
|
|
24
21
|
|
|
22
|
+
'--secondary-color': '#818181',
|
|
23
|
+
'--secondary-bg-color': '#eeeeee',
|
|
24
|
+
'--secondary-border-color': '#a0a0a0',
|
|
25
|
+
'--secondary-border': '1px solid var(--secondary-border-color)',
|
|
26
|
+
|
|
25
27
|
// including menus, tabs, sidebars
|
|
26
28
|
'--activatable-color-normal': 'var(--primary-color)',
|
|
27
29
|
'--activatable-bg-color-normal': 'var(--primary-bg-color)',
|