refract-ui 0.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/RefractProvider-Bzz4G22S.cjs +25 -0
  2. package/dist/RefractProvider-Bzz4G22S.cjs.map +1 -0
  3. package/dist/RefractProvider-D__A8gQl.js +238 -0
  4. package/dist/RefractProvider-D__A8gQl.js.map +1 -0
  5. package/dist/assets/iphone-11.glb +0 -0
  6. package/dist/assets/macbook-pro.glb +0 -0
  7. package/dist/carousel.cjs +48 -1
  8. package/dist/carousel.cjs.map +1 -1
  9. package/dist/carousel.js +300 -0
  10. package/dist/carousel.js.map +1 -1
  11. package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +10 -0
  12. package/dist/components/Breadcrumbs/index.d.ts +2 -0
  13. package/dist/components/Button/Button.d.ts +22 -0
  14. package/dist/components/Button/index.d.ts +2 -0
  15. package/dist/components/Carousel/Carousel.d.ts +21 -0
  16. package/dist/components/Carousel/index.d.ts +1 -0
  17. package/dist/components/Divider/Divider.d.ts +12 -0
  18. package/dist/components/Divider/index.d.ts +2 -0
  19. package/dist/components/Heading/Heading.d.ts +9 -0
  20. package/dist/components/Heading/index.d.ts +2 -0
  21. package/dist/components/Icon/Icon.d.ts +30 -0
  22. package/dist/components/Icon/index.d.ts +2 -0
  23. package/dist/components/Image/Image.d.ts +27 -0
  24. package/dist/components/Image/index.d.ts +1 -0
  25. package/dist/components/Input/Input.d.ts +21 -0
  26. package/dist/components/Input/TextArea.d.ts +11 -0
  27. package/dist/components/Input/index.d.ts +2 -0
  28. package/dist/components/Link/Link.d.ts +10 -0
  29. package/dist/components/Link/index.d.ts +1 -0
  30. package/dist/components/LinkProvider/LinkProvider.d.ts +11 -0
  31. package/dist/components/LinkProvider/index.d.ts +1 -0
  32. package/dist/components/List/List.d.ts +11 -0
  33. package/dist/components/List/index.d.ts +1 -0
  34. package/dist/components/Loader/Loader.d.ts +6 -0
  35. package/dist/components/Loader/index.d.ts +2 -0
  36. package/dist/components/Model/Model.d.ts +40 -0
  37. package/dist/components/Model/deviceModels.d.ts +29 -0
  38. package/dist/components/Model/index.d.ts +2 -0
  39. package/dist/components/RefractProvider/RefractProvider.d.ts +20 -0
  40. package/dist/components/RefractProvider/index.d.ts +1 -0
  41. package/dist/components/ScrambleReveal/ScrambleReveal.d.ts +9 -0
  42. package/dist/components/ScrambleReveal/index.d.ts +1 -0
  43. package/dist/components/Section/Section.d.ts +8 -0
  44. package/dist/components/Section/index.d.ts +1 -0
  45. package/dist/components/SegmentedControl/SegmentedControl.d.ts +15 -0
  46. package/dist/components/SegmentedControl/index.d.ts +1 -0
  47. package/dist/components/Table/Table.d.ts +11 -0
  48. package/dist/components/Table/index.d.ts +1 -0
  49. package/dist/components/ThemeProvider/ThemeProvider.d.ts +21 -0
  50. package/dist/components/ThemeProvider/index.d.ts +5 -0
  51. package/dist/components/ThemeProvider/theme.d.ts +138 -0
  52. package/dist/components/ThemeProvider/useTheme.d.ts +2 -0
  53. package/dist/components/Transition/Transition.d.ts +19 -0
  54. package/dist/components/Transition/index.d.ts +1 -0
  55. package/dist/components/VisuallyHidden/VisuallyHidden.d.ts +10 -0
  56. package/dist/components/VisuallyHidden/index.d.ts +2 -0
  57. package/dist/components/Wordmark/Wordmark.d.ts +5 -0
  58. package/dist/components/Wordmark/index.d.ts +2 -0
  59. package/dist/entries/carousel.d.ts +1 -1
  60. package/dist/entries/model.d.ts +1 -1
  61. package/dist/hooks/useFormInput.d.ts +11 -0
  62. package/dist/hooks/useFps.d.ts +8 -0
  63. package/dist/hooks/useHasMounted.d.ts +1 -0
  64. package/dist/hooks/useInViewport.d.ts +2 -0
  65. package/dist/index.cjs +1 -1
  66. package/dist/index.cjs.map +1 -1
  67. package/dist/index.d.ts +20 -0
  68. package/dist/index.js +914 -45
  69. package/dist/index.js.map +1 -1
  70. package/dist/model.cjs +4 -1
  71. package/dist/model.cjs.map +1 -1
  72. package/dist/model.js +267 -0
  73. package/dist/model.js.map +1 -1
  74. package/dist/style-CWBkJEps.cjs +2 -0
  75. package/dist/style-CWBkJEps.cjs.map +1 -0
  76. package/dist/style-uMN7vipQ.js +96 -0
  77. package/dist/style-uMN7vipQ.js.map +1 -0
  78. package/dist/styles.css +1 -1
  79. package/dist/three-CWsiEOQZ.js +48 -0
  80. package/dist/three-CWsiEOQZ.js.map +1 -0
  81. package/dist/three-aeLbW1yA.cjs +2 -0
  82. package/dist/three-aeLbW1yA.cjs.map +1 -0
  83. package/dist/tokens.css +1 -0
  84. package/dist/utils/delay.d.ts +1 -0
  85. package/dist/utils/image.d.ts +31 -0
  86. package/dist/utils/three.d.ts +29 -0
  87. package/package.json +3 -3
