@hewnui/themes 0.0.0-stage → 0.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.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +33 -2
  3. package/dist/authoring/css-vars.d.ts +10 -0
  4. package/dist/authoring/css-vars.js +83 -0
  5. package/dist/authoring/derive.d.ts +9 -0
  6. package/dist/authoring/derive.js +79 -0
  7. package/dist/authoring/export-css.d.ts +8 -0
  8. package/dist/authoring/export-css.js +60 -0
  9. package/dist/authoring/export-design-md.d.ts +5 -0
  10. package/dist/authoring/export-design-md.js +113 -0
  11. package/dist/authoring/export-dtcg.d.ts +6 -0
  12. package/dist/authoring/export-dtcg.js +85 -0
  13. package/dist/authoring/export-figma.d.ts +27 -0
  14. package/dist/authoring/export-figma.js +76 -0
  15. package/dist/authoring/export-formats.d.ts +27 -0
  16. package/dist/authoring/export-formats.js +62 -0
  17. package/dist/authoring/export-skill.d.ts +5 -0
  18. package/dist/authoring/export-skill.js +75 -0
  19. package/dist/authoring/export-sticker.d.ts +6 -0
  20. package/dist/authoring/export-sticker.js +54 -0
  21. package/dist/authoring/export-style-dictionary.d.ts +3 -0
  22. package/dist/authoring/export-style-dictionary.js +52 -0
  23. package/dist/authoring/figma-kit.d.ts +16 -0
  24. package/dist/authoring/figma-kit.js +41 -0
  25. package/dist/authoring/index.d.ts +21 -0
  26. package/dist/authoring/index.js +18 -0
  27. package/dist/authoring/oklch.d.ts +11 -0
  28. package/dist/authoring/oklch.js +116 -0
  29. package/dist/authoring/override-map.d.ts +9 -0
  30. package/dist/authoring/override-map.js +150 -0
  31. package/dist/authoring/pack-def.d.ts +7 -0
  32. package/dist/authoring/pack-def.js +3 -0
  33. package/dist/authoring/pack-meta.d.ts +10 -0
  34. package/dist/authoring/pack-meta.js +58 -0
  35. package/dist/authoring/packs-dual.d.ts +129 -0
  36. package/dist/authoring/packs-dual.js +130 -0
  37. package/dist/authoring/packs-single.d.ts +87 -0
  38. package/dist/authoring/packs-single.js +88 -0
  39. package/dist/authoring/packs.d.ts +8 -0
  40. package/dist/authoring/packs.js +26 -0
  41. package/dist/authoring/pro-apply.d.ts +8 -0
  42. package/dist/authoring/pro-apply.js +107 -0
  43. package/dist/authoring/propose.d.ts +21 -0
  44. package/dist/authoring/propose.js +162 -0
  45. package/dist/authoring/ramps.d.ts +13 -0
  46. package/dist/authoring/ramps.js +40 -0
  47. package/dist/authoring/status-ramps.d.ts +13 -0
  48. package/dist/authoring/status-ramps.js +76 -0
  49. package/dist/authoring/token-entries.d.ts +10 -0
  50. package/dist/authoring/token-entries.js +52 -0
  51. package/dist/authoring/types.d.ts +110 -0
  52. package/dist/authoring/types.js +11 -0
  53. package/exports/clay/DESIGN.md +138 -0
  54. package/exports/clay/SKILL.md +94 -0
  55. package/exports/clay/theme.css +37 -0
  56. package/exports/clay/tokens.dtcg.json +200 -0
  57. package/exports/dune/DESIGN.md +138 -0
  58. package/exports/dune/SKILL.md +94 -0
  59. package/exports/dune/theme.css +37 -0
  60. package/exports/dune/tokens.dtcg.json +200 -0
  61. package/exports/ember/DESIGN.md +138 -0
  62. package/exports/ember/SKILL.md +94 -0
  63. package/exports/ember/theme.css +37 -0
  64. package/exports/ember/tokens.dtcg.json +200 -0
  65. package/exports/forest/DESIGN.md +138 -0
  66. package/exports/forest/SKILL.md +94 -0
  67. package/exports/forest/theme.css +67 -0
  68. package/exports/forest/tokens.dtcg.json +348 -0
  69. package/exports/graphite/DESIGN.md +138 -0
  70. package/exports/graphite/SKILL.md +94 -0
  71. package/exports/graphite/theme.css +67 -0
  72. package/exports/graphite/tokens.dtcg.json +348 -0
  73. package/exports/index.json +45 -0
  74. package/exports/tide/DESIGN.md +138 -0
  75. package/exports/tide/SKILL.md +94 -0
  76. package/exports/tide/theme.css +67 -0
  77. package/exports/tide/tokens.dtcg.json +348 -0
  78. package/figma/README.md +16 -0
  79. package/figma/hewn.tokens.json +1308 -0
  80. package/figma/sticker-sheet.svg +93 -0
  81. package/package.json +98 -4
  82. package/src/authoring/css-vars.ts +92 -0
  83. package/src/authoring/derive.ts +106 -0
  84. package/src/authoring/export-css.ts +86 -0
  85. package/src/authoring/export-design-md.ts +134 -0
  86. package/src/authoring/export-dtcg.ts +116 -0
  87. package/src/authoring/export-figma.ts +109 -0
  88. package/src/authoring/export-formats.ts +101 -0
  89. package/src/authoring/export-skill.ts +93 -0
  90. package/src/authoring/export-sticker.ts +60 -0
  91. package/src/authoring/export-style-dictionary.ts +67 -0
  92. package/src/authoring/figma-kit.ts +60 -0
  93. package/src/authoring/index.ts +61 -0
  94. package/src/authoring/oklch.ts +137 -0
  95. package/src/authoring/override-map.ts +191 -0
  96. package/src/authoring/pack-def.ts +11 -0
  97. package/src/authoring/pack-meta.ts +66 -0
  98. package/src/authoring/packs-dual.ts +131 -0
  99. package/src/authoring/packs-single.ts +89 -0
  100. package/src/authoring/packs.ts +43 -0
  101. package/src/authoring/pro-apply.ts +156 -0
  102. package/src/authoring/propose.ts +181 -0
  103. package/src/authoring/ramps.ts +62 -0
  104. package/src/authoring/status-ramps.ts +98 -0
  105. package/src/authoring/token-entries.ts +59 -0
  106. package/src/authoring/types.ts +133 -0
  107. package/src/glass-buttons.css +46 -0
  108. package/src/glass.css +266 -0
  109. package/src/motion.css +60 -0
  110. package/src/packs/clay.css +45 -0
  111. package/src/packs/dune.css +45 -0
  112. package/src/packs/ember.css +45 -0
  113. package/src/packs/forest.css +80 -0
  114. package/src/packs/graphite.css +79 -0
  115. package/src/packs/tide.css +79 -0
  116. package/src/radius.css +25 -0
  117. package/src/tokens.css +104 -0
