@raydenui/ui 0.3.0 → 0.4.1

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 CHANGED
@@ -1,13 +1,21 @@
1
+ <picture>
2
+ <source media="(prefers-color-scheme: dark)" srcset="./public/MacBook Air - 17.png">
3
+ <source media="(prefers-color-scheme: light)" srcset="./public/MacBook Air - 17.png">
4
+ <img alt="Rayden UI - Build UI faster. A React UI system designed for humans and AI." src="./public/MacBook Air - 17.png" width="100%">
5
+ </picture>
6
+
1
7
  # Rayden UI
2
8
 
3
- A modern, accessible React component library built with Tailwind CSS v4. Rayden UI brings the [Rayna UI](https://www.figma.com/community/file/1229854793310881425) Figma design system to life with pixel-perfect React components.
9
+ A modern, accessible React component library built with Tailwind CSS v4. Rayden UI brings the [Rayna UI](https://www.raynaui.com/) Figma design system to life with pixel-perfect React components.
4
10
 
5
11
  [![npm version](https://img.shields.io/npm/v/@raydenui/ui.svg)](https://www.npmjs.com/package/@raydenui/ui)
6
12
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
13
 
8
14
  ## Features
9
15
 
10
- - **15+ Production-Ready Components** — Buttons, Inputs, Tabs, Alerts, and more
16
+ - **24+ Production-Ready Components** — Buttons, Inputs, Tables, Selects, Sidebars, and more
17
+ - **Pre-built Blocks** — Login forms, notifications, tables, and more ready to drop in
18
+ - **AI Compatibility** — `@raydenui/ai` package for reliable LLM code generation
11
19
  - **Tailwind CSS v4** — Modern styling with custom design tokens
12
20
  - **Fully Typed** — Complete TypeScript support with exported types
13
21
  - **Accessible** — Built with ARIA attributes and keyboard navigation
@@ -84,10 +92,12 @@ function App() {
84
92
  | [Button](./docs/components/Button.md) | Primary action buttons with variants and icon support |
85
93
  | [ButtonGroup](./docs/components/ButtonGroup.md) | Horizontal grouping of related buttons |
86
94
  | [Input](./docs/components/Input.md) | Text input with label, helper text, and validation states |
95
+ | [Select](./docs/components/Select.md) | Dropdown select with icons, avatars, and status indicators |
87
96
  | [Checkbox](./docs/components/FormControl.md#checkbox) | Checkbox input with label and description |
88
97
  | [Radio](./docs/components/FormControl.md#radio) | Radio button input with label and description |
89
98
  | [Toggle](./docs/components/FormControl.md#toggle) | Switch/toggle input for boolean values |
90
99
  | [Chip](./docs/components/Chip.md) | Compact input tags with close/filter actions |
100
+ | [FileUpload](./docs/components/FileUpload.md) | Drag-and-drop file upload with progress and states |
91
101
 
92
102
  ### Navigation
93
103
 
@@ -96,6 +106,19 @@ function App() {
96
106
  | [Tabs](./docs/components/Tabs.md) | Tabbed navigation with line and pill variants |
97
107
  | [Breadcrumb](./docs/components/Breadcrumb.md) | Hierarchical page navigation |
98
108
  | [Pagination](./docs/components/Pagination.md) | Page navigation with prev/next controls |
109
+ | [SidebarMenu](./docs/components/SidebarMenu.md) | Collapsible sidebar navigation with sections |
110
+ | [DropdownMenu](./docs/components/DropdownMenu.md) | Accessible dropdown menu with keyboard navigation |
111
+
112
+ ### Data Display
113
+
114
+ | Component | Description |
115
+ |-----------|-------------|
116
+ | [Table](./docs/components/Table.md) | Data table with sorting, selection, and avatars |
117
+ | [Avatar](./docs/components/Avatar.md) | User avatar with image, initials, icon, and status |
118
+ | [ActivityFeed](./docs/components/ActivityFeed.md) | Activity timelines and notification feeds |
119
+ | [MetricsCard](./docs/components/MetricsCard.md) | Dashboard metric cards with 6 layout variations |
120
+ | [Icon](./docs/components/Icon.md) | 200+ icons with outline and solid variants |
121
+ | [EmptyStateIllustration](./docs/components/EmptyStateIllustration.md) | 19 empty state illustrations with custom palettes |
99
122
 
100
123
  ### Feedback
101
124
 
@@ -113,6 +136,98 @@ function App() {
113
136
  |-----------|-------------|
114
137
  | [Divider](./docs/components/Divider.md) | Content separator with optional label/button |
115
138
 
139
+ ## Blocks
140
+
141
+ Pre-built UI patterns combining multiple components for common use cases. [View all blocks →](./docs/blocks.md)
142
+
143
+ | Block | Description |
144
+ |-------|-------------|
145
+ | [LoginBlock](./docs/blocks.md#loginblock) | Complete login form with social providers |
146
+ | [NotificationsBlock](./docs/blocks.md#notificationsblock) | Notification feed with actions and timestamps |
147
+ | [TableBlock](./docs/blocks.md#tableblock) | Full-featured data table with search and filters |
148
+ | [QuickSendBlock](./docs/blocks.md#quicksendblock) | Quick send interface for payments/transfers |
149
+ | [RecentTransactionsBlock](./docs/blocks.md#recenttransactionsblock) | Transaction history display |
150
+ | [EmptyStateBlock](./docs/blocks.md#emptystateblock) | Empty state with illustration and CTA |
151
+ | [SearchableTableBlock](./docs/blocks.md#searchabletableblock) | Table with integrated search |
152
+
153
+ ```tsx
154
+ import { LoginBlock, NotificationsBlock } from "@raydenui/ui";
155
+
156
+ function App() {
157
+ return (
158
+ <LoginBlock
159
+ variant="split"
160
+ onSubmit={handleLogin}
161
+ socialProviders={["google", "github"]}
162
+ />
163
+ );
164
+ }
165
+ ```
166
+
167
+ ## AI Integration
168
+
169
+ The `@raydenui/ai` package enables LLMs to reliably generate Rayden UI code without hallucination.
170
+
171
+ ```bash
172
+ # Run directly with npx (no install needed)
173
+ npx @raydenui/ai
174
+
175
+ # Or install globally
176
+ npm install -g @raydenui/ai
177
+ ```
178
+
179
+ ### Features
180
+
181
+ - **Component Manifests** — Structured definitions of all components, props, and examples
182
+ - **Design Tokens** — Complete token system in JSON format
183
+ - **Composition Rules** — Guidelines for combining components correctly
184
+ - **MCP Server** — Model Context Protocol server for AI assistants
185
+
186
+ ### Claude Desktop Integration
187
+
188
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
189
+
190
+ ```json
191
+ {
192
+ "mcpServers": {
193
+ "rayden-ai": {
194
+ "command": "npx",
195
+ "args": ["@raydenui/ai"]
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
201
+ ### Claude Code Integration
202
+
203
+ Add to your project's `.mcp.json`:
204
+
205
+ ```json
206
+ {
207
+ "mcpServers": {
208
+ "rayden-ai": {
209
+ "command": "npx",
210
+ "args": ["@raydenui/ai"]
211
+ }
212
+ }
213
+ }
214
+ ```
215
+
216
+ ### Programmatic Usage
217
+
218
+ ```tsx
219
+ import { getComponentManifest, getAllManifests } from "@raydenui/ai/manifests";
220
+ import { tokens } from "@raydenui/ai/tokens";
221
+
222
+ // Get all component definitions
223
+ const manifests = getAllManifests();
224
+
225
+ // Get a specific component
226
+ const buttonManifest = getComponentManifest("Button");
227
+ ```
228
+
229
+ See the full [AI Integration Guide](./docs/rayden-ai.md) for setup instructions.
230
+
116
231
  ## Design Tokens
117
232
 
118
233
  Rayden UI includes a complete design token system extracted from the Rayna UI Figma design system.
@@ -236,4 +351,4 @@ MIT License - see [LICENSE](./LICENSE) for details.
236
351
 
237
352
  ---
238
353
 
239
- Made with care for the React community.
354
+ Made with care for the React community. By Ovalay Studios (https://ovalay.studio)
package/dist/index.cjs CHANGED
@@ -12399,7 +12399,294 @@ var SelectOption = react.forwardRef(
12399
12399
  }
12400
12400
  );
12401
12401
  SelectOption.displayName = "SelectOption";
12402
+ var ActivityItem = react.forwardRef(
12403
+ ({
12404
+ avatar,
12405
+ text,
12406
+ unread = false,
12407
+ date,
12408
+ time,
12409
+ link,
12410
+ badge,
12411
+ connector,
12412
+ children,
12413
+ className,
12414
+ ...rest
12415
+ }, ref) => {
12416
+ const hasConnectorAbove = connector === "middle" || connector === "last";
12417
+ const hasConnectorBelow = connector === "top" || connector === "middle";
12418
+ return /* @__PURE__ */ jsxRuntime.jsxs(
12419
+ "div",
12420
+ {
12421
+ ref,
12422
+ className: cn("flex gap-3 items-start", className),
12423
+ ...rest,
12424
+ children: [
12425
+ /* @__PURE__ */ jsxRuntime.jsxs(
12426
+ "div",
12427
+ {
12428
+ className: cn(
12429
+ "flex flex-col items-center shrink-0 gap-1 self-stretch",
12430
+ (connector === "last" || !connector) && "justify-start"
12431
+ ),
12432
+ children: [
12433
+ hasConnectorAbove && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-px bg-grey-100" }),
12434
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 size-8", children: avatar }),
12435
+ hasConnectorBelow && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-px bg-grey-100" })
12436
+ ]
12437
+ }
12438
+ ),
12439
+ /* @__PURE__ */ jsxRuntime.jsxs(
12440
+ "div",
12441
+ {
12442
+ className: cn(
12443
+ "flex flex-1 flex-col gap-3 items-start min-w-0",
12444
+ !connector && "",
12445
+ connector === "top" && "pb-4",
12446
+ (connector === "middle" || connector === "last") && "py-4"
12447
+ ),
12448
+ children: [
12449
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 w-full", children: [
12450
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between w-full", children: [
12451
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 items-start gap-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-body-sm leading-5 text-grey-600", children: text }) }),
12452
+ unread && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 size-2 rounded-full bg-[#04802E] border-[1.5px] border-white" })
12453
+ ] }),
12454
+ (date || time || link || badge) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-1 w-full", children: [
12455
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 items-start min-w-0", children: [
12456
+ date && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-grey-400 whitespace-nowrap", children: date }),
12457
+ link && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
12458
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-grey-400 whitespace-nowrap", children: "\u30FB" }),
12459
+ link.href ? /* @__PURE__ */ jsxRuntime.jsx(
12460
+ "a",
12461
+ {
12462
+ href: link.href,
12463
+ onClick: link.onClick,
12464
+ className: "text-xs font-medium text-primary-400 underline whitespace-nowrap",
12465
+ children: link.label
12466
+ }
12467
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
12468
+ "button",
12469
+ {
12470
+ type: "button",
12471
+ onClick: link.onClick,
12472
+ className: "text-xs font-medium text-primary-400 underline whitespace-nowrap",
12473
+ children: link.label
12474
+ }
12475
+ )
12476
+ ] }),
12477
+ badge && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
12478
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-grey-400 whitespace-nowrap", children: "\u30FB" }),
12479
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center justify-center rounded-full bg-primary-400 px-2 text-xs font-medium text-white whitespace-nowrap", children: badge })
12480
+ ] })
12481
+ ] }),
12482
+ time && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-xs text-grey-400 whitespace-nowrap", children: time })
12483
+ ] })
12484
+ ] }),
12485
+ children
12486
+ ]
12487
+ }
12488
+ )
12489
+ ]
12490
+ }
12491
+ );
12492
+ }
12493
+ );
12494
+ ActivityItem.displayName = "ActivityItem";
12495
+ var styleClasses = {
12496
+ plain: "",
12497
+ card: "bg-white rounded-lg p-2 shadow-[0px_2px_5px_-2px_rgba(16,25,40,0.06),0px_2px_7px_0px_rgba(16,25,40,0.05),0px_0px_0px_1px_rgba(16,25,40,0.05)]",
12498
+ container: "bg-grey-50 border border-grey-100 rounded-lg p-3"
12499
+ };
12500
+ var ActivityContent = react.forwardRef(
12501
+ ({
12502
+ variant,
12503
+ contentStyle = "card",
12504
+ // File props
12505
+ icon,
12506
+ title,
12507
+ size,
12508
+ fileType,
12509
+ date,
12510
+ // Comment props
12511
+ avatar,
12512
+ author,
12513
+ timestamp,
12514
+ comment,
12515
+ attachments,
12516
+ reactions,
12517
+ replies,
12518
+ onReply,
12519
+ // CTA props
12520
+ primaryAction,
12521
+ secondaryAction,
12522
+ className,
12523
+ ...rest
12524
+ }, ref) => {
12525
+ if (variant === "file") {
12526
+ return /* @__PURE__ */ jsxRuntime.jsxs(
12527
+ "div",
12528
+ {
12529
+ ref,
12530
+ className: cn(
12531
+ "flex items-center gap-2",
12532
+ styleClasses[contentStyle],
12533
+ className
12534
+ ),
12535
+ ...rest,
12536
+ children: [
12537
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center justify-center size-8 rounded-lg bg-primary-50", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-4", children: resolveIcon(icon ?? "file", "sm") }) }),
12538
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start", children: [
12539
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
12540
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-grey-700 whitespace-nowrap", children: title }),
12541
+ size && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
12542
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-0.5 rounded-full bg-grey-400" }),
12543
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-grey-400 whitespace-nowrap", children: size })
12544
+ ] })
12545
+ ] }),
12546
+ (fileType || date) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
12547
+ fileType && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-grey-400 whitespace-nowrap", children: fileType }),
12548
+ fileType && date && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-0.5 rounded-full bg-grey-400" }),
12549
+ date && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-grey-400 whitespace-nowrap", children: date })
12550
+ ] })
12551
+ ] })
12552
+ ]
12553
+ }
12554
+ );
12555
+ }
12556
+ if (variant === "comment") {
12557
+ contentStyle === "plain" ? "flex gap-2 items-start" : cn("flex flex-col gap-2", styleClasses[contentStyle]);
12558
+ const commentContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
12559
+ (avatar || author) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 w-full", children: [
12560
+ avatar && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 size-5", children: avatar }),
12561
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
12562
+ author && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-body-sm font-medium text-grey-700 whitespace-nowrap", children: author }),
12563
+ timestamp && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-grey-400 whitespace-nowrap", children: [
12564
+ "\u30FB",
12565
+ timestamp
12566
+ ] })
12567
+ ] })
12568
+ ] }),
12569
+ comment && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-body-sm text-grey-600 leading-5", children: comment }),
12570
+ attachments && attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
12571
+ attachments.slice(0, 2).map((file) => /* @__PURE__ */ jsxRuntime.jsxs(
12572
+ "div",
12573
+ {
12574
+ className: "flex items-center gap-2 rounded-lg border border-grey-100 bg-white pl-1 pr-2 py-1",
12575
+ children: [
12576
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center justify-center size-6 rounded bg-primary-50 border border-primary-50", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-3", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "file", size: "xs" }) }) }),
12577
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-grey-700 whitespace-nowrap", children: [
12578
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: file.name }),
12579
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-grey-500", children: [
12580
+ ".",
12581
+ file.extension
12582
+ ] })
12583
+ ] })
12584
+ ]
12585
+ },
12586
+ `${file.name}.${file.extension}`
12587
+ )),
12588
+ attachments.length > 2 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center size-8 rounded-lg border border-grey-100 bg-white px-2 py-1", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-semibold text-grey-700", children: [
12589
+ "+",
12590
+ attachments.length - 2
12591
+ ] }) })
12592
+ ] }),
12593
+ (reactions != null || replies != null) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
12594
+ reactions != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-grey-100 bg-white px-2 py-1", children: [
12595
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-grey-700", children: "\u{1F91D}\u{1F525}" }),
12596
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-grey-700", children: [
12597
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-semibold", children: [
12598
+ reactions,
12599
+ " "
12600
+ ] }),
12601
+ "Reactions"
12602
+ ] })
12603
+ ] }),
12604
+ replies != null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-grey-100 bg-white px-2 py-1 h-8", children: [
12605
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "message", size: "sm", className: "text-grey-400" }),
12606
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-grey-700", children: [
12607
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-semibold", children: [
12608
+ replies,
12609
+ " "
12610
+ ] }),
12611
+ "Replies"
12612
+ ] })
12613
+ ] })
12614
+ ] }),
12615
+ onReply && /* @__PURE__ */ jsxRuntime.jsx(
12616
+ "button",
12617
+ {
12618
+ type: "button",
12619
+ onClick: onReply,
12620
+ className: "inline-flex items-center justify-center rounded-lg border border-grey-300 bg-white px-3 py-1 text-xs font-semibold text-grey-700",
12621
+ children: "Reply"
12622
+ }
12623
+ )
12624
+ ] });
12625
+ if (contentStyle === "plain") {
12626
+ return /* @__PURE__ */ jsxRuntime.jsxs(
12627
+ "div",
12628
+ {
12629
+ ref,
12630
+ className: cn("flex gap-2 items-start", className),
12631
+ ...rest,
12632
+ children: [
12633
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 w-px self-stretch bg-grey-100" }),
12634
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2 items-start rounded-lg p-3", children: commentContent })
12635
+ ]
12636
+ }
12637
+ );
12638
+ }
12639
+ return /* @__PURE__ */ jsxRuntime.jsx(
12640
+ "div",
12641
+ {
12642
+ ref,
12643
+ className: cn(
12644
+ "flex flex-col gap-2 items-start",
12645
+ styleClasses[contentStyle],
12646
+ className
12647
+ ),
12648
+ ...rest,
12649
+ children: commentContent
12650
+ }
12651
+ );
12652
+ }
12653
+ if (variant === "cta") {
12654
+ return /* @__PURE__ */ jsxRuntime.jsxs(
12655
+ "div",
12656
+ {
12657
+ ref,
12658
+ className: cn("flex items-start gap-3", className),
12659
+ ...rest,
12660
+ children: [
12661
+ primaryAction && /* @__PURE__ */ jsxRuntime.jsx(
12662
+ "button",
12663
+ {
12664
+ type: "button",
12665
+ onClick: primaryAction.onClick,
12666
+ className: "inline-flex items-center justify-center rounded-lg bg-primary-500 px-4 py-2 text-body-sm font-semibold text-white",
12667
+ children: primaryAction.label
12668
+ }
12669
+ ),
12670
+ secondaryAction && /* @__PURE__ */ jsxRuntime.jsx(
12671
+ "button",
12672
+ {
12673
+ type: "button",
12674
+ onClick: secondaryAction.onClick,
12675
+ className: "inline-flex items-center justify-center rounded-lg border border-grey-300 bg-white px-4 py-2 text-body-sm font-semibold text-grey-700",
12676
+ children: secondaryAction.label
12677
+ }
12678
+ )
12679
+ ]
12680
+ }
12681
+ );
12682
+ }
12683
+ return null;
12684
+ }
12685
+ );
12686
+ ActivityContent.displayName = "ActivityContent";
12402
12687
 
12688
+ exports.ActivityContent = ActivityContent;
12689
+ exports.ActivityItem = ActivityItem;
12403
12690
  exports.Alert = Alert;
12404
12691
  exports.Avatar = Avatar;
12405
12692
  exports.AvatarGroup = AvatarGroup;