jean-react-utils 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.
- package/README.md +39 -0
- package/dist/index.d.mts +72 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +333 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +289 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +66 -0
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Jean-utils
|
|
2
|
+
|
|
3
|
+
## 目的
|
|
4
|
+
|
|
5
|
+
个人 Next.js 博客与网站的可复用 UI 组件库
|
|
6
|
+
|
|
7
|
+
## 内容
|
|
8
|
+
- 通用组件(Button、Card)
|
|
9
|
+
- React Hooks(useForceRerender)
|
|
10
|
+
- Tailwind theme 配置
|
|
11
|
+
- i18n 封装,基于 next-intl
|
|
12
|
+
- 支持调用方自定义messages路径
|
|
13
|
+
- 兼容 getRequestConfig 自动集成功能
|
|
14
|
+
|
|
15
|
+
## 项目结构
|
|
16
|
+
```
|
|
17
|
+
jean-utils/
|
|
18
|
+
├── src/
|
|
19
|
+
│ ├── components/ ← Button / Card 等通用组件
|
|
20
|
+
│ ├── layout/ ← Header / Footer / Nav
|
|
21
|
+
│ ├── hooks/ ← useForceRerender、useMediaQuery 等
|
|
22
|
+
│ ├── theme/ ← tailwind theme、token
|
|
23
|
+
│ ├── i18n/ ← next-intl 封装
|
|
24
|
+
│ └── index.ts ← 统一导出
|
|
25
|
+
├── package.json
|
|
26
|
+
├── tsconfig.json
|
|
27
|
+
├── tailwind.config.ts
|
|
28
|
+
├── vitest.config.ts
|
|
29
|
+
├── postcss.config.js
|
|
30
|
+
└── README.md
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 现有痛点
|
|
34
|
+
- 每次调试都涉及多个package,心智负担大
|
|
35
|
+
- 更新组件时要发布版本、链接依赖、跑构建流程
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
4
|
+
variant?: 'primary' | 'secondary' | 'outline';
|
|
5
|
+
size?: 'sm' | 'md' | 'lg';
|
|
6
|
+
}
|
|
7
|
+
declare const Button: React.FC<ButtonProps>;
|
|
8
|
+
|
|
9
|
+
interface HeadingProps {
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
className?: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function PageTitle({ children, title, className }: HeadingProps): JSX.Element;
|
|
15
|
+
declare function SectionTitle({ children, title, className }: HeadingProps): JSX.Element;
|
|
16
|
+
declare function CardTitle({ children, title, className }: HeadingProps): JSX.Element;
|
|
17
|
+
declare function SubTitle({ children, title, className }: HeadingProps): JSX.Element;
|
|
18
|
+
|
|
19
|
+
interface NavItem {
|
|
20
|
+
key: string;
|
|
21
|
+
href: string;
|
|
22
|
+
label: string;
|
|
23
|
+
className?: {
|
|
24
|
+
pc?: string;
|
|
25
|
+
mobile?: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
interface HeaderProps {
|
|
29
|
+
logo: React.ReactNode;
|
|
30
|
+
menuItems: NavItem[];
|
|
31
|
+
className?: string;
|
|
32
|
+
/** 是否啟用動畫效果 */
|
|
33
|
+
enableAnimation?: boolean;
|
|
34
|
+
}
|
|
35
|
+
declare const Header: React.FC<HeaderProps>;
|
|
36
|
+
|
|
37
|
+
interface FooterLink {
|
|
38
|
+
href: string;
|
|
39
|
+
title: string;
|
|
40
|
+
}
|
|
41
|
+
interface FooterTexts {
|
|
42
|
+
copyright: string;
|
|
43
|
+
privacy: string;
|
|
44
|
+
terms: string;
|
|
45
|
+
social: string;
|
|
46
|
+
}
|
|
47
|
+
interface FooterProps {
|
|
48
|
+
/** 網站基本信息 */
|
|
49
|
+
site: {
|
|
50
|
+
name: string;
|
|
51
|
+
description: string;
|
|
52
|
+
};
|
|
53
|
+
/** 導航鏈接 */
|
|
54
|
+
navigation: {
|
|
55
|
+
/** 快速鏈接區塊 */
|
|
56
|
+
quickLinks: {
|
|
57
|
+
title: string;
|
|
58
|
+
items: FooterLink[];
|
|
59
|
+
};
|
|
60
|
+
/** 社交媒體鏈接 */
|
|
61
|
+
socialLinks: FooterLink[];
|
|
62
|
+
};
|
|
63
|
+
/** 頁腳文本 */
|
|
64
|
+
texts: FooterTexts;
|
|
65
|
+
/** 自定義類名 */
|
|
66
|
+
className?: string;
|
|
67
|
+
}
|
|
68
|
+
declare const Footer: React.FC<FooterProps>;
|
|
69
|
+
|
|
70
|
+
declare const useForceRerender: () => [number, () => void];
|
|
71
|
+
|
|
72
|
+
export { Button, CardTitle, Footer, type FooterLink, type FooterProps, type FooterTexts, Header, PageTitle, SectionTitle, SubTitle, useForceRerender };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
4
|
+
variant?: 'primary' | 'secondary' | 'outline';
|
|
5
|
+
size?: 'sm' | 'md' | 'lg';
|
|
6
|
+
}
|
|
7
|
+
declare const Button: React.FC<ButtonProps>;
|
|
8
|
+
|
|
9
|
+
interface HeadingProps {
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
className?: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function PageTitle({ children, title, className }: HeadingProps): JSX.Element;
|
|
15
|
+
declare function SectionTitle({ children, title, className }: HeadingProps): JSX.Element;
|
|
16
|
+
declare function CardTitle({ children, title, className }: HeadingProps): JSX.Element;
|
|
17
|
+
declare function SubTitle({ children, title, className }: HeadingProps): JSX.Element;
|
|
18
|
+
|
|
19
|
+
interface NavItem {
|
|
20
|
+
key: string;
|
|
21
|
+
href: string;
|
|
22
|
+
label: string;
|
|
23
|
+
className?: {
|
|
24
|
+
pc?: string;
|
|
25
|
+
mobile?: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
interface HeaderProps {
|
|
29
|
+
logo: React.ReactNode;
|
|
30
|
+
menuItems: NavItem[];
|
|
31
|
+
className?: string;
|
|
32
|
+
/** 是否啟用動畫效果 */
|
|
33
|
+
enableAnimation?: boolean;
|
|
34
|
+
}
|
|
35
|
+
declare const Header: React.FC<HeaderProps>;
|
|
36
|
+
|
|
37
|
+
interface FooterLink {
|
|
38
|
+
href: string;
|
|
39
|
+
title: string;
|
|
40
|
+
}
|
|
41
|
+
interface FooterTexts {
|
|
42
|
+
copyright: string;
|
|
43
|
+
privacy: string;
|
|
44
|
+
terms: string;
|
|
45
|
+
social: string;
|
|
46
|
+
}
|
|
47
|
+
interface FooterProps {
|
|
48
|
+
/** 網站基本信息 */
|
|
49
|
+
site: {
|
|
50
|
+
name: string;
|
|
51
|
+
description: string;
|
|
52
|
+
};
|
|
53
|
+
/** 導航鏈接 */
|
|
54
|
+
navigation: {
|
|
55
|
+
/** 快速鏈接區塊 */
|
|
56
|
+
quickLinks: {
|
|
57
|
+
title: string;
|
|
58
|
+
items: FooterLink[];
|
|
59
|
+
};
|
|
60
|
+
/** 社交媒體鏈接 */
|
|
61
|
+
socialLinks: FooterLink[];
|
|
62
|
+
};
|
|
63
|
+
/** 頁腳文本 */
|
|
64
|
+
texts: FooterTexts;
|
|
65
|
+
/** 自定義類名 */
|
|
66
|
+
className?: string;
|
|
67
|
+
}
|
|
68
|
+
declare const Footer: React.FC<FooterProps>;
|
|
69
|
+
|
|
70
|
+
declare const useForceRerender: () => [number, () => void];
|
|
71
|
+
|
|
72
|
+
export { Button, CardTitle, Footer, type FooterLink, type FooterProps, type FooterTexts, Header, PageTitle, SectionTitle, SubTitle, useForceRerender };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
Button: () => Button_default,
|
|
34
|
+
CardTitle: () => CardTitle,
|
|
35
|
+
Footer: () => Footer,
|
|
36
|
+
Header: () => Header_default,
|
|
37
|
+
PageTitle: () => PageTitle,
|
|
38
|
+
SectionTitle: () => SectionTitle,
|
|
39
|
+
SubTitle: () => SubTitle,
|
|
40
|
+
useForceRerender: () => useForceRerender_default
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(index_exports);
|
|
43
|
+
|
|
44
|
+
// src/components/Button/index.tsx
|
|
45
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
46
|
+
var Button = ({
|
|
47
|
+
variant = "primary",
|
|
48
|
+
size = "md",
|
|
49
|
+
className = "",
|
|
50
|
+
children,
|
|
51
|
+
...props
|
|
52
|
+
}) => {
|
|
53
|
+
const baseStyles = "rounded-full font-medium transition-colors";
|
|
54
|
+
const variants = {
|
|
55
|
+
primary: "bg-purple-600 text-white hover:bg-purple-700 shadow-lg shadow-purple-500/20",
|
|
56
|
+
secondary: "bg-purple-50 text-purple-700 hover:bg-purple-100",
|
|
57
|
+
outline: "border-2 border-purple-600 text-purple-600 hover:bg-purple-50"
|
|
58
|
+
};
|
|
59
|
+
const sizes = {
|
|
60
|
+
sm: "px-4 py-1.5 text-sm",
|
|
61
|
+
md: "px-6 py-2 text-sm",
|
|
62
|
+
lg: "px-8 py-3 text-base"
|
|
63
|
+
};
|
|
64
|
+
const classes = `${baseStyles} ${variants[variant]} ${sizes[size]} ${className}`;
|
|
65
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: classes, ...props, children });
|
|
66
|
+
};
|
|
67
|
+
var Button_default = Button;
|
|
68
|
+
|
|
69
|
+
// src/components/Heading/index.tsx
|
|
70
|
+
var import_framer_motion = require("framer-motion");
|
|
71
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
72
|
+
function PageTitle({ children, title, className = "" }) {
|
|
73
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
74
|
+
import_framer_motion.motion.h1,
|
|
75
|
+
{
|
|
76
|
+
initial: { opacity: 0, y: 20 },
|
|
77
|
+
animate: { opacity: 1, y: 0 },
|
|
78
|
+
transition: { duration: 0.8 },
|
|
79
|
+
className: `text-4xl md:text-5xl font-bold mb-6 bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent ${className}`,
|
|
80
|
+
children: title || children
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
function SectionTitle({ children, title, className = "" }) {
|
|
85
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
86
|
+
import_framer_motion.motion.h2,
|
|
87
|
+
{
|
|
88
|
+
initial: { opacity: 0, y: 20 },
|
|
89
|
+
animate: { opacity: 1, y: 0 },
|
|
90
|
+
transition: { duration: 0.8, delay: 0.2 },
|
|
91
|
+
className: `text-3xl font-bold text-center mb-16 bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent ${className}`,
|
|
92
|
+
children: title || children
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
function CardTitle({ children, title, className = "" }) {
|
|
97
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
98
|
+
import_framer_motion.motion.h3,
|
|
99
|
+
{
|
|
100
|
+
initial: { opacity: 0 },
|
|
101
|
+
animate: { opacity: 1 },
|
|
102
|
+
transition: { duration: 0.5 },
|
|
103
|
+
className: `text-2xl font-bold text-gray-800 ${className}`,
|
|
104
|
+
children: title || children
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
function SubTitle({ children, title, className = "" }) {
|
|
109
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
110
|
+
import_framer_motion.motion.h4,
|
|
111
|
+
{
|
|
112
|
+
initial: { opacity: 0 },
|
|
113
|
+
animate: { opacity: 1 },
|
|
114
|
+
transition: { duration: 0.5 },
|
|
115
|
+
className: `text-lg font-semibold text-gray-800 ${className}`,
|
|
116
|
+
children: title || children
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/layout/Header/index.tsx
|
|
122
|
+
var import_react = require("react");
|
|
123
|
+
var import_link = __toESM(require("next/link"));
|
|
124
|
+
var import_framer_motion2 = require("framer-motion");
|
|
125
|
+
|
|
126
|
+
// src/layout/Header/BreadIcon.tsx
|
|
127
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
128
|
+
function BreadIcon({ isMenuOpen }) {
|
|
129
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "w-6 h-5 relative flex flex-col justify-between", children: [
|
|
130
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: `w-full h-0.5 bg-gray-800 transition-transform duration-300 ${isMenuOpen ? "rotate-45 translate-y-2" : ""}` }),
|
|
131
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: `w-full h-0.5 bg-gray-800 transition-opacity duration-300 ${isMenuOpen ? "opacity-0" : ""}` }),
|
|
132
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: `w-full h-0.5 bg-gray-800 transition-transform duration-300 ${isMenuOpen ? "-rotate-45 -translate-y-2" : ""}` })
|
|
133
|
+
] });
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/layout/Header/index.tsx
|
|
137
|
+
var import_navigation = require("next/navigation");
|
|
138
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
139
|
+
var getActivedCls = (href, selectedKey) => {
|
|
140
|
+
if (href.includes(selectedKey) || href === "/" && selectedKey === "home") {
|
|
141
|
+
return "text-purple-600";
|
|
142
|
+
}
|
|
143
|
+
return "text-gray-600";
|
|
144
|
+
};
|
|
145
|
+
var Header = ({
|
|
146
|
+
logo,
|
|
147
|
+
menuItems,
|
|
148
|
+
className = "",
|
|
149
|
+
enableAnimation = true
|
|
150
|
+
}) => {
|
|
151
|
+
const [isMenuOpen, setIsMenuOpen] = (0, import_react.useState)(false);
|
|
152
|
+
const selectedKey = (0, import_navigation.usePathname)().split("/")[2] || "home";
|
|
153
|
+
console.log("selectedKey>>>", selectedKey);
|
|
154
|
+
const baseNavClassName = `fixed top-0 left-0 right-0 z-50 bg-white/80 backdrop-blur-lg border-b border-purple-100 ${className}`;
|
|
155
|
+
const navVariants = {
|
|
156
|
+
hidden: { y: -20, opacity: 0 },
|
|
157
|
+
visible: {
|
|
158
|
+
y: 0,
|
|
159
|
+
opacity: 1,
|
|
160
|
+
transition: {
|
|
161
|
+
duration: 0.5,
|
|
162
|
+
ease: "easeOut"
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const mobileMenuVariants = {
|
|
167
|
+
hidden: {
|
|
168
|
+
height: 0,
|
|
169
|
+
opacity: 0,
|
|
170
|
+
transition: {
|
|
171
|
+
duration: 0.3,
|
|
172
|
+
ease: "easeInOut"
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
visible: {
|
|
176
|
+
height: "auto",
|
|
177
|
+
opacity: 1,
|
|
178
|
+
transition: {
|
|
179
|
+
duration: 0.3,
|
|
180
|
+
ease: "easeInOut"
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
const NavComponent = enableAnimation ? import_framer_motion2.motion.nav : "nav";
|
|
185
|
+
const MobileMenuComponent = enableAnimation ? import_framer_motion2.motion.div : "div";
|
|
186
|
+
console.log("menuItems>>>", menuItems);
|
|
187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
188
|
+
NavComponent,
|
|
189
|
+
{
|
|
190
|
+
className: baseNavClassName,
|
|
191
|
+
...enableAnimation && {
|
|
192
|
+
initial: "hidden",
|
|
193
|
+
animate: "visible",
|
|
194
|
+
variants: navVariants
|
|
195
|
+
},
|
|
196
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "container mx-auto px-4", children: [
|
|
197
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center justify-between h-20", children: [
|
|
198
|
+
logo,
|
|
199
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("nav", { className: "hidden md:flex items-center space-x-8", children: menuItems.map((item) => (
|
|
200
|
+
// <Link
|
|
201
|
+
// key={item.key}
|
|
202
|
+
// href="/"
|
|
203
|
+
// className="flex items-center justify-center gap-2 text-lg font-bold tracking-wide transition-all duration-300 ease-in-out"
|
|
204
|
+
// >
|
|
205
|
+
// {item.label}
|
|
206
|
+
// </Link>
|
|
207
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NavLink, { href: item.href, className: item.className?.pc, selectedKey, children: item.label }, item.key)
|
|
208
|
+
)) }),
|
|
209
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
210
|
+
"button",
|
|
211
|
+
{
|
|
212
|
+
onClick: () => setIsMenuOpen(!isMenuOpen),
|
|
213
|
+
className: "md:hidden p-2 hover:bg-purple-50 rounded-lg transition-colors",
|
|
214
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BreadIcon, { isMenuOpen })
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
] }),
|
|
218
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_framer_motion2.AnimatePresence, { children: isMenuOpen && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
219
|
+
MobileMenuComponent,
|
|
220
|
+
{
|
|
221
|
+
className: "md:hidden overflow-hidden",
|
|
222
|
+
...enableAnimation && {
|
|
223
|
+
initial: "hidden",
|
|
224
|
+
animate: "visible",
|
|
225
|
+
exit: "hidden",
|
|
226
|
+
variants: mobileMenuVariants
|
|
227
|
+
},
|
|
228
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex flex-col space-y-4 py-4 items-center", children: menuItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
229
|
+
import_framer_motion2.motion.div,
|
|
230
|
+
{
|
|
231
|
+
...enableAnimation && {
|
|
232
|
+
initial: { x: -20, opacity: 0 },
|
|
233
|
+
animate: { x: 0, opacity: 1 },
|
|
234
|
+
transition: { delay: 0.1 }
|
|
235
|
+
},
|
|
236
|
+
children: menuItems.map((item2) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MobileNavLink, { href: item2.href, className: item2.className?.mobile, selectedKey, children: item2.label }, item2.key))
|
|
237
|
+
},
|
|
238
|
+
item.key
|
|
239
|
+
)) })
|
|
240
|
+
}
|
|
241
|
+
) })
|
|
242
|
+
] })
|
|
243
|
+
}
|
|
244
|
+
);
|
|
245
|
+
};
|
|
246
|
+
var NavLink = ({ href, children, className, selectedKey }) => {
|
|
247
|
+
const combinedClassName = `${className || "text-gray-600 hover:text-black transition-colors"} ${getActivedCls(href, selectedKey)}`;
|
|
248
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_link.default, { href, legacyBehavior: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { className: combinedClassName, children }) });
|
|
249
|
+
};
|
|
250
|
+
var MobileNavLink = ({ href, children, className, selectedKey }) => {
|
|
251
|
+
const combinedClassName = `${className || "text-lg font-medium text-center text-gray-600 hover:text-purple-600 transition-colors"} ${getActivedCls(href, selectedKey)}`;
|
|
252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_link.default, { href, legacyBehavior: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { className: combinedClassName, children }) });
|
|
253
|
+
};
|
|
254
|
+
var Header_default = Header;
|
|
255
|
+
|
|
256
|
+
// src/layout/Footer/index.tsx
|
|
257
|
+
var import_link2 = __toESM(require("next/link"));
|
|
258
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
259
|
+
var Footer = ({
|
|
260
|
+
site,
|
|
261
|
+
navigation,
|
|
262
|
+
texts,
|
|
263
|
+
className = ""
|
|
264
|
+
}) => {
|
|
265
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("footer", { className: `relative bg-gradient-to-b from-gray-50 to-gray-100 pt-16 pb-6 ${className}`, children: [
|
|
266
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "absolute inset-0 bg-grid-gray-200/25 [mask-image:linear-gradient(0deg,white,rgba(255,255,255,0.6))]" }),
|
|
267
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "container mx-auto p-4 relative", children: [
|
|
268
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-8 mb-12", children: [
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-4", children: [
|
|
270
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { className: "text-xl font-bold bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent", children: site.name }),
|
|
271
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-gray-600 max-w-xs", children: site.description })
|
|
272
|
+
] }),
|
|
273
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-4", children: [
|
|
274
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h4", { className: "text-sm font-semibold text-gray-900 uppercase", children: navigation.quickLinks.title }),
|
|
275
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("nav", { className: "flex flex-col space-y-2", children: navigation.quickLinks.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
276
|
+
import_link2.default,
|
|
277
|
+
{
|
|
278
|
+
href: item.href,
|
|
279
|
+
className: "text-gray-600 hover:text-purple-600 transition-colors",
|
|
280
|
+
children: item.title
|
|
281
|
+
},
|
|
282
|
+
item.href
|
|
283
|
+
)) })
|
|
284
|
+
] }),
|
|
285
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-4", children: [
|
|
286
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h4", { className: "text-sm font-semibold text-gray-900 uppercase", children: texts.social }),
|
|
287
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex space-x-4", children: navigation.socialLinks.map((link) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
288
|
+
"a",
|
|
289
|
+
{
|
|
290
|
+
href: link.href,
|
|
291
|
+
className: "text-gray-600 hover:text-purple-600 transition-colors",
|
|
292
|
+
target: "_blank",
|
|
293
|
+
rel: "noopener noreferrer",
|
|
294
|
+
children: link.title
|
|
295
|
+
},
|
|
296
|
+
link.href
|
|
297
|
+
)) })
|
|
298
|
+
] })
|
|
299
|
+
] }),
|
|
300
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "border-t border-gray-200 pt-6", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0", children: [
|
|
301
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-sm text-gray-600", children: texts.copyright }),
|
|
302
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex space-x-6", children: [
|
|
303
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_link2.default, { href: "/privacy", className: "text-sm text-gray-600 hover:text-purple-600 transition-colors", children: texts.privacy }),
|
|
304
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_link2.default, { href: "/terms", className: "text-sm text-gray-600 hover:text-purple-600 transition-colors", children: texts.terms })
|
|
305
|
+
] })
|
|
306
|
+
] }) })
|
|
307
|
+
] }),
|
|
308
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-purple-600 via-pink-500 to-purple-600" })
|
|
309
|
+
] });
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
// src/hooks/useForceRerender.ts
|
|
313
|
+
var import_react2 = require("react");
|
|
314
|
+
var useForceRerender = () => {
|
|
315
|
+
const [key, setKey] = (0, import_react2.useState)(0);
|
|
316
|
+
const forceRerender = (0, import_react2.useCallback)(() => {
|
|
317
|
+
setKey((prevKey) => prevKey + 1);
|
|
318
|
+
}, []);
|
|
319
|
+
return [key, forceRerender];
|
|
320
|
+
};
|
|
321
|
+
var useForceRerender_default = useForceRerender;
|
|
322
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
323
|
+
0 && (module.exports = {
|
|
324
|
+
Button,
|
|
325
|
+
CardTitle,
|
|
326
|
+
Footer,
|
|
327
|
+
Header,
|
|
328
|
+
PageTitle,
|
|
329
|
+
SectionTitle,
|
|
330
|
+
SubTitle,
|
|
331
|
+
useForceRerender
|
|
332
|
+
});
|
|
333
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/components/Button/index.tsx","../src/components/Heading/index.tsx","../src/layout/Header/index.tsx","../src/layout/Header/BreadIcon.tsx","../src/layout/Footer/index.tsx","../src/hooks/useForceRerender.ts"],"sourcesContent":["export * from './components'\nexport * from './layout'\nexport { default as useForceRerender } from './hooks/useForceRerender'\n// export * from './hooks'\n// export * from './layout'\n// export * from './theme'\n// export * from './i18n'","import React from 'react';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'primary' | 'secondary' | 'outline';\n size?: 'sm' | 'md' | 'lg';\n}\n\nexport const Button: React.FC<ButtonProps> = ({\n variant = 'primary',\n size = 'md',\n className = '',\n children,\n ...props\n}) => {\n const baseStyles = 'rounded-full font-medium transition-colors';\n \n const variants = {\n primary: 'bg-purple-600 text-white hover:bg-purple-700 shadow-lg shadow-purple-500/20',\n secondary: 'bg-purple-50 text-purple-700 hover:bg-purple-100',\n outline: 'border-2 border-purple-600 text-purple-600 hover:bg-purple-50'\n };\n\n const sizes = {\n sm: 'px-4 py-1.5 text-sm',\n md: 'px-6 py-2 text-sm',\n lg: 'px-8 py-3 text-base'\n };\n\n const classes = `${baseStyles} ${variants[variant]} ${sizes[size]} ${className}`;\n\n return (\n <button className={classes} {...props}>\n {children}\n </button>\n );\n}; \n\nexport default Button;","'use client';\n\nimport { motion } from 'framer-motion';\nimport { ReactNode } from 'react';\n\nexport interface HeadingProps {\n children?: ReactNode;\n className?: string;\n title?: string;\n}\n\n// 頁面主標題:大標題,帶漸變色\nexport function PageTitle({ children, title, className = '' }: HeadingProps) {\n return (\n <motion.h1\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.8 }}\n className={`text-4xl md:text-5xl font-bold mb-6 bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent ${className}`}\n >\n {title || children}\n </motion.h1>\n );\n}\n\n// 區塊標題:中等大小,帶漸變色\nexport function SectionTitle({ children, title, className = '' }: HeadingProps) {\n return (\n <motion.h2\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.8, delay: 0.2 }}\n className={`text-3xl font-bold text-center mb-16 bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent ${className}`}\n >\n {title || children}\n </motion.h2>\n );\n}\n\n// 卡片標題:較小,深灰色\nexport function CardTitle({ children, title,className = '' }: HeadingProps) {\n return (\n <motion.h3\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.5 }}\n className={`text-2xl font-bold text-gray-800 ${className}`}\n >\n {title || children}\n </motion.h3>\n );\n}\n\n// 區塊子標題:最小,帶圖標位置\nexport function SubTitle({ children, title, className = '' }: HeadingProps) {\n return (\n <motion.h4\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.5 }}\n className={`text-lg font-semibold text-gray-800 ${className}`}\n >\n {title || children}\n </motion.h4>\n );\n} \n\nexport default {\n PageTitle,\n SectionTitle,\n CardTitle,\n SubTitle,\n}","'use client';\nimport React, { useState } from 'react';\nimport Link from 'next/link';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport BreadIcon from './BreadIcon';\nimport { usePathname } from 'next/navigation';\nexport interface NavItem {\n key: string;\n href: string;\n label: string;\n className?: {\n pc?: string;\n mobile?: string;\n };\n}\n\nexport interface HeaderProps {\n logo: React.ReactNode;\n menuItems: NavItem[];\n className?: string;\n /** 是否啟用動畫效果 */\n enableAnimation?: boolean;\n}\nconst getActivedCls = (href: string, selectedKey: string) => {\n if(href.includes(selectedKey) || (href === '/' && selectedKey === 'home')) {\n return 'text-purple-600';\n }\n return 'text-gray-600';\n}\nexport const Header: React.FC<HeaderProps> = ({\n logo,\n menuItems,\n className = '',\n enableAnimation = true,\n}) => {\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n const selectedKey = usePathname().split('/')[2] || 'home'; // todo support home\n console.log('selectedKey>>>',selectedKey);\n // 基礎樣式\n const baseNavClassName = `fixed top-0 left-0 right-0 z-50 bg-white/80 backdrop-blur-lg border-b border-purple-100 ${className}`;\n // 動畫配置\n const navVariants = {\n hidden: { y: -20, opacity: 0 },\n visible: { \n y: 0, \n opacity: 1,\n transition: {\n duration: 0.5,\n ease: \"easeOut\"\n }\n }\n };\n\n const mobileMenuVariants = {\n hidden: { \n height: 0,\n opacity: 0,\n transition: {\n duration: 0.3,\n ease: \"easeInOut\"\n }\n },\n visible: { \n height: \"auto\",\n opacity: 1,\n transition: {\n duration: 0.3,\n ease: \"easeInOut\"\n }\n }\n };\n\n // 根據是否啟用動畫返回不同的組件\n const NavComponent = enableAnimation ? motion.nav : 'nav';\n const MobileMenuComponent = enableAnimation ? motion.div : 'div';\nconsole.log('menuItems>>>',menuItems);\n return (\n <NavComponent \n className={baseNavClassName}\n {...(enableAnimation && {\n initial: \"hidden\",\n animate: \"visible\",\n variants: navVariants\n })}\n >\n <div className=\"container mx-auto px-4\">\n <div className=\"flex items-center justify-between h-20\">\n {/* Logo */}\n {logo}\n\n {/* Desktop Navigation */}\n <nav className=\"hidden md:flex items-center space-x-8\">\n {menuItems.map((item) => (\n // <Link\n // key={item.key}\n // href=\"/\"\n // className=\"flex items-center justify-center gap-2 text-lg font-bold tracking-wide transition-all duration-300 ease-in-out\"\n // >\n // {item.label}\n // </Link>\n <NavLink key={item.key} href={item.href} className={item.className?.pc} selectedKey={selectedKey}>\n {item.label}\n </NavLink>\n ))}\n </nav>\n\n {/* Mobile Menu Button */}\n <button \n onClick={() => setIsMenuOpen(!isMenuOpen)}\n className=\"md:hidden p-2 hover:bg-purple-50 rounded-lg transition-colors\"\n >\n <BreadIcon isMenuOpen={isMenuOpen}/>\n </button>\n </div>\n\n {/* Mobile Menu */}\n <AnimatePresence>\n {isMenuOpen && (\n <MobileMenuComponent\n className=\"md:hidden overflow-hidden\"\n {...(enableAnimation && {\n initial: \"hidden\",\n animate: \"visible\",\n exit: \"hidden\",\n variants: mobileMenuVariants\n })}\n >\n <div className=\"flex flex-col space-y-4 py-4 items-center\">\n {menuItems.map((item) => (\n <motion.div\n key={item.key}\n {...(enableAnimation && {\n initial: { x: -20, opacity: 0 },\n animate: { x: 0, opacity: 1 },\n transition: { delay: 0.1 }\n })}\n >\n {\n menuItems.map((item) => (\n <MobileNavLink key={item.key} href={item.href} className={item.className?.mobile} selectedKey={selectedKey}>{item.label}</MobileNavLink>\n ))\n }\n </motion.div>\n ))}\n </div>\n </MobileMenuComponent>\n )}\n </AnimatePresence>\n </div>\n </NavComponent>\n );\n}; \n\n\nconst NavLink = ({ href, children, className, selectedKey }: { href: string; children: React.ReactNode, className?: string, selectedKey: string }) => {\n const combinedClassName = `${className || 'text-gray-600 hover:text-black transition-colors'} ${getActivedCls(href, selectedKey)}`;\n return (\n <Link href={href} legacyBehavior>\n <a className={combinedClassName}>{children}</a>\n </Link>\n );\n};\n\nconst MobileNavLink = ({ href, children, className, selectedKey }: { href: string; children: React.ReactNode, className?: string, selectedKey: string }) => {\n const combinedClassName = `${className || 'text-lg font-medium text-center text-gray-600 hover:text-purple-600 transition-colors'} ${getActivedCls(href, selectedKey)}`;\n return (\n <Link href={href} legacyBehavior>\n <a className={combinedClassName}>{children}</a>\n </Link>\n );\n};\n\nexport default Header;","export default function BreadIcon({isMenuOpen}: {isMenuOpen: boolean}) {\n return (\n <div className=\"w-6 h-5 relative flex flex-col justify-between\">\n <span className={`w-full h-0.5 bg-gray-800 transition-transform duration-300 ${isMenuOpen ? 'rotate-45 translate-y-2' : ''}`} />\n <span className={`w-full h-0.5 bg-gray-800 transition-opacity duration-300 ${isMenuOpen ? 'opacity-0' : ''}`} />\n <span className={`w-full h-0.5 bg-gray-800 transition-transform duration-300 ${isMenuOpen ? '-rotate-45 -translate-y-2' : ''}`} />\n </div>\n )\n}","'use client';\nimport React from 'react';\nimport Link from 'next/link';\n\nexport interface FooterLink {\n href: string;\n title: string;\n}\n\nexport interface FooterTexts {\n copyright: string;\n privacy: string;\n terms: string;\n social: string;\n}\n\nexport interface FooterProps {\n /** 網站基本信息 */\n site: {\n name: string;\n description: string;\n };\n /** 導航鏈接 */\n navigation: {\n /** 快速鏈接區塊 */\n quickLinks: {\n title: string;\n items: FooterLink[];\n };\n /** 社交媒體鏈接 */\n socialLinks: FooterLink[];\n };\n /** 頁腳文本 */\n texts: FooterTexts;\n /** 自定義類名 */\n className?: string;\n}\n\nexport const Footer: React.FC<FooterProps> = ({\n site,\n navigation,\n texts,\n className = '',\n}) => {\n return (\n <footer className={`relative bg-gradient-to-b from-gray-50 to-gray-100 pt-16 pb-6 ${className}`}>\n <div className=\"absolute inset-0 bg-grid-gray-200/25 [mask-image:linear-gradient(0deg,white,rgba(255,255,255,0.6))]\" />\n \n <div className=\"container mx-auto p-4 relative\">\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-8 mb-12\">\n {/* Brand Section */}\n <div className=\"space-y-4\">\n <h3 className=\"text-xl font-bold bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent\">\n {site.name}\n </h3>\n <p className=\"text-gray-600 max-w-xs\">\n {site.description}\n </p>\n </div>\n\n {/* Quick Links */}\n <div className=\"space-y-4\">\n <h4 className=\"text-sm font-semibold text-gray-900 uppercase\">\n {navigation.quickLinks.title}\n </h4>\n <nav className=\"flex flex-col space-y-2\">\n {navigation.quickLinks.items.map((item) => (\n <Link\n key={item.href}\n href={item.href}\n className=\"text-gray-600 hover:text-purple-600 transition-colors\"\n >\n {item.title}\n </Link>\n ))}\n </nav>\n </div>\n\n {/* Social Links */}\n <div className=\"space-y-4\">\n <h4 className=\"text-sm font-semibold text-gray-900 uppercase\">\n {texts.social}\n </h4>\n <div className=\"flex space-x-4\">\n {navigation.socialLinks.map((link) => (\n <a\n key={link.href}\n href={link.href}\n className=\"text-gray-600 hover:text-purple-600 transition-colors\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {link.title}\n </a>\n ))}\n </div>\n </div>\n </div>\n\n {/* Bottom Bar */}\n <div className=\"border-t border-gray-200 pt-6\">\n <div className=\"flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0\">\n <p className=\"text-sm text-gray-600\">\n {texts.copyright}\n </p>\n <div className=\"flex space-x-6\">\n <Link href=\"/privacy\" className=\"text-sm text-gray-600 hover:text-purple-600 transition-colors\">\n {texts.privacy}\n </Link>\n <Link href=\"/terms\" className=\"text-sm text-gray-600 hover:text-purple-600 transition-colors\">\n {texts.terms}\n </Link>\n </div>\n </div>\n </div>\n </div>\n\n {/* Decorative gradient line */}\n <div className=\"absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-purple-600 via-pink-500 to-purple-600\" />\n </footer>\n );\n}; ","import { useState, useCallback } from 'react';\n\nconst useForceRerender = (): [number, () => void] => {\n const [key, setKey] = useState(0);\n\n const forceRerender = useCallback(() => {\n setKey(prevKey => prevKey + 1);\n }, []);\n\n return [key, forceRerender];\n};\n\nexport default useForceRerender;"],"mappings":"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","names":["import_jsx_runtime","import_framer_motion","import_jsx_runtime","import_jsx_runtime","item","Link","import_link","import_jsx_runtime","Link","import_react"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
// src/components/Button/index.tsx
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
var Button = ({
|
|
4
|
+
variant = "primary",
|
|
5
|
+
size = "md",
|
|
6
|
+
className = "",
|
|
7
|
+
children,
|
|
8
|
+
...props
|
|
9
|
+
}) => {
|
|
10
|
+
const baseStyles = "rounded-full font-medium transition-colors";
|
|
11
|
+
const variants = {
|
|
12
|
+
primary: "bg-purple-600 text-white hover:bg-purple-700 shadow-lg shadow-purple-500/20",
|
|
13
|
+
secondary: "bg-purple-50 text-purple-700 hover:bg-purple-100",
|
|
14
|
+
outline: "border-2 border-purple-600 text-purple-600 hover:bg-purple-50"
|
|
15
|
+
};
|
|
16
|
+
const sizes = {
|
|
17
|
+
sm: "px-4 py-1.5 text-sm",
|
|
18
|
+
md: "px-6 py-2 text-sm",
|
|
19
|
+
lg: "px-8 py-3 text-base"
|
|
20
|
+
};
|
|
21
|
+
const classes = `${baseStyles} ${variants[variant]} ${sizes[size]} ${className}`;
|
|
22
|
+
return /* @__PURE__ */ jsx("button", { className: classes, ...props, children });
|
|
23
|
+
};
|
|
24
|
+
var Button_default = Button;
|
|
25
|
+
|
|
26
|
+
// src/components/Heading/index.tsx
|
|
27
|
+
import { motion } from "framer-motion";
|
|
28
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
29
|
+
function PageTitle({ children, title, className = "" }) {
|
|
30
|
+
return /* @__PURE__ */ jsx2(
|
|
31
|
+
motion.h1,
|
|
32
|
+
{
|
|
33
|
+
initial: { opacity: 0, y: 20 },
|
|
34
|
+
animate: { opacity: 1, y: 0 },
|
|
35
|
+
transition: { duration: 0.8 },
|
|
36
|
+
className: `text-4xl md:text-5xl font-bold mb-6 bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent ${className}`,
|
|
37
|
+
children: title || children
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
function SectionTitle({ children, title, className = "" }) {
|
|
42
|
+
return /* @__PURE__ */ jsx2(
|
|
43
|
+
motion.h2,
|
|
44
|
+
{
|
|
45
|
+
initial: { opacity: 0, y: 20 },
|
|
46
|
+
animate: { opacity: 1, y: 0 },
|
|
47
|
+
transition: { duration: 0.8, delay: 0.2 },
|
|
48
|
+
className: `text-3xl font-bold text-center mb-16 bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent ${className}`,
|
|
49
|
+
children: title || children
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
function CardTitle({ children, title, className = "" }) {
|
|
54
|
+
return /* @__PURE__ */ jsx2(
|
|
55
|
+
motion.h3,
|
|
56
|
+
{
|
|
57
|
+
initial: { opacity: 0 },
|
|
58
|
+
animate: { opacity: 1 },
|
|
59
|
+
transition: { duration: 0.5 },
|
|
60
|
+
className: `text-2xl font-bold text-gray-800 ${className}`,
|
|
61
|
+
children: title || children
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
function SubTitle({ children, title, className = "" }) {
|
|
66
|
+
return /* @__PURE__ */ jsx2(
|
|
67
|
+
motion.h4,
|
|
68
|
+
{
|
|
69
|
+
initial: { opacity: 0 },
|
|
70
|
+
animate: { opacity: 1 },
|
|
71
|
+
transition: { duration: 0.5 },
|
|
72
|
+
className: `text-lg font-semibold text-gray-800 ${className}`,
|
|
73
|
+
children: title || children
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/layout/Header/index.tsx
|
|
79
|
+
import { useState } from "react";
|
|
80
|
+
import Link from "next/link";
|
|
81
|
+
import { motion as motion2, AnimatePresence } from "framer-motion";
|
|
82
|
+
|
|
83
|
+
// src/layout/Header/BreadIcon.tsx
|
|
84
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
85
|
+
function BreadIcon({ isMenuOpen }) {
|
|
86
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-6 h-5 relative flex flex-col justify-between", children: [
|
|
87
|
+
/* @__PURE__ */ jsx3("span", { className: `w-full h-0.5 bg-gray-800 transition-transform duration-300 ${isMenuOpen ? "rotate-45 translate-y-2" : ""}` }),
|
|
88
|
+
/* @__PURE__ */ jsx3("span", { className: `w-full h-0.5 bg-gray-800 transition-opacity duration-300 ${isMenuOpen ? "opacity-0" : ""}` }),
|
|
89
|
+
/* @__PURE__ */ jsx3("span", { className: `w-full h-0.5 bg-gray-800 transition-transform duration-300 ${isMenuOpen ? "-rotate-45 -translate-y-2" : ""}` })
|
|
90
|
+
] });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/layout/Header/index.tsx
|
|
94
|
+
import { usePathname } from "next/navigation";
|
|
95
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
96
|
+
var getActivedCls = (href, selectedKey) => {
|
|
97
|
+
if (href.includes(selectedKey) || href === "/" && selectedKey === "home") {
|
|
98
|
+
return "text-purple-600";
|
|
99
|
+
}
|
|
100
|
+
return "text-gray-600";
|
|
101
|
+
};
|
|
102
|
+
var Header = ({
|
|
103
|
+
logo,
|
|
104
|
+
menuItems,
|
|
105
|
+
className = "",
|
|
106
|
+
enableAnimation = true
|
|
107
|
+
}) => {
|
|
108
|
+
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
109
|
+
const selectedKey = usePathname().split("/")[2] || "home";
|
|
110
|
+
console.log("selectedKey>>>", selectedKey);
|
|
111
|
+
const baseNavClassName = `fixed top-0 left-0 right-0 z-50 bg-white/80 backdrop-blur-lg border-b border-purple-100 ${className}`;
|
|
112
|
+
const navVariants = {
|
|
113
|
+
hidden: { y: -20, opacity: 0 },
|
|
114
|
+
visible: {
|
|
115
|
+
y: 0,
|
|
116
|
+
opacity: 1,
|
|
117
|
+
transition: {
|
|
118
|
+
duration: 0.5,
|
|
119
|
+
ease: "easeOut"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const mobileMenuVariants = {
|
|
124
|
+
hidden: {
|
|
125
|
+
height: 0,
|
|
126
|
+
opacity: 0,
|
|
127
|
+
transition: {
|
|
128
|
+
duration: 0.3,
|
|
129
|
+
ease: "easeInOut"
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
visible: {
|
|
133
|
+
height: "auto",
|
|
134
|
+
opacity: 1,
|
|
135
|
+
transition: {
|
|
136
|
+
duration: 0.3,
|
|
137
|
+
ease: "easeInOut"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const NavComponent = enableAnimation ? motion2.nav : "nav";
|
|
142
|
+
const MobileMenuComponent = enableAnimation ? motion2.div : "div";
|
|
143
|
+
console.log("menuItems>>>", menuItems);
|
|
144
|
+
return /* @__PURE__ */ jsx4(
|
|
145
|
+
NavComponent,
|
|
146
|
+
{
|
|
147
|
+
className: baseNavClassName,
|
|
148
|
+
...enableAnimation && {
|
|
149
|
+
initial: "hidden",
|
|
150
|
+
animate: "visible",
|
|
151
|
+
variants: navVariants
|
|
152
|
+
},
|
|
153
|
+
children: /* @__PURE__ */ jsxs2("div", { className: "container mx-auto px-4", children: [
|
|
154
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between h-20", children: [
|
|
155
|
+
logo,
|
|
156
|
+
/* @__PURE__ */ jsx4("nav", { className: "hidden md:flex items-center space-x-8", children: menuItems.map((item) => (
|
|
157
|
+
// <Link
|
|
158
|
+
// key={item.key}
|
|
159
|
+
// href="/"
|
|
160
|
+
// className="flex items-center justify-center gap-2 text-lg font-bold tracking-wide transition-all duration-300 ease-in-out"
|
|
161
|
+
// >
|
|
162
|
+
// {item.label}
|
|
163
|
+
// </Link>
|
|
164
|
+
/* @__PURE__ */ jsx4(NavLink, { href: item.href, className: item.className?.pc, selectedKey, children: item.label }, item.key)
|
|
165
|
+
)) }),
|
|
166
|
+
/* @__PURE__ */ jsx4(
|
|
167
|
+
"button",
|
|
168
|
+
{
|
|
169
|
+
onClick: () => setIsMenuOpen(!isMenuOpen),
|
|
170
|
+
className: "md:hidden p-2 hover:bg-purple-50 rounded-lg transition-colors",
|
|
171
|
+
children: /* @__PURE__ */ jsx4(BreadIcon, { isMenuOpen })
|
|
172
|
+
}
|
|
173
|
+
)
|
|
174
|
+
] }),
|
|
175
|
+
/* @__PURE__ */ jsx4(AnimatePresence, { children: isMenuOpen && /* @__PURE__ */ jsx4(
|
|
176
|
+
MobileMenuComponent,
|
|
177
|
+
{
|
|
178
|
+
className: "md:hidden overflow-hidden",
|
|
179
|
+
...enableAnimation && {
|
|
180
|
+
initial: "hidden",
|
|
181
|
+
animate: "visible",
|
|
182
|
+
exit: "hidden",
|
|
183
|
+
variants: mobileMenuVariants
|
|
184
|
+
},
|
|
185
|
+
children: /* @__PURE__ */ jsx4("div", { className: "flex flex-col space-y-4 py-4 items-center", children: menuItems.map((item) => /* @__PURE__ */ jsx4(
|
|
186
|
+
motion2.div,
|
|
187
|
+
{
|
|
188
|
+
...enableAnimation && {
|
|
189
|
+
initial: { x: -20, opacity: 0 },
|
|
190
|
+
animate: { x: 0, opacity: 1 },
|
|
191
|
+
transition: { delay: 0.1 }
|
|
192
|
+
},
|
|
193
|
+
children: menuItems.map((item2) => /* @__PURE__ */ jsx4(MobileNavLink, { href: item2.href, className: item2.className?.mobile, selectedKey, children: item2.label }, item2.key))
|
|
194
|
+
},
|
|
195
|
+
item.key
|
|
196
|
+
)) })
|
|
197
|
+
}
|
|
198
|
+
) })
|
|
199
|
+
] })
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
};
|
|
203
|
+
var NavLink = ({ href, children, className, selectedKey }) => {
|
|
204
|
+
const combinedClassName = `${className || "text-gray-600 hover:text-black transition-colors"} ${getActivedCls(href, selectedKey)}`;
|
|
205
|
+
return /* @__PURE__ */ jsx4(Link, { href, legacyBehavior: true, children: /* @__PURE__ */ jsx4("a", { className: combinedClassName, children }) });
|
|
206
|
+
};
|
|
207
|
+
var MobileNavLink = ({ href, children, className, selectedKey }) => {
|
|
208
|
+
const combinedClassName = `${className || "text-lg font-medium text-center text-gray-600 hover:text-purple-600 transition-colors"} ${getActivedCls(href, selectedKey)}`;
|
|
209
|
+
return /* @__PURE__ */ jsx4(Link, { href, legacyBehavior: true, children: /* @__PURE__ */ jsx4("a", { className: combinedClassName, children }) });
|
|
210
|
+
};
|
|
211
|
+
var Header_default = Header;
|
|
212
|
+
|
|
213
|
+
// src/layout/Footer/index.tsx
|
|
214
|
+
import Link2 from "next/link";
|
|
215
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
216
|
+
var Footer = ({
|
|
217
|
+
site,
|
|
218
|
+
navigation,
|
|
219
|
+
texts,
|
|
220
|
+
className = ""
|
|
221
|
+
}) => {
|
|
222
|
+
return /* @__PURE__ */ jsxs3("footer", { className: `relative bg-gradient-to-b from-gray-50 to-gray-100 pt-16 pb-6 ${className}`, children: [
|
|
223
|
+
/* @__PURE__ */ jsx5("div", { className: "absolute inset-0 bg-grid-gray-200/25 [mask-image:linear-gradient(0deg,white,rgba(255,255,255,0.6))]" }),
|
|
224
|
+
/* @__PURE__ */ jsxs3("div", { className: "container mx-auto p-4 relative", children: [
|
|
225
|
+
/* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-8 mb-12", children: [
|
|
226
|
+
/* @__PURE__ */ jsxs3("div", { className: "space-y-4", children: [
|
|
227
|
+
/* @__PURE__ */ jsx5("h3", { className: "text-xl font-bold bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent", children: site.name }),
|
|
228
|
+
/* @__PURE__ */ jsx5("p", { className: "text-gray-600 max-w-xs", children: site.description })
|
|
229
|
+
] }),
|
|
230
|
+
/* @__PURE__ */ jsxs3("div", { className: "space-y-4", children: [
|
|
231
|
+
/* @__PURE__ */ jsx5("h4", { className: "text-sm font-semibold text-gray-900 uppercase", children: navigation.quickLinks.title }),
|
|
232
|
+
/* @__PURE__ */ jsx5("nav", { className: "flex flex-col space-y-2", children: navigation.quickLinks.items.map((item) => /* @__PURE__ */ jsx5(
|
|
233
|
+
Link2,
|
|
234
|
+
{
|
|
235
|
+
href: item.href,
|
|
236
|
+
className: "text-gray-600 hover:text-purple-600 transition-colors",
|
|
237
|
+
children: item.title
|
|
238
|
+
},
|
|
239
|
+
item.href
|
|
240
|
+
)) })
|
|
241
|
+
] }),
|
|
242
|
+
/* @__PURE__ */ jsxs3("div", { className: "space-y-4", children: [
|
|
243
|
+
/* @__PURE__ */ jsx5("h4", { className: "text-sm font-semibold text-gray-900 uppercase", children: texts.social }),
|
|
244
|
+
/* @__PURE__ */ jsx5("div", { className: "flex space-x-4", children: navigation.socialLinks.map((link) => /* @__PURE__ */ jsx5(
|
|
245
|
+
"a",
|
|
246
|
+
{
|
|
247
|
+
href: link.href,
|
|
248
|
+
className: "text-gray-600 hover:text-purple-600 transition-colors",
|
|
249
|
+
target: "_blank",
|
|
250
|
+
rel: "noopener noreferrer",
|
|
251
|
+
children: link.title
|
|
252
|
+
},
|
|
253
|
+
link.href
|
|
254
|
+
)) })
|
|
255
|
+
] })
|
|
256
|
+
] }),
|
|
257
|
+
/* @__PURE__ */ jsx5("div", { className: "border-t border-gray-200 pt-6", children: /* @__PURE__ */ jsxs3("div", { className: "flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0", children: [
|
|
258
|
+
/* @__PURE__ */ jsx5("p", { className: "text-sm text-gray-600", children: texts.copyright }),
|
|
259
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex space-x-6", children: [
|
|
260
|
+
/* @__PURE__ */ jsx5(Link2, { href: "/privacy", className: "text-sm text-gray-600 hover:text-purple-600 transition-colors", children: texts.privacy }),
|
|
261
|
+
/* @__PURE__ */ jsx5(Link2, { href: "/terms", className: "text-sm text-gray-600 hover:text-purple-600 transition-colors", children: texts.terms })
|
|
262
|
+
] })
|
|
263
|
+
] }) })
|
|
264
|
+
] }),
|
|
265
|
+
/* @__PURE__ */ jsx5("div", { className: "absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-purple-600 via-pink-500 to-purple-600" })
|
|
266
|
+
] });
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
// src/hooks/useForceRerender.ts
|
|
270
|
+
import { useState as useState2, useCallback } from "react";
|
|
271
|
+
var useForceRerender = () => {
|
|
272
|
+
const [key, setKey] = useState2(0);
|
|
273
|
+
const forceRerender = useCallback(() => {
|
|
274
|
+
setKey((prevKey) => prevKey + 1);
|
|
275
|
+
}, []);
|
|
276
|
+
return [key, forceRerender];
|
|
277
|
+
};
|
|
278
|
+
var useForceRerender_default = useForceRerender;
|
|
279
|
+
export {
|
|
280
|
+
Button_default as Button,
|
|
281
|
+
CardTitle,
|
|
282
|
+
Footer,
|
|
283
|
+
Header_default as Header,
|
|
284
|
+
PageTitle,
|
|
285
|
+
SectionTitle,
|
|
286
|
+
SubTitle,
|
|
287
|
+
useForceRerender_default as useForceRerender
|
|
288
|
+
};
|
|
289
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Button/index.tsx","../src/components/Heading/index.tsx","../src/layout/Header/index.tsx","../src/layout/Header/BreadIcon.tsx","../src/layout/Footer/index.tsx","../src/hooks/useForceRerender.ts"],"sourcesContent":["import React from 'react';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'primary' | 'secondary' | 'outline';\n size?: 'sm' | 'md' | 'lg';\n}\n\nexport const Button: React.FC<ButtonProps> = ({\n variant = 'primary',\n size = 'md',\n className = '',\n children,\n ...props\n}) => {\n const baseStyles = 'rounded-full font-medium transition-colors';\n \n const variants = {\n primary: 'bg-purple-600 text-white hover:bg-purple-700 shadow-lg shadow-purple-500/20',\n secondary: 'bg-purple-50 text-purple-700 hover:bg-purple-100',\n outline: 'border-2 border-purple-600 text-purple-600 hover:bg-purple-50'\n };\n\n const sizes = {\n sm: 'px-4 py-1.5 text-sm',\n md: 'px-6 py-2 text-sm',\n lg: 'px-8 py-3 text-base'\n };\n\n const classes = `${baseStyles} ${variants[variant]} ${sizes[size]} ${className}`;\n\n return (\n <button className={classes} {...props}>\n {children}\n </button>\n );\n}; \n\nexport default Button;","'use client';\n\nimport { motion } from 'framer-motion';\nimport { ReactNode } from 'react';\n\nexport interface HeadingProps {\n children?: ReactNode;\n className?: string;\n title?: string;\n}\n\n// 頁面主標題:大標題,帶漸變色\nexport function PageTitle({ children, title, className = '' }: HeadingProps) {\n return (\n <motion.h1\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.8 }}\n className={`text-4xl md:text-5xl font-bold mb-6 bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent ${className}`}\n >\n {title || children}\n </motion.h1>\n );\n}\n\n// 區塊標題:中等大小,帶漸變色\nexport function SectionTitle({ children, title, className = '' }: HeadingProps) {\n return (\n <motion.h2\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.8, delay: 0.2 }}\n className={`text-3xl font-bold text-center mb-16 bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent ${className}`}\n >\n {title || children}\n </motion.h2>\n );\n}\n\n// 卡片標題:較小,深灰色\nexport function CardTitle({ children, title,className = '' }: HeadingProps) {\n return (\n <motion.h3\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.5 }}\n className={`text-2xl font-bold text-gray-800 ${className}`}\n >\n {title || children}\n </motion.h3>\n );\n}\n\n// 區塊子標題:最小,帶圖標位置\nexport function SubTitle({ children, title, className = '' }: HeadingProps) {\n return (\n <motion.h4\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.5 }}\n className={`text-lg font-semibold text-gray-800 ${className}`}\n >\n {title || children}\n </motion.h4>\n );\n} \n\nexport default {\n PageTitle,\n SectionTitle,\n CardTitle,\n SubTitle,\n}","'use client';\nimport React, { useState } from 'react';\nimport Link from 'next/link';\nimport { motion, AnimatePresence } from 'framer-motion';\nimport BreadIcon from './BreadIcon';\nimport { usePathname } from 'next/navigation';\nexport interface NavItem {\n key: string;\n href: string;\n label: string;\n className?: {\n pc?: string;\n mobile?: string;\n };\n}\n\nexport interface HeaderProps {\n logo: React.ReactNode;\n menuItems: NavItem[];\n className?: string;\n /** 是否啟用動畫效果 */\n enableAnimation?: boolean;\n}\nconst getActivedCls = (href: string, selectedKey: string) => {\n if(href.includes(selectedKey) || (href === '/' && selectedKey === 'home')) {\n return 'text-purple-600';\n }\n return 'text-gray-600';\n}\nexport const Header: React.FC<HeaderProps> = ({\n logo,\n menuItems,\n className = '',\n enableAnimation = true,\n}) => {\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n const selectedKey = usePathname().split('/')[2] || 'home'; // todo support home\n console.log('selectedKey>>>',selectedKey);\n // 基礎樣式\n const baseNavClassName = `fixed top-0 left-0 right-0 z-50 bg-white/80 backdrop-blur-lg border-b border-purple-100 ${className}`;\n // 動畫配置\n const navVariants = {\n hidden: { y: -20, opacity: 0 },\n visible: { \n y: 0, \n opacity: 1,\n transition: {\n duration: 0.5,\n ease: \"easeOut\"\n }\n }\n };\n\n const mobileMenuVariants = {\n hidden: { \n height: 0,\n opacity: 0,\n transition: {\n duration: 0.3,\n ease: \"easeInOut\"\n }\n },\n visible: { \n height: \"auto\",\n opacity: 1,\n transition: {\n duration: 0.3,\n ease: \"easeInOut\"\n }\n }\n };\n\n // 根據是否啟用動畫返回不同的組件\n const NavComponent = enableAnimation ? motion.nav : 'nav';\n const MobileMenuComponent = enableAnimation ? motion.div : 'div';\nconsole.log('menuItems>>>',menuItems);\n return (\n <NavComponent \n className={baseNavClassName}\n {...(enableAnimation && {\n initial: \"hidden\",\n animate: \"visible\",\n variants: navVariants\n })}\n >\n <div className=\"container mx-auto px-4\">\n <div className=\"flex items-center justify-between h-20\">\n {/* Logo */}\n {logo}\n\n {/* Desktop Navigation */}\n <nav className=\"hidden md:flex items-center space-x-8\">\n {menuItems.map((item) => (\n // <Link\n // key={item.key}\n // href=\"/\"\n // className=\"flex items-center justify-center gap-2 text-lg font-bold tracking-wide transition-all duration-300 ease-in-out\"\n // >\n // {item.label}\n // </Link>\n <NavLink key={item.key} href={item.href} className={item.className?.pc} selectedKey={selectedKey}>\n {item.label}\n </NavLink>\n ))}\n </nav>\n\n {/* Mobile Menu Button */}\n <button \n onClick={() => setIsMenuOpen(!isMenuOpen)}\n className=\"md:hidden p-2 hover:bg-purple-50 rounded-lg transition-colors\"\n >\n <BreadIcon isMenuOpen={isMenuOpen}/>\n </button>\n </div>\n\n {/* Mobile Menu */}\n <AnimatePresence>\n {isMenuOpen && (\n <MobileMenuComponent\n className=\"md:hidden overflow-hidden\"\n {...(enableAnimation && {\n initial: \"hidden\",\n animate: \"visible\",\n exit: \"hidden\",\n variants: mobileMenuVariants\n })}\n >\n <div className=\"flex flex-col space-y-4 py-4 items-center\">\n {menuItems.map((item) => (\n <motion.div\n key={item.key}\n {...(enableAnimation && {\n initial: { x: -20, opacity: 0 },\n animate: { x: 0, opacity: 1 },\n transition: { delay: 0.1 }\n })}\n >\n {\n menuItems.map((item) => (\n <MobileNavLink key={item.key} href={item.href} className={item.className?.mobile} selectedKey={selectedKey}>{item.label}</MobileNavLink>\n ))\n }\n </motion.div>\n ))}\n </div>\n </MobileMenuComponent>\n )}\n </AnimatePresence>\n </div>\n </NavComponent>\n );\n}; \n\n\nconst NavLink = ({ href, children, className, selectedKey }: { href: string; children: React.ReactNode, className?: string, selectedKey: string }) => {\n const combinedClassName = `${className || 'text-gray-600 hover:text-black transition-colors'} ${getActivedCls(href, selectedKey)}`;\n return (\n <Link href={href} legacyBehavior>\n <a className={combinedClassName}>{children}</a>\n </Link>\n );\n};\n\nconst MobileNavLink = ({ href, children, className, selectedKey }: { href: string; children: React.ReactNode, className?: string, selectedKey: string }) => {\n const combinedClassName = `${className || 'text-lg font-medium text-center text-gray-600 hover:text-purple-600 transition-colors'} ${getActivedCls(href, selectedKey)}`;\n return (\n <Link href={href} legacyBehavior>\n <a className={combinedClassName}>{children}</a>\n </Link>\n );\n};\n\nexport default Header;","export default function BreadIcon({isMenuOpen}: {isMenuOpen: boolean}) {\n return (\n <div className=\"w-6 h-5 relative flex flex-col justify-between\">\n <span className={`w-full h-0.5 bg-gray-800 transition-transform duration-300 ${isMenuOpen ? 'rotate-45 translate-y-2' : ''}`} />\n <span className={`w-full h-0.5 bg-gray-800 transition-opacity duration-300 ${isMenuOpen ? 'opacity-0' : ''}`} />\n <span className={`w-full h-0.5 bg-gray-800 transition-transform duration-300 ${isMenuOpen ? '-rotate-45 -translate-y-2' : ''}`} />\n </div>\n )\n}","'use client';\nimport React from 'react';\nimport Link from 'next/link';\n\nexport interface FooterLink {\n href: string;\n title: string;\n}\n\nexport interface FooterTexts {\n copyright: string;\n privacy: string;\n terms: string;\n social: string;\n}\n\nexport interface FooterProps {\n /** 網站基本信息 */\n site: {\n name: string;\n description: string;\n };\n /** 導航鏈接 */\n navigation: {\n /** 快速鏈接區塊 */\n quickLinks: {\n title: string;\n items: FooterLink[];\n };\n /** 社交媒體鏈接 */\n socialLinks: FooterLink[];\n };\n /** 頁腳文本 */\n texts: FooterTexts;\n /** 自定義類名 */\n className?: string;\n}\n\nexport const Footer: React.FC<FooterProps> = ({\n site,\n navigation,\n texts,\n className = '',\n}) => {\n return (\n <footer className={`relative bg-gradient-to-b from-gray-50 to-gray-100 pt-16 pb-6 ${className}`}>\n <div className=\"absolute inset-0 bg-grid-gray-200/25 [mask-image:linear-gradient(0deg,white,rgba(255,255,255,0.6))]\" />\n \n <div className=\"container mx-auto p-4 relative\">\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-8 mb-12\">\n {/* Brand Section */}\n <div className=\"space-y-4\">\n <h3 className=\"text-xl font-bold bg-gradient-to-r from-purple-600 to-pink-500 bg-clip-text text-transparent\">\n {site.name}\n </h3>\n <p className=\"text-gray-600 max-w-xs\">\n {site.description}\n </p>\n </div>\n\n {/* Quick Links */}\n <div className=\"space-y-4\">\n <h4 className=\"text-sm font-semibold text-gray-900 uppercase\">\n {navigation.quickLinks.title}\n </h4>\n <nav className=\"flex flex-col space-y-2\">\n {navigation.quickLinks.items.map((item) => (\n <Link\n key={item.href}\n href={item.href}\n className=\"text-gray-600 hover:text-purple-600 transition-colors\"\n >\n {item.title}\n </Link>\n ))}\n </nav>\n </div>\n\n {/* Social Links */}\n <div className=\"space-y-4\">\n <h4 className=\"text-sm font-semibold text-gray-900 uppercase\">\n {texts.social}\n </h4>\n <div className=\"flex space-x-4\">\n {navigation.socialLinks.map((link) => (\n <a\n key={link.href}\n href={link.href}\n className=\"text-gray-600 hover:text-purple-600 transition-colors\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {link.title}\n </a>\n ))}\n </div>\n </div>\n </div>\n\n {/* Bottom Bar */}\n <div className=\"border-t border-gray-200 pt-6\">\n <div className=\"flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0\">\n <p className=\"text-sm text-gray-600\">\n {texts.copyright}\n </p>\n <div className=\"flex space-x-6\">\n <Link href=\"/privacy\" className=\"text-sm text-gray-600 hover:text-purple-600 transition-colors\">\n {texts.privacy}\n </Link>\n <Link href=\"/terms\" className=\"text-sm text-gray-600 hover:text-purple-600 transition-colors\">\n {texts.terms}\n </Link>\n </div>\n </div>\n </div>\n </div>\n\n {/* Decorative gradient line */}\n <div className=\"absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-purple-600 via-pink-500 to-purple-600\" />\n </footer>\n );\n}; ","import { useState, useCallback } from 'react';\n\nconst useForceRerender = (): [number, () => void] => {\n const [key, setKey] = useState(0);\n\n const forceRerender = useCallback(() => {\n setKey(prevKey => prevKey + 1);\n }, []);\n\n return [key, forceRerender];\n};\n\nexport default useForceRerender;"],"mappings":"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","names":["jsx","motion","jsx","jsx","jsxs","motion","item","Link","jsx","jsxs","useState"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jean-react-utils",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Jean's personal reusable components, hooks, theme and i18n utils for Next.js projects",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"require": "./dist/index.cjs",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"dev": "tsup src/index.ts --format esm,cjs --watch --dts --external react",
|
|
22
|
+
"build": "tsup src/index.ts",
|
|
23
|
+
"test": "vitest",
|
|
24
|
+
"lint": "eslint . --ext .ts,.tsx",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
|
|
27
|
+
"test:watch": "vitest",
|
|
28
|
+
"test:coverage": "vitest run --coverage"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"classnames": "^2.5.1"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@testing-library/react": "^14.3.1",
|
|
35
|
+
"@testing-library/user-event": "^14.5.2",
|
|
36
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
37
|
+
"@vitest/coverage-v8": "^1.6.1",
|
|
38
|
+
"autoprefixer": "^10.4.21",
|
|
39
|
+
"happy-dom": "^13.3.8",
|
|
40
|
+
"postcss": "^8.5.4",
|
|
41
|
+
"tailwindcss": "^4.1.8",
|
|
42
|
+
"tsup": "^8.0.2",
|
|
43
|
+
"vitest": "^1.6.1"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@emotion/is-prop-valid": "^1.2.1",
|
|
47
|
+
"framer-motion": "^12.1.6",
|
|
48
|
+
"next": "^14.0.0",
|
|
49
|
+
"react": "^18.2.0",
|
|
50
|
+
"react-dom": "^18.2.0"
|
|
51
|
+
},
|
|
52
|
+
"author": "jean-w",
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "https://github.com/Jean-W-FE/jean-react-utils.git"
|
|
56
|
+
},
|
|
57
|
+
"keywords": [
|
|
58
|
+
"jean-react-utils",
|
|
59
|
+
"jean-dev",
|
|
60
|
+
"jean-blog-site"
|
|
61
|
+
],
|
|
62
|
+
"publishConfig": {
|
|
63
|
+
"access": "public"
|
|
64
|
+
},
|
|
65
|
+
"license": "MIT"
|
|
66
|
+
}
|