pixelforge-ui 1.0.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 +233 -0
- package/dist/index.css +1431 -0
- package/dist/index.d.mts +666 -0
- package/dist/index.d.ts +666 -0
- package/dist/index.js +1124 -0
- package/dist/index.mjs +1069 -0
- package/package.json +51 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,1069 @@
|
|
|
1
|
+
// src/tokens/index.ts
|
|
2
|
+
var colors = {
|
|
3
|
+
primary: {
|
|
4
|
+
lime: "#C4F0C8",
|
|
5
|
+
lavender: "#D4B5E8",
|
|
6
|
+
sky: "#B8E0F0",
|
|
7
|
+
peach: "#F0D9C8",
|
|
8
|
+
mint: "#C8F0E0"
|
|
9
|
+
},
|
|
10
|
+
dark: {
|
|
11
|
+
lime: "#6B9D77",
|
|
12
|
+
lavender: "#8B6BA8",
|
|
13
|
+
sky: "#6BA3C8",
|
|
14
|
+
peach: "#C89968",
|
|
15
|
+
mint: "#6BA89F"
|
|
16
|
+
},
|
|
17
|
+
neutral: {
|
|
18
|
+
black: "#1A1A24",
|
|
19
|
+
dark: "#2D2D3D",
|
|
20
|
+
gray: "#666670",
|
|
21
|
+
light: "#F5F5F0",
|
|
22
|
+
white: "#FFFBF5"
|
|
23
|
+
},
|
|
24
|
+
semantic: {
|
|
25
|
+
success: "#7FD8B8",
|
|
26
|
+
warning: "#FFB347",
|
|
27
|
+
error: "#FF6B6B",
|
|
28
|
+
info: "#B8E0F0"
|
|
29
|
+
},
|
|
30
|
+
accent: "#FF6B9D"
|
|
31
|
+
};
|
|
32
|
+
var typography = {
|
|
33
|
+
font: {
|
|
34
|
+
pixel: '"Press Start 2P", monospace',
|
|
35
|
+
sans: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
36
|
+
mono: '"Courier New", monospace'
|
|
37
|
+
},
|
|
38
|
+
size: {
|
|
39
|
+
xs: "12px",
|
|
40
|
+
sm: "14px",
|
|
41
|
+
base: "16px",
|
|
42
|
+
lg: "20px",
|
|
43
|
+
xl: "24px",
|
|
44
|
+
"2xl": "32px"
|
|
45
|
+
},
|
|
46
|
+
weight: {
|
|
47
|
+
normal: 400,
|
|
48
|
+
bold: 700
|
|
49
|
+
},
|
|
50
|
+
lineHeight: {
|
|
51
|
+
tight: 1.2,
|
|
52
|
+
normal: 1.5,
|
|
53
|
+
relaxed: 1.75
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
var spacing = {
|
|
57
|
+
0: "0",
|
|
58
|
+
1: "4px",
|
|
59
|
+
2: "8px",
|
|
60
|
+
3: "12px",
|
|
61
|
+
4: "16px",
|
|
62
|
+
5: "20px",
|
|
63
|
+
6: "24px",
|
|
64
|
+
8: "32px",
|
|
65
|
+
10: "40px",
|
|
66
|
+
12: "48px",
|
|
67
|
+
16: "64px",
|
|
68
|
+
20: "80px"
|
|
69
|
+
};
|
|
70
|
+
var shadows = {
|
|
71
|
+
sm: "4px 4px 0px rgba(0, 0, 0, 0.2)",
|
|
72
|
+
md: "8px 8px 0px rgba(0, 0, 0, 0.15)",
|
|
73
|
+
lg: "12px 12px 0px rgba(0, 0, 0, 0.1)",
|
|
74
|
+
glow: {
|
|
75
|
+
lime: "0 0 20px rgba(196, 240, 200, 0.4)",
|
|
76
|
+
lavender: "0 0 20px rgba(212, 181, 232, 0.4)",
|
|
77
|
+
sky: "0 0 20px rgba(184, 224, 240, 0.4)",
|
|
78
|
+
peach: "0 0 20px rgba(240, 217, 200, 0.4)"
|
|
79
|
+
},
|
|
80
|
+
press: "2px 2px 0px rgba(0, 0, 0, 0.3), inset 0 2px 0px rgba(0, 0, 0, 0.1)"
|
|
81
|
+
};
|
|
82
|
+
var borderRadius = {
|
|
83
|
+
sm: "4px",
|
|
84
|
+
base: "8px",
|
|
85
|
+
lg: "12px",
|
|
86
|
+
full: "9999px"
|
|
87
|
+
};
|
|
88
|
+
var breakpoints = {
|
|
89
|
+
xs: "320px",
|
|
90
|
+
sm: "640px",
|
|
91
|
+
md: "768px",
|
|
92
|
+
lg: "1024px",
|
|
93
|
+
xl: "1280px",
|
|
94
|
+
"2xl": "1536px"
|
|
95
|
+
};
|
|
96
|
+
var zIndex = {
|
|
97
|
+
hidden: -1,
|
|
98
|
+
base: 0,
|
|
99
|
+
dropdown: 1e3,
|
|
100
|
+
sticky: 1100,
|
|
101
|
+
fixed: 1200,
|
|
102
|
+
modal: 1300,
|
|
103
|
+
popover: 1400,
|
|
104
|
+
tooltip: 1500
|
|
105
|
+
};
|
|
106
|
+
var transitions = {
|
|
107
|
+
fast: "150ms ease-in-out",
|
|
108
|
+
base: "200ms ease-in-out",
|
|
109
|
+
slow: "300ms ease-in-out"
|
|
110
|
+
};
|
|
111
|
+
var gamePalettes = {
|
|
112
|
+
nes: {
|
|
113
|
+
name: "NES Classic",
|
|
114
|
+
colors: ["#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FF00FF", "#00FFFF"]
|
|
115
|
+
},
|
|
116
|
+
gameboy: {
|
|
117
|
+
name: "Game Boy",
|
|
118
|
+
colors: ["#9BBC0F", "#8BAC0F", "#306230", "#0F380F"]
|
|
119
|
+
},
|
|
120
|
+
atari: {
|
|
121
|
+
name: "Atari 2600",
|
|
122
|
+
colors: ["#000000", "#FFFFFF", "#FF0000", "#FFFF00"]
|
|
123
|
+
},
|
|
124
|
+
snes: {
|
|
125
|
+
name: "SNES",
|
|
126
|
+
colors: ["#8B008B", "#FF1493", "#1E90FF", "#FFD700"]
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// src/components/Button.tsx
|
|
131
|
+
import React from "react";
|
|
132
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
133
|
+
var Button = React.forwardRef(
|
|
134
|
+
({
|
|
135
|
+
variant = "primary",
|
|
136
|
+
size = "md",
|
|
137
|
+
disabled = false,
|
|
138
|
+
isLoading = false,
|
|
139
|
+
loadingText,
|
|
140
|
+
children,
|
|
141
|
+
className = "",
|
|
142
|
+
...props
|
|
143
|
+
}, ref) => {
|
|
144
|
+
const baseStyles = `
|
|
145
|
+
inline-flex items-center justify-center
|
|
146
|
+
font-pixel text-sm
|
|
147
|
+
transition-all duration-200
|
|
148
|
+
cursor-pointer
|
|
149
|
+
active:scale-95
|
|
150
|
+
focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-pixelforge-accent
|
|
151
|
+
disabled:opacity-50 disabled:cursor-not-allowed
|
|
152
|
+
`;
|
|
153
|
+
const sizeStyles = {
|
|
154
|
+
sm: "px-3 py-2 text-xs gap-2",
|
|
155
|
+
md: "px-4 py-3 text-sm gap-2",
|
|
156
|
+
lg: "px-6 py-4 text-base gap-3"
|
|
157
|
+
};
|
|
158
|
+
const variantStyles = {
|
|
159
|
+
primary: `
|
|
160
|
+
bg-pixelforge-lime text-pixelforge-black
|
|
161
|
+
border-2 border-pixelforge-darkLime
|
|
162
|
+
shadow-px
|
|
163
|
+
hover:shadow-px-lg hover:translate-y-[-2px]
|
|
164
|
+
active:shadow-px-press active:translate-y-[2px]
|
|
165
|
+
dark:bg-pixelforge-darkLime dark:text-pixelforge-white dark:border-pixelforge-lime
|
|
166
|
+
`,
|
|
167
|
+
secondary: `
|
|
168
|
+
bg-pixelforge-lavender text-pixelforge-black
|
|
169
|
+
border-2 border-pixelforge-darkLavender
|
|
170
|
+
shadow-px
|
|
171
|
+
hover:shadow-px-lg hover:translate-y-[-2px]
|
|
172
|
+
active:shadow-px-press active:translate-y-[2px]
|
|
173
|
+
dark:bg-pixelforge-darkLavender dark:text-pixelforge-white dark:border-pixelforge-lavender
|
|
174
|
+
`,
|
|
175
|
+
outline: `
|
|
176
|
+
bg-transparent border-2
|
|
177
|
+
text-pixelforge-black border-pixelforge-darkLime
|
|
178
|
+
hover:bg-pixelforge-lime/10 active:bg-pixelforge-lime/20
|
|
179
|
+
dark:text-pixelforge-white dark:border-pixelforge-lime
|
|
180
|
+
dark:hover:bg-pixelforge-lime/30 dark:active:bg-pixelforge-lime/40
|
|
181
|
+
`,
|
|
182
|
+
ghost: `
|
|
183
|
+
bg-transparent text-pixelforge-black border-2 border-transparent
|
|
184
|
+
hover:bg-pixelforge-lime/20 active:bg-pixelforge-lime/30
|
|
185
|
+
dark:text-pixelforge-white dark:hover:bg-pixelforge-lime/30
|
|
186
|
+
dark:active:bg-pixelforge-lime/40
|
|
187
|
+
`
|
|
188
|
+
};
|
|
189
|
+
return /* @__PURE__ */ jsx(
|
|
190
|
+
"button",
|
|
191
|
+
{
|
|
192
|
+
ref,
|
|
193
|
+
disabled: disabled || isLoading,
|
|
194
|
+
className: `${baseStyles} ${sizeStyles[size]} ${variantStyles[variant]} ${className}`,
|
|
195
|
+
...props,
|
|
196
|
+
children: isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
197
|
+
/* @__PURE__ */ jsx("span", { className: "animate-spin", children: "\u27F3" }),
|
|
198
|
+
loadingText || children
|
|
199
|
+
] }) : children
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
);
|
|
204
|
+
Button.displayName = "Button";
|
|
205
|
+
|
|
206
|
+
// src/components/Input.tsx
|
|
207
|
+
import React2 from "react";
|
|
208
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
209
|
+
var Input = React2.forwardRef(
|
|
210
|
+
({
|
|
211
|
+
label,
|
|
212
|
+
error,
|
|
213
|
+
helperText,
|
|
214
|
+
required,
|
|
215
|
+
leftIcon,
|
|
216
|
+
rightIcon,
|
|
217
|
+
className = "",
|
|
218
|
+
disabled,
|
|
219
|
+
...props
|
|
220
|
+
}, ref) => {
|
|
221
|
+
const hasError = !!error;
|
|
222
|
+
return /* @__PURE__ */ jsxs2("div", { className: "w-full", children: [
|
|
223
|
+
label && /* @__PURE__ */ jsx2(
|
|
224
|
+
"label",
|
|
225
|
+
{
|
|
226
|
+
htmlFor: props.id,
|
|
227
|
+
className: `
|
|
228
|
+
block font-pixel text-xs mb-2
|
|
229
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
230
|
+
${required ? "after:content-['*'] after:text-pixelforge-error after:ml-1" : ""}
|
|
231
|
+
`,
|
|
232
|
+
children: label
|
|
233
|
+
}
|
|
234
|
+
),
|
|
235
|
+
/* @__PURE__ */ jsxs2("div", { className: "relative", children: [
|
|
236
|
+
leftIcon && /* @__PURE__ */ jsx2("div", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-pixelforge-black dark:text-pixelforge-white", children: leftIcon }),
|
|
237
|
+
/* @__PURE__ */ jsx2(
|
|
238
|
+
"input",
|
|
239
|
+
{
|
|
240
|
+
ref,
|
|
241
|
+
disabled,
|
|
242
|
+
className: `
|
|
243
|
+
w-full
|
|
244
|
+
px-4 py-3
|
|
245
|
+
font-mono text-sm
|
|
246
|
+
bg-pixelforge-white dark:bg-pixelforge-dark
|
|
247
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
248
|
+
border-2 border-pixelforge-darkLime dark:border-pixelforge-lime
|
|
249
|
+
rounded-px-sm
|
|
250
|
+
shadow-px
|
|
251
|
+
transition-all duration-200
|
|
252
|
+
placeholder:text-pixelforge-gray/50
|
|
253
|
+
focus:outline-none focus:shadow-px-lg focus:translate-y-[-2px]
|
|
254
|
+
focus:border-pixelforge-accent
|
|
255
|
+
disabled:opacity-50 disabled:cursor-not-allowed
|
|
256
|
+
${hasError ? "border-pixelforge-error focus:border-pixelforge-error shadow-px focus:shadow-px-glow" : ""}
|
|
257
|
+
${leftIcon ? "pl-10" : ""}
|
|
258
|
+
${rightIcon ? "pr-10" : ""}
|
|
259
|
+
${className}
|
|
260
|
+
`,
|
|
261
|
+
...props
|
|
262
|
+
}
|
|
263
|
+
),
|
|
264
|
+
rightIcon && /* @__PURE__ */ jsx2("div", { className: "absolute right-3 top-1/2 -translate-y-1/2 text-pixelforge-black dark:text-pixelforge-white", children: rightIcon })
|
|
265
|
+
] }),
|
|
266
|
+
error && /* @__PURE__ */ jsxs2("p", { className: "mt-2 font-mono text-xs text-pixelforge-error", children: [
|
|
267
|
+
"\u26A0 ",
|
|
268
|
+
error
|
|
269
|
+
] }),
|
|
270
|
+
helperText && !error && /* @__PURE__ */ jsx2("p", { className: "mt-2 font-mono text-xs text-pixelforge-gray", children: helperText })
|
|
271
|
+
] });
|
|
272
|
+
}
|
|
273
|
+
);
|
|
274
|
+
Input.displayName = "Input";
|
|
275
|
+
|
|
276
|
+
// src/components/Card.tsx
|
|
277
|
+
import React3 from "react";
|
|
278
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
279
|
+
var Card = React3.forwardRef(
|
|
280
|
+
({
|
|
281
|
+
title,
|
|
282
|
+
subtitle,
|
|
283
|
+
interactive = false,
|
|
284
|
+
variant = "default",
|
|
285
|
+
header,
|
|
286
|
+
footer,
|
|
287
|
+
children,
|
|
288
|
+
className = "",
|
|
289
|
+
...props
|
|
290
|
+
}, ref) => {
|
|
291
|
+
const variantStyles = {
|
|
292
|
+
default: `
|
|
293
|
+
bg-pixelforge-white dark:bg-pixelforge-dark
|
|
294
|
+
border-pixelforge-darkLime dark:border-pixelforge-lime
|
|
295
|
+
`,
|
|
296
|
+
lime: `
|
|
297
|
+
bg-pixelforge-lime/20 dark:bg-pixelforge-darkLime/20
|
|
298
|
+
border-pixelforge-lime dark:border-pixelforge-lime
|
|
299
|
+
`,
|
|
300
|
+
lavender: `
|
|
301
|
+
bg-pixelforge-lavender/20 dark:bg-pixelforge-darkLavender/20
|
|
302
|
+
border-pixelforge-lavender dark:border-pixelforge-lavender
|
|
303
|
+
`,
|
|
304
|
+
sky: `
|
|
305
|
+
bg-pixelforge-sky/20 dark:bg-pixelforge-darkSky/20
|
|
306
|
+
border-pixelforge-sky dark:border-pixelforge-sky
|
|
307
|
+
`,
|
|
308
|
+
peach: `
|
|
309
|
+
bg-pixelforge-peach/20 dark:bg-pixelforge-darkPeach/20
|
|
310
|
+
border-pixelforge-peach dark:border-pixelforge-peach
|
|
311
|
+
`,
|
|
312
|
+
mint: `
|
|
313
|
+
bg-pixelforge-mint/20 dark:bg-pixelforge-darkMint/20
|
|
314
|
+
border-pixelforge-mint dark:border-pixelforge-mint
|
|
315
|
+
`
|
|
316
|
+
};
|
|
317
|
+
return /* @__PURE__ */ jsxs3(
|
|
318
|
+
"div",
|
|
319
|
+
{
|
|
320
|
+
ref,
|
|
321
|
+
className: `
|
|
322
|
+
border-2 border-solid
|
|
323
|
+
rounded-px
|
|
324
|
+
shadow-px
|
|
325
|
+
transition-all duration-200
|
|
326
|
+
${interactive ? "cursor-pointer hover:shadow-px-lg hover:translate-y-[-2px] active:shadow-px-press active:translate-y-[2px]" : ""}
|
|
327
|
+
${variantStyles[variant]}
|
|
328
|
+
${className}
|
|
329
|
+
`,
|
|
330
|
+
...props,
|
|
331
|
+
children: [
|
|
332
|
+
header && /* @__PURE__ */ jsx3("div", { className: "border-b-2 border-pixelforge-darkLime dark:border-pixelforge-lime/30 px-6 py-4", children: header }),
|
|
333
|
+
/* @__PURE__ */ jsxs3("div", { className: "p-6", children: [
|
|
334
|
+
title && /* @__PURE__ */ jsx3("h3", { className: "font-pixel text-lg text-pixelforge-black dark:text-pixelforge-white mb-1", children: title }),
|
|
335
|
+
subtitle && /* @__PURE__ */ jsx3("p", { className: "font-mono text-xs text-pixelforge-gray mb-4", children: subtitle }),
|
|
336
|
+
children
|
|
337
|
+
] }),
|
|
338
|
+
footer && /* @__PURE__ */ jsx3("div", { className: "border-t-2 border-pixelforge-darkLime dark:border-pixelforge-lime/30 px-6 py-4 bg-pixelforge-light/50 dark:bg-pixelforge-black/20", children: footer })
|
|
339
|
+
]
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
);
|
|
344
|
+
Card.displayName = "Card";
|
|
345
|
+
|
|
346
|
+
// src/components/Badge.tsx
|
|
347
|
+
import React4 from "react";
|
|
348
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
349
|
+
var Badge = React4.forwardRef(
|
|
350
|
+
({
|
|
351
|
+
variant = "default",
|
|
352
|
+
size = "md",
|
|
353
|
+
dismissible = false,
|
|
354
|
+
onDismiss,
|
|
355
|
+
children,
|
|
356
|
+
className = "",
|
|
357
|
+
...props
|
|
358
|
+
}, ref) => {
|
|
359
|
+
const sizeStyles = {
|
|
360
|
+
sm: "px-2 py-1 text-xs",
|
|
361
|
+
md: "px-3 py-1.5 text-sm",
|
|
362
|
+
lg: "px-4 py-2 text-base"
|
|
363
|
+
};
|
|
364
|
+
const variantStyles = {
|
|
365
|
+
default: `
|
|
366
|
+
bg-pixelforge-light dark:bg-pixelforge-dark
|
|
367
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
368
|
+
border-pixelforge-darkLime dark:border-pixelforge-lime
|
|
369
|
+
`,
|
|
370
|
+
lime: `
|
|
371
|
+
bg-pixelforge-lime text-pixelforge-black
|
|
372
|
+
border-pixelforge-darkLime dark:bg-pixelforge-darkLime dark:text-pixelforge-white dark:border-pixelforge-lime
|
|
373
|
+
`,
|
|
374
|
+
lavender: `
|
|
375
|
+
bg-pixelforge-lavender text-pixelforge-black
|
|
376
|
+
border-pixelforge-darkLavender dark:bg-pixelforge-darkLavender dark:text-pixelforge-white dark:border-pixelforge-lavender
|
|
377
|
+
`,
|
|
378
|
+
sky: `
|
|
379
|
+
bg-pixelforge-sky text-pixelforge-black
|
|
380
|
+
border-pixelforge-darkSky dark:bg-pixelforge-darkSky dark:text-pixelforge-white dark:border-pixelforge-sky
|
|
381
|
+
`,
|
|
382
|
+
peach: `
|
|
383
|
+
bg-pixelforge-peach text-pixelforge-black
|
|
384
|
+
border-pixelforge-darkPeach dark:bg-pixelforge-darkPeach dark:text-pixelforge-white dark:border-pixelforge-peach
|
|
385
|
+
`,
|
|
386
|
+
mint: `
|
|
387
|
+
bg-pixelforge-mint text-pixelforge-black
|
|
388
|
+
border-pixelforge-darkMint dark:bg-pixelforge-darkMint dark:text-pixelforge-white dark:border-pixelforge-mint
|
|
389
|
+
`,
|
|
390
|
+
success: `
|
|
391
|
+
bg-pixelforge-success/20 text-pixelforge-success
|
|
392
|
+
border-pixelforge-success dark:bg-pixelforge-success/10 dark:text-pixelforge-success/80
|
|
393
|
+
`,
|
|
394
|
+
warning: `
|
|
395
|
+
bg-pixelforge-warning/20 text-pixelforge-warning
|
|
396
|
+
border-pixelforge-warning dark:bg-pixelforge-warning/10 dark:text-pixelforge-warning/80
|
|
397
|
+
`,
|
|
398
|
+
error: `
|
|
399
|
+
bg-pixelforge-error/20 text-pixelforge-error
|
|
400
|
+
border-pixelforge-error dark:bg-pixelforge-error/10 dark:text-pixelforge-error/80
|
|
401
|
+
`,
|
|
402
|
+
info: `
|
|
403
|
+
bg-pixelforge-sky/20 text-pixelforge-sky
|
|
404
|
+
border-pixelforge-sky dark:bg-pixelforge-sky/10 dark:text-pixelforge-sky/80
|
|
405
|
+
`
|
|
406
|
+
};
|
|
407
|
+
return /* @__PURE__ */ jsxs4(
|
|
408
|
+
"span",
|
|
409
|
+
{
|
|
410
|
+
ref,
|
|
411
|
+
className: `
|
|
412
|
+
inline-flex items-center gap-2
|
|
413
|
+
font-pixel text-xs
|
|
414
|
+
border-2
|
|
415
|
+
rounded-px-sm
|
|
416
|
+
whitespace-nowrap
|
|
417
|
+
transition-all duration-200
|
|
418
|
+
${sizeStyles[size]}
|
|
419
|
+
${variantStyles[variant]}
|
|
420
|
+
${className}
|
|
421
|
+
`,
|
|
422
|
+
...props,
|
|
423
|
+
children: [
|
|
424
|
+
children,
|
|
425
|
+
dismissible && /* @__PURE__ */ jsx4(
|
|
426
|
+
"button",
|
|
427
|
+
{
|
|
428
|
+
onClick: (e) => {
|
|
429
|
+
e.stopPropagation();
|
|
430
|
+
onDismiss?.();
|
|
431
|
+
},
|
|
432
|
+
className: "ml-1 font-bold hover:opacity-70 transition-opacity",
|
|
433
|
+
"aria-label": "Dismiss",
|
|
434
|
+
children: "\u2715"
|
|
435
|
+
}
|
|
436
|
+
)
|
|
437
|
+
]
|
|
438
|
+
}
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
);
|
|
442
|
+
Badge.displayName = "Badge";
|
|
443
|
+
|
|
444
|
+
// src/components/Modal.tsx
|
|
445
|
+
import { useEffect } from "react";
|
|
446
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
447
|
+
var Modal = ({
|
|
448
|
+
isOpen,
|
|
449
|
+
onClose,
|
|
450
|
+
title,
|
|
451
|
+
closeOnBackdropClick = true,
|
|
452
|
+
showCloseButton = true,
|
|
453
|
+
footer,
|
|
454
|
+
size = "md",
|
|
455
|
+
children
|
|
456
|
+
}) => {
|
|
457
|
+
useEffect(() => {
|
|
458
|
+
if (!isOpen) return;
|
|
459
|
+
const handleKeyDown = (e) => {
|
|
460
|
+
if (e.key === "Escape") {
|
|
461
|
+
onClose();
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
465
|
+
document.body.style.overflow = "hidden";
|
|
466
|
+
return () => {
|
|
467
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
468
|
+
document.body.style.overflow = "unset";
|
|
469
|
+
};
|
|
470
|
+
}, [isOpen, onClose]);
|
|
471
|
+
if (!isOpen) return null;
|
|
472
|
+
const sizeStyles = {
|
|
473
|
+
sm: "max-w-sm",
|
|
474
|
+
md: "max-w-md",
|
|
475
|
+
lg: "max-w-lg"
|
|
476
|
+
};
|
|
477
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
478
|
+
/* @__PURE__ */ jsx5(
|
|
479
|
+
"div",
|
|
480
|
+
{
|
|
481
|
+
className: `
|
|
482
|
+
fixed inset-0 z-modal
|
|
483
|
+
bg-black/40 backdrop-blur-xs
|
|
484
|
+
transition-opacity duration-200
|
|
485
|
+
${isOpen ? "opacity-100" : "opacity-0 pointer-events-none"}
|
|
486
|
+
`,
|
|
487
|
+
onClick: () => closeOnBackdropClick && onClose(),
|
|
488
|
+
"aria-hidden": "true"
|
|
489
|
+
}
|
|
490
|
+
),
|
|
491
|
+
/* @__PURE__ */ jsxs5(
|
|
492
|
+
"div",
|
|
493
|
+
{
|
|
494
|
+
className: `
|
|
495
|
+
fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2
|
|
496
|
+
z-modal w-11/12 ${sizeStyles[size]}
|
|
497
|
+
bg-pixelforge-white dark:bg-pixelforge-dark
|
|
498
|
+
border-2 border-pixelforge-darkLime dark:border-pixelforge-lime
|
|
499
|
+
rounded-px
|
|
500
|
+
shadow-lg
|
|
501
|
+
transition-all duration-200
|
|
502
|
+
${isOpen ? "scale-100 opacity-100" : "scale-95 opacity-0 pointer-events-none"}
|
|
503
|
+
`,
|
|
504
|
+
role: "dialog",
|
|
505
|
+
"aria-modal": "true",
|
|
506
|
+
onClick: (e) => e.stopPropagation(),
|
|
507
|
+
children: [
|
|
508
|
+
title && /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between border-b-2 border-pixelforge-darkLime dark:border-pixelforge-lime/30 px-6 py-4", children: [
|
|
509
|
+
/* @__PURE__ */ jsx5("h2", { className: "font-pixel text-lg text-pixelforge-black dark:text-pixelforge-white", children: title }),
|
|
510
|
+
showCloseButton && /* @__PURE__ */ jsx5(
|
|
511
|
+
"button",
|
|
512
|
+
{
|
|
513
|
+
onClick: onClose,
|
|
514
|
+
className: `
|
|
515
|
+
text-2xl font-bold
|
|
516
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
517
|
+
hover:opacity-70
|
|
518
|
+
transition-opacity
|
|
519
|
+
p-1 -mr-2
|
|
520
|
+
`,
|
|
521
|
+
"aria-label": "Close modal",
|
|
522
|
+
children: "\u2715"
|
|
523
|
+
}
|
|
524
|
+
)
|
|
525
|
+
] }),
|
|
526
|
+
/* @__PURE__ */ jsx5("div", { className: "px-6 py-6 max-h-[60vh] overflow-y-auto", children }),
|
|
527
|
+
footer && /* @__PURE__ */ jsx5("div", { className: "border-t-2 border-pixelforge-darkLime dark:border-pixelforge-lime/30 px-6 py-4 bg-pixelforge-light/50 dark:bg-pixelforge-black/20", children: footer })
|
|
528
|
+
]
|
|
529
|
+
}
|
|
530
|
+
)
|
|
531
|
+
] });
|
|
532
|
+
};
|
|
533
|
+
Modal.displayName = "Modal";
|
|
534
|
+
|
|
535
|
+
// src/components/Dropdown.tsx
|
|
536
|
+
import { useEffect as useEffect2, useRef, useState } from "react";
|
|
537
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
538
|
+
var Dropdown = ({
|
|
539
|
+
trigger,
|
|
540
|
+
items,
|
|
541
|
+
isOpen: controlledIsOpen,
|
|
542
|
+
onOpenChange,
|
|
543
|
+
placement = "bottom"
|
|
544
|
+
}) => {
|
|
545
|
+
const [internalIsOpen, setInternalIsOpen] = useState(false);
|
|
546
|
+
const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
|
|
547
|
+
const triggerRef = useRef(null);
|
|
548
|
+
const dropdownRef = useRef(null);
|
|
549
|
+
useEffect2(() => {
|
|
550
|
+
if (!isOpen) return;
|
|
551
|
+
const handleClickOutside = (e) => {
|
|
552
|
+
if (triggerRef.current?.contains(e.target) || dropdownRef.current?.contains(e.target)) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
handleClose();
|
|
556
|
+
};
|
|
557
|
+
window.addEventListener("mousedown", handleClickOutside);
|
|
558
|
+
return () => window.removeEventListener("mousedown", handleClickOutside);
|
|
559
|
+
}, [isOpen]);
|
|
560
|
+
useEffect2(() => {
|
|
561
|
+
if (!isOpen) return;
|
|
562
|
+
const handleKeyDown = (e) => {
|
|
563
|
+
if (e.key === "Escape") {
|
|
564
|
+
handleClose();
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
568
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
569
|
+
}, [isOpen]);
|
|
570
|
+
const handleOpen = () => {
|
|
571
|
+
const newState = !isOpen;
|
|
572
|
+
if (controlledIsOpen === void 0) {
|
|
573
|
+
setInternalIsOpen(newState);
|
|
574
|
+
}
|
|
575
|
+
onOpenChange?.(newState);
|
|
576
|
+
};
|
|
577
|
+
const handleClose = () => {
|
|
578
|
+
if (controlledIsOpen === void 0) {
|
|
579
|
+
setInternalIsOpen(false);
|
|
580
|
+
}
|
|
581
|
+
onOpenChange?.(false);
|
|
582
|
+
};
|
|
583
|
+
const handleItemClick = (item) => {
|
|
584
|
+
if (item.disabled) return;
|
|
585
|
+
item.onClick?.();
|
|
586
|
+
handleClose();
|
|
587
|
+
};
|
|
588
|
+
const placementStyles = {
|
|
589
|
+
bottom: "top-full mt-2",
|
|
590
|
+
top: "bottom-full mb-2",
|
|
591
|
+
left: "right-full mr-2",
|
|
592
|
+
right: "left-full ml-2"
|
|
593
|
+
};
|
|
594
|
+
return /* @__PURE__ */ jsxs6("div", { className: "relative inline-block", children: [
|
|
595
|
+
/* @__PURE__ */ jsx6(
|
|
596
|
+
"div",
|
|
597
|
+
{
|
|
598
|
+
ref: triggerRef,
|
|
599
|
+
onClick: handleOpen,
|
|
600
|
+
className: "cursor-pointer",
|
|
601
|
+
children: trigger
|
|
602
|
+
}
|
|
603
|
+
),
|
|
604
|
+
isOpen && /* @__PURE__ */ jsx6(
|
|
605
|
+
"div",
|
|
606
|
+
{
|
|
607
|
+
ref: dropdownRef,
|
|
608
|
+
className: `
|
|
609
|
+
absolute ${placementStyles[placement]}
|
|
610
|
+
min-w-max
|
|
611
|
+
bg-pixelforge-white dark:bg-pixelforge-dark
|
|
612
|
+
border-2 border-pixelforge-darkLime dark:border-pixelforge-lime
|
|
613
|
+
rounded-px-sm
|
|
614
|
+
shadow-px-lg
|
|
615
|
+
z-dropdown
|
|
616
|
+
py-1
|
|
617
|
+
animation-in fade-in zoom-in-95 duration-200
|
|
618
|
+
`,
|
|
619
|
+
role: "menu",
|
|
620
|
+
children: items.map((item, index) => {
|
|
621
|
+
if (item.divider) {
|
|
622
|
+
return /* @__PURE__ */ jsx6(
|
|
623
|
+
"div",
|
|
624
|
+
{
|
|
625
|
+
className: "h-px bg-pixelforge-darkLime/20 dark:bg-pixelforge-lime/20 my-1",
|
|
626
|
+
role: "separator"
|
|
627
|
+
},
|
|
628
|
+
item.id || `divider-${index}`
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
return /* @__PURE__ */ jsx6(
|
|
632
|
+
"button",
|
|
633
|
+
{
|
|
634
|
+
onClick: () => handleItemClick(item),
|
|
635
|
+
disabled: item.disabled,
|
|
636
|
+
className: `
|
|
637
|
+
w-full text-left
|
|
638
|
+
px-4 py-2.5
|
|
639
|
+
font-mono text-sm
|
|
640
|
+
transition-colors duration-150
|
|
641
|
+
flex items-center gap-2
|
|
642
|
+
${item.disabled ? "opacity-50 cursor-not-allowed text-pixelforge-gray dark:text-pixelforge-gray/50" : `
|
|
643
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
644
|
+
hover:bg-pixelforge-lime/20 dark:hover:bg-pixelforge-lime/40
|
|
645
|
+
active:bg-pixelforge-lime/30 dark:active:bg-pixelforge-lime/50
|
|
646
|
+
`}
|
|
647
|
+
`,
|
|
648
|
+
role: "menuitem",
|
|
649
|
+
children: item.label
|
|
650
|
+
},
|
|
651
|
+
item.id
|
|
652
|
+
);
|
|
653
|
+
})
|
|
654
|
+
}
|
|
655
|
+
)
|
|
656
|
+
] });
|
|
657
|
+
};
|
|
658
|
+
Dropdown.displayName = "Dropdown";
|
|
659
|
+
|
|
660
|
+
// src/components/Tooltip.tsx
|
|
661
|
+
import { useEffect as useEffect3, useRef as useRef2, useState as useState2 } from "react";
|
|
662
|
+
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
663
|
+
var Tooltip = ({
|
|
664
|
+
content,
|
|
665
|
+
children,
|
|
666
|
+
placement = "top",
|
|
667
|
+
delay = 200,
|
|
668
|
+
disabled = false,
|
|
669
|
+
variant = "default"
|
|
670
|
+
}) => {
|
|
671
|
+
const [isVisible, setIsVisible] = useState2(false);
|
|
672
|
+
const [position, setPosition] = useState2({ top: 0, left: 0 });
|
|
673
|
+
const triggerRef = useRef2(null);
|
|
674
|
+
const tooltipRef = useRef2(null);
|
|
675
|
+
const timeoutRef = useRef2();
|
|
676
|
+
const handleMouseEnter = () => {
|
|
677
|
+
if (disabled) return;
|
|
678
|
+
timeoutRef.current = setTimeout(() => {
|
|
679
|
+
setIsVisible(true);
|
|
680
|
+
updatePosition();
|
|
681
|
+
}, delay);
|
|
682
|
+
};
|
|
683
|
+
const handleMouseLeave = () => {
|
|
684
|
+
if (timeoutRef.current) {
|
|
685
|
+
clearTimeout(timeoutRef.current);
|
|
686
|
+
}
|
|
687
|
+
setIsVisible(false);
|
|
688
|
+
};
|
|
689
|
+
const updatePosition = () => {
|
|
690
|
+
if (!triggerRef.current || !tooltipRef.current) return;
|
|
691
|
+
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
692
|
+
const tooltipRect = tooltipRef.current.getBoundingClientRect();
|
|
693
|
+
const offset = 8;
|
|
694
|
+
let top = 0;
|
|
695
|
+
let left = 0;
|
|
696
|
+
switch (placement) {
|
|
697
|
+
case "top":
|
|
698
|
+
top = triggerRect.top - tooltipRect.height - offset;
|
|
699
|
+
left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
|
|
700
|
+
break;
|
|
701
|
+
case "bottom":
|
|
702
|
+
top = triggerRect.bottom + offset;
|
|
703
|
+
left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
|
|
704
|
+
break;
|
|
705
|
+
case "left":
|
|
706
|
+
top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
|
|
707
|
+
left = triggerRect.left - tooltipRect.width - offset;
|
|
708
|
+
break;
|
|
709
|
+
case "right":
|
|
710
|
+
top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
|
|
711
|
+
left = triggerRect.right + offset;
|
|
712
|
+
break;
|
|
713
|
+
}
|
|
714
|
+
setPosition({ top, left });
|
|
715
|
+
};
|
|
716
|
+
useEffect3(() => {
|
|
717
|
+
if (isVisible) {
|
|
718
|
+
updatePosition();
|
|
719
|
+
const handleResize = () => updatePosition();
|
|
720
|
+
window.addEventListener("resize", handleResize);
|
|
721
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
722
|
+
}
|
|
723
|
+
}, [isVisible, placement]);
|
|
724
|
+
useEffect3(() => {
|
|
725
|
+
return () => {
|
|
726
|
+
if (timeoutRef.current) {
|
|
727
|
+
clearTimeout(timeoutRef.current);
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
}, []);
|
|
731
|
+
const variantStyles = {
|
|
732
|
+
default: `
|
|
733
|
+
bg-pixelforge-black dark:bg-pixelforge-white
|
|
734
|
+
text-pixelforge-white dark:text-pixelforge-black
|
|
735
|
+
border-2 border-pixelforge-darkLime
|
|
736
|
+
`,
|
|
737
|
+
dark: `
|
|
738
|
+
bg-pixelforge-black/90 dark:bg-pixelforge-white/90
|
|
739
|
+
text-pixelforge-white dark:text-pixelforge-black
|
|
740
|
+
border-2 border-pixelforge-darkLime/50
|
|
741
|
+
backdrop-blur-xs
|
|
742
|
+
`
|
|
743
|
+
};
|
|
744
|
+
return /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
745
|
+
/* @__PURE__ */ jsx7(
|
|
746
|
+
"div",
|
|
747
|
+
{
|
|
748
|
+
ref: triggerRef,
|
|
749
|
+
onMouseEnter: handleMouseEnter,
|
|
750
|
+
onMouseLeave: handleMouseLeave,
|
|
751
|
+
className: "inline-block",
|
|
752
|
+
children
|
|
753
|
+
}
|
|
754
|
+
),
|
|
755
|
+
isVisible && /* @__PURE__ */ jsxs7(
|
|
756
|
+
"div",
|
|
757
|
+
{
|
|
758
|
+
ref: tooltipRef,
|
|
759
|
+
style: {
|
|
760
|
+
position: "fixed",
|
|
761
|
+
top: `${position.top}px`,
|
|
762
|
+
left: `${position.left}px`
|
|
763
|
+
},
|
|
764
|
+
className: `
|
|
765
|
+
z-tooltip
|
|
766
|
+
px-3 py-2
|
|
767
|
+
font-mono text-xs
|
|
768
|
+
rounded-px-sm
|
|
769
|
+
shadow-px-lg
|
|
770
|
+
whitespace-nowrap
|
|
771
|
+
pointer-events-none
|
|
772
|
+
transition-opacity duration-200
|
|
773
|
+
${variantStyles[variant]}
|
|
774
|
+
`,
|
|
775
|
+
role: "tooltip",
|
|
776
|
+
children: [
|
|
777
|
+
content,
|
|
778
|
+
/* @__PURE__ */ jsx7(
|
|
779
|
+
"div",
|
|
780
|
+
{
|
|
781
|
+
className: `
|
|
782
|
+
absolute w-2 h-2 bg-pixelforge-black dark:bg-pixelforge-white
|
|
783
|
+
border-r-2 border-b-2 border-pixelforge-darkLime
|
|
784
|
+
${placement === "top" ? "bottom-0 left-1/2 -translate-x-1/2 translate-y-1/2 rotate-45" : placement === "bottom" ? "top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 -rotate-45" : placement === "left" ? "right-0 top-1/2 -translate-y-1/2 translate-x-1/2 rotate-[135deg]" : "left-0 top-1/2 -translate-y-1/2 -translate-x-1/2 -rotate-[135deg]"}
|
|
785
|
+
`
|
|
786
|
+
}
|
|
787
|
+
)
|
|
788
|
+
]
|
|
789
|
+
}
|
|
790
|
+
)
|
|
791
|
+
] });
|
|
792
|
+
};
|
|
793
|
+
Tooltip.displayName = "Tooltip";
|
|
794
|
+
|
|
795
|
+
// src/components/Navbar.tsx
|
|
796
|
+
import React8 from "react";
|
|
797
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
798
|
+
var Navbar = React8.forwardRef(
|
|
799
|
+
({
|
|
800
|
+
brand,
|
|
801
|
+
links = [],
|
|
802
|
+
rightElement,
|
|
803
|
+
onBrandClick,
|
|
804
|
+
sticky = false,
|
|
805
|
+
className = "",
|
|
806
|
+
...props
|
|
807
|
+
}, ref) => {
|
|
808
|
+
return /* @__PURE__ */ jsx8(
|
|
809
|
+
"nav",
|
|
810
|
+
{
|
|
811
|
+
ref,
|
|
812
|
+
className: `
|
|
813
|
+
bg-pixelforge-white dark:bg-pixelforge-dark
|
|
814
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
815
|
+
border-b-2 border-pixelforge-darkLime dark:border-pixelforge-lime
|
|
816
|
+
shadow-px
|
|
817
|
+
transition-all duration-200
|
|
818
|
+
${sticky ? "sticky top-0 z-fixed" : ""}
|
|
819
|
+
${className}
|
|
820
|
+
`,
|
|
821
|
+
...props,
|
|
822
|
+
children: /* @__PURE__ */ jsx8("div", { className: "max-w-full px-6 py-4", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between gap-8", children: [
|
|
823
|
+
brand && /* @__PURE__ */ jsx8(
|
|
824
|
+
"button",
|
|
825
|
+
{
|
|
826
|
+
onClick: onBrandClick,
|
|
827
|
+
className: `
|
|
828
|
+
font-pixel text-lg
|
|
829
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
830
|
+
hover:text-pixelforge-accent
|
|
831
|
+
transition-colors
|
|
832
|
+
whitespace-nowrap
|
|
833
|
+
${onBrandClick ? "cursor-pointer" : "cursor-default"}
|
|
834
|
+
`,
|
|
835
|
+
children: brand
|
|
836
|
+
}
|
|
837
|
+
),
|
|
838
|
+
links.length > 0 && /* @__PURE__ */ jsx8("div", { className: "hidden md:flex items-center gap-1", children: links.map((link, index) => /* @__PURE__ */ jsx8(
|
|
839
|
+
"a",
|
|
840
|
+
{
|
|
841
|
+
href: link.href || "#",
|
|
842
|
+
onClick: (e) => {
|
|
843
|
+
if (link.onClick) {
|
|
844
|
+
e.preventDefault();
|
|
845
|
+
link.onClick();
|
|
846
|
+
}
|
|
847
|
+
},
|
|
848
|
+
className: `
|
|
849
|
+
px-4 py-2
|
|
850
|
+
font-mono text-sm
|
|
851
|
+
border-2 border-transparent
|
|
852
|
+
rounded-px-sm
|
|
853
|
+
transition-all duration-200
|
|
854
|
+
${link.disabled ? "opacity-50 cursor-not-allowed text-pixelforge-gray dark:text-pixelforge-gray/50" : `
|
|
855
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
856
|
+
hover:bg-pixelforge-lime/20 dark:hover:bg-pixelforge-lime/40
|
|
857
|
+
${link.active ? "bg-pixelforge-lime/30 dark:bg-pixelforge-lime/50 border-pixelforge-darkLime dark:border-pixelforge-lime" : ""}
|
|
858
|
+
`}
|
|
859
|
+
`,
|
|
860
|
+
children: link.label
|
|
861
|
+
},
|
|
862
|
+
index
|
|
863
|
+
)) }),
|
|
864
|
+
/* @__PURE__ */ jsx8("div", { className: "flex-1" }),
|
|
865
|
+
rightElement && /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-4", children: rightElement })
|
|
866
|
+
] }) })
|
|
867
|
+
}
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
);
|
|
871
|
+
Navbar.displayName = "Navbar";
|
|
872
|
+
|
|
873
|
+
// src/components/Sidebar.tsx
|
|
874
|
+
import React9, { useState as useState3 } from "react";
|
|
875
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
876
|
+
var Sidebar = React9.forwardRef(
|
|
877
|
+
({
|
|
878
|
+
brand,
|
|
879
|
+
items,
|
|
880
|
+
collapsible = true,
|
|
881
|
+
defaultCollapsed = false,
|
|
882
|
+
footer,
|
|
883
|
+
className = "",
|
|
884
|
+
...props
|
|
885
|
+
}, ref) => {
|
|
886
|
+
const [isCollapsed, setIsCollapsed] = useState3(defaultCollapsed);
|
|
887
|
+
const [expandedItems, setExpandedItems] = useState3([]);
|
|
888
|
+
const toggleExpand = (itemId) => {
|
|
889
|
+
setExpandedItems(
|
|
890
|
+
(prev) => prev.includes(itemId) ? prev.filter((id) => id !== itemId) : [...prev, itemId]
|
|
891
|
+
);
|
|
892
|
+
};
|
|
893
|
+
const renderItem = (item, depth = 0) => {
|
|
894
|
+
const isExpanded = expandedItems.includes(item.id);
|
|
895
|
+
const hasChildren = item.children && item.children.length > 0;
|
|
896
|
+
return /* @__PURE__ */ jsxs9("div", { children: [
|
|
897
|
+
/* @__PURE__ */ jsxs9(
|
|
898
|
+
"button",
|
|
899
|
+
{
|
|
900
|
+
onClick: () => {
|
|
901
|
+
if (hasChildren) {
|
|
902
|
+
toggleExpand(item.id);
|
|
903
|
+
}
|
|
904
|
+
item.onClick?.();
|
|
905
|
+
},
|
|
906
|
+
disabled: item.disabled,
|
|
907
|
+
className: `
|
|
908
|
+
w-full text-left
|
|
909
|
+
px-4 py-3
|
|
910
|
+
font-mono text-sm
|
|
911
|
+
border-2 border-transparent
|
|
912
|
+
rounded-px-sm
|
|
913
|
+
transition-all duration-200
|
|
914
|
+
flex items-center gap-3
|
|
915
|
+
${item.disabled ? "opacity-50 cursor-not-allowed text-pixelforge-gray dark:text-pixelforge-gray/50" : `
|
|
916
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
917
|
+
hover:bg-pixelforge-lime/20 dark:hover:bg-pixelforge-lime/40
|
|
918
|
+
${item.active ? "bg-pixelforge-lime/30 dark:bg-pixelforge-lime/50 border-pixelforge-darkLime dark:border-pixelforge-lime" : ""}
|
|
919
|
+
`}
|
|
920
|
+
ml-${depth * 4}
|
|
921
|
+
`,
|
|
922
|
+
style: {
|
|
923
|
+
marginLeft: `${depth * 16}px`
|
|
924
|
+
},
|
|
925
|
+
children: [
|
|
926
|
+
item.icon && /* @__PURE__ */ jsx9("span", { className: "flex-shrink-0 text-lg", children: item.icon }),
|
|
927
|
+
/* @__PURE__ */ jsx9("span", { className: "flex-1", children: item.label }),
|
|
928
|
+
hasChildren && /* @__PURE__ */ jsx9(
|
|
929
|
+
"span",
|
|
930
|
+
{
|
|
931
|
+
className: `
|
|
932
|
+
transition-transform duration-200
|
|
933
|
+
${isExpanded ? "rotate-180" : ""}
|
|
934
|
+
`,
|
|
935
|
+
children: "\u25BC"
|
|
936
|
+
}
|
|
937
|
+
)
|
|
938
|
+
]
|
|
939
|
+
}
|
|
940
|
+
),
|
|
941
|
+
hasChildren && isExpanded && /* @__PURE__ */ jsx9("div", { className: "mt-1", children: item.children?.map((child) => renderItem(child, depth + 1)) })
|
|
942
|
+
] }, item.id);
|
|
943
|
+
};
|
|
944
|
+
return /* @__PURE__ */ jsxs9(
|
|
945
|
+
"div",
|
|
946
|
+
{
|
|
947
|
+
ref,
|
|
948
|
+
className: `
|
|
949
|
+
bg-pixelforge-white dark:bg-pixelforge-dark
|
|
950
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
951
|
+
border-r-2 border-pixelforge-darkLime dark:border-pixelforge-lime
|
|
952
|
+
h-screen
|
|
953
|
+
overflow-y-auto
|
|
954
|
+
transition-all duration-300
|
|
955
|
+
flex flex-col
|
|
956
|
+
${isCollapsed ? "w-20" : "w-64"}
|
|
957
|
+
${className}
|
|
958
|
+
`,
|
|
959
|
+
...props,
|
|
960
|
+
children: [
|
|
961
|
+
/* @__PURE__ */ jsx9("div", { className: "border-b-2 border-pixelforge-darkLime dark:border-pixelforge-lime px-4 py-4", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-2", children: [
|
|
962
|
+
!isCollapsed && brand && /* @__PURE__ */ jsx9("h2", { className: "font-pixel text-sm text-pixelforge-black dark:text-pixelforge-white truncate", children: brand }),
|
|
963
|
+
collapsible && /* @__PURE__ */ jsx9(
|
|
964
|
+
"button",
|
|
965
|
+
{
|
|
966
|
+
onClick: () => setIsCollapsed(!isCollapsed),
|
|
967
|
+
className: `
|
|
968
|
+
p-2 -mr-2
|
|
969
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
970
|
+
hover:bg-pixelforge-lime/20 dark:hover:bg-pixelforge-lime/30
|
|
971
|
+
rounded-px-sm
|
|
972
|
+
transition-all
|
|
973
|
+
flex-shrink-0
|
|
974
|
+
`,
|
|
975
|
+
"aria-label": isCollapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
976
|
+
children: isCollapsed ? "\u2192" : "\u2190"
|
|
977
|
+
}
|
|
978
|
+
)
|
|
979
|
+
] }) }),
|
|
980
|
+
/* @__PURE__ */ jsx9("div", { className: "flex-1 overflow-y-auto py-4 px-2 space-y-1", children: items.map((item) => renderItem(item)) }),
|
|
981
|
+
footer && /* @__PURE__ */ jsx9("div", { className: "border-t-2 border-pixelforge-darkLime dark:border-pixelforge-lime px-4 py-4", children: footer })
|
|
982
|
+
]
|
|
983
|
+
}
|
|
984
|
+
);
|
|
985
|
+
}
|
|
986
|
+
);
|
|
987
|
+
Sidebar.displayName = "Sidebar";
|
|
988
|
+
|
|
989
|
+
// src/components/Footer.tsx
|
|
990
|
+
import React10 from "react";
|
|
991
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
992
|
+
var Footer = React10.forwardRef(
|
|
993
|
+
({
|
|
994
|
+
brand,
|
|
995
|
+
sections = [],
|
|
996
|
+
copyright,
|
|
997
|
+
socialLinks,
|
|
998
|
+
className = "",
|
|
999
|
+
...props
|
|
1000
|
+
}, ref) => {
|
|
1001
|
+
return /* @__PURE__ */ jsxs10(
|
|
1002
|
+
"footer",
|
|
1003
|
+
{
|
|
1004
|
+
ref,
|
|
1005
|
+
className: `
|
|
1006
|
+
bg-pixelforge-white dark:bg-pixelforge-dark
|
|
1007
|
+
text-pixelforge-black dark:text-pixelforge-white
|
|
1008
|
+
border-t-2 border-pixelforge-darkLime dark:border-pixelforge-lime
|
|
1009
|
+
${className}
|
|
1010
|
+
`,
|
|
1011
|
+
...props,
|
|
1012
|
+
children: [
|
|
1013
|
+
(brand || sections.length > 0 || socialLinks) && /* @__PURE__ */ jsx10("div", { className: "max-w-full px-6 py-12", children: /* @__PURE__ */ jsxs10("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8", children: [
|
|
1014
|
+
brand && /* @__PURE__ */ jsxs10("div", { className: "col-span-1", children: [
|
|
1015
|
+
/* @__PURE__ */ jsx10("div", { className: "font-pixel text-lg text-pixelforge-black dark:text-pixelforge-white mb-4", children: brand }),
|
|
1016
|
+
socialLinks && /* @__PURE__ */ jsx10("div", { className: "flex gap-3", children: socialLinks })
|
|
1017
|
+
] }),
|
|
1018
|
+
sections.map((section, index) => /* @__PURE__ */ jsxs10("div", { children: [
|
|
1019
|
+
/* @__PURE__ */ jsx10("h3", { className: "font-pixel text-sm text-pixelforge-black dark:text-pixelforge-white mb-4 uppercase tracking-wider", children: section.title }),
|
|
1020
|
+
/* @__PURE__ */ jsx10("ul", { className: "space-y-3", children: section.links.map((link, linkIndex) => /* @__PURE__ */ jsx10("li", { children: /* @__PURE__ */ jsx10(
|
|
1021
|
+
"a",
|
|
1022
|
+
{
|
|
1023
|
+
href: link.href || "#",
|
|
1024
|
+
onClick: (e) => {
|
|
1025
|
+
if (link.onClick) {
|
|
1026
|
+
e.preventDefault();
|
|
1027
|
+
link.onClick();
|
|
1028
|
+
}
|
|
1029
|
+
},
|
|
1030
|
+
className: `
|
|
1031
|
+
font-mono text-sm
|
|
1032
|
+
text-pixelforge-gray dark:text-pixelforge-gray/70
|
|
1033
|
+
hover:text-pixelforge-black dark:hover:text-pixelforge-white
|
|
1034
|
+
transition-colors duration-200
|
|
1035
|
+
hover:underline
|
|
1036
|
+
`,
|
|
1037
|
+
children: link.label
|
|
1038
|
+
}
|
|
1039
|
+
) }, linkIndex)) })
|
|
1040
|
+
] }, index))
|
|
1041
|
+
] }) }),
|
|
1042
|
+
copyright && /* @__PURE__ */ jsx10("div", { className: "border-t-2 border-pixelforge-darkLime dark:border-pixelforge-lime/30 px-6 py-6 bg-pixelforge-light/50 dark:bg-pixelforge-black/20", children: /* @__PURE__ */ jsx10("p", { className: "font-mono text-xs text-pixelforge-gray dark:text-pixelforge-gray/70 text-center", children: copyright }) })
|
|
1043
|
+
]
|
|
1044
|
+
}
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
);
|
|
1048
|
+
Footer.displayName = "Footer";
|
|
1049
|
+
export {
|
|
1050
|
+
Badge,
|
|
1051
|
+
Button,
|
|
1052
|
+
Card,
|
|
1053
|
+
Dropdown,
|
|
1054
|
+
Footer,
|
|
1055
|
+
Input,
|
|
1056
|
+
Modal,
|
|
1057
|
+
Navbar,
|
|
1058
|
+
Sidebar,
|
|
1059
|
+
Tooltip,
|
|
1060
|
+
borderRadius,
|
|
1061
|
+
breakpoints,
|
|
1062
|
+
colors,
|
|
1063
|
+
gamePalettes,
|
|
1064
|
+
shadows,
|
|
1065
|
+
spacing,
|
|
1066
|
+
transitions,
|
|
1067
|
+
typography,
|
|
1068
|
+
zIndex
|
|
1069
|
+
};
|