@springbrand/gravel 0.1.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.
Files changed (39) hide show
  1. package/dist/components/ui-base/index.d.ts +1 -0
  2. package/dist/components/ui-base/responsive-dialog/index.d.ts +55 -0
  3. package/dist/components/ui-base/responsive-dialog/index.js +116 -0
  4. package/dist/components/ui-block/background/index.d.ts +8 -0
  5. package/dist/components/ui-block/background/index.js +51 -0
  6. package/dist/components/ui-block/cover/index.d.ts +17 -0
  7. package/dist/components/ui-block/cover/index.js +232 -0
  8. package/dist/components/ui-block/index.d.ts +4 -0
  9. package/dist/components/ui-block/sparkles/index.d.ts +13 -0
  10. package/dist/components/ui-block/sparkles/index.js +287 -0
  11. package/dist/components/ui-block/spotlight/index.d.ts +13 -0
  12. package/dist/components/ui-block/spotlight/index.js +158 -0
  13. package/dist/hooks/use-media-query.d.ts +1 -0
  14. package/dist/hooks/use-media-query.js +15 -0
  15. package/dist/hooks/use-prefers-reduced-motion.d.ts +1 -0
  16. package/dist/hooks/use-prefers-reduced-motion.js +23 -0
  17. package/dist/hooks/use-scroll-container.d.ts +18 -0
  18. package/dist/hooks/use-scroll-container.js +25 -0
  19. package/dist/index.d.ts +6 -0
  20. package/dist/index.js +57 -0
  21. package/dist/utils/css-utils.d.ts +10 -0
  22. package/dist/utils/css-utils.js +17 -0
  23. package/dist/utils/index.d.ts +9 -0
  24. package/dist/utils/index.js +34 -0
  25. package/dist/utils/storage-qetag.d.ts +22 -0
  26. package/dist/utils/storage-qetag.js +101 -0
  27. package/dist/utils/utils-api.d.ts +17 -0
  28. package/dist/utils/utils-api.js +31 -0
  29. package/dist/utils/utils-canvas.d.ts +30 -0
  30. package/dist/utils/utils-canvas.js +54 -0
  31. package/dist/utils/utils-common.d.ts +6 -0
  32. package/dist/utils/utils-common.js +15 -0
  33. package/dist/utils/utils-image.d.ts +33 -0
  34. package/dist/utils/utils-image.js +57 -0
  35. package/dist/utils/utils-random.d.ts +1 -0
  36. package/dist/utils/utils-random.js +6 -0
  37. package/dist/utils/utils-time.d.ts +49 -0
  38. package/dist/utils/utils-time.js +112 -0
  39. package/package.json +386 -0
@@ -0,0 +1,22 @@
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 {};
@@ -0,0 +1,101 @@
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
+ };
@@ -0,0 +1,17 @@
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;
@@ -0,0 +1,31 @@
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
+ };
@@ -0,0 +1,30 @@
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>;
@@ -0,0 +1,54 @@
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
+ };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @description 过滤对象中的空值
3
+ * @param obj 要过滤的对象
4
+ * @returns 过滤后的对象
5
+ */
6
+ export declare function filterEmptyValues(obj: Record<string, any>): Record<string, any>;
@@ -0,0 +1,15 @@
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
+ };
@@ -0,0 +1,33 @@
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>;
@@ -0,0 +1,57 @@
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
+ };
@@ -0,0 +1 @@
1
+ export declare const nanoid: (size?: number) => string;
@@ -0,0 +1,6 @@
1
+ import { customAlphabet } from "nanoid";
2
+ const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
3
+ const nanoid = customAlphabet(alphabet, 16);
4
+ export {
5
+ nanoid
6
+ };
@@ -0,0 +1,49 @@
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;
@@ -0,0 +1,112 @@
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
+ };