@snagtag/design-system 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -61,6 +61,7 @@ __export(index_exports, {
61
61
  createOverlay: () => createOverlay,
62
62
  createReassignmentState: () => createReassignmentState,
63
63
  createThemeEditorState: () => createThemeEditorState,
64
+ customTokenDefaults: () => customTokenDefaults,
64
65
  darken: () => darken,
65
66
  downloadAuditReport: () => downloadAuditReport,
66
67
  downloadStyleGuide: () => downloadStyleGuide,
@@ -327,6 +328,11 @@ function suggestPalettes(primaryHex) {
327
328
  }
328
329
 
329
330
  // src/theme-defaults.ts
331
+ function customTokenDefaults(tokens = []) {
332
+ const out = {};
333
+ for (const t of tokens) out[t.key] = t.defaultValue;
334
+ return out;
335
+ }
330
336
  var THEME_DEFAULTS = {
331
337
  // Primitives
332
338
  primaryColor: "#2563eb",
@@ -334,6 +340,17 @@ var THEME_DEFAULTS = {
334
340
  primaryLightColor: "#dbeafe",
335
341
  secondaryColor: "#64748b",
336
342
  accentColor: "#f59e0b",
343
+ // Foundations — global semantic text + border tokens.
344
+ // These are app-wide roles (not component-scoped) so host apps can map their
345
+ // own primary/secondary/muted text and default/subtle borders one-to-one.
346
+ // Defaults deliberately match the closest existing primitives so adopting
347
+ // them causes no visual shift (text-primary = ink-900, etc.).
348
+ textPrimary: "#0f172a",
349
+ textSecondary: "#64748b",
350
+ textMuted: "#94a3b8",
351
+ textInverse: "#ffffff",
352
+ borderDefault: "#e2e8f0",
353
+ borderSubtle: "#f1f5f9",
337
354
  // Sidebar
338
355
  sidebarBg: "#ffffff",
339
356
  sidebarText: "#475569",
@@ -418,6 +435,13 @@ var THEME_KEY_TO_CSS = {
418
435
  primaryLightColor: "--color-brand-100",
419
436
  secondaryColor: "--color-ink-500",
420
437
  accentColor: "--color-accent",
438
+ // Foundations — global semantic text + border tokens
439
+ textPrimary: "--color-text-primary",
440
+ textSecondary: "--color-text-secondary",
441
+ textMuted: "--color-text-muted",
442
+ textInverse: "--color-text-inverse",
443
+ borderDefault: "--color-border-default",
444
+ borderSubtle: "--color-border-subtle",
421
445
  // Sidebar
422
446
  sidebarBg: "--color-sidebar-bg",
423
447
  sidebarText: "--color-sidebar-text",
@@ -498,6 +522,10 @@ var THEME_CATEGORIES = [
498
522
  label: "Brand",
499
523
  keys: ["primaryColor", "primaryHoverColor", "primaryLightColor", "secondaryColor", "accentColor"]
500
524
  },
525
+ {
526
+ label: "Foundations",
527
+ keys: ["textPrimary", "textSecondary", "textMuted", "textInverse", "borderDefault", "borderSubtle"]
528
+ },
501
529
  {
502
530
  label: "Sidebar",
503
531
  keys: ["sidebarBg", "sidebarText", "sidebarActiveBg"]
@@ -719,6 +747,14 @@ var SEMANTIC_COLOURS = [
719
747
  { cssVar: "--color-info", label: "Info", category: "colour", defaultValue: "#3b82f6", themeKey: "infoColor" },
720
748
  { cssVar: "--color-info-light", label: "Info Light", category: "colour", defaultValue: "#dbeafe", themeKey: "infoLightColor" }
721
749
  ];
750
+ var FOUNDATION_TOKENS = [
751
+ { cssVar: "--color-text-primary", label: "Text Primary", category: "colour", defaultValue: "#0f172a", references: "--color-ink-900", themeKey: "textPrimary" },
752
+ { cssVar: "--color-text-secondary", label: "Text Secondary", category: "colour", defaultValue: "#64748b", references: "--color-ink-500", themeKey: "textSecondary" },
753
+ { cssVar: "--color-text-muted", label: "Text Muted", category: "colour", defaultValue: "#94a3b8", references: "--color-ink-400", themeKey: "textMuted" },
754
+ { cssVar: "--color-text-inverse", label: "Text Inverse", category: "colour", defaultValue: "#ffffff", themeKey: "textInverse" },
755
+ { cssVar: "--color-border-default", label: "Border Default", category: "colour", defaultValue: "#e2e8f0", references: "--color-ink-200", themeKey: "borderDefault" },
756
+ { cssVar: "--color-border-subtle", label: "Border Subtle", category: "colour", defaultValue: "#f1f5f9", references: "--color-ink-100", themeKey: "borderSubtle" }
757
+ ];
722
758
  var SURFACE_TOKENS = [
723
759
  { cssVar: "--color-surface-page", label: "Page Background", category: "colour", defaultValue: "#f8fafc", references: "--color-ink-50", themeKey: "surfacePageColor" },
724
760
  { cssVar: "--color-surface-card", label: "Card Surface", category: "colour", defaultValue: "#ffffff", themeKey: "surfaceCardColor" },
@@ -853,6 +889,7 @@ var TOKEN_REGISTRY = [
853
889
  { label: "Accent Colours", tokens: ACCENT_PRIMITIVES },
854
890
  { label: "Sidebar", tokens: SIDEBAR_TOKENS },
855
891
  { label: "Semantic Colours", tokens: SEMANTIC_COLOURS },
892
+ { label: "Foundations (Text & Border)", tokens: FOUNDATION_TOKENS },
856
893
  { label: "Surface", tokens: SURFACE_TOKENS },
857
894
  { label: "Interactive", tokens: INTERACTIVE_TOKENS },
858
895
  { label: "Button", tokens: BUTTON_TOKENS },
@@ -2756,7 +2793,7 @@ function downloadAuditReport(report) {
2756
2793
  }
2757
2794
 
2758
2795
  // src/dom.ts
2759
- function applyThemeToDOM(merged) {
2796
+ function applyThemeToDOM(merged, customTokens = []) {
2760
2797
  const root = document.documentElement;
2761
2798
  if (merged.primaryColor) {
2762
2799
  merged.primaryColor = ensureContrastOnWhite(merged.primaryColor);
@@ -2793,12 +2830,23 @@ function applyThemeToDOM(merged) {
2793
2830
  const accent = merged.accentColor || THEME_DEFAULTS.accentColor;
2794
2831
  root.style.setProperty("--color-accent-light", lighten(accent, 0.85));
2795
2832
  root.style.setProperty("--color-accent-hover", darken(accent, 0.15));
2833
+ for (const token of customTokens) {
2834
+ const value = merged[token.key] ?? token.defaultValue;
2835
+ if (value) {
2836
+ root.style.setProperty(token.cssVar, value);
2837
+ } else {
2838
+ root.style.removeProperty(token.cssVar);
2839
+ }
2840
+ }
2796
2841
  }
2797
- function clearThemeFromDOM() {
2842
+ function clearThemeFromDOM(customTokens = []) {
2798
2843
  const root = document.documentElement;
2799
2844
  for (const cssVar of Object.values(THEME_KEY_TO_CSS)) {
2800
2845
  root.style.removeProperty(cssVar);
2801
2846
  }
2847
+ for (const token of customTokens) {
2848
+ root.style.removeProperty(token.cssVar);
2849
+ }
2802
2850
  for (const v of [
2803
2851
  "--color-sidebar-border",
2804
2852
  "--color-sidebar-hover",
@@ -3164,6 +3212,7 @@ function calculateQualityScore2(overrides) {
3164
3212
  createOverlay,
3165
3213
  createReassignmentState,
3166
3214
  createThemeEditorState,
3215
+ customTokenDefaults,
3167
3216
  darken,
3168
3217
  downloadAuditReport,
3169
3218
  downloadStyleGuide,
package/dist/index.d.cts CHANGED
@@ -140,6 +140,27 @@ declare function suggestPalettes(primaryHex: string): ColourSuggestion[];
140
140
  * These are the canonical defaults for the design system package.
141
141
  */
142
142
 
143
+ /**
144
+ * A host-defined theme token, declared by a consuming app so its own bespoke
145
+ * tokens flow through the SnagTag editor + DOM pipeline without forking the
146
+ * built-in maps. See docs/LAYER2-HOST-EXTENSIBLE-TOKENS-PROPOSAL.md.
147
+ */
148
+ interface CustomTokenDef {
149
+ /** Theme key used in the persisted overrides map + editor state (e.g. 'statusWatching'). */
150
+ key: string;
151
+ /** CSS custom property written to :root (e.g. '--status-watching'). */
152
+ cssVar: string;
153
+ /** Default colour value, used until the user overrides it. */
154
+ defaultValue: string;
155
+ /** Editor category to group the swatch under. Defaults to 'Custom'. */
156
+ category?: string;
157
+ /** Optional human label (the colour editor otherwise derives one from `key`). */
158
+ label?: string;
159
+ /** Optional CSS var this token references, for inspector chain tracing. */
160
+ references?: string;
161
+ }
162
+ /** Build a { key: defaultValue } map from custom token definitions. */
163
+ declare function customTokenDefaults(tokens?: CustomTokenDef[]): Record<string, string>;
143
164
  /**
144
165
  * The hardcoded defaults matching a standard design system theme.
145
166
  * These are the "factory" values used when no overrides are set.
@@ -803,13 +824,18 @@ declare function downloadAuditReport(report: AuditReport): void;
803
824
  * DOM utilities for applying and clearing theme values on the document root.
804
825
  * These functions set/remove CSS custom properties on document.documentElement.
805
826
  */
827
+
806
828
  /**
807
829
  * Apply a merged theme to the DOM by setting CSS custom properties on :root.
808
830
  * Derives sidebar states and accent variants automatically.
831
+ *
832
+ * Pass `customTokens` to also write host-defined tokens (each `cssVar` is set
833
+ * from `merged[key]`, falling back to the token's `defaultValue`). Omitting it
834
+ * leaves behaviour identical to before.
809
835
  */
810
- declare function applyThemeToDOM(merged: Record<string, string>): void;
836
+ declare function applyThemeToDOM(merged: Record<string, string>, customTokens?: CustomTokenDef[]): void;
811
837
  /** Remove all theme overrides from :root, restoring CSS defaults. */
812
- declare function clearThemeFromDOM(): void;
838
+ declare function clearThemeFromDOM(customTokens?: CustomTokenDef[]): void;
813
839
 
814
840
  /**
815
841
  * Contrast Fix Engine - scans colour token pairs for WCAG AA failures
@@ -881,4 +907,4 @@ interface QualityBreakdown {
881
907
  */
882
908
  declare function calculateQualityScore(overrides?: Record<string, string>): QualityBreakdown;
883
909
 
884
- export { type ConsistencyIssue$1 as AuditConsistencyIssue, type ContrastIssue$1 as AuditContrastIssue, type QualityBreakdown$1 as AuditQualityBreakdown, type AuditReport, BUILT_IN_PRESETS, COLOUR_BLINDNESS_TYPES, type ColourBlindnessInfo, type ColourBlindnessType, type ColourSuggestion, type ConsistencyIssue, type ContrastIssue$2 as ContrastIssue, type CustomPreset, DENSITY_CONFIGS, type DarkModeConfig, type DensityConfig, type DensityMode, type DesignSystemAdapter, type ThemePreset as DesignThemePreset, EASING_PRESETS, type EasingPreset, type ExtractedTokenDef, FONT_PAIRINGS, type FontPairing, type HSL, type HarmonyType, type QualityBreakdown$2 as QualityBreakdown, type ReassignmentAction, type ReassignmentState, type RegistryOverlay, SCALE_RATIOS, SURFACE_DEFINITIONS, type ScaleRatio, type SurfaceDefinition, type SurfaceType, THEME_CATEGORIES, THEME_DEFAULTS, THEME_KEY_TO_CSS, TOKEN_REGISTRY, type ThemeEditorState, type ThemeExport, type ThemeExportPayload, type ThemePreset$1 as ThemePreset, type ThemeSnapshot, type ThemeVersion, type TokenCategory, type TokenDefinition, type TokenUsageResult, type TypeScale, type TypeScaleLevel, type UnusedTokenResult, addCustomCategory, addExtractedToken, adjustSemanticForDark, applyAddCategory, applyBulkChange, applyBulkMove, applyChange, applyDarkModeToDOM, applyDensity, applyDensityToDOM, applyExtract, applyMove, applySurface, applySurfaceToDOM, applyThemeToDOM, auditReportToMarkdown, bulkMoveTokens, calculateQualityScore, captureSnapshot, checkConsistency, clampControlPoint, clearSnapshots, clearSurface, clearThemeFromDOM, clearUsageCache, contrastRatio, countTokenUsage, createOverlay, createReassignmentState, createThemeEditorState, darken, downloadAuditReport, downloadStyleGuide, downloadThemeAsJSON, downloadW3CTokens, ensureContrastOnWhite, exportTheme, exportToW3CFormat, extractToken, findContrastIssues, findPreset, findPresetByValue, findToken, findUnusedTokens, formatCubicBezier, generateAuditReport, generateDarkTheme, generateScale, generateStyleGuide, generateTypeScale, getActiveDensity, getActiveSurface, getAllCategoryLabels, getDensityCSS, getDependents, getEffectiveCategories, getOpeningSnapshot, getPresetsByCategory, getSnapshot, getSurfaceDefinition, getSurfaceOverrides, getTokenCategory, getTokenChain, getTokenUsageCount, getTokenUsageStats, hasExtractedToken, hexToHSL, hexToHsl, hslToHex$1 as hslToHex, hslToHex as hslToHexDark, invertLightness, isDark, isDarkMode, lighten, luminance, makePreset, markSaved, moveToken, parseCubicBezier, readSnapshots, readThemeFromFile, redo, redoReassignment, resetToDefaults, resolveMode, rotateHue, sampleBezierCurve, setDarkMode, simulateColourBlindness, simulateThemeColourBlindness, snapToGrid, suggestFix, suggestPairings, suggestPalettes, suggestTokenName, systemPrefersDark, themesAreEqual, typeScaleToCSSVars, undo, undoReassignment, validateImport, validateTokenName };
910
+ export { type ConsistencyIssue$1 as AuditConsistencyIssue, type ContrastIssue$1 as AuditContrastIssue, type QualityBreakdown$1 as AuditQualityBreakdown, type AuditReport, BUILT_IN_PRESETS, COLOUR_BLINDNESS_TYPES, type ColourBlindnessInfo, type ColourBlindnessType, type ColourSuggestion, type ConsistencyIssue, type ContrastIssue$2 as ContrastIssue, type CustomPreset, type CustomTokenDef, DENSITY_CONFIGS, type DarkModeConfig, type DensityConfig, type DensityMode, type DesignSystemAdapter, type ThemePreset as DesignThemePreset, EASING_PRESETS, type EasingPreset, type ExtractedTokenDef, FONT_PAIRINGS, type FontPairing, type HSL, type HarmonyType, type QualityBreakdown$2 as QualityBreakdown, type ReassignmentAction, type ReassignmentState, type RegistryOverlay, SCALE_RATIOS, SURFACE_DEFINITIONS, type ScaleRatio, type SurfaceDefinition, type SurfaceType, THEME_CATEGORIES, THEME_DEFAULTS, THEME_KEY_TO_CSS, TOKEN_REGISTRY, type ThemeEditorState, type ThemeExport, type ThemeExportPayload, type ThemePreset$1 as ThemePreset, type ThemeSnapshot, type ThemeVersion, type TokenCategory, type TokenDefinition, type TokenUsageResult, type TypeScale, type TypeScaleLevel, type UnusedTokenResult, addCustomCategory, addExtractedToken, adjustSemanticForDark, applyAddCategory, applyBulkChange, applyBulkMove, applyChange, applyDarkModeToDOM, applyDensity, applyDensityToDOM, applyExtract, applyMove, applySurface, applySurfaceToDOM, applyThemeToDOM, auditReportToMarkdown, bulkMoveTokens, calculateQualityScore, captureSnapshot, checkConsistency, clampControlPoint, clearSnapshots, clearSurface, clearThemeFromDOM, clearUsageCache, contrastRatio, countTokenUsage, createOverlay, createReassignmentState, createThemeEditorState, customTokenDefaults, darken, downloadAuditReport, downloadStyleGuide, downloadThemeAsJSON, downloadW3CTokens, ensureContrastOnWhite, exportTheme, exportToW3CFormat, extractToken, findContrastIssues, findPreset, findPresetByValue, findToken, findUnusedTokens, formatCubicBezier, generateAuditReport, generateDarkTheme, generateScale, generateStyleGuide, generateTypeScale, getActiveDensity, getActiveSurface, getAllCategoryLabels, getDensityCSS, getDependents, getEffectiveCategories, getOpeningSnapshot, getPresetsByCategory, getSnapshot, getSurfaceDefinition, getSurfaceOverrides, getTokenCategory, getTokenChain, getTokenUsageCount, getTokenUsageStats, hasExtractedToken, hexToHSL, hexToHsl, hslToHex$1 as hslToHex, hslToHex as hslToHexDark, invertLightness, isDark, isDarkMode, lighten, luminance, makePreset, markSaved, moveToken, parseCubicBezier, readSnapshots, readThemeFromFile, redo, redoReassignment, resetToDefaults, resolveMode, rotateHue, sampleBezierCurve, setDarkMode, simulateColourBlindness, simulateThemeColourBlindness, snapToGrid, suggestFix, suggestPairings, suggestPalettes, suggestTokenName, systemPrefersDark, themesAreEqual, typeScaleToCSSVars, undo, undoReassignment, validateImport, validateTokenName };
package/dist/index.d.ts CHANGED
@@ -140,6 +140,27 @@ declare function suggestPalettes(primaryHex: string): ColourSuggestion[];
140
140
  * These are the canonical defaults for the design system package.
141
141
  */
142
142
 
143
+ /**
144
+ * A host-defined theme token, declared by a consuming app so its own bespoke
145
+ * tokens flow through the SnagTag editor + DOM pipeline without forking the
146
+ * built-in maps. See docs/LAYER2-HOST-EXTENSIBLE-TOKENS-PROPOSAL.md.
147
+ */
148
+ interface CustomTokenDef {
149
+ /** Theme key used in the persisted overrides map + editor state (e.g. 'statusWatching'). */
150
+ key: string;
151
+ /** CSS custom property written to :root (e.g. '--status-watching'). */
152
+ cssVar: string;
153
+ /** Default colour value, used until the user overrides it. */
154
+ defaultValue: string;
155
+ /** Editor category to group the swatch under. Defaults to 'Custom'. */
156
+ category?: string;
157
+ /** Optional human label (the colour editor otherwise derives one from `key`). */
158
+ label?: string;
159
+ /** Optional CSS var this token references, for inspector chain tracing. */
160
+ references?: string;
161
+ }
162
+ /** Build a { key: defaultValue } map from custom token definitions. */
163
+ declare function customTokenDefaults(tokens?: CustomTokenDef[]): Record<string, string>;
143
164
  /**
144
165
  * The hardcoded defaults matching a standard design system theme.
145
166
  * These are the "factory" values used when no overrides are set.
@@ -803,13 +824,18 @@ declare function downloadAuditReport(report: AuditReport): void;
803
824
  * DOM utilities for applying and clearing theme values on the document root.
804
825
  * These functions set/remove CSS custom properties on document.documentElement.
805
826
  */
827
+
806
828
  /**
807
829
  * Apply a merged theme to the DOM by setting CSS custom properties on :root.
808
830
  * Derives sidebar states and accent variants automatically.
831
+ *
832
+ * Pass `customTokens` to also write host-defined tokens (each `cssVar` is set
833
+ * from `merged[key]`, falling back to the token's `defaultValue`). Omitting it
834
+ * leaves behaviour identical to before.
809
835
  */
810
- declare function applyThemeToDOM(merged: Record<string, string>): void;
836
+ declare function applyThemeToDOM(merged: Record<string, string>, customTokens?: CustomTokenDef[]): void;
811
837
  /** Remove all theme overrides from :root, restoring CSS defaults. */
812
- declare function clearThemeFromDOM(): void;
838
+ declare function clearThemeFromDOM(customTokens?: CustomTokenDef[]): void;
813
839
 
814
840
  /**
815
841
  * Contrast Fix Engine - scans colour token pairs for WCAG AA failures
@@ -881,4 +907,4 @@ interface QualityBreakdown {
881
907
  */
882
908
  declare function calculateQualityScore(overrides?: Record<string, string>): QualityBreakdown;
883
909
 
884
- export { type ConsistencyIssue$1 as AuditConsistencyIssue, type ContrastIssue$1 as AuditContrastIssue, type QualityBreakdown$1 as AuditQualityBreakdown, type AuditReport, BUILT_IN_PRESETS, COLOUR_BLINDNESS_TYPES, type ColourBlindnessInfo, type ColourBlindnessType, type ColourSuggestion, type ConsistencyIssue, type ContrastIssue$2 as ContrastIssue, type CustomPreset, DENSITY_CONFIGS, type DarkModeConfig, type DensityConfig, type DensityMode, type DesignSystemAdapter, type ThemePreset as DesignThemePreset, EASING_PRESETS, type EasingPreset, type ExtractedTokenDef, FONT_PAIRINGS, type FontPairing, type HSL, type HarmonyType, type QualityBreakdown$2 as QualityBreakdown, type ReassignmentAction, type ReassignmentState, type RegistryOverlay, SCALE_RATIOS, SURFACE_DEFINITIONS, type ScaleRatio, type SurfaceDefinition, type SurfaceType, THEME_CATEGORIES, THEME_DEFAULTS, THEME_KEY_TO_CSS, TOKEN_REGISTRY, type ThemeEditorState, type ThemeExport, type ThemeExportPayload, type ThemePreset$1 as ThemePreset, type ThemeSnapshot, type ThemeVersion, type TokenCategory, type TokenDefinition, type TokenUsageResult, type TypeScale, type TypeScaleLevel, type UnusedTokenResult, addCustomCategory, addExtractedToken, adjustSemanticForDark, applyAddCategory, applyBulkChange, applyBulkMove, applyChange, applyDarkModeToDOM, applyDensity, applyDensityToDOM, applyExtract, applyMove, applySurface, applySurfaceToDOM, applyThemeToDOM, auditReportToMarkdown, bulkMoveTokens, calculateQualityScore, captureSnapshot, checkConsistency, clampControlPoint, clearSnapshots, clearSurface, clearThemeFromDOM, clearUsageCache, contrastRatio, countTokenUsage, createOverlay, createReassignmentState, createThemeEditorState, darken, downloadAuditReport, downloadStyleGuide, downloadThemeAsJSON, downloadW3CTokens, ensureContrastOnWhite, exportTheme, exportToW3CFormat, extractToken, findContrastIssues, findPreset, findPresetByValue, findToken, findUnusedTokens, formatCubicBezier, generateAuditReport, generateDarkTheme, generateScale, generateStyleGuide, generateTypeScale, getActiveDensity, getActiveSurface, getAllCategoryLabels, getDensityCSS, getDependents, getEffectiveCategories, getOpeningSnapshot, getPresetsByCategory, getSnapshot, getSurfaceDefinition, getSurfaceOverrides, getTokenCategory, getTokenChain, getTokenUsageCount, getTokenUsageStats, hasExtractedToken, hexToHSL, hexToHsl, hslToHex$1 as hslToHex, hslToHex as hslToHexDark, invertLightness, isDark, isDarkMode, lighten, luminance, makePreset, markSaved, moveToken, parseCubicBezier, readSnapshots, readThemeFromFile, redo, redoReassignment, resetToDefaults, resolveMode, rotateHue, sampleBezierCurve, setDarkMode, simulateColourBlindness, simulateThemeColourBlindness, snapToGrid, suggestFix, suggestPairings, suggestPalettes, suggestTokenName, systemPrefersDark, themesAreEqual, typeScaleToCSSVars, undo, undoReassignment, validateImport, validateTokenName };
910
+ export { type ConsistencyIssue$1 as AuditConsistencyIssue, type ContrastIssue$1 as AuditContrastIssue, type QualityBreakdown$1 as AuditQualityBreakdown, type AuditReport, BUILT_IN_PRESETS, COLOUR_BLINDNESS_TYPES, type ColourBlindnessInfo, type ColourBlindnessType, type ColourSuggestion, type ConsistencyIssue, type ContrastIssue$2 as ContrastIssue, type CustomPreset, type CustomTokenDef, DENSITY_CONFIGS, type DarkModeConfig, type DensityConfig, type DensityMode, type DesignSystemAdapter, type ThemePreset as DesignThemePreset, EASING_PRESETS, type EasingPreset, type ExtractedTokenDef, FONT_PAIRINGS, type FontPairing, type HSL, type HarmonyType, type QualityBreakdown$2 as QualityBreakdown, type ReassignmentAction, type ReassignmentState, type RegistryOverlay, SCALE_RATIOS, SURFACE_DEFINITIONS, type ScaleRatio, type SurfaceDefinition, type SurfaceType, THEME_CATEGORIES, THEME_DEFAULTS, THEME_KEY_TO_CSS, TOKEN_REGISTRY, type ThemeEditorState, type ThemeExport, type ThemeExportPayload, type ThemePreset$1 as ThemePreset, type ThemeSnapshot, type ThemeVersion, type TokenCategory, type TokenDefinition, type TokenUsageResult, type TypeScale, type TypeScaleLevel, type UnusedTokenResult, addCustomCategory, addExtractedToken, adjustSemanticForDark, applyAddCategory, applyBulkChange, applyBulkMove, applyChange, applyDarkModeToDOM, applyDensity, applyDensityToDOM, applyExtract, applyMove, applySurface, applySurfaceToDOM, applyThemeToDOM, auditReportToMarkdown, bulkMoveTokens, calculateQualityScore, captureSnapshot, checkConsistency, clampControlPoint, clearSnapshots, clearSurface, clearThemeFromDOM, clearUsageCache, contrastRatio, countTokenUsage, createOverlay, createReassignmentState, createThemeEditorState, customTokenDefaults, darken, downloadAuditReport, downloadStyleGuide, downloadThemeAsJSON, downloadW3CTokens, ensureContrastOnWhite, exportTheme, exportToW3CFormat, extractToken, findContrastIssues, findPreset, findPresetByValue, findToken, findUnusedTokens, formatCubicBezier, generateAuditReport, generateDarkTheme, generateScale, generateStyleGuide, generateTypeScale, getActiveDensity, getActiveSurface, getAllCategoryLabels, getDensityCSS, getDependents, getEffectiveCategories, getOpeningSnapshot, getPresetsByCategory, getSnapshot, getSurfaceDefinition, getSurfaceOverrides, getTokenCategory, getTokenChain, getTokenUsageCount, getTokenUsageStats, hasExtractedToken, hexToHSL, hexToHsl, hslToHex$1 as hslToHex, hslToHex as hslToHexDark, invertLightness, isDark, isDarkMode, lighten, luminance, makePreset, markSaved, moveToken, parseCubicBezier, readSnapshots, readThemeFromFile, redo, redoReassignment, resetToDefaults, resolveMode, rotateHue, sampleBezierCurve, setDarkMode, simulateColourBlindness, simulateThemeColourBlindness, snapToGrid, suggestFix, suggestPairings, suggestPalettes, suggestTokenName, systemPrefersDark, themesAreEqual, typeScaleToCSSVars, undo, undoReassignment, validateImport, validateTokenName };
package/dist/index.js CHANGED
@@ -189,6 +189,11 @@ function suggestPalettes(primaryHex) {
189
189
  }
190
190
 
191
191
  // src/theme-defaults.ts
192
+ function customTokenDefaults(tokens = []) {
193
+ const out = {};
194
+ for (const t of tokens) out[t.key] = t.defaultValue;
195
+ return out;
196
+ }
192
197
  var THEME_DEFAULTS = {
193
198
  // Primitives
194
199
  primaryColor: "#2563eb",
@@ -196,6 +201,17 @@ var THEME_DEFAULTS = {
196
201
  primaryLightColor: "#dbeafe",
197
202
  secondaryColor: "#64748b",
198
203
  accentColor: "#f59e0b",
204
+ // Foundations — global semantic text + border tokens.
205
+ // These are app-wide roles (not component-scoped) so host apps can map their
206
+ // own primary/secondary/muted text and default/subtle borders one-to-one.
207
+ // Defaults deliberately match the closest existing primitives so adopting
208
+ // them causes no visual shift (text-primary = ink-900, etc.).
209
+ textPrimary: "#0f172a",
210
+ textSecondary: "#64748b",
211
+ textMuted: "#94a3b8",
212
+ textInverse: "#ffffff",
213
+ borderDefault: "#e2e8f0",
214
+ borderSubtle: "#f1f5f9",
199
215
  // Sidebar
200
216
  sidebarBg: "#ffffff",
201
217
  sidebarText: "#475569",
@@ -280,6 +296,13 @@ var THEME_KEY_TO_CSS = {
280
296
  primaryLightColor: "--color-brand-100",
281
297
  secondaryColor: "--color-ink-500",
282
298
  accentColor: "--color-accent",
299
+ // Foundations — global semantic text + border tokens
300
+ textPrimary: "--color-text-primary",
301
+ textSecondary: "--color-text-secondary",
302
+ textMuted: "--color-text-muted",
303
+ textInverse: "--color-text-inverse",
304
+ borderDefault: "--color-border-default",
305
+ borderSubtle: "--color-border-subtle",
283
306
  // Sidebar
284
307
  sidebarBg: "--color-sidebar-bg",
285
308
  sidebarText: "--color-sidebar-text",
@@ -360,6 +383,10 @@ var THEME_CATEGORIES = [
360
383
  label: "Brand",
361
384
  keys: ["primaryColor", "primaryHoverColor", "primaryLightColor", "secondaryColor", "accentColor"]
362
385
  },
386
+ {
387
+ label: "Foundations",
388
+ keys: ["textPrimary", "textSecondary", "textMuted", "textInverse", "borderDefault", "borderSubtle"]
389
+ },
363
390
  {
364
391
  label: "Sidebar",
365
392
  keys: ["sidebarBg", "sidebarText", "sidebarActiveBg"]
@@ -581,6 +608,14 @@ var SEMANTIC_COLOURS = [
581
608
  { cssVar: "--color-info", label: "Info", category: "colour", defaultValue: "#3b82f6", themeKey: "infoColor" },
582
609
  { cssVar: "--color-info-light", label: "Info Light", category: "colour", defaultValue: "#dbeafe", themeKey: "infoLightColor" }
583
610
  ];
611
+ var FOUNDATION_TOKENS = [
612
+ { cssVar: "--color-text-primary", label: "Text Primary", category: "colour", defaultValue: "#0f172a", references: "--color-ink-900", themeKey: "textPrimary" },
613
+ { cssVar: "--color-text-secondary", label: "Text Secondary", category: "colour", defaultValue: "#64748b", references: "--color-ink-500", themeKey: "textSecondary" },
614
+ { cssVar: "--color-text-muted", label: "Text Muted", category: "colour", defaultValue: "#94a3b8", references: "--color-ink-400", themeKey: "textMuted" },
615
+ { cssVar: "--color-text-inverse", label: "Text Inverse", category: "colour", defaultValue: "#ffffff", themeKey: "textInverse" },
616
+ { cssVar: "--color-border-default", label: "Border Default", category: "colour", defaultValue: "#e2e8f0", references: "--color-ink-200", themeKey: "borderDefault" },
617
+ { cssVar: "--color-border-subtle", label: "Border Subtle", category: "colour", defaultValue: "#f1f5f9", references: "--color-ink-100", themeKey: "borderSubtle" }
618
+ ];
584
619
  var SURFACE_TOKENS = [
585
620
  { cssVar: "--color-surface-page", label: "Page Background", category: "colour", defaultValue: "#f8fafc", references: "--color-ink-50", themeKey: "surfacePageColor" },
586
621
  { cssVar: "--color-surface-card", label: "Card Surface", category: "colour", defaultValue: "#ffffff", themeKey: "surfaceCardColor" },
@@ -715,6 +750,7 @@ var TOKEN_REGISTRY = [
715
750
  { label: "Accent Colours", tokens: ACCENT_PRIMITIVES },
716
751
  { label: "Sidebar", tokens: SIDEBAR_TOKENS },
717
752
  { label: "Semantic Colours", tokens: SEMANTIC_COLOURS },
753
+ { label: "Foundations (Text & Border)", tokens: FOUNDATION_TOKENS },
718
754
  { label: "Surface", tokens: SURFACE_TOKENS },
719
755
  { label: "Interactive", tokens: INTERACTIVE_TOKENS },
720
756
  { label: "Button", tokens: BUTTON_TOKENS },
@@ -2618,7 +2654,7 @@ function downloadAuditReport(report) {
2618
2654
  }
2619
2655
 
2620
2656
  // src/dom.ts
2621
- function applyThemeToDOM(merged) {
2657
+ function applyThemeToDOM(merged, customTokens = []) {
2622
2658
  const root = document.documentElement;
2623
2659
  if (merged.primaryColor) {
2624
2660
  merged.primaryColor = ensureContrastOnWhite(merged.primaryColor);
@@ -2655,12 +2691,23 @@ function applyThemeToDOM(merged) {
2655
2691
  const accent = merged.accentColor || THEME_DEFAULTS.accentColor;
2656
2692
  root.style.setProperty("--color-accent-light", lighten(accent, 0.85));
2657
2693
  root.style.setProperty("--color-accent-hover", darken(accent, 0.15));
2694
+ for (const token of customTokens) {
2695
+ const value = merged[token.key] ?? token.defaultValue;
2696
+ if (value) {
2697
+ root.style.setProperty(token.cssVar, value);
2698
+ } else {
2699
+ root.style.removeProperty(token.cssVar);
2700
+ }
2701
+ }
2658
2702
  }
2659
- function clearThemeFromDOM() {
2703
+ function clearThemeFromDOM(customTokens = []) {
2660
2704
  const root = document.documentElement;
2661
2705
  for (const cssVar of Object.values(THEME_KEY_TO_CSS)) {
2662
2706
  root.style.removeProperty(cssVar);
2663
2707
  }
2708
+ for (const token of customTokens) {
2709
+ root.style.removeProperty(token.cssVar);
2710
+ }
2664
2711
  for (const v of [
2665
2712
  "--color-sidebar-border",
2666
2713
  "--color-sidebar-hover",
@@ -3025,6 +3072,7 @@ export {
3025
3072
  createOverlay,
3026
3073
  createReassignmentState,
3027
3074
  createThemeEditorState,
3075
+ customTokenDefaults,
3028
3076
  darken,
3029
3077
  downloadAuditReport,
3030
3078
  downloadStyleGuide,
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@snagtag/design-system",
3
- "version": "0.1.0",
4
- "buildTimestamp": "2026-06-09T21:34:53.445Z",
5
- "contentHash": "2effc038e3d2626a",
3
+ "version": "0.2.3",
4
+ "buildTimestamp": "2026-06-14T12:39:20.596Z",
5
+ "contentHash": "2a8368cc6251997e",
6
6
  "changes": [],
7
7
  "breaking": false,
8
8
  "siblings": {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snagtag/design-system",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",