@accelbyte/sdk 1.2.0 → 1.2.2

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 (38) hide show
  1. package/dist/cjs/node/index.node.js +11 -19
  2. package/dist/cjs/node/index.node.js.map +1 -1
  3. package/dist/es/browser/index.browser.js +11 -19
  4. package/dist/es/browser/index.browser.js.map +1 -1
  5. package/dist/es/node/index.node.js +11 -19
  6. package/dist/es/node/index.node.js.map +1 -1
  7. package/dist/index.d.ts +9 -15
  8. package/package.json +1 -1
  9. package/examples/next/README.md +0 -46
  10. package/examples/next/package.json +0 -22
  11. package/examples/next/pages/_app.tsx +0 -12
  12. package/examples/next/pages/_document.tsx +0 -19
  13. package/examples/next/pages/index.tsx +0 -124
  14. package/examples/next/public/favicon.ico +0 -0
  15. package/examples/next/public/next.svg +0 -1
  16. package/examples/next/public/thirteen.svg +0 -1
  17. package/examples/next/public/vercel.svg +0 -1
  18. package/examples/next/src/sdk.ts +0 -32
  19. package/examples/next/styles/Home.module.css +0 -274
  20. package/examples/next/styles/globals.css +0 -112
  21. package/examples/next/yarn.lock +0 -420
  22. package/examples/node/README.md +0 -29
  23. package/examples/node/index.js +0 -58
  24. package/examples/node/index.mjs +0 -56
  25. package/examples/node/package.json +0 -13
  26. package/examples/node/yarn.lock +0 -197
  27. package/examples/vite/README.md +0 -46
  28. package/examples/vite/index.html +0 -13
  29. package/examples/vite/package.json +0 -24
  30. package/examples/vite/public/vite.svg +0 -1
  31. package/examples/vite/src/App.css +0 -43
  32. package/examples/vite/src/App.tsx +0 -67
  33. package/examples/vite/src/Sdk.ts +0 -53
  34. package/examples/vite/src/assets/react.svg +0 -1
  35. package/examples/vite/src/index.css +0 -75
  36. package/examples/vite/src/main.tsx +0 -15
  37. package/examples/vite/src/vite-env.d.ts +0 -1
  38. package/examples/vite/yarn.lock +0 -890
package/dist/index.d.ts CHANGED
@@ -1,16 +1,6 @@
1
1
  import { Method, AxiosRequestConfig, AxiosInstance, AxiosResponse, AxiosError } from 'axios';
2
2
  import { z, ZodError } from 'zod';
3
3
 
