@springbrand/gravel 0.1.0 → 0.1.2

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.
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsxs, jsx } from "react/jsx-runtime";
3
- import { cn } from "../../../utils/css-utils.js";
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 "../../../utils/css-utils.js";
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.0",
3
+ "version": "0.1.2",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -38,190 +38,20 @@
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": {
59
- "@dnd-kit/core": "^6.3.1",
60
- "@dnd-kit/sortable": "^10.0.0",
61
- "@dnd-kit/utilities": "^3.2.2",
62
- "@emotion/is-prop-valid": "1.4.0",
63
- "@relume_io/relume-tailwind": "^1.3.0",
64
- "@springbrand/site-block": "0.1.0",
65
- "embla-carousel-autoplay": "8.6.0",
66
- "react-advanced-cropper": "0.20.1",
67
- "react-error-boundary": "6.1.1",
68
- "react-icons": "5.6.0",
69
- "shadcn": "4.2.0",
70
- "zod": "4.3.6"
44
+ "@springbrand/site-block": "0.1.2",
45
+ "@springbrand/utils": "0.1.1"
71
46
  },
72
47
  "peerDependencies": {
73
- "@base-ui/react": "^1.0.0",
74
- "@base-ui/utils": "^0.2.0",
75
- "@date-fns/tz": "^1.0.0",
76
- "@fluid-tailwind/tailwind-merge": "^0.0.3",
77
- "@puckeditor/core": "^0.21.0",
78
- "@radix-ui/primitive": "^1.0.0",
79
- "@radix-ui/react-compose-refs": "^1.0.0",
80
- "@radix-ui/react-context": "^1.0.0",
81
- "@radix-ui/react-dialog": "^1.0.0",
82
- "@radix-ui/react-direction": "^1.0.0",
83
- "@radix-ui/react-dismissable-layer": "^1.0.0",
84
- "@radix-ui/react-focus-guards": "^1.0.0",
85
- "@radix-ui/react-focus-scope": "^1.0.0",
86
- "@radix-ui/react-id": "^1.0.0",
87
- "@radix-ui/react-portal": "^1.0.0",
88
- "@radix-ui/react-presence": "^1.0.0",
89
- "@radix-ui/react-primitive": "^2.0.0",
90
- "@radix-ui/react-roving-focus": "^1.0.0",
91
- "@radix-ui/react-slot": "^1.0.0",
92
- "@radix-ui/react-toggle": "^1.0.0",
93
- "@radix-ui/react-toggle-group": "^1.0.0",
94
- "@radix-ui/react-use-controllable-state": "^1.0.0",
95
- "@radix-ui/react-use-effect-event": "^0.0.2",
96
- "@radix-ui/react-use-layout-effect": "^1.0.0",
97
48
  "@tsparticles/engine": "^3.0.0",
98
49
  "@tsparticles/react": "^3.0.0",
99
50
  "@tsparticles/slim": "^3.0.0",
100
- "aria-hidden": "^1.0.0",
101
- "axios": "^1.0.0",
102
- "class-variance-authority": "^0.7.0",
103
- "clsx": "^2.0.0",
104
- "cmdk": "^1.0.0",
105
- "d3-array": "^3.0.0",
106
- "d3-ease": "^3.0.0",
107
- "d3-format": "^3.0.0",
108
- "d3-interpolate": "^3.0.0",
109
- "d3-scale": "^4.0.0",
110
- "d3-shape": "^3.0.0",
111
- "d3-time": "^3.0.0",
112
- "d3-time-format": "^4.0.0",
113
- "d3-timer": "^3.0.0",
114
- "dayjs": "^1.11.0",
115
- "decimal.js-light": "^2.5.0",
116
- "embla-carousel": "^8.0.0",
117
- "embla-carousel-react": "^8.0.0",
118
- "embla-carousel-reactive-utils": "^8.0.0",
119
- "eventemitter3": "^4.0.0",
120
- "fast-equals": "^5.0.0",
121
- "file-saver": "^2.0.0",
122
- "file-type": "^12.0.0",
123
- "input-otp": "^1.0.0",
124
- "js-sha1": "^0.6.0",
125
- "lodash": "^4.17.0",
126
- "lodash-es": "^4.17.0",
127
- "lucide-react": ">=0.400.0",
128
51
  "motion": ">=12.0.0",
129
- "nanoid": "^5.0.0",
130
- "next-themes": "^0.4.0",
131
- "prop-types": "^15.0.0",
132
- "radix-ui": "^1.0.0",
133
- "react": "^19.0.0",
134
- "react-day-picker": "^9.0.0",
135
- "react-dom": "^19.0.0",
136
- "react-easy-crop": "^5.0.0",
137
- "react-is": "^19.0.0",
138
- "react-remove-scroll": "^2.0.0",
139
- "react-resizable-panels": "^2.0.0",
140
- "react-smooth": "^4.0.0",
141
- "react-transition-group": "^4.0.0",
142
- "recharts": "^2.0.0",
143
- "recharts-scale": "^0.4.0",
144
- "sonner": "^2.0.0",
145
- "tailwind-merge": "^3.0.0",
146
- "tailwindcss": "^4.0.0",
147
- "tiny-invariant": "^1.0.0",
148
- "tw-animate-css": "^1.0.0",
149
- "vaul": "^1.0.0",
150
- "victory-vendor": "^36.0.0"
52
+ "react": "^19.0.0"
151
53
  },
