shadcn-nuxt 2.3.2 → 2.4.0

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
@@ -64,6 +64,28 @@ export default defineNuxtConfig({
64
64
 
65
65
  That's it! You can now use Shadcn Nuxt in your Nuxt app ✨
66
66
 
67
+ ### Multiple component directories
68
+
69
+ Projects that split their base UI components from custom extensions can configure multiple directories, each with its own optional prefix:
70
+
71
+ ```ts
72
+ export default defineNuxtConfig({
73
+ modules: ['shadcn-nuxt'],
74
+ shadcn: {
75
+ prefix: 'Ui',
76
+ componentDir: [
77
+ '@/components/ui',
78
+ {
79
+ path: '@/components/ai',
80
+ prefix: 'Ai',
81
+ },
82
+ ],
83
+ },
84
+ })
85
+ ```
86
+
87
+ Each directory is ignored by Nuxt's default auto-import scanning and re-registered through the module, ensuring clean separation without console warnings. See [issue #1593](https://github.com/unovue/shadcn-vue/issues/1593) for the background.
88
+
67
89
  ## Development
68
90
 
69
91
  ```bash
package/dist/module.d.mts CHANGED
@@ -1,5 +1,11 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
2
 
3
+ interface ComponentDirConfig {
4
+ path: string;
5
+ prefix?: string;
6
+ }
7
+ type ComponentDirInput = string | ComponentDirConfig;
8
+ type ComponentDirOption = ComponentDirInput | ComponentDirInput[];
3
9
  interface ModuleOptions {
4
10
  /**
5
11
  * Prefix for all the imported component.
@@ -12,8 +18,9 @@ interface ModuleOptions {
12
18
  * @link https://nuxt.com/docs/api/nuxt-config#alias
13
19
  * @default "@/components/ui"
14
20
  */
15
- componentDir?: string;
21
+ componentDir?: ComponentDirOption;
16
22
  }
17
23
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
18
24
 
19
- export { type ModuleOptions, _default as default };
25
+ export { _default as default };
26
+ export type { ComponentDirConfig, ComponentDirInput, ComponentDirOption, ModuleOptions };
package/dist/module.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "shadcn",
3
3
  "configKey": "shadcn",
4
- "version": "2.3.2",
4
+ "version": "2.4.0",
5
5
  "builder": {
6
- "@nuxt/module-builder": "1.0.1",
6
+ "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
8
8
  }
9
9
  }
package/dist/module.mjs CHANGED
@@ -3,6 +3,19 @@ import { join } from 'node:path';
3
3
  import { defineNuxtModule, createResolver, addComponentsDir, addComponent } from '@nuxt/kit';
4
4
  import { parseSync } from 'oxc-parser';
5
5
 
6
+ function isComponentDirConfig(value) {
7
+ return typeof value === "object" && value !== null && "path" in value;
8
+ }
9
+ function normalizeComponentDirs(componentDir, fallbackPrefix) {
10
+ const dirs = Array.isArray(componentDir) ? componentDir : [componentDir];
11
+ return dirs.filter((dir) => Boolean(dir)).map((dir) => {
12
+ if (typeof dir === "string")
13
+ return { path: dir, prefix: fallbackPrefix };
14
+ if (isComponentDirConfig(dir))
15
+ return { path: dir.path, prefix: dir.prefix ?? fallbackPrefix };
16
+ throw new Error("Invalid componentDir entry provided to shadcn module.");
17
+ });
18
+ }
6
19
  const module = defineNuxtModule({
7
20
  meta: {
8
21
  name: "shadcn",
@@ -13,49 +26,51 @@ const module = defineNuxtModule({
13
26
  componentDir: "@/components/ui"
14
27
  },
15
28
  async setup({ prefix, componentDir }, nuxt) {
16
- const COMPONENT_DIR_PATH = componentDir;
17
29
  const ROOT_DIR_PATH = nuxt.options.rootDir;
18
30
  const { resolve, resolvePath } = createResolver(ROOT_DIR_PATH);
19
- const componentsPath = await resolvePath(COMPONENT_DIR_PATH);
20
- if (!existsSync(componentsPath)) {
21
- console.warn(`Component directory does not exist: ${componentsPath}`);
22
- return;
23
- }
24
- addComponentsDir({
25
- path: componentsPath,
26
- extensions: [],
27
- ignore: ["**/*"]
28
- }, {
29
- prepend: true
30
- });
31
- try {
32
- await Promise.all(readdirSync(componentsPath).map(async (dir) => {
33
- try {
34
- const filePath = await resolvePath(join(COMPONENT_DIR_PATH, dir, "index"), { extensions: [".ts", ".js"] });
35
- const content = readFileSync(filePath, { encoding: "utf8" });
36
- const ast = parseSync(filePath, content, {
37
- sourceType: "module"
38
- });
39
- const exportedKeys = ast.program.body.filter((node) => node.type === "ExportNamedDeclaration").flatMap((node) => node.specifiers?.map((specifier) => specifier.exported?.name) || []).filter((key) => /^[A-Z]/.test(key));
40
- exportedKeys.forEach((key) => {
41
- addComponent({
42
- name: `${prefix}${key}`,
43
- // name of the component to be used in vue templates
44
- export: key,
45
- // (optional) if the component is a named (rather than default) export
46
- filePath: resolve(filePath),
47
- priority: 1
31
+ const normalizedDirs = normalizeComponentDirs(componentDir ?? "@/components/ui", prefix ?? "Ui");
32
+ await Promise.all(normalizedDirs.map(async ({ path, prefix: dirPrefix }) => {
33
+ const componentsPath = await resolvePath(path);
34
+ if (!existsSync(componentsPath)) {
35
+ console.warn(`Component directory does not exist: ${componentsPath}`);
36
+ return;
37
+ }
38
+ addComponentsDir({
39
+ path: componentsPath,
40
+ extensions: [],
41
+ ignore: ["**/*"]
42
+ }, {
43
+ prepend: true
44
+ });
45
+ try {
46
+ await Promise.all(readdirSync(componentsPath).map(async (dir) => {
47
+ try {
48
+ const filePath = await resolvePath(join(path, dir, "index"), { extensions: [".ts", ".js"] });
49
+ const content = readFileSync(filePath, { encoding: "utf8" });
50
+ const ast = parseSync(filePath, content, {
51
+ sourceType: "module"
48
52
  });
49
- });
50
- } catch (err) {
51
- if (err instanceof Error)
52
- console.warn("Module error: ", err.message);
53
- }
54
- }));
55
- } catch (err) {
56
- if (err instanceof Error)
57
- console.warn(err.message);
58
- }
53
+ const exportedKeys = ast.program.body.filter((node) => node.type === "ExportNamedDeclaration").flatMap((node) => node.specifiers?.map((specifier) => specifier.exported?.name) || []).filter((key) => /^[A-Z]/.test(key));
54
+ exportedKeys.forEach((key) => {
55
+ addComponent({
56
+ name: `${dirPrefix}${key}`,
57
+ // name of the component to be used in vue templates
58
+ export: key,
59
+ // (optional) if the component is a named (rather than default) export
60
+ filePath: resolve(filePath),
61
+ priority: 1
62
+ });
63
+ });
64
+ } catch (err) {
65
+ if (err instanceof Error)
66
+ console.warn("Module error: ", err.message);
67
+ }
68
+ }));
69
+ } catch (err) {
70
+ if (err instanceof Error)
71
+ console.warn(err.message);
72
+ }
73
+ }));
59
74
  }
60
75
  });
61
76
 
package/dist/types.d.mts CHANGED
@@ -1 +1,3 @@
1
- export { type ModuleOptions, default } from './module.mjs'
1
+ export { default } from './module.mjs'
2
+
3
+ export { type ComponentDirConfig, type ComponentDirInput, type ComponentDirOption, type ModuleOptions } from './module.mjs'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shadcn-nuxt",
3
3
  "type": "module",
4
- "version": "2.3.2",
4
+ "version": "2.4.0",
5
5
  "description": "Add shadcn-vue module to Nuxt",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -24,18 +24,18 @@
24
24
  ],
25
25
  "dependencies": {
26
26
  "@nuxt/kit": "^3.17.4",
27
- "oxc-parser": "^0.93.0"
27
+ "oxc-parser": "^0.99.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@nuxt/eslint-config": "^1.4.1",
31
- "@nuxt/module-builder": "^1.0.1",
31
+ "@nuxt/module-builder": "^1.0.2",
32
32
  "@nuxt/schema": "^3.17.4",
33
33
  "@nuxt/test-utils": "^3.19.1",
34
34
  "@nuxtjs/color-mode": "^3.5.2",
35
35
  "@nuxtjs/tailwindcss": "^6.14.0",
36
- "@types/node": "^22",
36
+ "@types/node": "^24",
37
37
  "nuxt": "^3.17.4",
38
- "typescript": "^5.8.3"
38
+ "typescript": "^5.9.3"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "nuxt-module-build prepare && nuxt-module-build build",