@raydenui/ui 0.3.0 → 0.4.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 CHANGED
@@ -7,7 +7,9 @@ A modern, accessible React component library built with Tailwind CSS v4. Rayden
7
7
 
8
8
  ## Features
9
9
 
10
- - **15+ Production-Ready Components** — Buttons, Inputs, Tabs, Alerts, and more
10
+ - **24+ Production-Ready Components** — Buttons, Inputs, Tables, Selects, Sidebars, and more
11
+ - **Pre-built Blocks** — Login forms, notifications, tables, and more ready to drop in
12
+ - **AI Compatibility** — `@raydenui/ai` package for reliable LLM code generation
11
13
  - **Tailwind CSS v4** — Modern styling with custom design tokens
12
14
  - **Fully Typed** — Complete TypeScript support with exported types
13
15
  - **Accessible** — Built with ARIA attributes and keyboard navigation
@@ -84,10 +86,12 @@ function App() {
84
86
  | [Button](./docs/components/Button.md) | Primary action buttons with variants and icon support |
85
87
  | [ButtonGroup](./docs/components/ButtonGroup.md) | Horizontal grouping of related buttons |
86
88
  | [Input](./docs/components/Input.md) | Text input with label, helper text, and validation states |
89
+ | [Select](./docs/components/Select.md) | Dropdown select with icons, avatars, and status indicators |
87
90
  | [Checkbox](./docs/components/FormControl.md#checkbox) | Checkbox input with label and description |
88
91
  | [Radio](./docs/components/FormControl.md#radio) | Radio button input with label and description |
89
92
  | [Toggle](./docs/components/FormControl.md#toggle) | Switch/toggle input for boolean values |
90
93
  | [Chip](./docs/components/Chip.md) | Compact input tags with close/filter actions |
94
+ | [FileUpload](./docs/components/FileUpload.md) | Drag-and-drop file upload with progress and states |
91
95
 
92
96
  ### Navigation
93
97
 
@@ -96,6 +100,19 @@ function App() {
96
100
  | [Tabs](./docs/components/Tabs.md) | Tabbed navigation with line and pill variants |
97
101
  | [Breadcrumb](./docs/components/Breadcrumb.md) | Hierarchical page navigation |
98
102
  | [Pagination](./docs/components/Pagination.md) | Page navigation with prev/next controls |
103
+ | [SidebarMenu](./docs/components/SidebarMenu.md) | Collapsible sidebar navigation with sections |
104
+ | [DropdownMenu](./docs/components/DropdownMenu.md) | Accessible dropdown menu with keyboard navigation |
105
+
106
+ ### Data Display
107
+
108
+ | Component | Description |
109
+ |-----------|-------------|
110
+ | [Table](./docs/components/Table.md) | Data table with sorting, selection, and avatars |
111
+ | [Avatar](./docs/components/Avatar.md) | User avatar with image, initials, icon, and status |
112
+ | [ActivityFeed](./docs/components/ActivityFeed.md) | Activity timelines and notification feeds |
113
+ | [MetricsCard](./docs/components/MetricsCard.md) | Dashboard metric cards with 6 layout variations |
114
+ | [Icon](./docs/components/Icon.md) | 200+ icons with outline and solid variants |
115
+ | [EmptyStateIllustration](./docs/components/EmptyStateIllustration.md) | 19 empty state illustrations with custom palettes |
99
116
 
100
117
  ### Feedback
101
118
 
@@ -113,6 +130,62 @@ function App() {
113
130
  |-----------|-------------|
114
131
  | [Divider](./docs/components/Divider.md) | Content separator with optional label/button |
115
132
 
133
+ ## Blocks
134
+
135
+ Pre-built UI patterns combining multiple components for common use cases. [View all blocks →](./docs/blocks.md)
136
+
137
+ | Block | Description |
138
+ |-------|-------------|
139
+ | [LoginBlock](./docs/blocks.md#loginblock) | Complete login form with social providers |
140
+ | [NotificationsBlock](./docs/blocks.md#notificationsblock) | Notification feed with actions and timestamps |
141
+ | [TableBlock](./docs/blocks.md#tableblock) | Full-featured data table with search and filters |
142
+ | [QuickSendBlock](./docs/blocks.md#quicksendblock) | Quick send interface for payments/transfers |
143
+ | [RecentTransactionsBlock](./docs/blocks.md#recenttransactionsblock) | Transaction history display |
144
+ | [EmptyStateBlock](./docs/blocks.md#emptystateblock) | Empty state with illustration and CTA |
145
+ | [SearchableTableBlock](./docs/blocks.md#searchabletableblock) | Table with integrated search |
146
+
147
+ ```tsx
148
+ import { LoginBlock, NotificationsBlock } from "@raydenui/ui";
149
+
150
+ function App() {
151
+ return (
152
+ <LoginBlock
153
+ variant="split"
154
+ onSubmit={handleLogin}
155
+ socialProviders={["google", "github"]}
156
+ />
157
+ );
158
+ }
159
+ ```
160
+
161
+ ## AI Integration
162
+
163
+ The `@raydenui/ai` package enables LLMs to reliably generate Rayden UI code without hallucination.
164
+
165
+ ```bash
166
+ pnpm add @raydenui/ai
167
+ ```
168
+
169
+ ### Features
170
+
171
+ - **Component Manifests** — Structured definitions of all components, props, and examples
172
+ - **Design Tokens** — Complete token system in JSON format
173
+ - **Composition Rules** — Guidelines for combining components correctly
174
+ - **MCP Server** — Model Context Protocol server for AI assistants
175
+
176
+ ### Usage with AI Assistants
177
+
178
+ Add the rules to your AI assistant's context:
179
+
180
+ ```tsx
181
+ import { RAYDEN_RULES } from "@raydenui/ai/rules";
182
+
183
+ // Or use the MCP server for Claude, Cursor, etc.
184
+ // npx rayden-ai-mcp
185
+ ```
186
+
187
+ See the full [AI Integration Guide](./docs/rayden-ai.md) for setup instructions.
188
+
116
189
  ## Design Tokens
117
190
 
118
191
  Rayden UI includes a complete design token system extracted from the Rayna UI Figma design system.
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;