import React, { useMemo, useContext, useEffect } from "react"; import { ImageStyle, StyleSheet, View, ViewStyle } from "react-native"; import { useAccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks"; import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils"; import { MeasurementPortalContext } from "../../../MeasurmentsPortal/MeasurementsPortal"; type BorderPosition = "inside" | "outside" | "center"; interface Props { hasFocusableInside: (entry: ZappEntry) => boolean; entry: ZappEntry; state: CellState; hasTextLabels: boolean; style: ImageStyle | ViewStyle; borderPosition: BorderPosition; borderPaddingTop: number; borderPaddingRight: number; borderPaddingBottom: number; borderPaddingLeft: number; children: React.ReactNode; } const COLOR_TRANSPARENT = "transparent"; const styles = StyleSheet.create({ container: { overflow: "visible", borderWidth: 0, borderColor: COLOR_TRANSPARENT, }, border: { ...StyleSheet.absoluteFillObject, zIndex: 1, }, }); export const getBorderPadding = ( borderPosition: BorderPosition, borderWidth: number ) => { switch (borderPosition) { case "inside": return 0; case "center": return borderWidth / 2; case "outside": return borderWidth; default: return borderWidth; } }; const Border = ({ style, padding, borderPosition, }: { style: ViewStyle; padding: ViewStyle; borderPosition: BorderPosition; }) => { if (!borderPosition) { return null; } const borderWidth = toNumberWithDefaultZero(style.borderWidth); const containerPadding = getBorderPadding(borderPosition, borderWidth); const initialBorderRadius = toNumberWithDefaultZero(style.borderRadius); const paddingTop = toNumberWithDefaultZero(padding.paddingTop); const paddingRight = toNumberWithDefaultZero(padding.paddingRight); const paddingBottom = toNumberWithDefaultZero(padding.paddingBottom); const paddingLeft = toNumberWithDefaultZero(padding.paddingLeft); const borderRadiusStyle = initialBorderRadius ? { borderTopLeftRadius: initialBorderRadius + containerPadding + Math.min(paddingTop, paddingLeft), borderTopRightRadius: initialBorderRadius + containerPadding + Math.min(paddingTop, paddingRight), borderBottomLeftRadius: initialBorderRadius + containerPadding + Math.min(paddingBottom, paddingLeft), borderBottomRightRadius: initialBorderRadius + containerPadding + Math.min(paddingBottom, paddingRight), } : { borderTopLeftRadius: 0, borderTopRightRadius: 0, borderBottomLeftRadius: 0, borderBottomRightRadius: 0, }; return ( ); }; export const BorderContainerView = (props: Props) => { const { borderPosition, borderPaddingTop, borderPaddingRight, borderPaddingBottom, borderPaddingLeft, style, children, hasFocusableInside, entry, state, hasTextLabels, } = props; const accessibilityManager = useAccessibilityManager(); const isMeasurement = useContext(MeasurementPortalContext); const isImageOnlyCell = useMemo( () => !hasFocusableInside(entry) && !hasTextLabels && state === "focused" && !isMeasurement?.measuringInProgress, [ hasFocusableInside, entry, hasTextLabels, state, isMeasurement?.measuringInProgress, ] ); useEffect(() => { if (isImageOnlyCell && entry?.title) { accessibilityManager.addHeading(String(entry.title)); } }, [isImageOnlyCell, entry?.title]); const padding = borderPosition === "outside" ? { paddingTop: borderPaddingTop, paddingRight: borderPaddingRight, paddingBottom: borderPaddingBottom, paddingLeft: borderPaddingLeft, } : {}; return ( {children} ); };