diff --git a/README.md b/README.md index d9ac956..1f50ba4 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,33 @@ This functionality is available in various file types commonly used in React dev - #### This also works with async snippets. +## Component Generation + +You can easily generate a React Component snippet by typing `fc.ComponentName` for functional components +OR `cc.ComponentName` for class components and pressing Enter. The extension automatically expands this into a properly formatted React Component. + +For example, typing `fc.ComponentName` and pressing Enter will generate: + +```javascript +const ComponentName = () => { + return ( +
+ ); +}; +``` + +## Component props support + +- For example: `fc.ComponentName[firstName, lastName]` will create: + + ```javascript + const ComponentName = ({firstName, lastName}) => { + return ( +
+ ); + }; + ``` + ### Planned Features In future updates, we plan to extend support to other React hooks, such as `useContext`, and more, following the same intuitive Emmet-like pattern for quick and efficient coding. diff --git a/package.json b/package.json index 38703b2..3b6ac15 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,10 @@ { "command": "extension.generateReactHookSnippet", "title": "Generate React Hook" + }, + { + "command": "extension.generateReactComponentSnippet", + "title": "Generate React Component" } ], "keybindings": [ @@ -37,6 +41,11 @@ "command": "extension.generateReactHookSnippet", "key": "enter", "when": "editorTextFocus && !editorReadonly && editorLangId =~ /javascript|typescript|javascriptreact|typescriptreact/ && isReactHookPattern" + }, + { + "command": "extension.generateReactComponentSnippet", + "key": "enter", + "when": "editorTextFocus && !editorReadonly && editorLangId =~ /javascript|typescript|javascriptreact|typescriptreact/ && isReactComponentPattern" } ] }, diff --git a/src/extension.ts b/src/extension.ts index aab9492..21364c9 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -8,12 +8,19 @@ export function activate(context: vscode.ExtensionContext) { if (editor) { const position = editor.selection.active; const line = editor.document.lineAt(position.line).text; - const isPatternPresent = /use(state|effect)\.\w+.*$/i.test(line); + const isReactHookPatternPresent = /use(state|effect)\.\w+.*$/i.test(line); vscode.commands.executeCommand( "setContext", "isReactHookPattern", - isPatternPresent + isReactHookPatternPresent + ); + + const isComponentPatternPresent = /(fc|cc)\.\w+.*$/i.test(line); + vscode.commands.executeCommand( + "setContext", + "isReactComponentPattern", + isComponentPatternPresent ); } }); @@ -61,7 +68,50 @@ export function activate(context: vscode.ExtensionContext) { } ); - context.subscriptions.push(disposable); + let disposable2 = vscode.commands.registerCommand( + "extension.generateReactComponentSnippet", + () => { + const editor = vscode.window.activeTextEditor; + if (!editor) { + return; + } + + const position = editor.selection.active; + const line = editor.document.lineAt(position.line).text; + + const componentRegex = /(fc|cc)\.(\w+)(\[(.*)\])?$/i; + const match = line.match(componentRegex); + + if (!match) { + return; + } + + const componentType = match[1].toLowerCase(); + const componentName = match[2]; + const componentProps = match[4]; + + let snippet = ""; + + if (componentType === "fc") { + snippet = generateFunctionalComponentSnippet( + componentName, + componentProps + ); + } else if (componentType === "cc") { + snippet = generateClassComponentSnippet(componentName); + } + + // Replace the line with the generated snippet + editor.edit((editBuilder) => { + const range = new vscode.Range( + new vscode.Position(position.line, 0), + new vscode.Position(position.line, line.length) + ); + editBuilder.replace(range, snippet); + }); + } + ); + context.subscriptions.push(disposable2); // Helper functions function capitalizeFirstLetter(string: string): string { @@ -83,4 +133,16 @@ export function activate(context: vscode.ExtensionContext) { const functionCall = isAsync ? `${functionName}();` : `${functionName}();`; return `useEffect(() => {\n ${asyncSnippet}function ${functionName}() {\n // Your code here\n }\n ${functionCall}\n}, ${dependencies});`; } + + function generateFunctionalComponentSnippet( + componentName: string, + componentProps?: string + ): string { + const props = componentProps ? `{${componentProps}}` : ""; + return `const ${componentName} = (${props}) => {\n return (\n
\n );\n};`; + } + + function generateClassComponentSnippet(componentName: string): string { + return `class ${componentName} extends React.Component {\n render() {\n return (\n
\n );\n }\n}`; + } }