import { resolveResponsive, useResponsiveRuntime } from '@ankhorage/surface'; import React from 'react'; import { Platform, Text as ReactNativeText, type TextStyle } from 'react-native'; import type { HeadingProps } from '../../../../types/heading'; import { withZoraThemeScope } from '../../../theme/adapters/inbound/withZoraThemeScope'; import { useZoraTheme } from '../../../theme/composition/useZoraTheme'; import { useZoraThemeRecipe } from '../../../theme/composition/useZoraThemeRecipe'; import { resolveHeadingRecipe } from '../../utils/resolveHeadingRecipe'; import { resolveHeadingSizeFromLevel } from '../../utils/resolveHeadingSizeFromLevel'; import { resolveHeadingThemeRecipe } from '../../utils/resolveHeadingThemeRecipe'; /*** * Structured title primitive for accessible page, section, and card headings. * * `Heading` gives consumers a ZORA-owned title API with semantic levels, * responsive sizes, and theme-aware emphasis while preserving header semantics. * * @example Section title * ```tsx * Account settings * ``` */ export const Heading = withZoraThemeScope(HeadingInner); const headingLayoutStyle: TextStyle = { flexShrink: 1, maxWidth: '100%', minWidth: 0, ...(Platform.OS === 'web' ? { overflowWrap: 'break-word', whiteSpace: 'normal', wordBreak: 'normal', } : null), }; function resolveHeadingContent({ children, text, i18nKey, }: Pick) { if (children !== undefined) return children; if (text !== undefined) return text; if (i18nKey === undefined || i18nKey === '') return null; return i18nKey; } function HeadingInner({ themeId: _themeId, mode: _mode, children, text, i18nKey, level = 2, size, color, emphasis, align, weight, italic, numberOfLines, ellipsizeMode, selectable, style, accessibilityLabel, accessibilityHint, accessibilityRole, nativeID, testID, interactionPolicy: _interactionPolicy, }: HeadingProps) { const { theme } = useZoraTheme(); const { breakpoint } = useResponsiveRuntime(); const themeRecipe = resolveHeadingThemeRecipe(useZoraThemeRecipe('Heading')); const content = resolveHeadingContent({ children, text, i18nKey }); const resolvedSize = resolveResponsive(size ?? themeRecipe.size, breakpoint) ?? resolveHeadingSizeFromLevel(level); const resolvedColor = resolveResponsive(color ?? themeRecipe.color, breakpoint); const resolvedEmphasis = resolveResponsive(emphasis ?? themeRecipe.emphasis, breakpoint) ?? 'default'; const resolvedAlign = resolveResponsive(align ?? themeRecipe.align, breakpoint); const resolvedWeight = resolveResponsive(weight ?? themeRecipe.weight, breakpoint); if (content === null) return null; return ( {content} ); }