modula-ui 1.0.0 → 1.0.3

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,36 +1,98 @@
1
- This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2
-
3
- ## Getting Started
4
- https://grok.com/c/8a8910e9-3c12-4eb9-8136-d8650eadb428
5
- First, run the development server:
6
-
7
- ```bash
8
- npm run dev
9
- # or
10
- yarn dev
11
- # or
12
- pnpm dev
13
- # or
14
- bun dev
15
- ```
16
-
17
- Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18
-
19
- You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
20
-
21
- This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
22
-
23
- ## Learn More
24
-
25
- To learn more about Next.js, take a look at the following resources:
26
-
27
- - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28
- - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29
-
30
- You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
31
-
32
- ## Deploy on Vercel
33
-
34
- The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35
-
36
- Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
1
+ # Modula UI
2
+
3
+ A library of modern UI patterns and complete interfaces built with [Shadcn](https://ui.shadcn.com/) and [Tailwind CSS](https://tailwindcss.com/). Get beautiful, functional UIs without building from scratch.
4
+
5
+ ## Features
6
+
7
+ - 🎨 **Complete UI Patterns** - Full-featured interfaces, not just individual components
8
+ - 🚀 **Easy Integration** - Simple CLI to add entire UI blocks to your project
9
+ - 📦 **Copy & Paste** - Browse interfaces in your browser and copy code directly
10
+ - 🎯 **Modern Stack** - Built with Next.js, React 19, and Tailwind CSS 4
11
+ - 🔧 **Customizable** - Full control over styling and behavior
12
+ - 📱 **Responsive** - Mobile-first design approach
13
+
14
+ ## 🚀 Quick Start
15
+
16
+ ### Browse UI Patterns
17
+
18
+ Run the library locally to browse all available UI patterns and interfaces:
19
+
20
+ ```bash
21
+ npx modula-ui
22
+ ```
23
+
24
+ This will start a local server at `http://localhost:3177` where you can:
25
+ - Preview all UI patterns
26
+ - Copy interface code
27
+ - See live examples
28
+
29
+ ### Add UI Patterns to Your Project
30
+
31
+ Use the CLI to add complete interfaces directly to your project:
32
+
33
+ ```bash
34
+ npx modula-ui add <component-name>
35
+ ```
36
+
37
+ The CLI will automatically:
38
+ 1. Install required dependencies
39
+ 2. Install necessary Shadcn UI components
40
+ 3. Copy the complete interface files to your project
41
+
42
+ ## 📦 Available UI Patterns
43
+
44
+ - **video-conference** - Full-featured video conferencing interface with participant grid, controls, and animations
45
+ - **group-chat** - Modern group chat interface with sidebar, message threads, and real-time feel
46
+
47
+
48
+ ## 🛠️ Installation
49
+
50
+ ### Prerequisites
51
+
52
+ - Node.js >= 18.17.0
53
+ - A Next.js or React project with Tailwind CSS configured
54
+
55
+ ### Example: Adding a UI Block
56
+
57
+ ```bash
58
+ # Add the video conference page
59
+ npx modula-ui add video-conference
60
+
61
+ # Add the group chat interface
62
+ npx modula-ui add group-chat
63
+ ```
64
+
65
+ The interface will be added to `src/library/<type>/` (or `library/<type>/` if no `src` folder exists).
66
+
67
+ ## 🎯 Usage
68
+
69
+ After adding a UI pattern, import and use it in your project:
70
+
71
+ ```jsx
72
+ import VideoConferencePage from '@/library/pages/VideoConferencePage';
73
+
74
+ export default function MyPage() {
75
+ return <VideoConferencePage />;
76
+ }
77
+ ```
78
+
79
+ ## 🏗️ Tech Stack
80
+
81
+ - **Framework:** Next.js 16
82
+ - **UI Library:** React 19
83
+ - **Styling:** Tailwind CSS 4
84
+ - **Components:** Radix UI primitives
85
+ - **Animations:** Framer Motion
86
+ - **Icons:** Lucide React
87
+ - **Charts:** Recharts
88
+
89
+ ## 📄 License
90
+
91
+ MIT © Mary Ojo
92
+
93
+
94
+ ## 🔗 Links
95
+
96
+ - [npm Package](https://www.npmjs.com/package/modula-ui)
97
+ - [Shadcn UI](https://ui.shadcn.com/)
98
+ - [Tailwind CSS](https://tailwindcss.com/)
package/bin/run.js CHANGED
@@ -6,6 +6,7 @@ import { parse } from 'url';
6
6
  import fs from 'fs/promises';
7
7
  import path from 'path';
8
8
  import { fileURLToPath } from 'url';
9
+ import { execSync } from 'child_process';
9
10
 
10
11
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
12
  const packageRoot = path.join(__dirname, '..');
@@ -13,11 +14,60 @@ const packageRoot = path.join(__dirname, '..');
13
14
  const args = process.argv.slice(2);
14
15
  const command = args[0];
15
16
 
17
+ const getPackageManager = async () => {
18
+ const userRoot = process.cwd();
19
+ try {
20
+ await fs.access(path.join(userRoot, 'pnpm-lock.yaml'));
21
+ return 'pnpm';
22
+ } catch {}
23
+ try {
24
+ await fs.access(path.join(userRoot, 'yarn.lock'));
25
+ return 'yarn';
26
+ } catch {}
27
+ try {
28
+ await fs.access(path.join(userRoot, 'bun.lockb'));
29
+ return 'bun';
30
+ } catch {}
31
+ return 'npm';
32
+ };
33
+
34
+ const installDependencies = async (dependencies) => {
35
+ if (!dependencies || dependencies.length === 0) return;
36
+
37
+ const pm = await getPackageManager();
38
+ const installCmd = pm === 'npm' ? 'install' : 'add';
39
+ const cmd = `${pm} ${installCmd} ${dependencies.join(' ')}`;
40
+
41
+ console.log(`\n📦 Installing dependencies: ${dependencies.join(', ')}...`);
42
+ try {
43
+ execSync(cmd, { stdio: 'inherit', cwd: process.cwd() });
44
+ console.log('✅ Dependencies installed.');
45
+ } catch (error) {
46
+ console.error('❌ Failed to install dependencies.');
47
+ // Don't exit, just warn
48
+ }
49
+ };
50
+
51
+ const installRegistryDependencies = (dependencies) => {
52
+ if (!dependencies || dependencies.length === 0) return;
53
+
54
+ console.log(`\n🎨 Installing UI components: ${dependencies.join(', ')}...`);
55
+ try {
56
+ // Attempt to use shadcn CLI
57
+ // We add -y to accept defaults if possible, but shadcn might still prompt
58
+ execSync(`npx shadcn@latest add ${dependencies.join(' ')} -y`, { stdio: 'inherit', cwd: process.cwd() });
59
+ console.log('✅ UI components installed.');
60
+ } catch (error) {
61
+ console.warn('⚠️ Failed to install UI components via shadcn. You might need to install them manually.');
62
+ console.warn(` Run: npx shadcn@latest add ${dependencies.join(' ')}`);
63
+ }
64
+ };
65
+
16
66
  if (command === 'add') {
17
67
  const componentName = args[1];
18
68
 
19
69
  if (!componentName) {
20
- console.error('Please specify a component name: npx nora-ui add <component-name>');
70
+ console.error('Please specify a component name: npx modula-ui add <component-name>');
21
71
  process.exit(1);
22
72
  }
23
73
 
@@ -34,10 +84,20 @@ if (command === 'add') {
34
84
  process.exit(1);
35
85
  }
36
86
 
37
- const sourcePath = path.join(packageRoot, component.path);
87
+ // 1. Install External Dependencies
88
+ if (component.dependencies) {
89
+ await installDependencies(component.dependencies);
90
+ }
91
+
92
+ // 2. Install Registry Dependencies (Shadcn components)
93
+ if (component.registryDependencies) {
94
+ installRegistryDependencies(component.registryDependencies);
95
+ }
96
+
97
+ // 3. Copy Files
98
+ const filesToCopy = component.files || [component.path];
38
99
 
39
- // Determine destination path
40
- // Check if src directory exists in the user's project
100
+ // Determine destination directory
41
101
  const userProjectRoot = process.cwd();
42
102
  const hasSrc = await fs.access(path.join(userProjectRoot, 'src')).then(() => true).catch(() => false);
43
103
 
@@ -45,16 +105,20 @@ if (command === 'add') {
45
105
  ? path.join(userProjectRoot, 'src', 'library', component.type)
46
106
  : path.join(userProjectRoot, 'library', component.type);
47
107
 
48
- const destPath = path.join(destDir, path.basename(sourcePath));
49
-
50
108
  // Ensure destination directory exists
51
109
  await fs.mkdir(destDir, { recursive: true });
52
110
 
53
- // Read and write file
54
- const content = await fs.readFile(sourcePath, 'utf-8');
55
- await fs.writeFile(destPath, content);
111
+ for (const filePath of filesToCopy) {
112
+ const sourcePath = path.join(packageRoot, filePath);
113
+ const fileName = path.basename(sourcePath);
114
+ const destPath = path.join(destDir, fileName);
56
115
 
57
- console.log(`✓ Component ${component.name} added to ${path.relative(userProjectRoot, destPath)}`);
116
+ // Read and write file
117
+ const content = await fs.readFile(sourcePath, 'utf-8');
118
+ await fs.writeFile(destPath, content);
119
+
120
+ console.log(`\n✨ Component file ${fileName} added to ${path.relative(userProjectRoot, destPath)}`);
121
+ }
58
122
 
59
123
  } catch (error) {
60
124
  console.error('Error adding component:', error);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "modula-ui",
3
- "version": "1.0.0",
4
- "description": "A library of modern interfaces with great UX built with Shadcn",
3
+ "version": "1.0.3",
4
+ "description": "A library of modern interfaces and UI patterns with great UX built with Shadcn",
5
5
  "keywords": [
6
6
  "tailwind",
7
7
  "components",
@@ -15,7 +15,7 @@
15
15
  "type": "module",
16
16
  "bin": {
17
17
  "maryojo": "./bin/run.js",
18
- "nora-ui": "./bin/run.js"
18
+ "modula-ui": "./bin/run.js"
19
19
  },
20
20
  "files": [
21
21
  "src",
@@ -68,4 +68,4 @@
68
68
  "engines": {
69
69
  "node": ">=18.17.0"
70
70
  }
71
- }
71
+ }
package/registry.json CHANGED
@@ -2,11 +2,36 @@
2
2
  "video-conference": {
3
3
  "name": "VideoConference",
4
4
  "type": "pages",
5
- "path": "src/library/pages/VideoConference/VideoConferencePage.jsx"
5
+ "path": "src/library/pages/VideoConference/VideoConferencePage.jsx",
6
+ "dependencies": [
7
+ "lucide-react",
8
+ "framer-motion",
9
+ "clsx",
10
+ "tailwind-merge"
11
+ ],
12
+ "registryDependencies": [
13
+ "avatar"
14
+ ]
6
15
  },
7
16
  "group-chat": {
8
17
  "name": "GroupChat",
9
18
  "type": "pages",
10
- "path": "src/library/pages/GroupChat/GroupChatPage.jsx"
19
+ "path": "src/library/pages/GroupChat/GroupChat.jsx",
20
+ "files": [
21
+ "src/library/pages/GroupChat/GroupChat.jsx",
22
+ "src/library/pages/GroupChat/data.js"
23
+ ],
24
+ "dependencies": [
25
+ "lucide-react"
26
+ ],
27
+ "registryDependencies": [
28
+ "sidebar",
29
+ "avatar",
30
+ "badge",
31
+ "scroll-area",
32
+ "navigation-menu",
33
+ "input",
34
+ "button"
35
+ ]
11
36
  }
12
37
  }
package/src/app/layout.js CHANGED
@@ -12,8 +12,8 @@ const geistMono = Geist_Mono({
12
12
  });
13
13
 
14
14
  export const metadata = {
15
- title: "Nora UI",
16
- description: "A library of modern interfaces with great UX built with Shadcn",
15
+ title: "Modula UI",
16
+ description: "A library of modern interfaces and UI patterns with great UX built with Shadcn",
17
17
  };
18
18
 
19
19
  export default function RootLayout({ children }) {
@@ -9,7 +9,7 @@ export default function Header({ sidebarOpen, toggleSidebar }) {
9
9
  <div className="mb-8 flex items-center justify-between">
10
10
  <div>
11
11
  <Logo />
12
- <p className="text-gray-600">A library of modern interfaces with great UX built with Shadcn</p>
12
+ <p className="text-gray-600">A library of modern interfaces and UI patterns with great UX built with Shadcn</p>
13
13
  </div>
14
14
 
15
15
  <button
@@ -3,24 +3,24 @@ import React from 'react';
3
3
  const Logo = ({ className = '' }) => {
4
4
  return (
5
5
  <svg
6
- width="180"
6
+ width="215"
7
7
  height="50"
8
- viewBox="0 0 180 50"
8
+ viewBox="0 0 215 50"
9
9
  fill="none"
10
10
  xmlns="http://www.w3.org/2000/svg"
11
11
  className={className}
12
12
  >
13
- {/* Icon Element - Abstract 'N' or Tech shape */}
13
+ {/* Icon Element - Abstract 'M' */}
14
14
  <circle cx="25" cy="25" r="20" fill="url(#grad1)" opacity="0.2" />
15
15
  <path
16
- d="M15 35V15L35 35V15"
16
+ d="M15 35V15L25 25L35 15V35"
17
17
  stroke="url(#grad2)"
18
18
  strokeWidth="4"
19
19
  strokeLinecap="round"
20
20
  strokeLinejoin="round"
21
21
  />
22
22
 
23
- {/* Text 'nora' */}
23
+ {/* Text 'modula ui' */}
24
24
  <text
25
25
  x="55"
26
26
  y="32"
@@ -30,20 +30,7 @@ const Logo = ({ className = '' }) => {
30
30
  fill="#111827"
31
31
  letterSpacing="-1"
32
32
  >
33
- nora
34
- </text>
35
-
36
- {/* Text '-ui' with different style */}
37
- <text
38
- x="115"
39
- y="32"
40
- fontFamily="system-ui, -apple-system, sans-serif"
41
- fontWeight="800"
42
- fontSize="28"
43
- fill="#111827"
44
- letterSpacing="-1"
45
- >
46
- ui
33
+ modula ui
47
34
  </text>
48
35
 
49
36
  {/* Gradients */}
@@ -5,7 +5,7 @@ import GroupChatCode from './GroupChat'
5
5
 
6
6
  export const GroupChat = {
7
7
  name: "Group Chat",
8
- code: "npx nora-ui add group-chat",
8
+ code: "npx modula-ui add group-chat",
9
9
  preview: (
10
10
  <GroupChatCode />
11
11
  )
@@ -5,7 +5,7 @@ import VideoConferencePage from './VideoConferencePage'
5
5
 
6
6
  export const VideoConference = {
7
7
  name: "Video Conference",
8
- code: "npx nora-ui add video-conference",
8
+ code: "npx modula-ui add video-conference",
9
9
  preview: (
10
10
  <VideoConferencePage />
11
11
  )