package/dist/model.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
1
+ {"version":3,"file":"model.js","sources":["../src/hooks/useFps.ts","../src/components/Model/deviceModels.ts","../src/components/Model/Model.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, type MutableRefObject } from 'react';\n\nconst HISTORY_LENGTH = 9;\n\ninterface UseFpsReturn {\n measureFps: () => void;\n fps: MutableRefObject<number>;\n isLowFps: MutableRefObject<boolean>;\n}\n\nexport function useFps(running = true): UseFpsReturn {\n const fps = useRef(0);\n const prevTime = useRef(0);\n const frames = useRef(0);\n const frameHistory = useRef<number[]>([]);\n const isLowFps = useRef(false);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n prevTime.current = performance.now();\n frames.current = 0;\n frameHistory.current = [];\n }, [running]);\n\n const measureFps = useCallback(() => {\n const currentTime = performance.now();\n frames.current = frames.current + 1;\n\n // Measure fps every 100ms\n if (currentTime >= prevTime.current + 100) {\n fps.current = ((frames.current * 100) / (currentTime - prevTime.current)) * 10;\n frameHistory.current.push(fps.current);\n prevTime.current = currentTime;\n frames.current = 0;\n }\n\n if (frameHistory.current.length <= HISTORY_LENGTH) return;\n frameHistory.current = frameHistory.current.slice(-HISTORY_LENGTH);\n\n // Below 60 is considered low fps\n if (frameHistory.current.every(item => item < 60)) {\n isLowFps.current = true;\n }\n\n if (frameHistory.current.every(item => item > 70)) {\n isLowFps.current = false;\n }\n }, []);\n\n return { measureFps, fps, isLowFps };\n}\n","export const ModelAnimationType = {\n SpringUp: 'spring-up',\n LaptopOpen: 'laptop-open',\n} as const;\n\nexport type ModelAnimationTypeValue = typeof ModelAnimationType[keyof typeof ModelAnimationType];\n\nexport interface DeviceModelConfig {\n url: string;\n width: number;\n height: number;\n position: { x: number; y: number; z: number };\n animation: ModelAnimationTypeValue;\n}\n\n/** The device model filenames this module knows how to serve, relative to `basePath`. */\nexport const MODEL_FILES = {\n phone: 'iphone-11.glb',\n laptop: 'macbook-pro.glb',\n} as const;\n\n/**\n * Builds the device model config, resolving each model's `.glb` against\n * `basePath` rather than bundling it — so the host app controls where the\n * files are served from (defaults to `/models/`, matching `public/models/`).\n */\nexport function createDeviceModels(basePath = '/models/'): Record<string, DeviceModelConfig> {\n return {\n phone: {\n url: `${basePath}${MODEL_FILES.phone}`,\n width: 374,\n height: 512,\n position: { x: 0, y: 0, z: 0 },\n animation: ModelAnimationType.SpringUp,\n },\n laptop: {\n url: `${basePath}${MODEL_FILES.laptop}`,\n width: 1280,\n height: 800,\n position: { x: 0, y: 0, z: 0 },\n animation: ModelAnimationType.LaptopOpen,\n },\n };\n}\n\n/** Convenience export for the default `/models/` layout. */\nexport const deviceModels: Record<string, DeviceModelConfig> = createDeviceModels();\n","import { useRefractConfig } from '../RefractProvider';\nimport { animate, useReducedMotion, useSpring } from 'framer-motion';\nimport { useFps } from '../../hooks/useFps';\nimport { useInViewport } from '../../hooks/useInViewport';\nimport {\n createRef,\n startTransition,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type { CSSProperties, HTMLAttributes, RefObject } from 'react';\nimport {\n AmbientLight,\n Color,\n DirectionalLight,\n Group,\n MathUtils,\n Mesh,\n MeshBasicMaterial,\n MeshDepthMaterial,\n OrthographicCamera,\n PerspectiveCamera,\n PlaneGeometry,\n Scene,\n ShaderMaterial,\n SRGBColorSpace,\n Vector3,\n WebGLRenderTarget,\n WebGLRenderer,\n} from 'three';\nimport type { Light, Texture } from 'three';\nimport { HorizontalBlurShader, VerticalBlurShader } from 'three-stdlib';\nimport { resolveSrcFromSrcSet } from '../../utils/image';\nimport { classes, cssProps, numToMs } from '../../utils/style';\nimport {\n cleanRenderer,\n cleanScene,\n getModelLoader,\n removeLights,\n textureLoader,\n} from '../../utils/three';\nimport styles from './Model.module.css';\nimport { ModelAnimationType } from './deviceModels';\nimport type { ModelAnimationTypeValue } from './deviceModels';\n\nconst MeshType = {\n Frame: 'Frame',\n Logo: 'Logo',\n Screen: 'Screen',\n} as const;\n\nconst rotationSpringConfig = {\n stiffness: 40,\n damping: 20,\n mass: 1.4,\n restSpeed: 0.001,\n};\n\ninterface ImageLike {\n src: string;\n width?: number;\n height?: number;\n}\n\ninterface ModelTexture {\n placeholder: string | ImageLike;\n srcSet?: (string | ImageLike)[];\n src?: ImageLike;\n sizes?: string;\n}\n\ninterface ModelConfig {\n texture: ModelTexture;\n position: { x: number; y: number; z: number };\n url: string;\n animation: ModelAnimationTypeValue;\n}\n\ninterface ModelProps extends HTMLAttributes<HTMLDivElement> {\n models: ModelConfig[];\n show?: boolean;\n showDelay?: number;\n cameraPosition?: { x: number; y: number; z: number };\n style?: CSSProperties;\n className?: string;\n alt?: string;\n /** Path to the draco decoder assets, e.g. served at /draco/. */\n decoderPath?: string;\n}\n\nexport const Model = ({\n models,\n show = true,\n showDelay = 0,\n cameraPosition = { x: 0, y: 0, z: 8 },\n style,\n className,\n alt,\n decoderPath,\n ...rest\n}: ModelProps) => {\n const { dracoDecoderPath } = useRefractConfig();\n const resolvedDecoderPath = decoderPath ?? dracoDecoderPath;\n const [loaded, setLoaded] = useState(false);\n const container = useRef<HTMLDivElement>(null);\n const canvas = useRef<HTMLCanvasElement>(null);\n const camera = useRef<PerspectiveCamera>();\n const modelGroup = useRef<Group>();\n const scene = useRef<Scene>();\n const renderer = useRef<WebGLRenderer>();\n const shadowGroup = useRef<Group>();\n const renderTarget = useRef<WebGLRenderTarget>();\n const renderTargetBlur = useRef<WebGLRenderTarget>();\n const shadowCamera = useRef<OrthographicCamera>();\n const depthMaterial = useRef<MeshDepthMaterial>();\n const horizontalBlurMaterial = useRef<ShaderMaterial>();\n const verticalBlurMaterial = useRef<ShaderMaterial>();\n const plane = useRef<Mesh>();\n const lights = useRef<Light[]>();\n const blurPlane = useRef<Mesh>();\n const fillPlane = useRef<Mesh>();\n const isInViewport = useInViewport(container, false, { threshold: 0.2 });\n const reduceMotion = useReducedMotion();\n const rotationX = useSpring(0, rotationSpringConfig);\n const rotationY = useSpring(0, rotationSpringConfig);\n const { measureFps, isLowFps } = useFps(isInViewport);\n\n useEffect(() => {\n const { clientWidth, clientHeight } = container.current!;\n\n renderer.current = new WebGLRenderer({\n canvas: canvas.current!,\n alpha: true,\n antialias: false,\n powerPreference: 'high-performance',\n failIfMajorPerformanceCaveat: true,\n });\n\n renderer.current.setPixelRatio(2);\n renderer.current.setSize(clientWidth, clientHeight);\n renderer.current.outputColorSpace = SRGBColorSpace;\n\n camera.current = new PerspectiveCamera(36, clientWidth / clientHeight, 0.1, 100);\n camera.current.position.set(cameraPosition.x, cameraPosition.y, cameraPosition.z);\n scene.current = new Scene();\n\n modelGroup.current = new Group();\n scene.current.add(modelGroup.current);\n\n const ambientLight = new AmbientLight(0xffffff, 1.2);\n const keyLight = new DirectionalLight(0xffffff, 1.1);\n const fillLight = new DirectionalLight(0xffffff, 0.8);\n\n fillLight.position.set(-6, 2, 2);\n keyLight.position.set(0.5, 0, 0.866);\n lights.current = [ambientLight, keyLight, fillLight];\n lights.current.forEach(light => scene.current!.add(light));\n\n shadowGroup.current = new Group();\n scene.current.add(shadowGroup.current);\n shadowGroup.current.position.set(0, 0, -0.8);\n shadowGroup.current.rotateX(Math.PI / 2);\n\n const renderTargetSize = 512;\n const planeWidth = 8;\n const planeHeight = 8;\n const cameraHeight = 1.5;\n const shadowOpacity = 0.8;\n const shadowDarkness = 3;\n\n renderTarget.current = new WebGLRenderTarget(renderTargetSize, renderTargetSize);\n renderTarget.current.texture.generateMipmaps = false;\n\n renderTargetBlur.current = new WebGLRenderTarget(renderTargetSize, renderTargetSize);\n renderTargetBlur.current.texture.generateMipmaps = false;\n\n const planeGeometry = new PlaneGeometry(planeWidth, planeHeight).rotateX(\n Math.PI / 2\n );\n\n const planeMaterial = new MeshBasicMaterial({\n map: renderTarget.current.texture,\n opacity: shadowOpacity,\n transparent: true,\n });\n\n plane.current = new Mesh(planeGeometry, planeMaterial);\n plane.current.scale.y = -1;\n shadowGroup.current.add(plane.current);\n\n blurPlane.current = new Mesh(planeGeometry);\n blurPlane.current.visible = false;\n shadowGroup.current.add(blurPlane.current);\n\n const fillMaterial = new MeshBasicMaterial({\n color: 0xffffff,\n opacity: 0,\n transparent: true,\n });\n\n fillPlane.current = new Mesh(planeGeometry, fillMaterial);\n fillPlane.current.rotateX(Math.PI);\n fillPlane.current.position.y -= 0.00001;\n shadowGroup.current.add(fillPlane.current);\n\n shadowCamera.current = new OrthographicCamera(\n -planeWidth / 2,\n planeWidth / 2,\n planeHeight / 2,\n -planeHeight / 2,\n 0,\n cameraHeight\n );\n shadowCamera.current.rotation.x = Math.PI / 2;\n shadowGroup.current.add(shadowCamera.current);\n\n depthMaterial.current = new MeshDepthMaterial();\n depthMaterial.current.userData.darkness = { value: shadowDarkness };\n depthMaterial.current.onBeforeCompile = shader => {\n shader.uniforms.darkness = depthMaterial.current!.userData.darkness;\n shader.fragmentShader = `\n uniform float darkness;\n ${shader.fragmentShader.replace(\n 'gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );',\n 'gl_FragColor = vec4( vec3( 0.0 ), ( 1.0 - fragCoordZ ) * darkness );'\n )}\n `;\n };\n depthMaterial.current.depthTest = false;\n depthMaterial.current.depthWrite = false;\n\n horizontalBlurMaterial.current = new ShaderMaterial(HorizontalBlurShader);\n horizontalBlurMaterial.current.depthTest = false;\n\n verticalBlurMaterial.current = new ShaderMaterial(VerticalBlurShader);\n verticalBlurMaterial.current.depthTest = false;\n\n // eslint-disable-next-line react-hooks/immutability\n const unsubscribeX = rotationX.onChange(renderFrame);\n const unsubscribeY = rotationY.onChange(renderFrame);\n\n return () => {\n renderTarget.current!.dispose();\n renderTargetBlur.current!.dispose();\n removeLights(lights.current!);\n cleanScene(scene.current!);\n cleanRenderer(renderer.current!);\n unsubscribeX();\n unsubscribeY();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const blurShadow = useCallback((amount: number) => {\n blurPlane.current!.visible = true;\n\n blurPlane.current!.material = horizontalBlurMaterial.current!;\n (blurPlane.current!.material as ShaderMaterial).uniforms.tDiffuse.value = renderTarget.current!.texture;\n horizontalBlurMaterial.current!.uniforms.h.value = amount * (1 / 256);\n\n renderer.current!.setRenderTarget(renderTargetBlur.current!);\n renderer.current!.render(blurPlane.current!, shadowCamera.current!);\n\n blurPlane.current!.material = verticalBlurMaterial.current!;\n (blurPlane.current!.material as ShaderMaterial).uniforms.tDiffuse.value = renderTargetBlur.current!.texture;\n verticalBlurMaterial.current!.uniforms.v.value = amount * (1 / 256);\n\n renderer.current!.setRenderTarget(renderTarget.current!);\n renderer.current!.render(blurPlane.current!, shadowCamera.current!);\n\n blurPlane.current!.visible = false;\n }, []);\n\n // eslint-disable-next-line react-hooks/preserve-manual-memoization\n const renderFrame = useCallback(() => {\n const blurAmount = 5;\n\n const initialBackground = scene.current!.background;\n scene.current!.background = null;\n\n scene.current!.overrideMaterial = depthMaterial.current!;\n\n renderer.current!.setRenderTarget(renderTarget.current!);\n renderer.current!.render(scene.current!, shadowCamera.current!);\n\n scene.current!.overrideMaterial = null;\n\n blurShadow(blurAmount);\n\n blurShadow(blurAmount * 0.4);\n\n renderer.current!.setRenderTarget(null);\n scene.current!.background = initialBackground;\n\n modelGroup.current!.rotation.x = rotationX.get();\n modelGroup.current!.rotation.y = rotationY.get();\n\n renderer.current!.render(scene.current!, camera.current!);\n measureFps();\n\n if (isLowFps.current) {\n renderer.current!.setPixelRatio(1);\n } else {\n renderer.current!.setPixelRatio(2);\n }\n }, [blurShadow, isLowFps, measureFps, rotationX, rotationY]);\n\n useEffect(() => {\n const onMouseMove = (event: globalThis.MouseEvent) => {\n const { innerWidth, innerHeight } = window;\n\n const position = {\n x: (event.clientX - innerWidth / 2) / innerWidth,\n y: (event.clientY - innerHeight / 2) / innerHeight,\n };\n\n rotationY.set(position.x / 2);\n rotationX.set(position.y / 2);\n };\n\n if (isInViewport && !reduceMotion) {\n window.addEventListener('mousemove', onMouseMove);\n }\n\n return () => {\n window.removeEventListener('mousemove', onMouseMove);\n };\n }, [isInViewport, reduceMotion, rotationX, rotationY]);\n\n useEffect(() => {\n const handleResize = () => {\n if (!container.current) return;\n\n const { clientWidth, clientHeight } = container.current;\n\n renderer.current!.setSize(clientWidth, clientHeight);\n camera.current!.aspect = clientWidth / clientHeight;\n camera.current!.updateProjectionMatrix();\n\n renderFrame();\n };\n\n window.addEventListener('resize', handleResize);\n handleResize();\n\n return () => {\n window.removeEventListener('resize', handleResize);\n };\n }, [renderFrame]);\n\n return (\n <div\n className={classes(styles.model, className)}\n data-loaded={loaded}\n style={cssProps({ delay: numToMs(showDelay) }, style)}\n ref={container}\n role=\"img\"\n aria-label={alt}\n {...rest}\n >\n <canvas className={styles.canvas} ref={canvas} />\n {models.map((model, index) => (\n <Device\n key={JSON.stringify(model.position)}\n renderer={renderer}\n modelGroup={modelGroup}\n show={show}\n showDelay={showDelay}\n renderFrame={renderFrame}\n index={index}\n setLoaded={setLoaded}\n model={model}\n decoderPath={resolvedDecoderPath}\n />\n ))}\n </div>\n );\n};\n\ninterface DeviceProps {\n renderer: RefObject<WebGLRenderer | undefined>;\n model: ModelConfig;\n modelGroup: RefObject<Group | undefined>;\n renderFrame: () => void;\n index: number;\n showDelay: number;\n setLoaded: (loaded: boolean) => void;\n show: boolean;\n decoderPath?: string;\n}\n\ninterface LoadResult {\n loadFullResTexture: () => Promise<void>;\n playAnimation: () => { stop: () => void } | void;\n}\n\nconst Device = ({\n renderer,\n model,\n modelGroup,\n renderFrame,\n index,\n showDelay,\n setLoaded,\n show,\n decoderPath,\n}: DeviceProps) => {\n const [loadDevice, setLoadDevice] = useState<{ start: () => Promise<LoadResult> }>();\n const reduceMotion = useReducedMotion();\n const placeholderScreen = createRef<Mesh>();\n\n useEffect(() => {\n const applyScreenTexture = async (texture: Texture, node: Mesh) => {\n texture.colorSpace = SRGBColorSpace;\n texture.flipY = false;\n texture.anisotropy = renderer.current!.capabilities.getMaxAnisotropy();\n texture.generateMipmaps = false;\n\n await renderer.current!.initTexture(texture);\n\n (node.material as MeshBasicMaterial).color = new Color(0xffffff);\n (node.material as MeshBasicMaterial).transparent = true;\n (node.material as MeshBasicMaterial).map = texture;\n };\n\n const load = async (): Promise<LoadResult> => {\n const { texture, position, url } = model;\n let loadFullResTexture: () => Promise<void> = async () => {};\n let playAnimation: () => { stop: () => void } | void = () => {};\n\n const [placeholder, gltf] = await Promise.all([\n textureLoader.loadAsync(\n typeof texture.placeholder === 'string' ? texture.placeholder : texture.placeholder.src\n ),\n getModelLoader(decoderPath).loadAsync(url),\n ]);\n\n modelGroup.current!.add(gltf.scene);\n\n gltf.scene.traverse(async (node: unknown) => {\n const meshNode = node as Mesh;\n if (meshNode.material) {\n (meshNode.material as MeshBasicMaterial).color = new Color(0x1f2025);\n }\n\n if (meshNode.name === MeshType.Screen) {\n (placeholderScreen as { current: Mesh | null }).current = meshNode.clone();\n (placeholderScreen.current!.material as MeshBasicMaterial) = (meshNode.material as MeshBasicMaterial).clone();\n meshNode.parent!.add(placeholderScreen.current!);\n (placeholderScreen.current!.material as MeshBasicMaterial).opacity = 1;\n placeholderScreen.current!.position.z += 0.001;\n\n applyScreenTexture(placeholder, placeholderScreen.current!);\n\n loadFullResTexture = async () => {\n const image = await resolveSrcFromSrcSet({\n srcSet: texture.srcSet as unknown as string | { src: string; width: number }[],\n sizes: texture.sizes,\n });\n const fullSize = await textureLoader.loadAsync(image);\n await applyScreenTexture(fullSize, meshNode);\n\n animate(1, 0, {\n onUpdate: (value: number) => {\n (placeholderScreen.current!.material as MeshBasicMaterial).opacity = value;\n renderFrame();\n },\n });\n };\n }\n });\n\n const targetPosition = new Vector3(position.x, position.y, position.z);\n\n if (reduceMotion) {\n gltf.scene.position.set(...targetPosition.toArray());\n }\n\n if (model.animation === ModelAnimationType.SpringUp) {\n playAnimation = () => {\n const startPosition = new Vector3(\n targetPosition.x,\n targetPosition.y - 1,\n targetPosition.z\n );\n\n gltf.scene.position.set(...startPosition.toArray());\n\n animate(startPosition.y, targetPosition.y, {\n type: 'spring',\n delay: (300 * index + showDelay) / 1000,\n stiffness: 60,\n damping: 20,\n mass: 1,\n restSpeed: 0.0001,\n restDelta: 0.0001,\n onUpdate: (value: number) => {\n gltf.scene.position.y = value;\n renderFrame();\n },\n });\n };\n }\n\n if (model.animation === ModelAnimationType.LaptopOpen) {\n playAnimation = () => {\n const frameNode = gltf.scene.children.find(\n (child: { name: string }) => child.name === MeshType.Frame\n )!;\n const startRotation = new Vector3(MathUtils.degToRad(90), 0, 0);\n const endRotation = new Vector3(0, 0, 0);\n\n gltf.scene.position.set(...targetPosition.toArray());\n frameNode.rotation.set(...startRotation.toArray());\n\n return animate(startRotation.x, endRotation.x, {\n type: 'spring',\n delay: (300 * index + showDelay + 300) / 1000,\n stiffness: 80,\n damping: 20,\n restSpeed: 0.0001,\n restDelta: 0.0001,\n onUpdate: (value: number) => {\n frameNode.rotation.x = value;\n renderFrame();\n },\n });\n };\n }\n\n return { loadFullResTexture, playAnimation };\n };\n\n setLoadDevice({ start: load });\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n useEffect(() => {\n if (!loadDevice || !show) return;\n let animation: { stop: () => void } | void;\n\n const onLoad = async () => {\n const { loadFullResTexture, playAnimation } = await loadDevice.start();\n\n setLoaded(true);\n\n if (!reduceMotion) {\n animation = playAnimation();\n }\n\n await loadFullResTexture();\n\n if (reduceMotion) {\n renderFrame();\n }\n };\n\n startTransition(() => {\n onLoad();\n });\n\n return () => {\n animation?.stop();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [loadDevice, show]);\n\n return null;\n};\n"],"names":["HISTORY_LENGTH","useFps","running","fps","useRef","prevTime","frames","frameHistory","isLowFps","useEffect","useCallback","currentTime","item","ModelAnimationType","MODEL_FILES","createDeviceModels","basePath","deviceModels","MeshType","rotationSpringConfig","Model","models","show","showDelay","cameraPosition","style","className","alt","decoderPath","rest","dracoDecoderPath","useRefractConfig","resolvedDecoderPath","loaded","setLoaded","useState","container","canvas","camera","modelGroup","scene","renderer","shadowGroup","renderTarget","renderTargetBlur","shadowCamera","depthMaterial","horizontalBlurMaterial","verticalBlurMaterial","plane","lights","blurPlane","fillPlane","isInViewport","useInViewport","reduceMotion","useReducedMotion","rotationX","useSpring","rotationY","measureFps","clientWidth","clientHeight","WebGLRenderer","SRGBColorSpace","PerspectiveCamera","Scene","Group","ambientLight","AmbientLight","keyLight","DirectionalLight","fillLight","light","renderTargetSize","planeWidth","planeHeight","cameraHeight","shadowOpacity","shadowDarkness","WebGLRenderTarget","planeGeometry","PlaneGeometry","planeMaterial","MeshBasicMaterial","Mesh","fillMaterial","OrthographicCamera","MeshDepthMaterial","shader","ShaderMaterial","HorizontalBlurShader","VerticalBlurShader","unsubscribeX","renderFrame","unsubscribeY","removeLights","cleanScene","cleanRenderer","blurShadow","amount","initialBackground","onMouseMove","event","innerWidth","innerHeight","position","handleResize","jsxs","classes","styles","cssProps","numToMs","jsx","model","index","Device","loadDevice","setLoadDevice","placeholderScreen","createRef","applyScreenTexture","texture","node","Color","url","loadFullResTexture","playAnimation","placeholder","gltf","textureLoader","getModelLoader","meshNode","image","resolveSrcFromSrcSet","fullSize","animate","value","targetPosition","Vector3","startPosition","frameNode","child","startRotation","MathUtils","endRotation","animation","onLoad","startTransition"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use client";"use strict";const f=require("react");function w(e,r,c={},o=!0){const[s,t]=f.useState(!1),[n,i]=f.useState(!1);return f.useEffect(()=>{if(!(e!=null&&e.current))return;const a=new IntersectionObserver(([u])=>{const{isIntersecting:m,target:l}=u;t(m),m&&r&&(a.unobserve(l),i(!0))},c);return!n&&o&&a.observe(e.current),()=>a.disconnect()},[e,r,c,n,o]),s}async function g({src:e,srcSet:r,sizes:c}){return new Promise((o,s)=>{const t=p(r);try{if(!e&&!r)throw new Error("No image src or srcSet provided");let n=new Image;e&&(n.src=e),t&&(n.srcset=t),c&&(n.sizes=c);const i=()=>{n.removeEventListener("load",i);const a=n.currentSrc;n=null,o(a)};n.addEventListener("load",i)}catch(n){s(`Error loading ${t}: ${n}`)}})}function p(e=[]){return typeof e=="string"?e:e.map(r=>`${r.src} ${r.width}w`).join(", ")}async function T(e=1,r=1){return new Promise(c=>{const o=document.createElement("canvas"),s=o.getContext("2d");if(!s)throw new Error("Could not get 2d canvas context");o.width=e,o.height=r,s.fillStyle="rgba(0, 0, 0, 0)",s.fillRect(0,0,e,r),o.toBlob(async t=>{if(!t)throw new Error("Video thumbnail failed to load");const n=URL.createObjectURL(t);o.remove(),c(n)})})}async function v({srcSet:e,sizes:r}){const c=p(e),o=await Promise.all(c.split(", ").map(async i=>{const[a,u]=i.split(" "),m=Number(u.replace("w","")),l=await T(m);return{src:a,image:l,width:u}})),s=o.map(({image:i,width:a})=>`${i} ${a}`).join(", "),t=await g({srcSet:s,sizes:r});return o.find(i=>i.image===t).src}const y={desktop:2080,laptop:1680,tablet:1040,mobile:696,mobileS:400},b=e=>Number(e.replace("px","")),d=e=>`${e}px`,x=e=>`${e/16}rem`,$=e=>Number(e.replace("ms","")),S=e=>`${e}ms`,I=e=>(e==null?void 0:e.split(" ").map(r=>Number(r)/255))||[];function N(e,r={}){const c={},o=Object.keys(e);for(const s of o){let t=e[s];typeof t=="number"&&s==="delay"&&(t=S(t)),typeof t=="number"&&s!=="opacity"&&(t=d(t)),c[`--${s}`]=t}return{...c,...r}}function h(...e){return e.filter(Boolean).join(" ")}exports.classes=h;exports.cssProps=N;exports.media=y;exports.msToNum=$;exports.numToMs=S;exports.numToPx=d;exports.pxToNum=b;exports.pxToRem=x;exports.resolveSrcFromSrcSet=v;exports.rgbToThreeColor=I;exports.srcSetToString=p;exports.useInViewport=w;
2
+ //# sourceMappingURL=style-CWBkJEps.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-CWBkJEps.cjs","sources":["../src/hooks/useInViewport.ts","../src/utils/image.ts","../src/utils/style.ts"],"sourcesContent":["import { useEffect, useState, type RefObject } from 'react';\n\nexport function useInViewport(\n elementRef: RefObject<HTMLElement | null>,\n unobserveOnIntersect?: boolean,\n options: IntersectionObserverInit = {},\n shouldObserve = true\n): boolean {\n const [intersect, setIntersect] = useState(false);\n const [isUnobserved, setIsUnobserved] = useState(false);\n\n useEffect(() => {\n if (!elementRef?.current) return;\n\n const observer = new IntersectionObserver(([entry]) => {\n const { isIntersecting, target } = entry;\n\n setIntersect(isIntersecting);\n\n if (isIntersecting && unobserveOnIntersect) {\n observer.unobserve(target);\n setIsUnobserved(true);\n }\n }, options);\n\n if (!isUnobserved && shouldObserve) {\n observer.observe(elementRef.current);\n }\n\n return () => observer.disconnect();\n }, [elementRef, unobserveOnIntersect, options, isUnobserved, shouldObserve]);\n\n return intersect;\n}\n","interface SrcSetItem {\n src: string;\n width: number;\n}\n\ntype SrcSet = string | SrcSetItem[];\n\n/**\n * Use the browser's image loading to load an image and\n * grab the `src` it chooses from a `srcSet`\n */\nexport async function loadImageFromSrcSet({\n src,\n srcSet,\n sizes,\n}: {\n src?: string;\n srcSet?: SrcSet;\n sizes?: string;\n}): Promise<string> {\n return new Promise((resolve, reject) => {\n const srcSetString = srcSetToString(srcSet);\n\n try {\n if (!src && !srcSet) {\n throw new Error('No image src or srcSet provided');\n }\n\n let tempImage: HTMLImageElement | null = new Image();\n\n if (src) {\n tempImage.src = src;\n }\n\n if (srcSetString) {\n tempImage.srcset = srcSetString;\n }\n\n if (sizes) {\n tempImage.sizes = sizes;\n }\n\n const onLoad = (): void => {\n tempImage!.removeEventListener('load', onLoad);\n const source = tempImage!.currentSrc;\n tempImage = null;\n resolve(source);\n };\n\n tempImage.addEventListener('load', onLoad);\n } catch (error) {\n reject(`Error loading ${srcSetString}: ${error}`);\n }\n });\n}\n\n/**\n * Convert a `srcSet` array to a plain old `srcSet` string\n */\nexport function srcSetToString(srcSet: SrcSet = []): string {\n if (typeof srcSet === 'string') {\n return srcSet;\n }\n\n return srcSet.map(item => `${item.src} ${item.width}w`).join(', ');\n}\n\n/**\n * Generates a transparent png of a given width and height\n */\nexport async function generateImage(width: number = 1, height: number = 1): Promise<string> {\n return new Promise(resolve => {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n\n if (!ctx) {\n throw new Error('Could not get 2d canvas context');\n }\n\n canvas.width = width;\n canvas.height = height;\n\n ctx.fillStyle = 'rgba(0, 0, 0, 0)';\n ctx.fillRect(0, 0, width, height);\n\n canvas.toBlob(async blob => {\n if (!blob) throw new Error('Video thumbnail failed to load');\n const image = URL.createObjectURL(blob);\n canvas.remove();\n resolve(image);\n });\n });\n}\n\n/**\n * Use native html image `srcSet` resolution for non-html images\n */\nexport async function resolveSrcFromSrcSet({\n srcSet,\n sizes,\n}: {\n srcSet?: SrcSet;\n sizes?: string;\n [key: string]: unknown;\n}): Promise<string> {\n const stringSrcSet = srcSetToString(srcSet);\n\n const sources = await Promise.all(\n stringSrcSet.split(', ').map(async srcString => {\n const [src, width] = srcString.split(' ');\n const size = Number(width.replace('w', ''));\n const image = await generateImage(size);\n return { src, image, width };\n })\n );\n\n const fakeSrcSet = sources.map(({ image, width }) => `${image} ${width}`).join(', ');\n const fakeSrc = await loadImageFromSrcSet({ srcSet: fakeSrcSet, sizes });\n\n const output = sources.find(src => src.image === fakeSrc);\n return output!.src;\n}\n","import { CSSProperties } from 'react';\n\n/**\n * Media query breakpoints\n */\nexport const media = {\n desktop: 2080,\n laptop: 1680,\n tablet: 1040,\n mobile: 696,\n mobileS: 400,\n} as const;\n\n/**\n * Convert a px string to a number\n */\nexport const pxToNum = (px: string): number => Number(px.replace('px', ''));\n\n/**\n * Convert a number to a px string\n */\nexport const numToPx = (num: number): string => `${num}px`;\n\n/**\n * Convert pixel values to rem for a11y\n */\nexport const pxToRem = (px: number): string => `${px / 16}rem`;\n\n/**\n * Convert ms token values to a raw numbers for ReactTransitionGroup\n * Transition delay props\n */\nexport const msToNum = (msString: string): number => Number(msString.replace('ms', ''));\n\n/**\n * Convert a number to an ms string\n */\nexport const numToMs = (num: number): string => `${num}ms`;\n\n/**\n * Convert an rgb theme property (e.g. rgbBlack: '0 0 0')\n * to values that can be spread into a ThreeJS Color class\n */\nexport const rgbToThreeColor = (rgb: string | undefined): number[] =>\n rgb?.split(' ').map(value => Number(value) / 255) || [];\n\n/**\n * Convert a JS object into `--` prefixed css custom properties.\n * Optionally pass a second param for normal styles\n */\nexport function cssProps(\n props: Record<string, string | number>,\n style: CSSProperties = {}\n): Record<string, string | number> & CSSProperties {\n const result: Record<string, string | number> = {};\n\n const keys = Object.keys(props);\n\n for (const key of keys) {\n let value: string | number = props[key];\n\n if (typeof value === 'number' && key === 'delay') {\n value = numToMs(value);\n }\n\n if (typeof value === 'number' && key !== 'opacity') {\n value = numToPx(value);\n }\n\n result[`--${key}`] = value;\n }\n\n return { ...result, ...style };\n}\n\n/**\n * Concatenate classNames together\n */\nexport function classes(...args: (string | false | undefined | null)[]): string {\n return args.filter(Boolean).join(' ');\n}\n"],"names":["useInViewport","elementRef","unobserveOnIntersect","options","shouldObserve","intersect","setIntersect","useState","isUnobserved","setIsUnobserved","useEffect","observer","entry","isIntersecting","target","loadImageFromSrcSet","src","srcSet","sizes","resolve","reject","srcSetString","srcSetToString","tempImage","onLoad","source","error","item","generateImage","width","height","canvas","ctx","blob","image","resolveSrcFromSrcSet","stringSrcSet","sources","srcString","size","fakeSrcSet","fakeSrc","media","pxToNum","px","numToPx","num","pxToRem","msToNum","msString","numToMs","rgbToThreeColor","rgb","value","cssProps","props","style","result","keys","key","classes","args"],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ "use client";
2
+ import { useState as f, useEffect as d } from "react";
3
+ function v(t, r, c = {}, o = !0) {
4
+ const [s, e] = f(!1), [n, a] = f(!1);
5
+ return d(() => {
6
+ if (!(t != null && t.current)) return;
7
+ const i = new IntersectionObserver(([u]) => {
8
+ const { isIntersecting: m, target: l } = u;
9
+ e(m), m && r && (i.unobserve(l), a(!0));
10
+ }, c);
11
+ return !n && o && i.observe(t.current), () => i.disconnect();
12
+ }, [t, r, c, n, o]), s;
13
+ }
14
+ async function w({
15
+ src: t,
16
+ srcSet: r,
17
+ sizes: c
18
+ }) {
19
+ return new Promise((o, s) => {
20
+ const e = p(r);
21
+ try {
22
+ if (!t && !r)
23
+ throw new Error("No image src or srcSet provided");
24
+ let n = new Image();
25
+ t && (n.src = t), e && (n.srcset = e), c && (n.sizes = c);
26
+ const a = () => {
27
+ n.removeEventListener("load", a);
28
+ const i = n.currentSrc;
29
+ n = null, o(i);
30
+ };
31
+ n.addEventListener("load", a);
32
+ } catch (n) {
33
+ s(`Error loading ${e}: ${n}`);
34
+ }
35
+ });
36
+ }
37
+ function p(t = []) {
38
+ return typeof t == "string" ? t : t.map((r) => `${r.src} ${r.width}w`).join(", ");
39
+ }
40
+ async function S(t = 1, r = 1) {
41
+ return new Promise((c) => {
42
+ const o = document.createElement("canvas"), s = o.getContext("2d");
43
+ if (!s)
44
+ throw new Error("Could not get 2d canvas context");
45
+ o.width = t, o.height = r, s.fillStyle = "rgba(0, 0, 0, 0)", s.fillRect(0, 0, t, r), o.toBlob(async (e) => {
46
+ if (!e) throw new Error("Video thumbnail failed to load");
47
+ const n = URL.createObjectURL(e);
48
+ o.remove(), c(n);
49
+ });
50
+ });
51
+ }
52
+ async function $({
53
+ srcSet: t,
54
+ sizes: r
55
+ }) {
56
+ const c = p(t), o = await Promise.all(
57
+ c.split(", ").map(async (a) => {
58
+ const [i, u] = a.split(" "), m = Number(u.replace("w", "")), l = await S(m);
59
+ return { src: i, image: l, width: u };
60
+ })
61
+ ), s = o.map(({ image: a, width: i }) => `${a} ${i}`).join(", "), e = await w({ srcSet: s, sizes: r });
62
+ return o.find((a) => a.image === e).src;
63
+ }
64
+ const x = {
65
+ desktop: 2080,
66
+ laptop: 1680,
67
+ tablet: 1040,
68
+ mobile: 696,
69
+ mobileS: 400
70
+ }, E = (t) => Number(t.replace("px", "")), g = (t) => `${t}px`, I = (t) => `${t / 16}rem`, T = (t) => Number(t.replace("ms", "")), y = (t) => `${t}ms`, h = (t) => (t == null ? void 0 : t.split(" ").map((r) => Number(r) / 255)) || [];
71
+ function N(t, r = {}) {
72
+ const c = {}, o = Object.keys(t);
73
+ for (const s of o) {
74
+ let e = t[s];
75
+ typeof e == "number" && s === "delay" && (e = y(e)), typeof e == "number" && s !== "opacity" && (e = g(e)), c[`--${s}`] = e;
76
+ }
77
+ return { ...c, ...r };
78
+ }
79
+ function k(...t) {
80
+ return t.filter(Boolean).join(" ");
81
+ }
82
+ export {
83
+ k as a,
84
+ x as b,
85
+ N as c,
86
+ g as d,
87
+ I as e,
88
+ h as f,
89
+ T as m,
90
+ y as n,
91
+ E as p,
92
+ $ as r,
93
+ p as s,
94
+ v as u
95
+ };
96
+ //# sourceMappingURL=style-uMN7vipQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-uMN7vipQ.js","sources":["../src/hooks/useInViewport.ts","../src/utils/image.ts","../src/utils/style.ts"],"sourcesContent":["import { useEffect, useState, type RefObject } from 'react';\n\nexport function useInViewport(\n elementRef: RefObject<HTMLElement | null>,\n unobserveOnIntersect?: boolean,\n options: IntersectionObserverInit = {},\n shouldObserve = true\n): boolean {\n const [intersect, setIntersect] = useState(false);\n const [isUnobserved, setIsUnobserved] = useState(false);\n\n useEffect(() => {\n if (!elementRef?.current) return;\n\n const observer = new IntersectionObserver(([entry]) => {\n const { isIntersecting, target } = entry;\n\n setIntersect(isIntersecting);\n\n if (isIntersecting && unobserveOnIntersect) {\n observer.unobserve(target);\n setIsUnobserved(true);\n }\n }, options);\n\n if (!isUnobserved && shouldObserve) {\n observer.observe(elementRef.current);\n }\n\n return () => observer.disconnect();\n }, [elementRef, unobserveOnIntersect, options, isUnobserved, shouldObserve]);\n\n return intersect;\n}\n","interface SrcSetItem {\n src: string;\n width: number;\n}\n\ntype SrcSet = string | SrcSetItem[];\n\n/**\n * Use the browser's image loading to load an image and\n * grab the `src` it chooses from a `srcSet`\n */\nexport async function loadImageFromSrcSet({\n src,\n srcSet,\n sizes,\n}: {\n src?: string;\n srcSet?: SrcSet;\n sizes?: string;\n}): Promise<string> {\n return new Promise((resolve, reject) => {\n const srcSetString = srcSetToString(srcSet);\n\n try {\n if (!src && !srcSet) {\n throw new Error('No image src or srcSet provided');\n }\n\n let tempImage: HTMLImageElement | null = new Image();\n\n if (src) {\n tempImage.src = src;\n }\n\n if (srcSetString) {\n tempImage.srcset = srcSetString;\n }\n\n if (sizes) {\n tempImage.sizes = sizes;\n }\n\n const onLoad = (): void => {\n tempImage!.removeEventListener('load', onLoad);\n const source = tempImage!.currentSrc;\n tempImage = null;\n resolve(source);\n };\n\n tempImage.addEventListener('load', onLoad);\n } catch (error) {\n reject(`Error loading ${srcSetString}: ${error}`);\n }\n });\n}\n\n/**\n * Convert a `srcSet` array to a plain old `srcSet` string\n */\nexport function srcSetToString(srcSet: SrcSet = []): string {\n if (typeof srcSet === 'string') {\n return srcSet;\n }\n\n return srcSet.map(item => `${item.src} ${item.width}w`).join(', ');\n}\n\n/**\n * Generates a transparent png of a given width and height\n */\nexport async function generateImage(width: number = 1, height: number = 1): Promise<string> {\n return new Promise(resolve => {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n\n if (!ctx) {\n throw new Error('Could not get 2d canvas context');\n }\n\n canvas.width = width;\n canvas.height = height;\n\n ctx.fillStyle = 'rgba(0, 0, 0, 0)';\n ctx.fillRect(0, 0, width, height);\n\n canvas.toBlob(async blob => {\n if (!blob) throw new Error('Video thumbnail failed to load');\n const image = URL.createObjectURL(blob);\n canvas.remove();\n resolve(image);\n });\n });\n}\n\n/**\n * Use native html image `srcSet` resolution for non-html images\n */\nexport async function resolveSrcFromSrcSet({\n srcSet,\n sizes,\n}: {\n srcSet?: SrcSet;\n sizes?: string;\n [key: string]: unknown;\n}): Promise<string> {\n const stringSrcSet = srcSetToString(srcSet);\n\n const sources = await Promise.all(\n stringSrcSet.split(', ').map(async srcString => {\n const [src, width] = srcString.split(' ');\n const size = Number(width.replace('w', ''));\n const image = await generateImage(size);\n return { src, image, width };\n })\n );\n\n const fakeSrcSet = sources.map(({ image, width }) => `${image} ${width}`).join(', ');\n const fakeSrc = await loadImageFromSrcSet({ srcSet: fakeSrcSet, sizes });\n\n const output = sources.find(src => src.image === fakeSrc);\n return output!.src;\n}\n","import { CSSProperties } from 'react';\n\n/**\n * Media query breakpoints\n */\nexport const media = {\n desktop: 2080,\n laptop: 1680,\n tablet: 1040,\n mobile: 696,\n mobileS: 400,\n} as const;\n\n/**\n * Convert a px string to a number\n */\nexport const pxToNum = (px: string): number => Number(px.replace('px', ''));\n\n/**\n * Convert a number to a px string\n */\nexport const numToPx = (num: number): string => `${num}px`;\n\n/**\n * Convert pixel values to rem for a11y\n */\nexport const pxToRem = (px: number): string => `${px / 16}rem`;\n\n/**\n * Convert ms token values to a raw numbers for ReactTransitionGroup\n * Transition delay props\n */\nexport const msToNum = (msString: string): number => Number(msString.replace('ms', ''));\n\n/**\n * Convert a number to an ms string\n */\nexport const numToMs = (num: number): string => `${num}ms`;\n\n/**\n * Convert an rgb theme property (e.g. rgbBlack: '0 0 0')\n * to values that can be spread into a ThreeJS Color class\n */\nexport const rgbToThreeColor = (rgb: string | undefined): number[] =>\n rgb?.split(' ').map(value => Number(value) / 255) || [];\n\n/**\n * Convert a JS object into `--` prefixed css custom properties.\n * Optionally pass a second param for normal styles\n */\nexport function cssProps(\n props: Record<string, string | number>,\n style: CSSProperties = {}\n): Record<string, string | number> & CSSProperties {\n const result: Record<string, string | number> = {};\n\n const keys = Object.keys(props);\n\n for (const key of keys) {\n let value: string | number = props[key];\n\n if (typeof value === 'number' && key === 'delay') {\n value = numToMs(value);\n }\n\n if (typeof value === 'number' && key !== 'opacity') {\n value = numToPx(value);\n }\n\n result[`--${key}`] = value;\n }\n\n return { ...result, ...style };\n}\n\n/**\n * Concatenate classNames together\n */\nexport function classes(...args: (string | false | undefined | null)[]): string {\n return args.filter(Boolean).join(' ');\n}\n"],"names":["useInViewport","elementRef","unobserveOnIntersect","options","shouldObserve","intersect","setIntersect","useState","isUnobserved","setIsUnobserved","useEffect","observer","entry","isIntersecting","target","loadImageFromSrcSet","src","srcSet","sizes","resolve","reject","srcSetString","srcSetToString","tempImage","onLoad","source","error","item","generateImage","width","height","canvas","ctx","blob","image","resolveSrcFromSrcSet","stringSrcSet","sources","srcString","size","fakeSrcSet","fakeSrc","media","pxToNum","px","numToPx","num","pxToRem","msToNum","msString","numToMs","rgbToThreeColor","rgb","value","cssProps","props","style","result","keys","key","classes","args"],"mappings":"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"}
package/dist/styles.css CHANGED
@@ -1 +1 @@
1
- @keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes reveal{0%{transform:scale3d(0,1,1);transform-origin:left}50%{transform:scaleZ(1);transform-origin:left}51%{transform:scaleZ(1);transform-origin:right}to{transform:scale3d(0,1,1);transform-origin:right}}._text_18l38_1{line-height:var(--lineHeightBody);color:var(--colorTextBody)}._text_18l38_1[data-size=s]{font-size:var(--fontSizeBodyS)}._text_18l38_1[data-size=m]{font-size:var(--fontSizeBodyM)}._text_18l38_1[data-size=l]{font-size:var(--fontSizeBodyL)}._text_18l38_1[data-size=xl]{font-size:var(--fontSizeBodyXL)}._text_18l38_1[data-align=auto]{text-align:inherit}._text_18l38_1[data-align=start]{text-align:start}._text_18l38_1[data-align=center]{text-align:center}._text_18l38_1[data-weight=auto]{font-weight:inherit}._text_18l38_1[data-weight=regular]{font-weight:var(--fontWeightRegular)}._text_18l38_1[data-weight=medium]{font-weight:var(--fontWeightMedium)}._text_18l38_1[data-weight=bold]{font-weight:var(--fontWeightBold)}._text_18l38_1[data-secondary=true]{color:var(--colorTextLight)}
1
+ ._carousel_miavd_1{position:relative}._content_miavd_5{position:relative;display:grid;align-items:center}._imageWrapper_miavd_11{position:relative;display:grid;grid-template-columns:100%;cursor:grab;touch-action:none}._imageWrapper_miavd_11[data-dragging=true]{cursor:grabbing}._canvasWrapper_miavd_23{position:relative;grid-column:1;grid-row:1;-webkit-user-select:none;-moz-user-select:none;user-select:none;aspect-ratio:var(--aspectRatio);isolation:isolate}._canvas_miavd_23{position:relative}._placeholder_miavd_36{grid-column:1;grid-row:1;width:100%;transition:opacity 1s ease;opacity:1;pointer-events:none;position:relative;z-index:var(--zIndex1)}._placeholder_miavd_36[data-loaded=true]{opacity:0}._button_miavd_51{border:0;margin:0;background:none;width:70px;aspect-ratio:1 / 1;grid-area:1 / 1;position:absolute;z-index:var(--zIndex3);cursor:pointer;display:grid;place-items:center}._button_miavd_51:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;transition-property:background,box-shadow;transition-duration:var(--durationM);transition-timing-function:var(--bezierFastoutSlowin);clip-path:polygon(0 0,100% 0,100% calc(100% - 12px),calc(100% - 12px) 100%,0 100%)}._button_miavd_51:hover:before{background:rgb(var(--rgbWhite) / .1)}._button_miavd_51 svg{position:relative;left:var(--offset);fill:rgb(var(--rgbWhite))}@media(max-width:696px){._button_miavd_51{display:none}}._button_miavd_51[data-prev=true]{--offset: -2px;left:var(--spaceM)}._button_miavd_51[data-next=true]{--offset: 2px;right:var(--spaceM)}._nav_miavd_107{display:flex;align-items:center;justify-content:center;margin-top:var(--spaceS)}._navButton_miavd_114{--navButtonSize: 10px;--buttonColor: rgb(var(--rgbText) / .2);background:none;border:0;margin:0;padding:var(--spaceM);cursor:pointer}._navButton_miavd_114[aria-pressed=true]{--buttonColor: var(--colorTextBody)}._navButton_miavd_114:after{content:"";display:block;border-radius:50%;width:var(--navButtonSize);height:var(--navButtonSize);background:var(--buttonColor);transition-property:background,box-shadow;transition-duration:var(--durationL);transition-timing-function:var(--bezierFastoutSlowin)}._model_1mfwq_1{position:relative;opacity:0}._model_1mfwq_1[data-loaded=true]{animation:fadeIn 1s ease forwards var(--delay)}._canvas_1mfwq_10{position:absolute;top:0;right:0;bottom:0;left:0}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes reveal{0%{transform:scale3d(0,1,1);transform-origin:left}50%{transform:scaleZ(1);transform-origin:left}51%{transform:scaleZ(1);transform-origin:right}to{transform:scale3d(0,1,1);transform-origin:right}}._text_18l38_1{line-height:var(--lineHeightBody);color:var(--colorTextBody)}._text_18l38_1[data-size=s]{font-size:var(--fontSizeBodyS)}._text_18l38_1[data-size=m]{font-size:var(--fontSizeBodyM)}._text_18l38_1[data-size=l]{font-size:var(--fontSizeBodyL)}._text_18l38_1[data-size=xl]{font-size:var(--fontSizeBodyXL)}._text_18l38_1[data-align=auto]{text-align:inherit}._text_18l38_1[data-align=start]{text-align:start}._text_18l38_1[data-align=center]{text-align:center}._text_18l38_1[data-weight=auto]{font-weight:inherit}._text_18l38_1[data-weight=regular]{font-weight:var(--fontWeightRegular)}._text_18l38_1[data-weight=medium]{font-weight:var(--fontWeightMedium)}._text_18l38_1[data-weight=bold]{font-weight:var(--fontWeightBold)}._text_18l38_1[data-secondary=true]{color:var(--colorTextLight)}._heading_17xux_1{line-height:var(--lineHeightTitle);color:var(--colorTextTitle)}._heading_17xux_1[data-level="0"]{letter-spacing:-.05em;font-size:var(--fontSizeH0)}._heading_17xux_1[data-level="1"]{letter-spacing:-.05em;font-size:var(--fontSizeH1)}._heading_17xux_1[data-level="2"]{font-size:var(--fontSizeH2);letter-spacing:-.04em}._heading_17xux_1[data-level="3"]{font-size:var(--fontSizeH3);letter-spacing:-.02em}._heading_17xux_1[data-level="4"]{font-size:var(--fontSizeH4);letter-spacing:-.01em}._heading_17xux_1[data-level="5"]{font-size:var(--fontSizeH5)}._heading_17xux_1[data-align=auto]{text-align:inherit}._heading_17xux_1[data-align=start]{text-align:start}._heading_17xux_1[data-align=center]{text-align:center}._heading_17xux_1[data-weight=regular]{font-weight:var(--fontWeightRegular)}._heading_17xux_1[data-weight=medium]{font-weight:var(--fontWeightMedium)}._heading_17xux_1[data-weight=bold]{font-weight:var(--fontWeightBold)}._section_e4ou0_1{padding-right:var(--space5XL);padding-left:calc(var(--space4XL) * 2)}._section_e4ou0_1:focus{outline:none}@media(min-width:2080px){._section_e4ou0_1{padding-left:var(--space5XL)}}@media(max-width:1040px){._section_e4ou0_1{padding-left:calc(var(--space4XL) + var(--space3XL))}}@media(max-width:696px){._section_e4ou0_1{padding-right:var(--spaceL);padding-left:var(--spaceL)}}@media(max-width:696px),(max-height:696px){._section_e4ou0_1{padding-left:var(--spaceOuter);padding-right:var(--spaceOuter)}}@media(max-width:820px)and (max-height:420px){._section_e4ou0_1{padding-left:var(--space4XL);padding-right:var(--space4XL)}}._list_70779_1{padding-left:1.7em;line-height:var(--lineHeightBody)}ol._list_70779_1{list-style-type:decimal-leading-zero}ul._list_70779_1{list-style-type:none}._item_70779_14{--bulletSize: min(1.2em, 24px);--markerGap: var(--spaceS);margin-bottom:.6em}ol ._item_70779_14::marker{color:rgb(var(--rgbPrimary));font-feature-settings:"ordn";font-variant-numeric:ordinal;font-size:min(1.2em,16px);font-weight:var(--fontWeightMedium);font-family:var(--monoFontStack)}ul ._item_70779_14:before{content:"";position:relative;display:inline-block;vertical-align:middle;left:calc(var(--markerGap) * -1);margin-left:calc(var(--bulletSize) * -1);width:var(--bulletSize);height:var(--bulletSize);background-color:rgb(var(--rgbPrimary));-webkit-mask-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13.586 12L7.793 6.207l1.414-1.414 6.5 6.5.707.707-.707.707-6.5 6.5-1.414-1.414L13.586 12z"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13.586 12L7.793 6.207l1.414-1.414 6.5 6.5.707.707-.707.707-6.5 6.5-1.414-1.414L13.586 12z"/></svg>')}._divider_vqctv_1{--dividerOpacity: 1;position:relative;width:var(--lineWidth);height:var(--lineHeight)}._divider_vqctv_1[data-light=true]{--dividerOpacity: .2}._line_vqctv_14{width:100%;height:100%;background-color:rgb(var(--rgbPrimary));opacity:var(--dividerOpacity);transition-property:opacity;transition-duration:var(--durationL);transition-timing-function:var(--bezierFastoutSlowin);transition-delay:var(--collapseDelay);transform-origin:left center;transform:scaleX(1)}@media(prefers-reduced-motion:no-preference){._line_vqctv_14{transition-property:transform,opacity}}._line_vqctv_14[data-collapsed=true]{opacity:0;transform:scaleX(0)}._notch_vqctv_36{background-color:rgb(var(--rgbPrimary));position:absolute;transition-property:opacity;transition-duration:var(--durationL);transition-timing-function:var(--bezierFastoutSlowin);transition-delay:var(--collapseDelay);opacity:var(--dividerOpacity);clip-path:polygon(0 -1px,100% -1px,calc(100% - 10px) 100%,10px 100%);width:var(--notchWidth);height:var(--notchHeight);top:var(--lineHeight)}@media(prefers-reduced-motion:no-preference){._notch_vqctv_36{transition-property:clip-path,opacity}}._notch_vqctv_36[data-collapsed=true]{opacity:0;clip-path:polygon(0 -1px,0 -1px,10px 100%,10px 100%)}._table_1fa0f_1{border-collapse:collapse;width:100%}._row_1fa0f_6{--rowBorder: 1px solid rgb(var(--rgbText) / .2);border-top:var(--rowBorder)}._row_1fa0f_6:last-child{border-bottom:var(--rowBorder)}._head_1fa0f_15 ._row_1fa0f_6{border-top:0}._headCell_1fa0f_20{font-weight:var(--fontWeightMedium);text-align:left}._cell_1fa0f_25,._headCell_1fa0f_20{padding-right:var(--spaceXL);padding-top:var(--spaceM);padding-bottom:var(--spaceM)}._cell_1fa0f_25:last-child,._headCell_1fa0f_20:last-child{padding-right:0}._hidden_1xw0v_1{position:absolute}._hidden_1xw0v_1[data-hidden=true],._hidden_1xw0v_1[data-show-on-focus=true]:not(:focus){border:0;clip-path:inset(50%);height:1px;width:1px;margin:-1px;padding:0;overflow:hidden;position:absolute;white-space:nowrap;overflow-wrap:normal}._loader_19l09_1{display:flex;justify-content:center;width:var(--size);height:var(--size)}._text_19l09_8{color:inherit}._content_19l09_12{display:grid;grid-template-columns:repeat(3,var(--spanSize));grid-gap:var(--gapSize);gap:var(--gapSize);align-items:center;justify-content:center;transform:skew(22deg)}@keyframes _loaderSpan_19l09_1{0%{transform:scaleY(0);opacity:.5;transform-origin:top}40%{transform:scaleY(1);opacity:1;transform-origin:top}60%{transform:scaleY(1);opacity:1;transform-origin:bottom}to{transform:scaleY(0);opacity:.5;transform-origin:bottom}}._span_19l09_47{height:60%;background:currentColor;animation:_loaderSpan_19l09_1 1s var(--bezierFastoutSlowin) infinite;transform:scaleY(0);transform-origin:top left}._span_19l09_47:nth-child(2){animation-delay:.1s}._span_19l09_47:nth-child(3){animation-delay:.2s}._icon_13804_1{fill:currentColor}._container_19hr9_1{--inset: 4px}._options_19hr9_5{position:relative;display:flex;padding:var(--inset)}._options_19hr9_5:before{content:"";background-color:rgb(var(--rgbText) / .05);position:absolute;top:0;right:0;bottom:0;left:0;clip-path:polygon(0 0,100% 0,100% calc(100% - 10px),calc(100% - 10px) 100%,0 100%)}._button_19hr9_25{position:relative;display:flex;align-items:center;justify-content:center;background-color:transparent;color:var(--colorTextLight);transition-property:color,background;transition-duration:var(--durationM);transition-timing-function:ease;border:0;padding:0 24px;height:56px;font-size:inherit;font-family:inherit;font-weight:var(--fontWeightMedium);cursor:pointer}._button_19hr9_25[aria-checked=true]{color:var(--colorTextBody)}._button_19hr9_25:before{--inset: 12px;content:"";position:absolute;top:var(--inset);bottom:var(--inset);left:0;width:1px;background-color:rgb(var(--rgbText) / .1);transition:opacity var(--durationM) var(--bezierFastoutSlowin);opacity:0}._button_19hr9_25:not([aria-checked=true])+._button_19hr9_25:not([aria-checked=true]):before{opacity:1}._indicator_19hr9_66{position:absolute;top:var(--inset);bottom:var(--inset);left:0;filter:drop-shadow(0 6px 12px rgb(var(--rgbBlack) / .2));transform:translate3d(var(--left),0,0);width:var(--width)}@media(prefers-reduced-motion:no-preference){._indicator_19hr9_66{transition-property:width,transform;transition-duration:var(--durationM);transition-timing-function:var(--bezierFastoutSlowin)}}._indicator_19hr9_66:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background-color:rgb(var(--rgbBackgroundLight));filter:brightness(2.2);clip-path:polygon(0 0,100% 0,100% 100%,100% 100%,0 100%)}@media(prefers-reduced-motion:no-preference){._indicator_19hr9_66:before{transition:clip-path var(--durationM) var(--bezierFastoutSlowin)}}._indicator_19hr9_66[data-last=true]:before{clip-path:polygon(0 0,100% 0,100% calc(100% - 8px),calc(100% - 8px) 100%,0 100%)}._container_1a9g9_1{--inputFontSize: 1rem ;--inputFocusColor: rgb(var(--rgbPrimary));--inputUnderlineColor: rgb(var(--rgbText) / .2);position:relative;display:flex;flex-direction:column}._container_1a9g9_1[data-error=true]{--inputUnderlineColor: rgb(var(--rgbError))}._content_1a9g9_15{position:relative;display:flex}._input_1a9g9_20{display:block;color:var(--colorTextBody);box-shadow:inset 0 -2px 0 0 var(--inputUnderlineColor);transition:background-color 5000s linear 0s;width:100%;font-size:var(--inputFontSize);line-height:var(--lineHeightBody);padding:var(--spaceL) 0 var(--spaceM);overflow-x:hidden;outline:none}._input_1a9g9_20::-moz-placeholder{color:rgb(var(--rgbText) / .4)}._input_1a9g9_20::placeholder{color:rgb(var(--rgbText) / .4)}._input_1a9g9_20:-internal-autofill-selected{-webkit-text-fill-color:var(--colorTextBody);box-shadow:0 0 0 1000px rgb(var(--rgbText) / .1) inset}._input_1a9g9_20:-webkit-autofill{-webkit-text-fill-color:var(--colorTextBody);box-shadow:0 0 0 1000px rgb(var(--rgbText) / .1) inset}._input_1a9g9_20::-webkit-contacts-auto-fill-button:hover{background-color:rgb(var(--rgbPrimary))}@media(prefers-reduced-motion:reduce){#_root_1a9g9_1 ._input_1a9g9_20{transition:background-color 5000s linear 0s}}._underline_1a9g9_60{background:var(--inputFocusColor);transform:scale3d(0,1,1);width:100%;height:2px;position:absolute;bottom:0;transform-origin:left}@media(prefers-reduced-motion:no-preference){._underline_1a9g9_60{transition:transform var(--durationM) var(--bezierFastoutSlowin)}}._underline_1a9g9_60[data-focused=true]{transform:scaleZ(1)}._label_1a9g9_32{color:rgb(var(--rgbText) / .8);position:absolute;top:var(--spaceL);left:0;display:block;cursor:text;transform-origin:top left;transition:color var(--durationM) ease}@media(prefers-reduced-motion:no-preference){._label_1a9g9_32{transition:transform var(--durationM) var(--bezierFastoutSlowin),color var(--durationM) ease}}._label_1a9g9_32[data-filled=true],._label_1a9g9_32[data-focused=true],._label_1a9g9_32[data-placeholder=true]{color:rgb(var(--rgbText) / .54);transform:scale(.8) translateY(calc(var(--spaceL) * -1))}._container_1a9g9_1[data-multiline=true] ._content_1a9g9_15{flex-direction:column}._container_1a9g9_1[data-multiline=true] ._label_1a9g9_32{position:static;transform:none;transform-origin:left top;margin-bottom:var(--spaceXS);color:rgb(var(--rgbText) / .54);font-size:calc(var(--inputFontSize) * .8);cursor:default}._container_1a9g9_1[data-multiline=true] ._input_1a9g9_20{padding-top:0}._container_1a9g9_1[data-multiline=true] ._input_1a9g9_20:-moz-placeholder{white-space:nowrap;text-overflow:ellipsis}._container_1a9g9_1[data-multiline=true] ._input_1a9g9_20:placeholder-shown{white-space:nowrap;text-overflow:ellipsis}._error_1a9g9_135{transition-property:opacity;transition-duration:var(--durationM);transition-timing-function:var(--bezierFastoutSlowin);height:var(--height);opacity:0}@media(prefers-reduced-motion:no-preference){._error_1a9g9_135{transition-property:height,opacity}}._error_1a9g9_135[data-visible=true]{opacity:1}._errorMessage_1a9g9_151{display:grid;grid-template-columns:auto 1fr;align-items:center;grid-gap:var(--spaceXS);gap:var(--spaceXS);padding-top:var(--spaceS);color:rgb(var(--rgbError))}._textarea_vm3vl_1{resize:var(--resize);overflow-y:auto}._link_o3rjr_1{--lineStrokeWidth: 2px;--linkColor: var(--rgbPrimary);--lineOpacity: .3;--filledLineGradient: linear-gradient(rgb(var(--linkColor)), rgb(var(--linkColor)));--unfilledLineGradient: linear-gradient( rgb(var(--linkColor) / var(--lineOpacity)), rgb(var(--linkColor) / var(--lineOpacity)) );cursor:pointer;display:inline;color:rgb(var(--linkColor));background:var(--filledLineGradient) no-repeat 100% 100% / 0 var(--lineStrokeWidth),var(--unfilledLineGradient) no-repeat 0 100% / 100% var(--lineStrokeWidth);padding-bottom:var(--lineStrokeWidth)}._link_o3rjr_1:hover,._link_o3rjr_1:focus{background:var(--filledLineGradient) no-repeat 0 100% / 100% var(--lineStrokeWidth),var(--unfilledLineGradient) no-repeat 0 100% / 100% var(--lineStrokeWidth)}@media(prefers-reduced-motion:no-preference){._link_o3rjr_1{transition-duration:var(--durationM);transition-timing-function:var(--bezierFastoutSlowin);transition-property:background-size}}._link_o3rjr_1[data-secondary=true]{--linkColor: var(--rgbText)}._button_1yrod_1{--buttonSize: 3.5rem ;--buttonFontSize: 1.125rem ;--buttonFocusWidth: 4px;--buttonPadding: 0 var(--spaceL);--buttonTextColor: rgb(var(--rgbBackground));--buttonTextOpacity: 1;--buttonLoaderDelay: 0s;height:var(--buttonSize);padding:var(--buttonPadding);cursor:pointer;transition-property:opacity,color,background;transition-duration:var(--durationS);transition-timing-function:var(--bezierFastoutSlowin);display:inline-flex;align-items:center;color:var(--buttonTextColor);position:relative;isolation:isolate}._button_1yrod_1:active{transition-duration:calc(var(--durationXS) / 2)}._button_1yrod_1:after{content:"";transition-property:opacity,color,background;transition-duration:var(--durationM);transition-timing-function:var(--bezierFastoutSlowin);background:rgb(var(--rgbPrimary));position:absolute;top:0;right:0;bottom:0;left:0;z-index:-1;clip-path:polygon(0 0,100% 0,100% calc(100% - 8px),calc(100% - 8px) 100%,0 100%)}@media(prefers-reduced-motion:no-preference){._button_1yrod_1{transition-property:transform,opacity,color,background}._button_1yrod_1:hover{transform:scale(1.05)}._button_1yrod_1:active{transform:scale(1)}}._button_1yrod_1[data-secondary=true]{--buttonSpace: 10px;--buttonTextColor: rgb(var(--rgbPrimary));background:none;padding-left:var(--buttonSpace);padding-right:var(--buttonSpace);position:relative;left:calc(var(--buttonSpace) * -1);height:2rem}._button_1yrod_1[data-secondary=true]:after{content:"";height:2rem;position:absolute;top:0;right:0;bottom:0;left:0;background-color:rgb(var(--rgbPrimary) / .2);transform:scale3d(0,1,1);transform-origin:right;clip-path:none}._button_1yrod_1[data-secondary=true]:hover{transform:none;background:transparent}._button_1yrod_1[data-secondary=true]:hover:after{transform:scaleZ(1);transform-origin:left}._button_1yrod_1[data-secondary=true][data-icon=chevronRight]{padding-left:calc(var(--buttonSpace) / 2)}@media(prefers-reduced-motion:no-preference){._button_1yrod_1[data-secondary=true]:after{transition:transform var(--durationM) var(--bezierFastoutSlowin)}}._button_1yrod_1[data-loading=true]{--buttonTextOpacity: 0}._button_1yrod_1[data-icon-only=true]{--buttonPadding: 0;--buttonTextColor: var(--colorTextBody);width:var(--buttonSize);align-items:center;justify-content:center;padding:0}._button_1yrod_1[data-icon-only=true]:hover{color:var(--colorTextTitle)}._button_1yrod_1[data-icon-only=true]:after{background:rgb(var(--rgbText) / 0)}._button_1yrod_1[disabled]{pointer-events:none;opacity:.4}._text_1yrod_128{font-size:var(--buttonFontSize);font-weight:var(--fontWeightMedium);opacity:var(--buttonTextOpacity);position:relative;line-height:1;flex:1 1 auto;display:flex;align-items:center;justify-content:center;transition:opacity var(--durationM) var(--bezierFastoutSlowin)}._loader_1yrod_141{position:absolute;left:50%;transform:translate(-50%);color:rgb(var(--rgbBackground));opacity:0;transition:opacity var(--durationM) ease var(--buttonLoaderDelay)}._loader_1yrod_141[data-visible=true]{opacity:1}._icon_1yrod_154{transition-property:opacity,fill;transition-duration:var(--durationS);transition-timing-function:var(--bezierFastoutSlowin)}@media(prefers-reduced-motion:no-preference){._icon_1yrod_154{transition-property:transform,opacity,fill}}._icon_1yrod_154[data-start=true]{margin-right:var(--spaceS)}._icon_1yrod_154[data-end=true]{margin-left:var(--spaceS)}@media(prefers-reduced-motion:no-preference){._button_1yrod_1:hover ._icon_1yrod_154[data-shift=true]{transform:translate3d(var(--spaceXS),0,0)}}._button_1yrod_1[data-loading=true] ._icon_1yrod_154{opacity:0}._breadcrumbs_1k287_3{position:relative;z-index:1;width:100%;margin-bottom:var(--spaceL)}@media(max-width:696px){._breadcrumbs_1k287_3{margin-bottom:var(--spaceM)}}._list_1k287_16{display:flex;align-items:center;flex-wrap:wrap;list-style:none;margin:0;padding:0;gap:var(--spaceXS)}._item_1k287_26{display:flex;align-items:center;gap:var(--spaceXS);font-size:var(--fontSizeBodyS)}._link_1k287_33{color:rgb(var(--rgbText) / .6);text-decoration:none;transition:color var(--durationS) var(--bezierFastoutSlowin);white-space:nowrap}._link_1k287_33:hover{color:rgb(var(--rgbPrimary))}._separator_1k287_44{color:rgb(var(--rgbText) / .4);width:.875rem;height:.875rem;flex-shrink:0}._current_1k287_51{color:rgb(var(--rgbText));white-space:nowrap}._text_11knq_1:after{content:"_";visibility:hidden}._glyph_11knq_8{opacity:.8;font-weight:var(--fontWeightRegular);font-family:var(--devanagariFontStack);line-height:0}._value_11knq_15{opacity:1}._image_y6je9_1{position:relative;transform:translateZ(0);display:grid;grid-template-columns:100%;isolation:isolate}._image_y6je9_1[data-raised=true]{box-shadow:0 50px 100px -20px rgb(var(--rgbBlack) / .25),0 30px 60px -30px rgb(var(--rgbBlack) / .3)}._image_y6je9_1[data-reveal=true]{--revealDuration: 1.8s;transition:box-shadow var(--durationL) ease calc(var(--revealDuration) / 2)}._image_y6je9_1[data-reveal=true]:not([data-visible=true]){box-shadow:none}._image_y6je9_1[data-reveal=true]:before{content:"";background-color:rgb(var(--rgbAccent));position:absolute;top:0;right:0;bottom:0;left:0;transform:scale3d(0,1,1);transform-origin:left;will-change:transform;z-index:var(--zIndex2)}@media(prefers-reduced-motion:no-preference){._image_y6je9_1[data-reveal=true][data-visible=true]:before{animation:reveal var(--revealDuration) var(--bezierFastoutSlowin) var(--delay)}}._container_y6je9_42{position:relative;transform:none;display:grid;grid-template-columns:100%}._elementWrapper_y6je9_49{opacity:0;transition:none;transform:none;position:relative;display:grid;grid-template-columns:100%}._elementWrapper_y6je9_49[data-reveal=true]{opacity:0;transition:opacity var(--durationM) ease var(--delay)}@media(prefers-reduced-motion:reduce){._elementWrapper_y6je9_49[data-reveal=true]{transition-delay:calc(var(--delay) - 1s)}}._elementWrapper_y6je9_49[data-visible=true]{opacity:1}._placeholder_y6je9_71{width:100%;height:auto;transition:opacity var(--durationM) ease var(--delay);pointer-events:none;position:relative;z-index:var(--zIndex1);opacity:1;grid-column:1;grid-row:1}._placeholder_y6je9_71[data-loaded=true]{opacity:0}._element_y6je9_49{width:100%;height:auto;opacity:0;grid-column:1;grid-row:1;image-rendering:-webkit-optimize-contrast}._element_y6je9_49[data-loaded=true]{opacity:1}._button_y6je9_101{opacity:0;position:absolute;top:var(--spaceM);left:var(--spaceM);height:32px;color:rgb(var(--rgbWhite));padding:0 8px 0 2px}._button_y6je9_101:after{background-color:rgb(var(--rgbBlack) / .8)}._elementWrapper_y6je9_49:hover ._button_y6je9_101,._button_y6je9_101:focus{opacity:1}._wordmark_w8y5a_1{fill:var(--colorTextTitle);transition:fill var(--durationL) ease}._highlight_w8y5a_6{fill:rgb(var(--rgbAccent));opacity:0;transform:scale3d(1,0,1);transform-origin:top;transition:opacity .1s ease var(--durationM)}@media(prefers-reduced-motion:no-preference){._highlight_w8y5a_6{transition:transform var(--durationM) var(--bezierFastoutSlowin),opacity .1s ease var(--durationM)}}:is(a:focus,a:hover,._wordmark_w8y5a_1:hover) ._highlight_w8y5a_6{opacity:1;transform:scaleZ(1);transform-origin:bottom;transition:opacity .1s ease}@media(prefers-reduced-motion:no-preference){:is(a:focus,a:hover,._wordmark_w8y5a_1:hover) ._highlight_w8y5a_6{transition:transform var(--durationM) var(--bezierFastoutSlowin),opacity .1s ease}}
@@ -0,0 +1,48 @@
1
+ "use client";
2
+ import { Mesh as d, TextureLoader as f, Cache as m } from "three";
3
+ import { DRACOLoader as L, GLTFLoader as p } from "three-stdlib";
4
+ m.enabled = !0;
5
+ const i = /* @__PURE__ */ new Map();
6
+ function y(r = "/draco/") {
7
+ let e = i.get(r);
8
+ if (!e) {
9
+ const o = new L();
10
+ o.setDecoderPath(r), e = new p(), e.setDRACOLoader(o), i.set(r, e);
11
+ }
12
+ return e;
13
+ }
14
+ const v = new f(), w = (r) => {
15
+ r == null || r.traverse((e) => {
16
+ if (e instanceof d)
17
+ if (e.geometry.dispose(), Array.isArray(e.material))
18
+ for (const o of e.material)
19
+ c(o);
20
+ else
21
+ c(e.material);
22
+ });
23
+ }, c = (r) => {
24
+ var o, t, s;
25
+ r.dispose();
26
+ const e = r;
27
+ for (const l of Object.keys(e)) {
28
+ const a = e[l];
29
+ if (a && typeof a == "object" && "minFilter" in a) {
30
+ const n = a;
31
+ n.dispose(), (s = (t = (o = n.source) == null ? void 0 : o.data) == null ? void 0 : t.close) == null || s.call(t);
32
+ }
33
+ }
34
+ }, x = (r) => {
35
+ r.dispose();
36
+ }, A = (r) => {
37
+ var e;
38
+ for (const o of r)
39
+ (e = o.parent) == null || e.remove(o);
40
+ };
41
+ export {
42
+ x as a,
43
+ w as c,
44
+ y as g,
45
+ A as r,
46
+ v as t
47
+ };
48
+ //# sourceMappingURL=three-CWsiEOQZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"three-CWsiEOQZ.js","sources":["../src/utils/three.ts"],"sourcesContent":["import {\n Cache,\n TextureLoader,\n Mesh,\n Material,\n Object3D,\n Light,\n WebGLRenderer,\n Scene,\n} from 'three';\nimport { DRACOLoader, GLTFLoader } from 'three-stdlib';\n\n// Enable caching for all loaders\nCache.enabled = true;\n\nconst gltfLoaders = new Map<string, GLTFLoader>();\n\n/**\n * GLTF model loader configured with the draco decoder. Constructed lazily on\n * first use rather than at module scope, so importing this module has no\n * side effect. Cached per decoder path.\n */\nexport function getModelLoader(decoderPath = '/draco/'): GLTFLoader {\n let gltfLoader = gltfLoaders.get(decoderPath);\n\n if (!gltfLoader) {\n const dracoLoader = new DRACOLoader();\n dracoLoader.setDecoderPath(decoderPath);\n gltfLoader = new GLTFLoader();\n gltfLoader.setDRACOLoader(dracoLoader);\n gltfLoaders.set(decoderPath, gltfLoader);\n }\n\n return gltfLoader;\n}\n\nexport const textureLoader: TextureLoader = new TextureLoader();\n\n/**\n * Clean up a scene's materials and geometry\n */\nexport const cleanScene = (scene: Scene): void => {\n scene?.traverse(object => {\n if (!(object instanceof Mesh)) return;\n\n object.geometry.dispose();\n\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n cleanMaterial(material);\n }\n } else {\n cleanMaterial(object.material);\n }\n });\n};\n\n/**\n * Clean up and dispose of a material\n */\nexport const cleanMaterial = (material: Material): void => {\n material.dispose();\n\n const record = material as unknown as Record<string, unknown>;\n\n for (const key of Object.keys(record)) {\n const value = record[key];\n if (\n value &&\n typeof value === 'object' &&\n 'minFilter' in (value as Record<string, unknown>)\n ) {\n const texture = value as { dispose: () => void; source?: { data?: { close?: () => void } } };\n texture.dispose();\n\n // Close GLTF bitmap textures\n texture.source?.data?.close?.();\n }\n }\n};\n\n/**\n * Clean up and dispose of a renderer\n */\nexport const cleanRenderer = (renderer: WebGLRenderer): void => {\n renderer.dispose();\n};\n\n/**\n * Clean up lights by removing them from their parent\n */\nexport const removeLights = (lights: Light[]): void => {\n for (const light of lights) {\n light.parent?.remove(light);\n }\n};\n\n/**\n * Get child by name\n */\nexport const getChild = (name: string, object: Object3D): Object3D | undefined => {\n let node: Object3D | undefined;\n\n object.traverse(child => {\n if (child.name === name) {\n node = child;\n }\n });\n\n return node;\n};\n"],"names":["Cache","gltfLoaders","getModelLoader","decoderPath","gltfLoader","dracoLoader","DRACOLoader","GLTFLoader","textureLoader","TextureLoader","cleanScene","scene","object","Mesh","material","cleanMaterial","record","key","value","texture","_c","_b","_a","cleanRenderer","renderer","removeLights","lights","light"],"mappings":";;;AAaAA,EAAM,UAAU;AAEhB,MAAMC,wBAAkB,IAAA;AAOjB,SAASC,EAAeC,IAAc,WAAuB;AAClE,MAAIC,IAAaH,EAAY,IAAIE,CAAW;AAE5C,MAAI,CAACC,GAAY;AACf,UAAMC,IAAc,IAAIC,EAAA;AACxB,IAAAD,EAAY,eAAeF,CAAW,GACtCC,IAAa,IAAIG,EAAA,GACjBH,EAAW,eAAeC,CAAW,GACrCJ,EAAY,IAAIE,GAAaC,CAAU;AAAA,EACzC;AAEA,SAAOA;AACT;AAEO,MAAMI,IAA+B,IAAIC,EAAA,GAKnCC,IAAa,CAACC,MAAuB;AAChD,EAAAA,KAAA,QAAAA,EAAO,SAAS,CAAAC,MAAU;AACxB,QAAMA,aAAkBC;AAIxB,UAFAD,EAAO,SAAS,QAAA,GAEZ,MAAM,QAAQA,EAAO,QAAQ;AAC/B,mBAAWE,KAAYF,EAAO;AAC5B,UAAAG,EAAcD,CAAQ;AAAA;AAGxB,QAAAC,EAAcH,EAAO,QAAQ;AAAA,EAEjC;AACF,GAKaG,IAAgB,CAACD,MAA6B;;AACzD,EAAAA,EAAS,QAAA;AAET,QAAME,IAASF;AAEf,aAAWG,KAAO,OAAO,KAAKD,CAAM,GAAG;AACrC,UAAME,IAAQF,EAAOC,CAAG;AACxB,QACEC,KACA,OAAOA,KAAU,YACjB,eAAgBA,GAChB;AACA,YAAMC,IAAUD;AAChB,MAAAC,EAAQ,QAAA,IAGRC,KAAAC,KAAAC,IAAAH,EAAQ,WAAR,gBAAAG,EAAgB,SAAhB,gBAAAD,EAAsB,UAAtB,QAAAD,EAAA,KAAAC;AAAA,IACF;AAAA,EACF;AACF,GAKaE,IAAgB,CAACC,MAAkC;AAC9D,EAAAA,EAAS,QAAA;AACX,GAKaC,IAAe,CAACC,MAA0B;;AACrD,aAAWC,KAASD;AAClB,KAAAJ,IAAAK,EAAM,WAAN,QAAAL,EAAc,OAAOK;AAEzB;"}
@@ -0,0 +1,2 @@
1
+ "use client";"use strict";const s=require("three"),c=require("three-stdlib");s.Cache.enabled=!0;const d=new Map;function u(r="/draco/"){let e=d.get(r);if(!e){const t=new c.DRACOLoader;t.setDecoderPath(r),e=new c.GLTFLoader,e.setDRACOLoader(t),d.set(r,e)}return e}const L=new s.TextureLoader,g=r=>{r==null||r.traverse(e=>{if(e instanceof s.Mesh)if(e.geometry.dispose(),Array.isArray(e.material))for(const t of e.material)l(t);else l(e.material)})},l=r=>{var t,o,n;r.dispose();const e=r;for(const f of Object.keys(e)){const a=e[f];if(a&&typeof a=="object"&&"minFilter"in a){const i=a;i.dispose(),(n=(o=(t=i.source)==null?void 0:t.data)==null?void 0:o.close)==null||n.call(o)}}},m=r=>{r.dispose()},p=r=>{var e;for(const t of r)(e=t.parent)==null||e.remove(t)};exports.cleanRenderer=m;exports.cleanScene=g;exports.getModelLoader=u;exports.removeLights=p;exports.textureLoader=L;
2
+ //# sourceMappingURL=three-aeLbW1yA.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"three-aeLbW1yA.cjs","sources":["../src/utils/three.ts"],"sourcesContent":["import {\n Cache,\n TextureLoader,\n Mesh,\n Material,\n Object3D,\n Light,\n WebGLRenderer,\n Scene,\n} from 'three';\nimport { DRACOLoader, GLTFLoader } from 'three-stdlib';\n\n// Enable caching for all loaders\nCache.enabled = true;\n\nconst gltfLoaders = new Map<string, GLTFLoader>();\n\n/**\n * GLTF model loader configured with the draco decoder. Constructed lazily on\n * first use rather than at module scope, so importing this module has no\n * side effect. Cached per decoder path.\n */\nexport function getModelLoader(decoderPath = '/draco/'): GLTFLoader {\n let gltfLoader = gltfLoaders.get(decoderPath);\n\n if (!gltfLoader) {\n const dracoLoader = new DRACOLoader();\n dracoLoader.setDecoderPath(decoderPath);\n gltfLoader = new GLTFLoader();\n gltfLoader.setDRACOLoader(dracoLoader);\n gltfLoaders.set(decoderPath, gltfLoader);\n }\n\n return gltfLoader;\n}\n\nexport const textureLoader: TextureLoader = new TextureLoader();\n\n/**\n * Clean up a scene's materials and geometry\n */\nexport const cleanScene = (scene: Scene): void => {\n scene?.traverse(object => {\n if (!(object instanceof Mesh)) return;\n\n object.geometry.dispose();\n\n if (Array.isArray(object.material)) {\n for (const material of object.material) {\n cleanMaterial(material);\n }\n } else {\n cleanMaterial(object.material);\n }\n });\n};\n\n/**\n * Clean up and dispose of a material\n */\nexport const cleanMaterial = (material: Material): void => {\n material.dispose();\n\n const record = material as unknown as Record<string, unknown>;\n\n for (const key of Object.keys(record)) {\n const value = record[key];\n if (\n value &&\n typeof value === 'object' &&\n 'minFilter' in (value as Record<string, unknown>)\n ) {\n const texture = value as { dispose: () => void; source?: { data?: { close?: () => void } } };\n texture.dispose();\n\n // Close GLTF bitmap textures\n texture.source?.data?.close?.();\n }\n }\n};\n\n/**\n * Clean up and dispose of a renderer\n */\nexport const cleanRenderer = (renderer: WebGLRenderer): void => {\n renderer.dispose();\n};\n\n/**\n * Clean up lights by removing them from their parent\n */\nexport const removeLights = (lights: Light[]): void => {\n for (const light of lights) {\n light.parent?.remove(light);\n }\n};\n\n/**\n * Get child by name\n */\nexport const getChild = (name: string, object: Object3D): Object3D | undefined => {\n let node: Object3D | undefined;\n\n object.traverse(child => {\n if (child.name === name) {\n node = child;\n }\n });\n\n return node;\n};\n"],"names":["Cache","gltfLoaders","getModelLoader","decoderPath","gltfLoader","dracoLoader","DRACOLoader","GLTFLoader","textureLoader","TextureLoader","cleanScene","scene","object","Mesh","material","cleanMaterial","record","key","value","texture","_c","_b","_a","cleanRenderer","renderer","removeLights","lights","light"],"mappings":"6EAaAA,EAAAA,MAAM,QAAU,GAEhB,MAAMC,MAAkB,IAOjB,SAASC,EAAeC,EAAc,UAAuB,CAClE,IAAIC,EAAaH,EAAY,IAAIE,CAAW,EAE5C,GAAI,CAACC,EAAY,CACf,MAAMC,EAAc,IAAIC,cACxBD,EAAY,eAAeF,CAAW,EACtCC,EAAa,IAAIG,EAAAA,WACjBH,EAAW,eAAeC,CAAW,EACrCJ,EAAY,IAAIE,EAAaC,CAAU,CACzC,CAEA,OAAOA,CACT,CAEO,MAAMI,EAA+B,IAAIC,EAAAA,cAKnCC,EAAcC,GAAuB,CAChDA,GAAA,MAAAA,EAAO,SAASC,GAAU,CACxB,GAAMA,aAAkBC,EAAAA,KAIxB,GAFAD,EAAO,SAAS,QAAA,EAEZ,MAAM,QAAQA,EAAO,QAAQ,EAC/B,UAAWE,KAAYF,EAAO,SAC5BG,EAAcD,CAAQ,OAGxBC,EAAcH,EAAO,QAAQ,CAEjC,EACF,EAKaG,EAAiBD,GAA6B,WACzDA,EAAS,QAAA,EAET,MAAME,EAASF,EAEf,UAAWG,KAAO,OAAO,KAAKD,CAAM,EAAG,CACrC,MAAME,EAAQF,EAAOC,CAAG,EACxB,GACEC,GACA,OAAOA,GAAU,UACjB,cAAgBA,EAChB,CACA,MAAMC,EAAUD,EAChBC,EAAQ,QAAA,GAGRC,GAAAC,GAAAC,EAAAH,EAAQ,SAAR,YAAAG,EAAgB,OAAhB,YAAAD,EAAsB,QAAtB,MAAAD,EAAA,KAAAC,EACF,CACF,CACF,EAKaE,EAAiBC,GAAkC,CAC9DA,EAAS,QAAA,CACX,EAKaC,EAAgBC,GAA0B,OACrD,UAAWC,KAASD,GAClBJ,EAAAK,EAAM,SAAN,MAAAL,EAAc,OAAOK,EAEzB"}
@@ -0,0 +1 @@
1
+ :root { --rgbBlack: 0 0 0; --rgbWhite: 255 255 255; --bezierFastoutSlowin: cubic-bezier(0.4, 0.0, 0.2, 1); --durationXS: 200ms; --durationS: 300ms; --durationM: 400ms; --durationL: 600ms; --durationXL: 800ms; --systemFontStack: system-ui, -apple-system, BlinkMacSystemFont, San Francisco, Roboto, Segoe UI, Ubuntu, Helvetica Neue, sans-serif; --fontStack: var(--brandFontStack, var(--systemFontStack)); --monoFontStack: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace; --devanagariFontStack: Kohinoor Devanagari, Devanagari Sangam MN, Nirmala UI, Noto Sans Devanagari, sans-serif; --fontWeightRegular: 400; --fontWeightMedium: 500; --fontWeightBold: 700; --fontSizeH0: 8.75rem; --fontSizeH1: 6.25rem; --fontSizeH2: 3.625rem; --fontSizeH3: 2.375rem; --fontSizeH4: 1.75rem; --fontSizeH5: 1.5rem; --fontSizeBodyXL: 1.375rem; --fontSizeBodyL: 1.25rem; --fontSizeBodyM: 1.125rem; --fontSizeBodyS: 1rem; --fontSizeBodyXS: 0.875rem; --lineHeightTitle: 1.1; --lineHeightBody: 1.6; --maxWidthS: 540px; --maxWidthM: 720px; --maxWidthL: 1096px; --maxWidthXL: 1680px; --spaceOuter: 64px; --spaceXS: 4px; --spaceS: 8px; --spaceM: 16px; --spaceL: 24px; --spaceXL: 32px; --space2XL: 48px; --space3XL: 64px; --space4XL: 96px; --space5XL: 128px; --zIndex0: 0; --zIndex1: 4; --zIndex2: 8; --zIndex3: 16; --zIndex4: 32; --zIndex5: 64; } @media (max-width: 2080px) { :root { --fontSizeH0: 7.5rem; --fontSizeH1: 5rem; } } @media (max-width: 1680px) { :root { --maxWidthS: 480px; --maxWidthM: 640px; --maxWidthL: 1000px; --maxWidthXL: 1100px; --spaceOuter: 48px; --fontSizeH0: 6.25rem; --fontSizeH1: 4.375rem; --fontSizeH2: 3.125rem; --fontSizeH3: 2.25rem; --fontSizeH4: 1.625rem; --fontSizeH5: 1.375rem; } } @media (max-width: 1040px) { :root { --fontSizeH0: 5rem; --fontSizeH1: 3.75rem; --fontSizeH2: 3rem; --fontSizeH3: 2rem; --fontSizeH4: 1.5rem; --fontSizeH5: 1.25rem; } } @media (max-width: 696px) { :root { --spaceOuter: 24px; --fontSizeH0: 3.5rem; --fontSizeH1: 2.5rem; --fontSizeH2: 2.125rem; --fontSizeH3: 1.75rem; --fontSizeH4: 1.375rem; --fontSizeH5: 1.125rem; --fontSizeBodyL: 1.0625rem; --fontSizeBodyM: 1rem; --fontSizeBodyS: 0.875rem; } } @media (max-width: 400px) { :root { --spaceOuter: 16px; --fontSizeH0: 2.625rem; --fontSizeH1: 2.375rem; --fontSizeH2: 1.75rem; --fontSizeH3: 1.5rem; --fontSizeH4: 1.25rem; } } [data-theme='dark'] { --rgbBackground: 17 17 17; --rgbBackgroundLight: 26 26 26; --rgbPrimary: 251 146 60; --rgbAccent: 251 146 60; --rgbText: 255 255 255; --rgbError: 255 55 102; --colorTextName: 246 240 228; --colorTextTitle: rgb(var(--rgbText) / 1); --colorTextBody: rgb(var(--rgbText) / 0.8); --colorTextLight: rgb(var(--rgbText) / 0.6); } [data-theme='light'] { --rgbBackground: 242 242 242; --rgbBackgroundLight: 255 255 255; --rgbPrimary: 168 85 8; --rgbAccent: 255 138 45; --rgbText: 0 0 0; --rgbError: 255 0 60; --colorTextName: 28 24 20; --colorTextTitle: rgb(var(--rgbText) / 1); --colorTextBody: rgb(var(--rgbText) / 0.8); --colorTextLight: rgb(var(--rgbText) / 0.6); }
@@ -0,0 +1 @@
1
+ export declare function delay(ms: number): Promise<void>;
@@ -0,0 +1,31 @@
1
+ interface SrcSetItem {
2
+ src: string;
3
+ width: number;
4
+ }
5
+ type SrcSet = string | SrcSetItem[];
6
+ /**
7
+ * Use the browser's image loading to load an image and
8
+ * grab the `src` it chooses from a `srcSet`
9
+ */
10
+ export declare function loadImageFromSrcSet({ src, srcSet, sizes, }: {
11
+ src?: string;
12
+ srcSet?: SrcSet;
13
+ sizes?: string;
14
+ }): Promise<string>;
15
+ /**
16
+ * Convert a `srcSet` array to a plain old `srcSet` string
17
+ */
18
+ export declare function srcSetToString(srcSet?: SrcSet): string;
19
+ /**
20
+ * Generates a transparent png of a given width and height
21
+ */
22
+ export declare function generateImage(width?: number, height?: number): Promise<string>;
23
+ /**
24
+ * Use native html image `srcSet` resolution for non-html images
25
+ */
26
+ export declare function resolveSrcFromSrcSet({ srcSet, sizes, }: {
27
+ srcSet?: SrcSet;
28
+ sizes?: string;
29
+ [key: string]: unknown;
30
+ }): Promise<string>;
31
+ export {};
@@ -0,0 +1,29 @@
1
+ import { TextureLoader, Material, Object3D, Light, WebGLRenderer, Scene } from 'three';
2
+ import { GLTFLoader } from 'three-stdlib';
3
+ /**
4
+ * GLTF model loader configured with the draco decoder. Constructed lazily on
5
+ * first use rather than at module scope, so importing this module has no
6
+ * side effect. Cached per decoder path.
7
+ */
8
+ export declare function getModelLoader(decoderPath?: string): GLTFLoader;
9
+ export declare const textureLoader: TextureLoader;
10
+ /**
11
+ * Clean up a scene's materials and geometry
12
+ */
13
+ export declare const cleanScene: (scene: Scene) => void;
14
+ /**
15
+ * Clean up and dispose of a material
16
+ */
17
+ export declare const cleanMaterial: (material: Material) => void;
18
+ /**
19
+ * Clean up and dispose of a renderer
20
+ */
21
+ export declare const cleanRenderer: (renderer: WebGLRenderer) => void;
22
+ /**
23
+ * Clean up lights by removing them from their parent
24
+ */
25
+ export declare const removeLights: (lights: Light[]) => void;
26
+ /**
27
+ * Get child by name
28
+ */
29
+ export declare const getChild: (name: string, object: Object3D) => Object3D | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "refract-ui",
3
- "version": "0.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Themeable React component library — primitives, form controls, and Three.js device/carousel components.",
5
5
  "homepage": "https://storybook.parammehta.com",
6
6
  "repository": "https://github.com/parammehta/refract-ui.git",
@@ -68,7 +68,7 @@
68
68
  "@types/three": "^0.185.3",
69
69
  "@vitejs/plugin-react": "^4.3.4",
70
70
  "eslint": "^9.39.5",
71
- "eslint-plugin-react-hooks": "^5.1.0",
71
+ "eslint-plugin-react-hooks": "^7.1.1",
72
72
  "eslint-plugin-storybook": "^10.5.5",
73
73
  "framer-motion": "^7.10.3",
74
74
  "fs-extra": "^10.1.0",
@@ -96,7 +96,7 @@
96
96
  "scripts": {
97
97
  "dev": "storybook dev -p 9009 -h localhost",
98
98
  "storybook": "storybook dev -p 9009 -h localhost",
99
- "build": "vite build && node scripts/copy-static-css.cjs",
99
+ "build": "vite build && node scripts/copy-static-assets.cjs && node scripts/build-tokens-css.cjs",
100
100
  "build:storybook": "storybook build -o build-storybook && node scripts/draco-storybook.cjs && node scripts/models-storybook.cjs",
101
101
  "lint": "eslint .",
102
102
  "stylelint": "stylelint \"src/**/*.css\"",