@ankhorage/surface 1.0.0 → 1.0.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @ankhorage/surface
2
2
 
3
+ ## 1.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - de83ae5: Consume `@ankhorage/color-theory` semantic status helpers for danger/success/warning roles.
8
+
9
+ ## 1.0.1
10
+
11
+ ### Patch Changes
12
+
13
+ - c0c242d: update package
14
+
3
15
  ## 1.0.0
4
16
 
5
17
  ### Major Changes
@@ -1 +1 @@
1
- {"version":3,"file":"colorEngine.d.ts","sourceRoot":"","sources":["../../src/theme/colorEngine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,wBAAwB,EACxB,sBAAsB,EACtB,QAAQ,EACR,yBAAyB,EACzB,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AAOjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EAOV,cAAc,EACf,MAAM,SAAS,CAAC;AAOjB;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;AAEzE,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,wBAAwB,EACnC,UAAU,EAAE,yBAAyB,GACpC,qBAAqB,CAUvB;AA8DD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,WAAW,EACnB,IAAI,GAAE,OAAO,GAAG,MAAgB,GAC/B;IACD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,QAAQ,EAAE,sBAAsB,CAAC;IACjC,SAAS,EAAE,cAAc,CAAC;CAC3B,CAsFA"}
1
+ {"version":3,"file":"colorEngine.d.ts","sourceRoot":"","sources":["../../src/theme/colorEngine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,wBAAwB,EACxB,sBAAsB,EACtB,QAAQ,EACR,yBAAyB,EACzB,kBAAkB,EACnB,MAAM,yBAAyB,CAAC;AAOjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EAOV,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;AAEzE,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,wBAAwB,EACnC,UAAU,EAAE,yBAAyB,GACpC,qBAAqB,CAUvB;AA8DD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,WAAW,EACnB,IAAI,GAAE,OAAO,GAAG,MAAgB,GAC/B;IACD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,QAAQ,EAAE,sBAAsB,CAAC;IACjC,SAAS,EAAE,cAAc,CAAC;CAC3B,CAoFA"}
@@ -1,8 +1,4 @@
1
- import { generateColorSwatch, generateThemeModeColors, getReadableForeground, parseHexColorOrThrow, } from '@ankhorage/color-theory';
2
- // Fixed hex values for semantic status colors (not theme-generated)
3
- const DANGER_HEX = parseHexColorOrThrow('#ef4444');
4
- const SUCCESS_HEX = parseHexColorOrThrow('#22c55e');
5
- const WARNING_HEX = parseHexColorOrThrow('#f59e0b');
1
+ import { createDefaultSemanticStatusSwatches, generateThemeModeColors, getReadableForeground, parseHexColorOrThrow, } from '@ankhorage/color-theory';
6
2
  export function resolveSemanticColors(generated, references) {
7
3
  return Object.fromEntries(Object.entries(references).map(([token, ref]) => {
8
4
  const swatch = generated.swatches[ref.role];
@@ -82,12 +78,10 @@ export function generatePalette(config, mode = 'light') {
82
78
  const secondarySwatch = swatches.secondary ?? swatches.primary;
83
79
  const tertiarySwatch = swatches.tertiary ?? swatches.primary;
84
80
  const quaternarySwatch = swatches.quaternary ?? swatches.primary;
85
- const dangerSwatch = generateColorSwatch(DANGER_HEX).swatch;
86
- const successSwatch = generateColorSwatch(SUCCESS_HEX).swatch;
87
- const warningSwatch = generateColorSwatch(WARNING_HEX).swatch;
88
- const danger = buildRoleSemantics(dangerSwatch, isDark);
89
- const success = buildRoleSemantics(successSwatch, isDark);
90
- const warning = buildRoleSemantics(warningSwatch, isDark);
81
+ const semanticStatusSwatches = createDefaultSemanticStatusSwatches().swatches;
82
+ const danger = buildRoleSemantics(semanticStatusSwatches.danger, isDark);
83
+ const success = buildRoleSemantics(semanticStatusSwatches.success, isDark);
84
+ const warning = buildRoleSemantics(semanticStatusSwatches.warning, isDark);
91
85
  const surfaceSemantics = {
92
86
  default: neutral.surface,
93
87
  subtle: neutral.bgSubtle,
@@ -1 +1 @@
1
- {"version":3,"file":"colorEngine.js","sourceRoot":"","sources":["../../src/theme/colorEngine.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ColorSwatch,\n GeneratedThemeModeColors,\n GeneratedThemeSwatches,\n HexColor,\n SemanticColorReferenceMap,\n SemanticColorToken,\n} from '@ankhorage/color-theory';\nimport {\n generateColorSwatch,\n generateThemeModeColors,\n getReadableForeground,\n parseHexColorOrThrow,\n} from '@ankhorage/color-theory';\nimport type { ThemeConfig } from '@ankhorage/contracts';\n\nimport type {\n ActionSemantics,\n BorderSemantics,\n ContentSemantics,\n NeutralSemantics,\n RoleSemantics,\n SurfaceSemantics,\n ThemeSemantics,\n} from './types';\n\n// Fixed hex values for semantic status colors (not theme-generated)\nconst DANGER_HEX = parseHexColorOrThrow('#ef4444');\nconst SUCCESS_HEX = parseHexColorOrThrow('#22c55e');\nconst WARNING_HEX = parseHexColorOrThrow('#f59e0b');\n\n/**\n * Surface semantic resolver: maps color-theory SemanticColorToken references\n * to hex values from the generated swatches.\n */\nexport type SurfaceSemanticColors = Record<SemanticColorToken, HexColor>;\n\nexport function resolveSemanticColors(\n generated: GeneratedThemeModeColors,\n references: SemanticColorReferenceMap,\n): SurfaceSemanticColors {\n return Object.fromEntries(\n Object.entries(references).map(([token, ref]) => {\n const swatch = generated.swatches[ref.role];\n if (!swatch) {\n throw new Error(`Missing swatch for role '${ref.role}' (token: '${token}')`);\n }\n return [token, swatch[ref.step]];\n }),\n ) as SurfaceSemanticColors;\n}\n\nfunction buildNeutralSemantics(neutralSwatch: ColorSwatch, isDark: boolean): NeutralSemantics {\n if (isDark) {\n return {\n bg: neutralSwatch[950],\n bgSubtle: neutralSwatch[900],\n surface: neutralSwatch[900],\n surfaceHover: neutralSwatch[800],\n surfaceActive: neutralSwatch[700],\n border: neutralSwatch[800],\n borderStrong: neutralSwatch[600],\n divider: neutralSwatch[800],\n text: neutralSwatch[50],\n textMuted: neutralSwatch[200],\n textSubtle: neutralSwatch[300],\n };\n }\n return {\n bg: neutralSwatch[50],\n bgSubtle: neutralSwatch[100],\n surface: neutralSwatch[100],\n surfaceHover: neutralSwatch[200],\n surfaceActive: neutralSwatch[300],\n border: neutralSwatch[200],\n borderStrong: neutralSwatch[300],\n divider: neutralSwatch[200],\n text: neutralSwatch[900],\n textMuted: neutralSwatch[700],\n textSubtle: neutralSwatch[600],\n };\n}\n\nfunction buildRoleSemantics(swatch: ColorSwatch, isDark: boolean): RoleSemantics {\n const base = swatch[500];\n const { foreground: onSolidText } = getReadableForeground(base);\n\n if (isDark) {\n return {\n base,\n hover: swatch[400],\n strong: swatch[300],\n softBg: swatch[900],\n softHover: swatch[800],\n softActive: swatch[700],\n outline: swatch[500],\n onSolidText,\n };\n }\n\n return {\n base,\n hover: swatch[600],\n strong: swatch[700],\n softBg: swatch[100],\n softHover: swatch[200],\n softActive: swatch[300],\n outline: swatch[400],\n onSolidText,\n };\n}\n\nexport function generatePalette(\n config: ThemeConfig,\n mode: 'light' | 'dark' = 'light',\n): {\n colors: Record<string, string>;\n swatches: GeneratedThemeSwatches;\n semantics: ThemeSemantics;\n} {\n const modeConfig = mode === 'dark' ? config.dark : config.light;\n const isDark = mode === 'dark';\n\n // Throws deterministically on invalid primary color\n parseHexColorOrThrow(modeConfig.primaryColor);\n\n const generated = generateThemeModeColors(modeConfig);\n\n const { swatches } = generated;\n const neutralSwatch = swatches.neutral;\n\n const neutral = buildNeutralSemantics(neutralSwatch, isDark);\n const brand = buildRoleSemantics(swatches.primary, isDark);\n\n // Fallback to primary swatch for missing ordinal roles\n const secondarySwatch = swatches.secondary ?? swatches.primary;\n const tertiarySwatch = swatches.tertiary ?? swatches.primary;\n const quaternarySwatch = swatches.quaternary ?? swatches.primary;\n\n const dangerSwatch = generateColorSwatch(DANGER_HEX).swatch;\n const successSwatch = generateColorSwatch(SUCCESS_HEX).swatch;\n const warningSwatch = generateColorSwatch(WARNING_HEX).swatch;\n\n const danger = buildRoleSemantics(dangerSwatch, isDark);\n const success = buildRoleSemantics(successSwatch, isDark);\n const warning = buildRoleSemantics(warningSwatch, isDark);\n\n const surfaceSemantics: SurfaceSemantics = {\n default: neutral.surface,\n subtle: neutral.bgSubtle,\n raised: neutral.surface,\n };\n\n const content: ContentSemantics = {\n default: neutral.text,\n muted: neutral.textMuted,\n subtle: neutral.textSubtle,\n inverse: brand.onSolidText,\n };\n\n const border: BorderSemantics = {\n default: neutral.border,\n strong: neutral.borderStrong,\n focus: brand.outline,\n };\n\n const action: ActionSemantics = {\n primary: brand,\n neutral: buildRoleSemantics(neutralSwatch, isDark),\n danger,\n };\n\n const colors: Record<string, string> = {\n primary: brand.base,\n secondary: secondarySwatch[500],\n accent: tertiarySwatch[500],\n highlight: quaternarySwatch[500],\n background: neutral.bg,\n surface: neutral.surface,\n text: neutral.text,\n textSecondary: neutral.textMuted,\n border: neutral.border,\n error: danger.base,\n success: success.base,\n warning: warning.base,\n };\n\n return {\n colors,\n swatches,\n semantics: {\n neutral,\n brand,\n secondary: buildRoleSemantics(secondarySwatch, isDark),\n accent: buildRoleSemantics(tertiarySwatch, isDark),\n highlight: buildRoleSemantics(quaternarySwatch, isDark),\n danger,\n success,\n warning,\n surface: surfaceSemantics,\n content,\n border,\n action,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"colorEngine.js","sourceRoot":"","sources":["../../src/theme/colorEngine.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ColorSwatch,\n GeneratedThemeModeColors,\n GeneratedThemeSwatches,\n HexColor,\n SemanticColorReferenceMap,\n SemanticColorToken,\n} from '@ankhorage/color-theory';\nimport {\n createDefaultSemanticStatusSwatches,\n generateThemeModeColors,\n getReadableForeground,\n parseHexColorOrThrow,\n} from '@ankhorage/color-theory';\nimport type { ThemeConfig } from '@ankhorage/contracts';\n\nimport type {\n ActionSemantics,\n BorderSemantics,\n ContentSemantics,\n NeutralSemantics,\n RoleSemantics,\n SurfaceSemantics,\n ThemeSemantics,\n} from './types';\n\n/**\n * Surface semantic resolver: maps color-theory SemanticColorToken references\n * to hex values from the generated swatches.\n */\nexport type SurfaceSemanticColors = Record<SemanticColorToken, HexColor>;\n\nexport function resolveSemanticColors(\n generated: GeneratedThemeModeColors,\n references: SemanticColorReferenceMap,\n): SurfaceSemanticColors {\n return Object.fromEntries(\n Object.entries(references).map(([token, ref]) => {\n const swatch = generated.swatches[ref.role];\n if (!swatch) {\n throw new Error(`Missing swatch for role '${ref.role}' (token: '${token}')`);\n }\n return [token, swatch[ref.step]];\n }),\n ) as SurfaceSemanticColors;\n}\n\nfunction buildNeutralSemantics(neutralSwatch: ColorSwatch, isDark: boolean): NeutralSemantics {\n if (isDark) {\n return {\n bg: neutralSwatch[950],\n bgSubtle: neutralSwatch[900],\n surface: neutralSwatch[900],\n surfaceHover: neutralSwatch[800],\n surfaceActive: neutralSwatch[700],\n border: neutralSwatch[800],\n borderStrong: neutralSwatch[600],\n divider: neutralSwatch[800],\n text: neutralSwatch[50],\n textMuted: neutralSwatch[200],\n textSubtle: neutralSwatch[300],\n };\n }\n return {\n bg: neutralSwatch[50],\n bgSubtle: neutralSwatch[100],\n surface: neutralSwatch[100],\n surfaceHover: neutralSwatch[200],\n surfaceActive: neutralSwatch[300],\n border: neutralSwatch[200],\n borderStrong: neutralSwatch[300],\n divider: neutralSwatch[200],\n text: neutralSwatch[900],\n textMuted: neutralSwatch[700],\n textSubtle: neutralSwatch[600],\n };\n}\n\nfunction buildRoleSemantics(swatch: ColorSwatch, isDark: boolean): RoleSemantics {\n const base = swatch[500];\n const { foreground: onSolidText } = getReadableForeground(base);\n\n if (isDark) {\n return {\n base,\n hover: swatch[400],\n strong: swatch[300],\n softBg: swatch[900],\n softHover: swatch[800],\n softActive: swatch[700],\n outline: swatch[500],\n onSolidText,\n };\n }\n\n return {\n base,\n hover: swatch[600],\n strong: swatch[700],\n softBg: swatch[100],\n softHover: swatch[200],\n softActive: swatch[300],\n outline: swatch[400],\n onSolidText,\n };\n}\n\nexport function generatePalette(\n config: ThemeConfig,\n mode: 'light' | 'dark' = 'light',\n): {\n colors: Record<string, string>;\n swatches: GeneratedThemeSwatches;\n semantics: ThemeSemantics;\n} {\n const modeConfig = mode === 'dark' ? config.dark : config.light;\n const isDark = mode === 'dark';\n\n // Throws deterministically on invalid primary color\n parseHexColorOrThrow(modeConfig.primaryColor);\n\n const generated = generateThemeModeColors(modeConfig);\n\n const { swatches } = generated;\n const neutralSwatch = swatches.neutral;\n\n const neutral = buildNeutralSemantics(neutralSwatch, isDark);\n const brand = buildRoleSemantics(swatches.primary, isDark);\n\n // Fallback to primary swatch for missing ordinal roles\n const secondarySwatch = swatches.secondary ?? swatches.primary;\n const tertiarySwatch = swatches.tertiary ?? swatches.primary;\n const quaternarySwatch = swatches.quaternary ?? swatches.primary;\n\n const semanticStatusSwatches = createDefaultSemanticStatusSwatches().swatches;\n\n const danger = buildRoleSemantics(semanticStatusSwatches.danger, isDark);\n const success = buildRoleSemantics(semanticStatusSwatches.success, isDark);\n const warning = buildRoleSemantics(semanticStatusSwatches.warning, isDark);\n\n const surfaceSemantics: SurfaceSemantics = {\n default: neutral.surface,\n subtle: neutral.bgSubtle,\n raised: neutral.surface,\n };\n\n const content: ContentSemantics = {\n default: neutral.text,\n muted: neutral.textMuted,\n subtle: neutral.textSubtle,\n inverse: brand.onSolidText,\n };\n\n const border: BorderSemantics = {\n default: neutral.border,\n strong: neutral.borderStrong,\n focus: brand.outline,\n };\n\n const action: ActionSemantics = {\n primary: brand,\n neutral: buildRoleSemantics(neutralSwatch, isDark),\n danger,\n };\n\n const colors: Record<string, string> = {\n primary: brand.base,\n secondary: secondarySwatch[500],\n accent: tertiarySwatch[500],\n highlight: quaternarySwatch[500],\n background: neutral.bg,\n surface: neutral.surface,\n text: neutral.text,\n textSecondary: neutral.textMuted,\n border: neutral.border,\n error: danger.base,\n success: success.base,\n warning: warning.base,\n };\n\n return {\n colors,\n swatches,\n semantics: {\n neutral,\n brand,\n secondary: buildRoleSemantics(secondarySwatch, isDark),\n accent: buildRoleSemantics(tertiarySwatch, isDark),\n highlight: buildRoleSemantics(quaternarySwatch, isDark),\n danger,\n success,\n warning,\n surface: surfaceSemantics,\n content,\n border,\n action,\n },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/surface",
3
3
  "type": "module",
4
- "version": "1.0.0",
4
+ "version": "1.0.2",
5
5
  "description": "Stable UI foundation for React Native and React Native Web.",
6
6
  "homepage": "https://github.com/ankhorage/surface#readme",
7
7
  "bugs": {
@@ -41,7 +41,7 @@
41
41
  }
42
42
  },
43
43
  "dependencies": {
44
- "@ankhorage/color-theory": "^0.0.2",
44
+ "@ankhorage/color-theory": "^0.0.4",
45
45
  "@ankhorage/contracts": "^1.1.0"
46
46
  },
47
47
  "files": [
@@ -71,6 +71,19 @@ describe('colorEngine', () => {
71
71
  expect(semantics.content.inverse).toBe(semantics.brand.onSolidText);
72
72
  });
73
73
 
74
+ it('uses the color-theory default semantic status seeds', () => {
75
+ const light = generatePalette(mockConfig, 'light');
76
+ const dark = generatePalette(mockConfig, 'dark');
77
+
78
+ expect(light.semantics.danger.base).toBe('#ef4444');
79
+ expect(light.semantics.success.base).toBe('#22c55e');
80
+ expect(light.semantics.warning.base).toBe('#f59e0b');
81
+
82
+ expect(dark.semantics.danger.base).toBe('#ef4444');
83
+ expect(dark.semantics.success.base).toBe('#22c55e');
84
+ expect(dark.semantics.warning.base).toBe('#f59e0b');
85
+ });
86
+
74
87
  it('uses mode-aware role semantics for dark mode soft states', () => {
75
88
  const light = generatePalette(mockConfig, 'light');
76
89
  const dark = generatePalette(mockConfig, 'dark');
@@ -7,7 +7,7 @@ import type {
7
7
  SemanticColorToken,
8
8
  } from '@ankhorage/color-theory';
9
9
  import {
10
- generateColorSwatch,
10
+ createDefaultSemanticStatusSwatches,
11
11
  generateThemeModeColors,
12
12
  getReadableForeground,
13
13
  parseHexColorOrThrow,
@@ -24,11 +24,6 @@ import type {
24
24
  ThemeSemantics,
25
25
  } from './types';
26
26
 
27
- // Fixed hex values for semantic status colors (not theme-generated)
28
- const DANGER_HEX = parseHexColorOrThrow('#ef4444');
29
- const SUCCESS_HEX = parseHexColorOrThrow('#22c55e');
30
- const WARNING_HEX = parseHexColorOrThrow('#f59e0b');
31
-
32
27
  /**
33
28
  * Surface semantic resolver: maps color-theory SemanticColorToken references
34
29
  * to hex values from the generated swatches.
@@ -137,13 +132,11 @@ export function generatePalette(
137
132
  const tertiarySwatch = swatches.tertiary ?? swatches.primary;
138
133
  const quaternarySwatch = swatches.quaternary ?? swatches.primary;
139
134
 
140
- const dangerSwatch = generateColorSwatch(DANGER_HEX).swatch;
141
- const successSwatch = generateColorSwatch(SUCCESS_HEX).swatch;
142
- const warningSwatch = generateColorSwatch(WARNING_HEX).swatch;
135
+ const semanticStatusSwatches = createDefaultSemanticStatusSwatches().swatches;
143
136
 
144
- const danger = buildRoleSemantics(dangerSwatch, isDark);
145
- const success = buildRoleSemantics(successSwatch, isDark);
146
- const warning = buildRoleSemantics(warningSwatch, isDark);
137
+ const danger = buildRoleSemantics(semanticStatusSwatches.danger, isDark);
138
+ const success = buildRoleSemantics(semanticStatusSwatches.success, isDark);
139
+ const warning = buildRoleSemantics(semanticStatusSwatches.warning, isDark);
147
140
 
148
141
  const surfaceSemantics: SurfaceSemantics = {
149
142
  default: neutral.surface,