diff --git a/apps/frontend/package.json b/apps/frontend/package.json index fab485f..926798d 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -14,6 +14,7 @@ "@tanstack/router-devtools": "^1.52.5", "hono": "^4.5.11", "react": "^18.3.1", + "react-camera-pro": "^1.4.0", "react-dom": "^18.3.1", "tailwind-merge": "^2.5.2", "zod": "^3.23.8" diff --git a/apps/frontend/src/components/common/IconButton.tsx b/apps/frontend/src/components/common/IconButton.tsx new file mode 100644 index 0000000..9fa83af --- /dev/null +++ b/apps/frontend/src/components/common/IconButton.tsx @@ -0,0 +1,35 @@ +import type { Icon } from '@tabler/icons-react' +import type { FC, JSX } from 'react' +import { twMerge } from 'tailwind-merge' + +type IconButtonProps = { + icon: Icon + label?: string + iconPosition?: 'left' | 'right' + size?: number + iconClassName?: string +} & Omit + +export const IconButton: FC = ({ + label, + size, + icon: Icon, + iconPosition, + iconClassName, + ...props +}) => ( + +) diff --git a/apps/frontend/src/components/common/Modal.tsx b/apps/frontend/src/components/common/Modal.tsx new file mode 100644 index 0000000..c9fed5a --- /dev/null +++ b/apps/frontend/src/components/common/Modal.tsx @@ -0,0 +1,34 @@ +import { IconX } from '@tabler/icons-react' +import { type ReactNode, forwardRef } from 'react' +import { twJoin } from 'tailwind-merge' +import { IconButton } from './IconButton' + +type ModalProps = { + close: () => void + title?: string + displayContent?: boolean + children?: ReactNode +} + +export const Modal = forwardRef( + ({ close, title, children, displayContent = true }, ref) => ( + + {displayContent && ( + <> +
+

{title}

+ {/* biome-ignore lint/a11y/noPositiveTabindex: don't focus close button at fist time */} + +
+ {children} + + )} +
+ ), +) diff --git a/apps/frontend/src/hooks/useModal.tsx b/apps/frontend/src/hooks/useModal.tsx new file mode 100644 index 0000000..e26c890 --- /dev/null +++ b/apps/frontend/src/hooks/useModal.tsx @@ -0,0 +1,23 @@ +import { type FC, type ReactNode, useCallback, useEffect, useMemo, useRef } from 'react' +import { Modal as ModalComponent } from '../components/common/Modal' + +export const useModal = () => { + const modalRef = useRef(null) + + const open = useCallback(() => modalRef.current?.showModal(), []) + const close = useCallback(() => modalRef.current?.close(), []) + + const isOpen = useMemo(() => modalRef.current?.open, []) + + useEffect(() => { + if (isOpen) close() + }, [isOpen, close]) + + const Modal: FC<{ children: ReactNode; title: string }> = ({ children, title }) => ( + + {children} + + ) + + return { open, close, Modal, isOpen } +} diff --git a/apps/frontend/src/routes/_app/upload/.camera.tsx b/apps/frontend/src/routes/_app/upload/.camera.tsx new file mode 100644 index 0000000..f424951 --- /dev/null +++ b/apps/frontend/src/routes/_app/upload/.camera.tsx @@ -0,0 +1,85 @@ +import { IconCamera, IconCameraPlus, IconRotate, IconX } from '@tabler/icons-react' +import { type Dispatch, type FC, type SetStateAction, useCallback, useRef } from 'react' +import { Camera, type CameraType } from 'react-camera-pro' +import { twJoin } from 'tailwind-merge' +import { IconButton } from '../../../components/common/IconButton' +import { useModal } from '../../../hooks/useModal' +import { apiClient } from '../../../lib/apiClient' +import type { FoodImage } from '../../../types/FoodTypes' +import { imageDataToFile } from '../../../utils/imageDataToFile' + +type CameraButtonProps = { + setIsLoading: Dispatch> + setFoodImages: Dispatch> + setSelectedFoods: Dispatch> +} + +export const CameraButton: FC = ({ + setIsLoading, + setFoodImages, + setSelectedFoods, +}) => { + const { Modal, open, close } = useModal() + const cameraRef = useRef(null) + + const handlerClick = useCallback(async () => { + await navigator.mediaDevices.getUserMedia({ video: true }) + open() + }, [open]) + + const uploadFiles = useCallback( + async (file: File) => { + setIsLoading(true) + const res = await apiClient.upload.$post({ form: { file } }) + if (!res.ok) return setIsLoading(false) + + const { foods: newFoods } = await res.json() + + setFoodImages((prev) => [...prev, { file, foods: newFoods }]) + setSelectedFoods((prev) => [...prev, ...newFoods.filter((food) => !prev.includes(food))]) + + setIsLoading(false) + close() + }, + [close, setIsLoading, setFoodImages, setSelectedFoods], + ) + + const handleTakePhoto = useCallback(async () => { + const imageData = cameraRef.current?.takePhoto('imgData') + if (typeof imageData === 'string' || imageData === undefined) return + + const imageFile = imageDataToFile(imageData) + uploadFiles(imageFile) + }, [uploadFiles]) + + return ( + <> + + +
+ +
+
+ + cameraRef.current?.switchCamera()} + size={24} + className="order-1" + /> + close()} size={24} className="order-3" /> +
+
+ + ) +} diff --git a/apps/frontend/src/routes/_app/upload/.image-picker.tsx b/apps/frontend/src/routes/_app/upload/.image-picker.tsx index 5465cbb..57f630e 100644 --- a/apps/frontend/src/routes/_app/upload/.image-picker.tsx +++ b/apps/frontend/src/routes/_app/upload/.image-picker.tsx @@ -3,6 +3,7 @@ import { type Dispatch, type FC, type SetStateAction, useMemo, useState } from ' import { FileInput } from '../../../components/common/FileInput' import { apiClient } from '../../../lib/apiClient' import type { FoodImage } from '../../../types/FoodTypes' +import { CameraButton } from './.camera' type ImagePickerProps = { foodImages: FoodImage[] @@ -55,25 +56,28 @@ export const ImagePicker: FC = ({ return (
- {foodImages.length !== 0 && ( -
- {fileUrls.map((url, i) => ( -
+ {fileUrls.map((url, i) => ( +
+ preview + -
- ))} -
- )} + + +
+ ))} + +
) } diff --git a/apps/frontend/src/routes/_app/upload/index.tsx b/apps/frontend/src/routes/_app/upload/index.tsx index 936eb4a..184f766 100644 --- a/apps/frontend/src/routes/_app/upload/index.tsx +++ b/apps/frontend/src/routes/_app/upload/index.tsx @@ -32,7 +32,6 @@ const Upload = () => { setFoodImages={setFoodImages} setSelectedFoods={setSelectedFoods} /> - {selectedFoods.length > 5 && foods.length > 0 && (
diff --git a/apps/frontend/src/utils/imageDataToFile.ts b/apps/frontend/src/utils/imageDataToFile.ts new file mode 100644 index 0000000..7103c1e --- /dev/null +++ b/apps/frontend/src/utils/imageDataToFile.ts @@ -0,0 +1,23 @@ +export const imageDataToFile = (imageData: ImageData, fileName?: string): File => { + const canvas = document.createElement('canvas') + const context = canvas.getContext('2d') + + if (context === null) { + throw new Error('Could not get 2d context from canvas') + } + + canvas.width = imageData.width + canvas.height = imageData.height + context.putImageData(imageData, 0, 0) + + const dataUrl = canvas.toDataURL('image/png') + const byteString = atob(dataUrl.split(',')[1] ?? '') + const arrayBuffer = new ArrayBuffer(byteString.length) + const uint8Array = new Uint8Array(arrayBuffer) + + for (let i = 0; i < byteString.length; i++) { + uint8Array[i] = byteString.charCodeAt(i) + } + + return new File([uint8Array], fileName ?? 'image.png', { type: 'image/png' }) +} diff --git a/apps/frontend/tsconfig.json b/apps/frontend/tsconfig.json index 4fd903e..d69f943 100644 --- a/apps/frontend/tsconfig.json +++ b/apps/frontend/tsconfig.json @@ -21,6 +21,6 @@ "noFallthroughCasesInSwitch": true, "noUncheckedIndexedAccess": true }, - "include": ["src"], + "include": ["src/**/*", "src/**/.*"], "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7194917..68c2436 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -78,6 +78,9 @@ importers: react: specifier: ^18.3.1 version: 18.3.1 + react-camera-pro: + specifier: ^1.4.0 + version: 1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@5.3.11(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react-is@16.13.1)(react@18.3.1)) react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) @@ -961,6 +964,18 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} + '@emotion/is-prop-valid@1.3.0': + resolution: {integrity: sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ==} + + '@emotion/memoize@0.9.0': + resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} + + '@emotion/stylis@0.8.5': + resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==} + + '@emotion/unitless@0.7.5': + resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} + '@esbuild-plugins/node-globals-polyfill@0.2.3': resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==} peerDependencies: @@ -1630,6 +1645,9 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/webrtc@0.0.25': + resolution: {integrity: sha512-ep/e+p2uUKV1h96GBgRhwomrBch/bPDHPOKbCHODLGRUDuuKe2s7sErlFVKw+5BYUzvpxSmUNqoadaZ44MePoQ==} + '@vitejs/plugin-react-swc@3.7.0': resolution: {integrity: sha512-yrknSb3Dci6svCd/qhHqhFPDSw0QtjumcqdKMoNNzmOl5lMXTTiqzjWtG4Qask2HdvvzaNgSunbQGet8/GrKdA==} peerDependencies: @@ -1796,6 +1814,11 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + babel-plugin-styled-components@2.1.4: + resolution: {integrity: sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==} + peerDependencies: + styled-components: '>= 2' + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1839,6 +1862,9 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} + camelize@1.0.1: + resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} + caniuse-lite@1.0.30001655: resolution: {integrity: sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==} @@ -1945,9 +1971,16 @@ packages: resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} engines: {node: '>=8'} + css-color-keywords@1.0.0: + resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} + engines: {node: '>=4'} + css-select@5.1.0: resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + css-to-react-native@3.2.0: + resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} + css-tree@2.3.1: resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} @@ -2023,6 +2056,9 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + detectrtc@1.4.1: + resolution: {integrity: sha512-lxvyNN6/dSnwoVj1VstVFHel7S0BTmkfv1+01IBEy42D20pue27eB/MfphUOQz78jJ7WcQJDo6ZybhgBlUDi0Q==} + didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -2327,6 +2363,9 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + hono@4.5.11: resolution: {integrity: sha512-62FcjLPtjAFwISVBUshryl+vbHOjg8rE4uIK/dxyR8GpLztunZpwFmfEvmJCUI7xoGh/Sr3CGCDPCmYxVw7wUQ==} engines: {node: '>=16.0.0'} @@ -2916,11 +2955,21 @@ packages: randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + react-camera-pro@1.4.0: + resolution: {integrity: sha512-bTahfCvNrofJVqhdsPOZoMIjGM3MEGnHnRASJDhhD9BEPqHZpDQ7RgoH5/JOlArPCIl+0qUZMtk5Sw4z8nGNjg==} + peerDependencies: + react: ^18.3.1 + react-dom: ^18.3.1 + styled-components: ^5.1.34 + react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: react: ^18.3.1 + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -3043,6 +3092,9 @@ packages: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} + shallowequal@1.1.0: + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -3152,6 +3204,14 @@ packages: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} + styled-components@5.3.11: + resolution: {integrity: sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==} + engines: {node: '>=10'} + peerDependencies: + react: '>= 16.8.0' + react-dom: '>= 16.8.0' + react-is: '>= 16.8.0' + sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -3674,10 +3734,10 @@ snapshots: '@babel/helpers': 7.25.6 '@babel/parser': 7.25.6 '@babel/template': 7.25.0 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) '@babel/types': 7.25.6 convert-source-map: 2.0.0 - debug: 4.3.6 + debug: 4.3.6(supports-color@5.5.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -3697,7 +3757,7 @@ snapshots: '@babel/helper-builder-binary-assignment-operator-visitor@7.24.7': dependencies: - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color @@ -3718,7 +3778,7 @@ snapshots: '@babel/helper-optimise-call-expression': 7.24.7 '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2) '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -3735,7 +3795,7 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - debug: 4.3.6 + debug: 4.3.6(supports-color@5.5.0) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -3743,14 +3803,14 @@ snapshots: '@babel/helper-member-expression-to-functions@7.24.8': dependencies: - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color - '@babel/helper-module-imports@7.24.7': + '@babel/helper-module-imports@7.24.7(supports-color@5.5.0)': dependencies: - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color @@ -3758,10 +3818,10 @@ snapshots: '@babel/helper-module-transforms@7.25.2(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.24.7 + '@babel/helper-module-imports': 7.24.7(supports-color@5.5.0) '@babel/helper-simple-access': 7.24.7 '@babel/helper-validator-identifier': 7.24.7 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -3776,7 +3836,7 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.24.7 '@babel/helper-wrap-function': 7.25.0 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -3785,20 +3845,20 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-member-expression-to-functions': 7.24.8 '@babel/helper-optimise-call-expression': 7.24.7 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) transitivePeerDependencies: - supports-color '@babel/helper-simple-access@7.24.7': dependencies: - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.24.7': dependencies: - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color @@ -3812,7 +3872,7 @@ snapshots: '@babel/helper-wrap-function@7.25.0': dependencies: '@babel/template': 7.25.0 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color @@ -3837,7 +3897,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -3864,7 +3924,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -3984,14 +4044,14 @@ snapshots: '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.25.2) '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2) - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) transitivePeerDependencies: - supports-color '@babel/plugin-transform-async-to-generator@7.24.7(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.24.7 + '@babel/helper-module-imports': 7.24.7(supports-color@5.5.0) '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.25.2) transitivePeerDependencies: @@ -4031,7 +4091,7 @@ snapshots: '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2) - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -4097,7 +4157,7 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -4146,7 +4206,7 @@ snapshots: '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-validator-identifier': 7.24.7 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -4410,14 +4470,14 @@ snapshots: '@babel/parser': 7.25.6 '@babel/types': 7.25.6 - '@babel/traverse@7.25.6': + '@babel/traverse@7.25.6(supports-color@5.5.0)': dependencies: '@babel/code-frame': 7.24.7 '@babel/generator': 7.25.6 '@babel/parser': 7.25.6 '@babel/template': 7.25.0 '@babel/types': 7.25.6 - debug: 4.3.6 + debug: 4.3.6(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -4525,6 +4585,16 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 + '@emotion/is-prop-valid@1.3.0': + dependencies: + '@emotion/memoize': 0.9.0 + + '@emotion/memoize@0.9.0': {} + + '@emotion/stylis@0.8.5': {} + + '@emotion/unitless@0.7.5': {} + '@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)': dependencies: esbuild: 0.17.19 @@ -4735,7 +4805,7 @@ snapshots: '@rollup/plugin-babel@5.3.1(@babel/core@7.25.2)(@types/babel__core@7.20.5)(rollup@2.79.1)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.24.7 + '@babel/helper-module-imports': 7.24.7(supports-color@5.5.0) '@rollup/pluginutils': 3.1.0(rollup@2.79.1) rollup: 2.79.1 optionalDependencies: @@ -4942,7 +5012,7 @@ snapshots: '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) '@babel/template': 7.25.0 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) '@babel/types': 7.25.6 '@tanstack/router-generator': 1.52.0 '@types/babel__core': 7.20.5 @@ -5043,6 +5113,8 @@ snapshots: '@types/trusted-types@2.0.7': {} + '@types/webrtc@0.0.25': {} + '@vitejs/plugin-react-swc@3.7.0(vite@5.4.3(@types/node@22.5.2)(less@3.13.1)(terser@5.31.6))': dependencies: '@swc/core': 1.7.23 @@ -5231,7 +5303,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/parser': 7.25.6 - '@babel/traverse': 7.25.6 + '@babel/traverse': 7.25.6(supports-color@5.5.0) '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color @@ -5260,6 +5332,18 @@ snapshots: transitivePeerDependencies: - supports-color + babel-plugin-styled-components@2.1.4(@babel/core@7.25.2)(styled-components@5.3.11(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react-is@16.13.1)(react@18.3.1))(supports-color@5.5.0): + dependencies: + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-module-imports': 7.24.7(supports-color@5.5.0) + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) + lodash: 4.17.21 + picomatch: 2.3.1 + styled-components: 5.3.11(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react-is@16.13.1)(react@18.3.1) + transitivePeerDependencies: + - '@babel/core' + - supports-color + balanced-match@1.0.2: {} binary-extensions@2.3.0: {} @@ -5302,6 +5386,8 @@ snapshots: camelcase-css@2.0.1: {} + camelize@1.0.1: {} + caniuse-lite@1.0.30001655: {} capnp-ts@0.7.0: @@ -5426,6 +5512,8 @@ snapshots: crypto-random-string@2.0.0: {} + css-color-keywords@1.0.0: {} + css-select@5.1.0: dependencies: boolbase: 1.0.0 @@ -5434,6 +5522,12 @@ snapshots: domutils: 3.1.0 nth-check: 2.1.1 + css-to-react-native@3.2.0: + dependencies: + camelize: 1.0.1 + css-color-keywords: 1.0.0 + postcss-value-parser: 4.2.0 + css-tree@2.3.1: dependencies: mdn-data: 2.0.30 @@ -5471,9 +5565,11 @@ snapshots: dependencies: ms: 2.1.2 - debug@4.3.6: + debug@4.3.6(supports-color@5.5.0): dependencies: ms: 2.1.2 + optionalDependencies: + supports-color: 5.5.0 deepmerge@4.3.1: {} @@ -5496,6 +5592,8 @@ snapshots: dequal@2.0.3: {} + detectrtc@1.4.1: {} + didyoumean@1.2.2: {} diff-match-patch@1.0.5: {} @@ -5878,6 +5976,10 @@ snapshots: dependencies: function-bind: 1.1.2 + hoist-non-react-statics@3.3.2: + dependencies: + react-is: 16.13.1 + hono@4.5.11: {} htmlparser2@8.0.2: @@ -6085,7 +6187,7 @@ snapshots: dependencies: chalk: 5.3.0 commander: 12.1.0 - debug: 4.3.6 + debug: 4.3.6(supports-color@5.5.0) execa: 8.0.1 lilconfig: 3.1.2 listr2: 8.2.4 @@ -6420,12 +6522,22 @@ snapshots: dependencies: safe-buffer: 5.2.1 + react-camera-pro@1.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@5.3.11(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react-is@16.13.1)(react@18.3.1)): + dependencies: + '@types/webrtc': 0.0.25 + detectrtc: 1.4.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + styled-components: 5.3.11(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react-is@16.13.1)(react@18.3.1) + react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 react: 18.3.1 scheduler: 0.23.2 + react-is@16.13.1: {} + react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -6584,6 +6696,8 @@ snapshots: functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 + shallowequal@1.1.0: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -6710,6 +6824,24 @@ snapshots: strip-final-newline@3.0.0: {} + styled-components@5.3.11(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react-is@16.13.1)(react@18.3.1): + dependencies: + '@babel/helper-module-imports': 7.24.7(supports-color@5.5.0) + '@babel/traverse': 7.25.6(supports-color@5.5.0) + '@emotion/is-prop-valid': 1.3.0 + '@emotion/stylis': 0.8.5 + '@emotion/unitless': 0.7.5 + babel-plugin-styled-components: 2.1.4(@babel/core@7.25.2)(styled-components@5.3.11(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react-is@16.13.1)(react@18.3.1))(supports-color@5.5.0) + css-to-react-native: 3.2.0 + hoist-non-react-statics: 3.3.2 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-is: 16.13.1 + shallowequal: 1.1.0 + supports-color: 5.5.0 + transitivePeerDependencies: + - '@babel/core' + sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.5 @@ -6972,7 +7104,7 @@ snapshots: vite-plugin-pwa@0.20.3(vite@5.4.3(@types/node@22.5.2)(less@3.13.1)(terser@5.31.6))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.1.0): dependencies: - debug: 4.3.6 + debug: 4.3.6(supports-color@5.5.0) pretty-bytes: 6.1.1 tinyglobby: 0.2.5 vite: 5.4.3(@types/node@22.5.2)(less@3.13.1)(terser@5.31.6)