rafters 0.0.40 → 0.0.42
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.js +633 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45078,6 +45078,228 @@ var DEFAULT_FONT_WEIGHTS = {
|
|
|
45078
45078
|
extrabold: { value: 800, meaning: "Extra bold weight", contexts: ["display", "hero"] },
|
|
45079
45079
|
black: { value: 900, meaning: "Black weight", contexts: ["display", "impact"] }
|
|
45080
45080
|
};
|
|
45081
|
+
var TYPOGRAPHY_ROLE_CONSUMERS = {
|
|
45082
|
+
"display-large": ["hero"],
|
|
45083
|
+
"display-medium": ["h1"],
|
|
45084
|
+
"title-large": ["h2"],
|
|
45085
|
+
"title-medium": [
|
|
45086
|
+
"h3",
|
|
45087
|
+
"card-title",
|
|
45088
|
+
"dialog-title",
|
|
45089
|
+
"sheet-title",
|
|
45090
|
+
"drawer-title",
|
|
45091
|
+
"empty-title",
|
|
45092
|
+
"alert-dialog-title"
|
|
45093
|
+
],
|
|
45094
|
+
"title-small": ["h4", "alert-title", "accordion-trigger"],
|
|
45095
|
+
"body-large": ["lead"],
|
|
45096
|
+
"body-medium": ["p", "list-item", "blockquote", "accordion-content"],
|
|
45097
|
+
"body-small": [
|
|
45098
|
+
"card-description",
|
|
45099
|
+
"dialog-description",
|
|
45100
|
+
"sheet-description",
|
|
45101
|
+
"alert-description",
|
|
45102
|
+
"field-description",
|
|
45103
|
+
"tooltip",
|
|
45104
|
+
"menu-item",
|
|
45105
|
+
"table-cell",
|
|
45106
|
+
"input",
|
|
45107
|
+
"select",
|
|
45108
|
+
"textarea"
|
|
45109
|
+
],
|
|
45110
|
+
"label-large": ["button", "tab-trigger", "nav-trigger", "toggle", "pagination-link"],
|
|
45111
|
+
"label-medium": ["label", "breadcrumb", "button-sm", "sidebar-item"],
|
|
45112
|
+
"label-small": ["badge", "sidebar-label", "caption", "command-group-heading"],
|
|
45113
|
+
"code-large": ["code-block"],
|
|
45114
|
+
"code-small": ["code-inline", "kbd"],
|
|
45115
|
+
shortcut: ["keyboard-shortcut"]
|
|
45116
|
+
};
|
|
45117
|
+
var DEFAULT_TYPOGRAPHY_COMPOSITE_MAPPINGS = {
|
|
45118
|
+
"display-large": {
|
|
45119
|
+
fontFamily: "heading",
|
|
45120
|
+
fontSize: "5xl",
|
|
45121
|
+
fontWeight: "bold",
|
|
45122
|
+
lineHeight: "5xl",
|
|
45123
|
+
letterSpacing: "5xl",
|
|
45124
|
+
responsive: { lg: { fontSize: "6xl" } },
|
|
45125
|
+
meaning: "Largest display text for hero sections and landing pages",
|
|
45126
|
+
contexts: ["hero-heading", "landing-page"],
|
|
45127
|
+
do: ["Use sparingly for maximum visual impact", "Pair with ample whitespace"],
|
|
45128
|
+
never: ["Use more than once per page", "Use in constrained containers like cards"],
|
|
45129
|
+
trustLevel: "high",
|
|
45130
|
+
consequence: "reversible"
|
|
45131
|
+
},
|
|
45132
|
+
"display-medium": {
|
|
45133
|
+
fontFamily: "heading",
|
|
45134
|
+
fontSize: "4xl",
|
|
45135
|
+
fontWeight: "bold",
|
|
45136
|
+
lineHeight: "4xl",
|
|
45137
|
+
letterSpacing: "4xl",
|
|
45138
|
+
responsive: { lg: { fontSize: "5xl" } },
|
|
45139
|
+
meaning: "Primary page heading -- one per page",
|
|
45140
|
+
contexts: ["page-title", "h1"],
|
|
45141
|
+
do: ["Use once per page for the main title", "Place at the top of the content area"],
|
|
45142
|
+
never: ["Use multiple times on a single page", "Use inside cards or dialogs"],
|
|
45143
|
+
trustLevel: "high",
|
|
45144
|
+
consequence: "reversible"
|
|
45145
|
+
},
|
|
45146
|
+
"title-large": {
|
|
45147
|
+
fontFamily: "heading",
|
|
45148
|
+
fontSize: "3xl",
|
|
45149
|
+
fontWeight: "semibold",
|
|
45150
|
+
lineHeight: "3xl",
|
|
45151
|
+
letterSpacing: "3xl",
|
|
45152
|
+
meaning: "Major section heading",
|
|
45153
|
+
contexts: ["section-title", "h2"],
|
|
45154
|
+
do: ["Use to divide major content sections", "Maintain heading hierarchy (h1 > h2 > h3)"],
|
|
45155
|
+
never: ["Skip heading levels (h1 then h3)", "Use for decorative emphasis"],
|
|
45156
|
+
trustLevel: "medium",
|
|
45157
|
+
consequence: "reversible"
|
|
45158
|
+
},
|
|
45159
|
+
"title-medium": {
|
|
45160
|
+
fontFamily: "heading",
|
|
45161
|
+
fontSize: "lg",
|
|
45162
|
+
fontWeight: "semibold",
|
|
45163
|
+
lineHeight: "lg",
|
|
45164
|
+
letterSpacing: "lg",
|
|
45165
|
+
meaning: "Component and subsection title -- shared by card, dialog, sheet, drawer, empty state",
|
|
45166
|
+
contexts: ["h3", "card-title", "dialog-title", "sheet-title", "drawer-title", "empty-title"],
|
|
45167
|
+
do: ["Use for component-level headings", "Use consistently across all overlay and card titles"],
|
|
45168
|
+
never: ["Mix with other title sizes in the same component", "Override without why-gate"],
|
|
45169
|
+
trustLevel: "medium",
|
|
45170
|
+
consequence: "reversible"
|
|
45171
|
+
},
|
|
45172
|
+
"title-small": {
|
|
45173
|
+
fontFamily: "heading",
|
|
45174
|
+
fontSize: "base",
|
|
45175
|
+
fontWeight: "semibold",
|
|
45176
|
+
lineHeight: "base",
|
|
45177
|
+
letterSpacing: "base",
|
|
45178
|
+
meaning: "Minor heading and alert title",
|
|
45179
|
+
contexts: ["h4", "alert-title", "accordion-trigger"],
|
|
45180
|
+
do: ["Use for subsections within a card or panel", "Use for alert and accordion headings"],
|
|
45181
|
+
never: ["Use as the primary heading on a page"],
|
|
45182
|
+
trustLevel: "medium",
|
|
45183
|
+
consequence: "reversible"
|
|
45184
|
+
},
|
|
45185
|
+
"body-large": {
|
|
45186
|
+
fontFamily: "body",
|
|
45187
|
+
fontSize: "xl",
|
|
45188
|
+
fontWeight: "normal",
|
|
45189
|
+
lineHeight: "xl",
|
|
45190
|
+
letterSpacing: "xl",
|
|
45191
|
+
meaning: "Lead paragraph and introductory text",
|
|
45192
|
+
contexts: ["lead", "introduction", "hero-body"],
|
|
45193
|
+
do: ["Use for the first paragraph of a section", "Use for hero body copy"],
|
|
45194
|
+
never: ["Use for all body text", "Use in compact UI like sidebars"],
|
|
45195
|
+
trustLevel: "low",
|
|
45196
|
+
consequence: "reversible"
|
|
45197
|
+
},
|
|
45198
|
+
"body-medium": {
|
|
45199
|
+
fontFamily: "body",
|
|
45200
|
+
fontSize: "base",
|
|
45201
|
+
fontWeight: "normal",
|
|
45202
|
+
lineHeight: "base",
|
|
45203
|
+
letterSpacing: "base",
|
|
45204
|
+
meaning: "Default body text for paragraphs and content",
|
|
45205
|
+
contexts: ["paragraph", "body-text", "list-item", "blockquote", "accordion-content"],
|
|
45206
|
+
do: ["Use for all standard body content", "Ensure sufficient contrast against background"],
|
|
45207
|
+
never: ["Use for labels or UI chrome", "Set below 1rem"],
|
|
45208
|
+
trustLevel: "low",
|
|
45209
|
+
consequence: "reversible"
|
|
45210
|
+
},
|
|
45211
|
+
"body-small": {
|
|
45212
|
+
fontFamily: "body",
|
|
45213
|
+
fontSize: "sm",
|
|
45214
|
+
fontWeight: "normal",
|
|
45215
|
+
lineHeight: "sm",
|
|
45216
|
+
letterSpacing: "sm",
|
|
45217
|
+
meaning: "Secondary text -- descriptions, tooltips, menu items, table cells",
|
|
45218
|
+
contexts: ["description", "tooltip", "menu-item", "table-cell", "input-text", "helper-text"],
|
|
45219
|
+
do: ["Use for supplementary information", "Use for compact UI elements like menus and tables"],
|
|
45220
|
+
never: ["Use for primary content that users must read", "Set below 0.875rem for body text"],
|
|
45221
|
+
trustLevel: "low",
|
|
45222
|
+
consequence: "reversible"
|
|
45223
|
+
},
|
|
45224
|
+
"label-large": {
|
|
45225
|
+
fontFamily: "body",
|
|
45226
|
+
fontSize: "base",
|
|
45227
|
+
fontWeight: "medium",
|
|
45228
|
+
lineHeight: "base",
|
|
45229
|
+
letterSpacing: "base",
|
|
45230
|
+
meaning: "Interactive element text -- buttons, tabs, nav triggers, toggles",
|
|
45231
|
+
contexts: ["button", "tab-trigger", "nav-trigger", "toggle", "pagination"],
|
|
45232
|
+
do: ["Use for primary interactive controls", "Ensure touch target meets 24px minimum"],
|
|
45233
|
+
never: ["Use for passive content", "Mix with body text styling"],
|
|
45234
|
+
trustLevel: "medium",
|
|
45235
|
+
consequence: "reversible"
|
|
45236
|
+
},
|
|
45237
|
+
"label-medium": {
|
|
45238
|
+
fontFamily: "body",
|
|
45239
|
+
fontSize: "sm",
|
|
45240
|
+
fontWeight: "medium",
|
|
45241
|
+
lineHeight: "sm",
|
|
45242
|
+
letterSpacing: "sm",
|
|
45243
|
+
meaning: "Form labels, breadcrumbs, small buttons, sidebar items",
|
|
45244
|
+
contexts: ["label", "breadcrumb", "small-button", "sidebar-item"],
|
|
45245
|
+
do: ["Use for form field labels", "Use for secondary navigation"],
|
|
45246
|
+
never: ["Use for headings", "Use for primary call-to-action buttons"],
|
|
45247
|
+
trustLevel: "low",
|
|
45248
|
+
consequence: "reversible"
|
|
45249
|
+
},
|
|
45250
|
+
"label-small": {
|
|
45251
|
+
fontFamily: "body",
|
|
45252
|
+
fontSize: "xs",
|
|
45253
|
+
fontWeight: "medium",
|
|
45254
|
+
lineHeight: "xs",
|
|
45255
|
+
letterSpacing: "xs",
|
|
45256
|
+
meaning: "Smallest label text -- badges, sidebar labels, captions",
|
|
45257
|
+
contexts: ["badge", "sidebar-label", "caption", "command-group-heading"],
|
|
45258
|
+
do: ["Use only for tertiary UI information", "Ensure adequate contrast at small size"],
|
|
45259
|
+
never: ["Use for content users must read to complete a task", "Set below 0.75rem"],
|
|
45260
|
+
trustLevel: "low",
|
|
45261
|
+
consequence: "reversible"
|
|
45262
|
+
},
|
|
45263
|
+
"code-large": {
|
|
45264
|
+
fontFamily: "code",
|
|
45265
|
+
fontSize: "base",
|
|
45266
|
+
fontWeight: "normal",
|
|
45267
|
+
lineHeight: "base",
|
|
45268
|
+
letterSpacing: "base",
|
|
45269
|
+
meaning: "Code blocks and pre-formatted text",
|
|
45270
|
+
contexts: ["code-block", "pre", "terminal-output"],
|
|
45271
|
+
do: ["Use for multi-line code content", "Pair with syntax highlighting"],
|
|
45272
|
+
never: ["Use for inline code snippets", "Use for non-code content"],
|
|
45273
|
+
trustLevel: "low",
|
|
45274
|
+
consequence: "reversible"
|
|
45275
|
+
},
|
|
45276
|
+
"code-small": {
|
|
45277
|
+
fontFamily: "code",
|
|
45278
|
+
fontSize: "sm",
|
|
45279
|
+
fontWeight: "normal",
|
|
45280
|
+
lineHeight: "sm",
|
|
45281
|
+
letterSpacing: "sm",
|
|
45282
|
+
meaning: "Inline code and keyboard key indicators",
|
|
45283
|
+
contexts: ["code-inline", "kbd", "technical-term"],
|
|
45284
|
+
do: ["Use for code references within prose", "Use for keyboard shortcut labels"],
|
|
45285
|
+
never: ["Use for multi-line code blocks", "Use for body text"],
|
|
45286
|
+
trustLevel: "low",
|
|
45287
|
+
consequence: "reversible"
|
|
45288
|
+
},
|
|
45289
|
+
shortcut: {
|
|
45290
|
+
fontFamily: "code",
|
|
45291
|
+
fontSize: "xs",
|
|
45292
|
+
fontWeight: "normal",
|
|
45293
|
+
lineHeight: "xs",
|
|
45294
|
+
letterSpacing: "widest",
|
|
45295
|
+
meaning: "Keyboard shortcut indicators in menus",
|
|
45296
|
+
contexts: ["keyboard-shortcut", "command-shortcut", "menu-shortcut"],
|
|
45297
|
+
do: ["Use for keyboard shortcut text in menus and command palettes"],
|
|
45298
|
+
never: ["Use for regular text content", "Use outside of menu/command contexts"],
|
|
45299
|
+
trustLevel: "low",
|
|
45300
|
+
consequence: "reversible"
|
|
45301
|
+
}
|
|
45302
|
+
};
|
|
45081
45303
|
var DEFAULT_SEMANTIC_COLOR_MAPPINGS = {
|
|
45082
45304
|
// ============================================================================
|
|
45083
45305
|
// CORE SURFACE TOKENS (shadcn compatible)
|
|
@@ -46839,6 +47061,7 @@ function groupTokens(tokens) {
|
|
|
46839
47061
|
breakpoint: [],
|
|
46840
47062
|
elevation: [],
|
|
46841
47063
|
focus: [],
|
|
47064
|
+
"typography-composite": [],
|
|
46842
47065
|
other: []
|
|
46843
47066
|
};
|
|
46844
47067
|
for (const token of tokens) {
|
|
@@ -46876,6 +47099,9 @@ function groupTokens(tokens) {
|
|
|
46876
47099
|
case "focus":
|
|
46877
47100
|
groups.focus.push(token);
|
|
46878
47101
|
break;
|
|
47102
|
+
case "typography-composite":
|
|
47103
|
+
groups["typography-composite"].push(token);
|
|
47104
|
+
break;
|
|
46879
47105
|
default:
|
|
46880
47106
|
groups.other.push(token);
|
|
46881
47107
|
}
|
|
@@ -46944,7 +47170,8 @@ function generateThemeBlock(groups) {
|
|
|
46944
47170
|
const value2 = tokenValueToCSS(token);
|
|
46945
47171
|
if (value2 === null) continue;
|
|
46946
47172
|
const key = token.name.replace(/^spacing-/, "");
|
|
46947
|
-
|
|
47173
|
+
const themeValue = value2.replaceAll("var(--rafters-spacing-base)", "var(--spacing-base)");
|
|
47174
|
+
lines.push(` --spacing-${key}: ${themeValue};`);
|
|
46948
47175
|
}
|
|
46949
47176
|
lines.push("");
|
|
46950
47177
|
}
|
|
@@ -47156,7 +47383,95 @@ function generateAnimationTokens(motionTokens) {
|
|
|
47156
47383
|
}
|
|
47157
47384
|
return lines.join("\n");
|
|
47158
47385
|
}
|
|
47159
|
-
function
|
|
47386
|
+
function generateTypographyCompositeUtilities(compositeTokens) {
|
|
47387
|
+
if (compositeTokens.length === 0) {
|
|
47388
|
+
return "";
|
|
47389
|
+
}
|
|
47390
|
+
const lines = [];
|
|
47391
|
+
const mappings = compositeTokens.map((t2) => {
|
|
47392
|
+
try {
|
|
47393
|
+
const parsed = JSON.parse(t2.value);
|
|
47394
|
+
return { name: t2.name, ...parsed };
|
|
47395
|
+
} catch {
|
|
47396
|
+
return null;
|
|
47397
|
+
}
|
|
47398
|
+
}).filter((m3) => m3 !== null);
|
|
47399
|
+
for (const mapping of mappings) {
|
|
47400
|
+
lines.push(`@utility text-${mapping.name} {`);
|
|
47401
|
+
lines.push(` font-family: var(--font-${mapping.fontFamily});`);
|
|
47402
|
+
lines.push(` font-size: var(--font-size-${mapping.fontSize});`);
|
|
47403
|
+
lines.push(` font-weight: var(--font-weight-${mapping.fontWeight});`);
|
|
47404
|
+
lines.push(` line-height: var(--line-height-${mapping.lineHeight});`);
|
|
47405
|
+
const namedTrackingValues = {
|
|
47406
|
+
tighter: "-0.05em",
|
|
47407
|
+
tight: "-0.025em",
|
|
47408
|
+
normal: "0em",
|
|
47409
|
+
wide: "0.025em",
|
|
47410
|
+
wider: "0.05em",
|
|
47411
|
+
widest: "0.1em"
|
|
47412
|
+
};
|
|
47413
|
+
if (mapping.letterSpacing in namedTrackingValues) {
|
|
47414
|
+
lines.push(` letter-spacing: ${namedTrackingValues[mapping.letterSpacing]};`);
|
|
47415
|
+
} else {
|
|
47416
|
+
lines.push(` letter-spacing: var(--letter-spacing-${mapping.letterSpacing});`);
|
|
47417
|
+
}
|
|
47418
|
+
if (mapping.responsive) {
|
|
47419
|
+
for (const [breakpoint, overrides] of Object.entries(mapping.responsive)) {
|
|
47420
|
+
if (overrides.fontSize) {
|
|
47421
|
+
const bpWidth = breakpoint === "sm" ? "480px" : breakpoint === "md" ? "640px" : "1024px";
|
|
47422
|
+
lines.push(` @container (min-width: ${bpWidth}) {`);
|
|
47423
|
+
lines.push(` font-size: var(--font-size-${overrides.fontSize});`);
|
|
47424
|
+
lines.push(` line-height: var(--line-height-${overrides.fontSize});`);
|
|
47425
|
+
lines.push(" }");
|
|
47426
|
+
}
|
|
47427
|
+
}
|
|
47428
|
+
}
|
|
47429
|
+
lines.push("}");
|
|
47430
|
+
}
|
|
47431
|
+
return lines.join("\n");
|
|
47432
|
+
}
|
|
47433
|
+
function overridePropertyToUtility(property, value2) {
|
|
47434
|
+
switch (property) {
|
|
47435
|
+
case "fontFamily":
|
|
47436
|
+
return `font-${value2}`;
|
|
47437
|
+
case "fontWeight":
|
|
47438
|
+
return `font-${value2}`;
|
|
47439
|
+
case "fontSize":
|
|
47440
|
+
return `text-${value2}`;
|
|
47441
|
+
case "lineHeight":
|
|
47442
|
+
return `leading-${value2}`;
|
|
47443
|
+
case "letterSpacing":
|
|
47444
|
+
return `tracking-${value2}`;
|
|
47445
|
+
default:
|
|
47446
|
+
return "";
|
|
47447
|
+
}
|
|
47448
|
+
}
|
|
47449
|
+
function generateTypographyOverrideCSS(overrides) {
|
|
47450
|
+
if (overrides.length === 0) {
|
|
47451
|
+
return "";
|
|
47452
|
+
}
|
|
47453
|
+
const lines = [];
|
|
47454
|
+
lines.push("/* -- Typography Element Overrides -- */");
|
|
47455
|
+
for (const override of overrides) {
|
|
47456
|
+
const overrideUtilities = [];
|
|
47457
|
+
for (const [prop, val] of Object.entries(override.overrides)) {
|
|
47458
|
+
if (val) {
|
|
47459
|
+
const utility = overridePropertyToUtility(prop, val);
|
|
47460
|
+
if (utility) {
|
|
47461
|
+
overrideUtilities.push(utility);
|
|
47462
|
+
}
|
|
47463
|
+
}
|
|
47464
|
+
}
|
|
47465
|
+
if (overrideUtilities.length > 0) {
|
|
47466
|
+
lines.push(`/* ${override.element}: diverges from ${override.role} (${override.why}) */`);
|
|
47467
|
+
lines.push(`${override.element} {`);
|
|
47468
|
+
lines.push(` @apply text-${override.role} ${overrideUtilities.join(" ")};`);
|
|
47469
|
+
lines.push("}");
|
|
47470
|
+
}
|
|
47471
|
+
}
|
|
47472
|
+
return lines.join("\n");
|
|
47473
|
+
}
|
|
47474
|
+
function tokensToTailwind(tokens, options = {}, typographyOverrides = []) {
|
|
47160
47475
|
const { includeImport = true } = options;
|
|
47161
47476
|
if (tokens.length === 0) {
|
|
47162
47477
|
throw new Error("Registry is empty");
|
|
@@ -47180,13 +47495,24 @@ function tokensToTailwind(tokens, options = {}) {
|
|
|
47180
47495
|
if (keyframes) {
|
|
47181
47496
|
sections.push(keyframes);
|
|
47182
47497
|
}
|
|
47498
|
+
const typographyUtilities = generateTypographyCompositeUtilities(groups["typography-composite"]);
|
|
47499
|
+
if (typographyUtilities) {
|
|
47500
|
+
sections.push("");
|
|
47501
|
+
sections.push(typographyUtilities);
|
|
47502
|
+
}
|
|
47503
|
+
const overrideCSS = generateTypographyOverrideCSS(typographyOverrides);
|
|
47504
|
+
if (overrideCSS) {
|
|
47505
|
+
sections.push("");
|
|
47506
|
+
sections.push(overrideCSS);
|
|
47507
|
+
}
|
|
47183
47508
|
sections.push("");
|
|
47184
47509
|
sections.push(generateArticleBaseLayer());
|
|
47185
47510
|
return sections.join("\n");
|
|
47186
47511
|
}
|
|
47187
47512
|
function registryToTailwind(registry2, options) {
|
|
47188
47513
|
const tokens = registry2.list();
|
|
47189
|
-
|
|
47514
|
+
const typographyOverrides = registry2.getTypographyOverrides();
|
|
47515
|
+
return tokensToTailwind(tokens, options, typographyOverrides);
|
|
47190
47516
|
}
|
|
47191
47517
|
function generateVarsRootBlock(groups) {
|
|
47192
47518
|
const lines = [];
|
|
@@ -47203,7 +47529,7 @@ function generateVarsRootBlock(groups) {
|
|
|
47203
47529
|
for (const token of groups.spacing) {
|
|
47204
47530
|
const value2 = tokenValueToCSS(token);
|
|
47205
47531
|
if (value2 === null) continue;
|
|
47206
|
-
lines.push(` --rafters
|
|
47532
|
+
lines.push(` --rafters-${token.name}: ${value2};`);
|
|
47207
47533
|
}
|
|
47208
47534
|
lines.push("");
|
|
47209
47535
|
}
|
|
@@ -47222,7 +47548,7 @@ function generateVarsRootBlock(groups) {
|
|
|
47222
47548
|
for (const token of groups.radius) {
|
|
47223
47549
|
const value2 = tokenValueToCSS(token);
|
|
47224
47550
|
if (value2 === null) continue;
|
|
47225
|
-
lines.push(` --rafters
|
|
47551
|
+
lines.push(` --rafters-${token.name}: ${value2};`);
|
|
47226
47552
|
}
|
|
47227
47553
|
lines.push("");
|
|
47228
47554
|
}
|
|
@@ -48447,6 +48773,26 @@ var TokenSchema = external_exports.object({
|
|
|
48447
48773
|
requiresConfirmation: external_exports.boolean().optional()
|
|
48448
48774
|
// UI pattern requirement for destructive actions
|
|
48449
48775
|
});
|
|
48776
|
+
var TypographyElementOverrideSchema = external_exports.object({
|
|
48777
|
+
/** CSS element selector, e.g. 'h3' */
|
|
48778
|
+
element: external_exports.string().min(1),
|
|
48779
|
+
/** Base role this element uses, e.g. 'title-medium' */
|
|
48780
|
+
role: external_exports.string().min(1),
|
|
48781
|
+
/** Only the properties that differ from the role */
|
|
48782
|
+
overrides: external_exports.object({
|
|
48783
|
+
fontFamily: external_exports.string().optional(),
|
|
48784
|
+
fontWeight: external_exports.string().optional(),
|
|
48785
|
+
fontSize: external_exports.string().optional(),
|
|
48786
|
+
lineHeight: external_exports.string().optional(),
|
|
48787
|
+
letterSpacing: external_exports.string().optional()
|
|
48788
|
+
}),
|
|
48789
|
+
/** Why-gate: reason for the override (required, non-empty) */
|
|
48790
|
+
why: external_exports.string().min(1, "Why-gate required: provide a reason for this override"),
|
|
48791
|
+
/** Who made the override */
|
|
48792
|
+
who: external_exports.string().min(1),
|
|
48793
|
+
/** When the override was made (ISO timestamp) */
|
|
48794
|
+
when: external_exports.string()
|
|
48795
|
+
});
|
|
48450
48796
|
var NamespaceFileSchema = external_exports.object({
|
|
48451
48797
|
$schema: external_exports.string(),
|
|
48452
48798
|
namespace: external_exports.string(),
|
|
@@ -48455,6 +48801,121 @@ var NamespaceFileSchema = external_exports.object({
|
|
|
48455
48801
|
tokens: external_exports.array(TokenSchema)
|
|
48456
48802
|
});
|
|
48457
48803
|
|
|
48804
|
+
// ../design-tokens/src/validators/typography-a11y.ts
|
|
48805
|
+
var SIZE_ORDER = [
|
|
48806
|
+
"xs",
|
|
48807
|
+
"sm",
|
|
48808
|
+
"base",
|
|
48809
|
+
"lg",
|
|
48810
|
+
"xl",
|
|
48811
|
+
"2xl",
|
|
48812
|
+
"3xl",
|
|
48813
|
+
"4xl",
|
|
48814
|
+
"5xl",
|
|
48815
|
+
"6xl",
|
|
48816
|
+
"7xl",
|
|
48817
|
+
"8xl",
|
|
48818
|
+
"9xl"
|
|
48819
|
+
];
|
|
48820
|
+
function sizeIndex(size) {
|
|
48821
|
+
return SIZE_ORDER.indexOf(size);
|
|
48822
|
+
}
|
|
48823
|
+
var WEIGHT_VALUES = {
|
|
48824
|
+
thin: 100,
|
|
48825
|
+
extralight: 200,
|
|
48826
|
+
light: 300,
|
|
48827
|
+
normal: 400,
|
|
48828
|
+
medium: 500,
|
|
48829
|
+
semibold: 600,
|
|
48830
|
+
bold: 700,
|
|
48831
|
+
extrabold: 800,
|
|
48832
|
+
black: 900
|
|
48833
|
+
};
|
|
48834
|
+
function weightValue(weight) {
|
|
48835
|
+
return WEIGHT_VALUES[weight] ?? 400;
|
|
48836
|
+
}
|
|
48837
|
+
function validateTypographyComposite(mapping, role) {
|
|
48838
|
+
const violations = [];
|
|
48839
|
+
const sizeIdx = sizeIndex(mapping.fontSize);
|
|
48840
|
+
const weight = weightValue(mapping.fontWeight);
|
|
48841
|
+
const isBody = role.startsWith("body-");
|
|
48842
|
+
const isLabel = role.startsWith("label-");
|
|
48843
|
+
const isHeading = role.startsWith("title-") || role.startsWith("display-");
|
|
48844
|
+
if (isBody && sizeIdx < sizeIndex("sm")) {
|
|
48845
|
+
violations.push({
|
|
48846
|
+
rule: "min-body-font-size",
|
|
48847
|
+
severity: "error",
|
|
48848
|
+
message: `Body role "${role}" uses font-size "${mapping.fontSize}" which is below minimum 'sm' (14px)`,
|
|
48849
|
+
wcagCriterion: "1.4.4 Resize Text",
|
|
48850
|
+
property: "fontSize",
|
|
48851
|
+
currentValue: mapping.fontSize,
|
|
48852
|
+
requiredValue: "sm or larger"
|
|
48853
|
+
});
|
|
48854
|
+
}
|
|
48855
|
+
if (isLabel && sizeIdx < sizeIndex("xs")) {
|
|
48856
|
+
violations.push({
|
|
48857
|
+
rule: "min-label-font-size",
|
|
48858
|
+
severity: "error",
|
|
48859
|
+
message: `Label role "${role}" uses font-size "${mapping.fontSize}" which is below minimum 'xs' (12px)`,
|
|
48860
|
+
wcagCriterion: "1.4.4 Resize Text",
|
|
48861
|
+
property: "fontSize",
|
|
48862
|
+
currentValue: mapping.fontSize,
|
|
48863
|
+
requiredValue: "xs or larger"
|
|
48864
|
+
});
|
|
48865
|
+
}
|
|
48866
|
+
if (isBody) {
|
|
48867
|
+
const lhIdx = sizeIndex(mapping.lineHeight);
|
|
48868
|
+
if (lhIdx >= sizeIndex("xl")) {
|
|
48869
|
+
violations.push({
|
|
48870
|
+
rule: "body-line-height",
|
|
48871
|
+
severity: "warning",
|
|
48872
|
+
message: `Body role "${role}" line-height "${mapping.lineHeight}" may be below 1.5 (WCAG 1.4.12 recommends >= 1.5 for body text)`,
|
|
48873
|
+
wcagCriterion: "1.4.12 Text Spacing",
|
|
48874
|
+
property: "lineHeight",
|
|
48875
|
+
currentValue: mapping.lineHeight,
|
|
48876
|
+
requiredValue: "Scale key with line-height >= 1.5 (xs, sm, base, lg)"
|
|
48877
|
+
});
|
|
48878
|
+
}
|
|
48879
|
+
}
|
|
48880
|
+
if (isHeading) {
|
|
48881
|
+
const lhIdx = sizeIndex(mapping.lineHeight);
|
|
48882
|
+
if (lhIdx >= sizeIndex("7xl")) {
|
|
48883
|
+
violations.push({
|
|
48884
|
+
rule: "heading-line-height",
|
|
48885
|
+
severity: "warning",
|
|
48886
|
+
message: `Heading role "${role}" line-height "${mapping.lineHeight}" may be below 1.2`,
|
|
48887
|
+
wcagCriterion: "1.4.12 Text Spacing",
|
|
48888
|
+
property: "lineHeight",
|
|
48889
|
+
currentValue: mapping.lineHeight,
|
|
48890
|
+
requiredValue: "Scale key with line-height >= 1.2"
|
|
48891
|
+
});
|
|
48892
|
+
}
|
|
48893
|
+
}
|
|
48894
|
+
if (weight <= 300 && sizeIdx <= sizeIndex("sm")) {
|
|
48895
|
+
violations.push({
|
|
48896
|
+
rule: "weight-contrast-coupling",
|
|
48897
|
+
severity: "warning",
|
|
48898
|
+
message: `Role "${role}" uses thin weight (${mapping.fontWeight}) at small size (${mapping.fontSize}). This may have insufficient readability. Consider using weight >= medium for small text.`,
|
|
48899
|
+
wcagCriterion: "1.4.3 Contrast (Minimum)",
|
|
48900
|
+
property: "fontWeight",
|
|
48901
|
+
currentValue: mapping.fontWeight,
|
|
48902
|
+
requiredValue: "medium or heavier for small text"
|
|
48903
|
+
});
|
|
48904
|
+
}
|
|
48905
|
+
return violations;
|
|
48906
|
+
}
|
|
48907
|
+
function validateTypographyOverride(override, baseMapping) {
|
|
48908
|
+
const merged = {
|
|
48909
|
+
...baseMapping,
|
|
48910
|
+
fontFamily: override.overrides.fontFamily ? override.overrides.fontFamily : baseMapping.fontFamily,
|
|
48911
|
+
fontSize: override.overrides.fontSize ?? baseMapping.fontSize,
|
|
48912
|
+
fontWeight: override.overrides.fontWeight ?? baseMapping.fontWeight,
|
|
48913
|
+
lineHeight: override.overrides.lineHeight ?? baseMapping.lineHeight,
|
|
48914
|
+
letterSpacing: override.overrides.letterSpacing ?? baseMapping.letterSpacing
|
|
48915
|
+
};
|
|
48916
|
+
return validateTypographyComposite(merged, override.role);
|
|
48917
|
+
}
|
|
48918
|
+
|
|
48458
48919
|
// ../design-tokens/src/registry.ts
|
|
48459
48920
|
var TokenRegistry = class {
|
|
48460
48921
|
tokens = /* @__PURE__ */ new Map();
|
|
@@ -48464,6 +48925,7 @@ var TokenRegistry = class {
|
|
|
48464
48925
|
changeCallback;
|
|
48465
48926
|
adapter;
|
|
48466
48927
|
dirtyNamespaces = /* @__PURE__ */ new Set();
|
|
48928
|
+
typographyOverrides = /* @__PURE__ */ new Map();
|
|
48467
48929
|
constructor(initialTokens) {
|
|
48468
48930
|
if (initialTokens) {
|
|
48469
48931
|
for (const token of initialTokens) {
|
|
@@ -48999,6 +49461,49 @@ var TokenRegistry = class {
|
|
|
48999
49461
|
parseRuleDependencies(rule) {
|
|
49000
49462
|
return this.dependencyGraph.parseRuleDependencies(rule);
|
|
49001
49463
|
}
|
|
49464
|
+
// ===========================================================================
|
|
49465
|
+
// Typography Element Overrides
|
|
49466
|
+
// ===========================================================================
|
|
49467
|
+
/**
|
|
49468
|
+
* Add a typography element override with why-gate enforcement.
|
|
49469
|
+
* Stores an override for a specific HTML element that diverges from its
|
|
49470
|
+
* assigned typography role.
|
|
49471
|
+
*
|
|
49472
|
+
* @throws If why field is empty (why-gate enforcement)
|
|
49473
|
+
* @throws If role references a non-existent typography composite token
|
|
49474
|
+
*/
|
|
49475
|
+
addTypographyOverride(override) {
|
|
49476
|
+
const parsed = TypographyElementOverrideSchema.parse(override);
|
|
49477
|
+
const roleToken = this.get(parsed.role);
|
|
49478
|
+
if (!roleToken || roleToken.namespace !== "typography-composite") {
|
|
49479
|
+
throw new Error(
|
|
49480
|
+
`Typography override for "${parsed.element}" references unknown role "${parsed.role}". Role must be an existing typography-composite token.`
|
|
49481
|
+
);
|
|
49482
|
+
}
|
|
49483
|
+
const baseMapping = DEFAULT_TYPOGRAPHY_COMPOSITE_MAPPINGS[parsed.role];
|
|
49484
|
+
if (baseMapping) {
|
|
49485
|
+
const violations = validateTypographyOverride(parsed, baseMapping);
|
|
49486
|
+
const errors = violations.filter((v) => v.severity === "error");
|
|
49487
|
+
if (errors.length > 0) {
|
|
49488
|
+
throw new Error(
|
|
49489
|
+
`Typography override for "${parsed.element}" violates accessibility: ${errors.map((e) => e.message).join("; ")}`
|
|
49490
|
+
);
|
|
49491
|
+
}
|
|
49492
|
+
}
|
|
49493
|
+
this.typographyOverrides.set(parsed.element, parsed);
|
|
49494
|
+
}
|
|
49495
|
+
/**
|
|
49496
|
+
* Get all typography element overrides.
|
|
49497
|
+
*/
|
|
49498
|
+
getTypographyOverrides() {
|
|
49499
|
+
return Array.from(this.typographyOverrides.values());
|
|
49500
|
+
}
|
|
49501
|
+
/**
|
|
49502
|
+
* Remove a typography element override.
|
|
49503
|
+
*/
|
|
49504
|
+
removeTypographyOverride(element) {
|
|
49505
|
+
return this.typographyOverrides.delete(element);
|
|
49506
|
+
}
|
|
49002
49507
|
/**
|
|
49003
49508
|
* Enhanced validation that includes both registry and rule validation
|
|
49004
49509
|
*/
|
|
@@ -58167,6 +58672,54 @@ function generateTypographyTokens(config3, typographyScale, fontWeights) {
|
|
|
58167
58672
|
never: ["Use for body text", "Use for UI elements"]
|
|
58168
58673
|
}
|
|
58169
58674
|
});
|
|
58675
|
+
tokens.push({
|
|
58676
|
+
name: "font-heading",
|
|
58677
|
+
value: `var(--font-sans)`,
|
|
58678
|
+
category: "typography",
|
|
58679
|
+
namespace: "typography",
|
|
58680
|
+
semanticMeaning: "Font family for headings and display text",
|
|
58681
|
+
usageContext: ["headings", "display-text", "titles"],
|
|
58682
|
+
dependsOn: ["font-sans"],
|
|
58683
|
+
description: "Heading font family. Defaults to sans-serif. Override to change all headings to serif or another family.",
|
|
58684
|
+
generatedAt: timestamp,
|
|
58685
|
+
containerQueryAware: false,
|
|
58686
|
+
usagePatterns: {
|
|
58687
|
+
do: ["Override to set all headings to a different typeface"],
|
|
58688
|
+
never: ["Reference directly in components -- use typography role utilities instead"]
|
|
58689
|
+
}
|
|
58690
|
+
});
|
|
58691
|
+
tokens.push({
|
|
58692
|
+
name: "font-body",
|
|
58693
|
+
value: `var(--font-sans)`,
|
|
58694
|
+
category: "typography",
|
|
58695
|
+
namespace: "typography",
|
|
58696
|
+
semanticMeaning: "Font family for body text and UI elements",
|
|
58697
|
+
usageContext: ["body-text", "labels", "descriptions", "ui-elements"],
|
|
58698
|
+
dependsOn: ["font-sans"],
|
|
58699
|
+
description: "Body font family. Defaults to sans-serif. Override to change all body and UI text.",
|
|
58700
|
+
generatedAt: timestamp,
|
|
58701
|
+
containerQueryAware: false,
|
|
58702
|
+
usagePatterns: {
|
|
58703
|
+
do: ["Override to set all body text to a different typeface"],
|
|
58704
|
+
never: ["Reference directly in components -- use typography role utilities instead"]
|
|
58705
|
+
}
|
|
58706
|
+
});
|
|
58707
|
+
tokens.push({
|
|
58708
|
+
name: "font-code",
|
|
58709
|
+
value: `var(--font-mono)`,
|
|
58710
|
+
category: "typography",
|
|
58711
|
+
namespace: "typography",
|
|
58712
|
+
semanticMeaning: "Font family for code, keyboard shortcuts, and technical content",
|
|
58713
|
+
usageContext: ["code-blocks", "inline-code", "kbd", "shortcuts"],
|
|
58714
|
+
dependsOn: ["font-mono"],
|
|
58715
|
+
description: "Code font family. Defaults to monospace. Override for a custom code typeface.",
|
|
58716
|
+
generatedAt: timestamp,
|
|
58717
|
+
containerQueryAware: false,
|
|
58718
|
+
usagePatterns: {
|
|
58719
|
+
do: ["Override to set all code content to a custom monospace font"],
|
|
58720
|
+
never: ["Reference directly in components -- use typography role utilities instead"]
|
|
58721
|
+
}
|
|
58722
|
+
});
|
|
58170
58723
|
const baseFontSizeRem = baseFontSize / 16;
|
|
58171
58724
|
tokens.push({
|
|
58172
58725
|
name: "font-size-base",
|
|
@@ -58283,6 +58836,72 @@ function generateTypographyTokens(config3, typographyScale, fontWeights) {
|
|
|
58283
58836
|
};
|
|
58284
58837
|
}
|
|
58285
58838
|
|
|
58839
|
+
// ../design-tokens/src/generators/typography-composite.ts
|
|
58840
|
+
function familyRoleToDependency(role) {
|
|
58841
|
+
switch (role) {
|
|
58842
|
+
case "heading":
|
|
58843
|
+
return "font-heading";
|
|
58844
|
+
case "body":
|
|
58845
|
+
return "font-body";
|
|
58846
|
+
case "code":
|
|
58847
|
+
return "font-code";
|
|
58848
|
+
}
|
|
58849
|
+
}
|
|
58850
|
+
function generateTypographyCompositeTokens(_config) {
|
|
58851
|
+
const tokens = [];
|
|
58852
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
58853
|
+
for (const [name2, mapping] of Object.entries(DEFAULT_TYPOGRAPHY_COMPOSITE_MAPPINGS)) {
|
|
58854
|
+
const violations = validateTypographyComposite(mapping, name2);
|
|
58855
|
+
const errors = violations.filter((v) => v.severity === "error");
|
|
58856
|
+
if (errors.length > 0) {
|
|
58857
|
+
throw new Error(
|
|
58858
|
+
`Typography role "${name2}" violates accessibility: ${errors.map((e) => e.message).join("; ")}`
|
|
58859
|
+
);
|
|
58860
|
+
}
|
|
58861
|
+
const familyDep = familyRoleToDependency(mapping.fontFamily);
|
|
58862
|
+
const dependsOn = [
|
|
58863
|
+
familyDep,
|
|
58864
|
+
`font-size-${mapping.fontSize}`,
|
|
58865
|
+
`font-weight-${mapping.fontWeight}`,
|
|
58866
|
+
`line-height-${mapping.lineHeight}`,
|
|
58867
|
+
`letter-spacing-${mapping.letterSpacing}`
|
|
58868
|
+
];
|
|
58869
|
+
const compositeValue = JSON.stringify({
|
|
58870
|
+
fontFamily: mapping.fontFamily,
|
|
58871
|
+
fontSize: mapping.fontSize,
|
|
58872
|
+
fontWeight: mapping.fontWeight,
|
|
58873
|
+
lineHeight: mapping.lineHeight,
|
|
58874
|
+
letterSpacing: mapping.letterSpacing,
|
|
58875
|
+
...mapping.responsive ? { responsive: mapping.responsive } : {}
|
|
58876
|
+
});
|
|
58877
|
+
const consumers = TYPOGRAPHY_ROLE_CONSUMERS[name2] ?? [];
|
|
58878
|
+
tokens.push({
|
|
58879
|
+
name: name2,
|
|
58880
|
+
value: compositeValue,
|
|
58881
|
+
category: "typography",
|
|
58882
|
+
namespace: "typography-composite",
|
|
58883
|
+
semanticMeaning: mapping.meaning,
|
|
58884
|
+
usageContext: mapping.contexts,
|
|
58885
|
+
trustLevel: mapping.trustLevel,
|
|
58886
|
+
consequence: mapping.consequence,
|
|
58887
|
+
dependsOn,
|
|
58888
|
+
applicableComponents: consumers,
|
|
58889
|
+
containerQueryAware: true,
|
|
58890
|
+
generateUtilityClass: true,
|
|
58891
|
+
description: `Typography composite: font-${mapping.fontFamily} text-${mapping.fontSize} font-${mapping.fontWeight}. ${mapping.meaning}`,
|
|
58892
|
+
generatedAt: timestamp,
|
|
58893
|
+
usagePatterns: {
|
|
58894
|
+
do: mapping.do,
|
|
58895
|
+
never: mapping.never
|
|
58896
|
+
}
|
|
58897
|
+
});
|
|
58898
|
+
}
|
|
58899
|
+
return {
|
|
58900
|
+
namespace: "typography-composite",
|
|
58901
|
+
tokens
|
|
58902
|
+
};
|
|
58903
|
+
}
|
|
58904
|
+
|
|
58286
58905
|
// ../design-tokens/src/generators/index.ts
|
|
58287
58906
|
function buildAllColorScales(customBases) {
|
|
58288
58907
|
const bases = customBases ?? DEFAULT_SEMANTIC_COLOR_BASES;
|
|
@@ -58312,6 +58931,11 @@ function createGeneratorDefs(colorPaletteBases) {
|
|
|
58312
58931
|
},
|
|
58313
58932
|
// Semantic tokens (depend on color)
|
|
58314
58933
|
{ name: "semantic", generate: (config3) => generateSemanticTokens(config3) },
|
|
58934
|
+
// Typography composites (depend on typography)
|
|
58935
|
+
{
|
|
58936
|
+
name: "typography-composite",
|
|
58937
|
+
generate: (config3) => generateTypographyCompositeTokens(config3)
|
|
58938
|
+
},
|
|
58315
58939
|
// Derived tokens (depend on spacing/foundation)
|
|
58316
58940
|
{
|
|
58317
58941
|
name: "radius",
|
|
@@ -58832,13 +59456,13 @@ Container and Grid handle ALL layout. You do not write layout code.
|
|
|
58832
59456
|
|
|
58833
59457
|
| Instead of | Use |
|
|
58834
59458
|
|---|---|
|
|
58835
|
-
| \`<p className="text-sm text-muted-foreground">\` | \`<
|
|
59459
|
+
| \`<p className="text-sm text-muted-foreground">\` | \`<P size="sm" color="muted">\` |
|
|
58836
59460
|
| \`<p>\` | \`<P>\` |
|
|
58837
59461
|
| \`<h1 className="text-4xl font-bold">\` | \`<H1>\` |
|
|
58838
59462
|
| \`<h2>\` | \`<H2>\` |
|
|
58839
59463
|
| \`<h3>\` | \`<H3>\` |
|
|
58840
59464
|
| \`<span className="text-xs">\` | \`<Small>\` |
|
|
58841
|
-
| \`<span className="text-lg font-semibold">\` | \`<
|
|
59465
|
+
| \`<span className="text-lg font-semibold">\` | \`<P size="lg" weight="semibold">\` |
|
|
58842
59466
|
|
|
58843
59467
|
## Color -- Tokens, Not Values
|
|
58844
59468
|
|
|
@@ -58849,7 +59473,7 @@ Never use hex, HSL, or palette internals.
|
|
|
58849
59473
|
|
|
58850
59474
|
\`\`\`tsx
|
|
58851
59475
|
import { Container, Grid } from "@rafters/ui"
|
|
58852
|
-
import { H1,
|
|
59476
|
+
import { H1, P } from "@rafters/ui/components/ui/typography"
|
|
58853
59477
|
import { Card } from "@rafters/ui/components/ui/card"
|
|
58854
59478
|
import { Button } from "@rafters/ui/components/ui/button"
|
|
58855
59479
|
|
|
@@ -58857,7 +59481,7 @@ export default function Page() {
|
|
|
58857
59481
|
return (
|
|
58858
59482
|
<Container>
|
|
58859
59483
|
<H1>Title</H1>
|
|
58860
|
-
<
|
|
59484
|
+
<P size="xl" color="muted">Description.</P>
|
|
58861
59485
|
<Grid preset="cards">
|
|
58862
59486
|
<Card>...</Card>
|
|
58863
59487
|
<Card>...</Card>
|