@runic-rpc/ui 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 RunicRPC Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,70 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+
4
+ interface AppShellProps {
5
+ sidebar: React.ReactNode;
6
+ topbar?: React.ReactNode;
7
+ children: React.ReactNode;
8
+ className?: string;
9
+ }
10
+ declare function AppShell({ sidebar, topbar, children, className }: AppShellProps): react_jsx_runtime.JSX.Element;
11
+
12
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
13
+ variant?: 'primary' | 'secondary';
14
+ }
15
+ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
16
+
17
+ interface DropdownMenuProps {
18
+ trigger: React.ReactNode;
19
+ children: React.ReactNode;
20
+ align?: 'left' | 'right';
21
+ }
22
+ declare function DropdownMenu({ trigger, children, align }: DropdownMenuProps): react_jsx_runtime.JSX.Element;
23
+ interface DropdownMenuItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
24
+ icon?: React.ReactNode;
25
+ }
26
+ declare const DropdownMenuItem: React.ForwardRefExoticComponent<DropdownMenuItemProps & React.RefAttributes<HTMLButtonElement>>;
27
+
28
+ interface EmptyStateProps {
29
+ icon?: React.ReactNode;
30
+ title: string;
31
+ description?: string;
32
+ action?: React.ReactNode;
33
+ className?: string;
34
+ }
35
+ declare function EmptyState({ icon, title, description, action, className }: EmptyStateProps): react_jsx_runtime.JSX.Element;
36
+
37
+ interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
38
+ variant?: 'circle' | 'rounded';
39
+ }
40
+ declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<HTMLButtonElement>>;
41
+
42
+ interface SidebarProps {
43
+ logo?: React.ReactNode;
44
+ children: React.ReactNode;
45
+ footer?: React.ReactNode;
46
+ className?: string;
47
+ }
48
+ declare function Sidebar({ logo, children, footer, className }: SidebarProps): react_jsx_runtime.JSX.Element;
49
+ interface SidebarItemProps {
50
+ icon?: React.ReactNode;
51
+ label: string;
52
+ active?: boolean;
53
+ href?: string;
54
+ onClick?: () => void;
55
+ }
56
+ declare function SidebarItem({ icon, label, active, href, onClick }: SidebarItemProps): react_jsx_runtime.JSX.Element;
57
+
58
+ interface TopbarProps {
59
+ leftContent?: React.ReactNode;
60
+ rightContent?: React.ReactNode;
61
+ className?: string;
62
+ }
63
+ declare function Topbar({ leftContent, rightContent, className }: TopbarProps): react_jsx_runtime.JSX.Element;
64
+
65
+ /**
66
+ * Lightweight class name merger (like clsx but simpler)
67
+ */
68
+ declare function cn(...inputs: (string | undefined | null | false)[]): string;
69
+
70
+ export { AppShell, type AppShellProps, Button, type ButtonProps, DropdownMenu, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuProps, EmptyState, type EmptyStateProps, IconButton, type IconButtonProps, Sidebar, SidebarItem, type SidebarItemProps, type SidebarProps, Topbar, type TopbarProps, cn };
@@ -0,0 +1,70 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+
4
+ interface AppShellProps {
5
+ sidebar: React.ReactNode;
6
+ topbar?: React.ReactNode;
7
+ children: React.ReactNode;
8
+ className?: string;
9
+ }
10
+ declare function AppShell({ sidebar, topbar, children, className }: AppShellProps): react_jsx_runtime.JSX.Element;
11
+
12
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
13
+ variant?: 'primary' | 'secondary';
14
+ }
15
+ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
16
+
17
+ interface DropdownMenuProps {
18
+ trigger: React.ReactNode;
19
+ children: React.ReactNode;
20
+ align?: 'left' | 'right';
21
+ }
22
+ declare function DropdownMenu({ trigger, children, align }: DropdownMenuProps): react_jsx_runtime.JSX.Element;
23
+ interface DropdownMenuItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
24
+ icon?: React.ReactNode;
25
+ }
26
+ declare const DropdownMenuItem: React.ForwardRefExoticComponent<DropdownMenuItemProps & React.RefAttributes<HTMLButtonElement>>;
27
+
28
+ interface EmptyStateProps {
29
+ icon?: React.ReactNode;
30
+ title: string;
31
+ description?: string;
32
+ action?: React.ReactNode;
33
+ className?: string;
34
+ }
35
+ declare function EmptyState({ icon, title, description, action, className }: EmptyStateProps): react_jsx_runtime.JSX.Element;
36
+
37
+ interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
38
+ variant?: 'circle' | 'rounded';
39
+ }
40
+ declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<HTMLButtonElement>>;
41
+
42
+ interface SidebarProps {
43
+ logo?: React.ReactNode;
44
+ children: React.ReactNode;
45
+ footer?: React.ReactNode;
46
+ className?: string;
47
+ }
48
+ declare function Sidebar({ logo, children, footer, className }: SidebarProps): react_jsx_runtime.JSX.Element;
49
+ interface SidebarItemProps {
50
+ icon?: React.ReactNode;
51
+ label: string;
52
+ active?: boolean;
53
+ href?: string;
54
+ onClick?: () => void;
55
+ }
56
+ declare function SidebarItem({ icon, label, active, href, onClick }: SidebarItemProps): react_jsx_runtime.JSX.Element;
57
+
58
+ interface TopbarProps {
59
+ leftContent?: React.ReactNode;
60
+ rightContent?: React.ReactNode;
61
+ className?: string;
62
+ }
63
+ declare function Topbar({ leftContent, rightContent, className }: TopbarProps): react_jsx_runtime.JSX.Element;
64
+
65
+ /**
66
+ * Lightweight class name merger (like clsx but simpler)
67
+ */
68
+ declare function cn(...inputs: (string | undefined | null | false)[]): string;
69
+
70
+ export { AppShell, type AppShellProps, Button, type ButtonProps, DropdownMenu, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuProps, EmptyState, type EmptyStateProps, IconButton, type IconButtonProps, Sidebar, SidebarItem, type SidebarItemProps, type SidebarProps, Topbar, type TopbarProps, cn };
package/dist/index.js ADDED
@@ -0,0 +1,282 @@
1
+ "use client";
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var index_exports = {};
33
+ __export(index_exports, {
34
+ AppShell: () => AppShell,
35
+ Button: () => Button,
36
+ DropdownMenu: () => DropdownMenu,
37
+ DropdownMenuItem: () => DropdownMenuItem,
38
+ EmptyState: () => EmptyState,
39
+ IconButton: () => IconButton,
40
+ Sidebar: () => Sidebar,
41
+ SidebarItem: () => SidebarItem,
42
+ Topbar: () => Topbar,
43
+ cn: () => cn
44
+ });
45
+ module.exports = __toCommonJS(index_exports);
46
+
47
+ // src/lib/utils.ts
48
+ function cn(...inputs) {
49
+ return inputs.filter(Boolean).join(" ");
50
+ }
51
+
52
+ // src/components/AppShell.tsx
53
+ var import_jsx_runtime = require("react/jsx-runtime");
54
+ function AppShell({ sidebar, topbar, children, className }) {
55
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cn("flex h-screen bg-dark-bg", className), children: [
56
+ sidebar,
57
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 flex flex-col overflow-hidden", children: [
58
+ topbar,
59
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("main", { className: "flex-1 overflow-y-auto", children })
60
+ ] })
61
+ ] });
62
+ }
63
+
64
+ // src/components/Button.tsx
65
+ var React = __toESM(require("react"));
66
+ var import_jsx_runtime2 = require("react/jsx-runtime");
67
+ var Button = React.forwardRef(
68
+ ({ className, variant = "primary", ...props }, ref) => {
69
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
70
+ "button",
71
+ {
72
+ ref,
73
+ className: cn(
74
+ "px-6 py-3 text-sm font-medium rounded-lg transition-all duration-200",
75
+ "focus:outline-none focus:ring-2 focus:ring-cyan-primary focus:ring-offset-2 focus:ring-offset-dark-bg",
76
+ "disabled:opacity-50 disabled:cursor-not-allowed",
77
+ variant === "primary" && "bg-dark-elevated border border-border-light text-text-primary hover:border-cyan-primary",
78
+ variant === "secondary" && "bg-transparent border border-border-dark text-text-secondary hover:bg-dark-elevated",
79
+ className
80
+ ),
81
+ ...props
82
+ }
83
+ );
84
+ }
85
+ );
86
+ Button.displayName = "Button";
87
+
88
+ // src/components/DropdownMenu.tsx
89
+ var React2 = __toESM(require("react"));
90
+ var import_jsx_runtime3 = require("react/jsx-runtime");
91
+ function DropdownMenu({ trigger, children, align = "right" }) {
92
+ const [open, setOpen] = React2.useState(false);
93
+ const dropdownRef = React2.useRef(null);
94
+ React2.useEffect(() => {
95
+ const handleClickOutside = (event) => {
96
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
97
+ setOpen(false);
98
+ }
99
+ };
100
+ if (open) {
101
+ document.addEventListener("mousedown", handleClickOutside);
102
+ }
103
+ return () => {
104
+ document.removeEventListener("mousedown", handleClickOutside);
105
+ };
106
+ }, [open]);
107
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
108
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { onClick: () => setOpen(!open), children: trigger }),
109
+ open && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
110
+ "div",
111
+ {
112
+ className: cn(
113
+ "absolute top-full mt-2 w-56 z-50",
114
+ "bg-dark-surface border border-border-dark rounded-xl shadow-lg p-2",
115
+ align === "right" ? "right-0" : "left-0"
116
+ ),
117
+ style: { boxShadow: "0 10px 40px rgba(0, 0, 0, 0.5)" },
118
+ children
119
+ }
120
+ )
121
+ ] });
122
+ }
123
+ var DropdownMenuItem = React2.forwardRef(
124
+ ({ className, icon, children, ...props }, ref) => {
125
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
126
+ "button",
127
+ {
128
+ ref,
129
+ className: cn(
130
+ "w-full h-10 px-3 flex items-center gap-3",
131
+ "text-sm font-medium text-text-secondary",
132
+ "hover:bg-dark-elevated hover:text-text-primary",
133
+ "rounded-lg transition-all duration-200",
134
+ "focus:outline-none focus:ring-2 focus:ring-cyan-primary",
135
+ className
136
+ ),
137
+ ...props,
138
+ children: [
139
+ icon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "w-5 h-5 flex-shrink-0", children: icon }),
140
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children })
141
+ ]
142
+ }
143
+ );
144
+ }
145
+ );
146
+ DropdownMenuItem.displayName = "DropdownMenuItem";
147
+
148
+ // src/components/EmptyState.tsx
149
+ var import_jsx_runtime4 = require("react/jsx-runtime");
150
+ function EmptyState({ icon, title, description, action, className }) {
151
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
152
+ "div",
153
+ {
154
+ className: cn(
155
+ "flex flex-col items-center justify-center p-12 rounded-xl",
156
+ "glassmorphism border-2 border-cyan-primary/20",
157
+ className
158
+ ),
159
+ style: {
160
+ background: "linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(77, 232, 255, 0.05) 100%)"
161
+ },
162
+ children: [
163
+ icon && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "w-20 h-20 flex items-center justify-center mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
164
+ "div",
165
+ {
166
+ className: "w-full h-full flex items-center justify-center",
167
+ style: {
168
+ clipPath: "polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%)",
169
+ border: "2px solid #00D9FF",
170
+ boxShadow: "0 0 20px rgba(0, 217, 255, 0.3)"
171
+ },
172
+ children: icon
173
+ }
174
+ ) }),
175
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "text-xl font-semibold text-text-primary mb-2", children: title }),
176
+ description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-sm text-text-secondary text-center mb-6", children: description }),
177
+ action
178
+ ]
179
+ }
180
+ );
181
+ }
182
+
183
+ // src/components/IconButton.tsx
184
+ var React3 = __toESM(require("react"));
185
+ var import_jsx_runtime5 = require("react/jsx-runtime");
186
+ var IconButton = React3.forwardRef(
187
+ ({ className, variant = "circle", ...props }, ref) => {
188
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
189
+ "button",
190
+ {
191
+ ref,
192
+ className: cn(
193
+ "w-10 h-10 flex items-center justify-center",
194
+ "bg-dark-elevated border border-border-dark",
195
+ "text-text-secondary hover:text-text-primary",
196
+ "hover:bg-dark-elevated hover:border-cyan-primary",
197
+ "transition-all duration-200",
198
+ "focus:outline-none focus:ring-2 focus:ring-cyan-primary focus:ring-offset-2 focus:ring-offset-dark-bg",
199
+ "disabled:opacity-50 disabled:cursor-not-allowed",
200
+ variant === "circle" && "rounded-full",
201
+ variant === "rounded" && "rounded-lg",
202
+ className
203
+ ),
204
+ ...props
205
+ }
206
+ );
207
+ }
208
+ );
209
+ IconButton.displayName = "IconButton";
210
+
211
+ // src/components/Sidebar.tsx
212
+ var import_jsx_runtime6 = require("react/jsx-runtime");
213
+ function Sidebar({ logo, children, footer, className }) {
214
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
215
+ "aside",
216
+ {
217
+ className: cn(
218
+ "w-64 h-screen bg-dark-surface border-r border-border-dark",
219
+ "flex flex-col",
220
+ className
221
+ ),
222
+ children: [
223
+ logo && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "p-6 border-b border-border-dark", children: logo }),
224
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("nav", { className: "flex-1 overflow-y-auto p-4", children }),
225
+ footer && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "p-4 border-t border-border-dark", children: footer })
226
+ ]
227
+ }
228
+ );
229
+ }
230
+ function SidebarItem({ icon, label, active, href, onClick }) {
231
+ const Component = href ? "a" : "button";
232
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
233
+ Component,
234
+ {
235
+ href,
236
+ onClick,
237
+ className: cn(
238
+ "w-full h-10 px-4 flex items-center gap-3 rounded-lg",
239
+ "text-sm font-medium transition-all duration-200",
240
+ active ? "bg-dark-elevated text-text-primary border-l-2 border-cyan-primary" : "text-text-secondary hover:bg-dark-elevated hover:text-text-primary",
241
+ "focus:outline-none focus:ring-2 focus:ring-cyan-primary"
242
+ ),
243
+ children: [
244
+ icon && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-5 h-5 flex-shrink-0", children: icon }),
245
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: label })
246
+ ]
247
+ }
248
+ );
249
+ }
250
+
251
+ // src/components/Topbar.tsx
252
+ var import_jsx_runtime7 = require("react/jsx-runtime");
253
+ function Topbar({ leftContent, rightContent, className }) {
254
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
255
+ "header",
256
+ {
257
+ className: cn(
258
+ "h-16 border-b border-border-dark bg-dark-bg",
259
+ "flex items-center justify-between px-6",
260
+ className
261
+ ),
262
+ children: [
263
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex items-center gap-4", children: leftContent }),
264
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex items-center gap-3", children: rightContent })
265
+ ]
266
+ }
267
+ );
268
+ }
269
+ // Annotate the CommonJS export names for ESM import in node:
270
+ 0 && (module.exports = {
271
+ AppShell,
272
+ Button,
273
+ DropdownMenu,
274
+ DropdownMenuItem,
275
+ EmptyState,
276
+ IconButton,
277
+ Sidebar,
278
+ SidebarItem,
279
+ Topbar,
280
+ cn
281
+ });
282
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/lib/utils.ts","../src/components/AppShell.tsx","../src/components/Button.tsx","../src/components/DropdownMenu.tsx","../src/components/EmptyState.tsx","../src/components/IconButton.tsx","../src/components/Sidebar.tsx","../src/components/Topbar.tsx"],"sourcesContent":["export { AppShell } from './components/AppShell';\nexport type { AppShellProps } from './components/AppShell';\n\nexport { Button } from './components/Button';\nexport type { ButtonProps } from './components/Button';\n\nexport { DropdownMenu, DropdownMenuItem } from './components/DropdownMenu';\nexport type { DropdownMenuProps, DropdownMenuItemProps } from './components/DropdownMenu';\n\nexport { EmptyState } from './components/EmptyState';\nexport type { EmptyStateProps } from './components/EmptyState';\n\nexport { IconButton } from './components/IconButton';\nexport type { IconButtonProps } from './components/IconButton';\n\nexport { Sidebar, SidebarItem } from './components/Sidebar';\nexport type { SidebarProps, SidebarItemProps } from './components/Sidebar';\n\nexport { Topbar } from './components/Topbar';\nexport type { TopbarProps } from './components/Topbar';\n\nexport { cn } from './lib/utils';\n","/**\n * Lightweight class name merger (like clsx but simpler)\n */\nexport function cn(...inputs: (string | undefined | null | false)[]): string {\n return inputs.filter(Boolean).join(' ');\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface AppShellProps {\n sidebar: React.ReactNode;\n topbar?: React.ReactNode;\n children: React.ReactNode;\n className?: string;\n}\n\nexport function AppShell({ sidebar, topbar, children, className }: AppShellProps) {\n return (\n <div className={cn('flex h-screen bg-dark-bg', className)}>\n {sidebar}\n <div className=\"flex-1 flex flex-col overflow-hidden\">\n {topbar}\n <main className=\"flex-1 overflow-y-auto\">{children}</main>\n </div>\n </div>\n );\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'primary' | 'secondary';\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'primary', ...props }, ref) => {\n return (\n <button\n ref={ref}\n className={cn(\n 'px-6 py-3 text-sm font-medium rounded-lg transition-all duration-200',\n 'focus:outline-none focus:ring-2 focus:ring-cyan-primary focus:ring-offset-2 focus:ring-offset-dark-bg',\n 'disabled:opacity-50 disabled:cursor-not-allowed',\n variant === 'primary' &&\n 'bg-dark-elevated border border-border-light text-text-primary hover:border-cyan-primary',\n variant === 'secondary' &&\n 'bg-transparent border border-border-dark text-text-secondary hover:bg-dark-elevated',\n className\n )}\n {...props}\n />\n );\n }\n);\n\nButton.displayName = 'Button';\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface DropdownMenuProps {\n trigger: React.ReactNode;\n children: React.ReactNode;\n align?: 'left' | 'right';\n}\n\nexport function DropdownMenu({ trigger, children, align = 'right' }: DropdownMenuProps) {\n const [open, setOpen] = React.useState(false);\n const dropdownRef = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n\n if (open) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [open]);\n\n return (\n <div className=\"relative\" ref={dropdownRef}>\n <div onClick={() => setOpen(!open)}>{trigger}</div>\n {open && (\n <div\n className={cn(\n 'absolute top-full mt-2 w-56 z-50',\n 'bg-dark-surface border border-border-dark rounded-xl shadow-lg p-2',\n align === 'right' ? 'right-0' : 'left-0'\n )}\n style={{ boxShadow: '0 10px 40px rgba(0, 0, 0, 0.5)' }}\n >\n {children}\n </div>\n )}\n </div>\n );\n}\n\nexport interface DropdownMenuItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n icon?: React.ReactNode;\n}\n\nexport const DropdownMenuItem = React.forwardRef<HTMLButtonElement, DropdownMenuItemProps>(\n ({ className, icon, children, ...props }, ref) => {\n return (\n <button\n ref={ref}\n className={cn(\n 'w-full h-10 px-3 flex items-center gap-3',\n 'text-sm font-medium text-text-secondary',\n 'hover:bg-dark-elevated hover:text-text-primary',\n 'rounded-lg transition-all duration-200',\n 'focus:outline-none focus:ring-2 focus:ring-cyan-primary',\n className\n )}\n {...props}\n >\n {icon && <span className=\"w-5 h-5 flex-shrink-0\">{icon}</span>}\n <span>{children}</span>\n </button>\n );\n }\n);\n\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface EmptyStateProps {\n icon?: React.ReactNode;\n title: string;\n description?: string;\n action?: React.ReactNode;\n className?: string;\n}\n\nexport function EmptyState({ icon, title, description, action, className }: EmptyStateProps) {\n return (\n <div\n className={cn(\n 'flex flex-col items-center justify-center p-12 rounded-xl',\n 'glassmorphism border-2 border-cyan-primary/20',\n className\n )}\n style={{\n background:\n 'linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(77, 232, 255, 0.05) 100%)',\n }}\n >\n {icon && (\n <div className=\"w-20 h-20 flex items-center justify-center mb-4\">\n <div\n className=\"w-full h-full flex items-center justify-center\"\n style={{\n clipPath: 'polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%)',\n border: '2px solid #00D9FF',\n boxShadow: '0 0 20px rgba(0, 217, 255, 0.3)',\n }}\n >\n {icon}\n </div>\n </div>\n )}\n <h3 className=\"text-xl font-semibold text-text-primary mb-2\">{title}</h3>\n {description && <p className=\"text-sm text-text-secondary text-center mb-6\">{description}</p>}\n {action}\n </div>\n );\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'circle' | 'rounded';\n}\n\nexport const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(\n ({ className, variant = 'circle', ...props }, ref) => {\n return (\n <button\n ref={ref}\n className={cn(\n 'w-10 h-10 flex items-center justify-center',\n 'bg-dark-elevated border border-border-dark',\n 'text-text-secondary hover:text-text-primary',\n 'hover:bg-dark-elevated hover:border-cyan-primary',\n 'transition-all duration-200',\n 'focus:outline-none focus:ring-2 focus:ring-cyan-primary focus:ring-offset-2 focus:ring-offset-dark-bg',\n 'disabled:opacity-50 disabled:cursor-not-allowed',\n variant === 'circle' && 'rounded-full',\n variant === 'rounded' && 'rounded-lg',\n className\n )}\n {...props}\n />\n );\n }\n);\n\nIconButton.displayName = 'IconButton';\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface SidebarProps {\n logo?: React.ReactNode;\n children: React.ReactNode;\n footer?: React.ReactNode;\n className?: string;\n}\n\nexport function Sidebar({ logo, children, footer, className }: SidebarProps) {\n return (\n <aside\n className={cn(\n 'w-64 h-screen bg-dark-surface border-r border-border-dark',\n 'flex flex-col',\n className\n )}\n >\n {logo && <div className=\"p-6 border-b border-border-dark\">{logo}</div>}\n <nav className=\"flex-1 overflow-y-auto p-4\">{children}</nav>\n {footer && <div className=\"p-4 border-t border-border-dark\">{footer}</div>}\n </aside>\n );\n}\n\nexport interface SidebarItemProps {\n icon?: React.ReactNode;\n label: string;\n active?: boolean;\n href?: string;\n onClick?: () => void;\n}\n\nexport function SidebarItem({ icon, label, active, href, onClick }: SidebarItemProps) {\n const Component = href ? 'a' : 'button';\n\n return (\n <Component\n href={href}\n onClick={onClick}\n className={cn(\n 'w-full h-10 px-4 flex items-center gap-3 rounded-lg',\n 'text-sm font-medium transition-all duration-200',\n active\n ? 'bg-dark-elevated text-text-primary border-l-2 border-cyan-primary'\n : 'text-text-secondary hover:bg-dark-elevated hover:text-text-primary',\n 'focus:outline-none focus:ring-2 focus:ring-cyan-primary'\n )}\n >\n {icon && <span className=\"w-5 h-5 flex-shrink-0\">{icon}</span>}\n <span>{label}</span>\n </Component>\n );\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface TopbarProps {\n leftContent?: React.ReactNode;\n rightContent?: React.ReactNode;\n className?: string;\n}\n\nexport function Topbar({ leftContent, rightContent, className }: TopbarProps) {\n return (\n <header\n className={cn(\n 'h-16 border-b border-border-dark bg-dark-bg',\n 'flex items-center justify-between px-6',\n className\n )}\n >\n <div className=\"flex items-center gap-4\">{leftContent}</div>\n <div className=\"flex items-center gap-3\">{rightContent}</div>\n </header>\n );\n}\n"],"mappings":"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","names":["import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,237 @@
1
+ "use client";
2
+
3
+ // src/lib/utils.ts
4
+ function cn(...inputs) {
5
+ return inputs.filter(Boolean).join(" ");
6
+ }
7
+
8
+ // src/components/AppShell.tsx
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ function AppShell({ sidebar, topbar, children, className }) {
11
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex h-screen bg-dark-bg", className), children: [
12
+ sidebar,
13
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", children: [
14
+ topbar,
15
+ /* @__PURE__ */ jsx("main", { className: "flex-1 overflow-y-auto", children })
16
+ ] })
17
+ ] });
18
+ }
19
+
20
+ // src/components/Button.tsx
21
+ import * as React from "react";
22
+ import { jsx as jsx2 } from "react/jsx-runtime";
23
+ var Button = React.forwardRef(
24
+ ({ className, variant = "primary", ...props }, ref) => {
25
+ return /* @__PURE__ */ jsx2(
26
+ "button",
27
+ {
28
+ ref,
29
+ className: cn(
30
+ "px-6 py-3 text-sm font-medium rounded-lg transition-all duration-200",
31
+ "focus:outline-none focus:ring-2 focus:ring-cyan-primary focus:ring-offset-2 focus:ring-offset-dark-bg",
32
+ "disabled:opacity-50 disabled:cursor-not-allowed",
33
+ variant === "primary" && "bg-dark-elevated border border-border-light text-text-primary hover:border-cyan-primary",
34
+ variant === "secondary" && "bg-transparent border border-border-dark text-text-secondary hover:bg-dark-elevated",
35
+ className
36
+ ),
37
+ ...props
38
+ }
39
+ );
40
+ }
41
+ );
42
+ Button.displayName = "Button";
43
+
44
+ // src/components/DropdownMenu.tsx
45
+ import * as React2 from "react";
46
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
47
+ function DropdownMenu({ trigger, children, align = "right" }) {
48
+ const [open, setOpen] = React2.useState(false);
49
+ const dropdownRef = React2.useRef(null);
50
+ React2.useEffect(() => {
51
+ const handleClickOutside = (event) => {
52
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
53
+ setOpen(false);
54
+ }
55
+ };
56
+ if (open) {
57
+ document.addEventListener("mousedown", handleClickOutside);
58
+ }
59
+ return () => {
60
+ document.removeEventListener("mousedown", handleClickOutside);
61
+ };
62
+ }, [open]);
63
+ return /* @__PURE__ */ jsxs2("div", { className: "relative", ref: dropdownRef, children: [
64
+ /* @__PURE__ */ jsx3("div", { onClick: () => setOpen(!open), children: trigger }),
65
+ open && /* @__PURE__ */ jsx3(
66
+ "div",
67
+ {
68
+ className: cn(
69
+ "absolute top-full mt-2 w-56 z-50",
70
+ "bg-dark-surface border border-border-dark rounded-xl shadow-lg p-2",
71
+ align === "right" ? "right-0" : "left-0"
72
+ ),
73
+ style: { boxShadow: "0 10px 40px rgba(0, 0, 0, 0.5)" },
74
+ children
75
+ }
76
+ )
77
+ ] });
78
+ }
79
+ var DropdownMenuItem = React2.forwardRef(
80
+ ({ className, icon, children, ...props }, ref) => {
81
+ return /* @__PURE__ */ jsxs2(
82
+ "button",
83
+ {
84
+ ref,
85
+ className: cn(
86
+ "w-full h-10 px-3 flex items-center gap-3",
87
+ "text-sm font-medium text-text-secondary",
88
+ "hover:bg-dark-elevated hover:text-text-primary",
89
+ "rounded-lg transition-all duration-200",
90
+ "focus:outline-none focus:ring-2 focus:ring-cyan-primary",
91
+ className
92
+ ),
93
+ ...props,
94
+ children: [
95
+ icon && /* @__PURE__ */ jsx3("span", { className: "w-5 h-5 flex-shrink-0", children: icon }),
96
+ /* @__PURE__ */ jsx3("span", { children })
97
+ ]
98
+ }
99
+ );
100
+ }
101
+ );
102
+ DropdownMenuItem.displayName = "DropdownMenuItem";
103
+
104
+ // src/components/EmptyState.tsx
105
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
106
+ function EmptyState({ icon, title, description, action, className }) {
107
+ return /* @__PURE__ */ jsxs3(
108
+ "div",
109
+ {
110
+ className: cn(
111
+ "flex flex-col items-center justify-center p-12 rounded-xl",
112
+ "glassmorphism border-2 border-cyan-primary/20",
113
+ className
114
+ ),
115
+ style: {
116
+ background: "linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(77, 232, 255, 0.05) 100%)"
117
+ },
118
+ children: [
119
+ icon && /* @__PURE__ */ jsx4("div", { className: "w-20 h-20 flex items-center justify-center mb-4", children: /* @__PURE__ */ jsx4(
120
+ "div",
121
+ {
122
+ className: "w-full h-full flex items-center justify-center",
123
+ style: {
124
+ clipPath: "polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%)",
125
+ border: "2px solid #00D9FF",
126
+ boxShadow: "0 0 20px rgba(0, 217, 255, 0.3)"
127
+ },
128
+ children: icon
129
+ }
130
+ ) }),
131
+ /* @__PURE__ */ jsx4("h3", { className: "text-xl font-semibold text-text-primary mb-2", children: title }),
132
+ description && /* @__PURE__ */ jsx4("p", { className: "text-sm text-text-secondary text-center mb-6", children: description }),
133
+ action
134
+ ]
135
+ }
136
+ );
137
+ }
138
+
139
+ // src/components/IconButton.tsx
140
+ import * as React3 from "react";
141
+ import { jsx as jsx5 } from "react/jsx-runtime";
142
+ var IconButton = React3.forwardRef(
143
+ ({ className, variant = "circle", ...props }, ref) => {
144
+ return /* @__PURE__ */ jsx5(
145
+ "button",
146
+ {
147
+ ref,
148
+ className: cn(
149
+ "w-10 h-10 flex items-center justify-center",
150
+ "bg-dark-elevated border border-border-dark",
151
+ "text-text-secondary hover:text-text-primary",
152
+ "hover:bg-dark-elevated hover:border-cyan-primary",
153
+ "transition-all duration-200",
154
+ "focus:outline-none focus:ring-2 focus:ring-cyan-primary focus:ring-offset-2 focus:ring-offset-dark-bg",
155
+ "disabled:opacity-50 disabled:cursor-not-allowed",
156
+ variant === "circle" && "rounded-full",
157
+ variant === "rounded" && "rounded-lg",
158
+ className
159
+ ),
160
+ ...props
161
+ }
162
+ );
163
+ }
164
+ );
165
+ IconButton.displayName = "IconButton";
166
+
167
+ // src/components/Sidebar.tsx
168
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
169
+ function Sidebar({ logo, children, footer, className }) {
170
+ return /* @__PURE__ */ jsxs4(
171
+ "aside",
172
+ {
173
+ className: cn(
174
+ "w-64 h-screen bg-dark-surface border-r border-border-dark",
175
+ "flex flex-col",
176
+ className
177
+ ),
178
+ children: [
179
+ logo && /* @__PURE__ */ jsx6("div", { className: "p-6 border-b border-border-dark", children: logo }),
180
+ /* @__PURE__ */ jsx6("nav", { className: "flex-1 overflow-y-auto p-4", children }),
181
+ footer && /* @__PURE__ */ jsx6("div", { className: "p-4 border-t border-border-dark", children: footer })
182
+ ]
183
+ }
184
+ );
185
+ }
186
+ function SidebarItem({ icon, label, active, href, onClick }) {
187
+ const Component = href ? "a" : "button";
188
+ return /* @__PURE__ */ jsxs4(
189
+ Component,
190
+ {
191
+ href,
192
+ onClick,
193
+ className: cn(
194
+ "w-full h-10 px-4 flex items-center gap-3 rounded-lg",
195
+ "text-sm font-medium transition-all duration-200",
196
+ active ? "bg-dark-elevated text-text-primary border-l-2 border-cyan-primary" : "text-text-secondary hover:bg-dark-elevated hover:text-text-primary",
197
+ "focus:outline-none focus:ring-2 focus:ring-cyan-primary"
198
+ ),
199
+ children: [
200
+ icon && /* @__PURE__ */ jsx6("span", { className: "w-5 h-5 flex-shrink-0", children: icon }),
201
+ /* @__PURE__ */ jsx6("span", { children: label })
202
+ ]
203
+ }
204
+ );
205
+ }
206
+
207
+ // src/components/Topbar.tsx
208
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
209
+ function Topbar({ leftContent, rightContent, className }) {
210
+ return /* @__PURE__ */ jsxs5(
211
+ "header",
212
+ {
213
+ className: cn(
214
+ "h-16 border-b border-border-dark bg-dark-bg",
215
+ "flex items-center justify-between px-6",
216
+ className
217
+ ),
218
+ children: [
219
+ /* @__PURE__ */ jsx7("div", { className: "flex items-center gap-4", children: leftContent }),
220
+ /* @__PURE__ */ jsx7("div", { className: "flex items-center gap-3", children: rightContent })
221
+ ]
222
+ }
223
+ );
224
+ }
225
+ export {
226
+ AppShell,
227
+ Button,
228
+ DropdownMenu,
229
+ DropdownMenuItem,
230
+ EmptyState,
231
+ IconButton,
232
+ Sidebar,
233
+ SidebarItem,
234
+ Topbar,
235
+ cn
236
+ };
237
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/AppShell.tsx","../src/components/Button.tsx","../src/components/DropdownMenu.tsx","../src/components/EmptyState.tsx","../src/components/IconButton.tsx","../src/components/Sidebar.tsx","../src/components/Topbar.tsx"],"sourcesContent":["/**\n * Lightweight class name merger (like clsx but simpler)\n */\nexport function cn(...inputs: (string | undefined | null | false)[]): string {\n return inputs.filter(Boolean).join(' ');\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface AppShellProps {\n sidebar: React.ReactNode;\n topbar?: React.ReactNode;\n children: React.ReactNode;\n className?: string;\n}\n\nexport function AppShell({ sidebar, topbar, children, className }: AppShellProps) {\n return (\n <div className={cn('flex h-screen bg-dark-bg', className)}>\n {sidebar}\n <div className=\"flex-1 flex flex-col overflow-hidden\">\n {topbar}\n <main className=\"flex-1 overflow-y-auto\">{children}</main>\n </div>\n </div>\n );\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'primary' | 'secondary';\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'primary', ...props }, ref) => {\n return (\n <button\n ref={ref}\n className={cn(\n 'px-6 py-3 text-sm font-medium rounded-lg transition-all duration-200',\n 'focus:outline-none focus:ring-2 focus:ring-cyan-primary focus:ring-offset-2 focus:ring-offset-dark-bg',\n 'disabled:opacity-50 disabled:cursor-not-allowed',\n variant === 'primary' &&\n 'bg-dark-elevated border border-border-light text-text-primary hover:border-cyan-primary',\n variant === 'secondary' &&\n 'bg-transparent border border-border-dark text-text-secondary hover:bg-dark-elevated',\n className\n )}\n {...props}\n />\n );\n }\n);\n\nButton.displayName = 'Button';\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface DropdownMenuProps {\n trigger: React.ReactNode;\n children: React.ReactNode;\n align?: 'left' | 'right';\n}\n\nexport function DropdownMenu({ trigger, children, align = 'right' }: DropdownMenuProps) {\n const [open, setOpen] = React.useState(false);\n const dropdownRef = React.useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n\n if (open) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [open]);\n\n return (\n <div className=\"relative\" ref={dropdownRef}>\n <div onClick={() => setOpen(!open)}>{trigger}</div>\n {open && (\n <div\n className={cn(\n 'absolute top-full mt-2 w-56 z-50',\n 'bg-dark-surface border border-border-dark rounded-xl shadow-lg p-2',\n align === 'right' ? 'right-0' : 'left-0'\n )}\n style={{ boxShadow: '0 10px 40px rgba(0, 0, 0, 0.5)' }}\n >\n {children}\n </div>\n )}\n </div>\n );\n}\n\nexport interface DropdownMenuItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n icon?: React.ReactNode;\n}\n\nexport const DropdownMenuItem = React.forwardRef<HTMLButtonElement, DropdownMenuItemProps>(\n ({ className, icon, children, ...props }, ref) => {\n return (\n <button\n ref={ref}\n className={cn(\n 'w-full h-10 px-3 flex items-center gap-3',\n 'text-sm font-medium text-text-secondary',\n 'hover:bg-dark-elevated hover:text-text-primary',\n 'rounded-lg transition-all duration-200',\n 'focus:outline-none focus:ring-2 focus:ring-cyan-primary',\n className\n )}\n {...props}\n >\n {icon && <span className=\"w-5 h-5 flex-shrink-0\">{icon}</span>}\n <span>{children}</span>\n </button>\n );\n }\n);\n\nDropdownMenuItem.displayName = 'DropdownMenuItem';\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface EmptyStateProps {\n icon?: React.ReactNode;\n title: string;\n description?: string;\n action?: React.ReactNode;\n className?: string;\n}\n\nexport function EmptyState({ icon, title, description, action, className }: EmptyStateProps) {\n return (\n <div\n className={cn(\n 'flex flex-col items-center justify-center p-12 rounded-xl',\n 'glassmorphism border-2 border-cyan-primary/20',\n className\n )}\n style={{\n background:\n 'linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(77, 232, 255, 0.05) 100%)',\n }}\n >\n {icon && (\n <div className=\"w-20 h-20 flex items-center justify-center mb-4\">\n <div\n className=\"w-full h-full flex items-center justify-center\"\n style={{\n clipPath: 'polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%)',\n border: '2px solid #00D9FF',\n boxShadow: '0 0 20px rgba(0, 217, 255, 0.3)',\n }}\n >\n {icon}\n </div>\n </div>\n )}\n <h3 className=\"text-xl font-semibold text-text-primary mb-2\">{title}</h3>\n {description && <p className=\"text-sm text-text-secondary text-center mb-6\">{description}</p>}\n {action}\n </div>\n );\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: 'circle' | 'rounded';\n}\n\nexport const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(\n ({ className, variant = 'circle', ...props }, ref) => {\n return (\n <button\n ref={ref}\n className={cn(\n 'w-10 h-10 flex items-center justify-center',\n 'bg-dark-elevated border border-border-dark',\n 'text-text-secondary hover:text-text-primary',\n 'hover:bg-dark-elevated hover:border-cyan-primary',\n 'transition-all duration-200',\n 'focus:outline-none focus:ring-2 focus:ring-cyan-primary focus:ring-offset-2 focus:ring-offset-dark-bg',\n 'disabled:opacity-50 disabled:cursor-not-allowed',\n variant === 'circle' && 'rounded-full',\n variant === 'rounded' && 'rounded-lg',\n className\n )}\n {...props}\n />\n );\n }\n);\n\nIconButton.displayName = 'IconButton';\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface SidebarProps {\n logo?: React.ReactNode;\n children: React.ReactNode;\n footer?: React.ReactNode;\n className?: string;\n}\n\nexport function Sidebar({ logo, children, footer, className }: SidebarProps) {\n return (\n <aside\n className={cn(\n 'w-64 h-screen bg-dark-surface border-r border-border-dark',\n 'flex flex-col',\n className\n )}\n >\n {logo && <div className=\"p-6 border-b border-border-dark\">{logo}</div>}\n <nav className=\"flex-1 overflow-y-auto p-4\">{children}</nav>\n {footer && <div className=\"p-4 border-t border-border-dark\">{footer}</div>}\n </aside>\n );\n}\n\nexport interface SidebarItemProps {\n icon?: React.ReactNode;\n label: string;\n active?: boolean;\n href?: string;\n onClick?: () => void;\n}\n\nexport function SidebarItem({ icon, label, active, href, onClick }: SidebarItemProps) {\n const Component = href ? 'a' : 'button';\n\n return (\n <Component\n href={href}\n onClick={onClick}\n className={cn(\n 'w-full h-10 px-4 flex items-center gap-3 rounded-lg',\n 'text-sm font-medium transition-all duration-200',\n active\n ? 'bg-dark-elevated text-text-primary border-l-2 border-cyan-primary'\n : 'text-text-secondary hover:bg-dark-elevated hover:text-text-primary',\n 'focus:outline-none focus:ring-2 focus:ring-cyan-primary'\n )}\n >\n {icon && <span className=\"w-5 h-5 flex-shrink-0\">{icon}</span>}\n <span>{label}</span>\n </Component>\n );\n}\n","import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nexport interface TopbarProps {\n leftContent?: React.ReactNode;\n rightContent?: React.ReactNode;\n className?: string;\n}\n\nexport function Topbar({ leftContent, rightContent, className }: TopbarProps) {\n return (\n <header\n className={cn(\n 'h-16 border-b border-border-dark bg-dark-bg',\n 'flex items-center justify-between px-6',\n className\n )}\n >\n <div className=\"flex items-center gap-4\">{leftContent}</div>\n <div className=\"flex items-center gap-3\">{rightContent}</div>\n </header>\n );\n}\n"],"mappings":"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","names":["jsx","React","jsx","jsxs","jsx","jsxs","React","jsx","jsx","jsxs","jsx","jsxs"]}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@runic-rpc/ui",
3
+ "version": "0.1.0",
4
+ "description": "Shared UI components and design system for RunicRPC",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ },
14
+ "./styles": "./src/styles/global.css",
15
+ "./tailwind-preset": "./tailwind.preset.js"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "src/styles",
20
+ "tailwind.preset.js"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/RunicRPC/runic-rpc.git",
25
+ "directory": "packages/ui"
26
+ },
27
+ "homepage": "https://github.com/RunicRPC/runic-rpc#readme",
28
+ "bugs": {
29
+ "url": "https://github.com/RunicRPC/runic-rpc/issues"
30
+ },
31
+ "author": "RunicRPC <runic-rpc>",
32
+ "license": "MIT",
33
+ "keywords": [
34
+ "ui",
35
+ "components",
36
+ "design-system",
37
+ "react",
38
+ "tailwind"
39
+ ],
40
+ "dependencies": {
41
+ "class-variance-authority": "^0.7.0",
42
+ "lucide-react": "^0.469.0"
43
+ },
44
+ "peerDependencies": {
45
+ "react": "^18.0.0 || ^19.0.0",
46
+ "react-dom": "^18.0.0 || ^19.0.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/react": "^19.0.0",
50
+ "@types/react-dom": "^19.0.0",
51
+ "react": "^19.0.0",
52
+ "react-dom": "^19.0.0",
53
+ "tsup": "^8.0.1",
54
+ "typescript": "^5.3.3"
55
+ },
56
+ "scripts": {
57
+ "build": "tsup",
58
+ "dev": "tsup --watch",
59
+ "lint": "eslint src",
60
+ "typecheck": "tsc --noEmit",
61
+ "clean": "rm -rf dist"
62
+ }
63
+ }
@@ -0,0 +1,52 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ * {
7
+ @apply border-border-dark;
8
+ }
9
+
10
+ body {
11
+ @apply bg-dark-bg text-text-primary font-sans antialiased;
12
+ }
13
+
14
+ /* Custom scrollbar */
15
+ ::-webkit-scrollbar {
16
+ width: 12px;
17
+ height: 12px;
18
+ }
19
+
20
+ ::-webkit-scrollbar-track {
21
+ @apply bg-dark-surface;
22
+ }
23
+
24
+ ::-webkit-scrollbar-thumb {
25
+ @apply bg-cyan-primary/30 rounded-full;
26
+ }
27
+
28
+ ::-webkit-scrollbar-thumb:hover {
29
+ @apply bg-cyan-primary/50;
30
+ }
31
+
32
+ /* Firefox scrollbar */
33
+ * {
34
+ scrollbar-width: thin;
35
+ scrollbar-color: rgba(0, 217, 255, 0.3) #1A1A1A;
36
+ }
37
+
38
+ /* Selection */
39
+ ::selection {
40
+ @apply bg-cyan-primary/30 text-text-primary;
41
+ }
42
+ }
43
+
44
+ @layer utilities {
45
+ .focus-ring {
46
+ @apply ring-2 ring-cyan-primary ring-offset-2 ring-offset-dark-bg;
47
+ }
48
+
49
+ .glassmorphism {
50
+ @apply backdrop-blur-sm bg-dark-surface/50 border border-border-light;
51
+ }
52
+ }
@@ -0,0 +1,35 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ module.exports = {
3
+ theme: {
4
+ extend: {
5
+ colors: {
6
+ dark: {
7
+ bg: '#0F0F0F',
8
+ surface: '#1A1A1A',
9
+ elevated: '#242424',
10
+ },
11
+ cyan: {
12
+ primary: '#00D9FF',
13
+ light: '#4DE8FF',
14
+ glow: 'rgba(0, 217, 255, 0.15)',
15
+ },
16
+ text: {
17
+ primary: '#FFFFFF',
18
+ secondary: '#9CA3AF',
19
+ muted: '#6B7280',
20
+ },
21
+ border: {
22
+ dark: '#2A2A2A',
23
+ light: '#3A3A3A',
24
+ },
25
+ },
26
+ fontFamily: {
27
+ sans: ['Inter', 'system-ui', 'sans-serif'],
28
+ },
29
+ borderRadius: {
30
+ DEFAULT: '0.5rem',
31
+ },
32
+ },
33
+ },
34
+ plugins: [],
35
+ };