Skip to content

Instantly share code, notes, and snippets.

@Briscoooe
Last active October 31, 2024 07:25
Show Gist options
  • Save Briscoooe/ce13faf5c02a7ae69b9cddfa654786af to your computer and use it in GitHub Desktop.
Save Briscoooe/ce13faf5c02a7ae69b9cddfa654786af to your computer and use it in GitHub Desktop.
import React, { useCallback, useState } from "react";
const EnvironmentVariables = () => {
const [variables, setVariables] = useState([{ key: '', value: '' }]);
const handleInputChange = useCallback((index, field, value) => {
setVariables((prevVariables) => {
const newVariables = [...prevVariables];
newVariables[index][field] = value;
return newVariables;
});
}, []);
const removeVariable = useCallback((index) => {
setVariables((prevVariables) => {
if (prevVariables.length === 1) {
return [{ key: '', value: '' }];
}
const newVariables = [...prevVariables];
newVariables.splice(index, 1);
return newVariables;
});
}, []);
const addVariable = useCallback(() => {
setVariables((prevVariables) => [...prevVariables, { key: '', value: '' }]);
}, []);
const isEnvFormat = useCallback((content) => {
return /^\s*\w+\s*=.*$/m.test(content);
}, []);
const parseEnvContent = useCallback((content) => {
return content
.split("\n")
.map((line) => line.trim())
.filter((line) => line && !line.startsWith("#"))
.map((line) => {
const [key, ...valueParts] = line.split("=");
let value = valueParts.join("=").trim();
if (
(value.startsWith('"') && value.endsWith('"')) ||
(value.startsWith("'") && value.endsWith("'"))
) {
value = value.slice(1, -1);
}
return { key: key.trim(), value };
});
}, []);
const handlePaste = useCallback((e, index, field) => {
const pastedText = e.clipboardData.getData('text');
if (isEnvFormat(pastedText)) {
e.preventDefault();
const parsedVariables = parseEnvContent(pastedText);
setVariables(prevVariables => {
let newVariables = [...prevVariables];
if (index < newVariables.length) {
const currentVar = newVariables[index];
if (currentVar.key === '' && currentVar.value === '') {
newVariables[index] = parsedVariables[0];
parsedVariables.shift();
}
}
const existingKeys = new Set(newVariables.map(v => v.key));
const additionalVariables = parsedVariables.filter(v => !existingKeys.has(v.key));
return [...newVariables, ...additionalVariables];
});
} else {
setVariables(prevVariables => {
const newVariables = [...prevVariables];
newVariables[index][field] = e.target.value;
return newVariables;
});
}
}, [isEnvFormat, parseEnvContent]);
return (
<div>
<div>
{variables.map((variable, index) => (
<div key={index}>
<input
type="text"
placeholder="e.g. API_KEY"
value={variable.key}
onChange={(e) => handleInputChange(index, 'key', e.target.value)}
data-field="key"
data-index={index}
onPaste={(e) => handlePaste(e, index, 'key')}
/>
<input
type="text"
placeholder="Value"
value={variable.value}
onChange={(e) => handleInputChange(index, 'value', e.target.value)}
data-field="value"
data-index={index}
/>
<button onClick={() => removeVariable(index)}>
Remove
</button>
</div>
))}
<button onClick={addVariable}>
Add new
</button>
</div>
</div>
);
};
export default EnvironmentVariables;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment