shru-design-system 0.1.1 → 0.1.3
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/dist/index.d.mts +111 -1
- package/dist/index.d.ts +111 -1
- package/dist/index.js +1095 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1083 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -11
- package/scripts/apply-theme-sync.js +230 -0
- package/scripts/init.js +445 -10
package/scripts/init.js
CHANGED
|
@@ -1,14 +1,33 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Design system init script
|
|
5
5
|
* Sets up Tailwind CSS and required configuration
|
|
6
|
+
* This file is part of the design system library
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
const fs = require('fs');
|
|
9
10
|
const path = require('path');
|
|
10
11
|
const { execSync } = require('child_process');
|
|
11
12
|
|
|
13
|
+
// Get package name dynamically from package.json
|
|
14
|
+
function getPackageName() {
|
|
15
|
+
try {
|
|
16
|
+
const packageJsonPath = path.join(__dirname, '..', 'package.json');
|
|
17
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
18
|
+
return packageJson.name || 'shru-design-system';
|
|
19
|
+
} catch (error) {
|
|
20
|
+
// Fallback if package.json can't be read
|
|
21
|
+
return 'shru-design-system';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const PACKAGE_NAME = getPackageName();
|
|
26
|
+
const LIBRARY_NAME = `${PACKAGE_NAME} library`;
|
|
27
|
+
|
|
28
|
+
// Configuration constants
|
|
29
|
+
const TAILWIND_VERSION = '^3.4.0';
|
|
30
|
+
|
|
12
31
|
const colors = {
|
|
13
32
|
reset: '\x1b[0m',
|
|
14
33
|
green: '\x1b[32m',
|
|
@@ -49,8 +68,8 @@ function createTailwindConfig() {
|
|
|
49
68
|
const existing = fs.readFileSync(configPath, 'utf8');
|
|
50
69
|
|
|
51
70
|
// Check if our config is already there
|
|
52
|
-
if (existing.includes(
|
|
53
|
-
log(
|
|
71
|
+
if (existing.includes(PACKAGE_NAME)) {
|
|
72
|
+
log(`Configuration already includes ${PACKAGE_NAME} setup.`, 'green');
|
|
54
73
|
return;
|
|
55
74
|
}
|
|
56
75
|
|
|
@@ -60,11 +79,12 @@ function createTailwindConfig() {
|
|
|
60
79
|
}
|
|
61
80
|
|
|
62
81
|
const config = `/** @type {import('tailwindcss').Config} */
|
|
82
|
+
// This file was created by ${LIBRARY_NAME}
|
|
63
83
|
export default {
|
|
64
84
|
content: [
|
|
65
85
|
"./index.html",
|
|
66
86
|
"./src/**/*.{js,ts,jsx,tsx}",
|
|
67
|
-
"./node_modules/
|
|
87
|
+
"./node_modules/${PACKAGE_NAME}/dist/**/*.{js,mjs}",
|
|
68
88
|
],
|
|
69
89
|
theme: {
|
|
70
90
|
extend: {
|
|
@@ -104,6 +124,10 @@ export default {
|
|
|
104
124
|
md: "calc(var(--radius) - 2px)",
|
|
105
125
|
sm: "calc(var(--radius) - 4px)",
|
|
106
126
|
},
|
|
127
|
+
fontFamily: {
|
|
128
|
+
sans: ["var(--font-sans)", "system-ui", "sans-serif"],
|
|
129
|
+
body: ["var(--font-body)", "var(--font-sans)", "system-ui", "sans-serif"],
|
|
130
|
+
},
|
|
107
131
|
},
|
|
108
132
|
},
|
|
109
133
|
plugins: [],
|
|
@@ -122,7 +146,8 @@ function createPostCSSConfig() {
|
|
|
122
146
|
return;
|
|
123
147
|
}
|
|
124
148
|
|
|
125
|
-
const config =
|
|
149
|
+
const config = `// This file was created by ${LIBRARY_NAME}
|
|
150
|
+
export default {
|
|
126
151
|
plugins: {
|
|
127
152
|
tailwindcss: {},
|
|
128
153
|
autoprefixer: {},
|
|
@@ -155,7 +180,7 @@ function createCSSFile() {
|
|
|
155
180
|
// Append to existing file
|
|
156
181
|
const cssVars = `
|
|
157
182
|
|
|
158
|
-
/*
|
|
183
|
+
/* Design system CSS variables - Created by ${LIBRARY_NAME} */
|
|
159
184
|
@layer base {
|
|
160
185
|
:root {
|
|
161
186
|
--background: 0 0% 100%;
|
|
@@ -197,6 +222,7 @@ function createCSSFile() {
|
|
|
197
222
|
@tailwind components;
|
|
198
223
|
@tailwind utilities;
|
|
199
224
|
|
|
225
|
+
/* This file was created by ${LIBRARY_NAME} */
|
|
200
226
|
@layer base {
|
|
201
227
|
:root {
|
|
202
228
|
--background: 0 0% 100%;
|
|
@@ -234,6 +260,410 @@ function createCSSFile() {
|
|
|
234
260
|
log('Created src/index.css', 'green');
|
|
235
261
|
}
|
|
236
262
|
|
|
263
|
+
function createTokenFiles() {
|
|
264
|
+
const publicDir = path.join(process.cwd(), 'public');
|
|
265
|
+
const tokensDir = path.join(publicDir, 'tokens');
|
|
266
|
+
const themesDir = path.join(tokensDir, 'themes');
|
|
267
|
+
|
|
268
|
+
// Create directories
|
|
269
|
+
if (!fs.existsSync(publicDir)) {
|
|
270
|
+
fs.mkdirSync(publicDir, { recursive: true });
|
|
271
|
+
}
|
|
272
|
+
if (!fs.existsSync(tokensDir)) {
|
|
273
|
+
fs.mkdirSync(tokensDir, { recursive: true });
|
|
274
|
+
}
|
|
275
|
+
if (!fs.existsSync(themesDir)) {
|
|
276
|
+
fs.mkdirSync(themesDir, { recursive: true });
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Create base.json
|
|
280
|
+
const basePath = path.join(tokensDir, 'base.json');
|
|
281
|
+
if (!fs.existsSync(basePath)) {
|
|
282
|
+
const baseJson = {
|
|
283
|
+
"_createdBy": LIBRARY_NAME,
|
|
284
|
+
"color": {
|
|
285
|
+
"primary": "{palette.blue.500}",
|
|
286
|
+
"primary-hover": "{palette.blue.600}",
|
|
287
|
+
"primary-foreground": "{palette.white}",
|
|
288
|
+
"secondary": "{palette.gray.100}",
|
|
289
|
+
"secondary-foreground": "{palette.gray.900}",
|
|
290
|
+
"background": "{palette.white}",
|
|
291
|
+
"foreground": "{palette.gray.900}",
|
|
292
|
+
"card": "{palette.white}",
|
|
293
|
+
"card-foreground": "{palette.gray.900}",
|
|
294
|
+
"popover": "{palette.white}",
|
|
295
|
+
"popover-foreground": "{palette.gray.900}",
|
|
296
|
+
"muted": "{palette.gray.100}",
|
|
297
|
+
"muted-foreground": "{palette.gray.500}",
|
|
298
|
+
"accent": "{palette.gray.100}",
|
|
299
|
+
"accent-foreground": "{palette.gray.900}",
|
|
300
|
+
"destructive": "{palette.red.500}",
|
|
301
|
+
"destructive-foreground": "{palette.white}",
|
|
302
|
+
"border": "{palette.gray.200}",
|
|
303
|
+
"input": "{palette.gray.200}",
|
|
304
|
+
"ring": "{palette.gray.400}",
|
|
305
|
+
"skeleton": "{palette.gray.200}"
|
|
306
|
+
},
|
|
307
|
+
"spacing": {
|
|
308
|
+
"component": {
|
|
309
|
+
"xs": "0.25rem",
|
|
310
|
+
"sm": "0.5rem",
|
|
311
|
+
"md": "1rem",
|
|
312
|
+
"lg": "1.5rem",
|
|
313
|
+
"xl": "2rem"
|
|
314
|
+
},
|
|
315
|
+
"base": "0.25rem"
|
|
316
|
+
},
|
|
317
|
+
"typography": {
|
|
318
|
+
"font": {
|
|
319
|
+
"body": "var(--font-sans)",
|
|
320
|
+
"sans": "var(--font-sans)",
|
|
321
|
+
"mono": "var(--font-mono)"
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
"shape": {
|
|
325
|
+
"radius": {
|
|
326
|
+
"button": "0.375rem",
|
|
327
|
+
"card": "0.5rem",
|
|
328
|
+
"input": "0.375rem"
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
fs.writeFileSync(basePath, JSON.stringify(baseJson, null, 2));
|
|
333
|
+
log('Created public/tokens/base.json', 'green');
|
|
334
|
+
} else {
|
|
335
|
+
log('public/tokens/base.json already exists. Skipping...', 'yellow');
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Create palettes.json
|
|
339
|
+
const palettesPath = path.join(tokensDir, 'palettes.json');
|
|
340
|
+
if (!fs.existsSync(palettesPath)) {
|
|
341
|
+
const palettesJson = {
|
|
342
|
+
"_createdBy": LIBRARY_NAME,
|
|
343
|
+
"palette": {
|
|
344
|
+
"white": "#ffffff",
|
|
345
|
+
"black": "#000000",
|
|
346
|
+
"transparent": "transparent",
|
|
347
|
+
"gray": {
|
|
348
|
+
"50": "#f9fafb",
|
|
349
|
+
"100": "#f3f4f6",
|
|
350
|
+
"200": "#e5e7eb",
|
|
351
|
+
"300": "#d1d5db",
|
|
352
|
+
"400": "#9ca3af",
|
|
353
|
+
"500": "#6b7280",
|
|
354
|
+
"600": "#4b5563",
|
|
355
|
+
"700": "#374151",
|
|
356
|
+
"800": "#1f2937",
|
|
357
|
+
"900": "#111827",
|
|
358
|
+
"950": "#030712"
|
|
359
|
+
},
|
|
360
|
+
"blue": {
|
|
361
|
+
"50": "#eff6ff",
|
|
362
|
+
"100": "#dbeafe",
|
|
363
|
+
"200": "#bfdbfe",
|
|
364
|
+
"300": "#93c5fd",
|
|
365
|
+
"400": "#60a5fa",
|
|
366
|
+
"500": "#3b82f6",
|
|
367
|
+
"600": "#2563eb",
|
|
368
|
+
"700": "#1d4ed8",
|
|
369
|
+
"800": "#1e40af",
|
|
370
|
+
"900": "#1e3a8a",
|
|
371
|
+
"950": "#172554"
|
|
372
|
+
},
|
|
373
|
+
"red": {
|
|
374
|
+
"50": "#fef2f2",
|
|
375
|
+
"100": "#fee2e2",
|
|
376
|
+
"200": "#fecaca",
|
|
377
|
+
"300": "#fca5a5",
|
|
378
|
+
"400": "#f87171",
|
|
379
|
+
"500": "#ef4444",
|
|
380
|
+
"600": "#dc2626",
|
|
381
|
+
"700": "#b91c1c",
|
|
382
|
+
"800": "#991b1b",
|
|
383
|
+
"900": "#7f1d1d",
|
|
384
|
+
"950": "#450a0a"
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
fs.writeFileSync(palettesPath, JSON.stringify(palettesJson, null, 2));
|
|
389
|
+
log('Created public/tokens/palettes.json', 'green');
|
|
390
|
+
} else {
|
|
391
|
+
log('public/tokens/palettes.json already exists. Skipping...', 'yellow');
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Create theme directories and files
|
|
395
|
+
const themeCategories = ['color', 'typography', 'shape', 'density', 'animation', 'custom'];
|
|
396
|
+
|
|
397
|
+
themeCategories.forEach(category => {
|
|
398
|
+
const categoryDir = path.join(themesDir, category);
|
|
399
|
+
if (!fs.existsSync(categoryDir)) {
|
|
400
|
+
fs.mkdirSync(categoryDir, { recursive: true });
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
// Create color/white.json
|
|
405
|
+
const whiteThemePath = path.join(themesDir, 'color', 'white.json');
|
|
406
|
+
if (!fs.existsSync(whiteThemePath)) {
|
|
407
|
+
const whiteTheme = {
|
|
408
|
+
"_createdBy": LIBRARY_NAME,
|
|
409
|
+
"color": {
|
|
410
|
+
"primary": "{palette.blue.500}",
|
|
411
|
+
"primary-foreground": "{palette.white}",
|
|
412
|
+
"background": "{palette.white}",
|
|
413
|
+
"foreground": "{palette.gray.900}",
|
|
414
|
+
"card": "{palette.white}",
|
|
415
|
+
"card-foreground": "{palette.gray.900}",
|
|
416
|
+
"popover": "{palette.white}",
|
|
417
|
+
"popover-foreground": "{palette.gray.900}",
|
|
418
|
+
"secondary": "{palette.gray.100}",
|
|
419
|
+
"secondary-foreground": "{palette.gray.900}",
|
|
420
|
+
"muted": "{palette.gray.100}",
|
|
421
|
+
"muted-foreground": "{palette.gray.500}",
|
|
422
|
+
"accent": "{palette.gray.100}",
|
|
423
|
+
"accent-foreground": "{palette.gray.900}",
|
|
424
|
+
"destructive": "{palette.red.500}",
|
|
425
|
+
"destructive-foreground": "{palette.white}",
|
|
426
|
+
"border": "{palette.gray.200}",
|
|
427
|
+
"input": "{palette.gray.200}",
|
|
428
|
+
"ring": "{palette.gray.400}",
|
|
429
|
+
"skeleton": "{palette.gray.200}"
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
fs.writeFileSync(whiteThemePath, JSON.stringify(whiteTheme, null, 2));
|
|
433
|
+
log('Created public/tokens/themes/color/white.json', 'green');
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Create color/dark.json
|
|
437
|
+
const darkThemePath = path.join(themesDir, 'color', 'dark.json');
|
|
438
|
+
if (!fs.existsSync(darkThemePath)) {
|
|
439
|
+
const darkTheme = {
|
|
440
|
+
"_createdBy": LIBRARY_NAME,
|
|
441
|
+
"color": {
|
|
442
|
+
"primary": "{palette.blue.400}",
|
|
443
|
+
"primary-foreground": "{palette.gray.900}",
|
|
444
|
+
"background": "{palette.gray.900}",
|
|
445
|
+
"foreground": "{palette.gray.50}",
|
|
446
|
+
"card": "{palette.gray.800}",
|
|
447
|
+
"card-foreground": "{palette.gray.50}",
|
|
448
|
+
"popover": "{palette.gray.800}",
|
|
449
|
+
"popover-foreground": "{palette.gray.50}",
|
|
450
|
+
"secondary": "{palette.gray.800}",
|
|
451
|
+
"secondary-foreground": "{palette.gray.50}",
|
|
452
|
+
"muted": "{palette.gray.800}",
|
|
453
|
+
"muted-foreground": "{palette.gray.400}",
|
|
454
|
+
"accent": "{palette.gray.800}",
|
|
455
|
+
"accent-foreground": "{palette.gray.50}",
|
|
456
|
+
"destructive": "{palette.red.500}",
|
|
457
|
+
"destructive-foreground": "{palette.white}",
|
|
458
|
+
"border": "{palette.gray.700}",
|
|
459
|
+
"input": "{palette.gray.700}",
|
|
460
|
+
"ring": "{palette.gray.600}",
|
|
461
|
+
"skeleton": "{palette.gray.700}"
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
fs.writeFileSync(darkThemePath, JSON.stringify(darkTheme, null, 2));
|
|
465
|
+
log('Created public/tokens/themes/color/dark.json', 'green');
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Create typography/sans.json
|
|
469
|
+
const sansThemePath = path.join(themesDir, 'typography', 'sans.json');
|
|
470
|
+
if (!fs.existsSync(sansThemePath)) {
|
|
471
|
+
const sansTheme = {
|
|
472
|
+
"_createdBy": LIBRARY_NAME,
|
|
473
|
+
"typography": {
|
|
474
|
+
"font": {
|
|
475
|
+
"body": "system-ui, -apple-system, sans-serif",
|
|
476
|
+
"sans": "system-ui, -apple-system, sans-serif"
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
fs.writeFileSync(sansThemePath, JSON.stringify(sansTheme, null, 2));
|
|
481
|
+
log('Created public/tokens/themes/typography/sans.json', 'green');
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Create typography/serif.json
|
|
485
|
+
const serifThemePath = path.join(themesDir, 'typography', 'serif.json');
|
|
486
|
+
if (!fs.existsSync(serifThemePath)) {
|
|
487
|
+
const serifTheme = {
|
|
488
|
+
"_createdBy": LIBRARY_NAME,
|
|
489
|
+
"typography": {
|
|
490
|
+
"font": {
|
|
491
|
+
"body": "Georgia, serif",
|
|
492
|
+
"sans": "Georgia, serif"
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
fs.writeFileSync(serifThemePath, JSON.stringify(serifTheme, null, 2));
|
|
497
|
+
log('Created public/tokens/themes/typography/serif.json', 'green');
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Create shape/smooth.json
|
|
501
|
+
const smoothThemePath = path.join(themesDir, 'shape', 'smooth.json');
|
|
502
|
+
if (!fs.existsSync(smoothThemePath)) {
|
|
503
|
+
const smoothTheme = {
|
|
504
|
+
"_createdBy": LIBRARY_NAME,
|
|
505
|
+
"shape": {
|
|
506
|
+
"radius": {
|
|
507
|
+
"button": "0.5rem",
|
|
508
|
+
"card": "0.75rem",
|
|
509
|
+
"input": "0.5rem"
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
fs.writeFileSync(smoothThemePath, JSON.stringify(smoothTheme, null, 2));
|
|
514
|
+
log('Created public/tokens/themes/shape/smooth.json', 'green');
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Create shape/sharp.json
|
|
518
|
+
const sharpThemePath = path.join(themesDir, 'shape', 'sharp.json');
|
|
519
|
+
if (!fs.existsSync(sharpThemePath)) {
|
|
520
|
+
const sharpTheme = {
|
|
521
|
+
"_createdBy": LIBRARY_NAME,
|
|
522
|
+
"shape": {
|
|
523
|
+
"radius": {
|
|
524
|
+
"button": "0",
|
|
525
|
+
"card": "0",
|
|
526
|
+
"input": "0"
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
fs.writeFileSync(sharpThemePath, JSON.stringify(sharpTheme, null, 2));
|
|
531
|
+
log('Created public/tokens/themes/shape/sharp.json', 'green');
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Create density/comfortable.json
|
|
535
|
+
const comfortableThemePath = path.join(themesDir, 'density', 'comfortable.json');
|
|
536
|
+
if (!fs.existsSync(comfortableThemePath)) {
|
|
537
|
+
const comfortableTheme = {
|
|
538
|
+
"_createdBy": LIBRARY_NAME,
|
|
539
|
+
"spacing": {
|
|
540
|
+
"component": {
|
|
541
|
+
"xs": "0.5rem",
|
|
542
|
+
"sm": "0.75rem",
|
|
543
|
+
"md": "1.25rem",
|
|
544
|
+
"lg": "2rem",
|
|
545
|
+
"xl": "2.5rem"
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
fs.writeFileSync(comfortableThemePath, JSON.stringify(comfortableTheme, null, 2));
|
|
550
|
+
log('Created public/tokens/themes/density/comfortable.json', 'green');
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Create density/compact.json
|
|
554
|
+
const compactThemePath = path.join(themesDir, 'density', 'compact.json');
|
|
555
|
+
if (!fs.existsSync(compactThemePath)) {
|
|
556
|
+
const compactTheme = {
|
|
557
|
+
"_createdBy": LIBRARY_NAME,
|
|
558
|
+
"spacing": {
|
|
559
|
+
"component": {
|
|
560
|
+
"xs": "0.25rem",
|
|
561
|
+
"sm": "0.5rem",
|
|
562
|
+
"md": "0.75rem",
|
|
563
|
+
"lg": "1rem",
|
|
564
|
+
"xl": "1.5rem"
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
fs.writeFileSync(compactThemePath, JSON.stringify(compactTheme, null, 2));
|
|
569
|
+
log('Created public/tokens/themes/density/compact.json', 'green');
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Create animation/gentle.json
|
|
573
|
+
const gentleThemePath = path.join(themesDir, 'animation', 'gentle.json');
|
|
574
|
+
if (!fs.existsSync(gentleThemePath)) {
|
|
575
|
+
const gentleTheme = {
|
|
576
|
+
"_createdBy": LIBRARY_NAME,
|
|
577
|
+
"animation": {
|
|
578
|
+
"duration": {
|
|
579
|
+
"fast": "150ms",
|
|
580
|
+
"normal": "300ms",
|
|
581
|
+
"slow": "500ms"
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
fs.writeFileSync(gentleThemePath, JSON.stringify(gentleTheme, null, 2));
|
|
586
|
+
log('Created public/tokens/themes/animation/gentle.json', 'green');
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// Create animation/brisk.json
|
|
590
|
+
const briskThemePath = path.join(themesDir, 'animation', 'brisk.json');
|
|
591
|
+
if (!fs.existsSync(briskThemePath)) {
|
|
592
|
+
const briskTheme = {
|
|
593
|
+
"_createdBy": LIBRARY_NAME,
|
|
594
|
+
"animation": {
|
|
595
|
+
"duration": {
|
|
596
|
+
"fast": "100ms",
|
|
597
|
+
"normal": "200ms",
|
|
598
|
+
"slow": "300ms"
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
fs.writeFileSync(briskThemePath, JSON.stringify(briskTheme, null, 2));
|
|
603
|
+
log('Created public/tokens/themes/animation/brisk.json', 'green');
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function injectThemeScript() {
|
|
608
|
+
const scriptPath = path.join(__dirname, 'apply-theme-sync.js');
|
|
609
|
+
const scriptContent = fs.readFileSync(scriptPath, 'utf8');
|
|
610
|
+
|
|
611
|
+
// Try to find and update index.html
|
|
612
|
+
const htmlPaths = [
|
|
613
|
+
path.join(process.cwd(), 'index.html'),
|
|
614
|
+
path.join(process.cwd(), 'public', 'index.html'),
|
|
615
|
+
];
|
|
616
|
+
|
|
617
|
+
for (const htmlPath of htmlPaths) {
|
|
618
|
+
if (fs.existsSync(htmlPath)) {
|
|
619
|
+
let htmlContent = fs.readFileSync(htmlPath, 'utf8');
|
|
620
|
+
|
|
621
|
+
// Check if script is already injected
|
|
622
|
+
if (htmlContent.includes('dynamic-theme') || htmlContent.includes('apply-theme-sync')) {
|
|
623
|
+
log('Theme sync script already in index.html', 'green');
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Add resource hints for token files (helps browser preload)
|
|
628
|
+
// Preload critical token files that are always needed
|
|
629
|
+
const preloadLinks = ` <!-- Preload token files for faster theme application - Created by ${LIBRARY_NAME} -->
|
|
630
|
+
<link rel="preload" href="/tokens/base.json" as="fetch" crossorigin>
|
|
631
|
+
<link rel="preload" href="/tokens/palettes.json" as="fetch" crossorigin>
|
|
632
|
+
<link rel="preload" href="/tokens/themes/color/white.json" as="fetch" crossorigin>
|
|
633
|
+
<link rel="preload" href="/tokens/themes/color/dark.json" as="fetch" crossorigin>`;
|
|
634
|
+
|
|
635
|
+
// Inject blocking script in <head> (runs before React)
|
|
636
|
+
const scriptTag = ` <!-- Blocking theme script to prevent flash - Created by ${LIBRARY_NAME} -->
|
|
637
|
+
<script>${scriptContent}</script>`;
|
|
638
|
+
|
|
639
|
+
if (htmlContent.includes('</head>')) {
|
|
640
|
+
// Add preload links and script before </head>
|
|
641
|
+
htmlContent = htmlContent.replace('</head>', `${preloadLinks}\n${scriptTag}\n</head>`);
|
|
642
|
+
fs.writeFileSync(htmlPath, htmlContent);
|
|
643
|
+
log('Injected theme sync script and preload links into index.html', 'green');
|
|
644
|
+
return;
|
|
645
|
+
} else if (htmlContent.includes('<head>')) {
|
|
646
|
+
// If no closing </head>, try to add after <head>
|
|
647
|
+
htmlContent = htmlContent.replace('<head>', `<head>\n${preloadLinks}\n${scriptTag}`);
|
|
648
|
+
fs.writeFileSync(htmlPath, htmlContent);
|
|
649
|
+
log('Injected theme sync script and preload links into index.html', 'green');
|
|
650
|
+
return;
|
|
651
|
+
} else if (htmlContent.includes('</body>')) {
|
|
652
|
+
// Last resort: add before </body>
|
|
653
|
+
htmlContent = htmlContent.replace('</body>', `${preloadLinks}\n${scriptTag}\n</body>`);
|
|
654
|
+
fs.writeFileSync(htmlPath, htmlContent);
|
|
655
|
+
log('Injected theme sync script and preload links into index.html (before </body>)', 'yellow');
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
log('⚠️ Could not find index.html. Add these to <head> manually:', 'yellow');
|
|
662
|
+
log(' <link rel="preload" href="/tokens/base.json" as="fetch" crossorigin>', 'blue');
|
|
663
|
+
log(' <link rel="preload" href="/tokens/palettes.json" as="fetch" crossorigin>', 'blue');
|
|
664
|
+
log(' <script>/* apply-theme-sync.js content */</script>', 'blue');
|
|
665
|
+
}
|
|
666
|
+
|
|
237
667
|
function checkMainFile() {
|
|
238
668
|
const possiblePaths = [
|
|
239
669
|
path.join(process.cwd(), 'src', 'main.tsx'),
|
|
@@ -263,12 +693,12 @@ function checkMainFile() {
|
|
|
263
693
|
|
|
264
694
|
// Main execution
|
|
265
695
|
function main() {
|
|
266
|
-
log(
|
|
696
|
+
log(`\n🚀 Setting up ${PACKAGE_NAME}...\n`, 'blue');
|
|
267
697
|
|
|
268
698
|
// Check and install Tailwind
|
|
269
699
|
if (!checkPackageInstalled('tailwindcss')) {
|
|
270
700
|
log('Tailwind CSS not found. Installing...', 'yellow');
|
|
271
|
-
if (!installPackage(
|
|
701
|
+
if (!installPackage(`tailwindcss@${TAILWIND_VERSION}`)) {
|
|
272
702
|
log('Failed to install Tailwind CSS. Please install manually.', 'red');
|
|
273
703
|
process.exit(1);
|
|
274
704
|
}
|
|
@@ -290,6 +720,8 @@ function main() {
|
|
|
290
720
|
createTailwindConfig();
|
|
291
721
|
createPostCSSConfig();
|
|
292
722
|
createCSSFile();
|
|
723
|
+
createTokenFiles();
|
|
724
|
+
injectThemeScript();
|
|
293
725
|
checkMainFile();
|
|
294
726
|
|
|
295
727
|
log('\n✅ Setup complete!', 'green');
|
|
@@ -297,9 +729,12 @@ function main() {
|
|
|
297
729
|
log('1. Make sure to import the CSS file in your entry point:', 'yellow');
|
|
298
730
|
log(" import './index.css'", 'blue');
|
|
299
731
|
log('2. Start using components:', 'yellow');
|
|
300
|
-
log(
|
|
732
|
+
log(` import { Button, ThemeToggle } from '${PACKAGE_NAME}'`, 'blue');
|
|
733
|
+
log('\n💡 Custom Token Files:', 'blue');
|
|
734
|
+
log(' You can add custom theme files to public/tokens/themes/{category}/', 'yellow');
|
|
735
|
+
log(' Example: public/tokens/themes/color/ocean.json', 'blue');
|
|
736
|
+
log(' The ThemeToggle will automatically discover and use them.', 'blue');
|
|
301
737
|
log('\n');
|
|
302
738
|
}
|
|
303
739
|
|
|
304
740
|
main();
|
|
305
|
-
|