@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.
- package/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/dist/features/badge/adapters/inbound/Badge.d.ts.map +1 -1
- package/dist/features/badge/adapters/inbound/Badge.js +1 -1
- package/dist/features/badge/adapters/inbound/Badge.js.map +1 -1
- package/dist/features/button/adapters/inbound/Button.js +1 -2
- package/dist/features/button/adapters/inbound/Button.js.map +1 -1
- package/dist/features/icon/adapters/inbound/Icon.d.ts.map +1 -1
- package/dist/features/icon/adapters/inbound/Icon.js +9 -1
- package/dist/features/icon/adapters/inbound/Icon.js.map +1 -1
- package/dist/features/theme/adapters/inbound/ThemeProvider.d.ts.map +1 -1
- package/dist/features/theme/adapters/inbound/ThemeProvider.js +1 -0
- package/dist/features/theme/adapters/inbound/ThemeProvider.js.map +1 -1
- package/dist/features/theme/adapters/inbound/ThemeRuntimeContext.d.ts.map +1 -1
- package/dist/features/theme/adapters/inbound/ThemeRuntimeContext.js +1 -0
- package/dist/features/theme/adapters/inbound/ThemeRuntimeContext.js.map +1 -1
- package/dist/features/theme/adapters/inbound/ThemeScope.d.ts +2 -2
- package/dist/features/theme/adapters/inbound/ThemeScope.d.ts.map +1 -1
- package/dist/features/theme/adapters/inbound/ThemeScope.js +5 -4
- package/dist/features/theme/adapters/inbound/ThemeScope.js.map +1 -1
- package/dist/features/theme/application/use-cases/createTheme.d.ts +2 -2
- package/dist/features/theme/application/use-cases/createTheme.d.ts.map +1 -1
- package/dist/features/theme/application/use-cases/createTheme.js +6 -3
- package/dist/features/theme/application/use-cases/createTheme.js.map +1 -1
- package/dist/features/theme/domain/projectInvertedTheme.d.ts +4 -0
- package/dist/features/theme/domain/projectInvertedTheme.d.ts.map +1 -0
- package/dist/features/theme/domain/projectInvertedTheme.js +178 -0
- package/dist/features/theme/domain/projectInvertedTheme.js.map +1 -0
- package/dist/features/theme/domain/resolveInverseSurface.d.ts +10 -0
- package/dist/features/theme/domain/resolveInverseSurface.d.ts.map +1 -0
- package/dist/features/theme/domain/resolveInverseSurface.js +31 -0
- package/dist/features/theme/domain/resolveInverseSurface.js.map +1 -0
- package/dist/features/typography/adapters/inbound/Text.d.ts +1 -1
- package/dist/features/typography/adapters/inbound/Text.d.ts.map +1 -1
- package/dist/features/typography/adapters/inbound/Text.js +2 -1
- package/dist/features/typography/adapters/inbound/Text.js.map +1 -1
- package/dist/internal/resolvers/resolveInteractiveColors.d.ts.map +1 -1
- package/dist/internal/resolvers/resolveInteractiveColors.js +10 -2
- package/dist/internal/resolvers/resolveInteractiveColors.js.map +1 -1
- package/dist/internal/resolvers/resolveTextColor.d.ts.map +1 -1
- package/dist/internal/resolvers/resolveTextColor.js +2 -1
- package/dist/internal/resolvers/resolveTextColor.js.map +1 -1
- package/dist/types/theme.d.ts +3 -0
- package/dist/types/theme.d.ts.map +1 -1
- package/dist/types/theme.js.map +1 -1
- package/dist/types/typography.d.ts +1 -0
- package/dist/types/typography.d.ts.map +1 -1
- package/dist/types/typography.js.map +1 -1
- package/package.json +3 -3
- package/src/features/badge/adapters/inbound/Badge.tsx +1 -6
- package/src/features/button/adapters/inbound/Button.tsx +1 -3
- package/src/features/icon/adapters/inbound/Icon.tsx +12 -1
- package/src/features/icon/adapters/inbound/PortableIcon.test.tsx +32 -0
- package/src/features/theme/adapters/inbound/ThemeProvider.tsx +1 -0
- package/src/features/theme/adapters/inbound/ThemeRuntimeContext.tsx +1 -0
- package/src/features/theme/adapters/inbound/ThemeScope.test.tsx +38 -7
- package/src/features/theme/adapters/inbound/ThemeScope.tsx +7 -6
- package/src/features/theme/application/use-cases/createTheme.ts +6 -2
- package/src/features/theme/domain/projectInvertedTheme.ts +300 -0
- package/src/features/theme/domain/resolveInverseSurface.ts +55 -0
- package/src/features/typography/adapters/inbound/Text.tsx +2 -0
- package/src/internal/resolvers/resolveInteractiveColors.test.ts +1 -1
- package/src/internal/resolvers/resolveInteractiveColors.ts +12 -2
- package/src/internal/resolvers/resolveTextColor.test.ts +5 -0
- package/src/internal/resolvers/resolveTextColor.ts +2 -1
- package/src/invertedThemeAcceptance.test.ts +204 -0
- package/src/types/theme.ts +3 -0
- 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
|
-
         
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,IAAI,IAAI,eAAe,EAAkB,MAAM,cAAc,CAAC;AAE1F,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,GAChB,MAAM,gCAAgC,CAAC;AAIxC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAElD,+EAA+E;AAC/E,MAAM,UAAU,MAAM,CAAC,EACrB,QAAQ,EACR,OAAO,GAAG,OAAO,EACjB,KAAK,GAAG,SAAS,EACjB,IAAI,GAAG,GAAG,EACV,QAAQ,GAAG,KAAK,EAChB,OAAO,GAAG,KAAK,EACf,WAAW,EACX,YAAY,EACZ,SAAS,GAAG,KAAK,EACjB,OAAO,EACP,MAAM,EACN,GAAG,KAAK,EACI;IACZ,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC7B,MAAM,WAAW,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEpD,OAAO,CACL,CAAC,SAAS,CACR,IAAI,KAAK,CAAC,CACV,QAAQ,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,CAC9B,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,KAAK,CAAC,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC,CACxC,MAAM,CAAC,CAAC,MAAM,CAAC,CAEf;MAAA,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACV,CAAC,aAAa,CACZ,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,SAAS,CAAC,CAAC,SAAS,CAAC,CACrB,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,IAAI,CAAC,CAAC,IAAI,CAAC,CACX,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,KAAK,CAAC,CAAC,KAAK,CAAC,CACb,YAAY,CAAC,CAAC,YAAY,CAAC,CAC3B,OAAO,CAAC,CAAC,OAAO,CAAC,CAEjB;UAAA,CAAC,QAAQ,CACX;QAAA,EAAE,aAAa,CAAC,CACjB,CACH;IAAA,EAAE,SAAS,CAAC,CACb,CAAC;AACJ,CAAC;AAED,2EAA2E;AAC3E,SAAS,aAAa,CAAC,EACrB,QAAQ,EACR,KAAK,EACL,WAAW,EACX,SAAS,EACT,WAAW,EACX,OAAO,EACP,IAAI,EACJ,KAAK,EACL,KAAK,EACL,YAAY,EACZ,OAAO,GACY;IACnB,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,MAAM,
|
|
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":"
|
|
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 =
|
|
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":"
|
|
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,+
|
|
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,
|
|
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"}
|
|
@@ -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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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;
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|