gbs-add-block 0.0.51 → 0.0.52

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,4 +1,4 @@
1
- # GBS Building Blocks 2.0 (v0.0.51)
1
+ # GBS Building Blocks 2.0 (v0.0.52)
2
2
 
3
3
  Latest and upgraded version of GBS building blocks with headless UI and removed dependencies.
4
4
 
@@ -6,10 +6,9 @@ Latest and upgraded version of GBS building blocks with headless UI and removed
6
6
 
7
7
  For detailed documentation on usage and props, Please visit: [Building Block Documentation v2.0](https://blackmax-designs.gitbook.io/building-block-v2.0)
8
8
 
9
- ## What's New 🎉 (Ver 0.0.51)
9
+ ## What's New 🎉 (Ver 0.0.52)
10
10
 
11
- - Update on form renderer
12
- - Refactored Code for Better Readability
11
+ - Updated for more general installation methods
13
12
 
14
13
  ## Authors
15
14
 
package/index.js CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  const fs = require("fs-extra");
4
4
  const path = require("path");
5
- const { createInterface } = require("readline");
5
+ const yargs = require("yargs/yargs");
6
+ const { hideBin } = require("yargs/helpers");
6
7
 
7
8
  // Configuration
8
9
  const CONFIG = {
@@ -21,7 +22,8 @@ const CONFIG = {
21
22
  "Toast",
22
23
  "Uploader",
23
24
  "FormRenderer",
24
- "materialInput",
25
+ "MaterialInput",
26
+ "ContextMenu",
25
27
  ],
26
28
  frameworks: {
27
29
  next: {
@@ -37,23 +39,6 @@ const CONFIG = {
37
39
  };
38
40
 
39
41
  const SOURCE_PATH = path.join(__dirname, "source", "components");
40
- let isFirstCopy = true;
41
-
42
- const rl = createInterface({
43
- input: process.stdin,
44
- output: process.stdout,
45
- });
46
-
47
- const prompt = (question) =>
48
- new Promise((resolve) => {
49
- rl.question(question, resolve);
50
- });
51
-
52
- const displayOptions = (options, title) => {
53
- console.log(`\n${title}:\n`);
54
- options.forEach((option, index) => console.log(`${index + 1}. ${option}`));
55
- console.log("");
56
- };
57
42
 
58
43
  const copyCommonFiles = async (destPath) => {
59
44
  const commonFiles = [
@@ -66,7 +51,7 @@ const copyCommonFiles = async (destPath) => {
66
51
  const src = path.join(SOURCE_PATH, ...file.src);
67
52
  const dest = path.join(destPath, file.dest);
68
53
  await fs.copy(src, dest, { overwrite: true });
69
- console.log(`${file.dest} copied successfully to ${dest}`);
54
+ console.log(`✓ ${file.dest} copied successfully`);
70
55
  }
71
56
  };
72
57
 
@@ -80,80 +65,103 @@ const copyComponent = async (component, destPath) => {
80
65
  }
81
66
 
82
67
  await fs.copy(componentSrc, componentDest, { overwrite: true });
83
- console.log(
84
- `\nComponent ${component} copied successfully to ${componentDest}`
85
- );
86
-
87
- if (isFirstCopy) {
88
- await copyCommonFiles(destPath);
89
- isFirstCopy = false;
90
- }
91
-
92
- console.log(`\nFor Props and Usage Guides Visit: ${CONFIG.docs}\n`);
68
+ console.log(`✓ Component ${component} installed successfully`);
69
+ console.log(`\nFor documentation visit: ${CONFIG.docs}`);
93
70
  } catch (error) {
94
- console.error(`Error copying component ${component}:`, error.message);
71
+ console.error(`Error installing component ${component}:`, error.message);
72
+ process.exit(1);
95
73
  }
96
74
  };
97
75
 
98
- const selectFramework = async () => {
99
- displayOptions(
100
- Object.values(CONFIG.frameworks).map((f) => f.name),
101
- "Available frameworks"
102
- );
103
-
104
- const answer = await prompt("Select your framework (enter the number): ");
105
- const index = parseInt(answer) - 1;
106
- const frameworks = Object.keys(CONFIG.frameworks);
107
-
108
- if (isNaN(index) || index < 0 || index >= frameworks.length) {
109
- throw new Error("Invalid framework selection");
76
+ const detectFramework = () => {
77
+ // Check for Next.js
78
+ if (fs.existsSync(path.join(process.cwd(), "next.config.js"))) {
79
+ return "next";
110
80
  }
111
-
112
- return frameworks[index];
81
+ // Check for Vite
82
+ if (
83
+ fs.existsSync(path.join(process.cwd(), "vite.config.js")) ||
84
+ fs.existsSync(path.join(process.cwd(), "vite.config.ts"))
85
+ ) {
86
+ return "vite";
87
+ }
88
+ return null;
113
89
  };
114
90
 
115
- const handleComponentSelection = async (destPath) => {
116
- while (true) {
117
- displayOptions(CONFIG.components, "Available components");
91
+ const main = async () => {
92
+ const argv = yargs(hideBin(process.argv))
93
+ .option("add", {
94
+ alias: "a",
95
+ describe: "Component to install",
96
+ type: "string",
97
+ })
98
+ .option("framework", {
99
+ alias: "f",
100
+ describe: "Framework to use (next or vite)",
101
+ type: "string",
102
+ })
103
+ .option("list", {
104
+ alias: "l",
105
+ describe: "List available components",
106
+ type: "boolean",
107
+ })
108
+ .help().argv;
109
+
110
+ // List components if requested
111
+ if (argv.list) {
112
+ console.log("\nAvailable components:");
113
+ CONFIG.components.forEach((comp) => console.log(`- ${comp}`));
114
+ return;
115
+ }
118
116
 
119
- const answer = await prompt(
120
- 'Enter the number of the component to copy (or "q" to quit): '
121
- );
117
+ if (!argv.add) {
118
+ console.error("Please specify a component to install using -a or --add");
119
+ process.exit(1);
120
+ }
122
121
 
123
- if (answer.toLowerCase() === "q") break;
122
+ // Validate component name
123
+ const component = argv.add;
124
+ if (!CONFIG.components.includes(component)) {
125
+ console.error(`Invalid component: ${component}`);
126
+ console.log("\nAvailable components:");
127
+ CONFIG.components.forEach((comp) => console.log(`- ${comp}`));
128
+ process.exit(1);
129
+ }
124
130
 
125
- const index = parseInt(answer) - 1;
126
- if (isNaN(index) || index < 0 || index >= CONFIG.components.length) {
127
- console.log("Invalid selection. Please try again.");
128
- continue;
131
+ // Detect or get framework
132
+ let framework = argv.framework;
133
+ if (!framework) {
134
+ framework = detectFramework();
135
+ if (!framework) {
136
+ console.error(
137
+ "Could not detect framework. Please specify using -f or --framework"
138
+ );
139
+ process.exit(1);
129
140
  }
130
-
131
- await copyComponent(CONFIG.components[index], destPath);
132
-
133
- const continueAnswer = await prompt(
134
- "Do you want to copy another component? (y/n): "
135
- );
136
- if (continueAnswer.toLowerCase() !== "y") break;
137
141
  }
138
- };
139
142
 
140
- const main = async () => {
141
- try {
142
- const framework = await selectFramework();
143
- const destPath = path.join(
144
- process.cwd(),
145
- ...CONFIG.frameworks[framework].path
146
- );
147
-
148
- await fs.ensureDir(destPath);
149
- await handleComponentSelection(destPath);
150
- } catch (error) {
151
- console.error("Error:", error.message);
143
+ if (!CONFIG.frameworks[framework]) {
144
+ console.error(`Unsupported framework: ${framework}`);
152
145
  process.exit(1);
153
- } finally {
154
- rl.close();
155
146
  }
147
+
148
+ // Create destination directory
149
+ const destPath = path.join(
150
+ process.cwd(),
151
+ ...CONFIG.frameworks[framework].path
152
+ );
153
+ await fs.ensureDir(destPath);
154
+
155
+ // Copy common files if they don't exist
156
+ if (!fs.existsSync(path.join(destPath, "utils.ts"))) {
157
+ await copyCommonFiles(destPath);
158
+ }
159
+
160
+ // Copy the requested component
161
+ await copyComponent(component, destPath);
156
162
  };
157
163
 
158
- // Run the script
159
- main();
164
+ main().catch((error) => {
165
+ console.error("Error:", error.message);
166
+ process.exit(1);
167
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gbs-add-block",
3
- "version": "0.0.51",
3
+ "version": "0.0.52",
4
4
  "description": "React Component Library",
5
5
  "files": [
6
6
  "index.js",
@@ -20,7 +20,8 @@
20
20
  "license": "ISC",
21
21
  "dependencies": {
22
22
  "fs-extra": "^11.2.0",
23
- "path": "^0.12.7"
23
+ "path": "^0.12.7",
24
+ "yargs": "^17.7.2"
24
25
  },
25
26
  "devDependencies": {
26
27
  "@types/fs-extra": "^11.0.4"
@@ -0,0 +1,30 @@
1
+ import { ContextMenuItemProps } from "./types";
2
+
3
+ export const ContextMenuItem: React.FC<ContextMenuItemProps> = ({
4
+ onClick,
5
+ icon,
6
+ children,
7
+ disabled = false,
8
+ }) => (
9
+ <button
10
+ onClick={(e: React.MouseEvent) => {
11
+ e.stopPropagation();
12
+ if (!disabled) {
13
+ onClick?.();
14
+ }
15
+ }}
16
+ disabled={disabled}
17
+ className={`w-full px-4 py-2 text-left flex items-center gap-2 ${
18
+ disabled
19
+ ? "text-gray-400 cursor-not-allowed"
20
+ : "hover:bg-gray-100 cursor-pointer"
21
+ }`}
22
+ >
23
+ {icon && <span className="w-4 h-4">{icon}</span>}
24
+ {children}
25
+ </button>
26
+ );
27
+
28
+ export const ContextMenuDivider: React.FC = () => (
29
+ <div className="my-1 border-t border-gray-200" />
30
+ );
@@ -0,0 +1,63 @@
1
+ import React, { useState, useEffect, useCallback, MouseEvent } from "react";
2
+ import { ContextMenuProps, Position } from "./types";
3
+
4
+ export const ContextMenu: React.FC<ContextMenuProps> = ({ children }) => {
5
+ const [isVisible, setIsVisible] = useState<boolean>(false);
6
+ const [position, setPosition] = useState<Position>({ x: 0, y: 0 });
7
+
8
+ const handleContextMenu = useCallback(
9
+ (event: MouseEvent | globalThis.MouseEvent) => {
10
+ event.preventDefault();
11
+ setIsVisible(true);
12
+ setPosition({
13
+ x: event.pageX,
14
+ y: event.pageY,
15
+ });
16
+ },
17
+ []
18
+ );
19
+
20
+ const handleClick = useCallback(() => {
21
+ if (isVisible) setIsVisible(false);
22
+ }, [isVisible]);
23
+
24
+ useEffect(() => {
25
+ document.addEventListener("click", handleClick);
26
+ document.addEventListener("contextmenu", handleContextMenu);
27
+
28
+ return () => {
29
+ document.removeEventListener("click", handleClick);
30
+ document.removeEventListener("contextmenu", handleContextMenu);
31
+ };
32
+ }, [handleClick, handleContextMenu]);
33
+
34
+ // Ensure menu stays within viewport bounds
35
+ const adjustedPosition = useCallback((position: Position): Position => {
36
+ const menuWidth = 160; // min-width from CSS
37
+ const menuHeight = 200; // approximate max height
38
+
39
+ return {
40
+ x: Math.min(position.x, window.innerWidth - menuWidth),
41
+ y: Math.min(position.y, window.innerHeight - menuHeight),
42
+ };
43
+ }, []);
44
+
45
+ const finalPosition = adjustedPosition(position);
46
+
47
+ return (
48
+ <>
49
+ {isVisible && (
50
+ <div
51
+ className="fixed bg-white rounded-lg shadow-lg border border-gray-200 py-2 min-w-[160px]"
52
+ style={{
53
+ top: finalPosition.y,
54
+ left: finalPosition.x,
55
+ zIndex: 1000,
56
+ }}
57
+ >
58
+ {children}
59
+ </div>
60
+ )}
61
+ </>
62
+ );
63
+ };
@@ -0,0 +1,19 @@
1
+ import { ReactNode } from "react";
2
+
3
+ interface Position {
4
+ x: number;
5
+ y: number;
6
+ }
7
+
8
+ interface ContextMenuProps {
9
+ children: ReactNode;
10
+ }
11
+
12
+ interface ContextMenuItemProps {
13
+ onClick?: () => void;
14
+ icon?: ReactNode;
15
+ children: ReactNode;
16
+ disabled?: boolean;
17
+ }
18
+
19
+ export type { Position, ContextMenuProps, ContextMenuItemProps };