@windrun-huaiin/third-ui 5.11.5 → 5.12.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windrun-huaiin/third-ui",
3
- "version": "5.11.5",
3
+ "version": "5.12.0",
4
4
  "description": "Third-party integrated UI components for windrun-huaiin projects",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -1,18 +1,22 @@
1
1
  'use client'
2
2
 
3
3
  import { globalLucideIcons as icons } from "@base-ui/components/global-icon"
4
+ import { cn } from '@lib/utils'
4
5
  import { useTranslations } from 'next-intl'
5
6
  import Image from "next/image"
6
- import { GradientButton } from "@third-ui/fuma/mdx/gradient-button"
7
- import { cn } from '@lib/utils';
8
- import { useState } from 'react';
7
+ import { useState } from 'react'
9
8
 
10
9
  interface GalleryItem {
11
10
  url: string;
12
11
  altMsg: string;
13
12
  }
14
13
 
15
- export function Gallery({ sectionClassName }: { sectionClassName?: string }) {
14
+ interface GalleryProps {
15
+ sectionClassName?: string;
16
+ button?: React.ReactNode;
17
+ }
18
+
19
+ export function Gallery({ sectionClassName, button }: GalleryProps) {
16
20
  const t = useTranslations('gallery');
17
21
  const galleryItems = t.raw('prompts') as GalleryItem[];
18
22
  const defaultImgUrl = t.raw('defaultImgUrl') as string;
@@ -20,16 +24,63 @@ export function Gallery({ sectionClassName }: { sectionClassName?: string }) {
20
24
 
21
25
  const handleDownload = async (item: GalleryItem, index: number) => {
22
26
  try {
23
- const response = await fetch(item.url);
27
+ // use fetch to force download, and DO NEED CORS config in R2
28
+ const response = await fetch(item.url, {
29
+ method: 'GET',
30
+ // CORS mode declaration
31
+ mode: 'cors',
32
+ });
33
+
34
+ if (!response.ok) {
35
+ throw new Error(`HTTP error! status: ${response.status}`);
36
+ }
37
+
24
38
  const blob = await response.blob();
25
39
  const url = window.URL.createObjectURL(blob);
40
+
41
+ // set extension based on the actual file type
42
+ const contentType = response.headers.get('content-type');
43
+ let extension = '.webp';
44
+
45
+ if (contentType) {
46
+ switch (contentType) {
47
+ case 'image/jpeg':
48
+ case 'image/jpg':
49
+ extension = '.jpg';
50
+ break;
51
+ case 'image/png':
52
+ extension = '.png';
53
+ break;
54
+ case 'image/gif':
55
+ extension = '.gif';
56
+ break;
57
+ case 'image/webp':
58
+ extension = '.webp';
59
+ break;
60
+ case 'image/svg+xml':
61
+ extension = '.svg';
62
+ break;
63
+ default:
64
+ // if cannot determine, try to extract the extension from the URL
65
+ const urlExtension = item.url.split('.').pop()?.toLowerCase();
66
+ if (urlExtension && ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'].includes(urlExtension)) {
67
+ extension = `.${urlExtension}`;
68
+ }
69
+ }
70
+ }
71
+ const downloadPrefix = t('downloadPrefix');
26
72
  const a = document.createElement('a');
27
73
  a.href = url;
28
- a.download = `reve-image-${index + 1}.webp`;
74
+ a.download = `${downloadPrefix}-${index + 1}${extension}`;
75
+ a.style.display = 'none';
29
76
  document.body.appendChild(a);
30
77
  a.click();
31
- window.URL.revokeObjectURL(url);
32
- document.body.removeChild(a);
78
+
79
+ // clean up
80
+ setTimeout(() => {
81
+ window.URL.revokeObjectURL(url);
82
+ document.body.removeChild(a);
83
+ }, 100);
33
84
  } catch (error) {
34
85
  console.error('Download failed:', error);
35
86
  }
@@ -73,13 +124,11 @@ export function Gallery({ sectionClassName }: { sectionClassName?: string }) {
73
124
  </div>
74
125
  ))}
75
126
  </div>
76
- <div className="text-center mt-12">
77
- <GradientButton
78
- title={t('button')}
79
- href="https://preview.reve.art/"
80
- align="center"
81
- />
82
- </div>
127
+ {button && (
128
+ <div className="text-center mt-12">
129
+ {button}
130
+ </div>
131
+ )}
83
132
  </section>
84
133
  )
85
134
  }