@ankhorage/surface 9.1.115 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/dist/features/badge/adapters/inbound/Badge.d.ts.map +1 -1
  4. package/dist/features/badge/adapters/inbound/Badge.js +1 -1
  5. package/dist/features/badge/adapters/inbound/Badge.js.map +1 -1
  6. package/dist/features/button/adapters/inbound/Button.js +1 -2
  7. package/dist/features/button/adapters/inbound/Button.js.map +1 -1
  8. package/dist/features/icon/adapters/inbound/Icon.d.ts.map +1 -1
  9. package/dist/features/icon/adapters/inbound/Icon.js +9 -1
  10. package/dist/features/icon/adapters/inbound/Icon.js.map +1 -1
  11. package/dist/features/theme/adapters/inbound/ThemeProvider.d.ts.map +1 -1
  12. package/dist/features/theme/adapters/inbound/ThemeProvider.js +1 -0
  13. package/dist/features/theme/adapters/inbound/ThemeProvider.js.map +1 -1
  14. package/dist/features/theme/adapters/inbound/ThemeRuntimeContext.d.ts.map +1 -1
  15. package/dist/features/theme/adapters/inbound/ThemeRuntimeContext.js +1 -0
  16. package/dist/features/theme/adapters/inbound/ThemeRuntimeContext.js.map +1 -1
  17. package/dist/features/theme/adapters/inbound/ThemeScope.d.ts +2 -2
  18. package/dist/features/theme/adapters/inbound/ThemeScope.d.ts.map +1 -1
  19. package/dist/features/theme/adapters/inbound/ThemeScope.js +5 -4
  20. package/dist/features/theme/adapters/inbound/ThemeScope.js.map +1 -1
  21. package/dist/features/theme/application/use-cases/createTheme.d.ts +2 -2
  22. package/dist/features/theme/application/use-cases/createTheme.d.ts.map +1 -1
  23. package/dist/features/theme/application/use-cases/createTheme.js +6 -3
  24. package/dist/features/theme/application/use-cases/createTheme.js.map +1 -1
  25. package/dist/features/theme/domain/projectInvertedTheme.d.ts +4 -0
  26. package/dist/features/theme/domain/projectInvertedTheme.d.ts.map +1 -0
  27. package/dist/features/theme/domain/projectInvertedTheme.js +178 -0
  28. package/dist/features/theme/domain/projectInvertedTheme.js.map +1 -0
  29. package/dist/features/theme/domain/resolveInverseSurface.d.ts +10 -0
  30. package/dist/features/theme/domain/resolveInverseSurface.d.ts.map +1 -0
  31. package/dist/features/theme/domain/resolveInverseSurface.js +31 -0
  32. package/dist/features/theme/domain/resolveInverseSurface.js.map +1 -0
  33. package/dist/features/typography/adapters/inbound/Text.d.ts +1 -1
  34. package/dist/features/typography/adapters/inbound/Text.d.ts.map +1 -1
  35. package/dist/features/typography/adapters/inbound/Text.js +2 -1
  36. package/dist/features/typography/adapters/inbound/Text.js.map +1 -1
  37. package/dist/internal/resolvers/resolveInteractiveColors.d.ts.map +1 -1
  38. package/dist/internal/resolvers/resolveInteractiveColors.js +10 -2
  39. package/dist/internal/resolvers/resolveInteractiveColors.js.map +1 -1
  40. package/dist/internal/resolvers/resolveTextColor.d.ts.map +1 -1
  41. package/dist/internal/resolvers/resolveTextColor.js +2 -1
  42. package/dist/internal/resolvers/resolveTextColor.js.map +1 -1
  43. package/dist/types/theme.d.ts +3 -0
  44. package/dist/types/theme.d.ts.map +1 -1
  45. package/dist/types/theme.js.map +1 -1
  46. package/dist/types/typography.d.ts +1 -0
  47. package/dist/types/typography.d.ts.map +1 -1
  48. package/dist/types/typography.js.map +1 -1
  49. package/package.json +3 -3
  50. package/src/features/badge/adapters/inbound/Badge.tsx +1 -6
  51. package/src/features/button/adapters/inbound/Button.tsx +1 -3
  52. package/src/features/icon/adapters/inbound/Icon.tsx +12 -1
  53. package/src/features/icon/adapters/inbound/PortableIcon.test.tsx +32 -0
  54. package/src/features/theme/adapters/inbound/ThemeProvider.tsx +1 -0
  55. package/src/features/theme/adapters/inbound/ThemeRuntimeContext.tsx +1 -0
  56. package/src/features/theme/adapters/inbound/ThemeScope.test.tsx +38 -7
  57. package/src/features/theme/adapters/inbound/ThemeScope.tsx +7 -6
  58. package/src/features/theme/application/use-cases/createTheme.ts +6 -2
  59. package/src/features/theme/domain/projectInvertedTheme.ts +300 -0
  60. package/src/features/theme/domain/resolveInverseSurface.ts +55 -0
  61. package/src/features/typography/adapters/inbound/Text.tsx +2 -0
  62. package/src/internal/resolvers/resolveInteractiveColors.test.ts +1 -1
  63. package/src/internal/resolvers/resolveInteractiveColors.ts +12 -2
  64. package/src/internal/resolvers/resolveTextColor.test.ts +5 -0
  65. package/src/internal/resolvers/resolveTextColor.ts +2 -1
  66. package/src/invertedThemeAcceptance.test.ts +204 -0
  67. package/src/types/theme.ts +3 -0
  68. package/src/types/typography.ts +1 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @ankhorage/surface
2
2
 
