diff --git a/.eslintignore b/.eslintignore index 5a8bfc2..21feb23 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,6 @@ .vscode .eslintrc.js packlint.config.mjs -node_modules \ No newline at end of file +node_modules +esm +dist diff --git a/.gitignore b/.gitignore index d1595af..e17b911 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,9 @@ yarn-error.log* # vercel .vercel + +# bundled +dist +esm + +stats.html diff --git a/.vscode/settings.json b/.vscode/settings.json index 2fde182..d0b855d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,8 @@ { "typescript.tsdk": "node_modules/typescript/lib", "editor.defaultFormatter": "esbenp.prettier-vscode", - "eslint.packageManager": "pnpm", "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"], - "cSpell.words": ["packlint", "nextjs", "sulsul"], + "cSpell.words": ["packlint", "nextjs", "sulsul", "jsxcss"], "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, diff --git a/apps/falling/package.json b/apps/falling/package.json index 8144113..2b392e5 100644 --- a/apps/falling/package.json +++ b/apps/falling/package.json @@ -22,7 +22,7 @@ "@tanstack/react-query-devtools": "^4.29.3", "axios": "^1.3.6", "framer-motion": "^10.12.4", - "next": "13.4.4", + "next": "13.4.12", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.43.9", diff --git a/apps/falling/public/images/bubble-beer.png b/apps/falling/public/images/bubble-beer.png new file mode 100644 index 0000000..a322414 Binary files /dev/null and b/apps/falling/public/images/bubble-beer.png differ diff --git a/apps/falling/public/images/bubble-goryanju.png b/apps/falling/public/images/bubble-goryanju.png new file mode 100644 index 0000000..16e4584 Binary files /dev/null and b/apps/falling/public/images/bubble-goryanju.png differ diff --git a/apps/falling/public/images/bubble-soju.png b/apps/falling/public/images/bubble-soju.png new file mode 100644 index 0000000..4afe316 Binary files /dev/null and b/apps/falling/public/images/bubble-soju.png differ diff --git a/apps/falling/public/images/bubble-whisky.png b/apps/falling/public/images/bubble-whisky.png new file mode 100644 index 0000000..8d89a96 Binary files /dev/null and b/apps/falling/public/images/bubble-whisky.png differ diff --git a/apps/falling/public/images/bubble-wine.png b/apps/falling/public/images/bubble-wine.png new file mode 100644 index 0000000..4649868 Binary files /dev/null and b/apps/falling/public/images/bubble-wine.png differ diff --git a/apps/falling/src/app/components/Falling.tsx b/apps/falling/src/app/components/Falling.tsx new file mode 100644 index 0000000..2056179 --- /dev/null +++ b/apps/falling/src/app/components/Falling.tsx @@ -0,0 +1,39 @@ +'use client'; + +import { StackView, useStackBall } from '@sulsul/ui'; +import { useEffect, useState } from 'react'; +import { drinkImage, drinks } from '../constants/drinks'; + +export const Falling = () => { + const [isFirstTouch, setIsFirstTouch] = useState(false); + const { addBall, boxRef, canvasRef } = useStackBall(); + + useEffect(() => { + const addItem = (event: any) => { + if (!isFirstTouch) { + setIsFirstTouch(true); + return; + } + + if (event.detail.data === undefined) { + throw new Error('event.detail.data is undefined'); + } + + const { image, size } = drinkImage[event.detail.data as drinks]; + addBall(image, size); + + window.sulsulBridge.onAddBallSuccess(event.detail.data as drinks); + }; + window.addEventListener('addBall', addItem); + + return () => { + window.removeEventListener('addBall', addItem); + }; + }, [addBall, isFirstTouch]); + + return ( +
+ +
+ ); +}; diff --git a/apps/falling/src/app/constants/drinks.ts b/apps/falling/src/app/constants/drinks.ts new file mode 100644 index 0000000..9855f47 --- /dev/null +++ b/apps/falling/src/app/constants/drinks.ts @@ -0,0 +1,24 @@ +export const drinkImage = { + 소주: { + image: '/images/bubble-soju.png', + size: 80, + }, + 맥주: { + image: '/images/bubble-beer.png', + size: 100, + }, + 와인: { + image: '/images/bubble-wine.png', + size: 92, + }, + 고량주: { + image: '/images/bubble-goryanju.png', + size: 68, + }, + 위스키: { + image: '/images/bubble-whisky.png', + size: 68, + }, +} as const; + +export type drinks = keyof typeof drinkImage; diff --git a/apps/falling/src/app/layout.tsx b/apps/falling/src/app/layout.tsx index 2d68a84..6af4fe0 100644 --- a/apps/falling/src/app/layout.tsx +++ b/apps/falling/src/app/layout.tsx @@ -7,10 +7,17 @@ import { SuspensiveConfigs, SuspensiveProvider } from '@suspensive/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { Inter } from 'next/font/google'; +import { AndroidWebviewProvider } from '~/contexts/androidWeview'; import RootStyleRegistry from '../../emotion'; import './globals.css'; +declare global { + interface Window { + sulsulBridge: any; + } +} + const queryClient = new QueryClient({ defaultOptions: { queries: { @@ -34,16 +41,18 @@ export default function RootLayout({ children }: { children: React.ReactNode }) return ( - - - - - {children} - - - - - + + + + + + {children} + + + + + + ); diff --git a/apps/falling/src/app/page.tsx b/apps/falling/src/app/page.tsx index 7a58bf6..ff91014 100644 --- a/apps/falling/src/app/page.tsx +++ b/apps/falling/src/app/page.tsx @@ -1,5 +1,7 @@ 'use client'; +import { Falling } from './components/Falling'; + export default function Home() { - return
explore amplify test
; + return ; } diff --git a/apps/falling/src/contexts/androidWeview/index.tsx b/apps/falling/src/contexts/androidWeview/index.tsx new file mode 100644 index 0000000..9810949 --- /dev/null +++ b/apps/falling/src/contexts/androidWeview/index.tsx @@ -0,0 +1,72 @@ +import { + createContext, + PropsWithChildren, + ReactNode, + Suspense, + useContext, + useEffect, + useState, +} from 'react'; + +const AndroidWebviewContext = createContext(null); +export const AndroidWebviewProvider = (props: PropsWithChildren) => { + const [androidWebview, setAndroidWebview] = useState(null); + useEffect(() => { + if ((window as any).android) { + setAndroidWebview((window as any).android); + } + }, []); + return ; +}; + +export const AndroidWebviewGuaranteed = ({ + render, + fallback, +}: { + render: (androidWebview: AndroidWebview) => ReactNode; + fallback?: ReactNode; +}) => { + const androidWebviewContextValue = useContext(AndroidWebviewContext); + + if (androidWebviewContextValue === null) { + return <>{fallback}; + } + const androidWebview = androidWebviewContextValue; + return <>{render(androidWebview)}; +}; + +interface AndroidWebview { + showToastMessage(): void; +} + +export const useAndroidWebview = (): AndroidWebview => { + const androidWebviewContextValue = useContext(AndroidWebviewContext); + + if (androidWebviewContextValue === null) { + throw new Promise(() => {}); + } + + return androidWebviewContextValue; +}; + +export const Comp = () => { + return ( + <> + hihihih jijojooj + loading...}> + + + } + /> + + ); +}; + +const AndroidWebviewUser = () => { + const androidWebview = useAndroidWebview(); + + const handleClick = () => androidWebview.showToastMessage(); + + return ; +}; diff --git a/apps/onboarding/.eslintrc.js b/apps/onboarding/.eslintrc.js index a01a20e..907cb2a 100644 --- a/apps/onboarding/.eslintrc.js +++ b/apps/onboarding/.eslintrc.js @@ -1,4 +1,7 @@ module.exports = { root: true, extends: ['@sulsul/eslint-config/react-ts-noimport', 'plugin:@next/next/recommended'], + rules: { + 'react/no-unknown-property': ['error', { ignore: ['css'] }], + }, }; diff --git a/apps/onboarding/emotion.tsx b/apps/onboarding/emotion.tsx deleted file mode 100644 index 521f6a2..0000000 --- a/apps/onboarding/emotion.tsx +++ /dev/null @@ -1,26 +0,0 @@ -'use client'; - -import { useState } from 'react'; -import createCache from '@emotion/cache'; -import { CacheProvider } from '@emotion/react'; -import { useServerInsertedHTML } from 'next/navigation'; - -export default function RootStyleRegistry({ children }: { children: JSX.Element }) { - const [cache] = useState(() => { - const cache = createCache({ key: 'css' }); - cache.compat = true; - return cache; - }); - - useServerInsertedHTML(() => ( -