The weeb for the next gen discord boat - Wamellow wamellow.com
bot discord
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

better modals

Luna 36ac2183 16b0d788

+270 -200
+7 -1
app/globals.css
··· 63 63 @apply cursor-pointer 64 64 } 65 65 html { 66 + background: var(--background-rgb); 67 + } 68 + body { 66 69 font-family: var(--font-outfit), var(--font-noto-sans-jp), sans-serif; 67 70 scroll-behavior: smooth; 68 71 min-height: 100svh; 69 - background: var(--background-rgb); 70 72 } 71 73 } 72 74 ··· 247 249 248 250 td:has(audio) { 249 251 padding: 1px!important; 252 + } 253 + 254 + body[data-scroll-locked] { 255 + position: static !important; 250 256 }
+22 -22
app/layout.tsx
··· 96 96 }; 97 97 }; 98 98 99 - export default function RootLayout({ 100 - children 101 - }: { 102 - children: React.ReactNode; 103 - }) { 99 + export default function RootLayout({ children }: { children: React.ReactNode; }) { 104 100 return ( 105 101 <CookiesProvider> 106 102 <html 107 103 suppressHydrationWarning 108 104 data-theme="dark" 109 105 lang="en" 110 - className="dark flex justify-center max-w-screen overflow-x-hidden" 106 + className="dark max-w-screen overflow-x-hidden" 111 107 > 112 - <Script defer data-domain="wamellow.com" src="https://analytics.wamellow.com/js/script.outbound-links.js" /> 113 - {process.env.NODE_ENV === "development" && ( 114 - <Script src="https://unpkg.com/react-scan/dist/auto.global.js" /> 115 - )} 116 - 108 + <Script 109 + defer 110 + data-domain="wamellow.com" 111 + src="https://analytics.wamellow.com/js/script.outbound-links.js" 112 + /> 117 113 <Script 118 114 id="reviews" 119 115 type="application/ld+json" 120 116 > 121 117 {JSON.stringify(reviews)} 122 118 </Script> 119 + {process.env.NODE_ENV === "development" && ( 120 + <Script src="https://unpkg.com/react-scan/dist/auto.global.js" /> 121 + )} 123 122 124 123 <body 125 - className={cn("w-full max-w-7xl overflow-x-hidden xl:!overflow-visible", outfit.variable, notosansJP.variable)} 126 - style={{ overflow: "visible" }} 124 + className={cn( 125 + "relative top-0 w-full flex justify-center overflow-x-hidden xl:!overflow-visible", 126 + outfit.variable, 127 + notosansJP.variable 128 + )} 127 129 > 128 130 <div id="bg" className="absolute top-0 right-0 w-screen h-screen -z-50" /> 129 131 <Noise /> 130 132 131 - <NavBar /> 132 - 133 - <Provider> 134 - {children} 135 - </Provider> 136 - 133 + <div className="w-full max-w-7xl"> 134 + <NavBar className="w-full" /> 135 + <Provider className="w-full">{children}</Provider> 136 + </div> 137 137 </body> 138 138 </html> 139 139 </CookiesProvider> ··· 143 143 function Noise() { 144 144 return ( 145 145 <svg 146 - className="absolute top-0 left-0 w-screen h-full -z-40 blur-[1px] saturate-0" 146 + className="absolute top-0 left-0 w-screen h-screen -z-40 blur-[1px] saturate-0" 147 147 viewBox='0 0 142 158' 148 148 xmlns='http://www.w3.org/2000/svg' 149 149 > ··· 171 171 ); 172 172 } 173 173 174 - async function NavBar() { 174 + async function NavBar({ className }: { className?: string; }) { 175 175 const jar = await cookies(); 176 176 177 177 return ( 178 - <nav className="p-4 flex items-center gap-2 text-base text-neutral-300 select-none h-20 relative"> 178 + <nav className={cn("p-4 flex items-center gap-2 text-base text-neutral-300 select-none h-20 relative", className)}> 179 179 <Link 180 180 aria-label="Go to Wamellow's homepage" 181 181 className={cn("font-semibold flex items-center shrink-0", lexend.className)}
+4 -2
app/provider.tsx
··· 8 8 9 9 import { guildStore } from "@/common/guilds"; 10 10 import { TooltipProvider } from "@/components/ui/tooltip"; 11 + import { cn } from "@/utils/cn"; 11 12 12 13 const queryClient = new QueryClient(); 13 14 14 15 interface Props { 15 16 children: React.ReactNode; 17 + className?: string; 16 18 } 17 19 18 - export function Provider({ children }: Props) { 20 + export function Provider({ children, className }: Props) { 19 21 const cookies = useCookies(); 20 22 const path = usePathname(); 21 23 ··· 38 40 <TooltipProvider> 39 41 <NextUIProvider> 40 42 <QueryClientProvider client={queryClient}> 41 - <main className="dark:text-neutral-400 text-neutral-700 flex flex-col items-center justify-between md:p-5 p-3 w-6xl max-w-full mt-2 md:mt-10"> 43 + <main className={cn("dark:text-neutral-400 text-neutral-700 flex flex-col items-center justify-between md:p-5 p-3 w-full max-w-7xl mt-2 md:mt-10", className)}> 42 44 {children} 43 45 </main> 44 46 </QueryClientProvider>
+42 -39
bun.lock
··· 13 13 "@radix-ui/react-avatar": "^1.1.10", 14 14 "@radix-ui/react-checkbox": "^1.3.2", 15 15 "@radix-ui/react-compose-refs": "1.1.2", 16 + "@radix-ui/react-dialog": "^1.1.14", 16 17 "@radix-ui/react-popover": "^1.1.14", 17 18 "@radix-ui/react-primitive": "2.1.3", 18 19 "@radix-ui/react-separator": "^1.1.7", ··· 442 443 443 444 "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="], 444 445 445 - "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.5", "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.2", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-portal": "1.1.4", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-slot": "1.1.2", "@radix-ui/react-use-controllable-state": "1.1.0", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw=="], 446 + "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw=="], 446 447 447 448 "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ=="], 448 449 ··· 1880 1881 1881 1882 "@nextui-org/use-aria-multiselect/@react-aria/label": ["@react-aria/label@3.7.13", "", { "dependencies": { "@react-aria/utils": "^3.26.0", "@react-types/shared": "^3.26.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-brSAXZVTey5RG/Ex6mTrV/9IhGSQFU4Al34qmjEDho+Z2qT4oPwf8k7TRXWWqzOU0ugYxekYbsLd2zlN3XvWcg=="], 1882 1883 1883 - "@radix-ui/react-dialog/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="], 1884 - 1885 - "@radix-ui/react-dialog/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], 1886 - 1887 - "@radix-ui/react-dialog/@radix-ui/react-context": ["@radix-ui/react-context@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q=="], 1888 - 1889 - "@radix-ui/react-dialog/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg=="], 1890 - 1891 - "@radix-ui/react-dialog/@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg=="], 1892 - 1893 - "@radix-ui/react-dialog/@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA=="], 1894 - 1895 - "@radix-ui/react-dialog/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="], 1896 - 1897 - "@radix-ui/react-dialog/@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.4", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA=="], 1898 - 1899 - "@radix-ui/react-dialog/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg=="], 1900 - 1901 - "@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], 1902 - 1903 - "@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], 1904 - 1905 - "@radix-ui/react-dialog/@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="], 1906 - 1907 1884 "@react-aria/calendar/@internationalized/date": ["@internationalized/date@3.7.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-VJ5WS3fcVx0bejE/YHfbDKR/yawZgKqn/if+oEeLqNwBtPzVB06olkfcnojTmEMX+gTpH+FlQ69SHNitJ8/erQ=="], 1908 1885 1909 1886 "@react-aria/calendar/@react-aria/utils": ["@react-aria/utils@3.28.1", "", { "dependencies": { "@react-aria/ssr": "^3.9.7", "@react-stately/flags": "^3.1.0", "@react-stately/utils": "^3.10.5", "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-mnHFF4YOVu9BRFQ1SZSKfPhg3z+lBRYoW5mLcYTQihbKhz48+I1sqRkP7ahMITr8ANH3nb34YaMME4XWmK2Mgg=="], ··· 2182 2159 2183 2160 "unset-value/has-value": ["has-value@0.3.1", "", { "dependencies": { "get-value": "^2.0.3", "has-values": "^0.1.4", "isobject": "^2.0.0" } }, "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q=="], 2184 2161 2162 + "vaul/@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.5", "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.2", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-portal": "1.1.4", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-slot": "1.1.2", "@radix-ui/react-use-controllable-state": "1.1.0", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw=="], 2163 + 2185 2164 "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], 2186 2165 2187 2166 "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], ··· 2195 2174 "@nextui-org/use-aria-multiselect/@react-aria/label/@react-aria/utils": ["@react-aria/utils@3.28.1", "", { "dependencies": { "@react-aria/ssr": "^3.9.7", "@react-stately/flags": "^3.1.0", "@react-stately/utils": "^3.10.5", "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-mnHFF4YOVu9BRFQ1SZSKfPhg3z+lBRYoW5mLcYTQihbKhz48+I1sqRkP7ahMITr8ANH3nb34YaMME4XWmK2Mgg=="], 2196 2175 2197 2176 "@nextui-org/use-aria-multiselect/@react-aria/label/@react-types/shared": ["@react-types/shared@3.28.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q=="], 2198 - 2199 - "@radix-ui/react-dialog/@radix-ui/react-dismissable-layer/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], 2200 - 2201 - "@radix-ui/react-dialog/@radix-ui/react-dismissable-layer/@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw=="], 2202 - 2203 - "@radix-ui/react-dialog/@radix-ui/react-focus-scope/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], 2204 - 2205 - "@radix-ui/react-dialog/@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], 2206 - 2207 - "@radix-ui/react-dialog/@radix-ui/react-portal/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], 2208 - 2209 - "@radix-ui/react-dialog/@radix-ui/react-presence/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], 2210 - 2211 - "@radix-ui/react-dialog/@radix-ui/react-use-controllable-state/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], 2212 2177 2213 2178 "@react-aria/combobox/@react-aria/selection/@react-aria/focus": ["@react-aria/focus@3.20.1", "", { "dependencies": { "@react-aria/interactions": "^3.24.1", "@react-aria/utils": "^3.28.1", "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-lgYs+sQ1TtBrAXnAdRBQrBo0/7o5H6IrfDxec1j+VRpcXL0xyk0xPq+m3lZp8typzIghqDgpnKkJ5Jf4OrzPIw=="], 2214 2179 ··· 2322 2287 2323 2288 "unset-value/has-value/isobject": ["isobject@2.1.0", "", { "dependencies": { "isarray": "1.0.0" } }, "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA=="], 2324 2289 2290 + "vaul/@radix-ui/react-dialog/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="], 2291 + 2292 + "vaul/@radix-ui/react-dialog/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], 2293 + 2294 + "vaul/@radix-ui/react-dialog/@radix-ui/react-context": ["@radix-ui/react-context@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q=="], 2295 + 2296 + "vaul/@radix-ui/react-dialog/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg=="], 2297 + 2298 + "vaul/@radix-ui/react-dialog/@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg=="], 2299 + 2300 + "vaul/@radix-ui/react-dialog/@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA=="], 2301 + 2302 + "vaul/@radix-ui/react-dialog/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="], 2303 + 2304 + "vaul/@radix-ui/react-dialog/@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.4", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA=="], 2305 + 2306 + "vaul/@radix-ui/react-dialog/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg=="], 2307 + 2308 + "vaul/@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], 2309 + 2310 + "vaul/@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], 2311 + 2312 + "vaul/@radix-ui/react-dialog/@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="], 2313 + 2325 2314 "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], 2326 2315 2327 2316 "wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], ··· 2335 2324 "@react-aria/tabs/@react-aria/selection/@react-aria/i18n/@internationalized/date": ["@internationalized/date@3.7.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-VJ5WS3fcVx0bejE/YHfbDKR/yawZgKqn/if+oEeLqNwBtPzVB06olkfcnojTmEMX+gTpH+FlQ69SHNitJ8/erQ=="], 2336 2325 2337 2326 "unset-value/has-value/isobject/isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], 2327 + 2328 + "vaul/@radix-ui/react-dialog/@radix-ui/react-dismissable-layer/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], 2329 + 2330 + "vaul/@radix-ui/react-dialog/@radix-ui/react-dismissable-layer/@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw=="], 2331 + 2332 + "vaul/@radix-ui/react-dialog/@radix-ui/react-focus-scope/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], 2333 + 2334 + "vaul/@radix-ui/react-dialog/@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], 2335 + 2336 + "vaul/@radix-ui/react-dialog/@radix-ui/react-portal/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], 2337 + 2338 + "vaul/@radix-ui/react-dialog/@radix-ui/react-presence/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], 2339 + 2340 + "vaul/@radix-ui/react-dialog/@radix-ui/react-use-controllable-state/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], 2338 2341 } 2339 2342 }
+46 -131
components/modal.tsx
··· 1 1 "use client"; 2 2 3 - import { Progress } from "@nextui-org/react"; 4 - import { Separator } from "@radix-ui/react-separator"; 5 - import { AnimatePresence, motion, MotionConfig } from "framer-motion"; 6 3 import { useEffect, useState } from "react"; 7 - import { HiX } from "react-icons/hi"; 8 4 9 5 import type { ApiError } from "@/typings"; 10 6 import { cn } from "@/utils/cn"; 11 7 12 - import { ClickOutside } from "./click-outside"; 13 8 import Notice, { NoticeType } from "./notice"; 14 9 import { Button } from "./ui/button"; 10 + import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "./ui/dialog"; 11 + import { Separator } from "./ui/separator"; 15 12 16 13 enum State { 17 14 Idle = 0, ··· 60 57 useEffect(() => { 61 58 setError(null); 62 59 setState(State.Idle); 63 - 64 - const html = document.getElementsByTagName("html")?.[0]; 65 - if (isOpen) { 66 - html.style.overflow = document.body.style.overflow = "hidden"; 67 - } else { 68 - html.style.overflow = document.body.style.overflow = ""; 69 - } 70 - 71 - return () => { 72 - html.style.overflow = document.body.style.overflow = ""; 73 - }; 74 60 }, [isOpen]); 75 61 76 62 async function submit() { ··· 103 89 onError?.(); 104 90 } 105 91 106 - function Header() { 107 - return (<> 108 - <div className="flex items-center"> 109 - <span className="text-2xl font-semibold dark:text-neutral-200 text-neutral-800"> 110 - {title} 111 - </span> 112 - 113 - <Button 114 - onClick={() => state !== State.Loading && onClose()} 115 - className="ml-auto" 116 - size="icon" 117 - > 118 - <HiX /> 119 - </Button> 120 - </div> 92 + return ( 93 + <Dialog 94 + open={isOpen} 95 + onOpenChange={(open) => !open && onClose()} 96 + > 97 + <DialogContent> 98 + <DialogHeader> 99 + <DialogTitle>{title}</DialogTitle> 100 + <Separator className="bg-muted h-[1px]" loading={state === State.Loading} /> 101 + </DialogHeader> 121 102 122 - <Progress 123 - size="sm" 124 - isIndeterminate={state === State.Loading} 125 - aria-label="Loading..." 126 - className="mt-3 mb-4 h-0.5" 127 - classNames={{ 128 - track: "bg-divider", 129 - indicator: "bg-violet-500" 130 - }} 131 - value={0} 132 - /> 133 - </>); 134 - } 135 - 136 - function Footer() { 137 - return (<div className="flex items-center w-full gap-6 p-4"> 138 - {footer} 139 - 140 - {onSubmit && 141 - <button 142 - onClick={() => state !== State.Loading && onClose()} 103 + <div 143 104 className={cn( 144 - "ml-auto text-sm font-medium dark:text-neutral-200 text-neutral-800", 145 - state === State.Idle && "cursort-not-allowed" 105 + "scrollbar-hide overflow-y-scroll overflow-x-hidden max-h-[70vh] py-2", 106 + className 146 107 )} 147 - disabled={state !== State.Idle} 148 108 > 149 - Cancel 150 - </button> 151 - } 109 + {error && ( 110 + <Notice 111 + type={NoticeType.Error} 112 + message={error} 113 + /> 114 + )} 152 115 153 - <Button 154 - variant={variant} 155 - onClick={() => submit()} 156 - className={cn(!onSubmit && "ml-auto")} 157 - disabled={isDisabled} 158 - > 159 - {buttonName} 160 - </Button> 116 + {children} 117 + </div> 161 118 162 - {isOpen && state !== State.Loading && <ClickOutside onClose={onClose} />} 163 - </div>); 164 - } 119 + <DialogFooter> 120 + {footer} 165 121 166 - return (<MotionConfig transition={{ type: "spring", bounce: 0.4, duration: 1 }}> 167 - <AnimatePresence initial={false}> 122 + {onSubmit && ( 123 + <Button 124 + variant="link" 125 + onClick={() => state !== State.Loading && onClose()} 126 + className="hidden md:block ml-auto text-sm font-medium" 127 + disabled={state !== State.Idle} 128 + > 129 + Cancel 130 + </Button> 131 + )} 168 132 169 - {isOpen && 170 - <motion.div 171 - initial="closed" 172 - animate={isOpen ? "open" : "closed"} 173 - exit="closed" 174 - variants={{ closed: { opacity: 0 }, open: { opacity: 1 } }} 175 - className="fixed top-0 left-0 h-screen w-full inset-0 backdrop-brightness-[25%] backdrop-blur flex items-center justify-center z-50 cursor-default" 176 - style={{ maxHeight: "100dvh" }} 177 - > 178 - <motion.div 179 - initial="closed" 180 - animate={isOpen ? "open" : "closed"} 181 - exit="closed" 182 - variants={{ 183 - closed: { 184 - y: "var(--y-closed, 0)", 185 - opacity: "var(--opacity-closed)", 186 - scale: "var(--scale-closed, 1)" 187 - }, 188 - open: { 189 - y: "var(--y-open, 0)", 190 - opacity: "var(--opacity-open)", 191 - scale: "var(--scale-open, 1)" 192 - } 193 - }} 194 - className=" 195 - md:relative fixed bottom-0 min-h-[333px] md:min-h-fit mb-2 wamellow-modal 196 - w-[97%] md:w-[480px] bg-popover rounded-xl shadow-md 197 - max-sm:[--y-closed:28px] [--opacity-closed:0%] sm:[--scale-closed:90%] 198 - max-sm:[--y-open:0px] [--opacity-open:100%] sm:[--scale-open:100%] 199 - " 133 + <Button 134 + variant={variant} 135 + onClick={() => submit()} 136 + className={cn(!onSubmit && "ml-auto")} 137 + disabled={isDisabled} 200 138 > 201 - 202 - <div className="p-4 pb-0"> 203 - <Header /> 204 - 205 - <div 206 - className={cn( 207 - "scrollbar-none p-0.5 pb-8 md:pb-4 max-h-[512px] overflow-y-scroll md:overflow-y-visible overflow-x-hidden", 208 - className 209 - )} 210 - > 211 - {error && 212 - <Notice 213 - type={NoticeType.Error} 214 - message={error} 215 - /> 216 - } 217 - 218 - {children} 219 - </div> 220 - </div> 221 - 222 - <Separator className="bg-muted h-[1px]" /> 223 - 224 - <Footer /> 225 - </motion.div> 226 - </motion.div> 227 - } 228 - </AnimatePresence> 229 - </MotionConfig>); 139 + {buttonName} 140 + </Button> 141 + </DialogFooter> 142 + </DialogContent> 143 + </Dialog> 144 + ); 230 145 }
+122
components/ui/dialog.tsx
··· 1 + "use client"; 2 + 3 + import * as DialogPrimitive from "@radix-ui/react-dialog"; 4 + import { X } from "lucide-react"; 5 + import * as React from "react"; 6 + 7 + import { cn } from "@/utils/cn"; 8 + 9 + const Dialog = DialogPrimitive.Root; 10 + 11 + const DialogTrigger = DialogPrimitive.Trigger; 12 + 13 + const DialogPortal = DialogPrimitive.Portal; 14 + 15 + const DialogClose = DialogPrimitive.Close; 16 + 17 + const DialogOverlay = React.forwardRef< 18 + React.ElementRef<typeof DialogPrimitive.Overlay>, 19 + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> 20 + >(({ className, ...props }, ref) => ( 21 + <DialogPrimitive.Overlay 22 + ref={ref} 23 + className={cn( 24 + "fixed inset-0 z-50 backdrop-brightness-[25%] backdrop-blur data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", 25 + className 26 + )} 27 + {...props} 28 + /> 29 + )); 30 + DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; 31 + 32 + const DialogContent = React.forwardRef< 33 + React.ElementRef<typeof DialogPrimitive.Content>, 34 + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> 35 + >(({ className, children, ...props }, ref) => ( 36 + <DialogPortal> 37 + <DialogOverlay /> 38 + <DialogPrimitive.Content 39 + ref={ref} 40 + className={cn( 41 + "fixed left-[50%] top-[50%] z-50 w-full max-w-lg translate-x-[-50%] translate-y-[-50%] bg-popover p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] rounded-xl", 42 + className 43 + )} 44 + {...props} 45 + > 46 + {children} 47 + <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"> 48 + <X className="h-4 w-4" /> 49 + <span className="sr-only">Close</span> 50 + </DialogPrimitive.Close> 51 + </DialogPrimitive.Content> 52 + </DialogPortal> 53 + )); 54 + DialogContent.displayName = DialogPrimitive.Content.displayName; 55 + 56 + const DialogHeader = ({ 57 + className, 58 + ...props 59 + }: React.HTMLAttributes<HTMLDivElement>) => ( 60 + <div 61 + className={cn( 62 + "flex flex-col space-y-4", 63 + className 64 + )} 65 + {...props} 66 + /> 67 + ); 68 + DialogHeader.displayName = "DialogHeader"; 69 + 70 + const DialogFooter = ({ 71 + className, 72 + ...props 73 + }: React.HTMLAttributes<HTMLDivElement>) => ( 74 + <div 75 + className={cn( 76 + "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 pt-2", 77 + className 78 + )} 79 + {...props} 80 + /> 81 + ); 82 + DialogFooter.displayName = "DialogFooter"; 83 + 84 + const DialogTitle = React.forwardRef< 85 + React.ElementRef<typeof DialogPrimitive.Title>, 86 + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title> 87 + >(({ className, ...props }, ref) => ( 88 + <DialogPrimitive.Title 89 + ref={ref} 90 + className={cn( 91 + "text-xl font-semibold leading-none", 92 + className 93 + )} 94 + {...props} 95 + /> 96 + )); 97 + DialogTitle.displayName = DialogPrimitive.Title.displayName; 98 + 99 + const DialogDescription = React.forwardRef< 100 + React.ElementRef<typeof DialogPrimitive.Description>, 101 + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> 102 + >(({ className, ...props }, ref) => ( 103 + <DialogPrimitive.Description 104 + ref={ref} 105 + className={cn("text-sm text-muted-foreground", className)} 106 + {...props} 107 + /> 108 + )); 109 + DialogDescription.displayName = DialogPrimitive.Description.displayName; 110 + 111 + export { 112 + Dialog, 113 + DialogClose, 114 + DialogContent, 115 + DialogDescription, 116 + DialogFooter, 117 + DialogHeader, 118 + DialogOverlay, 119 + DialogPortal, 120 + DialogTitle, 121 + DialogTrigger 122 + };
+12 -4
components/ui/separator.tsx
··· 5 5 6 6 import { cn } from "@/utils/cn"; 7 7 8 + interface SeparatorProps extends React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> { 9 + loading?: boolean; 10 + } 11 + 8 12 const Separator = React.forwardRef< 9 13 React.ElementRef<typeof SeparatorPrimitive.Root>, 10 - React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> 14 + SeparatorProps 11 15 >( 12 16 ( 13 - { className, orientation = "horizontal", decorative = true, ...props }, 17 + { className, orientation = "horizontal", decorative = true, loading = false, ...props }, 14 18 ref 15 19 ) => ( 16 20 <SeparatorPrimitive.Root ··· 18 22 decorative={decorative} 19 23 orientation={orientation} 20 24 className={cn( 21 - "shrink-0 bg-separator/15", 25 + "shrink-0 bg-separator/15 relative overflow-hidden", 22 26 orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", 23 27 className 24 28 )} 25 29 {...props} 26 - /> 30 + > 31 + {loading && ( 32 + <div className="animate-progress w-full h-full bg-violet-500 origin-left-right" /> 33 + )} 34 + </SeparatorPrimitive.Root> 27 35 ) 28 36 ); 29 37 Separator.displayName = SeparatorPrimitive.Root.displayName;
+1
package.json
··· 22 22 "@radix-ui/react-avatar": "^1.1.10", 23 23 "@radix-ui/react-checkbox": "^1.3.2", 24 24 "@radix-ui/react-compose-refs": "1.1.2", 25 + "@radix-ui/react-dialog": "^1.1.14", 25 26 "@radix-ui/react-popover": "^1.1.14", 26 27 "@radix-ui/react-primitive": "2.1.3", 27 28 "@radix-ui/react-separator": "^1.1.7",
+14 -1
tailwind.config.js
··· 77 77 }, 78 78 fontSize: { 79 79 'xxs': '0.6rem' 80 - } 80 + }, 81 + animation: { 82 + progress: 'progress 1s infinite linear', 83 + }, 84 + keyframes: { 85 + progress: { 86 + '0%': { transform: ' translateX(0) scaleX(0)' }, 87 + '40%': { transform: 'translateX(0) scaleX(0.4)' }, 88 + '100%': { transform: 'translateX(100%) scaleX(0.5)' }, 89 + }, 90 + }, 91 + transformOrigin: { 92 + 'left-right': '0% 50%', 93 + } 81 94 } 82 95 }, 83 96 darkMode: ["class"],