@stachelock/ui 0.1.8 → 0.2.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/CUSTOMIZATION.md +325 -0
- 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/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 +251 -0
package/CUSTOMIZATION.md
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
# Customizing Stachelock UI Design Tokens
|
|
2
|
+
|
|
3
|
+
Stachelock UI now supports customizing design tokens (colors, spacing, typography, etc.) to match your project's design system while maintaining the `sl-` prefixed utility classes.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The customization system allows you to:
|
|
8
|
+
- Override default colors, spacing, shadows, and typography
|
|
9
|
+
- Generate custom CSS variables and Tailwind configurations
|
|
10
|
+
- Maintain the `sl-` prefix to avoid conflicts with your existing styles
|
|
11
|
+
- Use both programmatic configuration and build-time generation
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### 1. Create a Custom Tokens File
|
|
16
|
+
|
|
17
|
+
Create a JSON file (e.g., `my-tokens.json`) with your custom design tokens:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"colors": {
|
|
22
|
+
"primary": {
|
|
23
|
+
"50": "#f0f9ff",
|
|
24
|
+
"100": "#e0f2fe",
|
|
25
|
+
"500": "#0ea5e9",
|
|
26
|
+
"600": "#0284c7",
|
|
27
|
+
"700": "#0369a1"
|
|
28
|
+
},
|
|
29
|
+
"stachelock": {
|
|
30
|
+
"600": "#dc2626",
|
|
31
|
+
"700": "#b91c1c"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"spacing": {
|
|
35
|
+
"18": "4.5rem",
|
|
36
|
+
"22": "5.5rem"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 2. Generate Custom Configuration
|
|
42
|
+
|
|
43
|
+
Use the CLI tool to generate custom CSS variables and Tailwind config:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# From your project directory
|
|
47
|
+
npx @stachelock/ui generate-config ./my-tokens.json ./generated/
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
This will create:
|
|
51
|
+
- `stachelock-ui-variables.css` - CSS custom properties
|
|
52
|
+
- `stachelock-ui-tailwind.config.js` - Tailwind configuration
|
|
53
|
+
- `stachelock-ui-tokens.json` - Merged tokens for reference
|
|
54
|
+
|
|
55
|
+
### 3. Import and Use
|
|
56
|
+
|
|
57
|
+
In your main CSS file:
|
|
58
|
+
```css
|
|
59
|
+
@import "./generated/stachelock-ui-variables.css";
|
|
60
|
+
@import "@stachelock/ui/style.css";
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
In your `tailwind.config.js`:
|
|
64
|
+
```javascript
|
|
65
|
+
const stachelockConfig = require('./generated/stachelock-ui-tailwind.config.js');
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
content: ["./src/**/*.{vue,js,ts,jsx,tsx}"],
|
|
69
|
+
theme: {
|
|
70
|
+
extend: {
|
|
71
|
+
...stachelockConfig.theme.extend
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Programmatic Configuration
|
|
78
|
+
|
|
79
|
+
### Using the Vue Plugin
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { createApp } from 'vue';
|
|
83
|
+
import { StachelockUI } from '@stachelock/ui';
|
|
84
|
+
import App from './App.vue';
|
|
85
|
+
|
|
86
|
+
const app = createApp(App);
|
|
87
|
+
|
|
88
|
+
app.use(StachelockUI, {
|
|
89
|
+
designTokens: {
|
|
90
|
+
colors: {
|
|
91
|
+
primary: {
|
|
92
|
+
600: '#0ea5e9',
|
|
93
|
+
700: '#0369a1'
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
app.mount('#app');
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Advanced Plugin Usage
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { StachelockUI } from '@stachelock/ui';
|
|
106
|
+
|
|
107
|
+
// Configure after installation
|
|
108
|
+
StachelockUI.configure({
|
|
109
|
+
designTokens: {
|
|
110
|
+
colors: {
|
|
111
|
+
brand: {
|
|
112
|
+
500: '#ff6b6b',
|
|
113
|
+
600: '#ee5a52'
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
prefix: 'sl-', // Keep default prefix
|
|
118
|
+
injectCSS: true // Automatically inject CSS variables
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Get current design tokens
|
|
122
|
+
const tokens = StachelockUI.getDesignTokens();
|
|
123
|
+
|
|
124
|
+
// Generate custom CSS
|
|
125
|
+
const css = StachelockUI.generateCSS();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Design Token Structure
|
|
129
|
+
|
|
130
|
+
### Colors
|
|
131
|
+
```typescript
|
|
132
|
+
colors: {
|
|
133
|
+
primary: {
|
|
134
|
+
50: '#f0f9ff', // Lightest
|
|
135
|
+
100: '#e0f2fe',
|
|
136
|
+
200: '#bae6fd',
|
|
137
|
+
300: '#7dd3fc',
|
|
138
|
+
400: '#38bdf8',
|
|
139
|
+
500: '#0ea5e9', // Base
|
|
140
|
+
600: '#0284c7',
|
|
141
|
+
700: '#0369a1',
|
|
142
|
+
800: '#075985',
|
|
143
|
+
900: '#0c4a6e' // Darkest
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Spacing
|
|
149
|
+
```typescript
|
|
150
|
+
spacing: {
|
|
151
|
+
'0': '0',
|
|
152
|
+
'1': '0.25rem',
|
|
153
|
+
'2': '0.5rem',
|
|
154
|
+
'4': '1rem',
|
|
155
|
+
'8': '2rem',
|
|
156
|
+
'16': '4rem',
|
|
157
|
+
'32': '8rem',
|
|
158
|
+
'64': '16rem'
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Border Radius
|
|
163
|
+
```typescript
|
|
164
|
+
borderRadius: {
|
|
165
|
+
'none': '0',
|
|
166
|
+
'sm': '0.125rem',
|
|
167
|
+
'DEFAULT': '0.25rem',
|
|
168
|
+
'md': '0.375rem',
|
|
169
|
+
'lg': '0.5rem',
|
|
170
|
+
'xl': '0.75rem',
|
|
171
|
+
'2xl': '1rem',
|
|
172
|
+
'full': '9999px'
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Shadows
|
|
177
|
+
```typescript
|
|
178
|
+
shadows: {
|
|
179
|
+
'sm': '0 1px 2px 0 rgb(0 0 0 / 0.05)',
|
|
180
|
+
'DEFAULT': '0 1px 3px 0 rgb(0 0 0 / 0.1)',
|
|
181
|
+
'md': '0 4px 6px -1px rgb(0 0 0 / 0.1)',
|
|
182
|
+
'lg': '0 10px 15px -3px rgb(0 0 0 / 0.1)',
|
|
183
|
+
'xl': '0 20px 25px -5px rgb(0 0 0 / 0.1)'
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Typography
|
|
188
|
+
```typescript
|
|
189
|
+
typography: {
|
|
190
|
+
fontFamily: {
|
|
191
|
+
sans: ['Inter', 'ui-sans-serif', 'system-ui', 'sans-serif'],
|
|
192
|
+
display: ['Poppins', 'ui-sans-serif', 'system-ui', 'sans-serif'],
|
|
193
|
+
mono: ['JetBrains Mono', 'ui-monospace', 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', 'monospace']
|
|
194
|
+
},
|
|
195
|
+
fontSize: {
|
|
196
|
+
'xs': '0.75rem',
|
|
197
|
+
'sm': '0.875rem',
|
|
198
|
+
'base': '1rem',
|
|
199
|
+
'lg': '1.125rem',
|
|
200
|
+
'xl': '1.25rem',
|
|
201
|
+
'2xl': '1.5rem',
|
|
202
|
+
'3xl': '1.875rem',
|
|
203
|
+
'4xl': '2.25rem'
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Breakpoints
|
|
209
|
+
```typescript
|
|
210
|
+
breakpoints: {
|
|
211
|
+
'sm': '640px',
|
|
212
|
+
'md': '768px',
|
|
213
|
+
'lg': '1024px',
|
|
214
|
+
'xl': '1280px',
|
|
215
|
+
'2xl': '1536px',
|
|
216
|
+
'3xl': '1600px'
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Generated CSS Variables
|
|
221
|
+
|
|
222
|
+
The system generates CSS custom properties that you can use in your own CSS:
|
|
223
|
+
|
|
224
|
+
```css
|
|
225
|
+
:root {
|
|
226
|
+
--sl-color-primary-50: #f0f9ff;
|
|
227
|
+
--sl-color-primary-100: #e0f2fe;
|
|
228
|
+
--sl-color-primary-500: #0ea5e9;
|
|
229
|
+
--sl-color-primary-600: #0284c7;
|
|
230
|
+
--sl-color-primary-700: #0369a1;
|
|
231
|
+
|
|
232
|
+
--sl-spacing-18: 4.5rem;
|
|
233
|
+
--sl-spacing-22: 5.5rem;
|
|
234
|
+
|
|
235
|
+
--sl-border-radius-2xl: 1rem;
|
|
236
|
+
--sl-border-radius-3xl: 1.5rem;
|
|
237
|
+
|
|
238
|
+
--sl-shadow-glow: 0 0 20px rgba(59, 130, 246, 0.5);
|
|
239
|
+
--sl-shadow-glow-lg: 0 0 40px rgba(59, 130, 246, 0.3);
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Using Custom Tokens in Components
|
|
244
|
+
|
|
245
|
+
### In Vue Templates
|
|
246
|
+
```vue
|
|
247
|
+
<template>
|
|
248
|
+
<div class="sl-bg-primary-500 sl-text-white sl-p-18 sl-rounded-2xl sl-shadow-glow">
|
|
249
|
+
Custom styled content
|
|
250
|
+
</div>
|
|
251
|
+
</template>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### In CSS
|
|
255
|
+
```css
|
|
256
|
+
.my-custom-component {
|
|
257
|
+
background-color: var(--sl-color-primary-500);
|
|
258
|
+
padding: var(--sl-spacing-18);
|
|
259
|
+
border-radius: var(--sl-border-radius-2xl);
|
|
260
|
+
box-shadow: var(--sl-shadow-glow);
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Migration from Previous Versions
|
|
265
|
+
|
|
266
|
+
If you're upgrading from a previous version:
|
|
267
|
+
|
|
268
|
+
1. **No breaking changes** - existing `sl-` classes continue to work
|
|
269
|
+
2. **New customization options** - you can now override design tokens
|
|
270
|
+
3. **Backward compatibility** - all existing functionality is preserved
|
|
271
|
+
|
|
272
|
+
## Best Practices
|
|
273
|
+
|
|
274
|
+
### 1. Token Naming
|
|
275
|
+
- Use semantic names (e.g., `primary`, `secondary`, `accent`)
|
|
276
|
+
- Follow the 50-900 scale for colors
|
|
277
|
+
- Use consistent naming across your design system
|
|
278
|
+
|
|
279
|
+
### 2. Color Selection
|
|
280
|
+
- Ensure sufficient contrast for accessibility
|
|
281
|
+
- Test colors in both light and dark modes
|
|
282
|
+
- Consider using tools like [Coolors](https://coolors.co/) for color generation
|
|
283
|
+
|
|
284
|
+
### 3. Spacing Scale
|
|
285
|
+
- Use consistent spacing increments
|
|
286
|
+
- Consider your design system's needs
|
|
287
|
+
- Common scales: 4px (0.25rem), 8px (0.5rem), 16px (1rem)
|
|
288
|
+
|
|
289
|
+
### 4. Typography
|
|
290
|
+
- Choose fonts that complement your brand
|
|
291
|
+
- Ensure good readability across devices
|
|
292
|
+
- Consider loading performance for custom fonts
|
|
293
|
+
|
|
294
|
+
## Troubleshooting
|
|
295
|
+
|
|
296
|
+
### Common Issues
|
|
297
|
+
|
|
298
|
+
**CSS variables not loading**
|
|
299
|
+
- Check that the CSS file is imported before other styles
|
|
300
|
+
- Verify the file path is correct
|
|
301
|
+
- Ensure the build process completed successfully
|
|
302
|
+
|
|
303
|
+
**Tailwind classes not working**
|
|
304
|
+
- Verify the Tailwind config is properly merged
|
|
305
|
+
- Check that content paths include your components
|
|
306
|
+
- Ensure the prefix is set to `sl-`
|
|
307
|
+
|
|
308
|
+
**Build errors**
|
|
309
|
+
- Check that all required dependencies are installed
|
|
310
|
+
- Verify the JSON syntax in your tokens file
|
|
311
|
+
- Ensure the output directory is writable
|
|
312
|
+
|
|
313
|
+
### Getting Help
|
|
314
|
+
|
|
315
|
+
- Check the [main README](../README.md) for general usage
|
|
316
|
+
- Review the [examples](../examples/) directory for sample configurations
|
|
317
|
+
- Open an issue on GitHub for bugs or feature requests
|
|
318
|
+
|
|
319
|
+
## Examples
|
|
320
|
+
|
|
321
|
+
See the [examples](../examples/) directory for complete working examples:
|
|
322
|
+
|
|
323
|
+
- `custom-tokens.json` - Sample token configuration
|
|
324
|
+
- `vue-app/` - Complete Vue application with custom tokens
|
|
325
|
+
- `react-app/` - Complete React application with custom tokens
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { StachelockUIDesignTokens } from './design-tokens';
|
|
2
|
+
|
|
3
|
+
export declare function generateCSSVariables(tokens: StachelockUIDesignTokens): string;
|
|
4
|
+
export declare function generateTailwindConfig(tokens: StachelockUIDesignTokens): string;
|
|
5
|
+
//# sourceMappingURL=css-variables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css-variables.d.ts","sourceRoot":"","sources":["../../../src/config/css-variables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAEhE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CA6E7E;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CA2E/E"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface StachelockUIDesignTokens {
|
|
2
|
+
colors?: {
|
|
3
|
+
primary?: {
|
|
4
|
+
50?: string;
|
|
5
|
+
100?: string;
|
|
6
|
+
200?: string;
|
|
7
|
+
300?: string;
|
|
8
|
+
400?: string;
|
|
9
|
+
500?: string;
|
|
10
|
+
600?: string;
|
|
11
|
+
700?: string;
|
|
12
|
+
800?: string;
|
|
13
|
+
900?: string;
|
|
14
|
+
};
|
|
15
|
+
stachelock?: {
|
|
16
|
+
50?: string;
|
|
17
|
+
100?: string;
|
|
18
|
+
200?: string;
|
|
19
|
+
300?: string;
|
|
20
|
+
400?: string;
|
|
21
|
+
500?: string;
|
|
22
|
+
600?: string;
|
|
23
|
+
700?: string;
|
|
24
|
+
800?: string;
|
|
25
|
+
900?: string;
|
|
26
|
+
};
|
|
27
|
+
[key: string]: any;
|
|
28
|
+
};
|
|
29
|
+
spacing?: {
|
|
30
|
+
[key: string]: string;
|
|
31
|
+
};
|
|
32
|
+
borderRadius?: {
|
|
33
|
+
[key: string]: string;
|
|
34
|
+
};
|
|
35
|
+
shadows?: {
|
|
36
|
+
[key: string]: string;
|
|
37
|
+
};
|
|
38
|
+
typography?: {
|
|
39
|
+
fontFamily?: {
|
|
40
|
+
[key: string]: string[];
|
|
41
|
+
};
|
|
42
|
+
fontSize?: {
|
|
43
|
+
[key: string]: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
breakpoints?: {
|
|
47
|
+
[key: string]: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export declare const defaultDesignTokens: StachelockUIDesignTokens;
|
|
51
|
+
export declare function mergeDesignTokens(customTokens: StachelockUIDesignTokens, defaults?: StachelockUIDesignTokens): StachelockUIDesignTokens;
|
|
52
|
+
//# sourceMappingURL=design-tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-tokens.d.ts","sourceRoot":"","sources":["../../../src/config/design-tokens.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE;YACR,EAAE,CAAC,EAAE,MAAM,CAAC;YACZ,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;SACd,CAAC;QACF,UAAU,CAAC,EAAE;YACX,EAAE,CAAC,EAAE,MAAM,CAAC;YACZ,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;YACb,GAAG,CAAC,EAAE,MAAM,CAAC;SACd,CAAC;QACF,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;IACF,OAAO,CAAC,EAAE;QACR,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;KACvB,CAAC;IACF,YAAY,CAAC,EAAE;QACb,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;KACvB,CAAC;IACF,OAAO,CAAC,EAAE;QACR,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;KACvB,CAAC;IACF,UAAU,CAAC,EAAE;QACX,UAAU,CAAC,EAAE;YACX,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;SACzB,CAAC;QACF,QAAQ,CAAC,EAAE;YACT,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;SACvB,CAAC;KACH,CAAC;IACF,WAAW,CAAC,EAAE;QACZ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;KACvB,CAAC;CACH;AAED,eAAO,MAAM,mBAAmB,EAAE,wBAoGjC,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,wBAAwB,EACtC,QAAQ,GAAE,wBAA8C,GACvD,wBAAwB,CAoB1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { App } from 'vue';
|
|
2
|
+
import { StachelockUIDesignTokens } from '../config/design-tokens';
|
|
3
|
+
|
|
4
|
+
export interface StachelockUIOptions {
|
|
5
|
+
designTokens?: StachelockUIDesignTokens;
|
|
6
|
+
prefix?: string;
|
|
7
|
+
injectCSS?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface StachelockUIPlugin {
|
|
10
|
+
install: (app: App, options?: StachelockUIOptions) => void;
|
|
11
|
+
configure: (options: StachelockUIOptions) => void;
|
|
12
|
+
getDesignTokens: () => StachelockUIDesignTokens;
|
|
13
|
+
generateCSS: () => string;
|
|
14
|
+
}
|
|
15
|
+
declare class StachelockUIPluginImpl implements StachelockUIPlugin {
|
|
16
|
+
private designTokens;
|
|
17
|
+
private prefix;
|
|
18
|
+
private injectCSS;
|
|
19
|
+
constructor();
|
|
20
|
+
install(app: App, options?: StachelockUIOptions): void;
|
|
21
|
+
configure(options: StachelockUIOptions): void;
|
|
22
|
+
getDesignTokens(): StachelockUIDesignTokens;
|
|
23
|
+
generateCSS(): string;
|
|
24
|
+
private injectCSSVariables;
|
|
25
|
+
}
|
|
26
|
+
export declare const StachelockUI: StachelockUIPlugin;
|
|
27
|
+
export { StachelockUIPluginImpl };
|
|
28
|
+
//# sourceMappingURL=configure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../../../src/plugin/configure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC/B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAIxE,MAAM,WAAW,mBAAmB;IAClC,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC3D,SAAS,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAClD,eAAe,EAAE,MAAM,wBAAwB,CAAC;IAChD,WAAW,EAAE,MAAM,MAAM,CAAC;CAC3B;AAED,cAAM,sBAAuB,YAAW,kBAAkB;IACxD,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,SAAS,CAAiB;;IAQlC,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,GAAE,mBAAwB;IAkBnD,SAAS,CAAC,OAAO,EAAE,mBAAmB;IActC,eAAe,IAAI,wBAAwB;IAI3C,WAAW,IAAI,MAAM;IAIrB,OAAO,CAAC,kBAAkB;CAe3B;AAGD,eAAO,MAAM,YAAY,EAAE,kBAAiD,CAAC;AAG7E,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugin/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"colors": {
|
|
3
|
+
"primary": {
|
|
4
|
+
"50": "#f0f9ff",
|
|
5
|
+
"100": "#e0f2fe",
|
|
6
|
+
"200": "#bae6fd",
|
|
7
|
+
"300": "#7dd3fc",
|
|
8
|
+
"400": "#38bdf8",
|
|
9
|
+
"500": "#0ea5e9",
|
|
10
|
+
"600": "#0284c7",
|
|
11
|
+
"700": "#0369a1",
|
|
12
|
+
"800": "#075985",
|
|
13
|
+
"900": "#0c4a6e"
|
|
14
|
+
},
|
|
15
|
+
"stachelock": {
|
|
16
|
+
"50": "#fef2f2",
|
|
17
|
+
"100": "#fee2e2",
|
|
18
|
+
"200": "#fecaca",
|
|
19
|
+
"300": "#fca5a5",
|
|
20
|
+
"400": "#f87171",
|
|
21
|
+
"500": "#ef4444",
|
|
22
|
+
"600": "#dc2626",
|
|
23
|
+
"700": "#b91c1c",
|
|
24
|
+
"800": "#991b1b",
|
|
25
|
+
"900": "#7f1d1d"
|
|
26
|
+
},
|
|
27
|
+
"accent": {
|
|
28
|
+
"50": "#fdf4ff",
|
|
29
|
+
"100": "#fae8ff",
|
|
30
|
+
"200": "#f5d0fe",
|
|
31
|
+
"300": "#f0abfc",
|
|
32
|
+
"400": "#e879f9",
|
|
33
|
+
"500": "#d946ef",
|
|
34
|
+
"600": "#c026d3",
|
|
35
|
+
"700": "#a21caf",
|
|
36
|
+
"800": "#86198f",
|
|
37
|
+
"900": "#701a75"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"spacing": {
|
|
41
|
+
"18": "4.5rem",
|
|
42
|
+
"22": "5.5rem",
|
|
43
|
+
"26": "6.5rem",
|
|
44
|
+
"30": "7.5rem"
|
|
45
|
+
},
|
|
46
|
+
"borderRadius": {
|
|
47
|
+
"2xl": "1rem",
|
|
48
|
+
"3xl": "1.5rem",
|
|
49
|
+
"4xl": "2rem"
|
|
50
|
+
},
|
|
51
|
+
"shadows": {
|
|
52
|
+
"glow": "0 0 20px rgba(59, 130, 246, 0.5)",
|
|
53
|
+
"glow-lg": "0 0 40px rgba(59, 130, 246, 0.3)"
|
|
54
|
+
},
|
|
55
|
+
"typography": {
|
|
56
|
+
"fontFamily": {
|
|
57
|
+
"display": ["Poppins", "ui-sans-serif", "system-ui", "sans-serif"],
|
|
58
|
+
"mono": ["JetBrains Mono", "ui-monospace", "SFMono-Regular", "Menlo", "Monaco", "Consolas", "monospace"]
|
|
59
|
+
},
|
|
60
|
+
"fontSize": {
|
|
61
|
+
"2xs": "0.625rem",
|
|
62
|
+
"3xl": "1.875rem",
|
|
63
|
+
"4xl": "2.25rem"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"breakpoints": {
|
|
67
|
+
"3xl": "1600px",
|
|
68
|
+
"4xl": "1920px"
|
|
69
|
+
}
|
|
70
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stachelock/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A comprehensive Vue 3 UI component library built with Tailwind CSS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"./style.css": "./dist/style.css",
|
|
15
15
|
"./tailwind.config.js": "./dist/tailwind.config.js",
|
|
16
|
+
"./generate-config": "./scripts/generate-config.cjs",
|
|
16
17
|
"./components/*": {
|
|
17
18
|
"import": "./dist/components/*.js",
|
|
18
19
|
"types": "./dist/components/*.d.ts"
|
|
@@ -37,8 +38,14 @@
|
|
|
37
38
|
"files": [
|
|
38
39
|
"dist",
|
|
39
40
|
"tailwind.config.js",
|
|
40
|
-
"
|
|
41
|
+
"scripts",
|
|
42
|
+
"examples",
|
|
43
|
+
"README.md",
|
|
44
|
+
"CUSTOMIZATION.md"
|
|
41
45
|
],
|
|
46
|
+
"bin": {
|
|
47
|
+
"stachelock-ui": "./scripts/generate-config.cjs"
|
|
48
|
+
},
|
|
42
49
|
"scripts": {
|
|
43
50
|
"dev": "vite",
|
|
44
51
|
"build": "vite build && npm run build:css",
|
|
@@ -57,7 +64,8 @@
|
|
|
57
64
|
"prepack": "npm run build",
|
|
58
65
|
"postpack": "rm -rf dist",
|
|
59
66
|
"generate-indexes": "node scripts/generateRecursiveIndex.cjs",
|
|
60
|
-
"prebuild": "npm run generate-indexes"
|
|
67
|
+
"prebuild": "npm run generate-indexes",
|
|
68
|
+
"generate-config": "node scripts/generate-config.cjs"
|
|
61
69
|
},
|
|
62
70
|
"keywords": [
|
|
63
71
|
"vue",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
console.log('🔨 Building Tailwind CSS with sl- prefix...');
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
// Run Tailwind CLI to build the CSS
|
|
9
|
+
execSync('npx tailwindcss -i ./src/style.css -o ./dist/style.css --minify', {
|
|
10
|
+
stdio: 'inherit',
|
|
11
|
+
cwd: process.cwd()
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
console.log('✅ Tailwind CSS built successfully!');
|
|
15
|
+
|
|
16
|
+
// Read the generated CSS to verify it contains the sl- prefixed utilities
|
|
17
|
+
const cssContent = fs.readFileSync('./dist/style.css', 'utf8');
|
|
18
|
+
|
|
19
|
+
// Check if it contains some basic sl- prefixed utilities
|
|
20
|
+
if (cssContent.includes('.sl-bg-') || cssContent.includes('.sl-text-') || cssContent.includes('.sl-flex')) {
|
|
21
|
+
console.log('✅ CSS contains sl- prefixed Tailwind utilities');
|
|
22
|
+
} else {
|
|
23
|
+
console.log('⚠️ CSS may not contain expected sl- prefixed utilities');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error('❌ Error building Tailwind CSS:', error.message);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
console.log('🎨 Stachelock UI Config Generator');
|
|
7
|
+
console.log('==================================\n');
|
|
8
|
+
|
|
9
|
+
// Get command line arguments
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const configFile = args[0];
|
|
12
|
+
const outputDir = args[1] || './';
|
|
13
|
+
|
|
14
|
+
if (!configFile) {
|
|
15
|
+
console.log('Usage: node generate-config.cjs <config-file> [output-dir]');
|
|
16
|
+
console.log('');
|
|
17
|
+
console.log('Example:');
|
|
18
|
+
console.log(' node generate-config.cjs ./my-tokens.json ./generated/');
|
|
19
|
+
console.log('');
|
|
20
|
+
console.log('The config file should contain design tokens in the StachelockUIDesignTokens format.');
|
|
21
|
+
console.log('See the documentation for the expected format.');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!fs.existsSync(configFile)) {
|
|
26
|
+
console.error(`❌ Config file not found: ${configFile}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// Read and parse the config file
|
|
32
|
+
console.log(`📖 Reading config from: ${configFile}`);
|
|
33
|
+
const configContent = fs.readFileSync(configFile, 'utf8');
|
|
34
|
+
const customTokens = JSON.parse(configContent);
|
|
35
|
+
|
|
36
|
+
// Import the required functions
|
|
37
|
+
const { mergeDesignTokens, defaultDesignTokens } = require('../dist/config/design-tokens.js');
|
|
38
|
+
const { generateCSSVariables, generateTailwindConfig } = require('../dist/config/css-variables.js');
|
|
39
|
+
|
|
40
|
+
// Merge with default tokens
|
|
41
|
+
console.log('🔄 Merging with default design tokens...');
|
|
42
|
+
const mergedTokens = mergeDesignTokens(customTokens, defaultDesignTokens);
|
|
43
|
+
|
|
44
|
+
// Generate CSS variables
|
|
45
|
+
console.log('🎨 Generating CSS variables...');
|
|
46
|
+
const cssVariables = generateCSSVariables(mergedTokens);
|
|
47
|
+
|
|
48
|
+
// Generate Tailwind config
|
|
49
|
+
console.log('⚙️ Generating Tailwind config...');
|
|
50
|
+
const tailwindConfig = generateTailwindConfig(mergedTokens);
|
|
51
|
+
|
|
52
|
+
// Ensure output directory exists
|
|
53
|
+
if (!fs.existsSync(outputDir)) {
|
|
54
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Write CSS variables file
|
|
58
|
+
const cssOutputPath = path.join(outputDir, 'stachelock-ui-variables.css');
|
|
59
|
+
fs.writeFileSync(cssOutputPath, cssVariables);
|
|
60
|
+
console.log(`✅ CSS variables written to: ${cssOutputPath}`);
|
|
61
|
+
|
|
62
|
+
// Write Tailwind config file
|
|
63
|
+
const configOutputPath = path.join(outputDir, 'stachelock-ui-tailwind.config.js');
|
|
64
|
+
fs.writeFileSync(configOutputPath, tailwindConfig);
|
|
65
|
+
console.log(`✅ Tailwind config written to: ${configOutputPath}`);
|
|
66
|
+
|
|
67
|
+
// Write merged tokens JSON for reference
|
|
68
|
+
const tokensOutputPath = path.join(outputDir, 'stachelock-ui-tokens.json');
|
|
69
|
+
fs.writeFileSync(tokensOutputPath, JSON.stringify(mergedTokens, null, 2));
|
|
70
|
+
console.log(`✅ Merged tokens written to: ${tokensOutputPath}`);
|
|
71
|
+
|
|
72
|
+
console.log('\n🎉 Configuration generation complete!');
|
|
73
|
+
console.log('\nNext steps:');
|
|
74
|
+
console.log('1. Import the CSS variables in your main CSS file:');
|
|
75
|
+
console.log(` @import "${cssOutputPath}";`);
|
|
76
|
+
console.log('2. Use the Tailwind config in your tailwind.config.js:');
|
|
77
|
+
console.log(` const stachelockConfig = require("${configOutputPath}");`);
|
|
78
|
+
console.log('3. Merge it with your existing config as needed.');
|
|
79
|
+
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error('❌ Error generating configuration:', error.message);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
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
|
+
"// Base UI Components",
|
|
124
|
+
"export * from './components';",
|
|
125
|
+
"",
|
|
126
|
+
"// Layout Components",
|
|
127
|
+
"export * from './components/layouts';",
|
|
128
|
+
"",
|
|
129
|
+
"// Input Components",
|
|
130
|
+
"export * from './components/inputs';",
|
|
131
|
+
"",
|
|
132
|
+
"// Calendar Components",
|
|
133
|
+
"export * from './components/calendars';",
|
|
134
|
+
"",
|
|
135
|
+
"// Form Components",
|
|
136
|
+
"export * from './components/forms';",
|
|
137
|
+
"",
|
|
138
|
+
"// Plugin interface and Vue plugin",
|
|
139
|
+
"export { StachelockUI, type StachelockUIOptions } from './plugin';",
|
|
140
|
+
"export { StachelockUI as default } from './plugin';"
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
const newContent = exportStatements.join('\n') + '\n';
|
|
144
|
+
|
|
145
|
+
// Always write to ensure consistency
|
|
146
|
+
fs.writeFileSync(mainIndexPath, newContent);
|
|
147
|
+
console.log(`✅ Generated main index.ts`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Function to generate plugin file
|
|
151
|
+
function generatePluginFile(srcDirectoryPath) {
|
|
152
|
+
const pluginPath = path.join(srcDirectoryPath, 'plugin.ts');
|
|
153
|
+
|
|
154
|
+
const pluginContent = `import type { App } from 'vue';
|
|
155
|
+
import * as components from './components';
|
|
156
|
+
import * as layouts from './components/layouts';
|
|
157
|
+
import * as inputs from './components/inputs';
|
|
158
|
+
import * as calendars from './components/calendars';
|
|
159
|
+
import * as forms from './components/forms';
|
|
160
|
+
|
|
161
|
+
// Combine all components
|
|
162
|
+
const allComponents = {
|
|
163
|
+
...components,
|
|
164
|
+
...layouts,
|
|
165
|
+
...inputs,
|
|
166
|
+
...calendars,
|
|
167
|
+
...forms,
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// Plugin interface
|
|
171
|
+
export interface StachelockUIOptions {
|
|
172
|
+
/**
|
|
173
|
+
* Component name prefix (default: 'Sl')
|
|
174
|
+
*/
|
|
175
|
+
prefix?: string;
|
|
176
|
+
/**
|
|
177
|
+
* Array of component names to install globally
|
|
178
|
+
*/
|
|
179
|
+
components?: string[];
|
|
180
|
+
/**
|
|
181
|
+
* Whether to install all components globally
|
|
182
|
+
*/
|
|
183
|
+
installAll?: boolean;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Vue plugin
|
|
187
|
+
export const StachelockUI = {
|
|
188
|
+
install(app: App, options: StachelockUIOptions = {}) {
|
|
189
|
+
const { prefix = 'Sl', installAll = false, components: selectedComponents } = options;
|
|
190
|
+
|
|
191
|
+
// Register components
|
|
192
|
+
Object.entries(allComponents).forEach(([name, component]) => {
|
|
193
|
+
const shouldInstall = installAll ||
|
|
194
|
+
(selectedComponents && selectedComponents.includes(name)) ||
|
|
195
|
+
(!selectedComponents && !installAll);
|
|
196
|
+
|
|
197
|
+
if (shouldInstall) {
|
|
198
|
+
// Register non-prefixed
|
|
199
|
+
app.component(name, component);
|
|
200
|
+
// Also register prefixed alias for back-compat
|
|
201
|
+
const prefixedName = name.startsWith(prefix) ? name : \`\${prefix}\${name}\`;
|
|
202
|
+
app.component(prefixedName, component);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export default StachelockUI;
|
|
209
|
+
`;
|
|
210
|
+
|
|
211
|
+
// Only write if content is different
|
|
212
|
+
if (!fs.existsSync(pluginPath) || fs.readFileSync(pluginPath, 'utf8') !== pluginContent) {
|
|
213
|
+
fs.writeFileSync(pluginPath, pluginContent);
|
|
214
|
+
console.log(`✅ Generated plugin.ts`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Main execution
|
|
219
|
+
function main() {
|
|
220
|
+
console.log('🚀 Generating recursive index files for stachelock-ui...\n');
|
|
221
|
+
|
|
222
|
+
const srcDirectoryPath = path.join(__dirname, '../src');
|
|
223
|
+
|
|
224
|
+
if (!fs.existsSync(srcDirectoryPath)) {
|
|
225
|
+
console.error('❌ src directory not found!');
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
// Generate index files for all subdirectories
|
|
231
|
+
generateIndexFile(srcDirectoryPath);
|
|
232
|
+
|
|
233
|
+
// Generate main index file
|
|
234
|
+
generateMainIndexFile(srcDirectoryPath);
|
|
235
|
+
|
|
236
|
+
// Generate plugin file
|
|
237
|
+
generatePluginFile(srcDirectoryPath);
|
|
238
|
+
|
|
239
|
+
console.log('\n✨ All index files generated successfully!');
|
|
240
|
+
} catch (error) {
|
|
241
|
+
console.error('❌ Error generating index files:', error);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Run if called directly
|
|
247
|
+
if (require.main === module) {
|
|
248
|
+
main();
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
module.exports = { generateIndexFile, generateMainIndexFile, generatePluginFile };
|