@springbrand/gravel 0.1.0 → 0.1.1
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/components/ui-block/cover/index.js +1 -1
- package/dist/components/ui-block/sparkles/index.js +1 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.js +1 -39
- package/package.json +4 -18
- package/dist/hooks/use-media-query.d.ts +0 -1
- package/dist/hooks/use-media-query.js +0 -15
- package/dist/hooks/use-prefers-reduced-motion.d.ts +0 -1
- package/dist/hooks/use-prefers-reduced-motion.js +0 -23
- package/dist/hooks/use-scroll-container.d.ts +0 -18
- package/dist/hooks/use-scroll-container.js +0 -25
- package/dist/utils/css-utils.d.ts +0 -10
- package/dist/utils/css-utils.js +0 -17
- package/dist/utils/index.d.ts +0 -9
- package/dist/utils/index.js +0 -34
- package/dist/utils/storage-qetag.d.ts +0 -22
- package/dist/utils/storage-qetag.js +0 -101
- package/dist/utils/utils-api.d.ts +0 -17
- package/dist/utils/utils-api.js +0 -31
- package/dist/utils/utils-canvas.d.ts +0 -30
- package/dist/utils/utils-canvas.js +0 -54
- package/dist/utils/utils-common.d.ts +0 -6
- package/dist/utils/utils-common.js +0 -15
- package/dist/utils/utils-image.d.ts +0 -33
- package/dist/utils/utils-image.js +0 -57
- package/dist/utils/utils-random.d.ts +0 -1
- package/dist/utils/utils-random.js +0 -6
- package/dist/utils/utils-time.d.ts +0 -49
- package/dist/utils/utils-time.js +0 -112
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
|
-
import { cn } from "
|
|
3
|
+
import { cn } from "@springbrand/utils/css-utils";
|
|
4
4
|
import { AnimatePresence, motion } from "motion/react";
|
|
5
5
|
import { useState, useRef, useEffect, useId } from "react";
|
|
6
6
|
import { SparklesCore } from "../sparkles/index.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { cn } from "
|
|
3
|
+
import { cn } from "@springbrand/utils/css-utils";
|
|
4
4
|
import Particles, { initParticlesEngine } from "@tsparticles/react";
|
|
5
5
|
import { loadSlim } from "@tsparticles/slim";
|
|
6
6
|
import { useAnimation, motion } from "motion/react";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,2 @@
|
|
|
1
1
|
export * from "./components/ui-base/index.ts";
|
|
2
2
|
export * from "./components/ui-block/index.ts";
|
|
3
|
-
export * from "./hooks/use-media-query.ts";
|
|
4
|
-
export * from "./hooks/use-prefers-reduced-motion.ts";
|
|
5
|
-
export * from "./hooks/use-scroll-container.ts";
|
|
6
|
-
export * from "./utils/index.ts";
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
import { useMediaQuery } from "./hooks/use-media-query.js";
|
|
2
|
-
import { usePrefersReducedMotion } from "./hooks/use-prefers-reduced-motion.js";
|
|
3
|
-
import { useScrollContainer } from "./hooks/use-scroll-container.js";
|
|
4
|
-
import { filterEmptyValues } from "./utils/utils-common.js";
|
|
5
|
-
import { formatLargeNumber, getUrlWithParams } from "./utils/utils-api.js";
|
|
6
|
-
import { formatTimeAgo, formatTimeString, getTimeDetails, getTimestamp, sleep, timeAgo } from "./utils/utils-time.js";
|
|
7
|
-
import { base64ToFile, base64ToUrl, blobToBase64, blobToUrl, convertBase64ToBlob, structureFile } from "./utils/utils-canvas.js";
|
|
8
|
-
import { cn, liquidGlass } from "./utils/css-utils.js";
|
|
9
|
-
import "./utils/storage-qetag.js";
|
|
10
|
-
import { downloadImage, downloadImageClient, fetchHasOnlineFile, getBase64Client, isValidFileSize, isValidFileType } from "./utils/utils-image.js";
|
|
11
|
-
import { nanoid } from "./utils/utils-random.js";
|
|
12
1
|
import { default as default2 } from "./components/ui-block/background/index.js";
|
|
13
2
|
import { Cover } from "./components/ui-block/cover/index.js";
|
|
14
3
|
import { ResponsiveDialog, ResponsiveDialogClose, ResponsiveDialogContent, ResponsiveDialogDescription, ResponsiveDialogFooter, ResponsiveDialogHeader, ResponsiveDialogTitle, ResponsiveDialogTrigger } from "./components/ui-base/responsive-dialog/index.js";
|
|
@@ -26,32 +15,5 @@ export {
|
|
|
26
15
|
ResponsiveDialogTitle,
|
|
27
16
|
ResponsiveDialogTrigger,
|
|
28
17
|
SparklesCore,
|
|
29
|
-
Spotlight
|
|
30
|
-
base64ToFile,
|
|
31
|
-
base64ToUrl,
|
|
32
|
-
blobToBase64,
|
|
33
|
-
blobToUrl,
|
|
34
|
-
cn,
|
|
35
|
-
convertBase64ToBlob,
|
|
36
|
-
downloadImage,
|
|
37
|
-
downloadImageClient,
|
|
38
|
-
fetchHasOnlineFile,
|
|
39
|
-
filterEmptyValues,
|
|
40
|
-
formatLargeNumber,
|
|
41
|
-
formatTimeAgo,
|
|
42
|
-
formatTimeString,
|
|
43
|
-
getBase64Client,
|
|
44
|
-
getTimeDetails,
|
|
45
|
-
getTimestamp,
|
|
46
|
-
getUrlWithParams,
|
|
47
|
-
isValidFileSize,
|
|
48
|
-
isValidFileType,
|
|
49
|
-
liquidGlass,
|
|
50
|
-
nanoid,
|
|
51
|
-
sleep,
|
|
52
|
-
structureFile,
|
|
53
|
-
timeAgo,
|
|
54
|
-
useMediaQuery,
|
|
55
|
-
usePrefersReducedMotion,
|
|
56
|
-
useScrollContainer
|
|
18
|
+
Spotlight
|
|
57
19
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@springbrand/gravel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -38,21 +38,6 @@
|
|
|
38
38
|
"types": "./dist/components/ui-base/*/index.d.ts",
|
|
39
39
|
"import": "./dist/components/ui-base/*/index.js",
|
|
40
40
|
"default": "./dist/components/ui-base/*/index.js"
|
|
41
|
-
},
|
|
42
|
-
"./utils": {
|
|
43
|
-
"types": "./dist/utils/index.d.ts",
|
|
44
|
-
"import": "./dist/utils/index.js",
|
|
45
|
-
"default": "./dist/utils/index.js"
|
|
46
|
-
},
|
|
47
|
-
"./utils/*": {
|
|
48
|
-
"types": "./dist/utils/*.d.ts",
|
|
49
|
-
"import": "./dist/utils/*.js",
|
|
50
|
-
"default": "./dist/utils/*.js"
|
|
51
|
-
},
|
|
52
|
-
"./hooks/*": {
|
|
53
|
-
"types": "./dist/hooks/*.d.ts",
|
|
54
|
-
"import": "./dist/hooks/*.js",
|
|
55
|
-
"default": "./dist/hooks/*.js"
|
|
56
41
|
}
|
|
57
42
|
},
|
|
58
43
|
"dependencies": {
|
|
@@ -61,7 +46,8 @@
|
|
|
61
46
|
"@dnd-kit/utilities": "^3.2.2",
|
|
62
47
|
"@emotion/is-prop-valid": "1.4.0",
|
|
63
48
|
"@relume_io/relume-tailwind": "^1.3.0",
|
|
64
|
-
"@springbrand/site-block": "0.1.
|
|
49
|
+
"@springbrand/site-block": "0.1.1",
|
|
50
|
+
"@springbrand/utils": "0.1.1",
|
|
65
51
|
"embla-carousel-autoplay": "8.6.0",
|
|
66
52
|
"react-advanced-cropper": "0.20.1",
|
|
67
53
|
"react-error-boundary": "6.1.1",
|
|
@@ -382,5 +368,5 @@
|
|
|
382
368
|
"optional": true
|
|
383
369
|
}
|
|
384
370
|
},
|
|
385
|
-
"gitHead": "
|
|
371
|
+
"gitHead": "9c55f8cfb08008877a22aeed4cd51a66391bbddc"
|
|
386
372
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function useMediaQuery(query: string): boolean;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect } from "react";
|
|
2
|
-
function useMediaQuery(query) {
|
|
3
|
-
const [matches, setMatches] = useState(false);
|
|
4
|
-
useEffect(() => {
|
|
5
|
-
const mql = window.matchMedia(query);
|
|
6
|
-
const onChange = () => setMatches(mql.matches);
|
|
7
|
-
mql.addEventListener("change", onChange);
|
|
8
|
-
setMatches(mql.matches);
|
|
9
|
-
return () => mql.removeEventListener("change", onChange);
|
|
10
|
-
}, [query]);
|
|
11
|
-
return matches;
|
|
12
|
-
}
|
|
13
|
-
export {
|
|
14
|
-
useMediaQuery
|
|
15
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function usePrefersReducedMotion(): boolean;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
const QUERY = "(prefers-reduced-motion: no-preference)";
|
|
3
|
-
const isRenderingOnServer = typeof window === "undefined";
|
|
4
|
-
const getInitialState = () => {
|
|
5
|
-
return isRenderingOnServer ? true : !window.matchMedia(QUERY).matches;
|
|
6
|
-
};
|
|
7
|
-
function usePrefersReducedMotion() {
|
|
8
|
-
const [prefersReducedMotion, setPrefersReducedMotion] = React.useState(getInitialState);
|
|
9
|
-
React.useEffect(() => {
|
|
10
|
-
const mediaQueryList = window.matchMedia(QUERY);
|
|
11
|
-
const listener = (event) => {
|
|
12
|
-
setPrefersReducedMotion(!event.matches);
|
|
13
|
-
};
|
|
14
|
-
mediaQueryList.addEventListener("change", listener);
|
|
15
|
-
return () => {
|
|
16
|
-
mediaQueryList.removeEventListener("change", listener);
|
|
17
|
-
};
|
|
18
|
-
}, []);
|
|
19
|
-
return prefersReducedMotion;
|
|
20
|
-
}
|
|
21
|
-
export {
|
|
22
|
-
usePrefersReducedMotion
|
|
23
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { type RefObject } from "react";
|
|
2
|
-
/**
|
|
3
|
-
* 自动查找目标元素最近的可滚动祖先,返回一个 ref 供 framer-motion useScroll 的 container 使用。
|
|
4
|
-
*
|
|
5
|
-
* 解决:在 Puck 编辑器 iframe 中,滚动发生在 iframe 内部容器(而非 window),
|
|
6
|
-
* useScroll({ target }) 默认找不到正确的滚动容器。
|
|
7
|
-
*
|
|
8
|
-
* @returns [containerRef, ready] — ready 为 true 时 containerRef 已就绪
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* const targetRef = useRef(null);
|
|
12
|
-
* const [containerRef, ready] = useScrollContainer(targetRef);
|
|
13
|
-
* const { scrollYProgress } = useScroll({
|
|
14
|
-
* target: targetRef,
|
|
15
|
-
* container: containerRef,
|
|
16
|
-
* });
|
|
17
|
-
*/
|
|
18
|
-
export declare function useScrollContainer<T extends HTMLElement>(targetRef: RefObject<T | null>): [RefObject<HTMLElement | null>, boolean];
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { useRef, useState, useLayoutEffect } from "react";
|
|
2
|
-
function useScrollContainer(targetRef) {
|
|
3
|
-
const containerRef = useRef(null);
|
|
4
|
-
const [ready, setReady] = useState(false);
|
|
5
|
-
useLayoutEffect(() => {
|
|
6
|
-
const el = targetRef.current;
|
|
7
|
-
if (!el) return;
|
|
8
|
-
let ancestor = el.parentElement;
|
|
9
|
-
while (ancestor && ancestor !== document.documentElement) {
|
|
10
|
-
const { overflowY } = getComputedStyle(ancestor);
|
|
11
|
-
if (overflowY === "auto" || overflowY === "scroll") {
|
|
12
|
-
containerRef.current = ancestor;
|
|
13
|
-
setReady(true);
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
ancestor = ancestor.parentElement;
|
|
17
|
-
}
|
|
18
|
-
containerRef.current = null;
|
|
19
|
-
setReady(true);
|
|
20
|
-
}, [targetRef]);
|
|
21
|
-
return [containerRef, ready];
|
|
22
|
-
}
|
|
23
|
-
export {
|
|
24
|
-
useScrollContainer
|
|
25
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type ClassValue } from "clsx";
|
|
2
|
-
/**
|
|
3
|
-
* 合并CSS类名,支持条件类名和Tailwind冲突解决
|
|
4
|
-
* 支持Fluid Tailwind功能
|
|
5
|
-
*/
|
|
6
|
-
export declare function cn(...inputs: ClassValue[]): string;
|
|
7
|
-
/**
|
|
8
|
-
* 液体玻璃效果样式
|
|
9
|
-
*/
|
|
10
|
-
export declare function liquidGlass(...args: ClassValue[]): string;
|
package/dist/utils/css-utils.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { withFluid } from "@fluid-tailwind/tailwind-merge";
|
|
2
|
-
import { clsx } from "clsx";
|
|
3
|
-
import { extendTailwindMerge } from "tailwind-merge";
|
|
4
|
-
const twMerge = extendTailwindMerge({}, withFluid);
|
|
5
|
-
function cn(...inputs) {
|
|
6
|
-
return twMerge(clsx(inputs));
|
|
7
|
-
}
|
|
8
|
-
function liquidGlass(...args) {
|
|
9
|
-
return cn(
|
|
10
|
-
"shadow-[0px_-1px_0px_0px_#FFFFFF40_inset,_0px_1px_0px_0px_#FFFFFF40_inset]",
|
|
11
|
-
args
|
|
12
|
-
);
|
|
13
|
-
}
|
|
14
|
-
export {
|
|
15
|
-
cn,
|
|
16
|
-
liquidGlass
|
|
17
|
-
};
|
package/dist/utils/index.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export * from "./utils-common.ts";
|
|
2
|
-
export * from "./utils-api.ts";
|
|
3
|
-
export * from "./utils-time.ts";
|
|
4
|
-
export * from "./utils-canvas.ts";
|
|
5
|
-
export * from "./css-utils.ts";
|
|
6
|
-
export * from "./storage-qetag.ts";
|
|
7
|
-
export * from "./utils-image.ts";
|
|
8
|
-
export * from "./utils-time.ts";
|
|
9
|
-
export * from "./utils-random.ts";
|
package/dist/utils/index.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { filterEmptyValues } from "./utils-common.js";
|
|
2
|
-
import { formatLargeNumber, getUrlWithParams } from "./utils-api.js";
|
|
3
|
-
import { formatTimeAgo, formatTimeString, getTimeDetails, getTimestamp, sleep, timeAgo } from "./utils-time.js";
|
|
4
|
-
import { base64ToFile, base64ToUrl, blobToBase64, blobToUrl, convertBase64ToBlob, structureFile } from "./utils-canvas.js";
|
|
5
|
-
import { cn, liquidGlass } from "./css-utils.js";
|
|
6
|
-
import "./storage-qetag.js";
|
|
7
|
-
import { downloadImage, downloadImageClient, fetchHasOnlineFile, getBase64Client, isValidFileSize, isValidFileType } from "./utils-image.js";
|
|
8
|
-
import { nanoid } from "./utils-random.js";
|
|
9
|
-
export {
|
|
10
|
-
base64ToFile,
|
|
11
|
-
base64ToUrl,
|
|
12
|
-
blobToBase64,
|
|
13
|
-
blobToUrl,
|
|
14
|
-
cn,
|
|
15
|
-
convertBase64ToBlob,
|
|
16
|
-
downloadImage,
|
|
17
|
-
downloadImageClient,
|
|
18
|
-
fetchHasOnlineFile,
|
|
19
|
-
filterEmptyValues,
|
|
20
|
-
formatLargeNumber,
|
|
21
|
-
formatTimeAgo,
|
|
22
|
-
formatTimeString,
|
|
23
|
-
getBase64Client,
|
|
24
|
-
getTimeDetails,
|
|
25
|
-
getTimestamp,
|
|
26
|
-
getUrlWithParams,
|
|
27
|
-
isValidFileSize,
|
|
28
|
-
isValidFileType,
|
|
29
|
-
liquidGlass,
|
|
30
|
-
nanoid,
|
|
31
|
-
sleep,
|
|
32
|
-
structureFile,
|
|
33
|
-
timeAgo
|
|
34
|
-
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
interface ITypeInfo {
|
|
2
|
-
ext: string;
|
|
3
|
-
mime: string;
|
|
4
|
-
}
|
|
5
|
-
export default class QiNiuETag {
|
|
6
|
-
currentLength: number;
|
|
7
|
-
chunkTime: number;
|
|
8
|
-
sha1String: any[];
|
|
9
|
-
type: ITypeInfo | undefined;
|
|
10
|
-
updateBlob(blob: File): Promise<void>;
|
|
11
|
-
changeCurrent(): void;
|
|
12
|
-
concatArr2Uint8(s: any): Uint8Array<ArrayBuffer>;
|
|
13
|
-
readBlobToArrayBuffer(blob: Blob): Promise<string | ArrayBuffer | null>;
|
|
14
|
-
get sha1Buffer(): any;
|
|
15
|
-
get getEtag(): string;
|
|
16
|
-
get typeInfo(): ITypeInfo | undefined;
|
|
17
|
-
get fileInfo(): {
|
|
18
|
-
sha1: string;
|
|
19
|
-
typeInfo: ITypeInfo | undefined;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
export {};
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import fileType from "file-type";
|
|
5
|
-
import hash from "js-sha1";
|
|
6
|
-
const chunkSize = 4 * 1024 * 1024;
|
|
7
|
-
const shA1 = hash.digest;
|
|
8
|
-
class QiNiuETag {
|
|
9
|
-
constructor() {
|
|
10
|
-
__publicField(this, "currentLength", 0);
|
|
11
|
-
__publicField(this, "chunkTime", 0);
|
|
12
|
-
__publicField(this, "sha1String", []);
|
|
13
|
-
__publicField(this, "type");
|
|
14
|
-
}
|
|
15
|
-
async updateBlob(blob) {
|
|
16
|
-
let i = 0;
|
|
17
|
-
while (i < blob.size) {
|
|
18
|
-
const size = Math.min(
|
|
19
|
-
chunkSize,
|
|
20
|
-
blob.size - i,
|
|
21
|
-
chunkSize - this.currentLength
|
|
22
|
-
);
|
|
23
|
-
const to = i + size;
|
|
24
|
-
const chunkBlob = blob.slice(i, to);
|
|
25
|
-
const chunkData = await this.readBlobToArrayBuffer(chunkBlob);
|
|
26
|
-
if (chunkData === null) {
|
|
27
|
-
throw new Error("Failed to read blob data");
|
|
28
|
-
}
|
|
29
|
-
const chunkSha1 = shA1(chunkData);
|
|
30
|
-
this.sha1String.push(chunkSha1);
|
|
31
|
-
if (this.chunkTime === 0) {
|
|
32
|
-
this.type = await fileType(chunkData);
|
|
33
|
-
}
|
|
34
|
-
this.currentLength += size;
|
|
35
|
-
if (this.currentLength === chunkSize) {
|
|
36
|
-
this.changeCurrent();
|
|
37
|
-
}
|
|
38
|
-
i = to;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
changeCurrent() {
|
|
42
|
-
if (this.currentLength > 0) {
|
|
43
|
-
this.chunkTime++;
|
|
44
|
-
this.currentLength = 0;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
concatArr2Uint8(s) {
|
|
48
|
-
let tmp = [];
|
|
49
|
-
for (const i of s) tmp = tmp.concat(i);
|
|
50
|
-
return new Uint8Array(tmp);
|
|
51
|
-
}
|
|
52
|
-
readBlobToArrayBuffer(blob) {
|
|
53
|
-
return new Promise((resolve, reject) => {
|
|
54
|
-
const fileReader = new FileReader();
|
|
55
|
-
fileReader.onload = () => resolve(fileReader.result);
|
|
56
|
-
fileReader.onerror = reject;
|
|
57
|
-
fileReader.readAsArrayBuffer(blob);
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
get sha1Buffer() {
|
|
61
|
-
let returnData = this.concatArr2Uint8(this.sha1String);
|
|
62
|
-
let prefix;
|
|
63
|
-
if (this.chunkTime >= 1) {
|
|
64
|
-
prefix = [150];
|
|
65
|
-
returnData = shA1(returnData.buffer);
|
|
66
|
-
} else {
|
|
67
|
-
prefix = [22];
|
|
68
|
-
returnData = Array.apply([], returnData);
|
|
69
|
-
}
|
|
70
|
-
returnData = this.concatArr2Uint8([[prefix], returnData]);
|
|
71
|
-
return returnData;
|
|
72
|
-
}
|
|
73
|
-
get getEtag() {
|
|
74
|
-
const CHUNK_SIZE = 32768;
|
|
75
|
-
const length = this.sha1Buffer.length;
|
|
76
|
-
let index = 0;
|
|
77
|
-
let result = "";
|
|
78
|
-
let slice;
|
|
79
|
-
while (index < length) {
|
|
80
|
-
slice = this.sha1Buffer.subarray(
|
|
81
|
-
index,
|
|
82
|
-
Math.min(index + CHUNK_SIZE, length)
|
|
83
|
-
);
|
|
84
|
-
result += String.fromCharCode.apply(null, slice);
|
|
85
|
-
index += CHUNK_SIZE;
|
|
86
|
-
}
|
|
87
|
-
return btoa(result).replace(/\//g, "_").replace(/\+/g, "-");
|
|
88
|
-
}
|
|
89
|
-
get typeInfo() {
|
|
90
|
-
return this.type;
|
|
91
|
-
}
|
|
92
|
-
get fileInfo() {
|
|
93
|
-
return {
|
|
94
|
-
sha1: this.getEtag,
|
|
95
|
-
typeInfo: this.typeInfo
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
export {
|
|
100
|
-
QiNiuETag as default
|
|
101
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description 将对象转换为URL参数
|
|
3
|
-
* @param url 基础URL
|
|
4
|
-
* @param params 参数对象
|
|
5
|
-
* @returns 带参数的完整URL
|
|
6
|
-
*/
|
|
7
|
-
export declare function getUrlWithParams(url: string, params: Record<string, any>): string;
|
|
8
|
-
/**
|
|
9
|
-
* @description 大数字格式化工具函数
|
|
10
|
-
* @param num 要格式化的数字
|
|
11
|
-
* @param format 格式化配置
|
|
12
|
-
* @returns 格式化后的字符串
|
|
13
|
-
*/
|
|
14
|
-
export declare function formatLargeNumber(num: number, format?: {
|
|
15
|
-
unit?: number;
|
|
16
|
-
unitCN?: string;
|
|
17
|
-
}): string;
|
package/dist/utils/utils-api.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { filterEmptyValues } from "./utils-common.js";
|
|
2
|
-
function getUrlWithParams(url, params) {
|
|
3
|
-
if (!params || Object.keys(params).length === 0) {
|
|
4
|
-
return url;
|
|
5
|
-
}
|
|
6
|
-
const urlObj = new URL(url, window.location.origin);
|
|
7
|
-
Object.entries(filterEmptyValues(params)).forEach(([key, value]) => {
|
|
8
|
-
if (value !== void 0 && value !== null && value !== "") {
|
|
9
|
-
if (Array.isArray(value)) {
|
|
10
|
-
value.forEach((item) => {
|
|
11
|
-
urlObj.searchParams.append(key, String(item));
|
|
12
|
-
});
|
|
13
|
-
} else {
|
|
14
|
-
urlObj.searchParams.set(key, String(value));
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
return urlObj.toString();
|
|
19
|
-
}
|
|
20
|
-
function formatLargeNumber(num, format = {}) {
|
|
21
|
-
const { unit = 1e4, unitCN = "万" } = format;
|
|
22
|
-
if (num < unit) {
|
|
23
|
-
return `${unit}+`;
|
|
24
|
-
}
|
|
25
|
-
const result = Math.floor(num / unit);
|
|
26
|
-
return `${result}${unitCN}+`;
|
|
27
|
-
}
|
|
28
|
-
export {
|
|
29
|
-
formatLargeNumber,
|
|
30
|
-
getUrlWithParams
|
|
31
|
-
};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @description Blob转换File对象
|
|
3
|
-
* @param blobData
|
|
4
|
-
*/
|
|
5
|
-
export declare function structureFile(blobData: Blob): File;
|
|
6
|
-
/**
|
|
7
|
-
* @description blobToUrl
|
|
8
|
-
* @param {*} blobData
|
|
9
|
-
*/
|
|
10
|
-
export declare function blobToUrl(blobData: Blob): string;
|
|
11
|
-
/**
|
|
12
|
-
* @description base64ToBlob
|
|
13
|
-
* @param {*} base64
|
|
14
|
-
*/
|
|
15
|
-
export declare function convertBase64ToBlob(base64: string): Blob;
|
|
16
|
-
/**
|
|
17
|
-
* @description base64ToUrl
|
|
18
|
-
* @param {*} base64
|
|
19
|
-
*/
|
|
20
|
-
export declare function base64ToUrl(base64: string): string;
|
|
21
|
-
/**
|
|
22
|
-
* @description base64ToFile
|
|
23
|
-
* @param {*} base64
|
|
24
|
-
*/
|
|
25
|
-
export declare function base64ToFile(base64: string): File;
|
|
26
|
-
/**
|
|
27
|
-
* @description blobToBase64
|
|
28
|
-
* @param blob
|
|
29
|
-
*/
|
|
30
|
-
export declare function blobToBase64(blob: Blob): Promise<unknown>;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
function structureFile(blobData) {
|
|
2
|
-
const fileType = blobData.type.split("/");
|
|
3
|
-
const ext = fileType[1];
|
|
4
|
-
const file = new window.File([blobData], `tag.${ext}`, {
|
|
5
|
-
type: blobData.type
|
|
6
|
-
});
|
|
7
|
-
return file;
|
|
8
|
-
}
|
|
9
|
-
function blobToUrl(blobData) {
|
|
10
|
-
return URL.createObjectURL(blobData);
|
|
11
|
-
}
|
|
12
|
-
function convertBase64ToBlob(base64) {
|
|
13
|
-
const base64Arr = base64.split(",");
|
|
14
|
-
let imgType = "";
|
|
15
|
-
let base64String = "";
|
|
16
|
-
if (base64Arr.length > 1) {
|
|
17
|
-
base64String = base64Arr[1];
|
|
18
|
-
imgType = base64Arr[0].substring(
|
|
19
|
-
base64Arr[0].indexOf(":") + 1,
|
|
20
|
-
base64Arr[0].indexOf(";")
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
const bytes = atob(base64String);
|
|
24
|
-
const bytesCode = new ArrayBuffer(bytes.length);
|
|
25
|
-
const byteArray = new Uint8Array(bytesCode);
|
|
26
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
27
|
-
byteArray[i] = bytes.charCodeAt(i);
|
|
28
|
-
}
|
|
29
|
-
return new Blob([bytesCode], { type: imgType });
|
|
30
|
-
}
|
|
31
|
-
function base64ToUrl(base64) {
|
|
32
|
-
const blobData = convertBase64ToBlob(base64);
|
|
33
|
-
return blobToUrl(blobData);
|
|
34
|
-
}
|
|
35
|
-
function base64ToFile(base64) {
|
|
36
|
-
const blobData = convertBase64ToBlob(base64);
|
|
37
|
-
return structureFile(blobData);
|
|
38
|
-
}
|
|
39
|
-
function blobToBase64(blob) {
|
|
40
|
-
return new Promise((resolve, reject) => {
|
|
41
|
-
const reader = new FileReader();
|
|
42
|
-
reader.onloadend = () => resolve(reader.result);
|
|
43
|
-
reader.onerror = reject;
|
|
44
|
-
reader.readAsDataURL(blob);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
export {
|
|
48
|
-
base64ToFile,
|
|
49
|
-
base64ToUrl,
|
|
50
|
-
blobToBase64,
|
|
51
|
-
blobToUrl,
|
|
52
|
-
convertBase64ToBlob,
|
|
53
|
-
structureFile
|
|
54
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
function filterEmptyValues(obj) {
|
|
2
|
-
if (!obj || typeof obj !== "object") {
|
|
3
|
-
return {};
|
|
4
|
-
}
|
|
5
|
-
const filtered = {};
|
|
6
|
-
Object.entries(obj).forEach(([key, value]) => {
|
|
7
|
-
if (value !== "" && value !== null && value !== void 0) {
|
|
8
|
-
filtered[key] = value;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
return filtered;
|
|
12
|
-
}
|
|
13
|
-
export {
|
|
14
|
-
filterEmptyValues
|
|
15
|
-
};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 下载图片
|
|
3
|
-
* @param url 图片URL
|
|
4
|
-
*/
|
|
5
|
-
export declare function downloadImage(url: string): void;
|
|
6
|
-
/**
|
|
7
|
-
* @description 获取网络图片
|
|
8
|
-
* @param url
|
|
9
|
-
*/
|
|
10
|
-
export declare function fetchHasOnlineFile(url: string): Promise<number | false>;
|
|
11
|
-
/**
|
|
12
|
-
* @description 判断文件类型是否有效
|
|
13
|
-
* @param file
|
|
14
|
-
* @param validExtensions
|
|
15
|
-
* @param validMimeTypes
|
|
16
|
-
*/
|
|
17
|
-
export declare const isValidFileType: (file: File | string, validExtensions?: string[], validMimeTypes?: string[]) => boolean;
|
|
18
|
-
/**
|
|
19
|
-
* @description 判断文件大小是否有效
|
|
20
|
-
* @param file
|
|
21
|
-
* @param maxSize
|
|
22
|
-
*/
|
|
23
|
-
export declare const isValidFileSize: (file: File, maxSize?: number) => boolean;
|
|
24
|
-
/**
|
|
25
|
-
* @description getBase64 by tempUrl
|
|
26
|
-
* @param tempUrl
|
|
27
|
-
*/
|
|
28
|
-
export declare const getBase64Client: (tempUrl: string) => Promise<string>;
|
|
29
|
-
/**
|
|
30
|
-
* @description 下载图片
|
|
31
|
-
* @param url
|
|
32
|
-
*/
|
|
33
|
-
export declare const downloadImageClient: (url: string) => Promise<void>;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
|
-
import FileSaver from "file-saver";
|
|
3
|
-
import { blobToBase64 } from "./utils-canvas.js";
|
|
4
|
-
function downloadImage(url) {
|
|
5
|
-
const a = document.createElement("a");
|
|
6
|
-
a.href = url;
|
|
7
|
-
a.target = "_blank";
|
|
8
|
-
a.download = "my-labubu.png";
|
|
9
|
-
a.click();
|
|
10
|
-
}
|
|
11
|
-
async function fetchHasOnlineFile(url) {
|
|
12
|
-
const res = await fetch(url, {
|
|
13
|
-
method: "head"
|
|
14
|
-
});
|
|
15
|
-
if (res.status === 200) {
|
|
16
|
-
return Number(res.headers.get("Content-Length"));
|
|
17
|
-
} else {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
const isValidFileType = (file, validExtensions = [".jpg", ".jpeg", ".png", ".gif", ".webp"], validMimeTypes = [
|
|
22
|
-
"image/jpeg",
|
|
23
|
-
"image/png",
|
|
24
|
-
"image/gif",
|
|
25
|
-
"image/webp"
|
|
26
|
-
]) => {
|
|
27
|
-
if (typeof file === "string") {
|
|
28
|
-
return validExtensions.some((ext) => file.toLowerCase().endsWith(ext));
|
|
29
|
-
} else if (file instanceof File) {
|
|
30
|
-
return validMimeTypes.includes(file.type);
|
|
31
|
-
}
|
|
32
|
-
return false;
|
|
33
|
-
};
|
|
34
|
-
const isValidFileSize = (file, maxSize = 10 * 1024 * 1024) => {
|
|
35
|
-
return file.size <= maxSize;
|
|
36
|
-
};
|
|
37
|
-
const getBase64Client = async (tempUrl) => {
|
|
38
|
-
const response = await fetch(tempUrl);
|
|
39
|
-
const blob = await response.blob();
|
|
40
|
-
const base64 = await blobToBase64(blob);
|
|
41
|
-
return base64;
|
|
42
|
-
};
|
|
43
|
-
const downloadImageClient = async (url) => {
|
|
44
|
-
const response = await axios.get(url, { responseType: "blob" });
|
|
45
|
-
const blob = response.data;
|
|
46
|
-
const tempUrl = URL.createObjectURL(blob);
|
|
47
|
-
const uuid = Math.random().toString(36).substring(2);
|
|
48
|
-
FileSaver.saveAs(tempUrl, `${uuid}.png`);
|
|
49
|
-
};
|
|
50
|
-
export {
|
|
51
|
-
downloadImage,
|
|
52
|
-
downloadImageClient,
|
|
53
|
-
fetchHasOnlineFile,
|
|
54
|
-
getBase64Client,
|
|
55
|
-
isValidFileSize,
|
|
56
|
-
isValidFileType
|
|
57
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const nanoid: (size?: number) => string;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 计算距离现在多少时间
|
|
3
|
-
* @param date 目标日期
|
|
4
|
-
* @param options 配置选项
|
|
5
|
-
* @returns 格式化的时间差字符串
|
|
6
|
-
*/
|
|
7
|
-
export declare function timeAgo(date: string | Date, options?: {
|
|
8
|
-
lang?: "zh" | "en";
|
|
9
|
-
showSeconds?: boolean;
|
|
10
|
-
showZero?: boolean;
|
|
11
|
-
}): string;
|
|
12
|
-
/**
|
|
13
|
-
* 格式化日期为相对时间(简化版)
|
|
14
|
-
* @param date 目标日期
|
|
15
|
-
* @returns 格式化的时间差字符串
|
|
16
|
-
*/
|
|
17
|
-
export declare function formatTimeAgo(date: string | Date): string;
|
|
18
|
-
/**
|
|
19
|
-
* 获取详细的时间信息
|
|
20
|
-
* @param date 目标日期
|
|
21
|
-
* @returns 包含各种时间单位的对象
|
|
22
|
-
*/
|
|
23
|
-
export declare function getTimeDetails(date: string | Date): {
|
|
24
|
-
seconds: number;
|
|
25
|
-
minutes: number;
|
|
26
|
-
hours: number;
|
|
27
|
-
days: number;
|
|
28
|
-
weeks: number;
|
|
29
|
-
months: number;
|
|
30
|
-
years: number;
|
|
31
|
-
isValid: boolean;
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* 获取时间戳
|
|
35
|
-
* @returns 时间戳
|
|
36
|
-
*/
|
|
37
|
-
export declare const getTimestamp: () => number;
|
|
38
|
-
/**
|
|
39
|
-
* 睡眠
|
|
40
|
-
* @param ms 睡眠时间
|
|
41
|
-
* @returns 睡眠后的Promise
|
|
42
|
-
*/
|
|
43
|
-
export declare const sleep: (ms: number) => Promise<unknown>;
|
|
44
|
-
/**
|
|
45
|
-
* 格式化时间
|
|
46
|
-
* @param time 时间
|
|
47
|
-
* @returns 格式化后的时间
|
|
48
|
-
*/
|
|
49
|
-
export declare const formatTimeString: (time: Date) => string;
|
package/dist/utils/utils-time.js
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import dayjs from "dayjs";
|
|
2
|
-
function timeAgo(date, options = {}) {
|
|
3
|
-
const { lang = "zh", showSeconds = false, showZero = false } = options;
|
|
4
|
-
const now = /* @__PURE__ */ new Date();
|
|
5
|
-
const targetDate = typeof date === "string" ? new Date(date) : date;
|
|
6
|
-
const diffInMs = now.getTime() - targetDate.getTime();
|
|
7
|
-
if (isNaN(diffInMs) || diffInMs < 0) {
|
|
8
|
-
return lang === "zh" ? "刚刚" : "just now";
|
|
9
|
-
}
|
|
10
|
-
const diffInSeconds = Math.floor(diffInMs / 1e3);
|
|
11
|
-
const diffInMinutes = Math.floor(diffInSeconds / 60);
|
|
12
|
-
const diffInHours = Math.floor(diffInMinutes / 60);
|
|
13
|
-
const diffInDays = Math.floor(diffInHours / 24);
|
|
14
|
-
const diffInWeeks = Math.floor(diffInDays / 7);
|
|
15
|
-
const diffInMonths = Math.floor(diffInDays / 30);
|
|
16
|
-
const diffInYears = Math.floor(diffInDays / 365);
|
|
17
|
-
if (lang === "zh") {
|
|
18
|
-
if (diffInYears > 0) {
|
|
19
|
-
return `${diffInYears}年前`;
|
|
20
|
-
}
|
|
21
|
-
if (diffInMonths > 0) {
|
|
22
|
-
return `${diffInMonths}个月前`;
|
|
23
|
-
}
|
|
24
|
-
if (diffInWeeks > 0) {
|
|
25
|
-
return `${diffInWeeks}周前`;
|
|
26
|
-
}
|
|
27
|
-
if (diffInDays > 0) {
|
|
28
|
-
return `${diffInDays}天前`;
|
|
29
|
-
}
|
|
30
|
-
if (diffInHours > 0) {
|
|
31
|
-
return `${diffInHours}小时前`;
|
|
32
|
-
}
|
|
33
|
-
if (diffInMinutes > 0) {
|
|
34
|
-
return `${diffInMinutes}分钟前`;
|
|
35
|
-
}
|
|
36
|
-
if (showSeconds && diffInSeconds > 0) {
|
|
37
|
-
return `${diffInSeconds}秒前`;
|
|
38
|
-
}
|
|
39
|
-
return showZero ? "0秒前" : "刚刚";
|
|
40
|
-
} else {
|
|
41
|
-
if (diffInYears > 0) {
|
|
42
|
-
return `${diffInYears} year${diffInYears > 1 ? "s" : ""} ago`;
|
|
43
|
-
}
|
|
44
|
-
if (diffInMonths > 0) {
|
|
45
|
-
return `${diffInMonths} month${diffInMonths > 1 ? "s" : ""} ago`;
|
|
46
|
-
}
|
|
47
|
-
if (diffInWeeks > 0) {
|
|
48
|
-
return `${diffInWeeks} week${diffInWeeks > 1 ? "s" : ""} ago`;
|
|
49
|
-
}
|
|
50
|
-
if (diffInDays > 0) {
|
|
51
|
-
return `${diffInDays} day${diffInDays > 1 ? "s" : ""} ago`;
|
|
52
|
-
}
|
|
53
|
-
if (diffInHours > 0) {
|
|
54
|
-
return `${diffInHours} hour${diffInHours > 1 ? "s" : ""} ago`;
|
|
55
|
-
}
|
|
56
|
-
if (diffInMinutes > 0) {
|
|
57
|
-
return `${diffInMinutes} minute${diffInMinutes > 1 ? "s" : ""} ago`;
|
|
58
|
-
}
|
|
59
|
-
if (showSeconds && diffInSeconds > 0) {
|
|
60
|
-
return `${diffInSeconds} second${diffInSeconds > 1 ? "s" : ""} ago`;
|
|
61
|
-
}
|
|
62
|
-
return showZero ? "0 seconds ago" : "just now";
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
function formatTimeAgo(date) {
|
|
66
|
-
return timeAgo(date, { lang: "en" });
|
|
67
|
-
}
|
|
68
|
-
function getTimeDetails(date) {
|
|
69
|
-
const now = /* @__PURE__ */ new Date();
|
|
70
|
-
const targetDate = typeof date === "string" ? new Date(date) : date;
|
|
71
|
-
const diffInMs = now.getTime() - targetDate.getTime();
|
|
72
|
-
if (isNaN(diffInMs) || diffInMs < 0) {
|
|
73
|
-
return {
|
|
74
|
-
seconds: 0,
|
|
75
|
-
minutes: 0,
|
|
76
|
-
hours: 0,
|
|
77
|
-
days: 0,
|
|
78
|
-
weeks: 0,
|
|
79
|
-
months: 0,
|
|
80
|
-
years: 0,
|
|
81
|
-
isValid: false
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
seconds: Math.floor(diffInMs / 1e3),
|
|
86
|
-
minutes: Math.floor(diffInMs / (1e3 * 60)),
|
|
87
|
-
hours: Math.floor(diffInMs / (1e3 * 60 * 60)),
|
|
88
|
-
days: Math.floor(diffInMs / (1e3 * 60 * 60 * 24)),
|
|
89
|
-
weeks: Math.floor(diffInMs / (1e3 * 60 * 60 * 24 * 7)),
|
|
90
|
-
months: Math.floor(diffInMs / (1e3 * 60 * 60 * 24 * 30)),
|
|
91
|
-
years: Math.floor(diffInMs / (1e3 * 60 * 60 * 24 * 365)),
|
|
92
|
-
isValid: true
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
const getTimestamp = () => {
|
|
96
|
-
const time = Date.parse((/* @__PURE__ */ new Date()).toUTCString());
|
|
97
|
-
return time / 1e3;
|
|
98
|
-
};
|
|
99
|
-
const sleep = (ms) => {
|
|
100
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
101
|
-
};
|
|
102
|
-
const formatTimeString = (time) => {
|
|
103
|
-
return dayjs(time).format("YYYY-MM-DD HH:mm:ss");
|
|
104
|
-
};
|
|
105
|
-
export {
|
|
106
|
-
formatTimeAgo,
|
|
107
|
-
formatTimeString,
|
|
108
|
-
getTimeDetails,
|
|
109
|
-
getTimestamp,
|
|
110
|
-
sleep,
|
|
111
|
-
timeAgo
|
|
112
|
-
};
|