diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6854c3e8..5cf4a346 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
- Feature: GitHub source links for components via [@etchteam/storybook-addon-github-link](https://storybook.js.org/addons/@etchteam/storybook-addon-github-link) in storybook docs
- Patch: Update method of declaring Storybook component descriptions and add import instructions to components
- Patch: Remove description field from top level `meta` object in component `.stories.svelte` files (do not render)
+- Feature: CLI command to generate new component boilerplate (`npm run create-component`)
## v0.10.2
diff --git a/README.md b/README.md
index 58666e5f..7a537e38 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,14 @@ To build your library:
npm run package
```
+### CLI-based command for creating new component boilerplate
+
+To create three boilerplate files for a new component (`ComponentName.svelte`, `ComponentName.stories.svelte`, and `ComponentName.docs.md`), run the following command:
+
+```bash
+npm run create-component
+```
+
## Contributing to this library
When contributing to this library, keep the following guidelines in mind. The [pull request template](https://github.com/UrbanInstitute/dataviz-components/blob/main/.github/pull_request_template.md) requires explanation of changes and provides a checklist of tasks to ensure clean code and documentation. Please name all branches in `kebab-case`, beginning with "patch", "feature", or "bugfix", and provide insightful commit messages.
diff --git a/bin/createComponent/createComponent.js b/bin/createComponent/createComponent.js
new file mode 100644
index 00000000..435443cb
--- /dev/null
+++ b/bin/createComponent/createComponent.js
@@ -0,0 +1,72 @@
+#!/usr/bin/env node
+import { input } from "@inquirer/prompts";
+import fs from "fs";
+import path from "path";
+import process from "process";
+import { createStory } from "./createStory.js";
+import { createDocs } from "./createDocs.js";
+
+// check if PascalCase https://www.w3resource.com/javascript-exercises/javascript-string-exercise-56.php
+function isPascalCase(str) {
+ return /^[A-Z][A-Za-z]*$/.test(str);
+}
+
+// check if name is valid
+function validateName(componentName) {
+ if (!componentName) {
+ return "Please enter a component name";
+ } else if (!isPascalCase(componentName)) {
+ return "Component name must be in PascalCase";
+ } else {
+ return true;
+ }
+}
+
+function createFiles(componentName) {
+ // validate file name
+ const validated = validateName(componentName);
+ if (validated !== true) {
+ return console.error(validated);
+ }
+
+ // declare dir
+ const dir = path.join(process.cwd(), "src", "lib", componentName);
+
+ // if directory exists show error, else create files
+ if (fs.existsSync(dir)) {
+ console.error("Directory already exists");
+ } else {
+ // create directory
+ fs.mkdirSync(dir, { recursive: true });
+
+ // create Component.svelte (blank)
+ const svelteFilePath = path.join(dir, `${componentName}.svelte`);
+ fs.writeFileSync(svelteFilePath, "", "utf8");
+
+ // create Component.docs.md
+ const docsFilePath = path.join(dir, `${componentName}.docs.md`);
+ fs.writeFileSync(docsFilePath, createDocs(componentName), "utf8");
+
+ // create Component.stories.svelte
+ const storyFilePath = path.join(dir, `${componentName}.stories.svelte`);
+ fs.writeFileSync(storyFilePath, createStory(componentName), "utf8");
+
+ // Confirmation text
+ console.log(`Boilerplate files created in ${dir}`);
+ }
+}
+
+async function main() {
+ // if there's an argument in the command, use it (but no more)
+ if (process.argv[2] && !process.argv[3]) {
+ createFiles(process.argv[2]);
+ } else {
+ // show input
+ await input({
+ message: "What is the name of your component? (ie: MyComponent)",
+ validate: validateName
+ }).then(createFiles);
+ }
+}
+
+main().catch(console.error);
diff --git a/bin/createComponent/createDocs.js b/bin/createComponent/createDocs.js
new file mode 100644
index 00000000..0519e64b
--- /dev/null
+++ b/bin/createComponent/createDocs.js
@@ -0,0 +1,8 @@
+export function createDocs(componentName) {
+ return `Esse ipsum deserunt dolor minim dolore sunt cillum.
+
+\`\`\`js
+import { ${componentName} } from "@urbaninstitute/dataviz-components";
+\`\`\`
+`;
+}
diff --git a/bin/createComponent/createStory.js b/bin/createComponent/createStory.js
new file mode 100644
index 00000000..78af2849
--- /dev/null
+++ b/bin/createComponent/createStory.js
@@ -0,0 +1,32 @@
+export function createStory(componentName) {
+ return `
+
+
+
+
+
+
+
+`;
+}
diff --git a/package-lock.json b/package-lock.json
index 8b6679e8..6493ff3d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -26,6 +26,7 @@
},
"devDependencies": {
"@etchteam/storybook-addon-github-link": "^1.0.1",
+ "@inquirer/prompts": "^5.3.2",
"@storybook/addon-a11y": "^8.0.5",
"@storybook/addon-essentials": "^8.0.5",
"@storybook/addon-interactions": "^8.0.5",
@@ -2603,6 +2604,307 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
"dev": true
},
+ "node_modules/@inquirer/checkbox": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.4.2.tgz",
+ "integrity": "sha512-iZRNbTlSB9xXt/+jdMFViBdxw1ILWu3365rzfM5OLwAyOScbDFFGSH7LEUwoq1uOIo48ymOEwYSqP5y8hQMlmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.0.5",
+ "@inquirer/figures": "^1.0.5",
+ "@inquirer/type": "^1.5.1",
+ "ansi-escapes": "^4.3.2",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/confirm": {
+ "version": "3.1.17",
+ "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.17.tgz",
+ "integrity": "sha512-qCpt/AABzPynz8tr69VDvhcjwmzAryipWXtW8Vi6m651da4H/d0Bdn55LkxXD7Rp2gfgxvxzTdb66AhIA8gzBA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.0.5",
+ "@inquirer/type": "^1.5.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/core": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.5.tgz",
+ "integrity": "sha512-QWG41I7vn62O9stYKg/juKXt1PEbr/4ZZCPb4KgXDQGwgA9M5NBTQ7FnOvT1ridbxkm/wTxLCNraUs7y47pIRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/figures": "^1.0.5",
+ "@inquirer/type": "^1.5.1",
+ "@types/mute-stream": "^0.0.4",
+ "@types/node": "^20.14.11",
+ "@types/wrap-ansi": "^3.0.0",
+ "ansi-escapes": "^4.3.2",
+ "cli-spinners": "^2.9.2",
+ "cli-width": "^4.1.0",
+ "mute-stream": "^1.0.0",
+ "signal-exit": "^4.1.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^6.2.0",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@inquirer/core/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@inquirer/core/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@inquirer/editor": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.1.17.tgz",
+ "integrity": "sha512-hwx3VpFQzOY2hFWnY+XPsUGCIUVQ5kYxH6+CExv/RbMiAoN3zXtzj8DyrWBOHami0vBrrnPS8CTq3uQWc7N2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.0.5",
+ "@inquirer/type": "^1.5.1",
+ "external-editor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/expand": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.1.17.tgz",
+ "integrity": "sha512-s4V/dC+GeE5s97xoTtZSmC440uNKePKqZgzqEf0XM63ciilnXAtKGvoAWOePFdlK+oGTz0d8bhbPKwpKGvRYfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.0.5",
+ "@inquirer/type": "^1.5.1",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/figures": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.5.tgz",
+ "integrity": "sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/input": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.2.4.tgz",
+ "integrity": "sha512-wvYnDITPQn+ltktj/O9kQjPxOvpmwcpxLWh8brAyD+jlEbihxtrx9cZdZcxqaCVQj3caw4eZa2Uq5xELo4yXkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.0.5",
+ "@inquirer/type": "^1.5.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/number": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-1.0.5.tgz",
+ "integrity": "sha512-+H6TJPU2AJEcoF6nVTWssxS7gnhxWvf6CkILAdfq/yGm/htBKNDrvYLYaJvi1Be/aXQoKID9FaP94bUCjOvJNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.0.5",
+ "@inquirer/type": "^1.5.1"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/password": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.1.17.tgz",
+ "integrity": "sha512-/u6DM/fDHXoBWyA+9aRhghkeo5smE7wO9k4E2UoJbgiRCkt3JjBEuBqLOJNrz8E16M0ez4UM1vd5cXrmICHW+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.0.5",
+ "@inquirer/type": "^1.5.1",
+ "ansi-escapes": "^4.3.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/prompts": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-5.3.2.tgz",
+ "integrity": "sha512-8Jv+6rbY98ilFAZMYYfetu6XGXF/ZU44i5Z6Jx4t0xmwDh/AihdBV/FgetzDDZZMv5AMW1MT35LI0FiS55LoXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/checkbox": "^2.4.2",
+ "@inquirer/confirm": "^3.1.17",
+ "@inquirer/editor": "^2.1.17",
+ "@inquirer/expand": "^2.1.17",
+ "@inquirer/input": "^2.2.4",
+ "@inquirer/number": "^1.0.5",
+ "@inquirer/password": "^2.1.17",
+ "@inquirer/rawlist": "^2.1.17",
+ "@inquirer/search": "^1.0.2",
+ "@inquirer/select": "^2.4.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/rawlist": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.1.17.tgz",
+ "integrity": "sha512-RFrw34xU5aVlMA3ZJCaeKGxYjhu3j4i46O2GMmaRRGeLObCRM1yOKQOsRclSTzjd4A7+M5QleR2iuW/68J9Kwg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.0.5",
+ "@inquirer/type": "^1.5.1",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/search": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-1.0.2.tgz",
+ "integrity": "sha512-E/JD3MeJwJeNilOnRDmHGnlUksyVqrTQEUNqkRpioj8J0sVxW7+pFRHBM2coFsiCpvI4XKRRhWsai5VP8rrfrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.0.5",
+ "@inquirer/figures": "^1.0.5",
+ "@inquirer/type": "^1.5.1",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/select": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.4.2.tgz",
+ "integrity": "sha512-r78JlgShqRxyAtBDeBHSDtfrOhSQwm2ecWGGaxe7kD9JwgL3UN563G1ncVRYdsWD7/tigflcskfipVeoDLhLJg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@inquirer/core": "^9.0.5",
+ "@inquirer/figures": "^1.0.5",
+ "@inquirer/type": "^1.5.1",
+ "ansi-escapes": "^4.3.2",
+ "yoctocolors-cjs": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@inquirer/type": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.1.tgz",
+ "integrity": "sha512-m3YgGQlKNS0BM+8AFiJkCsTqHEFCWn6s/Rqye3mYwvqY6LdfUv12eSwbsgNzrYyrLXiy7IrrjDLPysaSBwEfhw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mute-stream": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -6024,11 +6326,22 @@
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
"dev": true
},
+ "node_modules/@types/mute-stream": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz",
+ "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/node": {
- "version": "20.12.11",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz",
- "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==",
+ "version": "20.14.12",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz",
+ "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
}
@@ -6133,6 +6446,13 @@
"@types/node": "*"
}
},
+ "node_modules/@types/wrap-ansi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz",
+ "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/yargs": {
"version": "17.0.32",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz",
@@ -7376,6 +7696,13 @@
"node": ">=10"
}
},
+ "node_modules/chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/check-error": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
@@ -7531,6 +7858,16 @@
"node": ">=8"
}
},
+ "node_modules/cli-width": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
+ "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
@@ -9559,6 +9896,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -14541,6 +14893,16 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
+ "node_modules/mute-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
+ "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
@@ -15463,6 +15825,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -18034,6 +18406,19 @@
"node": ">=14.0.0"
}
},
+ "node_modules/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "os-tmpdir": "~1.0.2"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
"node_modules/tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
@@ -19252,6 +19637,19 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/yoctocolors-cjs": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz",
+ "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
}
}
}
diff --git a/package.json b/package.json
index 950462f3..dbd6fdb3 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,8 @@
"build-storybook:test": "storybook build --quiet --test",
"test-storybook": "test-storybook",
"test-storybook-run": "npx concurrently -k -s first -n 'SB,TEST' -c 'magenta,blue' 'npx http-server storybook-static --port 6006 --silent' 'npx wait-on tcp:6006 && npm run test-storybook -- --index-json'",
- "compile-theme-styles": "node ./bin/compileTheme.js"
+ "compile-theme-styles": "node ./bin/compileTheme.js",
+ "create-component": "node ./bin/createComponent/createComponent.js"
},
"exports": {
".": {
@@ -55,6 +56,7 @@
},
"devDependencies": {
"@etchteam/storybook-addon-github-link": "^1.0.1",
+ "@inquirer/prompts": "^5.3.2",
"@storybook/addon-a11y": "^8.0.5",
"@storybook/addon-essentials": "^8.0.5",
"@storybook/addon-interactions": "^8.0.5",
diff --git a/src/docs/Intro.docs.mdx b/src/docs/Intro.docs.mdx
index 5102a141..b1c3363e 100644
--- a/src/docs/Intro.docs.mdx
+++ b/src/docs/Intro.docs.mdx
@@ -47,3 +47,11 @@ You can either wrap your entire page with a `` instance, or you can wrap
## Contributing to this library
We welcome contributions to this library! The [pull request template](https://github.com/UrbanInstitute/dataviz-components/blob/main/.github/pull_request_template.md) requires explanation of changes and provides a checklist of tasks to ensure clean code and documentation. Please name all branches in `kebab-case`, beginning with "patch", "feature", or "bugfix", and provide insightful commit messages.
+
+### CLI-based command for creating new component boilerplate
+
+To create three boilerplate files for a new component (`ComponentName.svelte`, `ComponentName.stories.svelte`, and `ComponentName.docs.md`), run the following command:
+
+```bash
+npm run create-component
+```