xegavnj 0.1.8

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.
@@ -0,0 +1,388 @@
1
+ "use client";
2
+ import styled, { css } from "styled-components";
3
+ import React, { useState } from "react";
4
+ import { Copy, Check, Code as CodeIcon, Clock, ArrowRight, Heart } from "lucide-react";
5
+
6
+ // =============================================================================
7
+ // REUSABLE CARD COMPONENT
8
+ // =============================================================================
9
+
10
+ const CardWrapper = styled.div`
11
+ background: white;
12
+ border-radius: 12px;
13
+ overflow: hidden;
14
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
15
+ transition: all 0.3s ease;
16
+ border: 1px solid #e5e7eb;
17
+
18
+ &:hover {
19
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
20
+ transform: translateY(-2px);
21
+ }
22
+
23
+ /* Basic Variant */
24
+ ${props => props.$variant === 'basic' && css`
25
+ width: 300px;
26
+ padding: 1.5rem;
27
+ display: flex;
28
+ flex-direction: column;
29
+ gap: 1rem;
30
+ border-top: 4px solid #6366f1;
31
+ `}
32
+
33
+ /* Image Variant */
34
+ ${props => props.$variant === 'image' && css`
35
+ width: 320px;
36
+ display: flex;
37
+ flex-direction: column;
38
+ `}
39
+
40
+ /* Horizontal Variant */
41
+ ${props => props.$variant === 'horizontal' && css`
42
+ width: 100%;
43
+ max-width: 500px;
44
+ display: flex;
45
+ flex-direction: row;
46
+ align-items: center;
47
+ padding: 1rem;
48
+ gap: 1.5rem;
49
+
50
+ @media (max-width: 480px) {
51
+ flex-direction: column;
52
+ }
53
+ `}
54
+ `;
55
+
56
+ const CardImage = styled.img`
57
+ object-fit: cover;
58
+
59
+ ${props => props.$variant === 'image' && css`
60
+ width: 100%;
61
+ height: 180px;
62
+ `}
63
+
64
+ ${props => props.$variant === 'horizontal' && css`
65
+ width: 120px;
66
+ height: 120px;
67
+ border-radius: 8px;
68
+ `}
69
+ `;
70
+
71
+ const CardBody = styled.div`
72
+ display: flex;
73
+ flex-direction: column;
74
+
75
+ ${props => props.$variant === 'image' && css`
76
+ padding: 1.5rem;
77
+ gap: 0.8rem;
78
+ `}
79
+
80
+ ${props => props.$variant === 'horizontal' && css`
81
+ flex: 1;
82
+ gap: 0.5rem;
83
+ `}
84
+ `;
85
+
86
+ const CardTitle = styled.h3`
87
+ font-size: 1.2rem;
88
+ font-weight: 700;
89
+ color: #1f2937;
90
+ margin: 0;
91
+ `;
92
+
93
+ const CardText = styled.p`
94
+ font-size: 0.95rem;
95
+ color: #6b7280;
96
+ line-height: 1.5;
97
+ margin: 0;
98
+ `;
99
+
100
+ const CardMeta = styled.div`
101
+ display: flex;
102
+ align-items: center;
103
+ gap: 0.5rem;
104
+ font-size: 0.85rem;
105
+ color: #9ca3af;
106
+ margin-top: 0.5rem;
107
+ `;
108
+
109
+ const CardAction = styled.button`
110
+ margin-top: auto;
111
+ padding: 0.6rem 1rem;
112
+ background-color: #4f46e5;
113
+ color: white;
114
+ border: none;
115
+ border-radius: 8px;
116
+ font-weight: 600;
117
+ cursor: pointer;
118
+ width: fit-content;
119
+ align-self: flex-start;
120
+ display: flex;
121
+ align-items: center;
122
+ gap: 0.5rem;
123
+ transition: background-color 0.2s;
124
+
125
+ &:hover {
126
+ background-color: #4338ca;
127
+ }
128
+
129
+ ${props => props.$outline && css`
130
+ background-color: transparent;
131
+ color: #4f46e5;
132
+ border: 1px solid #4f46e5;
133
+
134
+ &:hover {
135
+ background-color: #eef2ff;
136
+ }
137
+ `}
138
+ `;
139
+
140
+ export function Card({
141
+ variant = 'basic',
142
+ title,
143
+ description,
144
+ image,
145
+ meta,
146
+ buttonLabel,
147
+ onButtonClick,
148
+ outlineButton = false
149
+ }) {
150
+ const isHorizontal = variant === 'horizontal';
151
+
152
+ return (
153
+ <CardWrapper $variant={variant}>
154
+ {/* For Image/Horizontal variants, render image first if present */}
155
+ {(variant === 'image' || variant === 'horizontal') && image && (
156
+ <CardImage src={image} alt={title} $variant={variant} />
157
+ )}
158
+
159
+ {variant === 'basic' && (
160
+ <>
161
+ <CardTitle>{title}</CardTitle>
162
+ <CardText>{description}</CardText>
163
+ {meta && <CardMeta><Clock size={16} /> {meta}</CardMeta>}
164
+ {buttonLabel && (
165
+ <CardAction onClick={onButtonClick} $outline={outlineButton}>
166
+ {buttonLabel} <ArrowRight size={16} />
167
+ </CardAction>
168
+ )}
169
+ </>
170
+ )}
171
+
172
+ {(variant === 'image' || variant === 'horizontal') && (
173
+ <CardBody $variant={variant}>
174
+ <CardTitle>{title}</CardTitle>
175
+ <CardText>{description}</CardText>
176
+ {meta && <CardMeta><Clock size={16} /> {meta}</CardMeta>}
177
+
178
+ {buttonLabel && (
179
+ <div style={{ marginTop: '0.5rem' }}>
180
+ <CardAction onClick={onButtonClick} $outline={outlineButton}>
181
+ {buttonLabel}
182
+ </CardAction>
183
+ </div>
184
+ )}
185
+ </CardBody>
186
+ )}
187
+ </CardWrapper>
188
+ );
189
+ }
190
+
191
+ // =============================================================================
192
+ // SHOWCASE & DOCUMENTATION WRAPPER
193
+ // =============================================================================
194
+
195
+ const ShowcaseContainer = styled.div`
196
+ width: 100%;
197
+ padding: 2rem;
198
+ display: flex;
199
+ flex-direction: column;
200
+ gap: 3rem;
201
+ background-color: #f8fafc;
202
+ min-height: 100vh;
203
+ `;
204
+
205
+ const Title = styled.h2`
206
+ text-align: center;
207
+ font-size: 2rem;
208
+ color: #1e293b;
209
+ margin-bottom: 2rem;
210
+ font-weight: 800;
211
+ `;
212
+
213
+ const ShowcaseBlock = styled.div`
214
+ background: white;
215
+ border-radius: 16px;
216
+ overflow: hidden;
217
+ box-shadow: 0 4px 20px rgba(0,0,0,0.05);
218
+ border: 1px solid #e2e8f0;
219
+ `;
220
+
221
+ const PreviewArea = styled.div`
222
+ width: 100%;
223
+ padding: 2rem;
224
+ display: flex;
225
+ justify-content: center;
226
+ align-items: center;
227
+ background-color: #f3f4f6;
228
+ `;
229
+
230
+ const ActionSelect = styled.div`
231
+ display: flex;
232
+ justify-content: flex-end;
233
+ padding: 0.5rem;
234
+ background: #f1f5f9;
235
+ border-top: 1px solid #e2e8f0;
236
+ `;
237
+
238
+ const ActionButton = styled.button`
239
+ display: flex;
240
+ align-items: center;
241
+ gap: 0.5rem;
242
+ padding: 0.5rem 1rem;
243
+ border-radius: 6px;
244
+ border: 1px solid #cbd5e1;
245
+ background: white;
246
+ font-size: 0.85rem;
247
+ color: #475569;
248
+ cursor: pointer;
249
+ font-weight: 500;
250
+ transition: all 0.2s;
251
+
252
+ &:hover {
253
+ background: #f8fafc;
254
+ border-color: #94a3b8;
255
+ }
256
+ `;
257
+
258
+ const CodeBlock = styled.div`
259
+ background: #1e1e1e;
260
+ color: #d4d4d4;
261
+ padding: 1rem;
262
+ overflow-x: auto;
263
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
264
+ font-size: 0.85rem;
265
+ line-height: 1.5;
266
+ border-top: 1px solid #333;
267
+ `;
268
+
269
+ function CardVariantDisplay({ title, code, children }) {
270
+ const [showCode, setShowCode] = useState(false);
271
+ const [copied, setCopied] = useState(false);
272
+
273
+ const handleCopy = () => {
274
+ navigator.clipboard.writeText(code);
275
+ setCopied(true);
276
+ setTimeout(() => setCopied(false), 2000);
277
+ };
278
+
279
+ return (
280
+ <div>
281
+ <h3 style={{ textAlign: 'center', marginBottom: '1rem', color: '#64748b', textTransform: 'uppercase', letterSpacing: '0.1em', fontSize: '1rem' }}>{title}</h3>
282
+ <ShowcaseBlock>
283
+ <PreviewArea>
284
+ {children}
285
+ </PreviewArea>
286
+ <ActionSelect>
287
+ <div style={{ display: 'flex', gap: '0.5rem' }}>
288
+ <ActionButton onClick={() => setShowCode(!showCode)}>
289
+ <CodeIcon size={16} />
290
+ {showCode ? "Sembunyikan Kode" : "Lihat Kode"}
291
+ </ActionButton>
292
+ {showCode && (
293
+ <ActionButton onClick={handleCopy}>
294
+ {copied ? <Check size={16} /> : <Copy size={16} />}
295
+ {copied ? "Disalin!" : "Salin"}
296
+ </ActionButton>
297
+ )}
298
+ </div>
299
+ </ActionSelect>
300
+ {showCode && (
301
+ <CodeBlock>
302
+ <pre>{code}</pre>
303
+ </CodeBlock>
304
+ )}
305
+ </ShowcaseBlock>
306
+ </div>
307
+ );
308
+ }
309
+
310
+ export function CardShowcase() {
311
+ return (
312
+ <ShowcaseContainer>
313
+ <Title>Card Variants</Title>
314
+ <p style={{ textAlign: 'center', color: '#666', marginBottom: '2rem' }}>
315
+ Komponen kartu serbaguna untuk berbagai kebutuhan konten.
316
+ </p>
317
+
318
+ <CardVariantDisplay
319
+ title="1. Kartu Dasar (Teks Saja)"
320
+ code={`<Card
321
+ variant="basic"
322
+ title="Promo Mingguan"
323
+ description="Dapatkan diskon 20% untuk semua menu pasta setiap hari Jumat. Jangan lewatkan kesempatan ini!"
324
+ buttonLabel="Lihat Menu"
325
+ meta="Berakhir dalam 2 hari"
326
+ />`}
327
+ >
328
+ <Card
329
+ variant="basic"
330
+ title="Promo Mingguan"
331
+ description="Dapatkan diskon 20% untuk semua menu pasta setiap hari Jumat. Jangan lewatkan kesempatan ini!"
332
+ buttonLabel="Lihat Menu"
333
+ meta="Berakhir dalam 2 hari"
334
+ />
335
+ </CardVariantDisplay>
336
+
337
+ <CardVariantDisplay
338
+ title="2. Kartu dengan Gambar"
339
+ code={`<Card
340
+ variant="image"
341
+ image="https://images.unsplash.com/photo-1546069901-ba9599a7e63c"
342
+ title="Nasi Goreng Spesial"
343
+ description="Nasi goreng kampung dengan bumbu rahasia, dilengkapi telur mata sapi dan sate ayam."
344
+ buttonLabel="Pesan Sekarang"
345
+ outlineButton={true}
346
+ />`}
347
+ >
348
+ <Card
349
+ variant="image"
350
+ image="https://images.unsplash.com/photo-1546069901-ba9599a7e63c?auto=format&fit=crop&w=400&q=80"
351
+ title="Nasi Goreng Spesial"
352
+ description="Nasi goreng kampung dengan bumbu rahasia, dilengkapi telur mata sapi dan sate ayam."
353
+ buttonLabel="Pesan Sekarang"
354
+ outlineButton={true}
355
+ />
356
+ </CardVariantDisplay>
357
+
358
+ <CardVariantDisplay
359
+ title="3. Kartu Horizontal"
360
+ code={`<Card
361
+ variant="horizontal"
362
+ image="https://images.unsplash.com/photo-1555939594-58d7cb561ad1"
363
+ title="Paket Katering"
364
+ description="Layanan katering untuk acara kantor dan pesta keluarga."
365
+ buttonLabel="Hubungi Kami"
366
+ />`}
367
+ >
368
+ <Card
369
+ variant="horizontal"
370
+ image="https://images.unsplash.com/photo-1555939594-58d7cb561ad1?auto=format&fit=crop&w=200&q=80"
371
+ title="Paket Katering"
372
+ description="Layanan katering untuk acara kantor dan pesta keluarga."
373
+ buttonLabel="Hubungi Kami"
374
+ />
375
+ </CardVariantDisplay>
376
+
377
+ </ShowcaseContainer>
378
+ );
379
+ }
380
+
381
+ // Support legacy imports or default usage
382
+ export default function AppCard(props) {
383
+ if (props.variant) {
384
+ return <Card {...props} />;
385
+ }
386
+ // Backward compatibility wrapper for old props
387
+ return <Card variant="image" {...props} />;
388
+ }
@@ -0,0 +1,112 @@
1
+ "use client";
2
+ import styled, { keyframes, css } from "styled-components";
3
+ import { FaHome, FaUser, FaCog, FaPhone } from "react-icons/fa";
4
+
5
+ export const DemoSidebar = ({ variant = "primary" }) => {
6
+ return (
7
+ <SidebarContainer $variant={variant}>
8
+ <h3>
9
+ {variant === "dark"
10
+ ? "Menu Navigation"
11
+ : variant === "outline"
12
+ ? "Sidebar Menu"
13
+ : variant === "slide"
14
+ ? "Animated Sidebar"
15
+ : "Sidebar Menu"}
16
+ </h3>
17
+
18
+ <SidebarList>
19
+ <SidebarItem>{variant !== "primary" && <FaHome />} Home</SidebarItem>
20
+ <SidebarItem>{variant !== "primary" && <FaUser />} About</SidebarItem>
21
+ <SidebarItem>{variant !== "primary" && <FaCog />} Services</SidebarItem>
22
+ <SidebarItem>{variant !== "primary" && <FaPhone />} Contact</SidebarItem>
23
+ </SidebarList>
24
+
25
+ {variant === "outline" && <ActionButton>Get in Touch</ActionButton>}
26
+ </SidebarContainer>
27
+ );
28
+ };
29
+
30
+ // 🎬 Animations khusus untuk varian SLIDE
31
+ const fadeSlideIn = keyframes`
32
+ 0% { transform: translateX(-40px); opacity: 0; }
33
+ 100% { transform: translateX(0); opacity: 1; }
34
+ `;
35
+
36
+ const shimmer = keyframes`
37
+ 0% { background-position: 200% 0; }
38
+ 100% { background-position: -200% 0; }
39
+ `;
40
+
41
+ const SidebarContainer = styled.aside`
42
+ width: 200px;
43
+ padding: 20px;
44
+ border-radius: 16px;
45
+ color: #fff;
46
+ transition: all 0.4s ease;
47
+ box-shadow: 0 6px 14px rgba(0, 0, 0, 0.2);
48
+
49
+ ${({ $variant }) =>
50
+ $variant === "slide"
51
+ ? css`
52
+ background: linear-gradient(
53
+ 120deg,
54
+ #6548f5 0%,
55
+ #8e6dfc 50%,
56
+ #6548f5 100%
57
+ );
58
+ background-size: 300% 300%;
59
+ animation: ${fadeSlideIn} 0.8s ease forwards,
60
+ ${shimmer} 2.8s linear infinite;
61
+ `
62
+ : css`
63
+ background: ${() =>
64
+ $variant === "dark"
65
+ ? "linear-gradient(180deg, #1b1a2e, #0e0d17)"
66
+ : $variant === "outline"
67
+ ? "linear-gradient(180deg, #2c1e6b, #402c87)"
68
+ : "linear-gradient(180deg, #3d2d7c, #5a3ec5)"};
69
+ `}
70
+
71
+ h3 {
72
+ margin-bottom: 16px;
73
+ font-size: 1.1rem;
74
+ }
75
+ `;
76
+
77
+ const SidebarList = styled.ul`
78
+ list-style: none;
79
+ padding: 0;
80
+ margin: 0;
81
+ display: flex;
82
+ flex-direction: column;
83
+ gap: 10px;
84
+ `;
85
+
86
+ const SidebarItem = styled.li`
87
+ display: flex;
88
+ align-items: center;
89
+ gap: 10px;
90
+ cursor: pointer;
91
+ transition: 0.2s ease;
92
+
93
+ &:hover {
94
+ transform: translateX(5px);
95
+ opacity: 0.85;
96
+ }
97
+ `;
98
+
99
+ const ActionButton = styled.button`
100
+ width: 100%;
101
+ margin-top: 18px;
102
+ padding: 8px 14px;
103
+ border-radius: 8px;
104
+ border: none;
105
+ background: #b28aff;
106
+ cursor: pointer;
107
+ transition: 0.3s;
108
+
109
+ &:hover {
110
+ background: #a379ff;
111
+ }
112
+ `;
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { createContext, useContext, useState } from "react";
3
+
4
+ import { themes } from "../theme.js";
5
+
6
+ const ThemeContext = createContext();
7
+
8
+ export function ThemeProvider({ children }) {
9
+ const [theme, setTheme] = useState("light");
10
+
11
+ return (
12
+ <ThemeContext.Provider value={{ theme, setTheme }}>
13
+ <div
14
+ style={{
15
+ minHeight: "100vh",
16
+ background: themes[theme].background,
17
+ color: themes[theme].text,
18
+ transition: "0.3s",
19
+ }}
20
+ >
21
+ {children}
22
+ </div>
23
+ </ThemeContext.Provider>
24
+ );
25
+ }
26
+
27
+ export function useTheme() {
28
+ return useContext(ThemeContext);
29
+ }
package/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import Button, { ButtonShowcase } from "./components/Button";
2
+ import Card, { CardShowcase } from "./components/Card";
3
+ import AppHeader, { HeaderShowcase } from "./components/AppHeader";
4
+ import AppSidebar, { SidebarShowcase } from "./components/AppSidebar";
5
+ import AppFooter, { FooterShowcase } from "./components/AppFooter";
6
+ import { ThemeProvider, useTheme } from "./components/ThemeSwitcher";
7
+
8
+ export { Button, ButtonShowcase, Card, CardShowcase, AppHeader, HeaderShowcase, AppSidebar, SidebarShowcase, AppFooter, FooterShowcase, ThemeProvider, useTheme };
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "xegavnj",
3
+ "version": "0.1.8",
4
+ "type": "module",
5
+ "main": "index.js",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./index.js"
9
+ }
10
+ },
11
+ "files": [
12
+ "components",
13
+ "index.js",
14
+ "theme.js",
15
+ "theme"
16
+ ],
17
+ "scripts": {
18
+ "dev": "next dev --webpack",
19
+ "build": "next build --webpack",
20
+ "start": "next start",
21
+ "lint": "eslint"
22
+ },
23
+ "peerDependencies": {
24
+ "next": ">=15.0.0",
25
+ "react": ">=19.1.0",
26
+ "react-dom": ">=19.1.0",
27
+ "styled-components": "^6.1.19"
28
+ },
29
+ "dependencies": {
30
+ "lucide-react": "^0.553.0",
31
+ "next": " 16.0.1",
32
+ "react": "19.2.0",
33
+ "react-dom": "19.2.0",
34
+ "react-icons": "^5.5.0",
35
+ "styled-components": "^6.1.19"
36
+ },
37
+ "devDependencies": {
38
+ "autoprefixer": "^10.4.21",
39
+ "babel-plugin-styled-components": "^2.1.4",
40
+ "eslint": "^9",
41
+ "eslint-config-next": "16.0.1",
42
+ "postcss": "^8.5.6",
43
+ "tailwindcss": "^4.1.17"
44
+ }
45
+ }
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ import { createContext, useContext, useState } from "react";
3
+
4
+ const themes = {
5
+ light: {
6
+ background: "#ffffff",
7
+ text: "#111827",
8
+ },
9
+ dark: {
10
+ background: "#111827",
11
+ text: "#f9fafb",
12
+ },
13
+ colorful: {
14
+ background: "#fdf2f8",
15
+ text: "#831843",
16
+ },
17
+ };
18
+
19
+ const ThemeContext = createContext();
20
+
21
+ export function ThemeProvider({ children }) {
22
+ const [themeName, setThemeName] = useState("light");
23
+
24
+ return (
25
+ <ThemeContext.Provider value={{ themeName, setThemeName }}>
26
+ <div
27
+ style={{
28
+ minHeight: "100vh",
29
+ backgroundColor: themes[themeName].background,
30
+ color: themes[themeName].text,
31
+ transition: "0.3s ease",
32
+ }}
33
+ >
34
+ {children}
35
+ </div>
36
+ </ThemeContext.Provider>
37
+ );
38
+ }
39
+
40
+ export function useTheme() {
41
+ return useContext(ThemeContext);
42
+ }
package/theme.js ADDED
@@ -0,0 +1,23 @@
1
+ export const themes = {
2
+ light: {
3
+ background: "#ffffff",
4
+ text: "#111827",
5
+ primary: "#2563eb",
6
+ secondary: "#4b5563",
7
+ border: "#e5e7eb",
8
+ },
9
+ dark: {
10
+ background: "#0f172a",
11
+ text: "#f8fafc",
12
+ primary: "#3b82f6",
13
+ secondary: "#94a3b8",
14
+ border: "#1e293b",
15
+ },
16
+ colorful: {
17
+ background: "#fff7ed",
18
+ text: "#7c2d12",
19
+ primary: "#ea580c",
20
+ secondary: "#fdba74",
21
+ border: "#fed7aa",
22
+ },
23
+ };