3
+ ## 9.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 5c2f97d: Add inherited inverted surface polarity with contrast-safe semantic projection
8
+
9
+ ## 9.1.116
10
+
11
+ ### Patch Changes
12
+
13
+ - 3421a15: Update dependencies: `@ankhorage/contracts`.
14
+
3
15
  ## 9.1.115
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @ankhorage/surface
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v9.1.115](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![paradox: warnings](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v9.2.0](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![paradox: warnings](././paradox/badges/docs.svg)
7
7
 
8
8
  Cross-platform UI foundation for React Native and React Native Web. Provides theming, layout primitives, and core building blocks for modern apps.
9
9
 
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../../../src/features/badge/adapters/inbound/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAK1D,4DAA4D;AAC5D,wBAAgB,KAAK,CAAC,EACpB,OAAO,EACP,OAAgB,EAChB,KAAiB,EACjB,IAAU,EACV,MAAM,GACP,EAAE,UAAU,qBA2BZ"}
1
+ {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../../../src/features/badge/adapters/inbound/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAK1D,4DAA4D;AAC5D,wBAAgB,KAAK,CAAC,EACpB,OAAO,EACP,OAAgB,EAChB,KAAiB,EACjB,IAAU,EACV,MAAM,GACP,EAAE,UAAU,qBAsBZ"}
@@ -13,7 +13,7 @@ export function Badge({ content, variant = 'soft', color = 'primary', size = 's'
13
13
  state: { disabled: false, focused: false, hovered: false, pressed: false },
14
14
  });
15
15
  return (<View px={Math.max(theme.spacing.xs, controlSize.paddingHorizontal - 4)} py={Math.max(4, controlSize.paddingVertical - 2)} radius={controlSize.borderRadius} style={resolveBadgeStyle(colors.backgroundColor, colors.borderColor, variant)} testID={testID}>
16
- <Text color={color} emphasis={variant === 'solid' ? 'inverse' : 'default'} variant="bodySmall" weight="medium">
16
+ <Text style={{ color: colors.contentColor }} variant="bodySmall" weight="medium">
17
17
  {content}
18
18
  </Text>
19
19
  </View>);
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.js","sourceRoot":"","sources":["../../../../../src/features/badge/adapters/inbound/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEzF,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAElD,4DAA4D;AAC5D,MAAM,UAAU,KAAK,CAAC,EACpB,OAAO,EACP,OAAO,GAAG,MAAM,EAChB,KAAK,GAAG,SAAS,EACjB,IAAI,GAAG,GAAG,EACV,MAAM,GACK;IACX,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE;QACxC,OAAO;QACP,KAAK;QACL,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE;KAC3E,CAAC,CAAC;IAEH,OAAO,CACL,CAAC,IAAI,CACH,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,WAAW,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC,CAClE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,CACjD,MAAM,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,CACjC,KAAK,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAC9E,MAAM,CAAC,CAAC,MAAM,CAAC,CAEf;MAAA,CAAC,IAAI,CACH,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,QAAQ,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CACtD,OAAO,CAAC,WAAW,CACnB,MAAM,CAAC,QAAQ,CAEf;QAAA,CAAC,OAAO,CACV;MAAA,EAAE,IAAI,CACR;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC;AAED,kEAAkE;AAClE,SAAS,iBAAiB,CACxB,eAAuB,EACvB,WAAmB,EACnB,OAA2C;IAE3C,OAAO;QACL,SAAS,EAAE,YAAY;QACvB,eAAe;QACf,WAAW;QACX,WAAW,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACzC,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\nimport type { ViewStyle } from 'react-native';\n\nimport { resolveButtonColors, resolveControlSize } from '../../../../internal/resolvers';\nimport type { BadgeProps } from '../../../../types/badge';\nimport { View } from '../../../layout/public';\nimport { useTheme } from '../../../theme/runtime';\nimport { Text } from '../../../typography/public';\n\n/*** Renders compact semantic status or metadata content. */\nexport function Badge({\n content,\n variant = 'soft',\n color = 'primary',\n size = 's',\n testID,\n}: BadgeProps) {\n const { theme } = useTheme();\n const controlSize = resolveControlSize(theme, size);\n const colors = resolveButtonColors(theme, {\n variant,\n color,\n state: { disabled: false, focused: false, hovered: false, pressed: false },\n });\n\n return (\n <View\n px={Math.max(theme.spacing.xs, controlSize.paddingHorizontal - 4)}\n py={Math.max(4, controlSize.paddingVertical - 2)}\n radius={controlSize.borderRadius}\n style={resolveBadgeStyle(colors.backgroundColor, colors.borderColor, variant)}\n testID={testID}\n >\n <Text\n color={color}\n emphasis={variant === 'solid' ? 'inverse' : 'default'}\n variant=\"bodySmall\"\n weight=\"medium\"\n >\n {content}\n </Text>\n </View>\n );\n}\n\n/*** Resolves the visual container style for one badge variant. */\nfunction resolveBadgeStyle(\n backgroundColor: string,\n borderColor: string,\n variant: NonNullable<BadgeProps['variant']>,\n): ViewStyle {\n return {\n alignSelf: 'flex-start',\n backgroundColor,\n borderColor,\n borderWidth: variant === 'solid' ? 0 : 1,\n };\n}\n"]}
1
+ {"version":3,"file":"Badge.js","sourceRoot":"","sources":["../../../../../src/features/badge/adapters/inbound/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEzF,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAElD,4DAA4D;AAC5D,MAAM,UAAU,KAAK,CAAC,EACpB,OAAO,EACP,OAAO,GAAG,MAAM,EAChB,KAAK,GAAG,SAAS,EACjB,IAAI,GAAG,GAAG,EACV,MAAM,GACK;IACX,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE;QACxC,OAAO;QACP,KAAK;QACL,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE;KAC3E,CAAC,CAAC;IAEH,OAAO,CACL,CAAC,IAAI,CACH,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,WAAW,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC,CAClE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,CACjD,MAAM,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,CACjC,KAAK,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAC9E,MAAM,CAAC,CAAC,MAAM,CAAC,CAEf;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAC9E;QAAA,CAAC,OAAO,CACV;MAAA,EAAE,IAAI,CACR;IAAA,EAAE,IAAI,CAAC,CACR,CAAC;AACJ,CAAC;AAED,kEAAkE;AAClE,SAAS,iBAAiB,CACxB,eAAuB,EACvB,WAAmB,EACnB,OAA2C;IAE3C,OAAO;QACL,SAAS,EAAE,YAAY;QACvB,eAAe;QACf,WAAW;QACX,WAAW,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACzC,CAAC;AACJ,CAAC","sourcesContent":["import React from 'react';\nimport type { ViewStyle } from 'react-native';\n\nimport { resolveButtonColors, resolveControlSize } from '../../../../internal/resolvers';\nimport type { BadgeProps } from '../../../../types/badge';\nimport { View } from '../../../layout/public';\nimport { useTheme } from '../../../theme/runtime';\nimport { Text } from '../../../typography/public';\n\n/*** Renders compact semantic status or metadata content. */\nexport function Badge({\n content,\n variant = 'soft',\n color = 'primary',\n size = 's',\n testID,\n}: BadgeProps) {\n const { theme } = useTheme();\n const controlSize = resolveControlSize(theme, size);\n const colors = resolveButtonColors(theme, {\n variant,\n color,\n state: { disabled: false, focused: false, hovered: false, pressed: false },\n });\n\n return (\n <View\n px={Math.max(theme.spacing.xs, controlSize.paddingHorizontal - 4)}\n py={Math.max(4, controlSize.paddingVertical - 2)}\n radius={controlSize.borderRadius}\n style={resolveBadgeStyle(colors.backgroundColor, colors.borderColor, variant)}\n testID={testID}\n >\n <Text style={{ color: colors.contentColor }} variant=\"bodySmall\" weight=\"medium\">\n {content}\n </Text>\n </View>\n );\n}\n\n/*** Resolves the visual container style for one badge variant. */\nfunction resolveBadgeStyle(\n backgroundColor: string,\n borderColor: string,\n variant: NonNullable<BadgeProps['variant']>,\n): ViewStyle {\n return {\n alignSelf: 'flex-start',\n backgroundColor,\n borderColor,\n borderWidth: variant === 'solid' ? 0 : 1,\n };\n}\n"]}
@@ -19,14 +19,13 @@ export function Button({ children, variant = 'solid', color = 'primary', size =
19
19
  /*** Renders Button content after interaction colors have been resolved. */
20
20
  function ButtonContent({ children, color, controlSize, fullWidth, leadingIcon, loading, size, state, theme, trailingIcon, variant, }) {
21
21
  const colors = resolveButtonColors(theme, { variant, color, state });
22
- const muted = colors.contentColor === theme.semantics.content.muted;
23
22
  const iconSize = resolveIconSize(theme, size);
24
23
  return (<View px={controlSize.paddingHorizontal} py={controlSize.paddingVertical} radius={controlSize.borderRadius} style={resolveButtonContentStyle(controlSize, colors, fullWidth, variant)}>
25
24
  {loading ? (<ActivityIndicator color={colors.contentColor} size="small"/>) : (<>
26
25
  {leadingIcon ? (<ReactNativeView style={resolveAccessoryStyle(theme.spacing.s, 'leading')}>
27
26
  <Icon {...leadingIcon} color={colors.contentColor} size={iconSize}/>
28
27
  </ReactNativeView>) : null}
29
- <Text color={muted ? undefined : color} emphasis={muted ? 'muted' : variant === 'solid' ? 'inverse' : 'default'} variant={controlSize.textVariant} weight="semiBold">
28
+ <Text style={{ color: colors.contentColor }} variant={controlSize.textVariant} weight="semiBold">
30
29
  {children}
31
30
  </Text>
32
31
  {trailingIcon ? (<ReactNativeView style={resolveAccessoryStyle(theme.spacing.s, 'trailing')}>
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../../../src/features/button/adapters/inbound/Button.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { ActivityIndicator, View as ReactNativeView, type ViewStyle } from 'react-native';\n\nimport {\n resolveButtonColors,\n resolveControlSize,\n resolveIconSize,\n} from '../../../../internal/resolvers';\nimport type { ButtonProps } from '../../../../types/button';\nimport type { InteractionState } from '../../../../types/pressable';\nimport type { SurfaceTheme } from '../../../../types/theme';\nimport { Icon } from '../../../icon/public';\nimport { View } from '../../../layout/public';\nimport { Pressable } from '../../../pressable/public';\nimport { useTheme } from '../../../theme/runtime';\nimport { Text } from '../../../typography/public';\n\n/*** Renders the primary Surface action control with semantic visual states. */\nexport function Button({\n children,\n variant = 'solid',\n color = 'primary',\n size = 'm',\n disabled = false,\n loading = false,\n leadingIcon,\n trailingIcon,\n fullWidth = false,\n onPress,\n testID,\n ...props\n}: ButtonProps) {\n const { theme } = useTheme();\n const controlSize = resolveControlSize(theme, size);\n\n return (\n <Pressable\n {...props}\n disabled={disabled || loading}\n onPress={onPress}\n style={resolvePressableStyle(fullWidth)}\n testID={testID}\n >\n {(state) => (\n <ButtonContent\n color={color}\n controlSize={controlSize}\n fullWidth={fullWidth}\n leadingIcon={leadingIcon}\n loading={loading}\n size={size}\n state={state}\n theme={theme}\n trailingIcon={trailingIcon}\n variant={variant}\n >\n {children}\n </ButtonContent>\n )}\n </Pressable>\n );\n}\n\n/*** Renders Button content after interaction colors have been resolved. */\nfunction ButtonContent({\n children,\n color,\n controlSize,\n fullWidth,\n leadingIcon,\n loading,\n size,\n state,\n theme,\n trailingIcon,\n variant,\n}: ButtonContentProps) {\n const colors = resolveButtonColors(theme, { variant, color, state });\n const muted = colors.contentColor === theme.semantics.content.muted;\n const iconSize = resolveIconSize(theme, size);\n\n return (\n <View\n px={controlSize.paddingHorizontal}\n py={controlSize.paddingVertical}\n radius={controlSize.borderRadius}\n style={resolveButtonContentStyle(controlSize, colors, fullWidth, variant)}\n >\n {loading ? (\n <ActivityIndicator color={colors.contentColor} size=\"small\" />\n ) : (\n <>\n {leadingIcon ? (\n <ReactNativeView style={resolveAccessoryStyle(theme.spacing.s, 'leading')}>\n <Icon {...leadingIcon} color={colors.contentColor} size={iconSize} />\n </ReactNativeView>\n ) : null}\n <Text\n color={muted ? undefined : color}\n emphasis={muted ? 'muted' : variant === 'solid' ? 'inverse' : 'default'}\n variant={controlSize.textVariant}\n weight=\"semiBold\"\n >\n {children}\n </Text>\n {trailingIcon ? (\n <ReactNativeView style={resolveAccessoryStyle(theme.spacing.s, 'trailing')}>\n <Icon {...trailingIcon} color={colors.contentColor} size={iconSize} />\n </ReactNativeView>\n ) : null}\n </>\n )}\n </View>\n );\n}\n\n/*** Resolves the outer Pressable layout style. */\nfunction resolvePressableStyle(fullWidth: boolean): ViewStyle {\n return { alignSelf: fullWidth ? 'stretch' : 'flex-start' };\n}\n\n/*** Resolves the themed Button content container style. */\nfunction resolveButtonContentStyle(\n controlSize: ReturnType<typeof resolveControlSize>,\n colors: ReturnType<typeof resolveButtonColors>,\n fullWidth: boolean,\n variant: NonNullable<ButtonProps['variant']>,\n): ViewStyle {\n return {\n alignItems: 'center',\n backgroundColor: colors.backgroundColor,\n borderColor: colors.borderColor,\n borderWidth: variant === 'solid' ? 0 : 1,\n flexDirection: 'row',\n justifyContent: 'center',\n minHeight: controlSize.minHeight,\n opacity: colors.opacity,\n width: fullWidth ? '100%' : undefined,\n };\n}\n\n/*** Resolves spacing around a leading or trailing Button icon. */\nfunction resolveAccessoryStyle(spacing: number, position: 'leading' | 'trailing'): ViewStyle {\n return position === 'leading' ? { marginRight: spacing } : { marginLeft: spacing };\n}\n\ninterface ButtonContentProps {\n children: ButtonProps['children'];\n color: NonNullable<ButtonProps['color']>;\n controlSize: ReturnType<typeof resolveControlSize>;\n fullWidth: boolean;\n leadingIcon: ButtonProps['leadingIcon'];\n loading: boolean;\n size: NonNullable<ButtonProps['size']>;\n state: InteractionState;\n theme: SurfaceTheme;\n trailingIcon: ButtonProps['trailingIcon'];\n variant: NonNullable<ButtonProps['variant']>;\n}\n"]}
1
+ {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../../../src/features/button/adapters/inbound/Button.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { ActivityIndicator, View as ReactNativeView, type ViewStyle } from 'react-native';\n\nimport {\n resolveButtonColors,\n resolveControlSize,\n resolveIconSize,\n} from '../../../../internal/resolvers';\nimport type { ButtonProps } from '../../../../types/button';\nimport type { InteractionState } from '../../../../types/pressable';\nimport type { SurfaceTheme } from '../../../../types/theme';\nimport { Icon } from '../../../icon/public';\nimport { View } from '../../../layout/public';\nimport { Pressable } from '../../../pressable/public';\nimport { useTheme } from '../../../theme/runtime';\nimport { Text } from '../../../typography/public';\n\n/*** Renders the primary Surface action control with semantic visual states. */\nexport function Button({\n children,\n variant = 'solid',\n color = 'primary',\n size = 'm',\n disabled = false,\n loading = false,\n leadingIcon,\n trailingIcon,\n fullWidth = false,\n onPress,\n testID,\n ...props\n}: ButtonProps) {\n const { theme } = useTheme();\n const controlSize = resolveControlSize(theme, size);\n\n return (\n <Pressable\n {...props}\n disabled={disabled || loading}\n onPress={onPress}\n style={resolvePressableStyle(fullWidth)}\n testID={testID}\n >\n {(state) => (\n <ButtonContent\n color={color}\n controlSize={controlSize}\n fullWidth={fullWidth}\n leadingIcon={leadingIcon}\n loading={loading}\n size={size}\n state={state}\n theme={theme}\n trailingIcon={trailingIcon}\n variant={variant}\n >\n {children}\n </ButtonContent>\n )}\n </Pressable>\n );\n}\n\n/*** Renders Button content after interaction colors have been resolved. */\nfunction ButtonContent({\n children,\n color,\n controlSize,\n fullWidth,\n leadingIcon,\n loading,\n size,\n state,\n theme,\n trailingIcon,\n variant,\n}: ButtonContentProps) {\n const colors = resolveButtonColors(theme, { variant, color, state });\n const iconSize = resolveIconSize(theme, size);\n\n return (\n <View\n px={controlSize.paddingHorizontal}\n py={controlSize.paddingVertical}\n radius={controlSize.borderRadius}\n style={resolveButtonContentStyle(controlSize, colors, fullWidth, variant)}\n >\n {loading ? (\n <ActivityIndicator color={colors.contentColor} size=\"small\" />\n ) : (\n <>\n {leadingIcon ? (\n <ReactNativeView style={resolveAccessoryStyle(theme.spacing.s, 'leading')}>\n <Icon {...leadingIcon} color={colors.contentColor} size={iconSize} />\n </ReactNativeView>\n ) : null}\n <Text\n style={{ color: colors.contentColor }}\n variant={controlSize.textVariant}\n weight=\"semiBold\"\n >\n {children}\n </Text>\n {trailingIcon ? (\n <ReactNativeView style={resolveAccessoryStyle(theme.spacing.s, 'trailing')}>\n <Icon {...trailingIcon} color={colors.contentColor} size={iconSize} />\n </ReactNativeView>\n ) : null}\n </>\n )}\n </View>\n );\n}\n\n/*** Resolves the outer Pressable layout style. */\nfunction resolvePressableStyle(fullWidth: boolean): ViewStyle {\n return { alignSelf: fullWidth ? 'stretch' : 'flex-start' };\n}\n\n/*** Resolves the themed Button content container style. */\nfunction resolveButtonContentStyle(\n controlSize: ReturnType<typeof resolveControlSize>,\n colors: ReturnType<typeof resolveButtonColors>,\n fullWidth: boolean,\n variant: NonNullable<ButtonProps['variant']>,\n): ViewStyle {\n return {\n alignItems: 'center',\n backgroundColor: colors.backgroundColor,\n borderColor: colors.borderColor,\n borderWidth: variant === 'solid' ? 0 : 1,\n flexDirection: 'row',\n justifyContent: 'center',\n minHeight: controlSize.minHeight,\n opacity: colors.opacity,\n width: fullWidth ? '100%' : undefined,\n };\n}\n\n/*** Resolves spacing around a leading or trailing Button icon. */\nfunction resolveAccessoryStyle(spacing: number, position: 'leading' | 'trailing'): ViewStyle {\n return position === 'leading' ? { marginRight: spacing } : { marginLeft: spacing };\n}\n\ninterface ButtonContentProps {\n children: ButtonProps['children'];\n color: NonNullable<ButtonProps['color']>;\n controlSize: ReturnType<typeof resolveControlSize>;\n fullWidth: boolean;\n leadingIcon: ButtonProps['leadingIcon'];\n loading: boolean;\n size: NonNullable<ButtonProps['size']>;\n state: InteractionState;\n theme: SurfaceTheme;\n trailingIcon: ButtonProps['trailingIcon'];\n variant: NonNullable<ButtonProps['variant']>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Icon.d.ts","sourceRoot":"","sources":["../../../../../src/features/icon/adapters/inbound/Icon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAKxD,iFAAiF;AACjF,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,+BAOpC"}
1
+ {"version":3,"file":"Icon.d.ts","sourceRoot":"","sources":["../../../../../src/features/icon/adapters/inbound/Icon.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAMxD,iFAAiF;AACjF,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,+BAUpC"}
@@ -1,3 +1,5 @@
1
+ import { SURFACE_COLORS } from '../../../../constants/surfaceColor';
2
+ import { resolveTextColor } from '../../../../internal/resolvers/resolveTextColor';
1
3
  import { useTheme } from '../../../theme/runtime';
2
4
  import { resolveToken } from '../../../theme/utils/resolveToken';
3
5
  import { PortableIcon } from './PortableIcon';
@@ -7,7 +9,13 @@ export function Icon(props) {
7
9
  const size = props.size ?? 'm';
8
10
  const color = props.color ?? 'text';
9
11
  const resolvedSize = typeof size === 'number' ? size : resolveToken(theme.spacing, size);
10
- const resolvedColor = resolveToken(theme.colors, color);
12
+ const resolvedColor = typeof color === 'string' && isSurfaceColor(color)
13
+ ? resolveTextColor(theme, 'default', color)
14
+ : resolveToken(theme.colors, color);
11
15
  return <PortableIcon {...props} color={resolvedColor} size={resolvedSize}/>;
12
16
  }
17
+ /*** Distinguish semantic color roles from raw icon colors and other tokens. */
18
+ function isSurfaceColor(value) {
19
+ return SURFACE_COLORS.some((role) => role === value);
20
+ }
13
21
  //# sourceMappingURL=Icon.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Icon.js","sourceRoot":"","sources":["../../../../../src/features/icon/adapters/inbound/Icon.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,iFAAiF;AACjF,MAAM,UAAU,IAAI,CAAC,KAAgB;IACnC,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC;IACpC,MAAM,YAAY,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzF,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACxD,OAAO,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,EAAG,CAAC;AAC/E,CAAC","sourcesContent":["import type { IconProps } from '../../../../types/icon';\nimport { useTheme } from '../../../theme/runtime';\nimport { resolveToken } from '../../../theme/utils/resolveToken';\nimport { PortableIcon } from './PortableIcon';\n\n/*** Renders a theme-aware font or SVG icon through the portable icon adapter. */\nexport function Icon(props: IconProps) {\n const { theme } = useTheme();\n const size = props.size ?? 'm';\n const color = props.color ?? 'text';\n const resolvedSize = typeof size === 'number' ? size : resolveToken(theme.spacing, size);\n const resolvedColor = resolveToken(theme.colors, color);\n return <PortableIcon {...props} color={resolvedColor} size={resolvedSize} />;\n}\n"]}
1
+ {"version":3,"file":"Icon.js","sourceRoot":"","sources":["../../../../../src/features/icon/adapters/inbound/Icon.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iDAAiD,CAAC;AAGnF,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,iFAAiF;AACjF,MAAM,UAAU,IAAI,CAAC,KAAgB;IACnC,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC;IACpC,MAAM,YAAY,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzF,MAAM,aAAa,GACjB,OAAO,KAAK,KAAK,QAAQ,IAAI,cAAc,CAAC,KAAK,CAAC;QAChD,CAAC,CAAC,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC;QAC3C,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACxC,OAAO,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,EAAG,CAAC;AAC/E,CAAC;AAED,+EAA+E;AAC/E,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;AACvD,CAAC","sourcesContent":["import { SURFACE_COLORS } from '../../../../constants/surfaceColor';\nimport { resolveTextColor } from '../../../../internal/resolvers/resolveTextColor';\nimport type { IconProps } from '../../../../types/icon';\nimport type { SurfaceColor } from '../../../../types/surfaceColor';\nimport { useTheme } from '../../../theme/runtime';\nimport { resolveToken } from '../../../theme/utils/resolveToken';\nimport { PortableIcon } from './PortableIcon';\n\n/*** Renders a theme-aware font or SVG icon through the portable icon adapter. */\nexport function Icon(props: IconProps) {\n const { theme } = useTheme();\n const size = props.size ?? 'm';\n const color = props.color ?? 'text';\n const resolvedSize = typeof size === 'number' ? size : resolveToken(theme.spacing, size);\n const resolvedColor =\n typeof color === 'string' && isSurfaceColor(color)\n ? resolveTextColor(theme, 'default', color)\n : resolveToken(theme.colors, color);\n return <PortableIcon {...props} color={resolvedColor} size={resolvedSize} />;\n}\n\n/*** Distinguish semantic color roles from raw icon colors and other tokens. */\nfunction isSurfaceColor(value: string): value is SurfaceColor {\n return SURFACE_COLORS.some((role) => role === value);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeProvider.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,yBAAyB,CAAC;AAKhF,gGAAgG;AAChG,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,aAAa,EACb,WAAqB,GACtB,EAAE,kBAAkB,+BA6BpB"}
1
+ {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeProvider.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAgB,MAAM,yBAAyB,CAAC;AAKhF,gGAAgG;AAChG,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,aAAa,EACb,WAAqB,GACtB,EAAE,kBAAkB,+BA8BpB"}
@@ -15,6 +15,7 @@ export function ThemeProvider({ children, initialConfig, initialMode = 'light',
15
15
  const value = useMemo(() => ({
16
16
  theme,
17
17
  mode,
18
+ inverted: false,
18
19
  setThemeConfig: (nextConfig) => setConfig((previous) => deepMerge(previous, nextConfig)),
19
20
  setMode,
20
21
  }), [mode, theme]);
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.js","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeProvider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAE/E,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,gGAAgG;AAChG,MAAM,UAAU,aAAa,CAAC,EAC5B,QAAQ,EACR,aAAa,EACb,WAAW,GAAG,OAAO,GACF;IACnB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAc,GAAG,EAAE,CACrD,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CACpF,CAAC;IACF,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,EAAE,YAAY,EAAE,GAAG,cAAc,EAAE,CAAC;IAE1C,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,EAC7C,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,CAC7B,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC;QACL,KAAK;QACL,IAAI;QACJ,cAAc,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACxF,OAAO;KACR,CAAC,EACF,CAAC,IAAI,EAAE,KAAK,CAAC,CACd,CAAC;IAEF,OAAO,CACL,CAAC,kBAAkB,CACjB;MAAA,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAChC;QAAA,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,EAAE,eAAe,CAC9C;MAAA,EAAE,mBAAmB,CACvB;IAAA,EAAE,kBAAkB,CAAC,CACtB,CAAC;AACJ,CAAC","sourcesContent":["import type { ThemeConfig } from '@ankhorage/contracts';\nimport { deepMerge } from '@ankhorage/utility/object';\nimport { useMemo, useState } from 'react';\n\nimport { ResponsiveProvider } from '../../../../core/responsive/ResponsiveProvider';\nimport { OverlayProvider } from '../../../../internal/overlay/OverlayProvider';\nimport type { ThemeProviderProps, ThemeRuntime } from '../../../../types/theme';\nimport { useFontRuntime } from '../../../font/adapters/inbound/useFontRuntime';\nimport { createTheme } from '../../application/use-cases/createTheme';\nimport { ThemeRuntimeContext } from './ThemeRuntimeContext';\n\n/*** Install the app-level Surface theme together with global responsive and overlay runtime. */\nexport function ThemeProvider({\n children,\n initialConfig,\n initialMode = 'light',\n}: ThemeProviderProps) {\n const defaultTheme = useMemo(() => createTheme(), []);\n const [config, setConfig] = useState<ThemeConfig>(() =>\n initialConfig ? deepMerge(defaultTheme.config, initialConfig) : defaultTheme.config,\n );\n const [mode, setMode] = useState(initialMode);\n const { activeFontId } = useFontRuntime();\n\n const theme = useMemo(\n () => createTheme(config, mode, activeFontId),\n [activeFontId, config, mode],\n );\n const value = useMemo<ThemeRuntime>(\n () => ({\n theme,\n mode,\n setThemeConfig: (nextConfig) => setConfig((previous) => deepMerge(previous, nextConfig)),\n setMode,\n }),\n [mode, theme],\n );\n\n return (\n <ResponsiveProvider>\n <ThemeRuntimeContext value={value}>\n <OverlayProvider>{children}</OverlayProvider>\n </ThemeRuntimeContext>\n </ResponsiveProvider>\n );\n}\n"]}
1
+ {"version":3,"file":"ThemeProvider.js","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeProvider.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAE/E,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,gGAAgG;AAChG,MAAM,UAAU,aAAa,CAAC,EAC5B,QAAQ,EACR,aAAa,EACb,WAAW,GAAG,OAAO,GACF;IACnB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAc,GAAG,EAAE,CACrD,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CACpF,CAAC;IACF,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,EAAE,YAAY,EAAE,GAAG,cAAc,EAAE,CAAC;IAE1C,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,EAC7C,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,CAC7B,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC;QACL,KAAK;QACL,IAAI;QACJ,QAAQ,EAAE,KAAK;QACf,cAAc,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACxF,OAAO;KACR,CAAC,EACF,CAAC,IAAI,EAAE,KAAK,CAAC,CACd,CAAC;IAEF,OAAO,CACL,CAAC,kBAAkB,CACjB;MAAA,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAChC;QAAA,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,EAAE,eAAe,CAC9C;MAAA,EAAE,mBAAmB,CACvB;IAAA,EAAE,kBAAkB,CAAC,CACtB,CAAC;AACJ,CAAC","sourcesContent":["import type { ThemeConfig } from '@ankhorage/contracts';\nimport { deepMerge } from '@ankhorage/utility/object';\nimport { useMemo, useState } from 'react';\n\nimport { ResponsiveProvider } from '../../../../core/responsive/ResponsiveProvider';\nimport { OverlayProvider } from '../../../../internal/overlay/OverlayProvider';\nimport type { ThemeProviderProps, ThemeRuntime } from '../../../../types/theme';\nimport { useFontRuntime } from '../../../font/adapters/inbound/useFontRuntime';\nimport { createTheme } from '../../application/use-cases/createTheme';\nimport { ThemeRuntimeContext } from './ThemeRuntimeContext';\n\n/*** Install the app-level Surface theme together with global responsive and overlay runtime. */\nexport function ThemeProvider({\n children,\n initialConfig,\n initialMode = 'light',\n}: ThemeProviderProps) {\n const defaultTheme = useMemo(() => createTheme(), []);\n const [config, setConfig] = useState<ThemeConfig>(() =>\n initialConfig ? deepMerge(defaultTheme.config, initialConfig) : defaultTheme.config,\n );\n const [mode, setMode] = useState(initialMode);\n const { activeFontId } = useFontRuntime();\n\n const theme = useMemo(\n () => createTheme(config, mode, activeFontId),\n [activeFontId, config, mode],\n );\n const value = useMemo<ThemeRuntime>(\n () => ({\n theme,\n mode,\n inverted: false,\n setThemeConfig: (nextConfig) => setConfig((previous) => deepMerge(previous, nextConfig)),\n setMode,\n }),\n [mode, theme],\n );\n\n return (\n <ResponsiveProvider>\n <ThemeRuntimeContext value={value}>\n <OverlayProvider>{children}</OverlayProvider>\n </ThemeRuntimeContext>\n </ResponsiveProvider>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeRuntimeContext.d.ts","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeRuntimeContext.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAK5D,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,uCAK9B,CAAC"}
1
+ {"version":3,"file":"ThemeRuntimeContext.d.ts","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeRuntimeContext.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAK5D,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,uCAM9B,CAAC"}
@@ -5,6 +5,7 @@ const defaultTheme = createTheme();
5
5
  export const ThemeRuntimeContext = createContext({
6
6
  theme: defaultTheme,
7
7
  mode: 'light',
8
+ inverted: false,
8
9
  setThemeConfig: () => undefined,
9
10
  setMode: () => undefined,
10
11
  });
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeRuntimeContext.js","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeRuntimeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAEtE,MAAM,YAAY,GAAG,WAAW,EAAE,CAAC;AAEnC,yEAAyE;AACzE,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAAe;IAC7D,KAAK,EAAE,YAAY;IACnB,IAAI,EAAE,OAAO;IACb,cAAc,EAAE,GAAG,EAAE,CAAC,SAAS;IAC/B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;CACzB,CAAC,CAAC","sourcesContent":["import { createContext } from 'react';\n\nimport type { ThemeRuntime } from '../../../../types/theme';\nimport { createTheme } from '../../application/use-cases/createTheme';\n\nconst defaultTheme = createTheme();\n\n/*** Holds the active Surface theme runtime for component consumption. */\nexport const ThemeRuntimeContext = createContext<ThemeRuntime>({\n theme: defaultTheme,\n mode: 'light',\n setThemeConfig: () => undefined,\n setMode: () => undefined,\n});\n"]}
1
+ {"version":3,"file":"ThemeRuntimeContext.js","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeRuntimeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAEtE,MAAM,YAAY,GAAG,WAAW,EAAE,CAAC;AAEnC,yEAAyE;AACzE,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAAe;IAC7D,KAAK,EAAE,YAAY;IACnB,IAAI,EAAE,OAAO;IACb,QAAQ,EAAE,KAAK;IACf,cAAc,EAAE,GAAG,EAAE,CAAC,SAAS;IAC/B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;CACzB,CAAC,CAAC","sourcesContent":["import { createContext } from 'react';\n\nimport type { ThemeRuntime } from '../../../../types/theme';\nimport { createTheme } from '../../application/use-cases/createTheme';\n\nconst defaultTheme = createTheme();\n\n/*** Holds the active Surface theme runtime for component consumption. */\nexport const ThemeRuntimeContext = createContext<ThemeRuntime>({\n theme: defaultTheme,\n mode: 'light',\n inverted: false,\n setThemeConfig: () => undefined,\n setMode: () => undefined,\n});\n"]}
@@ -1,4 +1,4 @@
1
1
  import type { ThemeScopeProps } from '../../../../types/theme';
2
- /*** Apply a nested Surface theme or mode override without remounting app-level providers. */
3
- export declare function ThemeScope({ children, themeConfig, mode }: ThemeScopeProps): import("react").JSX.Element;
2
+ /*** Apply nested theme, mode, or inherited surface-polarity overrides without remounting providers. */
3
+ export declare function ThemeScope({ children, themeConfig, mode, inverted }: ThemeScopeProps): import("react").JSX.Element;
4
4
  //# sourceMappingURL=ThemeScope.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeScope.d.ts","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeScope.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAM7E,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,eAAe,+BAkB1E"}
1
+ {"version":3,"file":"ThemeScope.d.ts","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeScope.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAM7E,uGAAuG;AACvG,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,eAAe,+BAmBpF"}
@@ -4,14 +4,15 @@ import { useFontRuntime } from '../../../font/adapters/inbound/useFontRuntime';
4
4
  import { createTheme } from '../../application/use-cases/createTheme';
5
5
  import { ThemeRuntimeContext } from './ThemeRuntimeContext';
6
6
  import { useTheme } from './useTheme';
7
- /*** Apply a nested Surface theme or mode override without remounting app-level providers. */
8
- export function ThemeScope({ children, themeConfig, mode }) {
7
+ /*** Apply nested theme, mode, or inherited surface-polarity overrides without remounting providers. */
8
+ export function ThemeScope({ children, themeConfig, mode, inverted }) {
9
9
  const parent = useTheme();
10
10
  const { activeFontId } = useFontRuntime();
11
11
  const scopedMode = mode ?? parent.mode;
12
+ const scopedInverted = inverted ?? parent.inverted ?? false;
12
13
  const scopedConfig = useMemo(() => (themeConfig ? deepMerge(parent.theme.config, themeConfig) : parent.theme.config), [parent.theme.config, themeConfig]);
13
- const theme = useMemo(() => createTheme(scopedConfig, scopedMode, activeFontId), [activeFontId, scopedConfig, scopedMode]);
14
- const value = useMemo(() => ({ ...parent, theme, mode: scopedMode }), [parent, scopedMode, theme]);
14
+ const theme = useMemo(() => createTheme(scopedConfig, scopedMode, activeFontId, scopedInverted), [activeFontId, scopedConfig, scopedMode, scopedInverted]);
15
+ const value = useMemo(() => ({ ...parent, theme, mode: scopedMode, inverted: scopedInverted }), [parent, scopedMode, scopedInverted, theme]);
15
16
  return <ThemeRuntimeContext value={value}>{children}</ThemeRuntimeContext>;
16
17
  }
17
18
  //# sourceMappingURL=ThemeScope.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeScope.js","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeScope.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGhC,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,6FAA6F;AAC7F,MAAM,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAmB;IACzE,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,MAAM,EAAE,YAAY,EAAE,GAAG,cAAc,EAAE,CAAC;IAC1C,MAAM,UAAU,GAAG,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC;IACvC,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EACvF,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CACnC,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,WAAW,CAAC,YAAY,EAAE,UAAU,EAAE,YAAY,CAAC,EACzD,CAAC,YAAY,EAAE,YAAY,EAAE,UAAU,CAAC,CACzC,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAC9C,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,CAC5B,CAAC;IAEF,OAAO,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["import { deepMerge } from '@ankhorage/utility/object';\nimport { useMemo } from 'react';\n\nimport type { ThemeRuntime, ThemeScopeProps } from '../../../../types/theme';\nimport { useFontRuntime } from '../../../font/adapters/inbound/useFontRuntime';\nimport { createTheme } from '../../application/use-cases/createTheme';\nimport { ThemeRuntimeContext } from './ThemeRuntimeContext';\nimport { useTheme } from './useTheme';\n\n/*** Apply a nested Surface theme or mode override without remounting app-level providers. */\nexport function ThemeScope({ children, themeConfig, mode }: ThemeScopeProps) {\n const parent = useTheme();\n const { activeFontId } = useFontRuntime();\n const scopedMode = mode ?? parent.mode;\n const scopedConfig = useMemo(\n () => (themeConfig ? deepMerge(parent.theme.config, themeConfig) : parent.theme.config),\n [parent.theme.config, themeConfig],\n );\n const theme = useMemo(\n () => createTheme(scopedConfig, scopedMode, activeFontId),\n [activeFontId, scopedConfig, scopedMode],\n );\n const value = useMemo<ThemeRuntime>(\n () => ({ ...parent, theme, mode: scopedMode }),\n [parent, scopedMode, theme],\n );\n\n return <ThemeRuntimeContext value={value}>{children}</ThemeRuntimeContext>;\n}\n"]}
1
+ {"version":3,"file":"ThemeScope.js","sourceRoot":"","sources":["../../../../../src/features/theme/adapters/inbound/ThemeScope.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGhC,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,uGAAuG;AACvG,MAAM,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAmB;IACnF,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;IAC1B,MAAM,EAAE,YAAY,EAAE,GAAG,cAAc,EAAE,CAAC;IAC1C,MAAM,UAAU,GAAG,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC;IACvC,MAAM,cAAc,GAAG,QAAQ,IAAI,MAAM,CAAC,QAAQ,IAAI,KAAK,CAAC;IAC5D,MAAM,YAAY,GAAG,OAAO,CAC1B,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EACvF,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CACnC,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,WAAW,CAAC,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,CAAC,EACzE,CAAC,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,CAAC,CACzD,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,EACxE,CAAC,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,KAAK,CAAC,CAC5C,CAAC;IAEF,OAAO,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["import { deepMerge } from '@ankhorage/utility/object';\nimport { useMemo } from 'react';\n\nimport type { ThemeRuntime, ThemeScopeProps } from '../../../../types/theme';\nimport { useFontRuntime } from '../../../font/adapters/inbound/useFontRuntime';\nimport { createTheme } from '../../application/use-cases/createTheme';\nimport { ThemeRuntimeContext } from './ThemeRuntimeContext';\nimport { useTheme } from './useTheme';\n\n/*** Apply nested theme, mode, or inherited surface-polarity overrides without remounting providers. */\nexport function ThemeScope({ children, themeConfig, mode, inverted }: ThemeScopeProps) {\n const parent = useTheme();\n const { activeFontId } = useFontRuntime();\n const scopedMode = mode ?? parent.mode;\n const scopedInverted = inverted ?? parent.inverted ?? false;\n const scopedConfig = useMemo(\n () => (themeConfig ? deepMerge(parent.theme.config, themeConfig) : parent.theme.config),\n [parent.theme.config, themeConfig],\n );\n const theme = useMemo(\n () => createTheme(scopedConfig, scopedMode, activeFontId, scopedInverted),\n [activeFontId, scopedConfig, scopedMode, scopedInverted],\n );\n const value = useMemo<ThemeRuntime>(\n () => ({ ...parent, theme, mode: scopedMode, inverted: scopedInverted }),\n [parent, scopedMode, scopedInverted, theme],\n );\n\n return <ThemeRuntimeContext value={value}>{children}</ThemeRuntimeContext>;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { ThemeConfig } from '@ankhorage/contracts';
2
2
  import type { SurfaceTheme } from '../../../../types/theme';
3
- /*** Resolve canonical persisted theme source into the complete Surface runtime theme. */
4
- export declare function createTheme(config?: ThemeConfig, mode?: 'light' | 'dark', activeFontId?: string | null): SurfaceTheme;
3
+ /*** Resolve canonical theme source into a normal or inverted Surface runtime theme. */
4
+ export declare function createTheme(config?: ThemeConfig, mode?: 'light' | 'dark', activeFontId?: string | null, inverted?: boolean): SurfaceTheme;
5
5
  //# sourceMappingURL=createTheme.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createTheme.d.ts","sourceRoot":"","sources":["../../../../../src/features/theme/application/use-cases/createTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAWxE,yFAAyF;AACzF,wBAAgB,WAAW,CACzB,MAAM,GAAE,WAA4B,EACpC,IAAI,GAAE,OAAO,GAAG,MAAgB,EAChC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAC3B,YAAY,CAWd"}
1
+ {"version":3,"file":"createTheme.d.ts","sourceRoot":"","sources":["../../../../../src/features/theme/application/use-cases/createTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAYxE,uFAAuF;AACvF,wBAAgB,WAAW,CACzB,MAAM,GAAE,WAA4B,EACpC,IAAI,GAAE,OAAO,GAAG,MAAgB,EAChC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,EAC5B,QAAQ,UAAQ,GACf,YAAY,CAad"}
@@ -1,4 +1,5 @@
1
1
  import { generatePalette } from '../../domain/generatePalette';
2
+ import { projectInvertedTheme } from '../../domain/projectInvertedTheme';
2
3
  import { resolveGlobalTokens } from '../../utils/resolveGlobalTokens';
3
4
  const DEFAULT_CONFIG = {
4
5
  id: 'default',
@@ -6,8 +7,8 @@ const DEFAULT_CONFIG = {
6
7
  light: { primaryColor: '#3B82F6', harmony: 'monochromatic' },
7
8
  dark: { primaryColor: '#3B82F6', harmony: 'monochromatic' },
8
9
  };
9
- /*** Resolve canonical persisted theme source into the complete Surface runtime theme. */
10
- export function createTheme(config = DEFAULT_CONFIG, mode = 'light', activeFontId) {
10
+ /*** Resolve canonical theme source into a normal or inverted Surface runtime theme. */
11
+ export function createTheme(config = DEFAULT_CONFIG, mode = 'light', activeFontId, inverted = false) {
11
12
  const { colors, swatches, semantics, colorDiagnostics } = generatePalette(config, mode);
12
13
  const baseTheme = {
13
14
  ...resolveGlobalTokens(config.tokens),
@@ -16,8 +17,10 @@ export function createTheme(config = DEFAULT_CONFIG, mode = 'light', activeFontI
16
17
  semantics,
17
18
  colorDiagnostics,
18
19
  config,
20
+ inverted: false,
19
21
  };
20
- return activeFontId ? withActiveFont(baseTheme, activeFontId) : baseTheme;
22
+ const themed = activeFontId ? withActiveFont(baseTheme, activeFontId) : baseTheme;
23
+ return inverted ? projectInvertedTheme(themed) : themed;
21
24
  }
22
25
  /*** Return a theme with generated module font-family names without mutating the base theme. */
23
26
  function withActiveFont(theme, activeFontId) {
@@ -1 +1 @@
1
- {"version":3,"file":"createTheme.js","sourceRoot":"","sources":["../../../../../src/features/theme/application/use-cases/createTheme.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,MAAM,cAAc,GAAgB;IAClC,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE;IAC5D,IAAI,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE;CAC5D,CAAC;AAEF,yFAAyF;AACzF,MAAM,UAAU,WAAW,CACzB,SAAsB,cAAc,EACpC,OAAyB,OAAO,EAChC,YAA4B;IAE5B,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,GAAG,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACxF,MAAM,SAAS,GAAiB;QAC9B,GAAG,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC;QACrC,MAAM;QACN,QAAQ;QACR,SAAS;QACT,gBAAgB;QAChB,MAAM;KACP,CAAC;IACF,OAAO,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5E,CAAC;AAED,+FAA+F;AAC/F,SAAS,cAAc,CAAC,KAAmB,EAAE,YAAoB;IAC/D,MAAM,UAAU,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAC9C,OAAO;QACL,GAAG,KAAK;QACR,UAAU,EAAE;YACV,GAAG,KAAK,CAAC,UAAU;YACnB,KAAK,EAAE;gBACL,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC;gBAC3E,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC;aAC3E;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CACpB,QAAgD,EAChD,UAAkB,EAClB,KAA2B;IAE3B,OAAO;QACL,GAAG,QAAQ;QACX,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;KACnC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK;SACT,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC","sourcesContent":["import type { ThemeConfig } from '@ankhorage/contracts';\n\nimport type { FontWeight, SurfaceTheme } from '../../../../types/theme';\nimport { generatePalette } from '../../domain/generatePalette';\nimport { resolveGlobalTokens } from '../../utils/resolveGlobalTokens';\n\nconst DEFAULT_CONFIG: ThemeConfig = {\n id: 'default',\n name: 'Default',\n light: { primaryColor: '#3B82F6', harmony: 'monochromatic' },\n dark: { primaryColor: '#3B82F6', harmony: 'monochromatic' },\n};\n\n/*** Resolve canonical persisted theme source into the complete Surface runtime theme. */\nexport function createTheme(\n config: ThemeConfig = DEFAULT_CONFIG,\n mode: 'light' | 'dark' = 'light',\n activeFontId?: string | null,\n): SurfaceTheme {\n const { colors, swatches, semantics, colorDiagnostics } = generatePalette(config, mode);\n const baseTheme: SurfaceTheme = {\n ...resolveGlobalTokens(config.tokens),\n colors,\n swatches,\n semantics,\n colorDiagnostics,\n config,\n };\n return activeFontId ? withActiveFont(baseTheme, activeFontId) : baseTheme;\n}\n\n/*** Return a theme with generated module font-family names without mutating the base theme. */\nfunction withActiveFont(theme: SurfaceTheme, activeFontId: string): SurfaceTheme {\n const familyName = toPascalCase(activeFontId);\n return {\n ...theme,\n typography: {\n ...theme.typography,\n fonts: {\n normal: createFontMap(theme.typography.fonts.normal, familyName, 'Regular'),\n italic: createFontMap(theme.typography.fonts.italic, familyName, 'Italic'),\n },\n },\n };\n}\n\nfunction createFontMap(\n fallback: Record<FontWeight, string | undefined>,\n familyName: string,\n style: 'Regular' | 'Italic',\n): Record<FontWeight, string | undefined> {\n return {\n ...fallback,\n '100': `${familyName}_100${style}`,\n '200': `${familyName}_200${style}`,\n '300': `${familyName}_300${style}`,\n '400': `${familyName}_400${style}`,\n '500': `${familyName}_500${style}`,\n '600': `${familyName}_600${style}`,\n '700': `${familyName}_700${style}`,\n '800': `${familyName}_800${style}`,\n '900': `${familyName}_900${style}`,\n };\n}\n\nfunction toPascalCase(value: string): string {\n return value\n .split(/[- ]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join('');\n}\n"]}
1
+ {"version":3,"file":"createTheme.js","sourceRoot":"","sources":["../../../../../src/features/theme/application/use-cases/createTheme.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,MAAM,cAAc,GAAgB;IAClC,EAAE,EAAE,SAAS;IACb,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE;IAC5D,IAAI,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE;CAC5D,CAAC;AAEF,uFAAuF;AACvF,MAAM,UAAU,WAAW,CACzB,SAAsB,cAAc,EACpC,OAAyB,OAAO,EAChC,YAA4B,EAC5B,QAAQ,GAAG,KAAK;IAEhB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,GAAG,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACxF,MAAM,SAAS,GAAiB;QAC9B,GAAG,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC;QACrC,MAAM;QACN,QAAQ;QACR,SAAS;QACT,gBAAgB;QAChB,MAAM;QACN,QAAQ,EAAE,KAAK;KAChB,CAAC;IACF,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAClF,OAAO,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC1D,CAAC;AAED,+FAA+F;AAC/F,SAAS,cAAc,CAAC,KAAmB,EAAE,YAAoB;IAC/D,MAAM,UAAU,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAC9C,OAAO;QACL,GAAG,KAAK;QACR,UAAU,EAAE;YACV,GAAG,KAAK,CAAC,UAAU;YACnB,KAAK,EAAE;gBACL,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC;gBAC3E,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC;aAC3E;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CACpB,QAAgD,EAChD,UAAkB,EAClB,KAA2B;IAE3B,OAAO;QACL,GAAG,QAAQ;QACX,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;QAClC,KAAK,EAAE,GAAG,UAAU,OAAO,KAAK,EAAE;KACnC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK;SACT,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC","sourcesContent":["import type { ThemeConfig } from '@ankhorage/contracts';\n\nimport type { FontWeight, SurfaceTheme } from '../../../../types/theme';\nimport { generatePalette } from '../../domain/generatePalette';\nimport { projectInvertedTheme } from '../../domain/projectInvertedTheme';\nimport { resolveGlobalTokens } from '../../utils/resolveGlobalTokens';\n\nconst DEFAULT_CONFIG: ThemeConfig = {\n id: 'default',\n name: 'Default',\n light: { primaryColor: '#3B82F6', harmony: 'monochromatic' },\n dark: { primaryColor: '#3B82F6', harmony: 'monochromatic' },\n};\n\n/*** Resolve canonical theme source into a normal or inverted Surface runtime theme. */\nexport function createTheme(\n config: ThemeConfig = DEFAULT_CONFIG,\n mode: 'light' | 'dark' = 'light',\n activeFontId?: string | null,\n inverted = false,\n): SurfaceTheme {\n const { colors, swatches, semantics, colorDiagnostics } = generatePalette(config, mode);\n const baseTheme: SurfaceTheme = {\n ...resolveGlobalTokens(config.tokens),\n colors,\n swatches,\n semantics,\n colorDiagnostics,\n config,\n inverted: false,\n };\n const themed = activeFontId ? withActiveFont(baseTheme, activeFontId) : baseTheme;\n return inverted ? projectInvertedTheme(themed) : themed;\n}\n\n/*** Return a theme with generated module font-family names without mutating the base theme. */\nfunction withActiveFont(theme: SurfaceTheme, activeFontId: string): SurfaceTheme {\n const familyName = toPascalCase(activeFontId);\n return {\n ...theme,\n typography: {\n ...theme.typography,\n fonts: {\n normal: createFontMap(theme.typography.fonts.normal, familyName, 'Regular'),\n italic: createFontMap(theme.typography.fonts.italic, familyName, 'Italic'),\n },\n },\n };\n}\n\nfunction createFontMap(\n fallback: Record<FontWeight, string | undefined>,\n familyName: string,\n style: 'Regular' | 'Italic',\n): Record<FontWeight, string | undefined> {\n return {\n ...fallback,\n '100': `${familyName}_100${style}`,\n '200': `${familyName}_200${style}`,\n '300': `${familyName}_300${style}`,\n '400': `${familyName}_400${style}`,\n '500': `${familyName}_500${style}`,\n '600': `${familyName}_600${style}`,\n '700': `${familyName}_700${style}`,\n '800': `${familyName}_800${style}`,\n '900': `${familyName}_900${style}`,\n };\n}\n\nfunction toPascalCase(value: string): string {\n return value\n .split(/[- ]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join('');\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { SurfaceTheme } from '../../../types/theme';
2
+ /*** Project normal canonical theme semantics onto the opposite surface polarity. */
3
+ export declare function projectInvertedTheme(theme: SurfaceTheme): SurfaceTheme;
4
+ //# sourceMappingURL=projectInvertedTheme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectInvertedTheme.d.ts","sourceRoot":"","sources":["../../../../src/features/theme/domain/projectInvertedTheme.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAMV,YAAY,EAEb,MAAM,sBAAsB,CAAC;AAkB9B,oFAAoF;AACpF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY,CA6CtE"}
@@ -0,0 +1,178 @@
1
+ import { createDefaultSemanticStatusSwatches, parseHexColorOrThrow, selectColorSwatchStep, } from '@ankhorage/color-theory';
2
+ import { SURFACE_COLOR_POLICY } from '../constants';
3
+ import { createSurfaceColorDiagnosticCollector } from './createSurfaceColorDiagnosticCollector';
4
+ import { resolveInverseSurface } from './resolveInverseSurface';
5
+ /*** Project normal canonical theme semantics onto the opposite surface polarity. */
6
+ export function projectInvertedTheme(theme) {
7
+ const collector = createSurfaceColorDiagnosticCollector();
8
+ const lightSurface = theme.colorDiagnostics.mode === 'dark';
9
+ const { neutral } = theme.swatches;
10
+ const { surface, surfaceSeparation } = resolveInverseSurface(theme, lightSurface, collector);
11
+ const selection = createInverseSelection(collector, surface, neutral, lightSurface);
12
+ const content = resolveInverseContent(theme, selection);
13
+ const border = resolveInverseBorder(theme, selection);
14
+ const roles = resolveInverseRoles(theme, selection);
15
+ const { neutralAction, ...semanticRoles } = roles;
16
+ const semantics = {
17
+ ...theme.semantics,
18
+ neutral: resolveInverseNeutral(theme, surface, content, border, neutral, lightSurface),
19
+ surface,
20
+ content,
21
+ border,
22
+ ...semanticRoles,
23
+ error: roles.danger,
24
+ selection: {
25
+ background: roles.brand.softBg,
26
+ content: roles.brand.onSoftText,
27
+ border: border.focus,
28
+ },
29
+ action: { primary: roles.brand, neutral: neutralAction, danger: roles.danger },
30
+ };
31
+ return {
32
+ ...theme,
33
+ inverted: true,
34
+ semantics,
35
+ colors: {
36
+ ...theme.colors,
37
+ background: surface.sunken,
38
+ surface: surface.default,
39
+ text: content.default,
40
+ textSecondary: content.muted,
41
+ border: border.default,
42
+ },
43
+ colorDiagnostics: {
44
+ ...theme.colorDiagnostics,
45
+ selections: [...theme.colorDiagnostics.selections, ...collector.selections],
46
+ contrasts: [...theme.colorDiagnostics.contrasts, ...collector.contrasts],
47
+ surfaceSeparation,
48
+ },
49
+ };
50
+ }
51
+ /*** Select swatch steps against both inverse surface levels. */
52
+ function createInverseSelection(collector, surface, neutral, lightSurface) {
53
+ return {
54
+ collector,
55
+ neutral,
56
+ contexts: [
57
+ {
58
+ id: 'inverse-surface',
59
+ against: parseHexColorOrThrow(surface.default),
60
+ minimumContrast: SURFACE_COLOR_POLICY.textContrast,
61
+ },
62
+ {
63
+ id: 'inverse-subtle',
64
+ against: parseHexColorOrThrow(surface.subtle),
65
+ minimumContrast: SURFACE_COLOR_POLICY.textContrast,
66
+ },
67
+ {
68
+ id: 'inverse-sunken',
69
+ against: parseHexColorOrThrow(surface.sunken),
70
+ minimumContrast: SURFACE_COLOR_POLICY.textContrast,
71
+ },
72
+ ],
73
+ tiePolicy: lightSurface ? 'higher-step' : 'lower-step',
74
+ textTarget: { lightness: lightSurface ? 0.2 : 0.9, chroma: 0.02 },
75
+ mutedTarget: { lightness: lightSurface ? 0.35 : 0.75, chroma: 0.02 },
76
+ subtleTarget: { lightness: lightSurface ? 0.4 : 0.7, chroma: 0.02 },
77
+ borderTarget: { lightness: lightSurface ? 0.45 : 0.65, chroma: 0.02 },
78
+ };
79
+ }
80
+ /*** Resolve all surface-relative content colors against inverse backgrounds. */
81
+ function resolveInverseContent(theme, selection) {
82
+ const { neutral, primary } = theme.swatches;
83
+ const secondary = theme.swatches.secondary ?? primary;
84
+ return {
85
+ default: selectText('content.default', neutral, selection.textTarget, selection),
86
+ muted: selectText('content.muted', neutral, selection.mutedTarget, selection),
87
+ subtle: selectText('content.subtle', neutral, selection.subtleTarget, selection),
88
+ disabled: selectText('content.disabled', neutral, selection.subtleTarget, selection, SURFACE_COLOR_POLICY.disabledContrast),
89
+ icon: selectText('content.icon', neutral, selection.textTarget, selection),
90
+ link: selectText('content.link', primary, selection.textTarget, selection),
91
+ visited: selectText('content.visited', secondary, selection.textTarget, selection),
92
+ inverse: theme.semantics.content.default,
93
+ };
94
+ }
95
+ /*** Resolve separators and focus chrome against inverse backgrounds. */
96
+ function resolveInverseBorder(theme, selection) {
97
+ const { neutral } = theme.swatches;
98
+ const outline = selection.borderTarget;
99
+ return {
100
+ default: selectOutline('border.default', neutral, outline, selection),
101
+ subtle: selectOutline('border.subtle', neutral, outline, selection),
102
+ strong: selectOutline('border.strong', neutral, outline, selection),
103
+ divider: selectOutline('border.divider', neutral, outline, selection),
104
+ focus: selectOutline('border.focus', theme.swatches.primary, selection.textTarget, selection),
105
+ };
106
+ }
107
+ /*** Project only surface-relative role fields and preserve self-owned color pairs. */
108
+ function resolveInverseRoles(theme, selection) {
109
+ const status = createDefaultSemanticStatusSwatches().swatches;
110
+ const { semantics } = theme;
111
+ return {
112
+ brand: projectRole('brand', semantics.brand, theme.swatches.primary, selection),
113
+ secondary: projectRole('secondary', semantics.secondary, theme.swatches.secondary ?? theme.swatches.primary, selection),
114
+ accent: projectRole('accent', semantics.accent, theme.swatches.tertiary ?? theme.swatches.primary, selection),
115
+ highlight: projectRole('highlight', semantics.highlight, theme.swatches.quaternary ?? theme.swatches.primary, selection),
116
+ danger: projectRole('danger', semantics.danger, status.danger, selection),
117
+ success: projectRole('success', semantics.success, status.success, selection),
118
+ warning: projectRole('warning', semantics.warning, status.warning, selection),
119
+ info: projectRole('info', semantics.info, status.info, selection),
120
+ neutralAction: projectRole('neutral', semantics.action.neutral, theme.swatches.neutral, selection),
121
+ };
122
+ }
123
+ /*** Keep opaque and soft role pairs intact while selecting inverse-safe transparent colors. */
124
+ function projectRole(id, role, swatch, selection) {
125
+ return {
126
+ ...role,
127
+ onSurfaceText: selectText(`${id}.onSurfaceText`, swatch, selection.textTarget, selection),
128
+ outline: selectOutline(`${id}.outline`, swatch, selection.borderTarget, selection),
129
+ };
130
+ }
131
+ /*** Keep direct neutral semantic reads aligned with active surface polarity. */
132
+ function resolveInverseNeutral(theme, surface, content, border, swatch, lightSurface) {
133
+ return {
134
+ ...theme.semantics.neutral,
135
+ bg: surface.sunken,
136
+ bgSubtle: surface.subtle,
137
+ surface: surface.default,
138
+ surfaceHover: lightSurface ? swatch[200] : swatch[700],
139
+ surfaceActive: lightSurface ? swatch[300] : swatch[600],
140
+ border: border.default,
141
+ borderStrong: border.strong,
142
+ divider: border.divider,
143
+ text: content.default,
144
+ textMuted: content.muted,
145
+ textSubtle: content.subtle,
146
+ disabledBg: surface.disabled,
147
+ disabledText: content.disabled,
148
+ };
149
+ }
150
+ /*** Select and measure inverse-surface text through Color Theory. */
151
+ function selectText(id, swatch, target, selection, minimumContrast = SURFACE_COLOR_POLICY.textContrast) {
152
+ const contexts = selection.contexts.map((context) => ({ ...context, minimumContrast }));
153
+ const color = selectInverseColor(id, swatch, target, contexts, selection);
154
+ for (const context of contexts) {
155
+ selection.collector.measureForeground(`inverse.${id}/${context.id}`, color, context.against, minimumContrast);
156
+ }
157
+ return color;
158
+ }
159
+ /*** Select inverse-surface outlines with the UI contrast policy. */
160
+ function selectOutline(id, swatch, target, selection) {
161
+ const contexts = selection.contexts.map((context) => ({
162
+ ...context,
163
+ minimumContrast: SURFACE_COLOR_POLICY.uiContrast,
164
+ }));
165
+ const color = selectInverseColor(id, swatch, target, contexts, selection);
166
+ for (const context of contexts) {
167
+ selection.collector.measureForeground(`inverse.${id}/${context.id}`, color, context.against, SURFACE_COLOR_POLICY.uiContrast);
168
+ }
169
+ return color;
170
+ }
171
+ /*** Keep inverse contrast safe when a chromatic swatch cannot meet the policy. */
172
+ function selectInverseColor(id, swatch, target, contexts, selection) {
173
+ const result = selectColorSwatchStep(swatch, target, contexts, selection.tiePolicy);
174
+ selection.collector.selections.push({ id: `inverse.${id}`, result });
175
+ return (result.selected?.hex ??
176
+ selection.collector.selectColor(`inverse.${id}.neutralFallback`, selection.neutral, target, contexts, selection.tiePolicy));
177
+ }
178
+ //# sourceMappingURL=projectInvertedTheme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectInvertedTheme.js","sourceRoot":"","sources":["../../../../src/features/theme/domain/projectInvertedTheme.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ColorContrastContext,\n ColorSelectionTarget,\n ColorSwatch,\n ColorSwatchTiePolicy,\n HexColor,\n} from '@ankhorage/color-theory';\nimport {\n createDefaultSemanticStatusSwatches,\n parseHexColorOrThrow,\n selectColorSwatchStep,\n} from '@ankhorage/color-theory';\n\nimport type {\n BorderSemantics,\n ContentSemantics,\n NeutralSemantics,\n RoleSemantics,\n SurfaceSemantics,\n SurfaceTheme,\n ThemeSemantics,\n} from '../../../types/theme';\nimport { SURFACE_COLOR_POLICY } from '../constants';\nimport { createSurfaceColorDiagnosticCollector } from './createSurfaceColorDiagnosticCollector';\nimport { resolveInverseSurface } from './resolveInverseSurface';\n\ntype Collector = ReturnType<typeof createSurfaceColorDiagnosticCollector>;\n\ninterface InverseSelection {\n collector: Collector;\n contexts: readonly ColorContrastContext[];\n tiePolicy: ColorSwatchTiePolicy;\n textTarget: ColorSelectionTarget;\n mutedTarget: ColorSelectionTarget;\n subtleTarget: ColorSelectionTarget;\n borderTarget: ColorSelectionTarget;\n neutral: ColorSwatch;\n}\n\n/*** Project normal canonical theme semantics onto the opposite surface polarity. */\nexport function projectInvertedTheme(theme: SurfaceTheme): SurfaceTheme {\n const collector = createSurfaceColorDiagnosticCollector();\n const lightSurface = theme.colorDiagnostics.mode === 'dark';\n const { neutral } = theme.swatches;\n const { surface, surfaceSeparation } = resolveInverseSurface(theme, lightSurface, collector);\n const selection = createInverseSelection(collector, surface, neutral, lightSurface);\n const content = resolveInverseContent(theme, selection);\n const border = resolveInverseBorder(theme, selection);\n const roles = resolveInverseRoles(theme, selection);\n const { neutralAction, ...semanticRoles } = roles;\n const semantics: ThemeSemantics = {\n ...theme.semantics,\n neutral: resolveInverseNeutral(theme, surface, content, border, neutral, lightSurface),\n surface,\n content,\n border,\n ...semanticRoles,\n error: roles.danger,\n selection: {\n background: roles.brand.softBg,\n content: roles.brand.onSoftText,\n border: border.focus,\n },\n action: { primary: roles.brand, neutral: neutralAction, danger: roles.danger },\n };\n\n return {\n ...theme,\n inverted: true,\n semantics,\n colors: {\n ...theme.colors,\n background: surface.sunken,\n surface: surface.default,\n text: content.default,\n textSecondary: content.muted,\n border: border.default,\n },\n colorDiagnostics: {\n ...theme.colorDiagnostics,\n selections: [...theme.colorDiagnostics.selections, ...collector.selections],\n contrasts: [...theme.colorDiagnostics.contrasts, ...collector.contrasts],\n surfaceSeparation,\n },\n };\n}\n\n/*** Select swatch steps against both inverse surface levels. */\nfunction createInverseSelection(\n collector: Collector,\n surface: SurfaceSemantics,\n neutral: ColorSwatch,\n lightSurface: boolean,\n): InverseSelection {\n return {\n collector,\n neutral,\n contexts: [\n {\n id: 'inverse-surface',\n against: parseHexColorOrThrow(surface.default),\n minimumContrast: SURFACE_COLOR_POLICY.textContrast,\n },\n {\n id: 'inverse-subtle',\n against: parseHexColorOrThrow(surface.subtle),\n minimumContrast: SURFACE_COLOR_POLICY.textContrast,\n },\n {\n id: 'inverse-sunken',\n against: parseHexColorOrThrow(surface.sunken),\n minimumContrast: SURFACE_COLOR_POLICY.textContrast,\n },\n ],\n tiePolicy: lightSurface ? 'higher-step' : 'lower-step',\n textTarget: { lightness: lightSurface ? 0.2 : 0.9, chroma: 0.02 },\n mutedTarget: { lightness: lightSurface ? 0.35 : 0.75, chroma: 0.02 },\n subtleTarget: { lightness: lightSurface ? 0.4 : 0.7, chroma: 0.02 },\n borderTarget: { lightness: lightSurface ? 0.45 : 0.65, chroma: 0.02 },\n };\n}\n\n/*** Resolve all surface-relative content colors against inverse backgrounds. */\nfunction resolveInverseContent(theme: SurfaceTheme, selection: InverseSelection): ContentSemantics {\n const { neutral, primary } = theme.swatches;\n const secondary = theme.swatches.secondary ?? primary;\n return {\n default: selectText('content.default', neutral, selection.textTarget, selection),\n muted: selectText('content.muted', neutral, selection.mutedTarget, selection),\n subtle: selectText('content.subtle', neutral, selection.subtleTarget, selection),\n disabled: selectText(\n 'content.disabled',\n neutral,\n selection.subtleTarget,\n selection,\n SURFACE_COLOR_POLICY.disabledContrast,\n ),\n icon: selectText('content.icon', neutral, selection.textTarget, selection),\n link: selectText('content.link', primary, selection.textTarget, selection),\n visited: selectText('content.visited', secondary, selection.textTarget, selection),\n inverse: theme.semantics.content.default,\n };\n}\n\n/*** Resolve separators and focus chrome against inverse backgrounds. */\nfunction resolveInverseBorder(theme: SurfaceTheme, selection: InverseSelection): BorderSemantics {\n const { neutral } = theme.swatches;\n const outline = selection.borderTarget;\n return {\n default: selectOutline('border.default', neutral, outline, selection),\n subtle: selectOutline('border.subtle', neutral, outline, selection),\n strong: selectOutline('border.strong', neutral, outline, selection),\n divider: selectOutline('border.divider', neutral, outline, selection),\n focus: selectOutline('border.focus', theme.swatches.primary, selection.textTarget, selection),\n };\n}\n\n/*** Project only surface-relative role fields and preserve self-owned color pairs. */\nfunction resolveInverseRoles(theme: SurfaceTheme, selection: InverseSelection) {\n const status = createDefaultSemanticStatusSwatches().swatches;\n const { semantics } = theme;\n return {\n brand: projectRole('brand', semantics.brand, theme.swatches.primary, selection),\n secondary: projectRole(\n 'secondary',\n semantics.secondary,\n theme.swatches.secondary ?? theme.swatches.primary,\n selection,\n ),\n accent: projectRole(\n 'accent',\n semantics.accent,\n theme.swatches.tertiary ?? theme.swatches.primary,\n selection,\n ),\n highlight: projectRole(\n 'highlight',\n semantics.highlight,\n theme.swatches.quaternary ?? theme.swatches.primary,\n selection,\n ),\n danger: projectRole('danger', semantics.danger, status.danger, selection),\n success: projectRole('success', semantics.success, status.success, selection),\n warning: projectRole('warning', semantics.warning, status.warning, selection),\n info: projectRole('info', semantics.info, status.info, selection),\n neutralAction: projectRole(\n 'neutral',\n semantics.action.neutral,\n theme.swatches.neutral,\n selection,\n ),\n };\n}\n\n/*** Keep opaque and soft role pairs intact while selecting inverse-safe transparent colors. */\nfunction projectRole(\n id: string,\n role: RoleSemantics,\n swatch: ColorSwatch,\n selection: InverseSelection,\n): RoleSemantics {\n return {\n ...role,\n onSurfaceText: selectText(`${id}.onSurfaceText`, swatch, selection.textTarget, selection),\n outline: selectOutline(`${id}.outline`, swatch, selection.borderTarget, selection),\n };\n}\n\n/*** Keep direct neutral semantic reads aligned with active surface polarity. */\nfunction resolveInverseNeutral(\n theme: SurfaceTheme,\n surface: SurfaceSemantics,\n content: ContentSemantics,\n border: BorderSemantics,\n swatch: ColorSwatch,\n lightSurface: boolean,\n): NeutralSemantics {\n return {\n ...theme.semantics.neutral,\n bg: surface.sunken,\n bgSubtle: surface.subtle,\n surface: surface.default,\n surfaceHover: lightSurface ? swatch[200] : swatch[700],\n surfaceActive: lightSurface ? swatch[300] : swatch[600],\n border: border.default,\n borderStrong: border.strong,\n divider: border.divider,\n text: content.default,\n textMuted: content.muted,\n textSubtle: content.subtle,\n disabledBg: surface.disabled,\n disabledText: content.disabled,\n };\n}\n\n/*** Select and measure inverse-surface text through Color Theory. */\nfunction selectText(\n id: string,\n swatch: ColorSwatch,\n target: ColorSelectionTarget,\n selection: InverseSelection,\n minimumContrast: number = SURFACE_COLOR_POLICY.textContrast,\n): HexColor {\n const contexts = selection.contexts.map((context) => ({ ...context, minimumContrast }));\n const color = selectInverseColor(id, swatch, target, contexts, selection);\n for (const context of contexts) {\n selection.collector.measureForeground(\n `inverse.${id}/${context.id}`,\n color,\n context.against,\n minimumContrast,\n );\n }\n return color;\n}\n\n/*** Select inverse-surface outlines with the UI contrast policy. */\nfunction selectOutline(\n id: string,\n swatch: ColorSwatch,\n target: ColorSelectionTarget,\n selection: InverseSelection,\n): HexColor {\n const contexts = selection.contexts.map((context) => ({\n ...context,\n minimumContrast: SURFACE_COLOR_POLICY.uiContrast,\n }));\n const color = selectInverseColor(id, swatch, target, contexts, selection);\n for (const context of contexts) {\n selection.collector.measureForeground(\n `inverse.${id}/${context.id}`,\n color,\n context.against,\n SURFACE_COLOR_POLICY.uiContrast,\n );\n }\n return color;\n}\n\n/*** Keep inverse contrast safe when a chromatic swatch cannot meet the policy. */\nfunction selectInverseColor(\n id: string,\n swatch: ColorSwatch,\n target: ColorSelectionTarget,\n contexts: readonly ColorContrastContext[],\n selection: InverseSelection,\n): HexColor {\n const result = selectColorSwatchStep(swatch, target, contexts, selection.tiePolicy);\n selection.collector.selections.push({ id: `inverse.${id}`, result });\n return (\n result.selected?.hex ??\n selection.collector.selectColor(\n `inverse.${id}.neutralFallback`,\n selection.neutral,\n target,\n contexts,\n selection.tiePolicy,\n )\n );\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { SurfaceContrastDiagnostic, SurfaceSemantics, SurfaceTheme } from '../../../types/theme';
2
+ import type { createSurfaceColorDiagnosticCollector } from './createSurfaceColorDiagnosticCollector';
3
+ type Collector = ReturnType<typeof createSurfaceColorDiagnosticCollector>;
4
+ /*** Resolve inverted surface levels and measure their effective separation. */
5
+ export declare function resolveInverseSurface(theme: SurfaceTheme, lightSurface: boolean, collector: Collector): {
6
+ surface: SurfaceSemantics;
7
+ surfaceSeparation: SurfaceContrastDiagnostic[];
8
+ };
9
+ export {};
10
+ //# sourceMappingURL=resolveInverseSurface.d.ts.map