import React, { useEffect, useRef, useState } from 'react'
import Button from '../Button/Button'
import Image from '../Image/Image'
import LabelAndData from '../LabelAndData/LabelAndData'
import Tag from '../Tag/Tag'
import TrimText from '../TrimText/TrimText'
import { useMediaQuery } from '../../hooks/responsiveHooks'
import { type LabelAndDataProps } from '../LabelAndData/LabelAndData'
import { type TagProps } from '../Tag/Tag'
import ScrollingContainer from '../ScrollingContainer/ScrollingContainer'
import styles from './_information-pane.module.scss'
type Header = {
/** The header label and data that appears in the left side of the header */
labelAndData?: Omit<
LabelAndDataProps,
'children' | 'customClass' | 'labelClass'
>
/** The tag that appears in the right side of the header */
tag?: TagProps
/** The edit function to be passed into the edit icon in the right side of the header */
edit?: () => void
}
export type InformationPaneProps = {
/** InformationPane will accept any children elements. It is recommended to use the components defined in this file - ImageAndName, Section, CustomSection, and Divider - to achieve the desired design. */
children: React.ReactNode
/** The header that will be displayed when `simple` is not defined. This will always be displayed in the desktop view, even if `simple` is defined. */
header?: Header
/** Optional prop to simplify the mobile view for this component. */
simple?: SimpleProps
/** Indicates if the page has a PageFooter component, which affects container height calculations */
includePageFooterHeight?: boolean
/** Optionally hide gradient overlays in the scrolling container */
hideGradients?: boolean
/** Optional prop to add a test id to the InformationPane for QA testing */
qaTestId?: string
}
const InformationPane = ({
header,
children,
simple,
includePageFooterHeight = false,
hideGradients = false,
qaTestId = 'information-pane',
}: InformationPaneProps): React.JSX.Element => {
const mobileView = useMediaQuery({ type: 'max', breakpoint: 'sm' })
return simple && mobileView ? (
) : (
)
}
type SectionProps = {
/** Array of LabelAndData props that will populate in this section */
data: Omit[]
/** Boolean used to style the section into 1 or 2 columns. 1 column is the default. */
isTwoColumns?: boolean
}
const Section = ({ data, isTwoColumns }: SectionProps): React.JSX.Element => {
return (
{data.map((d, index) => (
))}
)
}
type CustomSectionProps = {
/** The children elements to be passed into the component. */
children: React.ReactNode
}
const CustomSection = ({ children }: CustomSectionProps) => {
return
{children}
}
const Divider = (): React.JSX.Element => {
return
}
type SimpleProps = ImageAndNameProps & {
/** The product identifier */
identifier: string
/** Optional prop to add a test id to the Simple for QA testing */
qaTestId?: string
}
const Simple = ({
imgUrl,
product,
identifier,
qaTestId,
}: SimpleProps): React.JSX.Element => {
const [touchY, setTouchY] = useState(0)
const [direction, setDirection] = useState<'down' | 'up'>('down')
const ref = useRef(null)
useEffect(() => {
let prevScrollPos = ref.current?.getBoundingClientRect().y || 0
const scroll = () => {
const currentScrollPos = ref.current?.getBoundingClientRect().y || 0
if (ref.current) {
if (prevScrollPos > currentScrollPos) {
setDirection('up')
}
if (currentScrollPos > prevScrollPos) {
setDirection('down')
}
prevScrollPos = currentScrollPos
}
}
window.addEventListener('wheel', scroll)
return () => {
window.removeEventListener('wheel', scroll)
}
}, [])
useEffect(() => {
const handleTouchMove = (event: TouchEvent) => {
const newY = event.touches[0].clientY
if (touchY !== null) {
const deltaY = newY - touchY
if (deltaY > 0) {
setDirection('down')
} else if (deltaY < 0) {
setDirection('up')
}
}
setTouchY(newY)
}
window.addEventListener('touchmove', handleTouchMove)
return () => {
window.removeEventListener('touchmove', handleTouchMove)
}
}, [touchY])
const imageSmallSize = 72 //The image size is set to small when scrolling up for a more compact view
const imageLargeSize = 175 //The image size is set to large when scrolling down for a more detailed view
const imageSize = direction === 'up' ? imageSmallSize : imageLargeSize
const ProductName = ({ className = '' }: { className?: string }) => {
const classes = `${styles.productName} ${className}`
return direction === 'up' ? (
) : (
{product.name}
)
}
return (