@galvyn-io/design 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 ADDED
@@ -0,0 +1,316 @@
1
+ # @galvyn-io/design
2
+
3
+ Dark-first design system with monotone canvas and surgical accent color. Built for internal tools and admin panels.
4
+
5
+ Works with **Next.js + Tailwind CSS + shadcn/ui** out of the box.
6
+
7
+ ## Quick Start
8
+
9
+ ### 1. Install
10
+
11
+ ```bash
12
+ npm install @galvyn-io/design
13
+ ```
14
+
15
+ ### 2. Import CSS
16
+
17
+ In your `app/globals.css` (or wherever your global styles live):
18
+
19
+ ```css
20
+ /* Import BEFORE Tailwind directives and shadcn styles */
21
+ @import "@galvyn-io/design/css";
22
+
23
+ /* Then your existing Tailwind + shadcn imports */
24
+ @tailwind base;
25
+ @tailwind components;
26
+ @tailwind utilities;
27
+
28
+ /* Optional: set accent hue per-project */
29
+ :root {
30
+ --galvyn-accent-hue: 220; /* blue (default) */
31
+ /* Try: 180 (teal), 270 (purple), 340 (pink), 150 (green), 30 (amber) */
32
+ }
33
+ ```
34
+
35
+ ### 3. Add Tailwind Preset
36
+
37
+ In your `tailwind.config.ts`:
38
+
39
+ ```ts
40
+ import type { Config } from 'tailwindcss';
41
+ import galvynPreset from '@galvyn-io/design/preset';
42
+
43
+ export default {
44
+ presets: [galvynPreset], // ← adds galvyn-* utilities
45
+ content: [
46
+ './app/**/*.{ts,tsx}',
47
+ './components/**/*.{ts,tsx}',
48
+ // ... your paths
49
+ ],
50
+ // ... rest of your config (shadcn, etc.)
51
+ } satisfies Config;
52
+ ```
53
+
54
+ > **Note:** The preset _extends_ your config. It does NOT override shadcn or any existing utilities. All galvyn classes are namespaced with `galvyn-*`.
55
+
56
+ ### 4. Use It
57
+
58
+ ```tsx
59
+ // Tailwind classes
60
+ <div className="bg-galvyn-bg-000 text-galvyn-text-100">
61
+ <button className="bg-galvyn-accent-400 text-white rounded-galvyn-md">
62
+ Deploy
63
+ </button>
64
+ </div>
65
+
66
+ // Gradient border utility class
67
+ <div className="galvyn-border-gradient rounded-galvyn-lg bg-galvyn-surface-100 p-4">
68
+ Card with gradient border
69
+ </div>
70
+
71
+ // React components (optional)
72
+ import { Button, Card, Badge } from '@galvyn-io/design/components';
73
+
74
+ <Card border="strong">
75
+ <Badge variant="success" dot>Healthy</Badge>
76
+ <Button variant="accent">Deploy</Button>
77
+ </Card>
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Architecture
83
+
84
+ ```
85
+ @galvyn-io/design
86
+ ├── /css → CSS custom properties + utility classes (the core)
87
+ ├── /preset → Tailwind preset (extends, never overrides)
88
+ ├── /components → React primitives (Button, Card, Badge, etc.)
89
+ ├── /tokens → Token constants + helper functions
90
+ └── index → Re-exports tokens, types, helpers
91
+ ```
92
+
93
+ ### Three import paths, each independent:
94
+
95
+ | Import | What | Required? |
96
+ |--------|------|-----------|
97
+ | `@galvyn-io/design/css` | CSS variables + utility classes | **Yes** |
98
+ | `@galvyn-io/design/preset` | Tailwind preset | **Yes** (if using Tailwind) |
99
+ | `@galvyn-io/design/components` | React components | Optional |
100
+
101
+ ---
102
+
103
+ ## Accent Hue System
104
+
105
+ The entire accent palette is driven by a single CSS variable:
106
+
107
+ ```css
108
+ :root {
109
+ --galvyn-accent-hue: 220; /* Change this to rotate everything */
110
+ }
111
+ ```
112
+
113
+ | Hue | Color | Vibe |
114
+ |-----|-------|------|
115
+ | `220` | Blue | Default / Vercel |
116
+ | `180` | Teal | Cloud / infra |
117
+ | `270` | Purple | Raycast |
118
+ | `340` | Pink | Warm |
119
+ | `150` | Green | Growth |
120
+ | `30` | Amber | Alert |
121
+
122
+ You can also set it per-component or per-section:
123
+
124
+ ```tsx
125
+ import { galvynAccent } from '@galvyn-io/design';
126
+
127
+ // Different accent per project
128
+ <div style={galvynAccent('teal')}>
129
+ This section uses teal accent
130
+ </div>
131
+
132
+ // Or with a raw hue value
133
+ <div style={galvynAccent(300)}>
134
+ Custom hue
135
+ </div>
136
+ ```
137
+
138
+ ---
139
+
140
+ ## shadcn Compatibility
141
+
142
+ Galvyn is designed to coexist with shadcn/ui:
143
+
144
+ - All CSS variables are prefixed `--galvyn-*` (no collision with shadcn's `--` vars)
145
+ - The Tailwind preset uses `extend` (never replaces shadcn utilities)
146
+ - All Tailwind classes are namespaced: `bg-galvyn-*`, `text-galvyn-*`, etc.
147
+ - You can use shadcn components alongside Galvyn components
148
+
149
+ **Recommended approach:** Use shadcn for complex components (Dialog, Dropdown, etc.) and style them with Galvyn CSS variables for consistent theming.
150
+
151
+ ```tsx
152
+ // shadcn Dialog, styled with Galvyn tokens
153
+ <Dialog>
154
+ <DialogContent className="bg-galvyn-surface-100 border-galvyn-border-200">
155
+ <DialogTitle className="text-galvyn-text-000">Settings</DialogTitle>
156
+ </DialogContent>
157
+ </Dialog>
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Gradient Borders
163
+
164
+ The signature effect. Four tiers:
165
+
166
+ ```html
167
+ <!-- Subtle (default cards) -->
168
+ <div class="galvyn-border-gradient">...</div>
169
+
170
+ <!-- Medium (focused elements) -->
171
+ <div class="galvyn-border-gradient galvyn-border-gradient-medium">...</div>
172
+
173
+ <!-- Strong (accent-tinted) -->
174
+ <div class="galvyn-border-gradient galvyn-border-gradient-strong">...</div>
175
+
176
+ <!-- Accent (full gradient) -->
177
+ <div class="galvyn-border-gradient galvyn-border-gradient-accent">...</div>
178
+
179
+ <!-- Shimmer (animated, use sparingly) -->
180
+ <div class="galvyn-border-gradient galvyn-border-shimmer">...</div>
181
+ ```
182
+
183
+ Or with the React helper:
184
+
185
+ ```tsx
186
+ import { GradientBorder } from '@galvyn-io/design/components';
187
+
188
+ <GradientBorder variant="strong" className="p-4 rounded-galvyn-lg">
189
+ Premium content
190
+ </GradientBorder>
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Multi-Project Setup
196
+
197
+ Each project installs the same package but can customize:
198
+
199
+ ```
200
+ galvyn-dashboard/ → --galvyn-accent-hue: 220 (blue)
201
+ jarvis-agent/ → --galvyn-accent-hue: 180 (teal)
202
+ golf-booking-agent/ → --galvyn-accent-hue: 150 (green)
203
+ ```
204
+
205
+ When you update the package:
206
+
207
+ ```bash
208
+ # In each project
209
+ npm update @galvyn-io/design
210
+ ```
211
+
212
+ Or pin to a version in `package.json` and update when ready.
213
+
214
+ ---
215
+
216
+ ## Components
217
+
218
+ All components use CSS variables — they automatically respond to theme and accent changes.
219
+
220
+ ### Button
221
+
222
+ ```tsx
223
+ import { Button } from '@galvyn-io/design/components';
224
+
225
+ <Button variant="default" size="md">Default</Button>
226
+ <Button variant="accent">Deploy</Button>
227
+ <Button variant="danger" size="sm">Delete</Button>
228
+ <Button variant="ghost" loading>Loading...</Button>
229
+ ```
230
+
231
+ ### Badge
232
+
233
+ ```tsx
234
+ import { Badge } from '@galvyn-io/design/components';
235
+
236
+ <Badge variant="success" dot>Healthy</Badge>
237
+ <Badge variant="error">3 errors</Badge>
238
+ <Badge variant="accent">New</Badge>
239
+ ```
240
+
241
+ ### Card
242
+
243
+ ```tsx
244
+ import { Card } from '@galvyn-io/design/components';
245
+
246
+ <Card border="subtle" padding="md">Default card</Card>
247
+ <Card border="strong" padding="lg" hover>Clickable card</Card>
248
+ ```
249
+
250
+ ### Input
251
+
252
+ ```tsx
253
+ import { Input } from '@galvyn-io/design/components';
254
+
255
+ <Input label="Project" placeholder="my-project" hint="Lowercase only" />
256
+ <Input label="Endpoint" mono placeholder="https://..." />
257
+ <Input label="Region" error="Invalid region" />
258
+ ```
259
+
260
+ ### StatusDot, Kbd
261
+
262
+ ```tsx
263
+ import { StatusDot, Kbd } from '@galvyn-io/design/components';
264
+
265
+ <StatusDot status="online" label="API Gateway" />
266
+ <Kbd>⌘</Kbd><Kbd>K</Kbd>
267
+ ```
268
+
269
+ ---
270
+
271
+ ## Development
272
+
273
+ ```bash
274
+ git clone https://github.com/galvyn-io/galvyn-design.git
275
+ cd galvyn-design
276
+ npm install
277
+ npm run build # builds to dist/
278
+ npm run dev # watch mode
279
+ ```
280
+
281
+ ### Publishing
282
+
283
+ ```bash
284
+ npm run release # builds + publishes to npm
285
+ ```
286
+
287
+ ---
288
+
289
+ ## Token Reference
290
+
291
+ ### Color Tokens
292
+
293
+ | Token | Dark | Light | Usage |
294
+ |-------|------|-------|-------|
295
+ | `--galvyn-bg-000` | `#09090b` | `#ffffff` | Page background |
296
+ | `--galvyn-bg-100` | `#0c0c0e` | `#fafafa` | App background |
297
+ | `--galvyn-surface-100` | `#141416` | `#ffffff` | Card/panel bg |
298
+ | `--galvyn-surface-hover` | `#2a2a2d` | `#ededf0` | Hover state |
299
+ | `--galvyn-text-100` | `#fafafa` | `#18181b` | Primary text |
300
+ | `--galvyn-text-200` | `#a1a1aa` | `#52525b` | Secondary text |
301
+ | `--galvyn-text-300` | `#71717a` | `#71717a` | Tertiary text |
302
+ | `--galvyn-accent-400` | hsl-based | hsl-based | Primary accent |
303
+
304
+ ### Spacing (4px grid)
305
+
306
+ `space-1` = 4px, `space-2` = 8px, `space-3` = 12px, `space-4` = 16px, `space-6` = 24px, `space-8` = 32px
307
+
308
+ ### Radii
309
+
310
+ `sm` = 4px, `md` = 6px, `lg` = 8px, `xl` = 12px, `2xl` = 16px
311
+
312
+ ---
313
+
314
+ ## License
315
+
316
+ MIT
@@ -0,0 +1,134 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+
6
+ // src/components/index.tsx
7
+
8
+ // src/tokens/index.ts
9
+ function galvynBorderClass(variant = "subtle") {
10
+ if (variant === "none") return "";
11
+ const base = "galvyn-border-gradient";
12
+ if (variant === "subtle") return base;
13
+ if (variant === "shimmer") return `${base} galvyn-border-shimmer`;
14
+ return `${base} galvyn-border-gradient-${variant}`;
15
+ }
16
+ function cn(...classes) {
17
+ return classes.filter(Boolean).join(" ");
18
+ }
19
+ var GradientBorder = react.forwardRef(
20
+ ({ variant = "subtle", className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
21
+ "div",
22
+ {
23
+ ref,
24
+ className: cn(galvynBorderClass(variant), className),
25
+ ...props,
26
+ children
27
+ }
28
+ )
29
+ );
30
+ GradientBorder.displayName = "GradientBorder";
31
+ var BUTTON_VARIANT_CLASSES = {
32
+ default: "galvyn-btn-default",
33
+ secondary: "galvyn-btn-secondary",
34
+ ghost: "galvyn-btn-ghost",
35
+ accent: "galvyn-btn-accent",
36
+ danger: "galvyn-btn-danger"
37
+ };
38
+ var BUTTON_SIZE_CLASSES = {
39
+ sm: "galvyn-btn-sm",
40
+ md: "galvyn-btn-md",
41
+ lg: "galvyn-btn-lg"
42
+ };
43
+ var Button = react.forwardRef(
44
+ ({ variant = "default", size = "md", loading, icon, children, className, disabled, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
45
+ "button",
46
+ {
47
+ ref,
48
+ className: cn(
49
+ "galvyn-btn",
50
+ BUTTON_VARIANT_CLASSES[variant],
51
+ BUTTON_SIZE_CLASSES[size],
52
+ "galvyn-focus-ring galvyn-transition",
53
+ className
54
+ ),
55
+ disabled: loading || disabled,
56
+ ...props,
57
+ children: [
58
+ loading && /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}),
59
+ icon && !loading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "galvyn-btn-icon", children: icon }),
60
+ children
61
+ ]
62
+ }
63
+ )
64
+ );
65
+ Button.displayName = "Button";
66
+ var Input = react.forwardRef(
67
+ ({ label, hint, error, icon, mono, className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "galvyn-input-wrapper", children: [
68
+ label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "galvyn-input-label", children: label }),
69
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("galvyn-input-container", error && "galvyn-input-error"), children: [
70
+ icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "galvyn-input-icon", children: icon }),
71
+ /* @__PURE__ */ jsxRuntime.jsx(
72
+ "input",
73
+ {
74
+ ref,
75
+ className: cn(
76
+ "galvyn-input galvyn-focus-ring",
77
+ mono && "galvyn-input-mono",
78
+ className
79
+ ),
80
+ "aria-invalid": !!error,
81
+ ...props
82
+ }
83
+ )
84
+ ] }),
85
+ (hint || error) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("galvyn-input-hint", error && "galvyn-input-hint-error"), children: error || hint })
86
+ ] })
87
+ );
88
+ Input.displayName = "Input";
89
+ var Badge = ({
90
+ variant = "default",
91
+ size = "sm",
92
+ dot = false,
93
+ children,
94
+ className,
95
+ ...props
96
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(`galvyn-badge galvyn-badge-${variant} galvyn-badge-${size}`, className), ...props, children: [
97
+ dot && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "galvyn-badge-dot" }),
98
+ children
99
+ ] });
100
+ var Card = react.forwardRef(
101
+ ({ border = "subtle", padding = "md", hover = false, className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
102
+ "div",
103
+ {
104
+ ref,
105
+ className: cn(
106
+ "galvyn-card",
107
+ `galvyn-card-pad-${padding}`,
108
+ hover && "galvyn-card-hover",
109
+ galvynBorderClass(border),
110
+ className
111
+ ),
112
+ ...props,
113
+ children
114
+ }
115
+ )
116
+ );
117
+ Card.displayName = "Card";
118
+ var Kbd = ({ children, className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: cn("galvyn-kbd", className), ...props, children });
119
+ var StatusDot = ({ status, label, className }) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("galvyn-status", className), children: [
120
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `galvyn-status-dot galvyn-status-dot-${status}` }),
121
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "galvyn-status-label", children: label })
122
+ ] });
123
+ var Spinner = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "galvyn-spinner", width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: [
124
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "7", cy: "7", r: "5.5", stroke: "currentColor", strokeOpacity: "0.25", strokeWidth: "2" }),
125
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12.5 7a5.5 5.5 0 00-5.5-5.5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
126
+ ] });
127
+
128
+ exports.Badge = Badge;
129
+ exports.Button = Button;
130
+ exports.Card = Card;
131
+ exports.GradientBorder = GradientBorder;
132
+ exports.Input = Input;
133
+ exports.Kbd = Kbd;
134
+ exports.StatusDot = StatusDot;
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+
3
+ type GalvynVariant = 'default' | 'secondary' | 'ghost' | 'accent' | 'danger';
4
+ type GalvynSize = 'sm' | 'md' | 'lg';
5
+ type GalvynBorderGradient = 'none' | 'subtle' | 'medium' | 'strong' | 'accent' | 'shimmer';
6
+
7
+ interface GradientBorderProps extends React.HTMLAttributes<HTMLDivElement> {
8
+ variant?: GalvynBorderGradient;
9
+ as?: keyof JSX.IntrinsicElements;
10
+ }
11
+ declare const GradientBorder: React.ForwardRefExoticComponent<GradientBorderProps & React.RefAttributes<HTMLDivElement>>;
12
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
13
+ variant?: GalvynVariant;
14
+ size?: GalvynSize;
15
+ loading?: boolean;
16
+ icon?: React.ReactNode;
17
+ }
18
+ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
19
+ interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
20
+ label?: string;
21
+ hint?: string;
22
+ error?: string;
23
+ icon?: React.ReactNode;
24
+ mono?: boolean;
25
+ }
26
+ declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
27
+ interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
28
+ variant?: 'default' | 'accent' | 'success' | 'warning' | 'error';
29
+ size?: 'sm' | 'md';
30
+ dot?: boolean;
31
+ }
32
+ declare const Badge: React.FC<BadgeProps>;
33
+ interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
34
+ border?: GalvynBorderGradient;
35
+ padding?: GalvynSize;
36
+ hover?: boolean;
37
+ }
38
+ declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
39
+ declare const Kbd: React.FC<React.HTMLAttributes<HTMLElement>>;
40
+ interface StatusDotProps {
41
+ status: 'online' | 'offline' | 'warning' | 'error';
42
+ label?: string;
43
+ className?: string;
44
+ }
45
+ declare const StatusDot: React.FC<StatusDotProps>;
46
+
47
+ export { Badge, type BadgeProps, Button, type ButtonProps, Card, type CardProps, GradientBorder, type GradientBorderProps, Input, type InputProps, Kbd, StatusDot, type StatusDotProps };
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+
3
+ type GalvynVariant = 'default' | 'secondary' | 'ghost' | 'accent' | 'danger';
4
+ type GalvynSize = 'sm' | 'md' | 'lg';
5
+ type GalvynBorderGradient = 'none' | 'subtle' | 'medium' | 'strong' | 'accent' | 'shimmer';
6
+
7
+ interface GradientBorderProps extends React.HTMLAttributes<HTMLDivElement> {
8
+ variant?: GalvynBorderGradient;
9
+ as?: keyof JSX.IntrinsicElements;
10
+ }
11
+ declare const GradientBorder: React.ForwardRefExoticComponent<GradientBorderProps & React.RefAttributes<HTMLDivElement>>;
12
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
13
+ variant?: GalvynVariant;
14
+ size?: GalvynSize;
15
+ loading?: boolean;
16
+ icon?: React.ReactNode;
17
+ }
18
+ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
19
+ interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
20
+ label?: string;
21
+ hint?: string;
22
+ error?: string;
23
+ icon?: React.ReactNode;
24
+ mono?: boolean;
25
+ }
26
+ declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
27
+ interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
28
+ variant?: 'default' | 'accent' | 'success' | 'warning' | 'error';
29
+ size?: 'sm' | 'md';
30
+ dot?: boolean;
31
+ }
32
+ declare const Badge: React.FC<BadgeProps>;
33
+ interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
34
+ border?: GalvynBorderGradient;
35
+ padding?: GalvynSize;
36
+ hover?: boolean;
37
+ }
38
+ declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
39
+ declare const Kbd: React.FC<React.HTMLAttributes<HTMLElement>>;
40
+ interface StatusDotProps {
41
+ status: 'online' | 'offline' | 'warning' | 'error';
42
+ label?: string;
43
+ className?: string;
44
+ }
45
+ declare const StatusDot: React.FC<StatusDotProps>;
46
+
47
+ export { Badge, type BadgeProps, Button, type ButtonProps, Card, type CardProps, GradientBorder, type GradientBorderProps, Input, type InputProps, Kbd, StatusDot, type StatusDotProps };
@@ -0,0 +1,126 @@
1
+ import { forwardRef } from 'react';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+
4
+ // src/components/index.tsx
5
+
6
+ // src/tokens/index.ts
7
+ function galvynBorderClass(variant = "subtle") {
8
+ if (variant === "none") return "";
9
+ const base = "galvyn-border-gradient";
10
+ if (variant === "subtle") return base;
11
+ if (variant === "shimmer") return `${base} galvyn-border-shimmer`;
12
+ return `${base} galvyn-border-gradient-${variant}`;
13
+ }
14
+ function cn(...classes) {
15
+ return classes.filter(Boolean).join(" ");
16
+ }
17
+ var GradientBorder = forwardRef(
18
+ ({ variant = "subtle", className, children, ...props }, ref) => /* @__PURE__ */ jsx(
19
+ "div",
20
+ {
21
+ ref,
22
+ className: cn(galvynBorderClass(variant), className),
23
+ ...props,
24
+ children
25
+ }
26
+ )
27
+ );
28
+ GradientBorder.displayName = "GradientBorder";
29
+ var BUTTON_VARIANT_CLASSES = {
30
+ default: "galvyn-btn-default",
31
+ secondary: "galvyn-btn-secondary",
32
+ ghost: "galvyn-btn-ghost",
33
+ accent: "galvyn-btn-accent",
34
+ danger: "galvyn-btn-danger"
35
+ };
36
+ var BUTTON_SIZE_CLASSES = {
37
+ sm: "galvyn-btn-sm",
38
+ md: "galvyn-btn-md",
39
+ lg: "galvyn-btn-lg"
40
+ };
41
+ var Button = forwardRef(
42
+ ({ variant = "default", size = "md", loading, icon, children, className, disabled, ...props }, ref) => /* @__PURE__ */ jsxs(
43
+ "button",
44
+ {
45
+ ref,
46
+ className: cn(
47
+ "galvyn-btn",
48
+ BUTTON_VARIANT_CLASSES[variant],
49
+ BUTTON_SIZE_CLASSES[size],
50
+ "galvyn-focus-ring galvyn-transition",
51
+ className
52
+ ),
53
+ disabled: loading || disabled,
54
+ ...props,
55
+ children: [
56
+ loading && /* @__PURE__ */ jsx(Spinner, {}),
57
+ icon && !loading && /* @__PURE__ */ jsx("span", { className: "galvyn-btn-icon", children: icon }),
58
+ children
59
+ ]
60
+ }
61
+ )
62
+ );
63
+ Button.displayName = "Button";
64
+ var Input = forwardRef(
65
+ ({ label, hint, error, icon, mono, className, ...props }, ref) => /* @__PURE__ */ jsxs("div", { className: "galvyn-input-wrapper", children: [
66
+ label && /* @__PURE__ */ jsx("label", { className: "galvyn-input-label", children: label }),
67
+ /* @__PURE__ */ jsxs("div", { className: cn("galvyn-input-container", error && "galvyn-input-error"), children: [
68
+ icon && /* @__PURE__ */ jsx("span", { className: "galvyn-input-icon", children: icon }),
69
+ /* @__PURE__ */ jsx(
70
+ "input",
71
+ {
72
+ ref,
73
+ className: cn(
74
+ "galvyn-input galvyn-focus-ring",
75
+ mono && "galvyn-input-mono",
76
+ className
77
+ ),
78
+ "aria-invalid": !!error,
79
+ ...props
80
+ }
81
+ )
82
+ ] }),
83
+ (hint || error) && /* @__PURE__ */ jsx("span", { className: cn("galvyn-input-hint", error && "galvyn-input-hint-error"), children: error || hint })
84
+ ] })
85
+ );
86
+ Input.displayName = "Input";
87
+ var Badge = ({
88
+ variant = "default",
89
+ size = "sm",
90
+ dot = false,
91
+ children,
92
+ className,
93
+ ...props
94
+ }) => /* @__PURE__ */ jsxs("span", { className: cn(`galvyn-badge galvyn-badge-${variant} galvyn-badge-${size}`, className), ...props, children: [
95
+ dot && /* @__PURE__ */ jsx("span", { className: "galvyn-badge-dot" }),
96
+ children
97
+ ] });
98
+ var Card = forwardRef(
99
+ ({ border = "subtle", padding = "md", hover = false, className, children, ...props }, ref) => /* @__PURE__ */ jsx(
100
+ "div",
101
+ {
102
+ ref,
103
+ className: cn(
104
+ "galvyn-card",
105
+ `galvyn-card-pad-${padding}`,
106
+ hover && "galvyn-card-hover",
107
+ galvynBorderClass(border),
108
+ className
109
+ ),
110
+ ...props,
111
+ children
112
+ }
113
+ )
114
+ );
115
+ Card.displayName = "Card";
116
+ var Kbd = ({ children, className, ...props }) => /* @__PURE__ */ jsx("kbd", { className: cn("galvyn-kbd", className), ...props, children });
117
+ var StatusDot = ({ status, label, className }) => /* @__PURE__ */ jsxs("span", { className: cn("galvyn-status", className), children: [
118
+ /* @__PURE__ */ jsx("span", { className: `galvyn-status-dot galvyn-status-dot-${status}` }),
119
+ label && /* @__PURE__ */ jsx("span", { className: "galvyn-status-label", children: label })
120
+ ] });
121
+ var Spinner = () => /* @__PURE__ */ jsxs("svg", { className: "galvyn-spinner", width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: [
122
+ /* @__PURE__ */ jsx("circle", { cx: "7", cy: "7", r: "5.5", stroke: "currentColor", strokeOpacity: "0.25", strokeWidth: "2" }),
123
+ /* @__PURE__ */ jsx("path", { d: "M12.5 7a5.5 5.5 0 00-5.5-5.5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
124
+ ] });
125
+
126
+ export { Badge, Button, Card, GradientBorder, Input, Kbd, StatusDot };