{"version":3,"file":"OverviewTechSpecs-Chunk-c95a41260302ddae1a56.js","mappings":"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","sources":["webpack://nikon-client/./utility/hooks/useHorizontalGrabScroll.ts","webpack://nikon-client/./utility/hooks/useHorizontalScrollShadows.ts","webpack://nikon-client/./components/atoms/ShadowContainerHorizontal/ShadowContainerHorizontal.tsx","webpack://nikon-client/./components/organisms/OverviewTechSpecs/OverviewTechSpecs.tsx","webpack://nikon-client/./models/enums/ScrollProgressEnum.ts"],"sourcesContent":["import { RefObject, useEffect, useRef, useState } from 'react';\n\nconst useHorizontalGrabScroll = (\n  containerRef: RefObject<HTMLElement>,\n  disabled: boolean\n) => {\n  const [isMouseDown, setIsMouseDown] = useState(false);\n  const mouseScrollPosition = useRef<{\n    top: number;\n    left: number;\n    x: number;\n    y: number;\n  }>({\n    top: 0,\n    left: 0,\n    x: 0,\n    y: 0,\n  });\n\n  useEffect(() => {\n    const container = containerRef.current;\n    if (!container?.clientWidth) return;\n\n    if (container.clientWidth >= container.scrollWidth || disabled) {\n      container.style.cursor = 'inherit';\n      return;\n    }\n\n    if (isMouseDown) {\n      container.style.cursor = 'grabbing';\n      return;\n    }\n\n    container.style.cursor = 'grab';\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [isMouseDown, disabled]);\n\n  useEffect(() => {\n    mouseScrollPosition.current = { top: 0, left: 0, x: 0, y: 0 };\n    const container = containerRef.current;\n\n    if (!container) return () => ({});\n    if (disabled) {\n      container.scrollTop = 0;\n      container.scrollLeft = 0;\n\n      return () => ({});\n    }\n\n    const mouseMoveHandler = (e: MouseEvent) => {\n      const dx = e.clientX - mouseScrollPosition.current.x;\n      const dy = e.clientY - mouseScrollPosition.current.y;\n\n      container.scrollTop = mouseScrollPosition.current.top - dy;\n      container.scrollLeft = mouseScrollPosition.current.left - dx;\n    };\n\n    const mouseUpHandler = () => {\n      document.removeEventListener('mousemove', mouseMoveHandler);\n      document.removeEventListener('mouseup', mouseUpHandler);\n      setIsMouseDown(false);\n    };\n\n    const mouseDownHandler = (e: MouseEvent) => {\n      mouseScrollPosition.current = {\n        top: container.scrollTop,\n        left: container.scrollLeft,\n        x: e.clientX,\n        y: e.clientY,\n      };\n      setIsMouseDown(true);\n\n      document.addEventListener('mousemove', mouseMoveHandler);\n      document.addEventListener('mouseup', mouseUpHandler);\n    };\n\n    const onWheel = (e: WheelEvent) => {\n      if (e.deltaY === 0) return;\n\n      container.scrollTo({\n        left: container.scrollLeft + e.deltaY,\n        behavior: 'smooth',\n      });\n    };\n\n    container.addEventListener('mousedown', mouseDownHandler);\n    container.addEventListener('wheel', onWheel, { passive: true });\n\n    return () => {\n      container.removeEventListener('mousedown', mouseDownHandler);\n      container.removeEventListener('wheel', onWheel);\n    };\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [disabled]);\n};\n\nexport default useHorizontalGrabScroll;\n","import ScrollProgressEnum from '@models/enums/ScrollProgressEnum';\nimport { useMotionValueEvent, useScroll } from 'framer-motion';\nimport { RefObject, useEffect, useState } from 'react';\n\nconst useHorizontalScrollShadows = (\n  containerRef: RefObject<HTMLElement>,\n  threshold: number,\n  disabled: boolean\n) => {\n  const { scrollXProgress } = useScroll({ container: containerRef });\n  const [isStart, setIsStart] = useState(true);\n  const [isEnd, setIsEnd] = useState(false);\n  const [scrollProgress, setScrollProgress] = useState(\n    ScrollProgressEnum.Start\n  );\n\n  useMotionValueEvent(scrollXProgress, 'change', (value: number) => {\n    if (value < threshold) {\n      setScrollProgress(ScrollProgressEnum.Start);\n    }\n\n    if (value >= threshold && value <= 1 - threshold) {\n      setScrollProgress(ScrollProgressEnum.Middle);\n    }\n\n    if (value > 1 - threshold) {\n      setScrollProgress(ScrollProgressEnum.End);\n    }\n  });\n\n  useEffect(() => {\n    const container = containerRef.current;\n    if (!container?.clientWidth || disabled) return;\n\n    const { clientWidth, scrollWidth } = container;\n    if (clientWidth >= scrollWidth) {\n      setIsStart(true);\n      setIsEnd(true);\n\n      return;\n    }\n\n    if (scrollProgress === ScrollProgressEnum.Start) {\n      setIsStart(true);\n      setIsEnd(false);\n    }\n\n    if (scrollProgress === ScrollProgressEnum.Middle) {\n      setIsStart(false);\n      setIsEnd(false);\n    }\n\n    if (scrollProgress === ScrollProgressEnum.End) {\n      setIsEnd(true);\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [disabled, scrollProgress]);\n\n  return { isStart, isEnd };\n};\n\nexport default useHorizontalScrollShadows;\n","import useHorizontalGrabScroll from '@utils/hooks/useHorizontalGrabScroll';\nimport useHorizontalScrollShadows from '@utils/hooks/useHorizontalScrollShadows';\nimport classNames from 'classnames';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport {\n  PropsWithChildren,\n  forwardRef,\n  useImperativeHandle,\n  useRef,\n} from 'react';\n\nexport interface IShadowContainerHorizontalRef {\n  readonly scrollTo: (offset: number) => void;\n  readonly getOffsetWidth: () => number;\n}\n\ninterface Props {\n  readonly className?: string;\n  readonly shadowColour?: string;\n  readonly threshold?: number;\n  readonly showStart?: boolean; // Manually override shadows from a parent component\n  readonly showEnd?: boolean;\n  readonly disableScroll?: boolean; // Used together with showStart/showEnd to disable scrolling within the container (e.g. when we want to wrap a carousel within some left/right shadows, we want to use the carousel's scrolling/swiping, not the container's one)\n  readonly shadowWidth?: string;\n  readonly isNoWrapEnabled?: boolean;\n}\n\nconst ShadowContainerHorizontal = forwardRef<\n  IShadowContainerHorizontalRef,\n  PropsWithChildren<Props>\n>(\n  (\n    {\n      children,\n      className,\n      disableScroll = false,\n      shadowColour = 'from-white dark:from-black-100',\n      threshold = 0.05,\n      showStart = false,\n      showEnd = true,\n      shadowWidth = 'w-10',\n      isNoWrapEnabled = true,\n    },\n    ref\n  ) => {\n    const containerRef = useRef<HTMLDivElement>(null);\n    const { isStart, isEnd } = useHorizontalScrollShadows(\n      containerRef,\n      threshold,\n      disableScroll\n    );\n    useHorizontalGrabScroll(containerRef, disableScroll);\n\n    useImperativeHandle(ref, () => ({\n      scrollTo: (leftOffset: number) => {\n        containerRef.current?.scrollTo({\n          left: leftOffset,\n          behavior: 'smooth',\n        });\n      },\n      getOffsetWidth: () => containerRef.current?.offsetWidth ?? 0,\n    }));\n\n    return (\n      <div className={classNames(className, 'relative')}>\n        <AnimatePresence>\n          {(!isStart || showStart) && (\n            <motion.span\n              animate={{ opacity: 1 }}\n              className={classNames(\n                shadowColour,\n                shadowWidth,\n                'pointer-events-none absolute left-0 top-0 z-10 -ml-[1px] h-full bg-gradient-to-r to-transparent'\n              )}\n              exit={{ opacity: 0 }}\n              initial={{ opacity: 0 }}\n              transition={{ duration: 0.25 }}\n            />\n          )}\n        </AnimatePresence>\n\n        <div\n          ref={containerRef}\n          // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n          tabIndex={0}\n          className={classNames(\n            {\n              'z-0 overflow-x-hidden': disableScroll,\n              'overflow-x-auto': !disableScroll,\n              'whitespace-nowrap': isNoWrapEnabled,\n            },\n            'relative select-none scrollbar-hide'\n          )}\n        >\n          {children}\n        </div>\n\n        {/* isEnd is always false when using showEnd override so !isEnd is always true */}\n        <AnimatePresence>\n          {!isEnd && showEnd && (\n            <motion.span\n              animate={{ opacity: 1 }}\n              className={classNames(\n                shadowColour || 'from-white dark:from-black-100',\n                shadowWidth,\n                'pointer-events-none absolute right-0 top-0 z-10 -ml-[1px] h-full bg-gradient-to-l to-transparent'\n              )}\n              exit={{ opacity: 0 }}\n              initial={{ opacity: 0 }}\n              transition={{ duration: 0.25 }}\n            />\n          )}\n        </AnimatePresence>\n      </div>\n    );\n  }\n);\n\nexport default ShadowContainerHorizontal;\n","import ShadowContainerHorizontal from '@atoms/ShadowContainerHorizontal/ShadowContainerHorizontal';\nimport { IMeta } from '@models/IMeta';\nimport classNames from 'classnames';\n\ninterface Props {\n  readonly highlights: string[];\n  readonly title?: string;\n  readonly meta: IMeta;\n  readonly anchorId: string;\n}\n\nconst OverviewTechSpecs = ({\n  highlights,\n  title,\n  meta,\n  anchorId = '',\n}: Props) => {\n  const displayedHighlights = highlights\n    .slice(0, 5)\n    .filter((highlight) => highlight);\n\n  return (\n    <section\n      id={`a-${anchorId}`}\n      className=\"component-padding bg-white dark:bg-black-100\"\n    >\n      {title && (\n        <div className=\"container mb-7.5 xl:grid xl:grid-cols-12\">\n          <h2\n            data-epi-property-name={meta?.editHints?.title}\n            className=\"h5 text-black-100 dark:text-white xl:col-span-10 xl:col-start-2\"\n          >\n            {title}\n          </h2>\n        </div>\n      )}\n\n      <div\n        className={classNames(\n          `${\n            displayedHighlights.length === 1 ? 'container' : 'md:container'\n          } xl:grid xl:grid-cols-12`\n        )}\n      >\n        <div className=\"xl:col-span-10 xl:col-start-2\">\n          <ShadowContainerHorizontal threshold={0.01}>\n            <div\n              className=\"flex gap-x-5 lg:grid lg:w-full lg:auto-cols-fr lg:grid-flow-col lg:gap-x-4 lg:whitespace-normal\"\n              data-epi-edit={meta?.editHints?.highlights}\n            >\n              {displayedHighlights.map((highlight) => (\n                <span\n                  key={highlight}\n                  className=\"body-two flex grow select-none items-center justify-center rounded-[5px] bg-grey-100 px-4 py-5 text-center text-black-100 dark:bg-grey-600 dark:text-white\"\n                >\n                  {highlight}\n                </span>\n              ))}\n            </div>\n          </ShadowContainerHorizontal>\n        </div>\n      </div>\n    </section>\n  );\n};\n\nexport default OverviewTechSpecs;\n","enum ScrollProgressEnum {\n  Start = 'Start',\n  Middle = 'Middle',\n  End = 'End',\n}\n\nexport default ScrollProgressEnum;\n"],"names":["useHorizontalGrabScroll","containerRef","disabled","isMouseDown","setIsMouseDown","useState","mouseScrollPosition","useRef","top","left","x","y","useEffect","container","current","clientWidth","scrollWidth","style","cursor","scrollTop","scrollLeft","mouseMoveHandler","e","dx","clientX","dy","clientY","mouseUpHandler","document","removeEventListener","mouseDownHandler","addEventListener","onWheel","deltaY","scrollTo","behavior","passive","useHorizontalScrollShadows","threshold","scrollXProgress","useScroll","isStart","setIsStart","isEnd","setIsEnd","scrollProgress","setScrollProgress","ScrollProgressEnum","Start","useMotionValueEvent","value","Middle","End","forwardRef","_ref","ref","children","className","disableScroll","shadowColour","showStart","showEnd","shadowWidth","isNoWrapEnabled","useImperativeHandle","leftOffset","getOffsetWidth","offsetWidth","React","createElement","classNames","AnimatePresence","motion","span","animate","opacity","exit","initial","transition","duration","tabIndex","highlights","title","meta","anchorId","displayedHighlights","slice","filter","highlight","id","editHints","length","ShadowContainerHorizontal","map","key"],"sourceRoot":""}