{"version":3,"sources":["../src/hooks/useCloudContainer.ts","../src/hooks/useCloudElement.ts","../src/components/ThreeDCloud/CloudElement.tsx","#style-inject:#style-inject","../src/components/ThreeDCloud/style.css","../src/assets/Pause.tsx","../src/assets/Play.tsx","../src/components/ThreeDCloud/CloudContainer.tsx"],"names":["React","useEffect","useRef","useState","useCloudContainer","children","size","speed","radius","randomPosition","isPausable","iconOnHover","mouseTracking","elements","numberElements","ref","pause","setPause","mousePosition","setMousePosition","a","b","l","sc","elementRandomPosition","computePosition","index","getRandomIndex","theta","phi","closest","previousValue","currentValue","i","elementsList","element","handlePause","handlePauseByKey","event","updateMousePosition","rect","XClient","YClient","useCloudElement","props","scale","setScale","per","setPer","position","setPosition","style","setStyle","nextPosition","rx1","ry1","rz1","rx2","ry2","rz2","getStyle","alpha","left","top","updateStyleInterval","Fragment","jsx","CloudElement","CloudElement_default","styleInject","css","insertAt","head","jsxs","Pause","Play","CloudContainer","elementIndex"],"mappings":"AAAA,OAAOA,GAAS,aAAAC,EAAW,UAAAC,EAAQ,YAAAC,MAAgB,QAG5C,SAASC,EAAkB,CAChC,SAAAC,EACA,KAAAC,EAAO,IACP,MAAAC,EAAQ,EACR,OAAAC,EAAS,IACT,eAAAC,EAAiB,GACjB,WAAAC,EAAa,GACb,YAAAC,EAAc,GACd,cAAAC,EAAgB,EAClB,EAAwB,CACtB,IAAMC,EAA+Bb,EAAM,SAAS,QAClDK,CACF,EACMS,EAAiBD,EAAS,OAC1BE,EAAMb,EAAuB,IAAI,EAEjC,CAACc,EAAOC,CAAQ,EAAId,EAAkB,EAAK,EAC3C,CAACe,EAAeC,CAAgB,EAAIhB,EAAmB,CAC3D,EAAG,KACH,EAAG,EACH,EAAG,CACL,CAAC,EAGKiB,EACJ,EAAE,KAAK,IAAI,KAAK,IAAI,CAACF,EAAc,EAAG,CAACZ,CAAI,EAAGA,CAAI,EAAIE,GAAUD,EAC5Dc,EACH,KAAK,IAAI,KAAK,IAAI,CAACH,EAAc,EAAG,CAACZ,CAAI,EAAGA,CAAI,EAAIE,EAAUD,EAC3De,EAAI,KAAK,GAAKhB,EACdiB,EAAK,CACT,KAAK,IAAIH,EAAIE,CAAC,EACd,KAAK,IAAIF,EAAIE,CAAC,EACd,KAAK,IAAID,EAAIC,CAAC,EACd,KAAK,IAAID,EAAIC,CAAC,CAChB,EAEME,EAAuC,MAAM,KAAKX,EAAS,KAAK,CAAC,EAEvE,SAASY,EAAgBC,EAAyB,CAC5CjB,IACFiB,EAAQC,EACN,KAAK,MAAM,KAAK,OAAO,GAAKb,EAAiB,EAAE,CACjD,EAAE,QAAQ,GACZ,IAAMc,EAAQ,KAAK,KAAK,IAAM,EAAIF,EAAQ,GAAKZ,CAAc,EACvDe,EAAM,KAAK,MAAMf,EAAiB,GAAK,KAAK,EAAE,EAAIc,EAExD,MAAO,CACL,EAAItB,EAAO,KAAK,IAAIsB,CAAK,EAAI,KAAK,IAAIC,CAAG,EAAK,EAC9C,EAAIvB,EAAO,KAAK,IAAIsB,CAAK,EAAI,KAAK,IAAIC,CAAG,EAAK,EAC9C,EAAIvB,EAAO,KAAK,IAAIsB,CAAK,EAAK,CAChC,CACF,CAEA,SAASD,EAAeD,EAAuB,CAC7C,IAAMI,EAAUN,EAAsB,OACpC,CAACO,EAAuBC,IACtB,KAAK,IAAIA,EAAa,QAAQ,EAAIN,CAAK,EACvC,KAAK,IAAIK,EAAc,QAAQ,EAAIL,CAAK,EACpCM,EACAD,CACR,EACA,QAASE,EAAI,EAAGA,EAAIT,EAAsB,OAAQS,IAC5CT,EAAsBS,CAAC,IAAMH,GAC/BN,EAAsB,OAAOS,EAAG,CAAC,EAGrC,OAAOH,CACT,CAEA,IAAMI,EAAyCrB,EAAS,IACtD,CAACsB,EAAST,KAAW,CACnB,SAAU1B,EAAM,cACdmC,EAAQ,KACRA,EAAQ,MACRA,EAAQ,MAAM,QAChB,EACA,MAAO3B,EACP,SAAUiB,EAAgBC,CAAK,EAC/B,KAAApB,EACA,MAAAC,EACA,GAAAgB,EACA,MAAAP,CACF,EACF,EAEMoB,EAAc,IAAY,CAC1B1B,GACFO,EAAS,CAACD,CAAK,CAEnB,EAEMqB,EACJC,GACS,CACLA,EAAM,OAAS,SACjBF,EAAY,CAEhB,EAEMG,EAAuBD,GAAsB,CACjD,GAAIvB,EAAI,QAAS,CACf,IAAMyB,EAAOzB,EAAI,QAAQ,sBAAsB,EACzC0B,GAAWH,EAAM,SAAWE,EAAK,KAAOA,EAAK,MAAQ,IAAM,EAC3DE,GAAWJ,EAAM,SAAWE,EAAK,IAAMA,EAAK,OAAS,IAAM,EACjErB,EAAiB,CAAE,EAAGsB,EAAS,EAAGC,EAAS,EAAG,CAAE,CAAC,CACnD,CACF,EAEA,OAAAzC,EAAU,IAAM,CACd,GAAIW,EACF,gBAAS,iBAAiB,YAAa2B,CAAmB,EAEnD,IAAM,CACX,SAAS,oBAAoB,YAAaA,CAAmB,CAC/D,CAGJ,EAAG,CAAC3B,CAAa,CAAC,EAEX,CACL,YAAAwB,EACA,MAAApB,EACA,iBAAAqB,EACA,WAAA3B,EACA,YAAAC,EACA,OAAAH,EACA,GAAAe,EACA,aAAAW,EACA,IAAAnB,EACA,oBAAAwB,EACA,cAAArB,CACF,CACF,CCvIA,OAAS,aAAAjB,EAAW,YAAAE,MAAgB,QAI7B,SAASwC,EAAgBC,EAA0B,CACxD,GAAM,CAACC,EAAOC,CAAQ,EAAI3C,EAAiB,CAAC,EACtC,CAAC4C,EAAKC,CAAM,EAAI7C,EAAiB,CAAC,EAClC,CAAC8C,EAAUC,CAAW,EAAI/C,EAAmByC,EAAM,QAAQ,EAC3D,CAACO,EAAOC,CAAQ,EAAIjD,EAAoB,CAAC,CAAC,EAEhD,SAASkD,GAAe,CACtB,IAAMC,EAAML,EAAS,EACfM,EAAMN,EAAS,EAAIL,EAAM,GAAG,CAAC,EAAIK,EAAS,EAAI,CAACL,EAAM,GAAG,CAAC,EACzDY,EAAMP,EAAS,EAAIL,EAAM,GAAG,CAAC,EAAIK,EAAS,EAAIL,EAAM,GAAG,CAAC,EAExDa,EAAMH,EAAMV,EAAM,GAAG,CAAC,EAAIY,EAAMZ,EAAM,GAAG,CAAC,EAC1Cc,EAAMH,EACNI,EAAMH,EAAMZ,EAAM,GAAG,CAAC,EAAIU,EAAMV,EAAM,GAAG,CAAC,EAEhDM,EAAY,CAAE,EAAGO,EAAK,EAAGC,EAAK,EAAGC,CAAI,CAAC,CACxC,CAEA,SAASC,GAAsB,CAC7B,IAAIC,EAAQd,EAAMA,EAAM,GACxBc,EAAQ,KAAK,IAAI,KAAK,OAAOA,EAAQ,EAAI,EAAIA,GAAS,GAAG,EAAI,GAAG,EAEhE,IAAMC,EAAOb,EAAS,EAAE,QAAQ,CAAC,EAC3Bc,EAAMd,EAAS,EAAE,QAAQ,CAAC,EAGhC,MAAO,CACL,UAHgB,2BAA2Ba,CAAI,oBAAoBC,CAAG,iBAAiBlB,CAAK,IAI5F,OAAQ,iBAAiB,KAAK,IAAI,IAAMgB,CAAK,CAAC,IAC9C,QAAS,GAAGA,CAAK,EACnB,CACF,CAEA,OAAA5D,EAAU,IAAM,CACd,GAAI,CAAC2C,EAAM,MAAO,CAChB,IAAMoB,EAAsB,YAAY,IAAM,CAC5CX,EAAa,EACbL,EAAQ,EAAIJ,EAAM,OAAU,EAAIA,EAAM,MAAQK,EAAS,EAAE,EACzDH,EAAS,KAAK,MAAMC,EAAM,GAAG,EAAI,GAAG,EACpCK,EAASQ,EAAS,CAAC,CACrB,EAAG,EAAE,EACL,MAAO,IAAM,cAAcI,CAAmB,CAChD,CACA,MAAO,IAAM,CAAC,CAChB,EAAG,CAACb,EAAOP,EAAM,KAAK,CAAC,EAEhB,CACL,MAAAO,EACA,MAAAN,CACF,CACF,CC5CI,mBAAAoB,EACE,OAAAC,MADF,oBANJ,IAAMC,EACJvB,GACG,CACH,GAAM,CAAE,MAAAO,EAAO,MAAAN,CAAM,EAAIF,EAAgBC,CAAK,EAE9C,OACEsB,EAAAD,EAAA,CACE,SAAAC,EAAC,QACC,UAAU,eACV,MAAO,CACL,OAAQf,EAAM,OACd,OAAQA,EAAM,OACd,QAASA,EAAM,QACf,UAAWA,EAAM,UACjB,MAAOA,EAAM,MACb,MAAAN,CACF,EAEC,SAAAD,EAAM,SACT,EACF,CAEJ,EAEOwB,EAAQD,EC3BU,SAARE,EAA6BC,EAAK,CAAE,SAAAC,CAAS,EAAI,CAAC,EAAG,CAC1D,GAAI,CAACD,GAAO,OAAO,SAAa,IAAa,OAE7C,IAAME,EAAO,SAAS,MAAQ,SAAS,qBAAqB,MAAM,EAAE,CAAC,EAC/DrB,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,KAAO,WAEToB,IAAa,OACXC,EAAK,WACPA,EAAK,aAAarB,EAAOqB,EAAK,UAAU,EAK1CA,EAAK,YAAYrB,CAAK,EAGpBA,EAAM,WACRA,EAAM,WAAW,QAAUmB,EAE3BnB,EAAM,YAAY,SAAS,eAAemB,CAAG,CAAC,CAElD,CCvB8BD,EAAY;AAAA,CAAshB,ECCxkB,mBAAAJ,EAEI,OAAAC,EADF,QAAAO,MADF,oBADK,IAAMC,EAAQ,IACnBR,EAAAD,EAAA,CACE,SAAAQ,EAAC,OAAI,MAAM,6BAA6B,QAAQ,YAC9C,UAAAP,EAAC,QAAK,EAAE,IAAI,EAAE,IAAI,MAAM,IAAI,OAAO,KAAK,KAAK,OAAO,EACpDA,EAAC,QAAK,EAAE,KAAK,EAAE,IAAI,MAAM,IAAI,OAAO,KAAK,KAAK,OAAO,GACvD,EACF,ECLA,mBAAAD,EAEI,OAAAC,EADF,QAAAO,MADF,oBADK,IAAME,EAAO,IAClBT,EAAAD,EAAA,CACE,SAAAQ,EAAC,OAAI,MAAM,6BAA6B,QAAQ,YAC9C,UAAAP,EAAC,QAAK,EAAE,gBAAgB,EACxBA,EAAC,QAAK,EAAE,gBAAgB,KAAK,OAAO,GACtC,EACF,ECmBE,OASe,OAAAA,EATf,QAAAO,MAAA,oBAhBG,IAAMG,EACXhC,GACG,CACH,GAAM,CACJ,GAAArB,EACA,OAAAf,EACA,aAAA0B,EACA,YAAAE,EACA,MAAApB,EACA,iBAAAqB,EACA,WAAA3B,EACA,YAAAC,EACA,IAAAI,CACF,EAAIX,EAAkBwC,CAAK,EAE3B,OACE6B,EAAC,OACC,UAAW,0BAA0B/D,EAAa,gBAAkB,EAAE,GACtE,KAAK,SACL,QAAS0B,EACT,UAAWC,EACX,SAAU,EAET,UAAA3B,GAAcC,GACbuD,EAAC,QAAK,UAAU,qBACb,SAAAlD,EAAQkD,EAACS,EAAA,EAAK,EAAKT,EAACQ,EAAA,EAAM,EAC7B,EAEFR,EAAC,OACC,UAAWtB,EAAM,UACjB,MAAO,CACL,MAAO,GAAGA,EAAM,IAAI,KACpB,OAAQ,GAAGA,EAAM,IAAI,IACvB,EACA,IAAK7B,EAEJ,SAAAmB,EAAa,IAAI,CAACC,EAAS0C,IAC1BX,EAACE,EAAA,CAEC,MAAO5D,EACP,GAAIe,EACJ,SAAUY,EAAQ,SAClB,MAAOnB,EAEN,SAAAmB,EAAQ,UANJ0C,CAOP,CACD,EACH,GACF,CAEJ","sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { CloudElementProps, CloudContainerProps, Position } from '../types';\n\nexport function useCloudContainer({\n  children,\n  size = 150,\n  speed = 1,\n  radius = 200,\n  randomPosition = true,\n  isPausable = true,\n  iconOnHover = false,\n  mouseTracking = true,\n}: CloudContainerProps) {\n  const elements: Array<JSX.Element> = React.Children.toArray(\n    children\n  ) as Array<JSX.Element>;\n  const numberElements = elements.length;\n  const ref = useRef<HTMLDivElement>(null);\n\n  const [pause, setPause] = useState<boolean>(false);\n  const [mousePosition, setMousePosition] = useState<Position>({\n    x: -500,\n    y: 0,\n    z: 0,\n  });\n\n  // Direction\n  const a =\n    -(Math.min(Math.max(-mousePosition.y, -size), size) / radius) * speed;\n  const b =\n    (Math.min(Math.max(-mousePosition.x, -size), size) / radius) * speed;\n  const l = Math.PI / size;\n  const sc = [\n    Math.sin(a * l),\n    Math.cos(a * l),\n    Math.sin(b * l),\n    Math.cos(b * l),\n  ];\n\n  const elementRandomPosition: Array<Number> = Array.from(elements.keys());\n\n  function computePosition(index: number): Position {\n    if (randomPosition)\n      index = getRandomIndex(\n        Math.floor(Math.random() * (numberElements + 1))\n      ).valueOf();\n    const theta = Math.acos(-1 + (2 * index + 1) / numberElements);\n    const phi = Math.sqrt((numberElements + 1) * Math.PI) * theta;\n\n    return {\n      x: (size * Math.sin(theta) * Math.cos(phi)) / 2,\n      y: (size * Math.sin(theta) * Math.sin(phi)) / 2,\n      z: (size * Math.cos(theta)) / 2,\n    };\n  }\n\n  function getRandomIndex(index: number): Number {\n    const closest = elementRandomPosition.reduce(\n      (previousValue: Number, currentValue: Number): Number =>\n        Math.abs(currentValue.valueOf() - index) <\n        Math.abs(previousValue.valueOf() - index)\n          ? currentValue\n          : previousValue\n    );\n    for (let i = 0; i < elementRandomPosition.length; i++) {\n      if (elementRandomPosition[i] === closest) {\n        elementRandomPosition.splice(i, 1);\n      }\n    }\n    return closest;\n  }\n\n  const elementsList: Array<CloudElementProps> = elements.map(\n    (element, index) => ({\n      children: React.createElement(\n        element.type,\n        element.props,\n        element.props.children\n      ),\n      depth: radius,\n      position: computePosition(index),\n      size,\n      speed,\n      sc,\n      pause,\n    })\n  );\n\n  const handlePause = (): void => {\n    if (isPausable) {\n      setPause(!pause);\n    }\n  };\n\n  const handlePauseByKey = (\n    event: React.KeyboardEvent<HTMLDivElement>\n  ): void => {\n    if (event.code === 'Space') {\n      handlePause();\n    }\n  };\n\n  const updateMousePosition = (event: MouseEvent) => {\n    if (ref.current) {\n      const rect = ref.current.getBoundingClientRect();\n      const XClient = (event.clientX - (rect.left + rect.width / 2)) / 5;\n      const YClient = (event.clientY - (rect.top + rect.height / 2)) / 5;\n      setMousePosition({ x: XClient, y: YClient, z: 0 });\n    }\n  };\n\n  useEffect(() => {\n    if (mouseTracking) {\n      document.addEventListener('mousemove', updateMousePosition);\n\n      return () => {\n        document.removeEventListener('mousemove', updateMousePosition);\n      };\n    }\n    return undefined;\n  }, [mouseTracking]);\n\n  return {\n    handlePause,\n    pause,\n    handlePauseByKey,\n    isPausable,\n    iconOnHover,\n    radius,\n    sc,\n    elementsList,\n    ref,\n    updateMousePosition,\n    mousePosition,\n  };\n}\n","import { useEffect, useState } from 'react';\nimport { CloudElementProps } from '../types/index';\nimport { ItemStyle, Position } from '../types';\n\nexport function useCloudElement(props: CloudElementProps) {\n  const [scale, setScale] = useState<number>(1);\n  const [per, setPer] = useState<number>(1);\n  const [position, setPosition] = useState<Position>(props.position);\n  const [style, setStyle] = useState<ItemStyle>({});\n\n  function nextPosition() {\n    const rx1 = position.x;\n    const ry1 = position.y * props.sc[1] + position.z * -props.sc[0];\n    const rz1 = position.y * props.sc[0] + position.z * props.sc[1];\n\n    const rx2 = rx1 * props.sc[3] + rz1 * props.sc[2];\n    const ry2 = ry1;\n    const rz2 = rz1 * props.sc[3] - rx1 * props.sc[2];\n\n    setPosition({ x: rx2, y: ry2, z: rz2 });\n  }\n\n  function getStyle(): ItemStyle {\n    let alpha = per * per - 0.2;\n    alpha = Math.abs(Math.round((alpha > 1 ? 1 : alpha) * 1e3) / 1e3);\n\n    const left = position.x.toFixed(2);\n    const top = position.y.toFixed(2);\n    const transform = `translate3d(calc(-50% + ${left}px), calc(-50% + ${top}px), 0) scale(${scale})`;\n\n    return {\n      transform,\n      filter: `alpha(opacity=${Math.abs(100 * alpha)})`,\n      opacity: `${alpha}`,\n    };\n  }\n\n  useEffect(() => {\n    if (!props.pause) {\n      const updateStyleInterval = setInterval(() => {\n        nextPosition();\n        setPer((2 * props.depth) / (2 * props.depth + position.z));\n        setScale(Math.round(per * 1e3) / 1e3);\n        setStyle(getStyle());\n      }, 15);\n      return () => clearInterval(updateStyleInterval);\n    }\n    return () => {};\n  }, [style, props.pause]);\n\n  return {\n    style,\n    scale,\n  };\n}\n","import React from 'react';\nimport { useCloudElement } from '../../hooks/useCloudElement';\nimport { CloudElementProps } from '../../types';\n\nconst CloudElement: React.FunctionComponent<CloudElementProps> = (\n  props: CloudElementProps\n) => {\n  const { style, scale } = useCloudElement(props);\n\n  return (\n    <>\n      <span\n        className=\"three-d-item\"\n        style={{\n          filter: style.filter,\n          height: style.height,\n          opacity: style.opacity,\n          transform: style.transform,\n          width: style.width,\n          scale,\n        }}\n      >\n        {props.children}\n      </span>\n    </>\n  );\n};\n\nexport default CloudElement;\n","\n          export default function styleInject(css, { insertAt } = {}) {\n            if (!css || typeof document === 'undefined') return\n          \n            const head = document.head || document.getElementsByTagName('head')[0]\n            const style = document.createElement('style')\n            style.type = 'text/css'\n          \n            if (insertAt === 'top') {\n              if (head.firstChild) {\n                head.insertBefore(style, head.firstChild)\n              } else {\n                head.appendChild(style)\n              }\n            } else {\n              head.appendChild(style)\n            }\n          \n            if (style.styleSheet) {\n              style.styleSheet.cssText = css\n            } else {\n              style.appendChild(document.createTextNode(css))\n            }\n          }\n          ","import styleInject from '#style-inject';styleInject(\".threed-cloud-container{display:flex;align-items:center;justify-content:center;min-height:100%;position:relative}.three-d-item{will-change:transform,opacity,filter;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}.tdc-animation-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:50px;opacity:0;transition:.3s}.threed-cloud-container:hover .tdc-animation-icon{opacity:.65}.tdcIsPausable{cursor:pointer}.threed-cloud-container span *{display:flex;justify-content:center;align-items:center}\\n\")","export const Pause = () => (\n  <>\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n      <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" fill=\"#000\" />\n      <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" fill=\"#000\" />\n    </svg>\n  </>\n);\n","export const Play = () => (\n  <>\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\">\n      <path d=\"M8 5v14l11-7z\" />\n      <path d=\"M0 0h24v24H0z\" fill=\"none\" />\n    </svg>\n  </>\n);\n","import React from 'react';\nimport { useCloudContainer } from '../../hooks/useCloudContainer';\nimport { CloudContainerProps } from '../../types';\nimport CloudElement from './CloudElement';\n\nimport './style.css';\nimport { Pause } from '../../assets/Pause';\nimport { Play } from '../../assets/Play';\n\nexport const CloudContainer: React.FunctionComponent<CloudContainerProps> = (\n  props: CloudContainerProps\n) => {\n  const {\n    sc,\n    radius,\n    elementsList,\n    handlePause,\n    pause,\n    handlePauseByKey,\n    isPausable,\n    iconOnHover,\n    ref,\n  } = useCloudContainer(props);\n\n  return (\n    <div\n      className={`threed-cloud-container ${isPausable ? 'tdcIsPausable' : ''}`}\n      role=\"button\"\n      onClick={handlePause}\n      onKeyDown={handlePauseByKey}\n      tabIndex={0}\n    >\n      {isPausable && iconOnHover && (\n        <span className=\"tdc-animation-icon\">\n          {pause ? <Play /> : <Pause />}\n        </span>\n      )}\n      <div\n        className={props.className}\n        style={{\n          width: `${props.size}px`,\n          height: `${props.size}px`,\n        }}\n        ref={ref}\n      >\n        {elementsList.map((element, elementIndex) => (\n          <CloudElement\n            key={elementIndex}\n            depth={radius}\n            sc={sc}\n            position={element.position}\n            pause={pause}\n          >\n            {element.children}\n          </CloudElement>\n        ))}\n      </div>\n    </div>\n  );\n};\n"]}