ui-thing 0.2.5 → 0.2.7

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.
Files changed (39) hide show
  1. package/.github/CONTRIBUTING.md +93 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
  3. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +27 -0
  5. package/.github/SECURITY.md +54 -0
  6. package/.github/workflows/test.yml +4 -4
  7. package/CHANGELOG.md +59 -0
  8. package/README.md +1 -1
  9. package/dist/index.js +24 -28
  10. package/dist/index.js.map +1 -1
  11. package/package.json +27 -26
  12. package/src/commands/block.ts +165 -0
  13. package/src/commands/init.ts +8 -4
  14. package/src/commands/prettier.ts +2 -6
  15. package/src/commands/prose.ts +200 -0
  16. package/src/index.ts +4 -0
  17. package/src/templates/prettier.ts +1 -1
  18. package/src/templates/shortcuts.ts +1 -7
  19. package/src/templates/vs-code.ts +10 -2
  20. package/src/types.ts +52 -7
  21. package/src/utils/addPrettierConfig.ts +13 -0
  22. package/src/utils/constants.ts +5 -3
  23. package/src/utils/fetchBlockCategories.ts +19 -0
  24. package/src/utils/fetchBlocks.ts +21 -0
  25. package/src/utils/fetchProseComponents.ts +21 -0
  26. package/src/utils/promptForComponents.ts +7 -4
  27. package/tests/utils/addPrettierConfig.test.ts +10 -17
  28. package/tests/utils/compareUIConfig.test.ts +3 -3
  29. package/tests/utils/constants.test.ts +136 -0
  30. package/tests/utils/detectNuxtVersion.test.ts +97 -0
  31. package/tests/utils/fetchBlockCategories.test.ts +59 -0
  32. package/tests/utils/fetchBlocks.test.ts +59 -0
  33. package/tests/utils/fetchComponents.test.ts +92 -0
  34. package/tests/utils/fetchProseComponents.test.ts +62 -0
  35. package/tests/utils/installPackages.test.ts +114 -0
  36. package/tests/utils/printFancyBoxMessage.test.ts +66 -0
  37. package/tests/utils/promptForComponents.test.ts +94 -0
  38. package/tests/utils/writeFile.test.ts +56 -0
  39. package/vite.config.ts +14 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ui-thing",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "CLI used to add Nuxt components to a project",
5
5
  "keywords": [
6
6
  "cli",
@@ -50,42 +50,43 @@
50
50
  ]
51
51
  },
52
52
  "dependencies": {
53
- "axios": "^1.11.0",
53
+ "axios": "^1.13.2",
54
54
  "boxen": "^8.0.1",
55
- "c12": "^3.2.0",
56
- "commander": "^14.0.0",
55
+ "c12": "^3.3.3",
56
+ "commander": "^14.0.2",
57
57
  "consola": "^3.4.2",
58
- "dotenv": "^17.2.2",
59
- "es-toolkit": "^1.39.10",
60
- "execa": "^9.6.0",
61
- "figlet": "^1.8.2",
62
- "fs-extra": "^11.3.1",
58
+ "dotenv": "^17.2.3",
59
+ "es-toolkit": "^1.43.0",
60
+ "execa": "^9.6.1",
61
+ "figlet": "^1.9.4",
62
+ "fs-extra": "^11.3.3",
63
63
  "kleur": "^4.1.5",
64
64
  "lodash": "^4.17.21",
65
- "magicast": "^0.3.5",
66
- "ora": "^8.2.0",
65
+ "magicast": "^0.5.1",
66
+ "ora": "^9.0.0",
67
67
  "prompts": "^2.4.2"
68
68
  },