@@ -0,0 +1,93 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="616" height="664" viewBox="0 0 616 664" role="img" aria-label="Hewn sticker sheet">
3
+ <rect width="100%" height="100%" fill="#f4f4f2"/>
4
+ <text x="24" y="40" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="16" font-weight="600" fill="#1a1a18">Hewn · sticker sheet</text>
5
+ <text x="112" y="58" font-family="IBM Plex Mono, ui-monospace, monospace" font-size="10" fill="#6b6b66">surface</text>
6
+ <text x="232" y="58" font-family="IBM Plex Mono, ui-monospace, monospace" font-size="10" fill="#6b6b66">raised</text>
7
+ <text x="352" y="58" font-family="IBM Plex Mono, ui-monospace, monospace" font-size="10" fill="#6b6b66">button</text>
8
+ <text x="472" y="58" font-family="IBM Plex Mono, ui-monospace, monospace" font-size="10" fill="#6b6b66">input</text>
9
+ <g>
10
+ <text x="24" y="106" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">forest</text>
11
+ <rect x="112" y="64" width="100" height="72" rx="10" fill="oklch(0.972 0.012 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
12
+ <rect x="124" y="78" width="76" height="44" rx="8" fill="oklch(0.995 0.004 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
13
+ <rect x="232" y="64" width="100" height="72" rx="10" fill="oklch(0.972 0.012 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
14
+ <rect x="244" y="78" width="76" height="44" rx="8" fill="oklch(1 0 0)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
15
+ <rect x="352" y="64" width="100" height="72" rx="10" fill="oklch(0.972 0.012 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
16
+ <rect x="366" y="86" width="72" height="28" rx="8" fill="oklch(0.49 0.105 148)"/>
17
+ <text x="402" y="104" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.985 0.008 145)">Button</text>
18
+ <rect x="472" y="64" width="100" height="72" rx="10" fill="oklch(0.972 0.012 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
19
+ <rect x="482" y="86" width="80" height="28" rx="8" fill="oklch(0.995 0.004 145)" stroke="oklch(0.36 0.035 145 / 14%)" stroke-width="1"/>
20
+ <text x="490" y="104" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.49 0.035 145)">Input</text>
21
+ <text x="542" y="104" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.225 0.028 145)" opacity="0.35">|</text>
22
+ </g>
23
+ <g>
24
+ <text x="24" y="202" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">tide</text>
25
+ <rect x="112" y="160" width="100" height="72" rx="10" fill="oklch(0.97 0.01 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
26
+ <rect x="124" y="174" width="76" height="44" rx="8" fill="oklch(0.995 0.004 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
27
+ <rect x="232" y="160" width="100" height="72" rx="10" fill="oklch(0.97 0.01 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
28
+ <rect x="244" y="174" width="76" height="44" rx="8" fill="oklch(1 0 0)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
29
+ <rect x="352" y="160" width="100" height="72" rx="10" fill="oklch(0.97 0.01 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
30
+ <rect x="366" y="182" width="72" height="28" rx="8" fill="oklch(0.52 0.07 210)"/>
31
+ <text x="402" y="200" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.98 0.01 210)">Button</text>
32
+ <rect x="472" y="160" width="100" height="72" rx="10" fill="oklch(0.97 0.01 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
33
+ <rect x="482" y="182" width="80" height="28" rx="8" fill="oklch(0.995 0.004 220)" stroke="oklch(0.35 0.03 230 / 14%)" stroke-width="1"/>
34
+ <text x="490" y="200" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.48 0.03 230)">Input</text>
35
+ <text x="542" y="200" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.24 0.03 230)" opacity="0.35">|</text>
36
+ </g>
37
+ <g>
38
+ <text x="24" y="298" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">graphite</text>
39
+ <rect x="112" y="256" width="100" height="72" rx="10" fill="oklch(0.965 0.005 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
40
+ <rect x="124" y="270" width="76" height="44" rx="8" fill="oklch(0.99 0.003 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
41
+ <rect x="232" y="256" width="100" height="72" rx="10" fill="oklch(0.965 0.005 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
42
+ <rect x="244" y="270" width="76" height="44" rx="8" fill="oklch(1 0 0)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
43
+ <rect x="352" y="256" width="100" height="72" rx="10" fill="oklch(0.965 0.005 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
44
+ <rect x="366" y="278" width="72" height="28" rx="8" fill="oklch(0.48 0.06 250)"/>
45
+ <text x="402" y="296" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.98 0.01 250)">Button</text>
46
+ <rect x="472" y="256" width="100" height="72" rx="10" fill="oklch(0.965 0.005 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
47
+ <rect x="482" y="278" width="80" height="28" rx="8" fill="oklch(0.99 0.003 255)" stroke="oklch(0.34 0.02 255 / 14%)" stroke-width="1"/>
48
+ <text x="490" y="296" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.47 0.02 255)">Input</text>
49
+ <text x="542" y="296" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.23 0.02 255)" opacity="0.35">|</text>
50
+ </g>
51
+ <g>
52
+ <text x="24" y="394" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">dune</text>
53
+ <rect x="112" y="352" width="100" height="72" rx="10" fill="oklch(0.96 0.02 85)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
54
+ <rect x="124" y="366" width="76" height="44" rx="8" fill="oklch(0.985 0.012 90)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
55
+ <rect x="232" y="352" width="100" height="72" rx="10" fill="oklch(0.96 0.02 85)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
56
+ <rect x="244" y="366" width="76" height="44" rx="8" fill="oklch(0.995 0.006 95)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
57
+ <rect x="352" y="352" width="100" height="72" rx="10" fill="oklch(0.96 0.02 85)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
58
+ <rect x="366" y="374" width="72" height="28" rx="8" fill="oklch(0.58 0.11 70)"/>
59
+ <text x="402" y="392" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.98 0.01 90)">Button</text>
60
+ <rect x="472" y="352" width="100" height="72" rx="10" fill="oklch(0.96 0.02 85)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
61
+ <rect x="482" y="374" width="80" height="28" rx="8" fill="oklch(0.985 0.012 90)" stroke="oklch(0.4 0.04 70 / 16%)" stroke-width="1"/>
62
+ <text x="490" y="392" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.5 0.04 70)">Input</text>
63
+ <text x="542" y="392" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.28 0.04 65)" opacity="0.35">|</text>
64
+ </g>
65
+ <g>
66
+ <text x="24" y="490" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">clay</text>
67
+ <rect x="112" y="448" width="100" height="72" rx="10" fill="oklch(0.955 0.02 55)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
68
+ <rect x="124" y="462" width="76" height="44" rx="8" fill="oklch(0.98 0.012 50)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
69
+ <rect x="232" y="448" width="100" height="72" rx="10" fill="oklch(0.955 0.02 55)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
70
+ <rect x="244" y="462" width="76" height="44" rx="8" fill="oklch(0.995 0.006 45)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
71
+ <rect x="352" y="448" width="100" height="72" rx="10" fill="oklch(0.955 0.02 55)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
72
+ <rect x="366" y="470" width="72" height="28" rx="8" fill="oklch(0.55 0.12 40)"/>
73
+ <text x="402" y="488" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.98 0.01 50)">Button</text>
74
+ <rect x="472" y="448" width="100" height="72" rx="10" fill="oklch(0.955 0.02 55)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
75
+ <rect x="482" y="470" width="80" height="28" rx="8" fill="oklch(0.98 0.012 50)" stroke="oklch(0.4 0.05 40 / 16%)" stroke-width="1"/>
76
+ <text x="490" y="488" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.5 0.045 40)">Input</text>
77
+ <text x="542" y="488" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.27 0.045 40)" opacity="0.35">|</text>
78
+ </g>
79
+ <g>
80
+ <text x="24" y="586" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="13" fill="#1a1a18">ember</text>
81
+ <rect x="112" y="544" width="100" height="72" rx="10" fill="oklch(0.17 0.02 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
82
+ <rect x="124" y="558" width="76" height="44" rx="8" fill="oklch(0.21 0.025 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
83
+ <rect x="232" y="544" width="100" height="72" rx="10" fill="oklch(0.17 0.02 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
84
+ <rect x="244" y="558" width="76" height="44" rx="8" fill="oklch(0.255 0.03 42)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
85
+ <rect x="352" y="544" width="100" height="72" rx="10" fill="oklch(0.17 0.02 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
86
+ <rect x="366" y="566" width="72" height="28" rx="8" fill="oklch(0.7 0.15 50)"/>
87
+ <text x="402" y="584" text-anchor="middle" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.985 0.015 50)">Button</text>
88
+ <rect x="472" y="544" width="100" height="72" rx="10" fill="oklch(0.17 0.02 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
89
+ <rect x="482" y="566" width="80" height="28" rx="8" fill="oklch(0.21 0.025 40)" stroke="oklch(0.84 0.03 60 / 14%)" stroke-width="1"/>
90
+ <text x="490" y="584" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="11" fill="oklch(0.72 0.03 60)">Input</text>
91
+ <text x="542" y="584" font-family="IBM Plex Sans, ui-sans-serif, system-ui, sans-serif" font-size="9" fill="oklch(0.93 0.02 70)" opacity="0.35">|</text>
92
+ </g>
93
+ </svg>
package/package.json CHANGED
@@ -1,6 +1,100 @@
1
1
  {
2
2
  "name": "@hewnui/themes",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/hewnui/Hewn.git",
8
+ "directory": "packages/themes"
9
+ },
10
+ "type": "module",
11
+ "sideEffects": [
12
+ "**/*.css"
13
+ ],
14
+ "publishConfig": {
15
+ "access": "public",
16
+ "exports": {
17
+ "./tokens.css": "./src/tokens.css",
18
+ "./motion.css": "./src/motion.css",
19
+ "./glass.css": "./src/glass.css",
20
+ "./glass-buttons.css": "./src/glass-buttons.css",
21
+ "./radius.css": "./src/radius.css",
22
+ "./packs/clay.css": "./src/packs/clay.css",
23
+ "./packs/dune.css": "./src/packs/dune.css",
24
+ "./packs/ember.css": "./src/packs/ember.css",
25
+ "./packs/forest.css": "./src/packs/forest.css",
26
+ "./packs/graphite.css": "./src/packs/graphite.css",
27
+ "./packs/tide.css": "./src/packs/tide.css",
28
+ "./authoring": {
29
+ "types": "./dist/authoring/index.d.ts",
30
+ "default": "./dist/authoring/index.js"
31
+ },
32
+ "./figma/hewn.tokens.json": "./figma/hewn.tokens.json",
33
+ "./figma/sticker-sheet.svg": "./figma/sticker-sheet.svg",
34
+ "./package.json": "./package.json"
35
+ }
36
+ },
37
+ "scripts": {
38
+ "build": "tsc -p tsconfig.build.json && tsx ../../tooling/fix-esm-relative-extensions.ts dist/authoring",
39
+ "generate": "tsx ../../tooling/build-figma-kit.ts && tsx ../../tooling/build-theme-exports.ts",
40
+ "typecheck": "tsc --noEmit",
41
+ "test": "vitest run"
42
+ },
43
+ "files": [
44
+ "README.md",
45
+ "LICENSE",
46
+ "dist",
47
+ "src",
48
+ "figma",
49
+ "exports",
50
+ "!src/**/*.test.ts",
51
+ "!src/**/*.test.tsx",
52
+ "!**/__tests__/**"
53
+ ],
54
+ "exports": {
55
+ "./tokens.css": "./src/tokens.css",
56
+ "./motion.css": "./src/motion.css",
57
+ "./glass.css": "./src/glass.css",
58
+ "./glass-buttons.css": "./src/glass-buttons.css",
59
+ "./radius.css": "./src/radius.css",
60
+ "./packs/clay.css": "./src/packs/clay.css",
61
+ "./packs/dune.css": "./src/packs/dune.css",
62
+ "./packs/ember.css": "./src/packs/ember.css",
63
+ "./packs/forest.css": "./src/packs/forest.css",
64
+ "./packs/graphite.css": "./src/packs/graphite.css",
65
+ "./packs/tide.css": "./src/packs/tide.css",
66
+ "./authoring": {
67
+ "types": "./src/authoring/index.ts",
68
+ "default": "./src/authoring/index.ts"
69
+ },
70
+ "./figma/hewn.tokens.json": "./figma/hewn.tokens.json",
71
+ "./figma/sticker-sheet.svg": "./figma/sticker-sheet.svg",
72
+ "./package.json": "./package.json"
73
+ },
74
+ "devDependencies": {
75
+ "@hewnui/tsconfig": "workspace:*",
76
+ "typescript": "6.0.3",
77
+ "vitest": "4.1.10"
78
+ },
79
+ "homepage": "https://hewnui.dev",
80
+ "bugs": {
81
+ "url": "https://github.com/hewnui/Hewn/issues"
82
+ },
83
+ "author": "Himanshu Kumar",
84
+ "description": "Semantic OKLCH design tokens, motion tokens and six curated theme packs (forest, tide, graphite, dune, clay, ember), with DESIGN.md, DTCG and Tailwind v4 exports.",
85
+ "keywords": [
86
+ "design-tokens",
87
+ "oklch",
88
+ "css-variables",
89
+ "themes",
90
+ "tailwindcss",
91
+ "tailwind-v4",
92
+ "dtcg",
93
+ "design-md",
94
+ "dark-mode",
95
+ "glassmorphism",
96
+ "wcag",
97
+ "figma-tokens",
98
+ "hewnui"
99
+ ]
100
+ }
@@ -0,0 +1,92 @@
1
+ import { formatOklch } from "./oklch";
2
+ import { colorEntries, structuralEntries } from "./token-entries";
3
+ import type { ResolvedMode } from "./types";
4
+
5
+ const COLOR_BRIDGE = [
6
+ "background",
7
+ "foreground",
8
+ "surface",
9
+ "surface-raised",
10
+ "muted",
11
+ "muted-foreground",
12
+ "accent",
13
+ "accent-foreground",
14
+ "border",
15
+ "ring",
16
+ "danger",
17
+ "danger-foreground",
18
+ "danger-subtle",
19
+ "danger-border",
20
+ "success",
21
+ "success-foreground",
22
+ "success-subtle",
23
+ "success-border",
24
+ "warning",
25
+ "warning-foreground",
26
+ "warning-subtle",
27
+ "warning-border",
28
+ "info",
29
+ "info-foreground",
30
+ "info-subtle",
31
+ "info-border",
32
+ ] as const;
33
+
34
+ /**
35
+ * Map a resolved mode to CSS custom properties for scoped live preview.
36
+ * Includes Tailwind `--color-*` rebinds so utilities do not keep :root-resolved
37
+ * docs-shell values, plus local glass vars so html[data-material=glass] rules
38
+ * sample the draft pack instead of the documentation theme.
39
+ */
40
+ export function modeToCssVars(mode: ResolvedMode): Record<string, string> {
41
+ const vars: Record<string, string> = {};
42
+ for (const entry of colorEntries(mode)) {
43
+ vars[`--kp-${entry.name}`] = entry.value;
44
+ }
45
+ for (const entry of structuralEntries(mode)) {
46
+ vars[`--kp-${entry.name}`] = entry.value;
47
+ }
48
+ vars["--kp-font-sans"] =
49
+ 'var(--font-plex-sans, "IBM Plex Sans"), ui-sans-serif, system-ui, sans-serif';
50
+ vars["--kp-font-mono"] =
51
+ 'var(--font-plex-mono, "IBM Plex Mono"), ui-monospace, monospace';
52
+ vars["--kp-font-display"] =
53
+ 'var(--font-space-grotesk, "Space Grotesk"), var(--kp-font-sans)';
54
+ vars["--kp-shadow-surface"] =
55
+ `0 1px 2px color-mix(in oklch, ${formatOklch(mode.foreground)} 8%, transparent), ` +
56
+ `0 16px 40px -28px color-mix(in oklch, ${formatOklch(mode.foreground)} 28%, transparent)`;
57
+
58
+ // Recompute glass locally so inherited html glass fills cannot leak docs tint.
59
+ vars["--kp-glass-fill"] =
60
+ "color-mix(in oklch, var(--kp-surface) 46%, transparent)";
61
+ vars["--kp-glass-border"] =
62
+ "color-mix(in oklch, var(--kp-foreground) 16%, transparent)";
63
+ vars["--kp-glass-sheen"] =
64
+ "linear-gradient(148deg, color-mix(in oklch, var(--kp-glass-tint) 70%, white 8%), " +
65
+ "color-mix(in oklch, var(--kp-surface) 22%, transparent) 42%, " +
66
+ "color-mix(in oklch, var(--kp-surface) 38%, transparent))";
67
+
68
+ for (const name of COLOR_BRIDGE) {
69
+ vars[`--color-${name}`] = `var(--kp-${name})`;
70
+ }
71
+ // Fumadocs tokens occasionally paint nested chrome; keep them on the draft.
72
+ vars["--color-fd-background"] = "var(--kp-background)";
73
+ vars["--color-fd-foreground"] = "var(--kp-foreground)";
74
+ vars["--color-fd-card"] = "var(--kp-surface)";
75
+ vars["--color-fd-card-foreground"] = "var(--kp-foreground)";
76
+ vars["--color-fd-muted"] = "var(--kp-muted)";
77
+ vars["--color-fd-muted-foreground"] = "var(--kp-muted-foreground)";
78
+ vars["--color-fd-primary"] = "var(--kp-accent)";
79
+ vars["--color-fd-primary-foreground"] = "var(--kp-accent-foreground)";
80
+ vars["--color-fd-border"] = "var(--kp-border)";
81
+ vars["--color-fd-ring"] = "var(--kp-ring)";
82
+
83
+ return vars;
84
+ }
85
+
86
+ /** Stylesheet block for a live-preview selector (no :root). */
87
+ export function modeToPreviewCss(selector: string, mode: ResolvedMode): string {
88
+ const lines = Object.entries(modeToCssVars(mode)).map(
89
+ ([name, value]) => ` ${name}: ${value};`,
90
+ );
91
+ return `${selector} {\n${lines.join("\n")}\n}\n`;
92
+ }
@@ -0,0 +1,106 @@
1
+ import { applyGlass, applyMotion, applyNeutrals, applySemantic, applyShape } from "./pro-apply";
2
+ import { BASE_PACKS, supportedModes } from "./packs";
3
+ import { accentSetFromSeed } from "./ramps";
4
+ import type {
5
+ OverrideMap,
6
+ RadiusPreset,
7
+ ResolvedMode,
8
+ ResolvedPack,
9
+ StructuralTokens,
10
+ ThemeMode,
11
+ } from "./types";
12
+
13
+ const RADIUS_PRESETS: Record<
14
+ Exclude<RadiusPreset, "soft">,
15
+ Pick<
16
+ StructuralTokens,
17
+ "radiusSm" | "radiusMd" | "radiusLg" | "radiusPanel"
18
+ >
19
+ > = {
20
+ sharp: {
21
+ radiusSm: "0.125rem",
22
+ radiusMd: "0.2rem",
23
+ radiusLg: "0.3rem",
24
+ radiusPanel: "0.25rem",
25
+ },
26
+ rounded: {
27
+ radiusSm: "0.85rem",
28
+ radiusMd: "1.15rem",
29
+ radiusLg: "1.5rem",
30
+ radiusPanel: "1.25rem",
31
+ },
32
+ pill: {
33
+ radiusSm: "9999px",
34
+ radiusMd: "9999px",
35
+ radiusLg: "1.5rem",
36
+ radiusPanel: "1.15rem",
37
+ },
38
+ };
39
+
40
+ export type DeriveResult =
41
+ | { ok: true; pack: ResolvedPack }
42
+ | { ok: false; errors: string[] };
43
+
44
+ export function derivePack(overrides: OverrideMap): DeriveResult {
45
+ const base = BASE_PACKS[overrides.basePackId];
46
+ const modes = supportedModes(overrides.basePackId);
47
+ const adjustments: string[] = [];
48
+ const resolved: Partial<Record<ThemeMode, ResolvedMode>> = {};
49
+
50
+ let structural: StructuralTokens = { ...base.structural };
51
+ if (overrides.radiusPreset && overrides.radiusPreset !== "soft") {
52
+ structural = { ...structural, ...RADIUS_PRESETS[overrides.radiusPreset] };
53
+ }
54
+ structural = applyShape(structural, overrides.shape);
55
+ structural = applyMotion(structural, overrides.motion);
56
+
57
+ for (const mode of modes) {
58
+ const colors = base.modes[mode];
59
+ if (!colors) continue;
60
+
61
+ let next = { ...colors };
62
+ if (overrides.accentSeed) {
63
+ const accent = accentSetFromSeed(overrides.accentSeed, mode);
64
+ if ("error" in accent) {
65
+ return { ok: false, errors: [accent.error] };
66
+ }
67
+ next = {
68
+ ...next,
69
+ accent: accent.set.accent,
70
+ accentForeground: accent.set.accentForeground,
71
+ ring: accent.set.ring,
72
+ glassTint: accent.set.glassTint,
73
+ };
74
+ adjustments.push(...accent.adjustments);
75
+ }
76
+
77
+ next = applyNeutrals(next, overrides.neutrals, mode, adjustments);
78
+ const semantic = applySemantic(next, overrides.semantic, mode, adjustments);
79
+ if ("error" in semantic) {
80
+ return { ok: false, errors: [semantic.error] };
81
+ }
82
+ next = applyGlass(semantic, overrides.glass);
83
+
84
+ resolved[mode] = {
85
+ ...next,
86
+ ...structural,
87
+ mode,
88
+ colorScheme: mode,
89
+ };
90
+ }
91
+
92
+ const packId =
93
+ overrides.packId ??
94
+ `custom-${overrides.basePackId}${overrides.accentSeed ? "-accent" : ""}`;
95
+
96
+ return {
97
+ ok: true,
98
+ pack: {
99
+ id: packId,
100
+ basePackId: overrides.basePackId,
101
+ supportedModes: modes,
102
+ modes: resolved,
103
+ adjustments: [...new Set(adjustments)],
104
+ },
105
+ };
106
+ }
@@ -0,0 +1,86 @@
1
+ import {
2
+ colorEntries,
3
+ modeOrder,
4
+ primaryMode,
5
+ structuralEntries,
6
+ } from "./token-entries";
7
+ import type { ResolvedMode, ResolvedPack } from "./types";
8
+
9
+ function colorLines(mode: ResolvedMode): string {
10
+ return [
11
+ ` color-scheme: ${mode.colorScheme};`,
12
+ ...colorEntries(mode).map(
13
+ (entry) => ` --kp-${entry.name}: ${entry.value};`,
14
+ ),
15
+ ].join("\n");
16
+ }
17
+
18
+ function structuralLines(mode: ResolvedMode): string {
19
+ return [
20
+ ...structuralEntries(mode).map(
21
+ (entry) => ` --kp-${entry.name}: ${entry.value};`,
22
+ ),
23
+ ` --kp-font-sans: var(--font-plex-sans, "IBM Plex Sans"), ui-sans-serif, system-ui,`,
24
+ ` sans-serif;`,
25
+ ` --kp-font-mono: var(--font-plex-mono, "IBM Plex Mono"), ui-monospace, monospace;`,
26
+ ` --kp-font-display: var(--font-space-grotesk, "Space Grotesk"), var(--kp-font-sans);`,
27
+ ].join("\n");
28
+ }
29
+
30
+ /** Free-tier CSS pack export — drop-in `[data-theme]` file. */
31
+ export function exportPackCss(pack: ResolvedPack): string {
32
+ const blocks: string[] = [];
33
+ let first = true;
34
+
35
+ for (const modeName of modeOrder(pack)) {
36
+ const mode = pack.modes[modeName];
37
+ if (!mode) continue;
38
+
39
+ const selector = first
40
+ ? `:root,\n[data-theme="${pack.id}"][data-mode="${mode.mode}"]`
41
+ : `[data-theme="${pack.id}"][data-mode="${mode.mode}"]`;
42
+
43
+ const body = first
44
+ ? `${colorLines(mode)}\n${structuralLines(mode)}`
45
+ : colorLines(mode);
46
+
47
+ blocks.push(`${selector} {\n${body}\n}`);
48
+ first = false;
49
+ }
50
+
51
+ return `${blocks.join("\n\n")}\n`;
52
+ }
53
+
54
+ /**
55
+ * Free — Tailwind v4 `@theme` block for the primary mode, plus mode overrides
56
+ * that remap the same `--color-*` custom properties.
57
+ */
58
+ export function exportTailwindTheme(pack: ResolvedPack): string {
59
+ const primary = primaryMode(pack);
60
+ const themeLines = [
61
+ ...colorEntries(primary).map(
62
+ (entry) => ` --color-${entry.name}: ${entry.value};`,
63
+ ),
64
+ ...structuralEntries(primary)
65
+ .filter((entry) => entry.name.startsWith("radius-"))
66
+ .map((entry) => ` --${entry.name}: ${entry.value};`),
67
+ ` --font-sans: var(--font-plex-sans, "IBM Plex Sans"), ui-sans-serif, system-ui, sans-serif;`,
68
+ ` --font-mono: var(--font-plex-mono, "IBM Plex Mono"), ui-monospace, monospace;`,
69
+ ` --font-display: var(--font-space-grotesk, "Space Grotesk"), var(--font-sans);`,
70
+ ];
71
+
72
+ const blocks = [`@theme {\n${themeLines.join("\n")}\n}`];
73
+
74
+ for (const modeName of modeOrder(pack).slice(1)) {
75
+ const mode = pack.modes[modeName];
76
+ if (!mode) continue;
77
+ const lines = colorEntries(mode).map(
78
+ (entry) => ` --color-${entry.name}: ${entry.value};`,
79
+ );
80
+ blocks.push(
81
+ `[data-theme="${pack.id}"][data-mode="${mode.mode}"] {\n${lines.join("\n")}\n}`,
82
+ );
83
+ }
84
+
85
+ return `/* ${pack.id} — Tailwind v4 @theme */\n${blocks.join("\n\n")}\n`;
86
+ }
@@ -0,0 +1,134 @@
1
+ import {
2
+ COLOR_ROLES,
3
+ DESIGN_DO,
4
+ DESIGN_DONT,
5
+ PACK_IDENTITY,
6
+ } from "./pack-meta";
7
+ import { formatOklch } from "./oklch";
8
+ import {
9
+ colorEntries,
10
+ modeOrder,
11
+ primaryMode,
12
+ structuralEntries,
13
+ } from "./token-entries";
14
+ import type { BasePackId, ResolvedPack } from "./types";
15
+
16
+ function identity(pack: ResolvedPack) {
17
+ const meta = PACK_IDENTITY[pack.basePackId as BasePackId];
18
+ return meta ?? { label: pack.id, summary: `Custom pack based on ${pack.basePackId}.` };
19
+ }
20
+
21
+ function paletteTable(pack: ResolvedPack): string {
22
+ const modes = modeOrder(pack);
23
+ const header =
24
+ modes.length > 1
25
+ ? `| Token | Role | ${modes.map((m) => m).join(" | ")} |`
26
+ : `| Token | Role | ${modes[0]} |`;
27
+ const sep =
28
+ modes.length > 1
29
+ ? `|---|---|${modes.map(() => "---").join("|")}|`
30
+ : `|---|---|---|`;
31
+
32
+ const primary = primaryMode(pack);
33
+ const rows = colorEntries(primary).map((entry) => {
34
+ const role = COLOR_ROLES[entry.name] ?? entry.name;
35
+ const values = modes.map((modeName) => {
36
+ const mode = pack.modes[modeName];
37
+ if (!mode) return "—";
38
+ const match = colorEntries(mode).find((e) => e.name === entry.name);
39
+ return match ? `\`${match.value}\`` : "—";
40
+ });
41
+ return `| \`${entry.name}\` | ${role} | ${values.join(" | ")} |`;
42
+ });
43
+
44
+ return [header, sep, ...rows].join("\n");
45
+ }
46
+
47
+ function structuralBlock(pack: ResolvedPack): string {
48
+ const mode = primaryMode(pack);
49
+ return structuralEntries(mode)
50
+ .map((entry) => `- \`${entry.name}\`: \`${entry.value}\``)
51
+ .join("\n");
52
+ }
53
+
54
+ function list(items: readonly string[]): string {
55
+ return items.map((item) => `- ${item}`).join("\n");
56
+ }
57
+
58
+ /** Free — human- and AI-readable design brief for one pack. */
59
+ export function exportDesignMd(pack: ResolvedPack): string {
60
+ const { label, summary } = identity(pack);
61
+ const modes = modeOrder(pack).join(", ");
62
+ const mode = primaryMode(pack);
63
+
64
+ return `# ${label} — Design brief
65
+
66
+ > Generated from Hewn curated theme packs. Semantic OKLCH tokens; do not edit by hand.
67
+
68
+ ## Identity
69
+
70
+ ${summary}
71
+
72
+ - **Pack id:** \`${pack.id}\`
73
+ - **Base pack:** \`${pack.basePackId}\`
74
+ - **Supported modes:** ${modes}
75
+ - **Color scheme (primary):** ${mode.colorScheme}
76
+
77
+ ## Palette
78
+
79
+ ${paletteTable(pack)}
80
+
81
+ ## Typography
82
+
83
+ | Role | Stack | Usage |
84
+ |---|---|---|
85
+ | Sans | IBM Plex Sans, ui-sans-serif, system-ui | UI chrome, body, headings |
86
+ | Mono | IBM Plex Mono, ui-monospace | Labels, code, tabular metrics |
87
+ | Display | Space Grotesk → sans | Marketing hero H1 and brand wordmark ≥18px only |
88
+
89
+ Body text uses pretty wrapping; headings use balanced wrapping; dynamic numbers use \`tabular-nums\`.
90
+
91
+ ## Radius & density
92
+
93
+ ${structuralBlock(pack)}
94
+
95
+ Density scales control spacing rhythm. Panel radius (\`radius-panel\`) caps menus and dialogs so they never go full-pill.
96
+
97
+ ## Motion
98
+
99
+ - Duration: \`${mode.motionDuration}\`
100
+ - Spring stiffness: \`${mode.motionStiffness}\`
101
+ - Spring damping: \`${mode.motionDamping}\`
102
+ - Reduced motion always wins over global motion toggles.
103
+ - Prefer transform / opacity / filter; never animate layout properties continuously.
104
+
105
+ ## Material
106
+
107
+ - \`solid\` — structured product surfaces and separators
108
+ - \`glass\` — accent-tinted frosted surfaces (blur, saturation, refraction, opaque fallback)
109
+
110
+ ## Do
111
+
112
+ ${list(DESIGN_DO)}
113
+
114
+ ## Don't
115
+
116
+ ${list(DESIGN_DONT)}
117
+
118
+ ## Token reference (primary mode)
119
+
120
+ \`\`\`
121
+ ${colorEntries(mode)
122
+ .map((e) => `--kp-${e.name}: ${e.value};`)
123
+ .join("\n")}
124
+ ${structuralEntries(mode)
125
+ .map((e) => `--kp-${e.name}: ${e.value};`)
126
+ .join("\n")}
127
+ \`\`\`
128
+ `;
129
+ }
130
+
131
+ /** Convenience — expose formatted OKLCH for tests/docs samples. */
132
+ export function sampleAccent(pack: ResolvedPack): string {
133
+ return formatOklch(primaryMode(pack).accent);
134
+ }