152
54
  "peerDependenciesMeta": {
153
- "@base-ui/react": {
154
- "optional": true
155
- },
156
- "@base-ui/utils": {
157
- "optional": true
158
- },
159
- "@date-fns/tz": {
160
- "optional": true
161
- },
162
- "@fluid-tailwind/tailwind-merge": {
163
- "optional": true
164
- },
165
- "@puckeditor/core": {
166
- "optional": true
167
- },
168
- "@radix-ui/primitive": {
169
- "optional": true
170
- },
171
- "@radix-ui/react-compose-refs": {
172
- "optional": true
173
- },
174
- "@radix-ui/react-context": {
175
- "optional": true
176
- },
177
- "@radix-ui/react-dialog": {
178
- "optional": true
179
- },
180
- "@radix-ui/react-direction": {
181
- "optional": true
182
- },
183
- "@radix-ui/react-dismissable-layer": {
184
- "optional": true
185
- },
186
- "@radix-ui/react-focus-guards": {
187
- "optional": true
188
- },
189
- "@radix-ui/react-focus-scope": {
190
- "optional": true
191
- },
192
- "@radix-ui/react-id": {
193
- "optional": true
194
- },
195
- "@radix-ui/react-portal": {
196
- "optional": true
197
- },
198
- "@radix-ui/react-presence": {
199
- "optional": true
200
- },
201
- "@radix-ui/react-primitive": {
202
- "optional": true
203
- },
204
- "@radix-ui/react-roving-focus": {
205
- "optional": true
206
- },
207
- "@radix-ui/react-slot": {
208
- "optional": true
209
- },
210
- "@radix-ui/react-toggle": {
211
- "optional": true
212
- },
213
- "@radix-ui/react-toggle-group": {
214
- "optional": true
215
- },
216
- "@radix-ui/react-use-controllable-state": {
217
- "optional": true
218
- },
219
- "@radix-ui/react-use-effect-event": {
220
- "optional": true
221
- },
222
- "@radix-ui/react-use-layout-effect": {
223
- "optional": true
224
- },
225
55
  "@tsparticles/engine": {
226
56
  "optional": true
227
57
  },
@@ -231,156 +61,9 @@
231
61
  "@tsparticles/slim": {
232
62
  "optional": true
233
63
  },
234
- "aria-hidden": {
235
- "optional": true
236
- },
237
- "axios": {
238
- "optional": true
239
- },
240
- "class-variance-authority": {
241
- "optional": true
242
- },
243
- "clsx": {
244
- "optional": true
245
- },
246
- "cmdk": {
247
- "optional": true
248
- },
249
- "d3-array": {
250
- "optional": true
251
- },
252
- "d3-ease": {
253
- "optional": true
254
- },
255
- "d3-format": {
256
- "optional": true
257
- },
258
- "d3-interpolate": {
259
- "optional": true
260
- },
261
- "d3-scale": {
262
- "optional": true
263
- },
264
- "d3-shape": {
265
- "optional": true
266
- },
267
- "d3-time": {
268
- "optional": true
269
- },
270
- "d3-time-format": {
271
- "optional": true
272
- },
273
- "d3-timer": {
274
- "optional": true
275
- },
276
- "dayjs": {
277
- "optional": true
278
- },
279
- "decimal.js-light": {
280
- "optional": true
281
- },
282
- "embla-carousel": {
283
- "optional": true
284
- },
285
- "embla-carousel-react": {
286
- "optional": true
287
- },
288
- "embla-carousel-reactive-utils": {
289
- "optional": true
290
- },
291
- "eventemitter3": {
292
- "optional": true
293
- },
294
- "fast-equals": {
295
- "optional": true
296
- },
297
- "file-saver": {
298
- "optional": true
299
- },
300
- "file-type": {
301
- "optional": true
302
- },
303
- "input-otp": {
304
- "optional": true
305
- },
306
- "js-sha1": {
307
- "optional": true
308
- },
309
- "lodash": {
310
- "optional": true
311
- },
312
- "lodash-es": {
313
- "optional": true
314
- },
315
- "lucide-react": {
316
- "optional": true
317
- },
318
64
  "motion": {
319
65
  "optional": true
320
- },
321
- "nanoid": {
322
- "optional": true
323
- },
324
- "next-themes": {
325
- "optional": true
326
- },
327
- "prop-types": {
328
- "optional": true
329
- },
330
- "radix-ui": {
331
- "optional": true
332
- },
333
- "react-day-picker": {
334
- "optional": true
335
- },
336
- "react-easy-crop": {
337
- "optional": true
338
- },
339
- "react-error-boundary": {
340
- "optional": true
341
- },
342
- "react-is": {
343
- "optional": true
344
- },
345
- "react-remove-scroll": {
346
- "optional": true
347
- },
348
- "react-resizable-panels": {
349
- "optional": true
350
- },
351
- "react-smooth": {
352
- "optional": true
353
- },
354
- "react-transition-group": {
355
- "optional": true
356
- },
357
- "recharts": {
358
- "optional": true
359
- },
360
- "recharts-scale": {
361
- "optional": true
362
- },
363
- "sonner": {
364
- "optional": true
365
- },
366
- "tailwind-merge": {
367
- "optional": true
368
- },
369
- "tailwindcss": {
370
- "optional": true
371
- },
372
- "tiny-invariant": {
373
- "optional": true
374
- },
375
- "tw-animate-css": {
376
- "optional": true
377
- },
378
- "vaul": {
379
- "optional": true
380
- },
381
- "victory-vendor": {
382
- "optional": true
383
66
  }
384
67
  },
385
- "gitHead": "2cdd3f78e11ced73fb109ba9d4718476370829c7"
68
+ "gitHead": "c5c89c18c4ffc827aeaa239163542ef288d8dc5b"
386
69
  }
@@ -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;
@@ -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
- };
@@ -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";
@@ -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;
@@ -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,6 +0,0 @@
1
- /**
2
- * @description 过滤对象中的空值
3
- * @param obj 要过滤的对象
4
- * @returns 过滤后的对象
5
- */
6
- export declare function filterEmptyValues(obj: Record<string, any>): Record<string, any>;
@@ -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,6 +0,0 @@
1
- import { customAlphabet } from "nanoid";
2
- const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
3
- const nanoid = customAlphabet(alphabet, 16);
4
- export {
5
- nanoid
6
- };
@@ -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;
@@ -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
- };