ui-library-spj 1.0.2 → 1.0.5
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/components/buttons/ActionButton.jsx +40 -0
- package/components/buttons/BasicButton.jsx +40 -10
- package/components/buttons/ConfirmButton.jsx +35 -0
- package/components/buttons/IconActionButton.jsx +14 -0
- package/components/buttons/LinkButton.jsx +17 -0
- package/components/buttons/SubmitButton.jsx +22 -0
- package/components/carousel/BasicCarousel.jsx +89 -0
- package/index.js +12 -4
- package/package.json +19 -19
- package/postcss.config.mjs +4 -4
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
export function ActionButton({
|
|
4
|
+
children,
|
|
5
|
+
onAction,
|
|
6
|
+
onError,
|
|
7
|
+
disabled = false,
|
|
8
|
+
className = "",
|
|
9
|
+
...props
|
|
10
|
+
}) {
|
|
11
|
+
const [loading, setLoading] = useState(false);
|
|
12
|
+
|
|
13
|
+
async function handleClick() {
|
|
14
|
+
if (!onAction || loading || disabled) return;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
setLoading(true);
|
|
18
|
+
await onAction();
|
|
19
|
+
} catch (err) {
|
|
20
|
+
console.error(err);
|
|
21
|
+
onError && onError(err);
|
|
22
|
+
} finally {
|
|
23
|
+
setLoading(false);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<button
|
|
29
|
+
onClick={handleClick}
|
|
30
|
+
disabled={disabled || loading}
|
|
31
|
+
className={`px-4 py-2 rounded-md bg-indigo-600 text-white font-medium
|
|
32
|
+
hover:bg-indigo-700 transition
|
|
33
|
+
disabled:opacity-60 disabled:cursor-not-allowed
|
|
34
|
+
${className}`}
|
|
35
|
+
{...props}
|
|
36
|
+
>
|
|
37
|
+
{loading ? "Processing..." : children}
|
|
38
|
+
</button>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -1,10 +1,40 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
export function BasicButton({
|
|
4
|
+
children,
|
|
5
|
+
onAction,
|
|
6
|
+
onError,
|
|
7
|
+
disabled = false,
|
|
8
|
+
className = "",
|
|
9
|
+
...props
|
|
10
|
+
}) {
|
|
11
|
+
const [loading, setLoading] = useState(false);
|
|
12
|
+
|
|
13
|
+
async function handleClick(e) {
|
|
14
|
+
if (!onAction || loading || disabled) return;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
setLoading(true);
|
|
18
|
+
await onAction();
|
|
19
|
+
} catch (err) {
|
|
20
|
+
console.error("Button action failed:", err);
|
|
21
|
+
onError && onError(err);
|
|
22
|
+
} finally {
|
|
23
|
+
setLoading(false);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<button
|
|
29
|
+
onClick={handleClick}
|
|
30
|
+
disabled={disabled || loading}
|
|
31
|
+
className={`px-4 py-2 rounded-md bg-indigo-600 text-white font-medium
|
|
32
|
+
hover:bg-indigo-700 transition
|
|
33
|
+
disabled:opacity-60 disabled:cursor-not-allowed
|
|
34
|
+
${className}`}
|
|
35
|
+
{...props}
|
|
36
|
+
>
|
|
37
|
+
{loading ? "Processing..." : children}
|
|
38
|
+
</button>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
export function ConfirmButton({
|
|
4
|
+
children,
|
|
5
|
+
onConfirm,
|
|
6
|
+
message = "Are you sure?",
|
|
7
|
+
className = "",
|
|
8
|
+
...props
|
|
9
|
+
}) {
|
|
10
|
+
const [confirming, setConfirming] = useState(false);
|
|
11
|
+
|
|
12
|
+
async function handleClick() {
|
|
13
|
+
if (!confirming) {
|
|
14
|
+
setConfirming(true);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
setConfirming(false);
|
|
19
|
+
await onConfirm();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<button
|
|
24
|
+
type="button"
|
|
25
|
+
onClick={handleClick}
|
|
26
|
+
className={`px-4 py-2 rounded-md font-medium text-white
|
|
27
|
+
${confirming ? "bg-red-700" : "bg-red-600 hover:bg-red-700"}
|
|
28
|
+
transition
|
|
29
|
+
${className}`}
|
|
30
|
+
{...props}
|
|
31
|
+
>
|
|
32
|
+
{confirming ? message : children}
|
|
33
|
+
</button>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export function IconActionButton({ children, onAction, className = "" }) {
|
|
4
|
+
return (
|
|
5
|
+
<button
|
|
6
|
+
onClick={onAction}
|
|
7
|
+
className={`p-2 rounded-md hover:bg-gray-100 transition
|
|
8
|
+
focus:outline-none focus:ring-2 focus:ring-indigo-500
|
|
9
|
+
${className}`}
|
|
10
|
+
>
|
|
11
|
+
{children}
|
|
12
|
+
</button>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export function LinkButton({ children, onNavigate, className = "" }) {
|
|
4
|
+
function handleClick(e) {
|
|
5
|
+
e.preventDefault();
|
|
6
|
+
onNavigate && onNavigate();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<button
|
|
11
|
+
onClick={handleClick}
|
|
12
|
+
className={`text-indigo-600 hover:underline font-medium ${className}`}
|
|
13
|
+
>
|
|
14
|
+
{children}
|
|
15
|
+
</button>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export function SubmitButton({
|
|
4
|
+
children,
|
|
5
|
+
loading = false,
|
|
6
|
+
className = "",
|
|
7
|
+
...props
|
|
8
|
+
}) {
|
|
9
|
+
return (
|
|
10
|
+
<button
|
|
11
|
+
type="submit"
|
|
12
|
+
disabled={loading}
|
|
13
|
+
className={`px-4 py-2 rounded-md bg-green-600 text-white font-medium
|
|
14
|
+
hover:bg-green-700 transition
|
|
15
|
+
disabled:opacity-60 disabled:cursor-not-allowed
|
|
16
|
+
${className}`}
|
|
17
|
+
{...props}
|
|
18
|
+
>
|
|
19
|
+
{loading ? "Submitting..." : children}
|
|
20
|
+
</button>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import "../../index.css";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* BasicCarousel
|
|
6
|
+
*
|
|
7
|
+
* @param {React.ReactNode[]} items - slides content
|
|
8
|
+
* @param {string} className - override container styles
|
|
9
|
+
* @param {string} slideClassName - override slide styles
|
|
10
|
+
*/
|
|
11
|
+
export function BasicCarousel({
|
|
12
|
+
items = [],
|
|
13
|
+
className = "",
|
|
14
|
+
slideClassName = "",
|
|
15
|
+
}) {
|
|
16
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
17
|
+
const totalSlides = items.length;
|
|
18
|
+
|
|
19
|
+
const next = () =>
|
|
20
|
+
setCurrentIndex((prev) => (prev + 1) % totalSlides);
|
|
21
|
+
|
|
22
|
+
const prev = () =>
|
|
23
|
+
setCurrentIndex((prev) => (prev - 1 + totalSlides) % totalSlides);
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div
|
|
27
|
+
className={`
|
|
28
|
+
relative flex items-center justify-center overflow-hidden
|
|
29
|
+
w-full h-[60vh] sm:h-[70vh] md:h-[80vh]
|
|
30
|
+
bg-slate-900
|
|
31
|
+
${className}
|
|
32
|
+
`}
|
|
33
|
+
>
|
|
34
|
+
{/* Left button */}
|
|
35
|
+
<button
|
|
36
|
+
onClick={prev}
|
|
37
|
+
className="absolute left-2 sm:left-4 z-20
|
|
38
|
+
w-10 h-10 sm:w-12 sm:h-12
|
|
39
|
+
rounded-full bg-violet-500 text-white
|
|
40
|
+
flex items-center justify-center
|
|
41
|
+
hover:bg-white hover:text-black transition"
|
|
42
|
+
>
|
|
43
|
+
‹
|
|
44
|
+
</button>
|
|
45
|
+
|
|
46
|
+
{/* Slides container */}
|
|
47
|
+
<div className="relative w-full h-full flex items-center justify-center">
|
|
48
|
+
{items.map((item, index) => {
|
|
49
|
+
const offset = index - currentIndex;
|
|
50
|
+
const scale = Math.max(0.6, 1 - Math.abs(offset) * 0.15);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div
|
|
54
|
+
key={index}
|
|
55
|
+
className={`
|
|
56
|
+
absolute transition-all duration-300 ease-out
|
|
57
|
+
rounded-xl
|
|
58
|
+
w-[80%] sm:w-[65%] md:w-[55%]
|
|
59
|
+
h-[70%] sm:h-[75%] md:h-[80%]
|
|
60
|
+
${slideClassName}
|
|
61
|
+
`}
|
|
62
|
+
style={{
|
|
63
|
+
transform: `
|
|
64
|
+
translateX(${offset * 18}rem)
|
|
65
|
+
scale(${scale})
|
|
66
|
+
`,
|
|
67
|
+
zIndex: totalSlides - Math.abs(offset),
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
{item}
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
})}
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
{/* Right button */}
|
|
77
|
+
<button
|
|
78
|
+
onClick={next}
|
|
79
|
+
className="absolute right-2 sm:right-4 z-20
|
|
80
|
+
w-10 h-10 sm:w-12 sm:h-12
|
|
81
|
+
rounded-full bg-violet-500 text-white
|
|
82
|
+
flex items-center justify-center
|
|
83
|
+
hover:bg-white hover:text-black transition"
|
|
84
|
+
>
|
|
85
|
+
›
|
|
86
|
+
</button>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
}
|
package/index.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
// index.js
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export {BasicButton} from './components/buttons/BasicButton';
|
|
1
|
+
// index.js
|
|
2
|
+
|
|
3
|
+
// Button variants
|
|
4
|
+
export {BasicButton} from './components/buttons/BasicButton';
|
|
5
|
+
export { ActionButton } from "./components/buttons/ActionButton";
|
|
6
|
+
export { ConfirmButton } from "./components/buttons/ConfirmButton";
|
|
7
|
+
export { LinkButton } from "./components/buttons/LinkButton";
|
|
8
|
+
export {IconActionButton} from "./components/buttons/IconActionButton"
|
|
9
|
+
export { SubmitButton } from "./components/buttons/SubmitButton";
|
|
10
|
+
|
|
11
|
+
// Carousal
|
|
12
|
+
export {BasicCarousel} from './components/carousel/BasicCarousel'
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "ui-library-spj",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
-
},
|
|
9
|
-
"keywords": [],
|
|
10
|
-
"author": "",
|
|
11
|
-
"license": "ISC",
|
|
12
|
-
"type": "module",
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"@tailwindcss/postcss": "^4.1.18",
|
|
15
|
-
"postcss": "^8.5.6",
|
|
16
|
-
"react": "^19.2.3",
|
|
17
|
-
"tailwindcss": "^4.1.18"
|
|
18
|
-
}
|
|
19
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "ui-library-spj",
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@tailwindcss/postcss": "^4.1.18",
|
|
15
|
+
"postcss": "^8.5.6",
|
|
16
|
+
"react": "^19.2.3",
|
|
17
|
+
"tailwindcss": "^4.1.18"
|
|
18
|
+
}
|
|
19
|
+
}
|
package/postcss.config.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
plugins: {
|
|
3
|
-
"@tailwindcss/postcss": {},
|
|
4
|
-
}
|
|
1
|
+
export default {
|
|
2
|
+
plugins: {
|
|
3
|
+
"@tailwindcss/postcss": {},
|
|
4
|
+
}
|
|
5
5
|
}
|