vueless 1.2.5-beta.1 → 1.2.5-beta.11

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.
@@ -1,22 +1,26 @@
1
1
  /* eslint-disable no-console */
2
2
 
3
- import { existsSync } from "node:fs";
4
3
  import path from "node:path";
5
4
  import { cwd } from "node:process";
6
- import { cp, readFile, writeFile, rename } from "node:fs/promises";
5
+ import { existsSync } from "node:fs";
7
6
  import { styleText } from "node:util";
7
+ import { cp, readFile, writeFile, rename } from "node:fs/promises";
8
8
 
9
9
  import { getDirFiles } from "../../utils/node/helper.js";
10
10
  import { replaceRelativeImports } from "../utils/format.js";
11
11
  import { getStorybookId, getStoryMetaKeyIndex } from "../utils/data.js";
12
-
13
- import { SRC_COMPONENTS_PATH, COMPONENTS_PATH } from "../constants.js";
14
- import { COMPONENTS, VUELESS_PACKAGE_DIR, VUELESS_LOCAL_DIR } from "../../constants.js";
15
-
16
- function getSourcePath(componentName) {
17
- return path.join(cwd(), VUELESS_PACKAGE_DIR, COMPONENTS[componentName]);
18
- }
19
-
12
+ import { COMPONENTS, VUELESS_PACKAGE_DIR, VUELESS_USER_COMPONENTS_DIR } from "../../constants.js";
13
+
14
+ /**
15
+ * Copies an existing Vueless component to a new location with a new name.
16
+ * This includes duplicating the source files and updating the component's internal references as needed.
17
+ *
18
+ * @param {Array<string>} options - An array containing two elements:
19
+ * – The name of the component to be copied.
20
+ * – The desired name for the copied component.
21
+ * @return {Promise<void>} A promise that resolves when the component has been successfully copied.
22
+ * If an error occurs, no value is returned, and the operation exits early with a logged message.
23
+ */
20
24
  export async function copyVuelessComponent(options) {
21
25
  const [componentName, newComponentName] = options;
22
26
 
@@ -32,73 +36,120 @@ export async function copyVuelessComponent(options) {
32
36
  return;
33
37
  }
34
38
 
35
- const sourceComponentPath = getSourcePath(componentName);
39
+ if (newComponentName in COMPONENTS) {
40
+ console.log(
41
+ styleText("red", `Component with name '${newComponentName}' already exists in Vueless UI.`),
42
+ );
36
43
 
37
- const isSrcDir = existsSync(path.join(cwd(), VUELESS_LOCAL_DIR));
38
- const destPath = isSrcDir
39
- ? path.join(SRC_COMPONENTS_PATH, newComponentName)
40
- : path.join(COMPONENTS_PATH, newComponentName);
41
- const absoluteDestPath = path.join(cwd(), destPath);
44
+ return;
45
+ }
46
+
47
+ if (!newComponentName.startsWith("U")) {
48
+ console.log(styleText("red", `Component should have 'U' prefix (ex. 'UButtonCustom').`));
49
+
50
+ return;
51
+ }
42
52
 
43
- const isComponentExists = newComponentName in COMPONENTS || existsSync(absoluteDestPath);
53
+ const absoluteSourcePath = path.join(cwd(), VUELESS_PACKAGE_DIR, COMPONENTS[componentName]);
54
+ const absoluteDestPath = path.join(cwd(), VUELESS_USER_COMPONENTS_DIR, newComponentName);
44
55
 
45
- if (isComponentExists) {
46
- console.log(styleText("red", `Component with name ${newComponentName} already exists.`));
56
+ if (existsSync(absoluteDestPath)) {
57
+ console.log(styleText("red", `Component with name '${newComponentName}' already exists.`));
47
58
 
48
59
  return;
49
60
  }
50
61
 
51
- await cp(sourceComponentPath, absoluteDestPath, { recursive: true });
62
+ await cp(absoluteSourcePath, absoluteDestPath, { recursive: true });
52
63
  await modifyCreatedComponent(absoluteDestPath, componentName, newComponentName);
53
64
 
54
- const successMessage = styleText(
55
- "green",
56
- `The '${componentName}' was successfully copied into the '${destPath}' directory.`,
65
+ console.log(
66
+ // eslint-disable-next-line vue/max-len, prettier/prettier
67
+ styleText("green", `The '${componentName}' was successfully copied into the '${VUELESS_USER_COMPONENTS_DIR}/${newComponentName}' directory.`)
57
68
  );
58
-
59
- console.log(successMessage);
60
69
  }
61
70
 
71
+ /**
72
+ * Modifies the files related to a specified component by renaming the component and updating its references
73
+ * across various files in the specified directory.
74
+ *
75
+ * @param {string} destPath - The destination path where the component and its related files are located.
76
+ * @param {string} componentName - The current name of the component to be modified.
77
+ * @param {string} newComponentName - The new name to assign to the component and its references.
78
+ * @return {Promise<void>} A promise that resolves when the modification process is completed.
79
+ */
62
80
  async function modifyCreatedComponent(destPath, componentName, newComponentName) {
63
81
  const destFiles = await getDirFiles(destPath, "");
64
82
  const storybookId = await getStorybookId();
65
83
 
66
- const componentFileName = `${componentName}.vue`;
67
- const newComponentFileName = `${newComponentName}.vue`;
68
-
69
84
  for await (const filePath of destFiles) {
70
85
  const fileContent = await readFile(filePath, "utf-8");
71
-
72
86
  let updatedContent = replaceRelativeImports(newComponentName, filePath, fileContent);
73
- let targetPath = filePath;
74
87
 
88
+ /* Renaming component name in constants */
75
89
  if (filePath.endsWith("constants.ts")) {
76
- updatedContent = updatedContent.replace(componentName, newComponentName);
90
+ updatedContent = updatedContent.replaceAll(componentName, newComponentName);
91
+ }
92
+
93
+ /* Renaming component name in tests */
94
+ if (filePath.endsWith("test.ts")) {
95
+ updatedContent = updatedContent.replaceAll(componentName, newComponentName);
96
+ }
97
+
98
+ /* Renaming component name in types */
99
+ if (filePath.endsWith("types.ts")) {
100
+ updatedContent = updatedContent.replaceAll(componentName, newComponentName);
101
+ }
102
+
103
+ /* Renaming component name in components */
104
+ if (filePath.endsWith(".vue")) {
105
+ let lines = updatedContent.split("\n");
106
+
107
+ for (const [index, line] of lines.entries()) {
108
+ // Add some condition here in future if some edge cases appear
109
+ if (line.includes(componentName)) {
110
+ lines[index] = line.replaceAll(componentName, newComponentName);
111
+ }
112
+ }
113
+
114
+ updatedContent = lines.join("\n");
77
115
  }
78
116
 
117
+ /* Renaming component name in stories */
79
118
  if (filePath.endsWith("stories.ts")) {
80
- const storyLines = updatedContent.split("\n");
119
+ let lines = updatedContent.split("\n");
81
120
 
82
- const storyComponentImportIndex = storyLines.findIndex(
83
- (line) => line.includes(componentName) && line.includes("import"),
84
- );
121
+ // saving indexes
85
122
  const storyIdIndex = getStoryMetaKeyIndex(fileContent, "id");
86
123
  const storyTitleIndex = getStoryMetaKeyIndex(fileContent, "title");
124
+ const componentImportIndex = lines.findIndex(
125
+ (line) => line.includes(componentName) && line.includes("import"),
126
+ );
87
127
 
88
- storyLines[storyIdIndex] = ` id: "${storybookId}",`;
89
- storyLines[storyTitleIndex] = ` title: "Custom / ${newComponentName}",`;
90
- storyLines[storyComponentImportIndex] =
91
- `import ${newComponentName} from "../${newComponentFileName}"`;
128
+ updatedContent = lines.join("\n").replaceAll(componentName, newComponentName);
129
+ lines = updatedContent.split("\n");
92
130
 
93
- updatedContent = storyLines.join("\n").replaceAll(componentName, newComponentName);
131
+ // replacing lines by indexes
132
+ lines[storyIdIndex] = ` id: "${storybookId}",`;
133
+ lines[storyTitleIndex] = ` title: "Custom / ${newComponentName}",`;
134
+ lines[componentImportIndex] = `import ${newComponentName} from "../${newComponentName}.vue";`;
135
+
136
+ updatedContent = lines.join("\n");
94
137
  }
95
138
 
96
- if (targetPath.endsWith(componentFileName)) {
97
- targetPath = targetPath.replace(componentFileName, newComponentFileName);
139
+ /* Renaming file */
140
+ let targetPath = filePath;
141
+ const [fileName] = filePath.split("/").reverse();
142
+
143
+ if (fileName.includes(componentName)) {
144
+ const [targetDir] = filePath.split(fileName);
145
+ const targetFileName = fileName.replace(componentName, newComponentName);
146
+
147
+ targetPath = path.join(targetDir, targetFileName);
98
148
 
99
149
  await rename(filePath, targetPath);
100
150
  }
101
151
 
152
+ /* Update file */
102
153
  await writeFile(targetPath, updatedContent);
103
154
  }
104
155
  }
@@ -1,18 +1,15 @@
1
1
  /* eslint-disable no-console */
2
2
 
3
- import { existsSync } from "node:fs";
4
3
  import path from "node:path";
5
4
  import { cwd } from "node:process";
6
- import { readFile, writeFile, rename, mkdir, readdir, copyFile } from "node:fs/promises";
5
+ import { existsSync } from "node:fs";
7
6
  import { styleText } from "node:util";
7
+ import { readFile, writeFile, rename, mkdir, readdir, copyFile } from "node:fs/promises";
8
8
 
9
+ import { getStorybookId } from "../utils/data.js";
9
10
  import { getDirFiles } from "../../utils/node/helper.js";
10
11
  import { replaceRelativeImports } from "../utils/format.js";
11
- import { getStorybookId } from "../utils/data.js";
12
-
13
- import { SRC_COMPONENTS_PATH, COMPONENTS_PATH } from "../constants.js";
14
-
15
- import { COMPONENTS, VUELESS_PACKAGE_DIR, VUELESS_LOCAL_DIR } from "../../constants.js";
12
+ import { COMPONENTS, VUELESS_PACKAGE_DIR, VUELESS_USER_COMPONENTS_DIR } from "../../constants.js";
16
13
 
17
14
  const BOILERPLATE_NAME = "UBoilerplate";
18
15
  const BOILERPLATE_PATH = path.join(cwd(), VUELESS_PACKAGE_DIR, "ui.boilerplate");
@@ -26,26 +23,34 @@ export async function createVuelessComponent(options) {
26
23
  return;
27
24
  }
28
25
 
29
- const isSrcDir = existsSync(path.join(cwd(), VUELESS_LOCAL_DIR));
30
- const destPath = isSrcDir
31
- ? path.join(SRC_COMPONENTS_PATH, componentName)
32
- : path.join(COMPONENTS_PATH, componentName);
33
- const absoluteDestPath = path.join(cwd(), destPath);
26
+ if (componentName in COMPONENTS) {
27
+ console.log(
28
+ styleText("red", `Component with name '${componentName}' already exists in Vueless UI.`),
29
+ );
30
+
31
+ return;
32
+ }
33
+
34
+ if (!componentName.startsWith("U")) {
35
+ console.log(styleText("red", `Component should have 'U' prefix (ex. 'UButtonCustom').`));
36
+
37
+ return;
38
+ }
34
39
 
35
- const isComponentExists = componentName in COMPONENTS || existsSync(absoluteDestPath);
40
+ const absoluteDestPath = path.join(cwd(), VUELESS_USER_COMPONENTS_DIR, componentName);
36
41
 
37
- if (isComponentExists) {
38
- console.log(styleText("red", `Component with name ${componentName} already exists.`));
42
+ if (existsSync(absoluteDestPath)) {
43
+ console.log(styleText("red", `Component with name '${componentName}' already exists.`));
39
44
 
40
45
  return;
41
46
  }
42
47
 
43
48
  await copyAndRenameFiles(BOILERPLATE_PATH, absoluteDestPath);
44
- await modifyCreatedComponent(absoluteDestPath, componentName);
49
+ await modifyCreatedComponent(componentName, absoluteDestPath);
45
50
 
46
51
  console.log(
47
- // eslint-disable-next-line prettier/prettier
48
- styleText("green", `The '${componentName}' was successfully created in the '${destPath}' directory.`,),
52
+ // eslint-disable-next-line vue/max-len, prettier/prettier
53
+ styleText("green", `The '${componentName}' was successfully created in the '${VUELESS_USER_COMPONENTS_DIR}/${componentName}' directory.`,),
49
54
  );
50
55
  }
51
56
 
@@ -55,11 +60,7 @@ async function copyAndRenameFiles(srcDir, destDir) {
55
60
 
56
61
  for (const entry of entries) {
57
62
  const srcPath = path.join(srcDir, entry.name);
58
-
59
- const renamed = entry.name.replace(".hidden", "");
60
- const destPath = path.join(destDir, renamed);
61
-
62
- console.log(entry.name, renamed);
63
+ const destPath = path.join(destDir, entry.name);
63
64
 
64
65
  entry.isDirectory()
65
66
  ? await copyAndRenameFiles(srcPath, destPath)
@@ -67,32 +68,64 @@ async function copyAndRenameFiles(srcDir, destDir) {
67
68
  }
68
69
  }
69
70
 
70
- async function modifyCreatedComponent(destPath, componentName) {
71
+ async function modifyCreatedComponent(componentName, destPath) {
71
72
  const destFiles = await getDirFiles(destPath, "");
72
73
  const storybookId = await getStorybookId();
73
74
 
74
75
  for await (const filePath of destFiles) {
75
76
  const fileContent = await readFile(filePath, "utf-8");
76
-
77
77
  let updatedContent = replaceRelativeImports(componentName, filePath, fileContent);
78
- let targetPath = filePath;
79
78
 
79
+ /* Renaming component name in constants */
80
80
  if (filePath.endsWith("constants.ts")) {
81
- updatedContent = updatedContent.replace(BOILERPLATE_NAME, componentName);
81
+ updatedContent = updatedContent.replaceAll(BOILERPLATE_NAME, componentName);
82
+ }
83
+
84
+ /* Renaming component name in tests */
85
+ if (filePath.endsWith("test.ts")) {
86
+ updatedContent = updatedContent.replaceAll(BOILERPLATE_NAME, componentName);
87
+ }
88
+
89
+ /* Renaming component name in types */
90
+ if (filePath.endsWith("types.ts")) {
91
+ updatedContent = updatedContent.replaceAll(BOILERPLATE_NAME, componentName);
82
92
  }
83
93
 
94
+ /* Renaming component name in components */
95
+ if (filePath.endsWith(".vue")) {
96
+ let lines = updatedContent.split("\n");
97
+
98
+ for (const [index, line] of lines.entries()) {
99
+ // Add some condition here in future if some edge cases appear
100
+ if (line.includes(componentName)) {
101
+ lines[index] = line.replaceAll(BOILERPLATE_NAME, componentName);
102
+ }
103
+ }
104
+
105
+ updatedContent = lines.join("\n");
106
+ }
107
+
108
+ /* Renaming component name in stories */
84
109
  if (filePath.endsWith("stories.ts")) {
85
110
  updatedContent = updatedContent
86
111
  .replaceAll(BOILERPLATE_NAME, componentName)
87
112
  .replace("{{component_id}}", String(storybookId));
88
113
  }
89
114
 
90
- if (targetPath.endsWith(`${BOILERPLATE_NAME}.vue`)) {
91
- targetPath = targetPath.replace(BOILERPLATE_NAME, componentName);
115
+ /* Renaming file */
116
+ let targetPath = filePath;
117
+ const [fileName] = filePath.split("/").reverse();
118
+
119
+ if (fileName.includes(BOILERPLATE_NAME)) {
120
+ const [targetDir] = filePath.split(fileName);
121
+ const targetFileName = fileName.replace(BOILERPLATE_NAME, componentName);
122
+
123
+ targetPath = path.join(targetDir, targetFileName);
92
124
 
93
125
  await rename(filePath, targetPath);
94
126
  }
95
127
 
128
+ /* Update file */
96
129
  await writeFile(targetPath, updatedContent);
97
130
  }
98
131
  }
@@ -1,3 +1 @@
1
- export const SRC_COMPONENTS_PATH: "/src/components";
2
- export const COMPONENTS_PATH: "/components";
3
1
  export const DEFAULT_VUELESS_CONFIG_CONTENT: "import { componentConfigs } from \"./.vueless\";\n\nexport default {\n /**\n * Global settings.\n */\n primary: \"grayscale\",\n neutral: \"gray\",\n text: 14,\n outline: 2,\n rounding: 8,\n letterSpacing: 0,\n disabledOpacity: 50,\n colorMode: \"auto\",\n\n /**\n * Component settings.\n */\n components: /*tw*/ {\n ...componentConfigs,\n },\n\n /**\n * Directive settings.\n */\n directives: {},\n\n /**\n * Light theme CSS variable settings.\n */\n lightTheme: {\n /* Primary colors */\n \"--vl-primary\": \"--vl-primary-600\",\n \"--vl-primary-lifted\": \"--vl-primary-700\",\n \"--vl-primary-accented\": \"--vl-primary-800\",\n\n /* Secondary colors */\n \"--vl-secondary\": \"--vl-neutral-500\",\n \"--vl-secondary-lifted\": \"--vl-neutral-600\",\n \"--vl-secondary-accented\": \"--vl-neutral-700\",\n\n /* Success colors */\n \"--vl-success\": \"--color-green-600\",\n \"--vl-success-lifted\": \"--color-green-700\",\n \"--vl-success-accented\": \"--color-green-800\",\n\n /* Info colors */\n \"--vl-info\": \"--color-blue-600\",\n \"--vl-info-lifted\": \"--color-blue-700\",\n \"--vl-info-accented\": \"--color-blue-800\",\n\n /* Notice colors */\n \"--vl-notice\": \"--color-violet-600\",\n \"--vl-notice-lifted\": \"--color-violet-700\",\n \"--vl-notice-accented\": \"--color-violet-800\",\n\n /* Warning colors */\n \"--vl-warning\": \"--color-orange-600\",\n \"--vl-warning-lifted\": \"--color-orange-700\",\n \"--vl-warning-accented\": \"--color-orange-800\",\n\n /* Error colors */\n \"--vl-error\": \"--color-red-600\",\n \"--vl-error-lifted\": \"--color-red-700\",\n \"--vl-error-accented\": \"--color-red-800\",\n\n /* Grayscale colors */\n \"--vl-grayscale\": \"--vl-neutral-900\",\n \"--vl-grayscale-lifted\": \"--vl-neutral-800\",\n \"--vl-grayscale-accented\": \"--vl-neutral-700\",\n\n /* Neutral colors */\n \"--vl-neutral\": \"--vl-neutral-500\",\n \"--vl-neutral-lifted\": \"--vl-neutral-600\",\n \"--vl-neutral-accented\": \"--vl-neutral-700\",\n\n /* Text neutral colors */\n \"--vl-text-inverted\": \"--color-white\",\n \"--vl-text-muted\": \"--vl-neutral-400\",\n \"--vl-text-lifted\": \"--vl-neutral-500\",\n \"--vl-text-accented\": \"--vl-neutral-600\",\n \"--vl-text\": \"--vl-neutral-900\",\n\n /* Border neutral colors */\n \"--vl-border-muted\": \"--vl-neutral-200\",\n \"--vl-border\": \"--vl-neutral-300\",\n \"--vl-border-lifted\": \"--vl-neutral-400\",\n \"--vl-border-accented\": \"--vl-neutral-600\",\n\n /* Background neutral colors */\n \"--vl-bg\": \"--color-white\",\n \"--vl-bg-muted\": \"--vl-neutral-50\",\n \"--vl-bg-lifted\": \"--vl-neutral-100\",\n \"--vl-bg-accented\": \"--vl-neutral-200\",\n \"--vl-bg-inverted\": \"--vl-neutral-900\",\n },\n\n /**\n * Dark theme CSS variable settings.\n */\n darkTheme: {\n /* Primary colors */\n \"--vl-primary\": \"--vl-primary-400\",\n \"--vl-primary-lifted\": \"--vl-primary-500\",\n \"--vl-primary-accented\": \"--vl-primary-600\",\n\n /* Secondary colors */\n \"--vl-secondary\": \"--vl-neutral-300\",\n \"--vl-secondary-lifted\": \"--vl-neutral-400\",\n \"--vl-secondary-accented\": \"--vl-neutral-500\",\n\n /* Success colors */\n \"--vl-success\": \"--color-green-400\",\n \"--vl-success-lifted\": \"--color-green-500\",\n \"--vl-success-accented\": \"--color-green-600\",\n\n /* Info colors */\n \"--vl-info\": \"--color-blue-400\",\n \"--vl-info-lifted\": \"--color-blue-500\",\n \"--vl-info-accented\": \"--color-blue-600\",\n\n /* Notice colors */\n \"--vl-notice\": \"--color-violet-400\",\n \"--vl-notice-lifted\": \"--color-violet-500\",\n \"--vl-notice-accented\": \"--color-violet-600\",\n\n /* Warning colors */\n \"--vl-warning\": \"--color-orange-400\",\n \"--vl-warning-lifted\": \"--color-orange-500\",\n \"--vl-warning-accented\": \"--color-orange-600\",\n\n /* Error colors */\n \"--vl-error\": \"--color-red-400\",\n \"--vl-error-lifted\": \"--color-red-500\",\n \"--vl-error-accented\": \"--color-red-600\",\n\n /* Grayscale colors */\n \"--vl-grayscale\": \"--vl-neutral-100\",\n \"--vl-grayscale-lifted\": \"--vl-neutral-200\",\n \"--vl-grayscale-accented\": \"--vl-neutral-300\",\n\n /* Neutral colors */\n \"--vl-neutral\": \"--vl-neutral-300\",\n \"--vl-neutral-lifted\": \"--vl-neutral-400\",\n \"--vl-neutral-accented\": \"--vl-neutral-500\",\n\n /* Text neutral colors */\n \"--vl-text-inverted\": \"--vl-neutral-900\",\n \"--vl-text-muted\": \"--vl-neutral-600\",\n \"--vl-text-lifted\": \"--vl-neutral-400\",\n \"--vl-text-accented\": \"--vl-neutral-300\",\n \"--vl-text\": \"--vl-neutral-100\",\n\n /* Border neutral colors */\n \"--vl-border-muted\": \"--vl-neutral-800\",\n \"--vl-border\": \"--vl-neutral-700\",\n \"--vl-border-lifted\": \"--vl-neutral-600\",\n \"--vl-border-accented\": \"--vl-neutral-400\",\n\n /* Background neutral colors */\n \"--vl-bg\": \"--vl-neutral-900\",\n \"--vl-bg-muted\": \"--vl-neutral-800\",\n \"--vl-bg-lifted\": \"--vl-neutral-800\",\n \"--vl-bg-accented\": \"--vl-neutral-700\",\n \"--vl-bg-inverted\": \"--vl-neutral-100\",\n },\n};\n";
package/bin/constants.js CHANGED
@@ -1,6 +1,3 @@
1
- export const SRC_COMPONENTS_PATH = "/src/components";
2
- export const COMPONENTS_PATH = "/components";
3
-
4
1
  export const DEFAULT_VUELESS_CONFIG_CONTENT = `import { componentConfigs } from "./.vueless";
5
2
 
6
3
  export default {
package/bin/utils/data.js CHANGED
@@ -5,30 +5,26 @@ import { readFile } from "node:fs/promises";
5
5
 
6
6
  import { getDirFiles } from "../../utils/node/helper.js";
7
7
 
8
- import { SRC_COMPONENTS_PATH, COMPONENTS_PATH } from "../constants.js";
9
- import { VUELESS_PACKAGE_DIR } from "../../constants.js";
8
+ import { VUELESS_PACKAGE_DIR, VUELESS_USER_COMPONENTS_DIR } from "../../constants.js";
10
9
 
11
10
  const storiesName = "stories.ts";
12
11
 
12
+ /**
13
+ * Retrieves the next available Storybook ID by scanning story files for the highest existing ID and incrementing it.
14
+ *
15
+ * @return {Promise<number>} A promise that resolves to the next available Storybook ID.
16
+ */
13
17
  export async function getStorybookId() {
14
- const srcComponentsDir = path.join(cwd(), SRC_COMPONENTS_PATH);
15
- const componentsDir = path.join(cwd(), COMPONENTS_PATH);
16
18
  const vuelessPackagePath = path.join(cwd(), VUELESS_PACKAGE_DIR);
17
- const isSrcComponentsDir = existsSync(srcComponentsDir);
18
- const isComponentsDir = existsSync(componentsDir);
19
+ const vuelessUserComponentsPath = path.join(cwd(), VUELESS_USER_COMPONENTS_DIR);
19
20
 
20
21
  const stories = await getDirFiles(vuelessPackagePath, storiesName);
22
+ const hasVuelessUserComponentsDir = existsSync(vuelessUserComponentsPath);
21
23
 
22
- if (isSrcComponentsDir) {
23
- const srcComponentsDirStories = await getDirFiles(srcComponentsDir, storiesName);
24
+ if (hasVuelessUserComponentsDir) {
25
+ const customStories = await getDirFiles(vuelessUserComponentsPath, storiesName);
24
26
 
25
- stories.push(...srcComponentsDirStories);
26
- }
27
-
28
- if (isComponentsDir) {
29
- const componentsDirStories = await getDirFiles(componentsDir, storiesName);
30
-
31
- stories.push(...componentsDirStories);
27
+ stories.push(...customStories);
32
28
  }
33
29
 
34
30
  let id = 200000;
@@ -51,6 +47,14 @@ export async function getStorybookId() {
51
47
  return id + 10;
52
48
  }
53
49
 
50
+ /**
51
+ * Retrieves the line index within a file content where a specific key appears
52
+ * as a top-level property in an exported default object.
53
+ *
54
+ * @param {string} fileContent - The content of the file to search through.
55
+ * @param {string} key - The key to locate within the top-level export block.
56
+ * @return {number} The zero-based index of the line where the key is found, or -1 if the key is not found.
57
+ */
54
58
  export function getStoryMetaKeyIndex(fileContent, key) {
55
59
  const lines = fileContent.split("\n");
56
60
  let insideExportBlock = false;
@@ -2,6 +2,14 @@ import path from "node:path";
2
2
 
3
3
  import { VUELESS_LIBRARY } from "../../constants.js";
4
4
 
5
+ /**
6
+ * Replaces relative import paths in the provided file content based on the given component name and file path.
7
+ *
8
+ * @param {string} componentName - The name of the component, used to determine if the file is at the top level.
9
+ * @param {string} filePath - The file path to check if the file is located at the top level of the component.
10
+ * @param {string} fileContent - The content of the file where the relative import paths need to be replaced.
11
+ * @return {string} The updated file content with the adjusted relative import paths.
12
+ */
5
13
  export function replaceRelativeImports(componentName, filePath, fileContent) {
6
14
  const isTopLevelFile = path.dirname(filePath).endsWith(componentName);
7
15
  const contentLines = fileContent.split("\n");
@@ -9,6 +17,13 @@ export function replaceRelativeImports(componentName, filePath, fileContent) {
9
17
  return contentLines.map((line) => replaceRelativeLineImports(line, isTopLevelFile)).join("\n");
10
18
  }
11
19
 
20
+ /**
21
+ * Replaces relative import paths in a given line of code with a new base path for certain types of imports.
22
+ *
23
+ * @param {string} line - The line of code containing import statements to process.
24
+ * @param {boolean} isTopLevelFile - Indicates if the file is a top-level file within the project structure.
25
+ * @return {string} The modified line of code with adjusted import paths, or the original line if no changes are required.
26
+ */
12
27
  function replaceRelativeLineImports(line, isTopLevelFile) {
13
28
  const importRegex = /import\s+(?:[\w\s{},*]+)\s+from\s+(['"])(\.\.?\/.*?)(\.[tj]s)?\1(?!\?)/g;
14
29
  const multiLineImportRegExp = /from\s+(['"])(\.\.?\/.*?)(\.[tj]s)?\1(?!\?)/g; // Matches import's "from" part
@@ -23,8 +38,8 @@ function replaceRelativeLineImports(line, isTopLevelFile) {
23
38
  }
24
39
 
25
40
  if (line.startsWith("}")) {
26
- return line.replace(multiLineImportRegExp, (match, quote, oldPath, ext) => {
27
- return match.replace(oldPath + (ext || ""), VUELESS_LIBRARY);
41
+ return line.replace(multiLineImportRegExp, (match) => {
42
+ return match.replace(relativePathStartRegExp, `${VUELESS_LIBRARY}/`);
28
43
  });
29
44
  }
30
45
 
package/constants.d.ts CHANGED
@@ -290,16 +290,21 @@ export namespace TAILWIND_MERGE_EXTENSION {
290
290
  }
291
291
  }
292
292
  export namespace DEFAULT_SVGO_CONFIG {
293
- let plugins: {
293
+ let plugins: ({
294
294
  name: string;
295
295
  params: {
296
- overrides: {
297
- convertColors: {
298
- currentColor: boolean;
299
- };
300
- };
296
+ attrs: string;
297
+ attributes?: undefined;
301
298
  };
302
- }[];
299
+ } | {
300
+ name: string;
301
+ params: {
302
+ attributes: {
303
+ fill: string;
304
+ }[];
305
+ attrs?: undefined;
306
+ };
307
+ })[];
303
308
  }
304
309
  export const INTERNAL_ENV: "internal";
305
310
  export const STORYBOOK_ENV: "storybook";
@@ -307,6 +312,7 @@ export const NUXT_MODULE_ENV: "nuxt-module";
307
312
  export const VUELESS_LIBRARY: "vueless";
308
313
  export const INTERNAL_ICONS_LIBRARY: "internal";
309
314
  export const STORYBOOK_ICONS_LIBRARY: "storybook";
315
+ export const SRC_DIR: "src";
310
316
  export const CACHE_DIR: ".cache";
311
317
  export const NODE_MODULES_DIR: "node_modules";
312
318
  export const VUELESS_PACKAGE_DIR: "node_modules/vueless";
@@ -323,6 +329,8 @@ export const VUELESS_MERGED_CONFIGS_CACHED_DIR: "node_modules/.cache/vueless/mer
323
329
  export const VUELESS_CONFIG_FILE_NAME: "vueless.config";
324
330
  export const CONFIG_INDEX_FILE_NAME: "index";
325
331
  export const VUELESS_CONFIG_DIR: ".vueless";
332
+ export const VUELESS_USER_COMPONENTS_DIR: ".vueless/components";
333
+ export const SRC_USER_COMPONENTS_DIR: "src/components";
326
334
  export const DEFAULT_EXIT_CODE: 0;
327
335
  export const FAILURE_CODE: 1;
328
336
  export const PX_IN_REM: 16;
package/constants.js CHANGED
@@ -368,13 +368,15 @@ export const TAILWIND_MERGE_EXTENSION = {
368
368
  export const DEFAULT_SVGO_CONFIG = {
369
369
  plugins: [
370
370
  {
371
- name: "preset-default",
371
+ name: "removeAttrs",
372
372
  params: {
373
- overrides: {
374
- convertColors: {
375
- currentColor: true,
376
- },
377
- },
373
+ attrs: "(fill)",
374
+ },
375
+ },
376
+ {
377
+ name: "addAttributesToSVGElement",
378
+ params: {
379
+ attributes: [{ fill: "currentColor" }],
378
380
  },
379
381
  },
380
382
  ],
@@ -389,11 +391,12 @@ export const VUELESS_LIBRARY = "vueless";
389
391
  export const INTERNAL_ICONS_LIBRARY = "internal";
390
392
  export const STORYBOOK_ICONS_LIBRARY = "storybook";
391
393
 
394
+ export const SRC_DIR = "src";
392
395
  export const CACHE_DIR = ".cache";
393
396
  export const NODE_MODULES_DIR = "node_modules";
394
397
  export const VUELESS_PACKAGE_DIR = `${NODE_MODULES_DIR}/vueless`;
395
398
  export const VUELESS_CACHE_DIR = `${NODE_MODULES_DIR}/${CACHE_DIR}/vueless`;
396
- export const VUELESS_LOCAL_DIR = "src";
399
+ export const VUELESS_LOCAL_DIR = SRC_DIR;
397
400
  export const ICONS_DIR = "icons";
398
401
  export const ICONS_VUELESS_DIR = `${VUELESS_PACKAGE_DIR}/${ICONS_DIR}`;
399
402
  export const ICONS_CACHED_DIR = `${VUELESS_CACHE_DIR}/${ICONS_DIR}`;
@@ -407,6 +410,8 @@ export const VUELESS_MERGED_CONFIGS_CACHED_DIR = `${VUELESS_CACHE_DIR}/mergedCon
407
410
  export const VUELESS_CONFIG_FILE_NAME = "vueless.config";
408
411
  export const CONFIG_INDEX_FILE_NAME = "index";
409
412
  export const VUELESS_CONFIG_DIR = ".vueless";
413
+ export const VUELESS_USER_COMPONENTS_DIR = `${VUELESS_CONFIG_DIR}/components`;
414
+ export const SRC_USER_COMPONENTS_DIR = `${SRC_DIR}/components`;
410
415
 
411
416
  /* System error codes */
412
417
  export const DEFAULT_EXIT_CODE = 0;
package/index.d.ts CHANGED
@@ -7,17 +7,18 @@ export {
7
7
  isSSR,
8
8
  isCSR,
9
9
  setTitle,
10
+ getStored,
10
11
  getRandomId,
11
12
  getCookie,
12
13
  setCookie,
13
14
  deleteCookie,
14
15
  createDebounce,
15
- hasSlotContent
16
+ hasSlotContent,
16
17
  } from "./utils/helper";
17
- export { getStored, setTheme, cssVar } from "./utils/theme";
18
18
  export { isMac, isPWA, isIOS, isAndroid, isMobileApp, isWindows } from "./utils/platform";
19
19
  export { cx, cva, compose, getDefaults, setVuelessConfig, setColor, vuelessConfig } from "./utils/ui";
20
- export { getArgTypes, getSlotNames, getSlotsFragment, getSource, getDocsDescription } from "./utils/storybook";
20
+ export { getTheme, setTheme, resetTheme, normalizeThemeConfig, cssVar } from "./utils/theme";
21
+ export { getArgs, getArgTypes, getSlotNames, getSlotsFragment, getSource, getDocsDescription } from "./utils/storybook";
21
22
  /* adapters */
22
23
  export { default as defaultEnLocale } from "./adapter.locale/locales/en";
23
24
  export { createVuelessAdapter } from "./adapter.locale/vueless";
@@ -28,6 +29,8 @@ export { default as useUI } from "./composables/useUI";
28
29
  export { useDarkMode } from "./composables/useDarkMode";
29
30
  export { useLoaderProgress } from "./ui.loader-progress/useLoaderProgress";
30
31
  export { useMutationObserver } from "./composables/useMutationObserver";
32
+ export { Direction, useAutoPosition } from "./composables/useAutoPosition";
33
+ export { useComponentLocaleMessages } from "./composables/useComponentLocaleMassages";
31
34
  /* loaders */
32
35
  export { loaderProgressOn, loaderProgressOff } from "./ui.loader-progress/utilLoaderProgress";
33
36
  export { useLoaderOverlay } from "./ui.loader-overlay/useLoaderOverlay";
@@ -133,6 +136,7 @@ export type {
133
136
  ThemeConfigText,
134
137
  ThemeConfigRounding,
135
138
  ThemeConfigOutline,
139
+ MergedThemeConfig,
136
140
  NestedComponent,
137
141
  ComponentConfig,
138
142
  ComponentDefaults,
package/index.ts CHANGED
@@ -13,17 +13,18 @@ export {
13
13
  isSSR,
14
14
  isCSR,
15
15
  setTitle,
16
+ getStored,
16
17
  getRandomId,
17
18
  getCookie,
18
19
  setCookie,
19
20
  deleteCookie,
20
21
  createDebounce,
21
- hasSlotContent
22
+ hasSlotContent,
22
23
  } from "./utils/helper";
23
- export { getStored, setTheme, cssVar } from "./utils/theme";
24
24
  export { isMac, isPWA, isIOS, isAndroid, isMobileApp, isWindows } from "./utils/platform";
25
25
  export { cx, cva, compose, getDefaults, setVuelessConfig, setColor, vuelessConfig } from "./utils/ui";
26
- export { getArgTypes, getSlotNames, getSlotsFragment, getSource, getDocsDescription } from "./utils/storybook";
26
+ export { getTheme, setTheme, resetTheme, normalizeThemeConfig, cssVar } from "./utils/theme";
27
+ export { getArgs, getArgTypes, getSlotNames, getSlotsFragment, getSource, getDocsDescription } from "./utils/storybook";
27
28
  /* adapters */
28
29
  export { default as defaultEnLocale } from "./adapter.locale/locales/en";
29
30
  export { createVuelessAdapter } from "./adapter.locale/vueless";
@@ -34,6 +35,8 @@ export { default as useUI } from "./composables/useUI";
34
35
  export { useDarkMode } from "./composables/useDarkMode";
35
36
  export { useLoaderProgress } from "./ui.loader-progress/useLoaderProgress";
36
37
  export { useMutationObserver } from "./composables/useMutationObserver";
38
+ export { Direction, useAutoPosition } from "./composables/useAutoPosition";
39
+ export { useComponentLocaleMessages } from "./composables/useComponentLocaleMassages";
37
40
  /* loaders */
38
41
  export { loaderProgressOn, loaderProgressOff } from "./ui.loader-progress/utilLoaderProgress";
39
42
  export { useLoaderOverlay } from "./ui.loader-overlay/useLoaderOverlay";
@@ -139,6 +142,7 @@ export type {
139
142
  ThemeConfigText,
140
143
  ThemeConfigRounding,
141
144
  ThemeConfigOutline,
145
+ MergedThemeConfig,
142
146
  NestedComponent,
143
147
  ComponentConfig,
144
148
  ComponentDefaults,