shru-design-system 0.1.4 → 0.1.6

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.mjs CHANGED
@@ -500,26 +500,11 @@ var baseThemeCategories = {
500
500
  description: "Fast, brisk animations"
501
501
  }
502
502
  }
503
- },
504
- custom: {
505
- name: "Custom",
506
- order: 10,
507
- // Highest priority
508
- themes: {
509
- brand: {
510
- name: "Brand",
511
- file: "custom/brand.json",
512
- icon: "\u{1F3AF}",
513
- description: "Brand-specific theme"
514
- },
515
- minimal: {
516
- name: "Minimal",
517
- file: "custom/minimal.json",
518
- icon: "\u{1F3AA}",
519
- description: "Minimal theme"
520
- }
521
- }
522
503
  }
504
+ // Custom themes are not included in base config
505
+ // They should be discovered dynamically or registered by users
506
+ // Users can add custom themes by creating files in /tokens/themes/custom/
507
+ // and registering them using registerTheme()
523
508
  };
524
509
  var discoveredThemesCache = null;
525
510
  async function discoverThemes() {
@@ -536,7 +521,9 @@ async function discoverThemes() {
536
521
  discoveredThemesCache = discovered;
537
522
  return discovered;
538
523
  } catch (error) {
539
- console.warn("Error discovering themes:", error);
524
+ if (typeof window !== "undefined" && window.__DESIGN_SYSTEM_DEBUG__) {
525
+ console.warn("Error discovering themes:", error);
526
+ }
540
527
  return baseThemeCategories;
541
528
  }
542
529
  }
@@ -648,14 +635,23 @@ async function loadTokenFile(path) {
648
635
  try {
649
636
  const response = await fetch(path);
650
637
  if (!response.ok) {
638
+ if (response.status === 404) {
639
+ return null;
640
+ }
651
641
  throw new Error(`Failed to load ${path}: ${response.statusText}`);
652
642
  }
643
+ const contentType = response.headers.get("content-type");
644
+ if (!contentType || !contentType.includes("application/json")) {
645
+ return null;
646
+ }
653
647
  const data = await response.json();
654
648
  tokenCache.set(path, data);
655
649
  return deepClone(data);
656
650
  } catch (error) {
657
- console.error(`Error loading token file ${path}:`, error);
658
- throw error;
651
+ if (typeof window !== "undefined" && window.__DESIGN_SYSTEM_DEBUG__) {
652
+ console.warn(`Error loading token file ${path}:`, error);
653
+ }
654
+ return null;
659
655
  }
660
656
  }
661
657
  function resolveReferences(tokens, palette) {
@@ -670,7 +666,9 @@ function resolveReferences(tokens, palette) {
670
666
  if (current && typeof current === "object" && key in current) {
671
667
  current = current[key];
672
668
  } else {
673
- console.warn(`Token reference not found: {${match[1]}}`);
669
+ if (typeof window !== "undefined" && window.__DESIGN_SYSTEM_DEBUG__) {
670
+ console.warn(`Token reference not found: {${match[1]}}`);
671
+ }
674
672
  return value;
675
673
  }
676
674
  }
@@ -755,49 +753,31 @@ function flattenToCSS(tokens, prefix = "", result = {}, isColorContext = false)
755
753
  }
