@vettvangur/design-system 1.0.1 → 1.0.2

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.
@@ -0,0 +1,242 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs/promises';
3
+ import { constants } from 'node:fs';
4
+ import path from 'node:path';
5
+ import chalk from 'chalk';
6
+ import { p as paths } from './index.esm.js';
7
+ import { p as parseButtons } from './buttons-o2a9tpOe.js';
8
+ import 'node:process';
9
+ import 'boxen';
10
+ import 'fs';
11
+ import 'path';
12
+ import 'os';
13
+ import 'crypto';
14
+ import 'node:url';
15
+
16
+ const tag = chalk.cyan('[design-system]');
17
+
18
+ /*
19
+ * This needs to genrate:
20
+ * variables:
21
+ * color.css
22
+ * font.css
23
+ * radius.css
24
+ * shadow.css
25
+ * typography.css
26
+ * core:
27
+ * body.css
28
+ * headline.css
29
+ */
30
+
31
+ async function generateTailwind(type, figmaStyles) {
32
+ console.log(`${tag} starting tailwind generation...`);
33
+ await generateColors(figmaStyles.paint);
34
+ await generateTypography(figmaStyles.text);
35
+
36
+ // core utilities
37
+ await generateBodies(figmaStyles.text);
38
+ await generateHeadlines(figmaStyles.text);
39
+ await generateButtons(figmaStyles);
40
+ console.log(`${tag} finished tailwind generation`);
41
+ }
42
+
43
+ // ------- VARIABLES -------
44
+ async function generateColors(data) {
45
+ console.log(`${tag} generating colors...`);
46
+ const outDir = path.join(paths.styles, 'config');
47
+ await fs.mkdir(outDir, {
48
+ recursive: true
49
+ });
50
+ const lines = [];
51
+ for (const [key, entry] of Object.entries(data ?? {})) {
52
+ const paints = entry?.paints ?? [];
53
+ const p = paints[0] ?? {};
54
+ // exporter already normalizes; prefer .hex/.value, else stringify fallback
55
+ const value = (p.hex && String(p.hex)) ?? (p.value && String(p.value)) ?? (p.css && String(p.css)) ?? String(p);
56
+ if (!value) {
57
+ continue;
58
+ }
59
+ lines.push(` --color-${key}: ${value};`);
60
+ }
61
+ const css = `/* Auto-generated. Do not edit by hand. */
62
+ @theme {
63
+ ${lines.join('\n')}
64
+ }
65
+ `;
66
+ const filePath = path.join(outDir, 'color.css');
67
+ await fs.writeFile(filePath, css, 'utf8');
68
+ console.log(`${tag} finished generating colors`);
69
+ }
70
+ async function generateButtons(figma) {
71
+ console.log(`${tag} generating buttons...`);
72
+ const outDir = path.join(paths.styles, "core");
73
+ const outFile = path.join(outDir, "button-variants.css");
74
+
75
+ // If file already exists, skip generation
76
+ try {
77
+ await fs.access(outFile, constants.F_OK);
78
+ console.log(`${tag} button-variants.css already exists, skipping`);
79
+ return;
80
+ } catch {
81
+ // access threw -> file does not exist, continue
82
+ }
83
+ const getButtons = await parseButtons(figma);
84
+ const buttons = getButtons.map(b => `@utility ${b} {
85
+ @apply button;
86
+
87
+ }`).join("\n\n");
88
+ const out = `/* Auto-generated. Do not edit by hand. */
89
+ ${buttons}
90
+ `;
91
+ await fs.writeFile(outFile, out, "utf8");
92
+ console.log(`${tag} finished generating buttons`);
93
+ }
94
+ async function generateTypography(data) {
95
+ console.log(`${tag} generating typography...`);
96
+ const outDir = path.join(paths.styles, 'config');
97
+ await fs.mkdir(outDir, {
98
+ recursive: true
99
+ });
100
+ const lines = [];
101
+ for (const [key, entry] of Object.entries(data ?? {})) {
102
+ if (!entry || typeof entry !== 'object') {
103
+ console.log(`${tag} [typography] skip "${key}" – entry is not an object`, entry);
104
+ continue;
105
+ }
106
+ const fontSize = entry.fontSize;
107
+ const lh = entry.lineHeight ?? {};
108
+ const lhVal = lh && typeof lh === 'object' ? lh.value : undefined;
109
+ const lhUnit = lh && typeof lh === 'object' ? lh.unit ?? '' : '';
110
+ const hasFontSize = typeof fontSize === 'number' && !Number.isNaN(fontSize);
111
+ const hasLineHeight = typeof lhVal === 'number' && !Number.isNaN(lhVal) && lhUnit !== '';
112
+ if (!hasFontSize && !hasLineHeight) {
113
+ // This will tell you exactly which keys are coming in “empty”
114
+ console.log(`${tag} [typography] "${key}" has no usable fontSize/lineHeight`, {
115
+ fontSize,
116
+ lineHeight: lh
117
+ });
118
+ continue;
119
+ }
120
+ if (hasFontSize) {
121
+ lines.push(` --text-${key}: ${fontSize}px;`);
122
+ }
123
+ if (hasLineHeight) {
124
+ lines.push(` --leading-${key}: ${lhVal}${lhUnit};`);
125
+ }
126
+ }
127
+ const css = `/* Auto-generated. Do not edit by hand. */
128
+ @theme {
129
+ ${lines.join('\n')}
130
+ }
131
+ `;
132
+ const filePath = path.join(outDir, 'typography.css');
133
+ await fs.writeFile(filePath, css, 'utf8');
134
+ console.log(`${tag} finished generating typography`);
135
+ }
136
+
137
+ // ------- CORE (fixed grouping incl. semibold) -------
138
+
139
+ async function generateBodies(textMap = {}) {
140
+ console.log(`${tag} generating bodies...`);
141
+ const outDir = path.join(paths.styles, 'core');
142
+ await fs.mkdir(outDir, {
143
+ recursive: true
144
+ });
145
+ const keys = Object.keys(textMap || {}).filter(k => k.startsWith('body-'));
146
+
147
+ // Normalize base: remove a single "mobile" segment after "body-"
148
+ function baseKey(k) {
149
+ const parts = k.split('-');
150
+ const idx = parts.indexOf('mobile');
151
+ if (idx !== -1) parts.splice(idx, 1);
152
+ return parts.join('-');
153
+ }
154
+
155
+ /** @type {Map<string,{desktop:string|null,mobile:string|null}>} */
156
+ const groups = new Map();
157
+ for (const k of keys) {
158
+ const base = baseKey(k);
159
+ const g = groups.get(base) ?? {
160
+ desktop: null,
161
+ mobile: null
162
+ };
163
+ if (k.includes('-mobile-')) g.mobile = k;else g.desktop = k;
164
+ groups.set(base, g);
165
+ }
166
+ const blocks = [];
167
+ for (const [base, {
168
+ desktop,
169
+ mobile
170
+ }] of [...groups.entries()].sort()) {
171
+ const hasMobile = !!mobile;
172
+ const hasDesktop = !!desktop;
173
+ const mobileRef = hasMobile ? mobile : desktop;
174
+ const desktopUpgrade = hasMobile && hasDesktop ? `\n @apply desktop-xs:text-${desktop} desktop-xs:leading-${desktop};` : ``;
175
+
176
+ // collapse “body-body-x” → “body-x”
177
+ const isDouble = base.startsWith('body-body-');
178
+ const utilName = isDouble ? base.replace(/^body-body-/, 'body-') : base;
179
+
180
+ // main utility
181
+ blocks.push(`@utility ${utilName} {
182
+ @apply text-${mobileRef} leading-${mobileRef};${desktopUpgrade}
183
+ }`);
184
+
185
+ // only add numeric alias if no collapse happened
186
+ if (!isDouble) {
187
+ const m = /^body-body-(\d+)$/i.exec(base);
188
+ if (m) {
189
+ const n = m[1];
190
+ blocks.push(`@utility body-${n} {
191
+ @apply text-${mobileRef} leading-${mobileRef};${desktopUpgrade}
192
+ }`);
193
+ }
194
+ }
195
+ }
196
+ const out = `/* Auto-generated. Do not edit by hand. */
197
+ ${blocks.join('\n\n')}
198
+ `;
199
+ await fs.writeFile(path.join(outDir, 'body.css'), out, 'utf8');
200
+ console.log(`${tag} finished generating bodies`);
201
+ }
202
+ async function generateHeadlines(textMap = {}) {
203
+ console.log(`${tag} generating headlines...`);
204
+ const outDir = path.join(paths.styles, 'core');
205
+ await fs.mkdir(outDir, {
206
+ recursive: true
207
+ });
208
+ const keys = Object.keys(textMap || {}).filter(k => k.startsWith('headline-'));
209
+
210
+ // collect ids present in either mobile or desktop
211
+ const ids = new Set();
212
+ for (const k of keys) {
213
+ let m = /^headline-h(\d+)$/i.exec(k);
214
+ if (m) {
215
+ ids.add(+m[1]);
216
+ continue;
217
+ }
218
+ m = /^headline-mobile-h(\d+)$/i.exec(k);
219
+ if (m) {
220
+ ids.add(+m[1]);
221
+ continue;
222
+ }
223
+ }
224
+ const blocks = [];
225
+ for (const n of [...ids].sort((a, b) => a - b)) {
226
+ const mobileKey = keys.includes(`headline-mobile-h${n}`) ? `headline-mobile-h${n}` : `headline-h${n}`;
227
+ const hasDesktop = keys.includes(`headline-h${n}`);
228
+ const desktopKey = hasDesktop ? `headline-h${n}` : null;
229
+ const desktopUpgrade = hasDesktop ? `\n @apply desktop-xs:text-${desktopKey} desktop-xs:leading-${desktopKey};` : ``;
230
+ blocks.push(`@utility headline-h${n} {
231
+ @apply text-${mobileKey} leading-${mobileKey};
232
+ @apply font-default;${desktopUpgrade}
233
+ }`);
234
+ }
235
+ const out = `/* Auto-generated. Do not edit by hand. */
236
+ ${blocks.join('\n\n')}
237
+ `;
238
+ await fs.writeFile(path.join(outDir, 'headline.css'), out, 'utf8');
239
+ console.log(`${tag} finished generating headlines`);
240
+ }
241
+
242
+ export { generateTailwind as default, generateTailwind };
package/dist/index.esm.js CHANGED
@@ -1131,7 +1131,7 @@ async function readFigma() {
1131
1131
  try {
1132
1132
  const {
1133
1133
  default: generateTailwind
1134
- } = await import('./generate-tailwind-yIoMdo1g.js');
1134
+ } = await import('./generate-tailwind-DQMJ7rRw.js');
1135
1135
  const figma = await readFigma();
1136
1136
  switch (cmd) {
1137
1137
  case 'astro':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vettvangur/design-system",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "",
5
5
  "access": "public",
6
6
  "type": "module",