@stachelock/ui 0.1.9 → 0.2.1
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/CUSTOMIZATION.md +325 -0
- package/dist/index.js +391 -188
- package/dist/index.js.map +1 -1
- package/dist/src/config/css-variables.d.ts +5 -0
- package/dist/src/config/css-variables.d.ts.map +1 -0
- package/dist/src/config/design-tokens.d.ts +52 -0
- package/dist/src/config/design-tokens.d.ts.map +1 -0
- package/dist/src/config/index.d.ts +3 -0
- package/dist/src/config/index.d.ts.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/plugin/configure.d.ts +28 -0
- package/dist/src/plugin/configure.d.ts.map +1 -0
- package/dist/src/plugin/index.d.ts +2 -0
- package/dist/src/plugin/index.d.ts.map +1 -0
- package/examples/custom-tokens.json +70 -0
- package/package.json +11 -3
- package/scripts/build-css.cjs +29 -0
- package/scripts/generate-config.cjs +83 -0
- package/scripts/generateRecursiveIndex.cjs +255 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/* eslint-env node */
|
|
2
|
+
/* eslint-disable no-undef */
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// Function to convert to camelCase
|
|
7
|
+
function toCamelCase(str) {
|
|
8
|
+
return str.replace(/[_-](.)/g, (_, group1) => group1.toUpperCase());
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Function to convert to PascalCase
|
|
12
|
+
function toPascalCase(str) {
|
|
13
|
+
const camelCase = toCamelCase(str);
|
|
14
|
+
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Function to generate export name for components
|
|
18
|
+
function generateComponentExportName(fileName, directoryName) {
|
|
19
|
+
const cleanFileName = fileName.replace(/^Ui/, '').replace(/^Sl/, '');
|
|
20
|
+
const pascalFileName = toPascalCase(cleanFileName);
|
|
21
|
+
|
|
22
|
+
// For base components, just return the clean name
|
|
23
|
+
if (directoryName === 'components') {
|
|
24
|
+
return pascalFileName;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// For subdirectories, use a more intuitive naming
|
|
28
|
+
if (['layouts', 'inputs', 'calendars', 'forms'].includes(directoryName)) {
|
|
29
|
+
// Remove the 's' from the end and capitalize
|
|
30
|
+
const singularDirName = directoryName.slice(0, -1);
|
|
31
|
+
const pascalDirName = toPascalCase(singularDirName);
|
|
32
|
+
|
|
33
|
+
// Special cases for better naming
|
|
34
|
+
if (singularDirName === 'layout') {
|
|
35
|
+
return pascalFileName; // Just use the component name for layouts
|
|
36
|
+
}
|
|
37
|
+
if (singularDirName === 'input') {
|
|
38
|
+
return pascalFileName; // Just use the component name for inputs
|
|
39
|
+
}
|
|
40
|
+
if (singularDirName === 'calendar') {
|
|
41
|
+
return pascalFileName; // Just use the component name for calendars
|
|
42
|
+
}
|
|
43
|
+
if (singularDirName === 'form') {
|
|
44
|
+
// Handle naming conflicts with types
|
|
45
|
+
if (fileName === 'DynamicFormField') {
|
|
46
|
+
return 'FormField'; // Avoid conflict with type
|
|
47
|
+
}
|
|
48
|
+
return pascalFileName; // Just use the component name for forms
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return `${pascalDirName}${pascalFileName}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return pascalFileName;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Function to generate index file for a directory
|
|
58
|
+
function generateIndexFile(directoryPath, baseDirectoryPath = directoryPath) {
|
|
59
|
+
const files = fs.readdirSync(directoryPath, { withFileTypes: true });
|
|
60
|
+
let exportStatements = [];
|
|
61
|
+
let hasExports = false;
|
|
62
|
+
|
|
63
|
+
for (const file of files) {
|
|
64
|
+
if (file.isDirectory()) {
|
|
65
|
+
// Skip certain directories
|
|
66
|
+
if (['tests', 'test', '__tests__', 'node_modules', '.git'].includes(file.name.toLowerCase())) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Recursively handle subdirectories
|
|
71
|
+
const subDirectoryPath = path.join(directoryPath, file.name);
|
|
72
|
+
if (generateIndexFile(subDirectoryPath, baseDirectoryPath)) {
|
|
73
|
+
exportStatements.push(`export * from './${file.name}';`);
|
|
74
|
+
hasExports = true;
|
|
75
|
+
}
|
|
76
|
+
} else if (file.name.endsWith('.vue') && file.name !== 'index.vue') {
|
|
77
|
+
const fileName = file.name.replace('.vue', '');
|
|
78
|
+
const directoryName = path.basename(directoryPath);
|
|
79
|
+
const exportName = generateComponentExportName(fileName, directoryName);
|
|
80
|
+
|
|
81
|
+
exportStatements.push(`export { default as ${exportName} } from './${fileName}.vue';`);
|
|
82
|
+
hasExports = true;
|
|
83
|
+
} else if (file.name.endsWith('.ts') && file.name !== 'index.ts' && !file.name.endsWith('.d.ts')) {
|
|
84
|
+
const fileName = file.name.replace('.ts', '');
|
|
85
|
+
// For types directory, export all type files
|
|
86
|
+
if (path.basename(baseDirectoryPath) === 'types') {
|
|
87
|
+
exportStatements.push(`export * from './${fileName}';`);
|
|
88
|
+
} else {
|
|
89
|
+
exportStatements.push(`export * from './${fileName}';`);
|
|
90
|
+
}
|
|
91
|
+
hasExports = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (hasExports) {
|
|
96
|
+
const indexPath = path.join(directoryPath, 'index.ts');
|
|
97
|
+
const content = exportStatements.join('\n') + '\n';
|
|
98
|
+
|
|
99
|
+
// Only write if content is different to avoid unnecessary file changes
|
|
100
|
+
if (!fs.existsSync(indexPath) || fs.readFileSync(indexPath, 'utf8') !== content) {
|
|
101
|
+
fs.writeFileSync(indexPath, content);
|
|
102
|
+
console.log(`✅ Generated index.ts for ${path.relative(baseDirectoryPath, directoryPath)}`);
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Function to generate main index file
|
|
111
|
+
function generateMainIndexFile(srcDirectoryPath) {
|
|
112
|
+
const mainIndexPath = path.join(srcDirectoryPath, 'index.ts');
|
|
113
|
+
|
|
114
|
+
// Generate new content - clean, non-prefixed exports only
|
|
115
|
+
const exportStatements = [
|
|
116
|
+
"// Types",
|
|
117
|
+
"export * from './types';",
|
|
118
|
+
"",
|
|
119
|
+
"// Utils",
|
|
120
|
+
"export * from './utils/id';",
|
|
121
|
+
"export * from './utils/component-registry';",
|
|
122
|
+
"",
|
|
123
|
+
"// Configuration System",
|
|
124
|
+
"export * from './config/design-tokens';",
|
|
125
|
+
"export * from './config/css-variables';",
|
|
126
|
+
"",
|
|
127
|
+
"// Base UI Components",
|
|
128
|
+
"export * from './components';",
|
|
129
|
+
"",
|
|
130
|
+
"// Layout Components",
|
|
131
|
+
"export * from './components/layouts';",
|
|
132
|
+
"",
|
|
133
|
+
"// Input Components",
|
|
134
|
+
"export * from './components/inputs';",
|
|
135
|
+
"",
|
|
136
|
+
"// Calendar Components",
|
|
137
|
+
"export * from './components/calendars';",
|
|
138
|
+
"",
|
|
139
|
+
"// Form Components",
|
|
140
|
+
"export * from './components/forms';",
|
|
141
|
+
"",
|
|
142
|
+
"// Plugin interface and Vue plugin",
|
|
143
|
+
"export { StachelockUI, type StachelockUIOptions } from './plugin';",
|
|
144
|
+
"export { StachelockUI as default } from './plugin';"
|
|
145
|
+
];
|
|
146
|
+
|
|
147
|
+
const newContent = exportStatements.join('\n') + '\n';
|
|
148
|
+
|
|
149
|
+
// Always write to ensure consistency
|
|
150
|
+
fs.writeFileSync(mainIndexPath, newContent);
|
|
151
|
+
console.log(`✅ Generated main index.ts`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Function to generate plugin file
|
|
155
|
+
function generatePluginFile(srcDirectoryPath) {
|
|
156
|
+
const pluginPath = path.join(srcDirectoryPath, 'plugin.ts');
|
|
157
|
+
|
|
158
|
+
const pluginContent = `import type { App } from 'vue';
|
|
159
|
+
import * as components from './components';
|
|
160
|
+
import * as layouts from './components/layouts';
|
|
161
|
+
import * as inputs from './components/inputs';
|
|
162
|
+
import * as calendars from './components/calendars';
|
|
163
|
+
import * as forms from './components/forms';
|
|
164
|
+
|
|
165
|
+
// Combine all components
|
|
166
|
+
const allComponents = {
|
|
167
|
+
...components,
|
|
168
|
+
...layouts,
|
|
169
|
+
...inputs,
|
|
170
|
+
...calendars,
|
|
171
|
+
...forms,
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// Plugin interface
|
|
175
|
+
export interface StachelockUIOptions {
|
|
176
|
+
/**
|
|
177
|
+
* Component name prefix (default: 'Sl')
|
|
178
|
+
*/
|
|
179
|
+
prefix?: string;
|
|
180
|
+
/**
|
|
181
|
+
* Array of component names to install globally
|
|
182
|
+
*/
|
|
183
|
+
components?: string[];
|
|
184
|
+
/**
|
|
185
|
+
* Whether to install all components globally
|
|
186
|
+
*/
|
|
187
|
+
installAll?: boolean;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Vue plugin
|
|
191
|
+
export const StachelockUI = {
|
|
192
|
+
install(app: App, options: StachelockUIOptions = {}) {
|
|
193
|
+
const { prefix = 'Sl', installAll = false, components: selectedComponents } = options;
|
|
194
|
+
|
|
195
|
+
// Register components
|
|
196
|
+
Object.entries(allComponents).forEach(([name, component]) => {
|
|
197
|
+
const shouldInstall = installAll ||
|
|
198
|
+
(selectedComponents && selectedComponents.includes(name)) ||
|
|
199
|
+
(!selectedComponents && !installAll);
|
|
200
|
+
|
|
201
|
+
if (shouldInstall) {
|
|
202
|
+
// Register non-prefixed
|
|
203
|
+
app.component(name, component);
|
|
204
|
+
// Also register prefixed alias for back-compat
|
|
205
|
+
const prefixedName = name.startsWith(prefix) ? name : \`\${prefix}\${name}\`;
|
|
206
|
+
app.component(prefixedName, component);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export default StachelockUI;
|
|
213
|
+
`;
|
|
214
|
+
|
|
215
|
+
// Only write if content is different
|
|
216
|
+
if (!fs.existsSync(pluginPath) || fs.readFileSync(pluginPath, 'utf8') !== pluginContent) {
|
|
217
|
+
fs.writeFileSync(pluginPath, pluginContent);
|
|
218
|
+
console.log(`✅ Generated plugin.ts`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Main execution
|
|
223
|
+
function main() {
|
|
224
|
+
console.log('🚀 Generating recursive index files for stachelock-ui...\n');
|
|
225
|
+
|
|
226
|
+
const srcDirectoryPath = path.join(__dirname, '../src');
|
|
227
|
+
|
|
228
|
+
if (!fs.existsSync(srcDirectoryPath)) {
|
|
229
|
+
console.error('❌ src directory not found!');
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
try {
|
|
234
|
+
// Generate index files for all subdirectories
|
|
235
|
+
generateIndexFile(srcDirectoryPath);
|
|
236
|
+
|
|
237
|
+
// Generate main index file
|
|
238
|
+
generateMainIndexFile(srcDirectoryPath);
|
|
239
|
+
|
|
240
|
+
// Don't generate plugin file - we have a custom one
|
|
241
|
+
// generatePluginFile(srcDirectoryPath);
|
|
242
|
+
|
|
243
|
+
console.log('\n✨ All index files generated successfully!');
|
|
244
|
+
} catch (error) {
|
|
245
|
+
console.error('❌ Error generating index files:', error);
|
|
246
|
+
process.exit(1);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Run if called directly
|
|
251
|
+
if (require.main === module) {
|
|
252
|
+
main();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
module.exports = { generateIndexFile, generateMainIndexFile, generatePluginFile };
|