@vettvangur/design-system 2.0.61 → 2.0.63

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 (2) hide show
  1. package/dist/index.js +87 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1725,6 +1725,10 @@ function groupColors(variableSet, collectionKey = 'colour') {
1725
1725
  * @generated
1726
1726
  * @module design-system
1727
1727
  */
1728
+ function isFontFamilyKey(key) {
1729
+ // NOTE: accept historical typo "familiy" as well.
1730
+ return key.startsWith('font-family-') || key.startsWith('font-familiy-');
1731
+ }
1728
1732
 
1729
1733
  /**
1730
1734
  * Entries.
@@ -1764,7 +1768,7 @@ function groupTypography(variableSet) {
1764
1768
  console.log('[design-system] typography: token count =', keys.length);
1765
1769
  if (keys.length) {
1766
1770
  console.log('[design-system] typography: token key sample =', keys.slice(0, 25).join(', '));
1767
- const ff = keys.filter(k => k.startsWith('font-family-'));
1771
+ const ff = keys.filter(k => isFontFamilyKey(k));
1768
1772
  console.log('[design-system] typography: font-family key sample =', ff.slice(0, 25).join(', '));
1769
1773
  }
1770
1774
  }
@@ -1776,7 +1780,7 @@ function groupTypography(variableSet) {
1776
1780
  other: {}
1777
1781
  };
1778
1782
  for (const [key, token] of entries$1(toks)) {
1779
- if (key.startsWith('font-family-')) {
1783
+ if (isFontFamilyKey(key)) {
1780
1784
  out.families[key] = token;
1781
1785
  continue;
1782
1786
  }
@@ -2112,6 +2116,10 @@ function normalizeFontKey(rawKey) {
2112
2116
  if (rawKey.startsWith('font-family-')) {
2113
2117
  return rawKey.replace(/^font-family-/, 'font-');
2114
2118
  }
2119
+ // accept common typo
2120
+ if (rawKey.startsWith('font-familiy-')) {
2121
+ return rawKey.replace(/^font-familiy-/, 'font-');
2122
+ }
2115
2123
  if (rawKey.startsWith('font-')) {
2116
2124
  return rawKey;
2117
2125
  }
@@ -2143,6 +2151,65 @@ function normalizeValuesKeys(values) {
2143
2151
  }
2144
2152
  return out;
2145
2153
  }
2154
+ function escapeCssSingleQuotedString(value) {
2155
+ return String(value).replace(/\\/g, '\\\\').replace(/'/g, "\\'");
2156
+ }
2157
+ function splitFontStack(raw) {
2158
+ return String(raw ?? '').split(',').map(p => p.trim()).filter(Boolean);
2159
+ }
2160
+ function maybeCollapseToBaseFont(raw, {
2161
+ baseTokenKey,
2162
+ baseFamily
2163
+ }) {
2164
+ // Collapse "Sharp Grotesk Medium 19" -> var(--font-body) when baseFamily is "Sharp Grotesk".
2165
+ // This keeps projects with a single font family from generating multiple (near-identical) families.
2166
+ // Does not hardcode any specific family name.
2167
+ const v = String(raw ?? '').trim();
2168
+ if (!v || !baseTokenKey || !baseFamily) {
2169
+ return raw;
2170
+ }
2171
+
2172
+ // Avoid changing var() or multi-stack definitions.
2173
+ if (/^var\(/.test(v) || v.includes(',')) {
2174
+ return raw;
2175
+ }
2176
+ const base = String(baseFamily).trim();
2177
+ if (!base) {
2178
+ return raw;
2179
+ }
2180
+ if (v === base || v.startsWith(`${base} `)) {
2181
+ return `var(--${baseTokenKey})`;
2182
+ }
2183
+ return raw;
2184
+ }
2185
+ function formatFontFamilyValue(raw) {
2186
+ if (raw == null) {
2187
+ return raw;
2188
+ }
2189
+ const s = String(raw).trim();
2190
+ if (!s) {
2191
+ return null;
2192
+ }
2193
+
2194
+ // Allow comma-separated stacks and quote parts that would otherwise be parsed as separate identifiers.
2195
+ const parts = splitFontStack(s);
2196
+ const formatted = parts.map(p => {
2197
+ // Keep CSS var() and already-quoted values.
2198
+ if (/^var\(/.test(p)) {
2199
+ return p;
2200
+ }
2201
+ if (p.startsWith("'") && p.endsWith("'") || p.startsWith('"') && p.endsWith('"')) {
2202
+ return p;
2203
+ }
2204
+
2205
+ // Quote anything containing whitespace or special characters.
2206
+ if (/\s/.test(p) || /[^a-zA-Z0-9_-]/.test(p)) {
2207
+ return `'${escapeCssSingleQuotedString(p)}'`;
2208
+ }
2209
+ return p;
2210
+ });
2211
+ return formatted.join(', ');
2212
+ }
2146
2213
 
2147
2214
  /**
2148
2215
  * Generate font family.
@@ -2187,9 +2254,25 @@ async function generateFontFamily(variableSet, config) {
2187
2254
  */
2188
2255
  async function generateFile(variables, config) {
2189
2256
  let css = `/* AUTO-GENERATED - DO NOT EDIT BY HAND */\n\n` + `@theme {\n`;
2257
+
2258
+ // If a project uses a single font family, designers sometimes encode style/optical size into the
2259
+ // "family" token (e.g. "Sharp Grotesk Medium 19"). For CSS, we usually want a stable family name.
2260
+ // We use the first part of the base token's mobile stack as the canonical family and collapse
2261
+ // other families that match (or start with) it.
2262
+ const baseTokenKey = Object.hasOwn(variables || {}, 'font-body') ? 'font-body' : null;
2263
+ const baseMobileRaw = baseTokenKey ? variables?.[baseTokenKey]?.values?.mobile : null;
2264
+ const baseFamily = baseMobileRaw ? splitFontStack(baseMobileRaw)[0] : null;
2190
2265
  for (const [key, token] of Object.entries(variables || {})) {
2191
- const mobile = token?.values?.mobile;
2192
- const desktop = token?.values?.desktop;
2266
+ const mobileRaw = key === baseTokenKey ? token?.values?.mobile : maybeCollapseToBaseFont(token?.values?.mobile, {
2267
+ baseTokenKey,
2268
+ baseFamily
2269
+ });
2270
+ const desktopRaw = key === baseTokenKey ? token?.values?.desktop : maybeCollapseToBaseFont(token?.values?.desktop, {
2271
+ baseTokenKey,
2272
+ baseFamily
2273
+ });
2274
+ const mobile = formatFontFamilyValue(mobileRaw);
2275
+ const desktop = formatFontFamilyValue(desktopRaw);
2193
2276
  if (mobile != null) {
2194
2277
  css += ` --${key}: ${mobile};\n`;
2195
2278
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vettvangur/design-system",
3
- "version": "2.0.61",
3
+ "version": "2.0.63",
4
4
  "description": "",
5
5
  "access": "public",
6
6
  "type": "module",