69
69
  "devDependencies": {
70
- "@eslint/js": "^9.35.0",
70
+ "@eslint/js": "^9.39.2",
71
71
  "@ianvs/prettier-plugin-sort-imports": "^4.7.0",
72
- "@types/figlet": "^1.7.0",
73
72
  "@types/fs-extra": "^11.0.4",
74
- "@types/lodash": "^4.17.20",
75
- "@types/node": "^24.3.1",
73
+ "@types/lodash": "^4.17.21",
74
+ "@types/node": "^24.10.4",
76
75
  "@types/prompts": "^2.4.9",
77
- "@vitest/coverage-v8": "^3.2.4",
78
- "eslint": "^9.35.0",
79
- "globals": "^16.3.0",
76
+ "@vitest/coverage-v8": "^4.0.16",
77
+ "@vitest/ui": "^4.0.16",
78
+ "axios-mock-adapter": "^2.1.0",
79
+ "eslint": "^9.39.2",
80
+ "globals": "^16.5.0",
80
81
  "husky": "^9.1.7",
81
- "jiti": "^2.5.1",
82
- "knip": "^5.63.1",
83
- "lint-staged": "^16.1.6",
84
- "prettier": "^3.6.2",
85
- "tsup": "^8.5.0",
86
- "typescript": "^5.9.2",
87
- "typescript-eslint": "^8.42.0",
88
- "vitest": "^3.2.4"
82
+ "jiti": "^2.6.1",
83
+ "knip": "^5.78.0",
84
+ "lint-staged": "^16.2.7",
85
+ "prettier": "^3.7.4",
86
+ "tsup": "^8.5.1",
87
+ "typescript": "^5.9.3",
88
+ "typescript-eslint": "^8.51.0",
89
+ "vitest": "^4.0.16"
89
90
  },