756
754
  function mapToTailwindVars(cssVars) {
757
755
  const mapped = { ...cssVars };
758
- if (cssVars["--radius-button"]) {
756
+ if (cssVars["--radius-button"] && !cssVars["--radius"]) {
759
757
  mapped["--radius"] = cssVars["--radius-button"];
760
758
  }
761
- if (cssVars["--radius-card"]) {
759
+ if (cssVars["--radius-card"] && !cssVars["--radius-lg"]) {
762
760
  mapped["--radius-lg"] = cssVars["--radius-card"];
763
761
  }
764
- if (cssVars["--font-body"]) {
762
+ if (cssVars["--font-body"] && !cssVars["--font-sans"]) {
765
763
  mapped["--font-sans"] = cssVars["--font-body"];
766
764
  }
767
- if (cssVars["--spacing-base"]) {
765
+ if (cssVars["--spacing-base"] && !cssVars["--spacing"]) {
768
766
  mapped["--spacing"] = cssVars["--spacing-base"];
769
- } else if (cssVars["--spacing-component-md"]) {
767
+ } else if (cssVars["--spacing-component-md"] && !cssVars["--spacing"]) {
770
768
  mapped["--spacing"] = cssVars["--spacing-component-md"];
771
769
  }
772
- if (cssVars["--spacing-component-xs"]) {
773
- mapped["--spacing-component-xs"] = cssVars["--spacing-component-xs"];
774
- }
775
- if (cssVars["--spacing-component-sm"]) {
776
- mapped["--spacing-component-sm"] = cssVars["--spacing-component-sm"];
777
- }
778
- if (cssVars["--spacing-component-md"]) {
779
- mapped["--spacing-component-md"] = cssVars["--spacing-component-md"];
780
- }
781
- if (cssVars["--spacing-component-lg"]) {
782
- mapped["--spacing-component-lg"] = cssVars["--spacing-component-lg"];
783
- }
784
- if (cssVars["--spacing-component-xl"]) {
785
- mapped["--spacing-component-xl"] = cssVars["--spacing-component-xl"];
786
- }
787
- if (cssVars["--duration-fast"]) {
788
- mapped["--duration-fast"] = cssVars["--duration-fast"];
789
- }
790
- if (cssVars["--duration-normal"]) {
791
- mapped["--duration-normal"] = cssVars["--duration-normal"];
792
- }
793
- if (cssVars["--duration-slow"]) {
794
- mapped["--duration-slow"] = cssVars["--duration-slow"];
795
- }
796
770
  return mapped;
797
771
  }
798
772
  function generateCSSString(cssVars) {
799
773
  const mappedVars = mapToTailwindVars(cssVars);
800
- const vars = Object.entries(mappedVars).map(([key, value]) => ` ${key}: ${value};`).join("\n");
774
+ const vars = Object.entries(mappedVars).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => ` ${key}: ${value};`).join("\n");
775
+ if (typeof window !== "undefined" && window.__DESIGN_SYSTEM_DEBUG__) {
776
+ console.group("\u{1F3A8} Design System CSS Variables");
777
+ console.table(mappedVars);
778
+ console.log("Total variables:", Object.keys(mappedVars).length);
779
+ console.groupEnd();
780
+ }
801
781
  return `:root {
802
782
  ${vars}
803
783
  }`;
@@ -811,16 +791,49 @@ function applyThemeCSS(css) {
811
791
  }
812
792
  styleTag.textContent = css;
813
793
  }
794
+ function enableDebugMode() {
795
+ if (typeof window !== "undefined") {
796
+ window.__DESIGN_SYSTEM_DEBUG__ = true;
797
+ console.log("\u{1F50D} Design System debug mode enabled");
798
+ console.log("CSS variables will be logged when themes change");
799
+ }
800
+ }
801
+ function getCurrentCSSVariables() {
802
+ if (typeof window === "undefined") return {};
803
+ const styleTag = document.getElementById("dynamic-theme");
804
+ if (!styleTag) return {};
805
+ const cssText = styleTag.textContent || "";
806
+ const vars = {};
807
+ const matches = cssText.matchAll(/--([^:]+):\s*([^;]+);/g);
808
+ for (const match of matches) {
809
+ vars[`--${match[1].trim()}`] = match[2].trim();
810
+ }
811
+ return vars;
812
+ }
814
813
  async function generateAndApplyTheme(selectedThemes = {}) {
815
814
  try {
816
815
  const themeCategories = await getThemeCategories();
817
816
  const validation = validateThemeSelection(selectedThemes, themeCategories);
818
817
  if (!validation.valid) {
819
- console.error("Invalid theme selection:", validation.errors);
820
- throw new Error(`Invalid theme selection: ${validation.errors.join(", ")}`);
818
+ const nonCustomErrors = validation.errors.filter((err) => !err.includes("custom"));
819
+ if (nonCustomErrors.length > 0) {
820
+ if (typeof window !== "undefined" && window.__DESIGN_SYSTEM_DEBUG__) {
821
+ console.error("Invalid theme selection:", nonCustomErrors);
822
+ }
823
+ throw new Error(`Invalid theme selection: ${nonCustomErrors.join(", ")}`);
824
+ }
825
+ if (typeof window !== "undefined" && window.__DESIGN_SYSTEM_DEBUG__) {
826
+ console.warn("Custom theme files not found, continuing without them:", validation.errors);
827
+ }
821
828
  }
822
829
  const base = await loadTokenFile("/tokens/base.json");
830
+ if (!base) {
831
+ throw new Error("Failed to load base tokens from /tokens/base.json");
832
+ }
823
833
  const palettes = await loadTokenFile("/tokens/palettes.json");
834
+ if (!palettes || !palettes.palette) {
835
+ throw new Error("Failed to load palette from /tokens/palettes.json");
836
+ }
824
837
  const palette = palettes.palette;
825
838
  let merged = deepMerge(base, { palette });
826
839
  const categoryOrder = Object.values(themeCategories).sort((a, b) => a.order - b.order).map((cat) => cat.name.toLowerCase());
@@ -830,18 +843,30 @@ async function generateAndApplyTheme(selectedThemes = {}) {
830
843
  if (!themeId) continue;
831
844
  const themePath = `/tokens/themes/${category}/${themeId}.json`;
832
845
  const themeData = await loadTokenFile(themePath);
833
- merged = deepMerge(merged, themeData);
846
+ if (themeData) {
847
+ merged = deepMerge(merged, themeData);
848
+ } else if (typeof window !== "undefined" && window.__DESIGN_SYSTEM_DEBUG__) {
849
+ console.warn(`Theme file not found: ${themePath}`);
850
+ }
834
851
  }
835
852
  if (selectedThemes.custom) {
836
853
  const customPath = `/tokens/themes/custom/${selectedThemes.custom}.json`;
837
854
  const customData = await loadTokenFile(customPath);
838
- merged = deepMerge(merged, customData);
855
+ if (customData) {
856
+ merged = deepMerge(merged, customData);
857
+ } else if (typeof window !== "undefined" && window.__DESIGN_SYSTEM_DEBUG__) {
858
+ console.warn(`Custom theme file not found: ${customPath} (this is normal if you haven't created it yet)`);
859
+ }
839
860
  }
840
861
  const resolved = resolveReferences(merged, palette);
841
862
  const cssVars = flattenToCSS(resolved);
842
863
  const css = generateCSSString(cssVars);
843
864
  if (typeof document !== "undefined") {
844
865
  applyThemeCSS(css);
866
+ if (window.__DESIGN_SYSTEM_DEBUG__) {
867
+ window.__DESIGN_SYSTEM_VARS__ = cssVars;
868
+ console.log("\u{1F4A1} Access CSS variables via: window.__DESIGN_SYSTEM_VARS__");
869
+ }
845
870
  }
846
871
  return {
847
872
  success: true,
@@ -849,7 +874,9 @@ async function generateAndApplyTheme(selectedThemes = {}) {
849
874
  cssVars
850
875
  };
851
876
  } catch (error) {
852
- console.error("Error generating theme:", error);
877
+ if (typeof window !== "undefined" && window.__DESIGN_SYSTEM_DEBUG__) {
878
+ console.error("Error generating theme:", error);
879
+ }
853
880
  throw error;
854
881
  }
855
882
  }
@@ -871,7 +898,9 @@ function useTheme() {
871
898
  } catch (err) {
872
899
  const errorMessage = err instanceof Error ? err.message : "Failed to apply theme";
873
900
  setError(errorMessage);
874
- console.error("Theme application error:", err);
901
+ if (typeof window !== "undefined" && window.__DESIGN_SYSTEM_DEBUG__) {
902
+ console.error("Theme application error:", err);
903
+ }
875
904
  } finally {
876
905
  setIsLoading(false);
877
906
  }
@@ -1279,28 +1308,25 @@ function applyThemeSync() {
1279
1308
  }
1280
1309
  try {
1281
1310
  const base = loadJSONSync("/tokens/base.json");
1311
+ if (!base) {
1312
+ return;
1313
+ }
1282
1314
  const palettes = loadJSONSync("/tokens/palettes.json");
1283
1315
  const palette = palettes?.palette || {};
1284
- let merged = deepMergeSync(base || {}, { palette });
1316
+ let merged = deepMergeSync(base, { palette });
1285
1317
  const categoryOrder = ["color", "typography", "shape", "density", "animation"];
1286
1318
  for (const category of categoryOrder) {
1287
1319
  const themeId = selectedThemes[category];
1288
1320
  if (!themeId) continue;
1289
- try {
1290
- const themeData = loadJSONSync(`/tokens/themes/${category}/${themeId}.json`);
1291
- if (themeData) {
1292
- merged = deepMergeSync(merged, themeData);
1293
- }
1294
- } catch {
1321
+ const themeData = loadJSONSync(`/tokens/themes/${category}/${themeId}.json`);
1322
+ if (themeData) {
1323
+ merged = deepMergeSync(merged, themeData);
1295
1324
  }
1296
1325
  }
1297
1326
  if (selectedThemes.custom) {
1298
- try {
1299
- const customData = loadJSONSync(`/tokens/themes/custom/${selectedThemes.custom}.json`);
1300
- if (customData) {
1301
- merged = deepMergeSync(merged, customData);
1302
- }
1303
- } catch {
1327
+ const customData = loadJSONSync(`/tokens/themes/custom/${selectedThemes.custom}.json`);
1328
+ if (customData) {
1329
+ merged = deepMergeSync(merged, customData);
1304
1330
  }
1305
1331
  }
1306
1332
  const resolved = resolveReferencesSync(merged, palette);
@@ -1317,7 +1343,9 @@ ${Object.entries(mappedVars).map(([key, value]) => ` ${key}: ${value};`).join("
1317
1343
  }
1318
1344
  styleTag.textContent = css;
1319
1345
  } catch (error) {
1320
- console.warn("Sync theme application failed, will apply via React:", error);
1346
+ if (typeof window !== "undefined" && window.__DESIGN_SYSTEM_DEBUG__) {
1347
+ console.warn("Sync theme application failed, will apply via React:", error);
1348
+ }
1321
1349
  }
1322
1350
  }
1323
1351
  function loadJSONSync(path) {
@@ -1325,8 +1353,15 @@ function loadJSONSync(path) {
1325
1353
  const xhr = new XMLHttpRequest();
1326
1354
  xhr.open("GET", path, false);
1327
1355
  xhr.send(null);
1356
+ if (xhr.status === 404) {
1357
+ return null;
1358
+ }
1328
1359
  if (xhr.status === 200 || xhr.status === 0) {
1329
- return JSON.parse(xhr.responseText);
1360
+ const contentType = xhr.getResponseHeader("content-type");
1361
+ if (contentType && contentType.includes("application/json")) {
1362
+ return JSON.parse(xhr.responseText);
1363
+ }
1364
+ return null;
1330
1365
  }
1331
1366
  } catch {
1332
1367
  }
@@ -1448,47 +1483,23 @@ function flattenToCSSSync(tokens, prefix = "", result = {}, isColorContext = fal
1448
1483
  }
1449
1484
  function mapToTailwindVarsSync(cssVars) {
1450
1485
  const mapped = { ...cssVars };
1451
- if (cssVars["--radius-button"]) {
1486
+ if (cssVars["--radius-button"] && !cssVars["--radius"]) {
1452
1487
  mapped["--radius"] = cssVars["--radius-button"];
1453
1488
  }
1454
- if (cssVars["--radius-card"]) {
1489
+ if (cssVars["--radius-card"] && !cssVars["--radius-lg"]) {
1455
1490
  mapped["--radius-lg"] = cssVars["--radius-card"];
1456
1491
  }
1457
- if (cssVars["--font-body"]) {
1492
+ if (cssVars["--font-body"] && !cssVars["--font-sans"]) {
1458
1493
  mapped["--font-sans"] = cssVars["--font-body"];
1459
1494
  }
1460
- if (cssVars["--spacing-base"]) {
1495
+ if (cssVars["--spacing-base"] && !cssVars["--spacing"]) {
1461
1496
  mapped["--spacing"] = cssVars["--spacing-base"];
1462
- } else if (cssVars["--spacing-component-md"]) {
1497
+ } else if (cssVars["--spacing-component-md"] && !cssVars["--spacing"]) {
1463
1498
  mapped["--spacing"] = cssVars["--spacing-component-md"];
1464
1499
  }
1465
- if (cssVars["--spacing-component-xs"]) {
1466
- mapped["--spacing-component-xs"] = cssVars["--spacing-component-xs"];
1467
- }
1468
- if (cssVars["--spacing-component-sm"]) {
1469
- mapped["--spacing-component-sm"] = cssVars["--spacing-component-sm"];
1470
- }
1471
- if (cssVars["--spacing-component-md"]) {
1472
- mapped["--spacing-component-md"] = cssVars["--spacing-component-md"];
1473
- }
1474
- if (cssVars["--spacing-component-lg"]) {
1475
- mapped["--spacing-component-lg"] = cssVars["--spacing-component-lg"];
1476
- }
1477
- if (cssVars["--spacing-component-xl"]) {
1478
- mapped["--spacing-component-xl"] = cssVars["--spacing-component-xl"];
1479
- }
1480
- if (cssVars["--duration-fast"]) {
1481
- mapped["--duration-fast"] = cssVars["--duration-fast"];
1482
- }
1483
- if (cssVars["--duration-normal"]) {
1484
- mapped["--duration-normal"] = cssVars["--duration-normal"];
1485
- }
1486
- if (cssVars["--duration-slow"]) {
1487
- mapped["--duration-slow"] = cssVars["--duration-slow"];
1488
- }
1489
1500
  return mapped;
1490
1501
  }
1491
1502
 
1492
- export { Badge, Button, Modal, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ThemeToggle, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, applyThemeSync, badgeVariants, buttonVariants, getTheme, getThemeCategories, getThemeFilePath, getThemesForCategory, registerTheme, useTheme, useThemeToggle };
1503
+ export { Badge, Button, Modal, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ThemeToggle, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, applyThemeSync, badgeVariants, buttonVariants, enableDebugMode, getCurrentCSSVariables, getTheme, getThemeCategories, getThemeFilePath, getThemesForCategory, registerTheme, useTheme, useThemeToggle };
1493
1504
  //# sourceMappingURL=index.mjs.map
1494
1505
  //# sourceMappingURL=index.mjs.map