omnidesign 1.0.2 → 1.1.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/AGENTS.md +383 -0
- package/README.md +307 -98
- package/bin/cli.js +1 -1
- package/package.json +22 -7
- package/packages/tokens-css/dist/tokens.css +162 -0
- package/packages/tokens-tailwind/dist/index.js +315 -0
- package/packages/tokens-tailwind/dist/tailwind.config.js +339 -0
- package/packages/tokens-tailwind/dist/tailwind.config.json +339 -0
- package/packages/tokens-tailwind/dist/tokens.css +313 -0
- package/packages/tokens-tailwind/dist/utility-mapping.json +145 -0
- package/packages/tokens-tailwind/package.json +47 -0
- package/packages/tokens-tailwind/scripts/build-tailwind.js +285 -0
- package/packages/tokens-ts/dist/tokens.ts +1307 -0
- package/skills/opencode/omnidesign-tailwind.md +450 -0
- package/tokens/primitives/colors-extended.json +455 -0
- package/tokens/typography/nerd-fonts-catalog.json +511 -0
- package/tokens/typography/nerd-fonts-complete.json +1858 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const rootDir = path.join(__dirname, '../..');
|
|
7
|
+
const outputDir = path.join(__dirname, '../dist');
|
|
8
|
+
|
|
9
|
+
const colorFamilies = [
|
|
10
|
+
'neutral', 'slate', 'zinc', 'stone',
|
|
11
|
+
'red', 'orange', 'amber', 'yellow', 'lime', 'green', 'emerald', 'teal', 'cyan', 'sky', 'blue', 'indigo', 'violet', 'purple', 'fuchsia', 'pink', 'rose'
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const semanticMapping = {
|
|
15
|
+
light: {
|
|
16
|
+
'text-default': 'slate.900',
|
|
17
|
+
'text-muted': 'slate.500',
|
|
18
|
+
'text-inverted': 'white',
|
|
19
|
+
'surface-default': 'white',
|
|
20
|
+
'surface-raised': 'slate.50',
|
|
21
|
+
'surface-sunken': 'slate.100',
|
|
22
|
+
'border-default': 'slate.200',
|
|
23
|
+
'border-subtle': 'slate.100',
|
|
24
|
+
'interactive-primary': 'blue.600',
|
|
25
|
+
'interactive-primary-hover': 'blue.700',
|
|
26
|
+
'interactive-secondary': 'slate.600',
|
|
27
|
+
'status-success': 'green.600',
|
|
28
|
+
'status-warning': 'amber.500',
|
|
29
|
+
'status-error': 'red.600',
|
|
30
|
+
'status-info': 'blue.500'
|
|
31
|
+
},
|
|
32
|
+
dark: {
|
|
33
|
+
'text-default': 'slate.50',
|
|
34
|
+
'text-muted': 'slate.400',
|
|
35
|
+
'text-inverted': 'slate.950',
|
|
36
|
+
'surface-default': 'slate.950',
|
|
37
|
+
'surface-raised': 'slate.900',
|
|
38
|
+
'surface-sunken': 'slate.950',
|
|
39
|
+
'border-default': 'slate.800',
|
|
40
|
+
'border-subtle': 'slate.900',
|
|
41
|
+
'interactive-primary': 'blue.500',
|
|
42
|
+
'interactive-primary-hover': 'blue.400',
|
|
43
|
+
'interactive-secondary': 'slate.500',
|
|
44
|
+
'status-success': 'green.500',
|
|
45
|
+
'status-warning': 'amber.400',
|
|
46
|
+
'status-error': 'red.500',
|
|
47
|
+
'status-info': 'blue.400'
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
function generateTailwindConfig() {
|
|
52
|
+
const config = {
|
|
53
|
+
theme: {
|
|
54
|
+
extend: {
|
|
55
|
+
colors: {},
|
|
56
|
+
fontFamily: {},
|
|
57
|
+
spacing: {},
|
|
58
|
+
borderRadius: {},
|
|
59
|
+
boxShadow: {}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
colorFamilies.forEach(family => {
|
|
65
|
+
config.theme.extend.colors[family] = {};
|
|
66
|
+
const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
|
|
67
|
+
shades.forEach(shade => {
|
|
68
|
+
config.theme.extend.colors[family][shade] = `var(--color-${family}-${shade})`;
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
config.theme.extend.colors.semantic = {};
|
|
73
|
+
Object.entries(semanticMapping.light).forEach(([key, value]) => {
|
|
74
|
+
const [family, shade] = value.split('.');
|
|
75
|
+
config.theme.extend.colors.semantic[key] = `var(--color-${family}-${shade})`;
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
config.theme.extend.fontFamily = {
|
|
79
|
+
sans: ['var(--font-geist-sans)', 'system-ui', 'sans-serif'],
|
|
80
|
+
mono: ['var(--font-geist-mono)', 'monospace'],
|
|
81
|
+
display: ['var(--font-clash-display)', 'sans-serif']
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const spacingScale = {
|
|
85
|
+
'0.5': '0.125rem',
|
|
86
|
+
'1': '0.25rem',
|
|
87
|
+
'2': '0.5rem',
|
|
88
|
+
'3': '0.75rem',
|
|
89
|
+
'4': '1rem',
|
|
90
|
+
'5': '1.25rem',
|
|
91
|
+
'6': '1.5rem',
|
|
92
|
+
'8': '2rem',
|
|
93
|
+
'10': '2.5rem',
|
|
94
|
+
'12': '3rem',
|
|
95
|
+
'16': '4rem',
|
|
96
|
+
'20': '5rem',
|
|
97
|
+
'24': '6rem'
|
|
98
|
+
};
|
|
99
|
+
config.theme.extend.spacing = spacingScale;
|
|
100
|
+
|
|
101
|
+
config.theme.extend.borderRadius = {
|
|
102
|
+
'none': '0',
|
|
103
|
+
'sm': '0.125rem',
|
|
104
|
+
'DEFAULT': '0.25rem',
|
|
105
|
+
'md': '0.375rem',
|
|
106
|
+
'lg': '0.5rem',
|
|
107
|
+
'xl': '0.75rem',
|
|
108
|
+
'2xl': '1rem',
|
|
109
|
+
'full': '9999px'
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
return config;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function generateCSSVariables() {
|
|
116
|
+
const lines = [
|
|
117
|
+
'/* OmniDesign CSS Variables - Tailwind Compatible */',
|
|
118
|
+
'/* Auto-generated - Do not edit manually */',
|
|
119
|
+
'',
|
|
120
|
+
':root {'
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
colorFamilies.forEach(family => {
|
|
124
|
+
lines.push(` /* ${family.charAt(0).toUpperCase() + family.slice(1)} */`);
|
|
125
|
+
const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
|
|
126
|
+
shades.forEach(shade => {
|
|
127
|
+
lines.push(` --color-${family}-${shade}: var(--color-${family}-${shade}, inherit);`);
|
|
128
|
+
});
|
|
129
|
+
lines.push('');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
lines.push(' /* Semantic Tokens - Light Mode */');
|
|
133
|
+
Object.entries(semanticMapping.light).forEach(([key, value]) => {
|
|
134
|
+
const [family, shade] = value.split('.');
|
|
135
|
+
lines.push(` --color-${key}: var(--color-${family}-${shade});`);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
lines.push('}');
|
|
139
|
+
lines.push('');
|
|
140
|
+
|
|
141
|
+
lines.push('.dark {');
|
|
142
|
+
lines.push(' /* Semantic Tokens - Dark Mode */');
|
|
143
|
+
Object.entries(semanticMapping.dark).forEach(([key, value]) => {
|
|
144
|
+
const [family, shade] = value.split('.');
|
|
145
|
+
lines.push(` --color-${key}: var(--color-${family}-${shade});`);
|
|
146
|
+
});
|
|
147
|
+
lines.push('}');
|
|
148
|
+
|
|
149
|
+
return lines.join('\n');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function generateUtilityMapping() {
|
|
153
|
+
const mapping = {
|
|
154
|
+
_meta: {
|
|
155
|
+
version: '1.0.0',
|
|
156
|
+
description: 'Token to Tailwind utility class mapping',
|
|
157
|
+
generated: new Date().toISOString()
|
|
158
|
+
},
|
|
159
|
+
colors: {},
|
|
160
|
+
spacing: {},
|
|
161
|
+
typography: {},
|
|
162
|
+
examples: {}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
Object.entries(semanticMapping.light).forEach(([token, value]) => {
|
|
166
|
+
const [family, shade] = value.split('.');
|
|
167
|
+
const tailwindClass = token.replace(/-/g, '-');
|
|
168
|
+
mapping.colors[token] = {
|
|
169
|
+
token: `color.${token}`,
|
|
170
|
+
tailwindUtility: `bg-${tailwindClass} text-${tailwindClass} border-${tailwindClass}`,
|
|
171
|
+
cssVariable: `var(--color-${token})`,
|
|
172
|
+
hexReference: `{${value}}`,
|
|
173
|
+
usage: getColorUsage(token),
|
|
174
|
+
example: getColorExample(token, tailwindClass)
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
mapping.examples = {
|
|
179
|
+
button: {
|
|
180
|
+
primary: `<button class="bg-interactive-primary hover:bg-interactive-primary-hover text-text-inverted px-4 py-2 rounded-md font-medium shadow-card transition-colors focus:outline-none focus:ring-2 focus:ring-focus-ring">Primary</button>`,
|
|
181
|
+
secondary: `<button class="bg-surface-raised hover:bg-surface text-text border border-border px-4 py-2 rounded-md font-medium transition-colors">Secondary</button>`,
|
|
182
|
+
destructive: `<button class="bg-status-error hover:bg-red-700 text-text-inverted px-4 py-2 rounded-md font-medium transition-colors">Delete</button>`
|
|
183
|
+
},
|
|
184
|
+
card: `<div class="bg-surface-raised rounded-lg shadow-card p-6 border border-border-subtle"><h3 class="text-xl font-semibold text-text mb-2">Card Title</h3><p class="text-text-muted">Card content with semantic colors.</p></div>`,
|
|
185
|
+
input: `<input class="bg-surface-sunken text-text border border-border rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-interactive-primary focus:border-transparent placeholder-text-muted" placeholder="Enter text..." />`,
|
|
186
|
+
alert: {
|
|
187
|
+
success: `<div class="bg-green-50 border border-green-200 text-green-800 px-4 py-3 rounded-md"><p class="font-medium">Success!</p><p class="text-sm">Operation completed successfully.</p></div>`,
|
|
188
|
+
warning: `<div class="bg-amber-50 border border-amber-200 text-amber-800 px-4 py-3 rounded-md"><p class="font-medium">Warning!</p><p class="text-sm">Please review your input.</p></div>`,
|
|
189
|
+
error: `<div class="bg-red-50 border border-red-200 text-red-800 px-4 py-3 rounded-md"><p class="font-medium">Error!</p><p class="text-sm">Something went wrong.</p></div>`
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
return mapping;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function getColorUsage(token) {
|
|
197
|
+
const usages = {
|
|
198
|
+
'text-default': 'Primary body text on light surfaces',
|
|
199
|
+
'text-muted': 'Secondary text, captions, helper text',
|
|
200
|
+
'text-inverted': 'Text on dark or colored backgrounds',
|
|
201
|
+
'surface-default': 'Default page/app background',
|
|
202
|
+
'surface-raised': 'Cards, elevated surfaces, modals',
|
|
203
|
+
'surface-sunken': 'Input fields, depressed areas, wells',
|
|
204
|
+
'border-default': 'Default border color for inputs and dividers',
|
|
205
|
+
'border-subtle': 'Very light borders for subtle separation',
|
|
206
|
+
'interactive-primary': 'Primary buttons, links, CTAs',
|
|
207
|
+
'interactive-primary-hover': 'Hover state for primary interactive elements',
|
|
208
|
+
'interactive-secondary': 'Secondary buttons, less prominent actions',
|
|
209
|
+
'status-success': 'Success messages, confirmations, positive indicators',
|
|
210
|
+
'status-warning': 'Warning messages, caution indicators',
|
|
211
|
+
'status-error': 'Error messages, destructive actions, validation errors',
|
|
212
|
+
'status-info': 'Informational messages, tips, neutral alerts'
|
|
213
|
+
};
|
|
214
|
+
return usages[token] || 'General usage';
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function getColorExample(token, tailwindClass) {
|
|
218
|
+
const examples = {
|
|
219
|
+
'text-default': `<p class="text-text">Primary text content</p>`,
|
|
220
|
+
'text-muted': `<p class="text-text-muted">Secondary helper text</p>`,
|
|
221
|
+
'text-inverted': `<div class="bg-blue-600 text-text-inverted p-4">Text on dark background</div>`,
|
|
222
|
+
'surface-default': `<div class="bg-surface-default min-h-screen">Page content</div>`,
|
|
223
|
+
'surface-raised': `<div class="bg-surface-raised rounded-lg shadow p-6">Card content</div>`,
|
|
224
|
+
'surface-sunken': `<div class="bg-surface-sunken p-4 rounded-md">Input container</div>`,
|
|
225
|
+
'border-default': `<div class="border border-border rounded-md">Bordered element</div>`,
|
|
226
|
+
'border-subtle': `<hr class="border-border-subtle" />`,
|
|
227
|
+
'interactive-primary': `<button class="bg-interactive-primary text-text-inverted px-4 py-2 rounded">Click me</button>`,
|
|
228
|
+
'interactive-primary-hover': `<button class="bg-interactive-primary hover:bg-interactive-primary-hover transition-colors">Hover me</button>`,
|
|
229
|
+
'interactive-secondary': `<button class="bg-interactive-secondary text-text-inverted px-4 py-2 rounded">Secondary</button>`,
|
|
230
|
+
'status-success': `<span class="text-status-success font-medium">✓ Success</span>`,
|
|
231
|
+
'status-warning': `<span class="text-status-warning font-medium">⚠ Warning</span>`,
|
|
232
|
+
'status-error': `<span class="text-status-error font-medium">✕ Error</span>`,
|
|
233
|
+
'status-info': `<span class="text-status-info font-medium">ℹ Info</span>`
|
|
234
|
+
};
|
|
235
|
+
return examples[token] || `<div class="${tailwindClass}">Example</div>`;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function build() {
|
|
239
|
+
console.log('Building Tailwind integration...\n');
|
|
240
|
+
|
|
241
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
242
|
+
|
|
243
|
+
console.log('Generating tailwind.config.js...');
|
|
244
|
+
const tailwindConfig = generateTailwindConfig();
|
|
245
|
+
fs.writeFileSync(
|
|
246
|
+
path.join(outputDir, 'tailwind.config.json'),
|
|
247
|
+
JSON.stringify(tailwindConfig, null, 2)
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
const configJs = `module.exports = ${JSON.stringify(tailwindConfig, null, 2)};`;
|
|
251
|
+
fs.writeFileSync(path.join(outputDir, 'tailwind.config.js'), configJs);
|
|
252
|
+
|
|
253
|
+
console.log(' ✓ tailwind.config.js generated');
|
|
254
|
+
|
|
255
|
+
console.log('Generating CSS variables...');
|
|
256
|
+
const cssVariables = generateCSSVariables();
|
|
257
|
+
fs.writeFileSync(path.join(outputDir, 'tokens.css'), cssVariables);
|
|
258
|
+
console.log(' ✓ tokens.css generated');
|
|
259
|
+
|
|
260
|
+
console.log('Generating utility mapping...');
|
|
261
|
+
const utilityMapping = generateUtilityMapping();
|
|
262
|
+
fs.writeFileSync(
|
|
263
|
+
path.join(outputDir, 'utility-mapping.json'),
|
|
264
|
+
JSON.stringify(utilityMapping, null, 2)
|
|
265
|
+
);
|
|
266
|
+
console.log(' ✓ utility-mapping.json generated');
|
|
267
|
+
|
|
268
|
+
console.log('Generating index...');
|
|
269
|
+
const indexJs = `export { default as tailwindConfig } from './tailwind.config.json' assert { type: 'json' };
|
|
270
|
+
export { default as utilityMapping } from './utility-mapping.json' assert { type: 'json' };
|
|
271
|
+
export const cssVariables = \`${cssVariables.replace(/`/g, '\\`')}\`;
|
|
272
|
+
`;
|
|
273
|
+
fs.writeFileSync(path.join(outputDir, 'index.js'), indexJs);
|
|
274
|
+
console.log(' ✓ index.js generated');
|
|
275
|
+
|
|
276
|
+
console.log('\n✅ Tailwind integration build complete!');
|
|
277
|
+
console.log(`\nOutput files in ${outputDir}:`);
|
|
278
|
+
const files = fs.readdirSync(outputDir);
|
|
279
|
+
files.forEach(file => {
|
|
280
|
+
const stats = fs.statSync(path.join(outputDir, file));
|
|
281
|
+
console.log(` - ${file} (${(stats.size / 1024).toFixed(1)} KB)`);
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
build();
|