4
- declare type Overrides = {
5
- config?: SDKRequestConfig;
6
- cache?: boolean;
7
- };
8
- declare type ServiceVersion = {
9
- title: string;
10
- name: string;
11
- version: string | undefined;
12
- buildDate: string;
13
- };
14
4
  interface ApiArgs {
15
5
  config?: SDKRequestConfig;
16
6
  namespace?: string;
@@ -55,13 +45,13 @@ declare class SDKError extends Error {
55
45
  */
56
46
  interface AccelbyteSDK {
57
47
  refreshTokens: (accessToken: string | undefined | null, refreshToken?: string | undefined | null) => void;
58
- assembly: (cache?: boolean) => {
48
+ assembly: () => {
59
49
  config: SDKRequestConfig<any>;
60
50
  namespace: string;
61
51
  clientId: string;
62
52
  redirectURI: string;
63
53
  baseURL: string;
64
- cache: boolean;
54
+ cache: boolean | undefined;
65
55
  };
66
56
  }
67
57
  declare const Accelbyte: {
@@ -159,11 +149,15 @@ declare type IResponseWithSync<D> = {
159
149
  onSync: (syncedData: (_: IResponse<D>) => void) => void;
160
150
  };
161
151
  declare class Validate {
162
- static responseType<D>(networkCall: () => Promise<AxiosResponse<D>>, Codec: z.ZodType<D>): Promise<IResponse<D>>;
152
+ static responseType<D>(networkCall: () => Promise<AxiosResponse<D>>, Codec: z.ZodType<D>, modelName: string): Promise<IResponse<D>>;
163
153
  static safeParse<D>(data: unknown, Codec: z.ZodType<D>): D | null;
164
154
  }
165
155
  declare class DecodeError extends Error {
166
- constructor(error: ZodError, response: AxiosResponse);
156
+ constructor({ error, response, modelName }: {
157
+ error: ZodError;
158
+ response: AxiosResponse;
159
+ modelName: string;
160
+ });
167
161
  }
168
162
 
169
163
  declare class SdkCache {
@@ -334,4 +328,4 @@ declare const injectAuthInterceptors: (clientId: string, getSDKConfig: () => Axi
334
328
 
335
329
  declare const injectErrorInterceptors: (baseUrl: string, onUserEligibilityChange?: (() => void) | undefined, onError?: ((error: AxiosError) => void) | undefined) => void;
336
330
 
337
- export { Accelbyte, AccelbyteSDK, ApiArgs, ApiUtils, BrowserHelper, CodeGenUtil, DecodeError, DesktopChecker, ERROR_CODE_LINK_DELETION_ACCOUNT, ERROR_CODE_TOKEN_EXPIRED, ERROR_LINK_ANOTHER_3RD_PARTY_ACCOUNT, ERROR_USER_BANNED, IDataStatus, IResponse, IResponseError, IResponseWithSync, Network, Overrides, RefreshSession, SDKEvents, SDKOptions, SDKRequestConfig, SdkCache, SdkDevice, ServiceVersion, UrlHelper, VALIDATION_ERROR_CODE, Validate, doRefreshSession, injectAuthInterceptors, injectErrorInterceptors, injectRequestInterceptors, injectResponseInterceptors, refreshWithLock };
331
+ export { Accelbyte, AccelbyteSDK, ApiArgs, ApiUtils, BrowserHelper, CodeGenUtil, DecodeError, DesktopChecker, ERROR_CODE_LINK_DELETION_ACCOUNT, ERROR_CODE_TOKEN_EXPIRED, ERROR_LINK_ANOTHER_3RD_PARTY_ACCOUNT, ERROR_USER_BANNED, IDataStatus, IResponse, IResponseError, IResponseWithSync, Network, RefreshSession, SDKEvents, SDKOptions, SDKRequestConfig, SdkCache, SdkDevice, UrlHelper, VALIDATION_ERROR_CODE, Validate, doRefreshSession, injectAuthInterceptors, injectErrorInterceptors, injectRequestInterceptors, injectResponseInterceptors, refreshWithLock };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@accelbyte/sdk",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "author": "AccelByte Inc",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "main": "./dist/cjs/node/index.cjs",
@@ -1,46 +0,0 @@
1
- # SDK Usage Example: Next.js
2
-
3
- This is a sample usage of SDK using [Next.js](https://nextjs.org).
4
-
5
- ## How to Run
6
-
7
- This folder should be ready to run without any changes as it is pointing to the [AccelByte's demo environment](https://demo.accelbyte.io) by default.
8
-
9
- ```sh
10
- # Install the dependencies.
11
- yarn install
12
-
13
- # Run the dev server.
14
- yarn dev
15
- ```
16
-
17
- After that, open http://localhost:3030. There will be few requests fired on the background, which then you could inspect the response by collapsing the `<details>` element.
18
-
19
- There will be also a `<details>` element with the title `currentUser`, which will contain your user information. By default, if you aren't logged in, then you will get `401 Unauthorized` in the network response.
20
-
21
- If you want to log in, you can click on the "Log in" button and it will redirect you to the Login website. After you submit with the valid credentials, you will be redirected back to http://localhost:3030 with some query parameters in it. These query parameters will be processed by this function `exchangeAuthorizationCode`, which will exchange the code passed in the query parameters to cookies.
22
-
23
- ## How to Point to Other Environments
24
-
25
- If you want to use this example folder for other environments, do these steps:
26
-
27
- 1. Change the [proxy target](https://github.com/AccelByte/accelbyte-web-sdk/blob/main/packages/sdk/examples/next/next.config.js#L8). It is required because otherwise during local development, we will be blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for some client side requests.
28
- 2. Change the [base URL, client ID, namespace, and redirect URI](https://github.com/AccelByte/accelbyte-web-sdk/blob/main/packages/sdk/examples/next/pages/index.tsx#L17-L20) of the SDK options. You can get these from Admin Portal's IAM Clients page. As for the redirect URI, ensure that it is a subset of the redirect URIs listed in the IAM Client.
29
-
30
- ## Production builds
31
-
32
- For production builds, please ensure that you have added conditionals to the `baseURL`. As mentioned in the section above, the default `baseURL` is the local development's origin with `/api` suffix to bypass CORS. However, we won't need it in production builds, because the default proxy server doesn't exist when we run in production mode.
33
-
34
- As such, what we can do is to have something like this:
35
-
36
- ```ts
37
- const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL
38
- const SDK_CONFIG = {
39
- baseURL: process.env.NODE_ENV === 'production' ? BASE_URL : 'http://localhost:3030/api',
40
- clientId: '77f88506b6174c3ea4d925f5b4096ce8',
41
- namespace: 'accelbyte',
42
- redirectURI: process.env.NODE_ENV === 'production' ? BASE_URL : 'http://localhost:3030'
43
- }
44
- ```
45
-
46
- So, when we are building for production, it will use `NEXT_PUBLIC_BASE_URL` environment variable instead of the `localhost:3030` one.
@@ -1,22 +0,0 @@
1
- {
2
- "name": "next",
3
- "version": "0.1.0",
4
- "private": true,
5
- "scripts": {
6
- "dev": "next dev -p 3030",
7
- "build": "next build",
8
- "start": "next start",
9
- "lint": "next lint"
10
- },
11
- "dependencies": {
12
- "@accelbyte/sdk": "1.1.3",
13
- "@next/font": "13.0.7",
14
- "@types/node": "18.11.17",
15
- "@types/react": "18.0.26",
16
- "@types/react-dom": "18.0.9",
17
- "next": "13.0.7",
18
- "react": "18.2.0",
19
- "react-dom": "18.2.0",
20
- "typescript": "4.9.4"
21
- }
22
- }
@@ -1,12 +0,0 @@
1
- /*
2
- * Copyright (c) 2018-2023 AccelByte Inc. All Rights Reserved
3
- * This is licensed software from AccelByte Inc, for limitations
4
- * and restrictions contact your company contract manager.
5
- */
6
- import '../styles/globals.css'
7
- import React from 'react'
8
- import type { AppProps } from 'next/app'
9
-
10
- export default function App({ Component, pageProps }: AppProps) {
11
- return <Component {...pageProps} />
12
- }
@@ -1,19 +0,0 @@
1
- /*
2
- * Copyright (c) 2018-2023 AccelByte Inc. All Rights Reserved
3
- * This is licensed software from AccelByte Inc, for limitations
4
- * and restrictions contact your company contract manager.
5
- */
6
- import React from 'react'
7
- import { Html, Head, Main, NextScript } from 'next/document'
8
-
9
- export default function Document() {
10
- return (
11
- <Html lang="en">
12
- <Head />
13
- <body>
14
- <Main />
15
- <NextScript />
16
- </body>
17
- </Html>
18
- )
19
- }
@@ -1,124 +0,0 @@
1
- /*
2
- * Copyright (c) 2018-2023 AccelByte Inc. All Rights Reserved
3
- * This is licensed software from AccelByte Inc, for limitations
4
- * and restrictions contact your company contract manager.
5
- */
6
- import React, { useEffect } from 'react'
7
- import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
8
- import Head from 'next/head'
9
- import Image from 'next/image'
10
- import { Accelbyte, CurrencyInfo, DiscoveryConfigData, ItemPagingSlicedResult, UserResponseV3 } from '@accelbyte/sdk'
11
- import { exchangeAuthorizationCode, login } from '~/sdk'
12
-
13
- import styles from '../styles/Home.module.css'
14
-
15
- const SDK_CONFIG = {
16
- baseURL: 'http://localhost:3030/api',
17
- clientId: '77f88506b6174c3ea4d925f5b4096ce8',
18
- namespace: 'accelbyte',
19
- redirectURI: 'http://localhost:3030'
20
- }
21
-
22
- const sdk = Accelbyte.SDK({
23
- options: SDK_CONFIG
24
- })
25
-
26
- interface TestSdkReturnType {
27
- currentUser: UserResponseV3 | null | undefined
28
- listDiscoveryConfigs: DiscoveryConfigData | null | undefined
29
- listOfCurrencies: CurrencyInfo[] | null | undefined
30
- listOfItems: ItemPagingSlicedResult | null | undefined
31
- }
32
-
33
- export const getServerSideProps: GetServerSideProps<{ data: TestSdkReturnType }> = async ({ req }) => {
34
- const accessToken = req.cookies.access_token
35
- const [currentUser, listDiscoveryConfigs, listOfCurrencies, listOfItems] = await Promise.all([
36
- sdk.IAM.User({
37
- config: {
38
- headers: {
39
- authorization: `Bearer ${accessToken}`
40
- }
41
- }
42
- }).getCurrentUser(),
43
- sdk.AccelbyteConfig.PublicTemplate().getDiscoveryTemplateConfigs(),
44
-
45
- sdk.Platform.Currency().getCurrencies(),
46
- sdk.Platform.Item().fetchItemsByCriteria({})
47
- ])
48
-
49
- return {
50
- props: {
51
- data: {
52
- currentUser: currentUser.response?.data || null,
53
- listDiscoveryConfigs: listDiscoveryConfigs.response?.data || null,
54
- listOfCurrencies: listOfCurrencies.response?.data || null,
55
- listOfItems: listOfItems.response?.data || null
56
- }
57
- }
58
- }
59
- }
60
-
61
- // Page.
62
- export default function Home({ data }: InferGetServerSidePropsType<typeof getServerSideProps>) {
63
- useEffect(() => {
64
- async function exchange() {
65
- const result = await exchangeAuthorizationCode(sdk, window.location.href)
66
- if (result) {
67
- // Reload so we can re-fetch the `currentUser` from the server side.
68
- window.location.reload()
69
- }
70
- }
71
-
72
- exchange()
73
- }, [])
74
-
75
- return (
76
- <>
77
- <Head>
78
- <title>Create Next App</title>
79
- <meta name="description" content="Generated by create next app" />
80
- <meta name="viewport" content="width=device-width, initial-scale=1" />
81
- <link rel="icon" href="/favicon.ico" />
82
- </Head>
83
- <main className={styles.main}>
84
- <div className={styles.description}>
85
- <p>
86
- Get started by editing&nbsp;
87
- <code className={styles.code}>pages/index.tsx</code>
88
- </p>
89
- <div>
90
- <a
91
- href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
92
- target="_blank"
93
- rel="noopener noreferrer">
94
- By <Image src="/vercel.svg" alt="Vercel Logo" className={styles.vercelLogo} width={100} height={24} priority />
95
- </a>
96
- </div>
97
- </div>
98
-
99
- {!data?.currentUser && (
100
- <div>
101
- <button onClick={() => login(sdk)}>Log in</button>
102
- </div>
103
- )}
104
-
105
- <div className={styles.responses} id="response">
106
- {Object.keys(data).map(key => (
107
- <Collapsible key={key} json={data[key as keyof TestSdkReturnType]} title={key} />
108
- ))}
109
- </div>
110
- </main>
111
- </>
112
- )
113
- }
114
-
115
- // composing components.
116
- function Collapsible(props: { title: string; json: any }) {
117
- return (
118
- <details id={'toogle' + props.title}>
119
- <summary>{props.title}</summary>
120
-
121
- <pre id={props.title}>{JSON.stringify(props.json, null, 2)}</pre>
122
- </details>
123
- )
124
- }
Binary file
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="40" height="31" fill="none"><g opacity=".9"><path fill="url(#a)" d="M13 .4v29.3H7V6.3h-.2L0 10.5V5L7.2.4H13Z"/><path fill="url(#b)" d="M28.8 30.1c-2.2 0-4-.3-5.7-1-1.7-.8-3-1.8-4-3.1a7.7 7.7 0 0 1-1.4-4.6h6.2c0 .8.3 1.4.7 2 .4.5 1 .9 1.7 1.2.7.3 1.6.4 2.5.4 1 0 1.7-.2 2.5-.5.7-.3 1.3-.8 1.7-1.4.4-.6.6-1.2.6-2s-.2-1.5-.7-2.1c-.4-.6-1-1-1.8-1.4-.8-.4-1.8-.5-2.9-.5h-2.7v-4.6h2.7a6 6 0 0 0 2.5-.5 4 4 0 0 0 1.7-1.3c.4-.6.6-1.3.6-2a3.5 3.5 0 0 0-2-3.3 5.6 5.6 0 0 0-4.5 0 4 4 0 0 0-1.7 1.2c-.4.6-.6 1.2-.6 2h-6c0-1.7.6-3.2 1.5-4.5 1-1.3 2.2-2.3 3.8-3C25 .4 26.8 0 28.8 0s3.8.4 5.3 1.1c1.5.7 2.7 1.7 3.6 3a7.2 7.2 0 0 1 1.2 4.2c0 1.6-.5 3-1.5 4a7 7 0 0 1-4 2.2v.2c2.2.3 3.8 1 5 2.2a6.4 6.4 0 0 1 1.6 4.6c0 1.7-.5 3.1-1.4 4.4a9.7 9.7 0 0 1-4 3.1c-1.7.8-3.7 1.1-5.8 1.1Z"/></g><defs><linearGradient id="a" x1="20" x2="20" y1="0" y2="30.1" gradientUnits="userSpaceOnUse"><stop/><stop offset="1" stop-color="#3D3D3D"/></linearGradient><linearGradient id="b" x1="20" x2="20" y1="0" y2="30.1" gradientUnits="userSpaceOnUse"><stop/><stop offset="1" stop-color="#3D3D3D"/></linearGradient></defs></svg>
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>
@@ -1,32 +0,0 @@
1
- /*
2
- * Copyright (c) 2023 AccelByte Inc. All Rights Reserved
3
- * This is licensed software from AccelByte Inc, for limitations
4
- * and restrictions contact your company contract manager.
5
- */
6
-
7
- import { AccelbyteSDK } from '@accelbyte/sdk'
8
-
9
- export function login(sdk: AccelbyteSDK) {
10
- const url = sdk.IAM.UserAuthorization().createLoginURL()
11
- window.location.replace(url)
12
- }
13
-
14
- export async function exchangeAuthorizationCode(sdk: AccelbyteSDK, url: string) {
15
- const searchParams = new URL(url).searchParams
16
- const { code, error, state } = Object.fromEntries(searchParams.entries())
17
- if (!code) return null
18
-
19
- try {
20
- const response = await sdk.IAM.UserAuthorization().exchangeAuthorizationCode({ code, error, state })
21
- window.history.pushState({}, '', window.location.origin)
22
-
23
- return {
24
- accessToken: response?.response?.data.access_token,
25
- refreshToken: response?.response?.data.refresh_token
26
- }
27
- } catch (err) {
28
- console.error(err)
29
- }
30
-
31
- return null
32
- }
@@ -1,274 +0,0 @@
1
- /*
2
- * Copyright (c) 2018-2023 AccelByte Inc. All Rights Reserved
3
- * This is licensed software from AccelByte Inc, for limitations
4
- * and restrictions contact your company contract manager.
5
- */
6
- .main {
7
- display: flex;
8
- flex-direction: column;
9
- justify-content: space-between;
10
- align-items: center;
11
- min-height: 100vh;
12
- }
13
-
14
- .description {
15
- display: inherit;
16
- justify-content: inherit;
17
- align-items: inherit;
18
- font-size: 0.85rem;
19
- max-width: var(--max-width);
20
- width: 100%;
21
- z-index: 2;
22
- font-family: var(--font-mono);
23
- }
24
-
25
- .description a {
26
- display: flex;
27
- justify-content: center;
28
- align-items: center;
29
- gap: 0.5rem;
30
- }
31
-
32
- .description p {
33
- position: relative;
34
- margin: 0;
35
- padding: 1rem;
36
- background-color: rgba(var(--callout-rgb), 0.5);
37
- border: 1px solid rgba(var(--callout-border-rgb), 0.3);
38
- border-radius: var(--border-radius);
39
- }
40
-
41
- .code {
42
- font-weight: 700;
43
- font-family: var(--font-mono);
44
- }
45
-
46
- .grid {
47
- display: grid;
48
- grid-template-columns: repeat(4, minmax(25%, auto));
49
- width: var(--max-width);
50
- max-width: 100%;
51
- }
52
-
53
- .card {
54
- padding: 1rem 1.2rem;
55
- border-radius: var(--border-radius);
56
- background: rgba(var(--card-rgb), 0);
57
- border: 1px solid rgba(var(--card-border-rgb), 0);
58
- transition: background 200ms, border 200ms;
59
- }
60
-
61
- .card span {
62
- display: inline-block;
63
- transition: transform 200ms;
64
- }
65
-
66
- .card h2 {
67
- font-weight: 600;
68
- margin-bottom: 0.7rem;
69
- }
70
-
71
- .card p {
72
- margin: 0;
73
- opacity: 0.6;
74
- font-size: 0.9rem;
75
- line-height: 1.5;
76
- max-width: 30ch;
77
- }
78
-
79
- .center {
80
- display: flex;
81
- justify-content: center;
82
- align-items: center;
83
- position: relative;
84
- padding: 4rem 0;
85
- }
86
-
87
- .center::before {
88
- background: var(--secondary-glow);
89
- border-radius: 50%;
90
- width: 480px;
91
- height: 360px;
92
- margin-left: -400px;
93
- }
94
-
95
- .center::after {
96
- background: var(--primary-glow);
97
- width: 240px;
98
- height: 180px;
99
- z-index: -1;
100
- }
101
-
102
- .center::before,
103
- .center::after {
104
- content: '';
105
- left: 50%;
106
- position: absolute;
107
- filter: blur(45px);
108
- transform: translateZ(0);
109
- }
110
-
111
- .logo,
112
- .thirteen {
113
- position: relative;
114
- }
115
-
116
- .thirteen {
117
- display: flex;
118
- justify-content: center;
119
- align-items: center;
120
- width: 75px;
121
- height: 75px;
122
- padding: 25px 10px;
123
- margin-left: 16px;
124
- transform: translateZ(0);
125
- border-radius: var(--border-radius);
126
- overflow: hidden;
127
- box-shadow: 0px 2px 8px -1px #0000001a;
128
- }
129
-
130
- .thirteen::before,
131
- .thirteen::after {
132
- content: '';
133
- position: absolute;
134
- z-index: -1;
135
- }
136
-
137
- /* Conic Gradient Animation */
138
- .thirteen::before {
139
- animation: 6s rotate linear infinite;
140
- width: 200%;
141
- height: 200%;
142
- background: var(--tile-border);
143
- }
144
-
145
- /* Inner Square */
146
- .thirteen::after {
147
- inset: 0;
148
- padding: 1px;
149
- border-radius: var(--border-radius);
150
- background: linear-gradient(to bottom right, rgba(var(--tile-start-rgb), 1), rgba(var(--tile-end-rgb), 1));
151
- background-clip: content-box;
152
- }
153
-
154
- /* Enable hover only on non-touch devices */
155
- @media (hover: hover) and (pointer: fine) {
156
- .card:hover {
157
- background: rgba(var(--card-rgb), 0.1);
158
- border: 1px solid rgba(var(--card-border-rgb), 0.15);
159
- }
160
-
161
- .card:hover span {
162
- transform: translateX(4px);
163
- }
164
- }
165
-
166
- @media (prefers-reduced-motion) {
167
- .thirteen::before {
168
- animation: none;
169
- }
170
-
171
- .card:hover span {
172
- transform: none;
173
- }
174
- }
175
-
176
- /* Mobile */
177
- @media (max-width: 700px) {
178
- .content {
179
- padding: 4rem;
180
- }
181
-
182
- .grid {
183
- grid-template-columns: 1fr;
184
- margin-bottom: 120px;
185
- max-width: 320px;
186
- text-align: center;
187
- }
188
-
189
- .card {
190
- padding: 1rem 2.5rem;
191
- }
192
-
193
- .card h2 {
194
- margin-bottom: 0.5rem;
195
- }
196
-
197
- .center {
198
- padding: 8rem 0 6rem;
199
- }
200
-
201
- .center::before {
202
- transform: none;
203
- height: 300px;
204
- }
205
-
206
- .description {
207
- font-size: 0.8rem;
208
- }
209
-
210
- .description a {
211
- padding: 1rem;
212
- }
213
-
214
- .description p,
215
- .description div {
216
- display: flex;
217
- justify-content: center;
218
- position: fixed;
219
- width: 100%;
220
- }
221
-
222
- .description p {
223
- align-items: center;
224
- inset: 0 0 auto;
225
- padding: 2rem 1rem 1.4rem;
226
- border-radius: 0;
227
- border: none;
228
- border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
229
- background: linear-gradient(to bottom, rgba(var(--background-start-rgb), 1), rgba(var(--callout-rgb), 0.5));
230
- background-clip: padding-box;
231
- backdrop-filter: blur(24px);
232
- }
233
-
234
- .description div {
235
- align-items: flex-end;
236
- pointer-events: none;
237
- inset: auto 0 0;
238
- padding: 2rem;
239
- height: 200px;
240
- background: linear-gradient(to bottom, transparent 0%, rgb(var(--background-end-rgb)) 40%);
241
- z-index: 1;
242
- }
243
- }
244
-
245
- /* Tablet and Smaller Desktop */
246
- @media (min-width: 701px) and (max-width: 1120px) {
247
- .grid {
248
- grid-template-columns: repeat(2, 50%);
249
- }
250
- }
251
-
252
- @media (prefers-color-scheme: dark) {
253
- .vercelLogo {
254
- filter: invert(1);
255
- }
256
-
257
- .logo,
258
- .thirteen img {
259
- filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
260
- }
261
- }
262
-
263
- @keyframes rotate {
264
- from {
265
- transform: rotate(360deg);
266
- }
267
- to {
268
- transform: rotate(0deg);
269
- }
270
- }
271
-
272
- .responses {
273
- width: 100%;
274
- }