90
91
  "publishConfig": {
91
92
  "access": "public"
@@ -0,0 +1,165 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import path from "node:path";
3
+ import { Command } from "commander";
4
+ import { consola } from "consola";
5
+ import kleur from "kleur";
6
+ import _ from "lodash";
7
+ import prompts from "prompts";
8
+
9
+ import { AddCommand, BlockComponent } from "../types";
10
+ import { compareUIConfig } from "../utils/compareUIConfig";
11
+ import { getUIConfig } from "../utils/config";
12
+ import { fetchBlockCategories } from "../utils/fetchBlockCategories";
13
+ import { fetchBlocks } from "../utils/fetchBlocks";
14
+ import { fileExists } from "../utils/fileExists";
15
+ import { printFancyBoxMessage } from "../utils/printFancyBoxMessage";
16
+ import { writeFile } from "../utils/writeFile";
17
+
18
+ type BlockOptions = AddCommand & { category?: string };
19
+
20
+ let allBlocks: BlockComponent[] = [];
21
+ const currentDirectory = process.cwd();
22
+
23
+ /**
24
+ * Get the default blocks directory based on Nuxt version from config
25
+ */
26
+ function getDefaultBlocksDir(uiConfig: any): string {
27
+ const isNuxt4 = uiConfig.componentsLocation?.startsWith("app/");
28
+ return isNuxt4 ? "app/components/Blocks" : "components/Blocks";
29
+ }
30
+
31
+ async function safeWriteFile(
32
+ targetPath: string,
33
+ content: string,
34
+ forceOverwrite: boolean,
35
+ promptMessage: string
36
+ ) {
37
+ const exists = await fileExists(targetPath);
38
+
39
+ if (exists && !forceOverwrite) {
40
+ const { value: overwrite } = await prompts({
41
+ type: "confirm",
42
+ name: "value",
43
+ message: promptMessage,
44
+ initial: false,
45
+ });
46
+ if (!overwrite) {
47
+ consola.info(`Skipped: ${kleur.cyan(path.basename(targetPath))}`);
48
+ return false;
49
+ }
50
+ }
51
+
52
+ await writeFile(targetPath, content);
53
+ return true;
54
+ }
55
+
56
+ const runBlockCommand = async (components: string[], options: BlockOptions) => {
57
+ let uiConfig = await getUIConfig();
58
+ if (!(await compareUIConfig())) {
59
+ uiConfig = await getUIConfig({ force: true });
60
+ }
61
+ if (_.isEmpty(uiConfig)) {
62
+ consola.info("Config file not set. Exiting...");
63
+ process.exit(0);
64
+ }
65
+
66
+ // Step 1: Fetch categories
67
+ const categories = await fetchBlockCategories();
68
+
69
+ // Step 2: Ask user to select category
70
+ let selectedCategory = options.category;
71
+ if (!selectedCategory && categories?.length) {
72
+ const { category } = await prompts({
73
+ type: "select",
74
+ name: "category",
75
+ message: "Choose a block category",
76
+ choices: [{ title: "All", value: "all" }, ...categories.map((c) => ({ title: c, value: c }))],
77
+ initial: 0,
78
+ });
79
+ selectedCategory = category;
80
+ }
81
+
82
+ // Step 3: Fetch all blocks
83
+ allBlocks = await fetchBlocks();
84
+
85
+ // Step 4: Filter blocks by category if not "all"
86
+ let blocksToSelect = allBlocks;
87
+ if (selectedCategory && selectedCategory !== "all") {
88
+ blocksToSelect = allBlocks.filter((b) => b.category === selectedCategory);
89
+ if (blocksToSelect.length === 0) {
90
+ consola.warn(
91
+ `No blocks found for category ${kleur.cyan(selectedCategory)}. Falling back to all.`
92
+ );
93
+ blocksToSelect = allBlocks;
94
+ }
95
+ }
96
+
97
+ // Step 5: Let user select blocks via autocomplete multi-select
98
+ const { selectedBlocks } = await prompts({
99
+ type: "autocompleteMultiselect",
100
+ name: "selectedBlocks",
101
+ message: "Select the blocks you want to add",
102
+ choices: blocksToSelect.map((b) => ({ title: b.name, value: b })),
103
+ });
104
+
105
+ if (!selectedBlocks || selectedBlocks.length === 0) {
106
+ consola.info("No blocks selected. Exiting...");
107
+ process.exit(0);
108
+ }
109
+
110
+ const found: BlockComponent[] = selectedBlocks;
111
+
112
+ // Step 6: Ask user where to add blocks (with default based on Nuxt version)
113
+ const defaultBlocksDir = getDefaultBlocksDir(uiConfig);
114
+ const { blocksDir } = await prompts({
115
+ type: "text",
116
+ name: "blocksDir",
117
+ message: "Where should we add the blocks?",
118
+ initial: defaultBlocksDir,
119
+ });
120
+
121
+ const blocksDirPath = blocksDir || defaultBlocksDir;
122
+
123
+ // Step 7: Write block files
124
+ for (const block of found) {
125
+ // Create full path: blocksDirPath + block.path + block.fileName
126
+ const fullPath = path.join(blocksDirPath, block.path);
127
+ const targetPath = path.join(currentDirectory, fullPath);
128
+
129
+ const fileWritten = await safeWriteFile(
130
+ targetPath,
131
+ block.file,
132
+ uiConfig.force,
133
+ `The block file ${kleur.bold(block.fileName)} already exists. Overwrite?`
134
+ );
135
+
136
+ if (!fileWritten) continue;
137
+ }
138
+
139
+ // Step 8: Handle components if present
140
+ const componentsToAdd = _.uniq(found.flatMap((b) => b.components || []));
141
+ if (componentsToAdd.length > 0) {
142
+ consola.info(`Adding ${componentsToAdd.length} component(s) required by blocks...`);
143
+ const result = spawnSync("npx", ["ui-thing@latest", "add", ...componentsToAdd], {
144
+ cwd: currentDirectory,
145
+ stdio: "inherit",
146
+ });
147
+ if (result.error) {
148
+ consola.error("Failed to add components:", result.error.message);
149
+ }
150
+ }
151
+
152
+ // Step 9: Success message
153
+ printFancyBoxMessage(
154
+ "Blocks added!",
155
+ `Run the ${kleur.cyan("ui-thing@latest --help")} command to learn more.\n`,
156
+ { box: { title: "Blocks Added" } }
157
+ );
158
+ };
159
+
160
+ export const block = new Command()
161
+ .name("block")
162
+ .command("block")
163
+ .description("Add UI Thing blocks to your project.")
164
+ .option("-c --category <category>", "Filter blocks by category before selection")
165
+ .action(runBlockCommand);
@@ -8,11 +8,11 @@ import ora from "ora";
8
8
  import { createCSS } from "../templates/css";
9
9
  import { TW_HELPER } from "../templates/tw-helper";
10
10
  import { InitOptions, UIConfig } from "../types";
11
- import { addPrettierConfig } from "../utils/addPrettierConfig";
11
+ import { addPrettierConfig, askPrettierConfig } from "../utils/addPrettierConfig";
12
12
  import { addTailwindVitePlugin } from "../utils/addTailwindVitePlugin";
13
13
  import { addVSCodeFiles } from "../utils/addVSCodeFiles";
14
14
  import { getUIConfig } from "../utils/config";
15
- import { INIT_DEPS, INIT_DEV_DEPS, INIT_MODULES } from "../utils/constants";
15
+ import { INIT_DEPS, INIT_DEV_DEPS, INIT_DEV_DEPS_PRETTIER, INIT_MODULES } from "../utils/constants";
16
16
  import { installPackages } from "../utils/installPackages";
17
17
  import { printFancyBoxMessage } from "../utils/printFancyBoxMessage";
18
18
 
@@ -103,8 +103,12 @@ const runInitCommand = async (options: InitOptions) => {
103
103
  spinner.succeed("Merged VS Code settings!");
104
104
  // Install deps
105
105
  await installPackages(uiConfig.packageManager, INIT_DEPS, INIT_DEV_DEPS);
106
- // Add prettier config
107
- await addPrettierConfig();
106
+ // Add prettier config if user agrees
107
+ const addPrettier = await askPrettierConfig();
108
+ if (addPrettier) {
109
+ await installPackages(uiConfig.packageManager, [], INIT_DEV_DEPS_PRETTIER);
110
+ await addPrettierConfig();
111
+ }
108
112
  printFancyBoxMessage(
109
113
  "Initialized",
110
114
  `Feel free to start adding components with the ${kleur.bgWhite(" add ")} command.`,
@@ -2,7 +2,7 @@ import { Command } from "commander";
2
2
  import prompts from "prompts";
3
3
 
4
4
  import { addPrettierConfig } from "../utils/addPrettierConfig";
5
- import { PACKAGE_MANAGER_CHOICES } from "../utils/constants";
5
+ import { INIT_DEV_DEPS_PRETTIER, PACKAGE_MANAGER_CHOICES } from "../utils/constants";
6
6
  import { installPackages } from "../utils/installPackages";
7
7
  import { printFancyBoxMessage } from "../utils/printFancyBoxMessage";
8
8
 
@@ -28,11 +28,7 @@ export const addPrettier = new Command()
28
28
  if (!pkgManager) return process.exit(0);
29
29
 
30
30
  // install prettier dep
31
- await installPackages(pkgManager, undefined, [
32
- "prettier",
33
- "prettier-plugin-tailwindcss",
34
- "@ianvs/prettier-plugin-sort-imports",
35
- ]);
31
+ await installPackages(pkgManager, undefined, INIT_DEV_DEPS_PRETTIER);
36
32
  printFancyBoxMessage(
37
33
  "All Done!",
38
34
  `A .prettierrc file has been added to your project and the code formatted. Enjoy!`,
@@ -0,0 +1,200 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import path from "node:path";
3
+ import { Command } from "commander";
4
+ import { consola } from "consola";
5
+ import kleur from "kleur";
6
+ import _ from "lodash";
7
+ import prompts from "prompts";
8
+
9
+ import { AddCommand, ProseComponent, TemplateFile } from "../types";
10
+ import { compareUIConfig } from "../utils/compareUIConfig";
11
+ import { addModuleToConfig, getUIConfig } from "../utils/config";
12
+ import { fetchProseComponents } from "../utils/fetchProseComponents";
13
+ import { fileExists } from "../utils/fileExists";
14
+ import { installPackages } from "../utils/installPackages";
15
+ import { printFancyBoxMessage } from "../utils/printFancyBoxMessage";
16
+ import { promptUserForComponents } from "../utils/promptForComponents";
17
+ import { writeFile } from "../utils/writeFile";
18
+
19
+ let allProse: ProseComponent[] = [];
20
+ const currentDirectory = process.cwd();
21
+
22
+ const findProse = (name: string) =>
23
+ allProse.find((c) => c.value.toLowerCase() === name.toLowerCase());
24
+
25
+ async function safeWriteFile(
26
+ targetPath: string,
27
+ content: string,
28
+ forceOverwrite: boolean,
29
+ promptMessage: string
30
+ ) {
31
+ const exists = await fileExists(targetPath);
32
+
33
+ if (exists && !forceOverwrite) {
34
+ const { value: overwrite } = await prompts({
35
+ type: "confirm",
36
+ name: "value",
37
+ message: promptMessage,
38
+ initial: false,
39
+ });
40
+ if (!overwrite) {
41
+ consola.info(`Skipped: ${kleur.cyan(path.basename(targetPath))}`);
42
+ return false;
43
+ }
44
+ }
45
+
46
+ await writeFile(targetPath, content);
47
+ return true;
48
+ }
49
+
50
+ async function writeCategoryFiles(
51
+ category: string,
52
+ items: TemplateFile[] | undefined,
53
+ baseDir: string,
54
+ forceOverwrite: boolean
55
+ ) {
56
+ if (!items || items.length === 0) return;
57
+ for (const item of items) {
58
+ const targetPath = path.join(currentDirectory, baseDir, item.fileName);
59
+ await safeWriteFile(
60
+ targetPath,
61
+ item.fileContent,
62
+ forceOverwrite,
63
+ `The ${category} file ${kleur.bold(item.fileName)} already exists. Overwrite?`
64
+ );
65
+ }
66
+ }
67
+
68
+ const runProseCommand = async (components: string[], options: AddCommand) => {
69
+ let uiConfig = await getUIConfig();
70
+ if (!(await compareUIConfig())) {
71
+ uiConfig = await getUIConfig({ force: true });
72
+ }
73
+ if (_.isEmpty(uiConfig)) {
74
+ consola.info("Config file not set. Exiting...");
75
+ process.exit(0);
76
+ }
77
+
78
+ allProse = await fetchProseComponents();
79
+
80
+ let componentNames = components;
81
+ if (componentNames.length === 0) {
82
+ const response = await promptUserForComponents(options.all, allProse);
83
+ if (!response || response.length === 0) {
84
+ consola.info("No components selected. Exiting...");
85
+ process.exit(0);
86
+ }
87
+ componentNames = response;
88
+ }
89
+
90
+ const notFound = componentNames.filter((name) => !findProse(name));
91
+ if (notFound.length > 0) {
92
+ consola.error(`Not found: ${kleur.bgRed(notFound.join(", "))}`);
93
+ }
94
+
95
+ const found: ProseComponent[] = componentNames
96
+ .map((name) => findProse(name))
97
+ .filter(Boolean) as ProseComponent[];
98
+
99
+ // Handle prose dependencies
100
+ for (const comp of [...found]) {
101
+ if (comp.prose && comp.prose.length > 0) {
102
+ comp.prose.forEach((proseName) => {
103
+ if (!found.find((c) => c.value === proseName)) {
104
+ const proseComp = findProse(proseName);
105
+ if (proseComp) {
106
+ found.push(proseComp);
107
+ }
108
+ }
109
+ });
110
+ }
111
+ }
112
+
113
+ for (const component of found) {
114
+ const componentFile = component.file;
115
+ let dirPath = uiConfig.componentsLocation;
116
+ let filePath = path.join(currentDirectory, dirPath, componentFile.fileName);
117
+
118
+ if (!uiConfig.useDefaultFilename) {
119
+ const { value: newDir } = await prompts({
120
+ type: "text",
121
+ name: "value",
122
+ message: `Where should we add the file ${kleur.cyan(componentFile.fileName)}?`,
123
+ initial: dirPath,
124
+ });
125
+ if (newDir) {
126
+ dirPath = newDir;
127
+ filePath = path.join(currentDirectory, dirPath, componentFile.fileName);
128
+ }
129
+ }
130
+
131
+ const fileWritten = await safeWriteFile(
132
+ filePath,
133
+ componentFile.fileContent,
134
+ uiConfig.force,
135
+ `The file ${kleur.bold(componentFile.fileName)} already exists. Overwrite?`
136
+ );
137
+ if (!fileWritten) continue;
138
+
139
+ await writeCategoryFiles("utils", component.utils, uiConfig.utilsLocation, uiConfig.force);
140
+ await writeCategoryFiles(
141
+ "composables",
142
+ component.composables,
143
+ uiConfig.composablesLocation,
144
+ uiConfig.force
145
+ );
146
+ await writeCategoryFiles(
147
+ "plugins",
148
+ component.plugins,
149
+ uiConfig.pluginsLocation ?? "",
150
+ uiConfig.force
151
+ );
152
+ }
153
+
154
+ await addModuleToConfig(_.uniq(found.flatMap((c) => c.modules || [])));
155
+
156
+ const deps = _.uniq(found.flatMap((c) => c.deps || []));
157
+ const devDeps = _.uniq(found.flatMap((c) => c.devDeps || []));
158
+ if (deps.length > 0 || devDeps.length > 0) {
159
+ if (options.all) {
160
+ await installPackages(uiConfig.packageManager, deps, devDeps);
161
+ } else {
162
+ const { confirmInstall } = await prompts({
163
+ type: "confirm",
164
+ name: "confirmInstall",
165
+ message: `Install packages: ${kleur.cyan([...deps, ...devDeps].join(", "))}?`,
166
+ initial: true,
167
+ });
168
+ if (confirmInstall) {
169
+ await installPackages(uiConfig.packageManager, deps, devDeps);
170
+ }
171
+ }
172
+ }
173
+
174
+ // Collect and add components via the add command
175
+ const componentsToAdd = _.uniq(found.flatMap((c) => c.components || []));
176
+ if (componentsToAdd.length > 0) {
177
+ consola.info(`Adding ${componentsToAdd.length} component(s) required by prose...`);
178
+ const result = spawnSync("npx", ["ui-thing@latest", "add", ...componentsToAdd], {
179
+ cwd: currentDirectory,
180
+ stdio: "inherit",
181
+ });
182
+ if (result.error) {
183
+ consola.error("Failed to add components:", result.error.message);
184
+ }
185
+ }
186
+
187
+ printFancyBoxMessage(
188
+ "Prose added!",
189
+ `Run the ${kleur.cyan("ui-thing@latest --help")} command to learn more.\n`,
190
+ { box: { title: "Prose Components Added" } }
191
+ );
192
+ };
193
+
194
+ export const prose = new Command()
195
+ .name("prose")
196
+ .command("prose")
197
+ .description("Add prose components to your project.")
198
+ .option("-a --all", "Add all prose components to your project.", false)
199
+ .argument("[componentNames...]")
200
+ .action(runProseCommand);
package/src/index.ts CHANGED
@@ -3,8 +3,10 @@ import { Command } from "commander";
3
3
 
4
4
  import { version } from "../package.json";
5
5
  import { add } from "./commands/add";
6
+ import { block } from "./commands/block";
6
7
  import { init } from "./commands/init";
7
8
  import { addPrettier } from "./commands/prettier";
9
+ import { prose } from "./commands/prose";
8
10
  import { addShortcuts } from "./commands/shortcuts";
9
11
  import { theme } from "./commands/theme";
10
12
  import { printFancyBoxMessage } from "./utils/printFancyBoxMessage";
@@ -26,6 +28,8 @@ program
26
28
  .version(version)
27
29
  .addCommand(init)
28
30
  .addCommand(add)
31
+ .addCommand(prose)
32
+ .addCommand(block)
29
33
  .addCommand(theme)
30
34
  .addCommand(addShortcuts)
31
35
  .addCommand(addPrettier);
@@ -9,6 +9,6 @@ export const PRETTIER_CONFIG = {
9
9
  trailingComma: "es5",
10
10
  useTabs: false,
11
11
  vueIndentScriptAndStyle: true,
12
- tailwindFunctions: ["tv"],
12
+ tailwindFunctions: ["tv", "tw"],
13
13
  importOrder: ["<BUILTIN_MODULES>", "<THIRD_PARTY_MODULES>", "<TYPES>", "", "^[.]"],
14
14
  };
@@ -1,10 +1,4 @@
1
- export const DEFINE_SHORTCUT = `import {
2
- createSharedComposable,
3
- useActiveElement,
4
- useDebounceFn,
5
- useEventListener,
6
- } from "@vueuse/core";
7
- import type { MaybeRef } from "vue";
1
+ export const DEFINE_SHORTCUT = `import type { MaybeRef } from "vue";
8
2
 
9
3
  type KbdKeysSpecificMap = {
10
4
  meta: string;
@@ -5,10 +5,10 @@ export const VS_CODE_RECOMMENDATIONS = {
5
5
  recommendations: [
6
6
  "vue.volar",
7
7
  "bradlc.vscode-tailwindcss",
8
- "esbenp.prettier-vscode",
9
8
  "antfu.iconify",
10
9
  "formulahendry.auto-close-tag",
11
10
  "formulahendry.auto-rename-tag",
11
+ "prettier.prettier-vscode",
12
12
  ],
13
13
  };
14
14
 
@@ -20,5 +20,13 @@ export const VS_CODE_SETTINGS = {
20
20
  "editor.quickSuggestions": { strings: "on" },
21
21
  "files.associations": { "*.css": "tailwindcss" },
22
22
  "tailwindCSS.classFunctions": ["tw", "clsx", "tw\\.[a-z-]+"],
23
- "tailwindCSS.experimental.classRegex": [["([\"'`][^\"'`]*.*?[\"'`])", "[\"'`]([^\"'`]*)[\"'`]"]],
23
+ "tailwindCSS.experimental.classRegex": [
24
+ [
25
+ "tv\\(([^)(]*(?:\\([^)(]*(?:\\([^)(]*(?:\\([^)(]*\\)[^)(]*)*\\)[^)(]*)*\\)[^)(]*)*)\\)",
26
+ '"(.*?)"',
27
+ ],
28
+ "tw`(.*?)`",
29
+ "tw\\('(.*?)'\\)",
30
+ "tw\\(\\s*('(.*?)'|\"(.*?)\")\\s*\\)",
31
+ ],
24
32
  };
package/src/types.ts CHANGED
@@ -85,6 +85,12 @@ export type AddCommand = {
85
85
  all?: boolean;
86
86
  };
87
87
 
88
+ export type TemplateFile = {
89
+ fileName: string;
90
+ dirPath: string;
91
+ fileContent: string;
92
+ };
93
+
88
94
  export type Component = {
89
95
  name: string;
90
96
  value: string;
@@ -92,17 +98,56 @@ export type Component = {
92
98
  devDeps?: string[];
93
99
  nuxtModules?: string[];
94
100
  instructions?: string[];
95
- files: Composable[];
96
- utils: Composable[];
97
- composables: Composable[];
98
- plugins: Composable[];
101
+ files: TemplateFile[];
102
+ utils: TemplateFile[];
103
+ composables: TemplateFile[];
104
+ plugins: TemplateFile[];
99
105
  components?: string[];
100
106
  askValidator?: boolean;
101
107
  overrides?: Record<string, any>;
108
+ docsPath?: string;
102
109
  };
103
110
 
104
- type Composable = {
111
+ export type ProseComponent = {
112
+ name: string;
113
+ value: string;
114
+ description?: string;
115
+ filePath: string;
105
116
  fileName: string;
106
- dirPath: string;
107
- fileContent: string;
117
+ /**
118
+ * The other prose components that should be added alongside this one.
119
+ */
120
+ prose?: string[];
121
+ docsUrl?: string;
122
+ file: TemplateFile;
123
+ /**
124
+ * The components that this prose component depends on.
125
+ *
126
+ * Should be added from the add command
127
+ */
128
+ components?: string[];
129
+ composables?: TemplateFile[];
130
+ utils?: TemplateFile[];
131
+ plugins?: TemplateFile[];
132
+ /** The dependencies to add */
133
+ deps?: string[];
134
+ /** The development dependencies to add */
135
+ devDeps?: string[];
136
+ /** The nuxt modules to add */
137
+ modules?: string[];
138
+ };
139
+
140
+ export type BlockComponent = {
141
+ /** The display name of the block */
142
+ name: string;
143
+ /** The filename of the block */
144
+ fileName: string;
145
+ /** The actual file content of the block */
146
+ file: string;
147
+ /** The category of the block */
148
+ category: string;
149
+ /** The path to the block */
150
+ path: string;
151
+ /** The components used by the block */
152
+ components?: string[];
108
153
  };
@@ -67,3 +67,16 @@ export const addPrettierConfig = async (cwd = process.cwd(), format: boolean = t
67
67
 
68
68
  return true;
69
69
  };
70
+
71
+ /**
72
+ * Asks the user if they want to add a Prettier configuration.
73
+ */
74
+ export const askPrettierConfig = async (): Promise<boolean> => {
75
+ const { addPrettier } = await prompts({
76
+ name: "addPrettier",
77
+ type: "confirm",
78
+ message: "Would you like to add a Prettier configuration to your project?",
79
+ initial: true,
80
+ });
81
+ return addPrettier;
82
+ };
@@ -58,12 +58,14 @@ export const INIT_DEPS = [
58
58
  /**
59
59
  * The initial development dependencies
60
60
  */
61
- export const INIT_DEV_DEPS = [
62
- "typescript",
61
+ export const INIT_DEV_DEPS = ["typescript", "tw-animate-css"];
62
+ /**
63
+ * The initial development dependencies for prettier stuff
64
+ */
65
+ export const INIT_DEV_DEPS_PRETTIER = [
63
66
  "prettier-plugin-tailwindcss",
64
67
  "prettier",
65
68
  "@ianvs/prettier-plugin-sort-imports",
66
- "tw-animate-css",
67
69
  ];
68
70
 
69
71
  /**