+1
.gitignore
+1
.gitignore
+39
-5
README.md
+39
-5
README.md
···
1
# Red Dwarf
2
Red Dwarf is a Bluesky client that does not use any AppView servers, instead it gathers the data from [Constellation](https://constellation.microcosm.blue/) and each users' PDS.
3
4
-

5
6
huge thanks to [Microcosm](https://microcosm.blue/) for making this possible
7
8
## useQuery
9
Red Dwarf has been upgraded from its original bespoke caching system to Tanstack Query (react query). this migration was done to achieve a more robust and maintainable approach to data fetching and caching and state synchronization. ive seen serious performance gains from this switch!
10
···
22
### Slingshot
23
though Red Dwarf was made before Microcosm [Slingshot](https://slingshot.microcosm.blue) existed, it now uses Slingshot to reduce load from each respective PDS server. Slignshot
24
25
-
## PassAuthProvider
26
-
a really bad app-password auth provider, inherited from TestFront and used in all my projects from TestFront to ForumTest (im very good at naming things). in ForumTest, its been superseded by the [OAuthProvider](https://tangled.sh/@whey.party/forumtest/blob/main/src/providers/OAuthProvider.tsx). i havent backported it here and maybe soon, although oauth makes it slightly more annoying to do development because it requires a tunnel so maybe someday if i managed to merge the password and oauth logins to provide both options
27
28
## Custom Feeds
29
they work, but i havent implemented a simple way of viewing arbitraty feeds. currently it either loads discover (logged out) or your saved feeds (logged in) and its not a technical limitation i just havent implemented it yet
···
36
and for list feeds, you can just use something like graze or skyfeed to input a list of users and output a custom feed
37
38
## Tanstack Router
39
-
it does the job, nothing very specific was used here
40
41
-
im planning to use the loader system on select pages to prevent loss of scroll positon and state though its really complex so i havent done it yet but the migration to tanstack query is a huge first step towards this goal
···
1
# Red Dwarf
2
Red Dwarf is a Bluesky client that does not use any AppView servers, instead it gathers the data from [Constellation](https://constellation.microcosm.blue/) and each users' PDS.
3
4
+

5
6
huge thanks to [Microcosm](https://microcosm.blue/) for making this possible
7
8
+
## running dev and build
9
+
in the `vite.config.ts` file you should change these values
10
+
```ts
11
+
const PROD_URL = "https://reddwarf.app"
12
+
const DEV_URL = "https://local3768forumtest.whey.party"
13
+
```
14
+
the PROD_URL is what will compile your oauth client metadata so it is very important to change that. same for DEV_URL if you are using a tunnel for dev work
15
+
16
+
run dev with `npm run dev` (port 3768) and build with `npm run build` (the output is the `dist` folder)
17
+
18
## useQuery
19
Red Dwarf has been upgraded from its original bespoke caching system to Tanstack Query (react query). this migration was done to achieve a more robust and maintainable approach to data fetching and caching and state synchronization. ive seen serious performance gains from this switch!
20
···
32
### Slingshot
33
though Red Dwarf was made before Microcosm [Slingshot](https://slingshot.microcosm.blue) existed, it now uses Slingshot to reduce load from each respective PDS server. Slignshot
34
35
+
## UnifiedAuthProvider
36
+
a merged auth provider with oauth and password based login. oauth makes it slightly more annoying to do development because it requires a tunnel, so so the password auth option is still here if you do prefer password login for whatever reason.
37
+
38
+
### Pass Auth
39
+
a really bad app-password auth provider, inherited from TestFront and used in all my projects from TestFront to ForumTest (im very good at naming things).
40
+
41
+
### OAuth
42
+
taken from ForumTest [OAuthProvider](https://tangled.sh/@whey.party/forumtest/blob/main/src/providers/OAuthProvider.tsx)
43
44
## Custom Feeds
45
they work, but i havent implemented a simple way of viewing arbitraty feeds. currently it either loads discover (logged out) or your saved feeds (logged in) and its not a technical limitation i just havent implemented it yet
···
52
and for list feeds, you can just use something like graze or skyfeed to input a list of users and output a custom feed
53
54
## Tanstack Router
55
+
something specific was used here
56
+
57
+
so tanstack router is used as the base, but the home route is using tanstack-router-keepalive to preserve the route for better responsiveness, and it also saves scroll position of feeds into jotai (persistent)
58
+
59
+
i previously used a tanstack router loader to ensure the tanstack query cache is ready to prevent scroll jumps but it is way too slow so i replaced it with tanstack-router-keepalive
60
+
61
+
## Icons
62
+
this project uses Material icons. do not the light variant. sometimes i use `Mdi` if the icon needed doesnt exist in `MaterialSymbols`
63
64
+
the project uses unplugin icon auto import, so you can just use the component and itll just work!
65
+
66
+
the format is:
67
+
```tsx
68
+
<IconMaterialSymbols{icon name here} />
69
+
// or
70
+
<IconMdi{icon name here} />
71
+
```
72
+
73
+
you can get the full list of icon names from iconify ([Material Symbols](https://icon-sets.iconify.design/material-symbols/) or [MDI](https://icon-sets.iconify.design/mdi/))
74
+
75
+
while it is nice to keep everything consistent by using material icons, if the icon you need is not provided by either material symbols nor mdi, you are allowed to just grab any icon from any pack (please do prioritize icons that fit in)
+59
eslint.config.ts
+59
eslint.config.ts
···
···
1
+
import eslintJs from "@eslint/js";
2
+
import eslintReact from "@eslint-react/eslint-plugin";
3
+
import { defineConfig } from "eslint/config";
4
+
import reactHooks from "eslint-plugin-react-hooks";
5
+
import simpleImportSort from "eslint-plugin-simple-import-sort";
6
+
import unusedImports from "eslint-plugin-unused-imports";
7
+
import tseslint from "typescript-eslint";
8
+
9
+
export default defineConfig([
10
+
{
11
+
files: ["**/*.ts", "**/*.tsx"],
12
+
extends: [
13
+
eslintJs.configs.recommended,
14
+
tseslint.configs.recommended,
15
+
eslintReact.configs["recommended-typescript"],
16
+
reactHooks.configs.flat["recommended-latest"],
17
+
],
18
+
plugins: {
19
+
"react-hooks": reactHooks,
20
+
"simple-import-sort": simpleImportSort,
21
+
"unused-imports": unusedImports,
22
+
},
23
+
languageOptions: {
24
+
parser: tseslint.parser,
25
+
parserOptions: {
26
+
projectService: true,
27
+
tsconfigRootDir: import.meta.dirname,
28
+
},
29
+
},
30
+
rules: {
31
+
// Unused imports
32
+
"unused-imports/no-unused-imports": "error",
33
+
"unused-imports/no-unused-vars": [
34
+
"warn",
35
+
{
36
+
vars: "all",
37
+
varsIgnorePattern: "^_",
38
+
args: "after-used",
39
+
argsIgnorePattern: "^_",
40
+
},
41
+
],
42
+
43
+
// Auto sort imports
44
+
"simple-import-sort/imports": "error",
45
+
"simple-import-sort/exports": "error",
46
+
47
+
48
+
"@typescript-eslint/no-unused-vars": [
49
+
"warn",
50
+
{
51
+
argsIgnorePattern: "^_",
52
+
varsIgnorePattern: "^_",
53
+
caughtErrorsIgnorePattern: "^_",
54
+
},
55
+
],
56
+
"@typescript-eslint/no-explicit-any": "warn",
57
+
},
58
+
},
59
+
]);
+1
-2
index.html
+1
-2
index.html
···
4
<meta charset="UTF-8" />
5
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
<link rel="icon" href="/favicon.ico" />
7
-
<meta name="theme-color" content="#000000" />
8
<meta
9
name="description"
10
content="an appview-less Bluesky client using Constellation and PDS Queries"
11
/>
12
<link rel="apple-touch-icon" href="/redstar.png" />
13
<link rel="manifest" href="/manifest.json" />
14
-
<link rel="stylesheet" href="/src/styles/app.css" />
15
<title>Red Dwarf</title>
16
</head>
17
<body>
···
4
<meta charset="UTF-8" />
5
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
<link rel="icon" href="/favicon.ico" />
7
+
<meta name="theme-color" content="#180001" />
8
<meta
9
name="description"
10
content="an appview-less Bluesky client using Constellation and PDS Queries"
11
/>
12
<link rel="apple-touch-icon" href="/redstar.png" />
13
<link rel="manifest" href="/manifest.json" />
14
<title>Red Dwarf</title>
15
</head>
16
<body>
+48
oauthdev.mts
+48
oauthdev.mts
···
···
1
+
import fs from 'fs';
2
+
import path from 'path';
3
+
//import { generateClientMetadata } from './src/helpers/oauthClient'
4
+
export const generateClientMetadata = (appOrigin: string) => {
5
+
const callbackPath = '/callback';
6
+
7
+
return {
8
+
"client_id": `${appOrigin}/client-metadata.json`,
9
+
"client_name": "ForumTest",
10
+
"client_uri": appOrigin,
11
+
"logo_uri": `${appOrigin}/logo192.png`,
12
+
"tos_uri": `${appOrigin}/terms-of-service`,
13
+
"policy_uri": `${appOrigin}/privacy-policy`,
14
+
"redirect_uris": [`${appOrigin}${callbackPath}`] as [string, ...string[]],
15
+
"scope": "atproto transition:generic",
16
+
"grant_types": ["authorization_code", "refresh_token"] as ["authorization_code", "refresh_token"],
17
+
"response_types": ["code"] as ["code"],
18
+
"token_endpoint_auth_method": "none" as "none",
19
+
"application_type": "web" as "web",
20
+
"dpop_bound_access_tokens": true
21
+
};
22
+
}
23
+
24
+
25
+
export function generateMetadataPlugin({prod, dev}:{prod: string, dev: string}) {
26
+
return {
27
+
name: 'vite-plugin-generate-metadata',
28
+
config(_config: any, { mode }: any) {
29
+
let appOrigin;
30
+
if (mode === 'production') {
31
+
appOrigin = prod
32
+
if (!appOrigin || !appOrigin.startsWith('https://')) {
33
+
throw new Error('VITE_APP_ORIGIN environment variable must be set to a valid HTTPS URL for production build.');
34
+
}
35
+
} else {
36
+
appOrigin = dev;
37
+
}
38
+
39
+
40
+
const metadata = generateClientMetadata(appOrigin);
41
+
const outputPath = path.resolve(process.cwd(), 'public', 'client-metadata.json');
42
+
43
+
fs.writeFileSync(outputPath, JSON.stringify(metadata, null, 2));
44
+
45
+
// /*mass comment*/ console.log(`โ
Generated client-metadata.json for ${appOrigin}`);
46
+
},
47
+
};
48
+
}
+9033
-32
package-lock.json
+9033
-32
package-lock.json
···
7
"name": "red-dwarf-tanstack",
8
"dependencies": {
9
"@atproto/api": "^0.16.6",
10
"@tailwindcss/vite": "^4.0.6",
11
"@tanstack/react-devtools": "^0.2.2",
12
"@tanstack/react-query": "^5.85.6",
13
"@tanstack/react-router": "^1.130.2",
14
"@tanstack/react-router-devtools": "^1.131.5",
15
"@tanstack/router-plugin": "^1.121.2",
16
"idb-keyval": "^6.2.2",
17
"jotai": "^2.13.1",
18
"react": "^19.0.0",
19
"react-dom": "^19.0.0",
20
"react-player": "^3.3.2",
21
-
"tailwindcss": "^4.0.6"
22
},
23
"devDependencies": {
24
"@testing-library/dom": "^10.4.0",
25
"@testing-library/react": "^16.2.0",
26
"@types/node": "^24.3.0",
27
"@types/react": "^19.0.8",
28
"@types/react-dom": "^19.0.3",
29
"@vitejs/plugin-react": "^4.3.4",
30
"jsdom": "^26.0.0",
31
"prettier": "^3.6.2",
32
"typescript": "^5.7.2",
33
"vite": "^6.3.5",
34
"vitest": "^3.0.5",
35
"web-vitals": "^4.2.4"
···
46
},
47
"engines": {
48
"node": ">=6.0.0"
49
}
50
},
51
"node_modules/@asamuzakjp/css-color": {
···
69
"dev": true,
70
"license": "ISC"
71
},
72
"node_modules/@atproto/api": {
73
"version": "0.16.6",
74
"resolved": "https://registry.npmjs.org/@atproto/api/-/api-0.16.6.tgz",
···
86
}
87
},
88
"node_modules/@atproto/common-web": {
89
-
"version": "0.4.2",
90
-
"resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.4.2.tgz",
91
-
"integrity": "sha512-vrXwGNoFGogodjQvJDxAeP3QbGtawgZute2ed1XdRO0wMixLk3qewtikZm06H259QDJVu6voKC5mubml+WgQUw==",
92
"license": "MIT",
93
"dependencies": {
94
"graphemer": "^1.4.0",
···
97
"zod": "^3.23.8"
98
}
99
},
100
"node_modules/@atproto/lexicon": {
101
-
"version": "0.5.0",
102
-
"resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.5.0.tgz",
103
-
"integrity": "sha512-3aAzEAy9EAPs3CxznzMhEcqDd7m3vz1eze/ya9/ThbB7yleqJIhz5GY2q76tCCwHPhn5qDDMhlA9kKV6fG23gA==",
104
"license": "MIT",
105
"dependencies": {
106
-
"@atproto/common-web": "^0.4.2",
107
"@atproto/syntax": "^0.4.1",
108
"iso-datestring-validator": "^2.2.2",
109
"multiformats": "^9.9.0",
110
"zod": "^3.23.8"
111
}
112
},
113
"node_modules/@atproto/syntax": {
114
"version": "0.4.1",
115
"resolved": "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.4.1.tgz",
···
117
"license": "MIT"
118
},
119
"node_modules/@atproto/xrpc": {
120
-
"version": "0.7.4",
121
-
"resolved": "https://registry.npmjs.org/@atproto/xrpc/-/xrpc-0.7.4.tgz",
122
-
"integrity": "sha512-sDi68+QE1XHegTaNAndlX41Gp827pouSzSs8CyAwhrqZdsJUxE3P7TMtrA0z+zAjvxVyvzscRc0TsN/fGUGrhw==",
123
"license": "MIT",
124
"dependencies": {
125
-
"@atproto/lexicon": "^0.5.0",
126
"zod": "^3.23.8"
127
}
128
},
···
1104
"node": ">=18"
1105
}
1106
},
1107
"node_modules/@isaacs/fs-minipass": {
1108
"version": "4.0.1",
1109
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
···
1229
"mux-embed": "^5.8.3"
1230
}
1231
},
1232
"node_modules/@rolldown/pluginutils": {
1233
"version": "1.0.0-beta.27",
1234
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
···
1543
"solid-js": "^1.6.12"
1544
}
1545
},
1546
"node_modules/@svta/common-media-library": {
1547
"version": "0.12.4",
1548
"resolved": "https://registry.npmjs.org/@svta/common-media-library/-/common-media-library-0.12.4.tgz",
···
1894
"url": "https://github.com/sponsors/tannerlinsley"
1895
}
1896
},
1897
"node_modules/@tanstack/react-devtools": {
1898
"version": "0.2.2",
1899
"resolved": "https://registry.npmjs.org/@tanstack/react-devtools/-/react-devtools-0.2.2.tgz",
···
1929
"url": "https://github.com/sponsors/tannerlinsley"
1930
},
1931
"peerDependencies": {
1932
"react": "^18 || ^19"
1933
}
1934
},
···
2290
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
2291
"license": "MIT"
2292
},
2293
"node_modules/@types/node": {
2294
"version": "24.3.0",
2295
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz",
···
2318
"@types/react": "^19.0.0"
2319
}
2320
},
2321
"node_modules/@vercel/edge": {
2322
"version": "1.2.2",
2323
"resolved": "https://registry.npmjs.org/@vercel/edge/-/edge-1.2.2.tgz",
···
2482
"node": ">=0.4.0"
2483
}
2484
},
2485
"node_modules/agent-base": {
2486
"version": "7.1.4",
2487
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
···
2492
"node": ">= 14"
2493
}
2494
},
2495
"node_modules/ansi-regex": {
2496
"version": "5.0.1",
2497
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
···
2537
"node": ">= 8"
2538
}
2539
},
2540
"node_modules/aria-query": {
2541
"version": "5.3.0",
2542
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
···
2547
"dequal": "^2.0.3"
2548
}
2549
},
2550
"node_modules/assertion-error": {
2551
"version": "2.0.1",
2552
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
···
2569
"node": ">=4"
2570
}
2571
},
2572
"node_modules/await-lock": {
2573
"version": "2.2.2",
2574
"resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz",
···
2586
"@babel/traverse": "^7.23.7",
2587
"@babel/types": "^7.23.6"
2588
}
2589
},
2590
"node_modules/bcp-47": {
2591
"version": "2.1.0",
···
2638
"url": "https://github.com/sponsors/sindresorhus"
2639
}
2640
},
2641
"node_modules/braces": {
2642
"version": "3.0.3",
2643
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
···
2692
"node": ">=8"
2693
}
2694
},
2695
"node_modules/caniuse-lite": {
2696
"version": "1.0.30001737",
2697
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001737.tgz",
···
2747
"node": ">=18"
2748
}
2749
},
2750
"node_modules/check-error": {
2751
"version": "2.1.1",
2752
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
···
2811
"integrity": "sha512-eNk3TRV+xQMJ1PEj0FQGY8KD4m0GPxT487XJ+Iftm7mVa9WpPFDMWqPt+46buiP5j5Wzqe5oMIhqBcAeKfygSA==",
2812
"license": "MIT"
2813
},
2814
"node_modules/convert-source-map": {
2815
"version": "2.0.0",
2816
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
···
2823
"integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==",
2824
"license": "MIT"
2825
},
2826
"node_modules/cssstyle": {
2827
"version": "4.6.0",
2828
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz",
···
2891
"node": ">=18"
2892
}
2893
},
2894
"node_modules/debug": {
2895
-
"version": "4.4.1",
2896
-
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
2897
-
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
2898
"license": "MIT",
2899
"dependencies": {
2900
"ms": "^2.1.3"
···
2925
"node": ">=6"
2926
}
2927
},
2928
"node_modules/dequal": {
2929
"version": "2.0.3",
2930
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
···
2944
"node": ">=8"
2945
}
2946
},
2947
"node_modules/diff": {
2948
"version": "8.0.2",
2949
"resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz",
···
2953
"node": ">=0.3.1"
2954
}
2955
},
2956
"node_modules/dom-accessibility-api": {
2957
"version": "0.5.16",
2958
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
···
2960
"dev": true,
2961
"license": "MIT"
2962
},
2963
"node_modules/electron-to-chromium": {
2964
"version": "1.5.211",
2965
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.211.tgz",
···
2992
"url": "https://github.com/fb55/entities?sponsor=1"
2993
}
2994
},
2995
"node_modules/es-module-lexer": {
2996
"version": "1.7.0",
2997
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
···
2999
"dev": true,
3000
"license": "MIT"
3001
},
3002
"node_modules/esbuild": {
3003
"version": "0.25.9",
3004
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
···
3049
"node": ">=6"
3050
}
3051
},
3052
"node_modules/esprima": {
3053
"version": "4.0.1",
3054
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
···
3062
"node": ">=4"
3063
}
3064
},
3065
"node_modules/estree-walker": {
3066
"version": "3.0.3",
3067
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
···
3072
"@types/estree": "^1.0.0"
3073
}
3074
},
3075
"node_modules/expect-type": {
3076
"version": "1.2.2",
3077
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz",
···
3082
"node": ">=12.0.0"
3083
}
3084
},
3085
"node_modules/fast-deep-equal": {
3086
"version": "3.1.3",
3087
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
3088
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
3089
"license": "MIT"
3090
},
3091
"node_modules/fill-range": {
3092
"version": "7.1.1",
3093
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
···
3100
"node": ">=8"
3101
}
3102
},
3103
"node_modules/fsevents": {
3104
"version": "2.3.3",
3105
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
···
3114
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
3115
}
3116
},
3117
"node_modules/gensync": {
3118
"version": "1.0.0-beta.2",
3119
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
···
3123
"node": ">=6.9.0"
3124
}
3125
},
3126
"node_modules/get-tsconfig": {
3127
"version": "4.10.1",
3128
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz",
···
3147
"node": ">= 6"
3148
}
3149
},
3150
"node_modules/goober": {
3151
"version": "2.1.16",
3152
"resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz",
···
3156
"csstype": "^3.0.10"
3157
}
3158
},
3159
"node_modules/graceful-fs": {
3160
"version": "4.2.11",
3161
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
···
3168
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
3169
"license": "MIT"
3170
},
3171
"node_modules/hls-video-element": {
3172
"version": "1.5.7",
3173
"resolved": "https://registry.npmjs.org/hls-video-element/-/hls-video-element-1.5.7.tgz",
···
3242
"node": ">= 14"
3243
}
3244
},
3245
"node_modules/iconv-lite": {
3246
"version": "0.6.3",
3247
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
···
3261
"integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==",
3262
"license": "Apache-2.0"
3263
},
3264
"node_modules/immediate": {
3265
"version": "3.0.6",
3266
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
3267
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
3268
"license": "MIT"
3269
},
3270
"node_modules/imsc": {
3271
"version": "1.1.5",
3272
"resolved": "https://registry.npmjs.org/imsc/-/imsc-1.1.5.tgz",
···
3276
"sax": "1.2.1"
3277
}
3278
},
3279
"node_modules/is-alphabetical": {
3280
"version": "2.0.1",
3281
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
···
3300
"url": "https://github.com/sponsors/wooorm"
3301
}
3302
},
3303
"node_modules/is-binary-path": {
3304
"version": "2.1.0",
3305
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
···
3312
"node": ">=8"
3313
}
3314
},
3315
"node_modules/is-decimal": {
3316
"version": "2.0.1",
3317
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
···
3331
"node": ">=0.10.0"
3332
}
3333
},
3334
"node_modules/is-glob": {
3335
"version": "4.0.3",
3336
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
···
3343
"node": ">=0.10.0"
3344
}
3345
},
3346
"node_modules/is-number": {
3347
"version": "7.0.0",
3348
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
···
3352
"node": ">=0.12.0"
3353
}
3354
},
3355
"node_modules/is-potential-custom-element-name": {
3356
"version": "1.0.1",
3357
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
···
3359
"dev": true,
3360
"license": "MIT"
3361
},
3362
"node_modules/isbot": {
3363
"version": "5.1.30",
3364
"resolved": "https://registry.npmjs.org/isbot/-/isbot-5.1.30.tgz",
···
3368
"node": ">=18"
3369
}
3370
},
3371
"node_modules/iso-datestring-validator": {
3372
"version": "2.2.2",
3373
"resolved": "https://registry.npmjs.org/iso-datestring-validator/-/iso-datestring-validator-2.2.2.tgz",
3374
"integrity": "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==",
3375
"license": "MIT"
3376
},
3377
"node_modules/jiti": {
3378
"version": "2.5.1",
3379
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
···
3381
"license": "MIT",
3382
"bin": {
3383
"jiti": "lib/jiti-cli.mjs"
3384
}
3385
},
3386
"node_modules/jotai": {
···
3418
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
3419
"license": "MIT"
3420
},
3421
"node_modules/jsdom": {
3422
"version": "26.1.0",
3423
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz",
···
3470
"node": ">=6"
3471
}
3472
},
3473
"node_modules/json5": {
3474
"version": "2.2.3",
3475
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
···
3482
"node": ">=6"
3483
}
3484
},
3485
"node_modules/lie": {
3486
"version": "3.1.1",
3487
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
···
3719
"url": "https://opencollective.com/parcel"
3720
}
3721
},
3722
"node_modules/localforage": {
3723
"version": "1.10.0",
3724
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
···
3728
"lie": "3.1.1"
3729
}
3730
},
3731
"node_modules/loose-envify": {
3732
"version": "1.4.0",
3733
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
···
3747
"dev": true,
3748
"license": "MIT"
3749
},
3750
"node_modules/lru-cache": {
3751
"version": "5.1.1",
3752
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
···
3767
}
3768
},
3769
"node_modules/magic-string": {
3770
-
"version": "0.30.18",
3771
-
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz",
3772
-
"integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==",
3773
"license": "MIT",
3774
"dependencies": {
3775
"@jridgewell/sourcemap-codec": "^1.5.5"
3776
}
3777
},
3778
"node_modules/media-chrome": {
···
3791
"integrity": "sha512-9P2FuUHnZZ3iji+2RQk7Zkh5AmZTnOG5fODACnjhCVveX1McY3jmCRHofIEI+yTBqplz7LXy48c7fQ3Uigp88w==",
3792
"license": "MIT"
3793
},
3794
"node_modules/minipass": {
3795
"version": "7.1.2",
3796
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
···
3827
"url": "https://github.com/sponsors/isaacs"
3828
}
3829
},
3830
"node_modules/ms": {
3831
"version": "2.1.3",
3832
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
···
3869
"integrity": "sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==",
3870
"license": "MIT"
3871
},
3872
"node_modules/node-releases": {
3873
"version": "2.0.19",
3874
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
···
3884
"node": ">=0.10.0"
3885
}
3886
},
3887
"node_modules/nwsapi": {
3888
"version": "2.2.21",
3889
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.21.tgz",
···
3900
"node": ">=0.10.0"
3901
}
3902
},
3903
"node_modules/parse5": {
3904
"version": "7.3.0",
3905
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
···
3919
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
3920
"license": "MIT"
3921
},
3922
"node_modules/pathe": {
3923
"version": "2.0.3",
3924
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
···
3954
"url": "https://github.com/sponsors/jonschlinkert"
3955
}
3956
},
3957
"node_modules/player.style": {
3958
"version": "0.1.10",
3959
"resolved": "https://registry.npmjs.org/player.style/-/player.style-0.1.10.tgz",
···
3970
"media-chrome": "~4.11.0"
3971
}
3972
},
3973
"node_modules/postcss": {
3974
"version": "8.5.6",
3975
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
···
3998
"node": "^10 || ^12 || >=14"
3999
}
4000
},
4001
"node_modules/prettier": {
4002
"version": "3.6.2",
4003
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
···
4055
"node": ">=6"
4056
}
4057
},
4058
"node_modules/react": {
4059
"version": "19.1.1",
4060
"resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
···
4116
"node": ">=0.10.0"
4117
}
4118
},
4119
"node_modules/readdirp": {
4120
"version": "3.6.0",
4121
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
···
4153
"node": ">=0.10.0"
4154
}
4155
},
4156
"node_modules/resolve-pkg-maps": {
4157
"version": "1.0.0",
4158
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
···
4162
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
4163
}
4164
},
4165
"node_modules/rollup": {
4166
"version": "4.49.0",
4167
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.49.0.tgz",
···
4208
"dev": true,
4209
"license": "MIT"
4210
},
4211
"node_modules/safer-buffer": {
4212
"version": "2.1.2",
4213
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
···
4240
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
4241
"license": "MIT"
4242
},
4243
"node_modules/semver": {
4244
"version": "6.3.1",
4245
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
···
4270
"seroval": "^1.0"
4271
}
4272
},
4273
"node_modules/siginfo": {
4274
"version": "2.0.0",
4275
"resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
···
4277
"dev": true,
4278
"license": "ISC"
4279
},
4280
"node_modules/solid-js": {
4281
"version": "1.9.9",
4282
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.9.tgz",
···
4326
"dev": true,
4327
"license": "MIT"
4328
},
4329
"node_modules/strip-literal": {
4330
-
"version": "3.0.0",
4331
-
"resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz",
4332
-
"integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==",
4333
"dev": true,
4334
"license": "MIT",
4335
"dependencies": {
···
4352
"integrity": "sha512-9pP/CVNp4NF2MNlRzLwQkjiTgKKe9WYXrLh9+8QokWmMxz+zt2mf1utkWLco26IuA3AfVcTb//qtlTIjY3VHxA==",
4353
"license": "MIT"
4354
},
4355
"node_modules/symbol-tree": {
4356
"version": "3.2.4",
4357
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
···
4364
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.12.tgz",
4365
"integrity": "sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==",
4366
"license": "MIT"
4367
},
4368
"node_modules/tapable": {
4369
"version": "2.2.3",
···
4437
"license": "MIT"
4438
},
4439
"node_modules/tinyglobby": {
4440
-
"version": "0.2.14",
4441
-
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
4442
-
"integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
4443
"license": "MIT",
4444
"dependencies": {
4445
-
"fdir": "^6.4.4",
4446
-
"picomatch": "^4.0.2"
4447
},
4448
"engines": {
4449
"node": ">=12.0.0"
···
4578
"node": ">=18"
4579
}
4580
},
4581
"node_modules/tslib": {
4582
"version": "2.8.1",
4583
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
···
4609
"integrity": "sha512-SDpZ4f7sZmwHF6XG5PF0KWuP18pH/kNG04MhTcpqJby7Lk/D3TS/lCYd+RSg0rIAAVi1LDgSIo1yJs9kmHlhgw==",
4610
"license": "MIT"
4611
},
4612
"node_modules/typescript": {
4613
-
"version": "5.9.2",
4614
-
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
4615
-
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
4616
"dev": true,
4617
"license": "Apache-2.0",
4618
"bin": {
···
4623
"node": ">=14.17"
4624
}
4625
},
4626
"node_modules/ua-parser-js": {
4627
"version": "1.0.41",
4628
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz",
···
4649
"node": "*"
4650
}
4651
},
4652
"node_modules/uint8arrays": {
4653
"version": "3.0.0",
4654
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz",
···
4658
"multiformats": "^9.4.2"
4659
}
4660
},
4661
"node_modules/undici-types": {
4662
"version": "7.10.0",
4663
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
···
4665
"devOptional": true,
4666
"license": "MIT"
4667
},
4668
"node_modules/unplugin": {
4669
-
"version": "2.3.9",
4670
-
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.9.tgz",
4671
-
"integrity": "sha512-2dcbZq6aprwXTkzptq3k5qm5B8cvpjG9ynPd5fyM2wDJuuF7PeUK64Sxf0d+X1ZyDOeGydbNzMqBSIVlH8GIfA==",
4672
"license": "MIT",
4673
"dependencies": {
4674
"@jridgewell/remapping": "^2.3.5",
···
4680
"node": ">=18.12.0"
4681
}
4682
},
4683
"node_modules/unplugin/node_modules/picomatch": {
4684
"version": "4.0.3",
4685
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
···
4720
},
4721
"peerDependencies": {
4722
"browserslist": ">= 4.21.0"
4723
}
4724
},
4725
"node_modules/use-sync-external-store": {
···
5034
"node": ">=18"
5035
}
5036
},
5037
"node_modules/why-is-node-running": {
5038
"version": "2.3.0",
5039
"resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
···
5060
"super-media-element": "~1.4.2"
5061
}
5062
},
5063
"node_modules/ws": {
5064
"version": "8.18.3",
5065
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
···
5104
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
5105
"license": "ISC"
5106
},
5107
"node_modules/youtube-video-element": {
5108
"version": "1.6.2",
5109
"resolved": "https://registry.npmjs.org/youtube-video-element/-/youtube-video-element-1.6.2.tgz",
···
5117
"license": "MIT",
5118
"funding": {
5119
"url": "https://github.com/sponsors/colinhacks"
5120
}
5121
}
5122
}
···
7
"name": "red-dwarf-tanstack",
8
"dependencies": {
9
"@atproto/api": "^0.16.6",
10
+
"@atproto/oauth-client-browser": "^0.3.33",
11
+
"@radix-ui/react-dialog": "^1.1.15",
12
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
13
+
"@radix-ui/react-hover-card": "^1.1.15",
14
+
"@radix-ui/react-slider": "^1.3.6",
15
"@tailwindcss/vite": "^4.0.6",
16
+
"@tanstack/query-sync-storage-persister": "^5.85.6",
17
"@tanstack/react-devtools": "^0.2.2",
18
"@tanstack/react-query": "^5.85.6",
19
+
"@tanstack/react-query-persist-client": "^5.85.6",
20
"@tanstack/react-router": "^1.130.2",
21
"@tanstack/react-router-devtools": "^1.131.5",
22
"@tanstack/router-plugin": "^1.121.2",
23
+
"dompurify": "^3.3.0",
24
+
"i": "^0.3.7",
25
"idb-keyval": "^6.2.2",
26
"jotai": "^2.13.1",
27
+
"npm": "^11.6.2",
28
+
"radix-ui": "^1.4.3",
29
"react": "^19.0.0",
30
"react-dom": "^19.0.0",
31
"react-player": "^3.3.2",
32
+
"tailwindcss": "^4.0.6",
33
+
"tanstack-router-keepalive": "^1.0.0"
34
},
35
"devDependencies": {
36
+
"@eslint-react/eslint-plugin": "^2.2.1",
37
+
"@iconify-icon/react": "^3.0.1",
38
+
"@iconify-json/material-symbols": "^1.2.42",
39
+
"@iconify-json/mdi": "^1.2.3",
40
+
"@iconify/json": "^2.2.396",
41
+
"@svgr/core": "^8.1.0",
42
+
"@svgr/plugin-jsx": "^8.1.0",
43
"@testing-library/dom": "^10.4.0",
44
"@testing-library/react": "^16.2.0",
45
"@types/node": "^24.3.0",
46
"@types/react": "^19.0.8",
47
"@types/react-dom": "^19.0.3",
48
+
"@typescript-eslint/eslint-plugin": "^8.46.1",
49
+
"@typescript-eslint/parser": "^8.46.1",
50
"@vitejs/plugin-react": "^4.3.4",
51
+
"babel-plugin-react-compiler": "^1.0.0",
52
+
"eslint-plugin-react": "^7.37.5",
53
+
"eslint-plugin-react-hooks": "^7.0.0",
54
+
"eslint-plugin-simple-import-sort": "^12.1.1",
55
+
"eslint-plugin-unused-imports": "^4.2.0",
56
"jsdom": "^26.0.0",
57
"prettier": "^3.6.2",
58
"typescript": "^5.7.2",
59
+
"typescript-eslint": "^8.46.1",
60
+
"unplugin-auto-import": "^20.2.0",
61
+
"unplugin-icons": "^22.4.2",
62
"vite": "^6.3.5",
63
"vitest": "^3.0.5",
64
"web-vitals": "^4.2.4"
···
75
},
76
"engines": {
77
"node": ">=6.0.0"
78
+
}
79
+
},
80
+
"node_modules/@antfu/install-pkg": {
81
+
"version": "1.1.0",
82
+
"resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz",
83
+
"integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==",
84
+
"dev": true,
85
+
"license": "MIT",
86
+
"dependencies": {
87
+
"package-manager-detector": "^1.3.0",
88
+
"tinyexec": "^1.0.1"
89
+
},
90
+
"funding": {
91
+
"url": "https://github.com/sponsors/antfu"
92
+
}
93
+
},
94
+
"node_modules/@antfu/install-pkg/node_modules/tinyexec": {
95
+
"version": "1.0.1",
96
+
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz",
97
+
"integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==",
98
+
"dev": true,
99
+
"license": "MIT"
100
+
},
101
+
"node_modules/@antfu/utils": {
102
+
"version": "9.3.0",
103
+
"resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-9.3.0.tgz",
104
+
"integrity": "sha512-9hFT4RauhcUzqOE4f1+frMKLZrgNog5b06I7VmZQV1BkvwvqrbC8EBZf3L1eEL2AKb6rNKjER0sEvJiSP1FXEA==",
105
+
"dev": true,
106
+
"license": "MIT",
107
+
"funding": {
108
+
"url": "https://github.com/sponsors/antfu"
109
}
110
},
111
"node_modules/@asamuzakjp/css-color": {
···
129
"dev": true,
130
"license": "ISC"
131
},
132
+
"node_modules/@atproto-labs/did-resolver": {
133
+
"version": "0.2.2",
134
+
"resolved": "https://registry.npmjs.org/@atproto-labs/did-resolver/-/did-resolver-0.2.2.tgz",
135
+
"integrity": "sha512-ca2B7xR43tVoQ8XxBvha58DXwIH8cIyKQl6lpOKGkPUrJuFoO4iCLlDiSDi2Ueh+yE1rMDPP/qveHdajgDX3WQ==",
136
+
"license": "MIT",
137
+
"dependencies": {
138
+
"@atproto-labs/fetch": "0.2.3",
139
+
"@atproto-labs/pipe": "0.1.1",
140
+
"@atproto-labs/simple-store": "0.3.0",
141
+
"@atproto-labs/simple-store-memory": "0.1.4",
142
+
"@atproto/did": "0.2.1",
143
+
"zod": "^3.23.8"
144
+
}
145
+
},
146
+
"node_modules/@atproto-labs/fetch": {
147
+
"version": "0.2.3",
148
+
"resolved": "https://registry.npmjs.org/@atproto-labs/fetch/-/fetch-0.2.3.tgz",
149
+
"integrity": "sha512-NZtbJOCbxKUFRFKMpamT38PUQMY0hX0p7TG5AEYOPhZKZEP7dHZ1K2s1aB8MdVH0qxmqX7nQleNrrvLf09Zfdw==",
150
+
"license": "MIT",
151
+
"dependencies": {
152
+
"@atproto-labs/pipe": "0.1.1"
153
+
}
154
+
},
155
+
"node_modules/@atproto-labs/handle-resolver": {
156
+
"version": "0.3.2",
157
+
"resolved": "https://registry.npmjs.org/@atproto-labs/handle-resolver/-/handle-resolver-0.3.2.tgz",
158
+
"integrity": "sha512-KIerCzh3qb+zZoqWbIvTlvBY0XPq0r56kwViaJY/LTe/3oPO2JaqlYKS/F4dByWBhHK6YoUOJ0sWrh6PMJl40A==",
159
+
"license": "MIT",
160
+
"dependencies": {
161
+
"@atproto-labs/simple-store": "0.3.0",
162
+
"@atproto-labs/simple-store-memory": "0.1.4",
163
+
"@atproto/did": "0.2.1",
164
+
"zod": "^3.23.8"
165
+
}
166
+
},
167
+
"node_modules/@atproto-labs/identity-resolver": {
168
+
"version": "0.3.2",
169
+
"resolved": "https://registry.npmjs.org/@atproto-labs/identity-resolver/-/identity-resolver-0.3.2.tgz",
170
+
"integrity": "sha512-MYxO9pe0WsFyi5HFdKAwqIqHfiF2kBPoVhAIuH/4PYHzGr799ED47xLhNMxR3ZUYrJm5+TQzWXypGZ0Btw1Ffw==",
171
+
"license": "MIT",
172
+
"dependencies": {
173
+
"@atproto-labs/did-resolver": "0.2.2",
174
+
"@atproto-labs/handle-resolver": "0.3.2"
175
+
}
176
+
},
177
+
"node_modules/@atproto-labs/pipe": {
178
+
"version": "0.1.1",
179
+
"resolved": "https://registry.npmjs.org/@atproto-labs/pipe/-/pipe-0.1.1.tgz",
180
+
"integrity": "sha512-hdNw2oUs2B6BN1lp+32pF7cp8EMKuIN5Qok2Vvv/aOpG/3tNSJ9YkvfI0k6Zd188LeDDYRUpYpxcoFIcGH/FNg==",
181
+
"license": "MIT"
182
+
},
183
+
"node_modules/@atproto-labs/simple-store": {
184
+
"version": "0.3.0",
185
+
"resolved": "https://registry.npmjs.org/@atproto-labs/simple-store/-/simple-store-0.3.0.tgz",
186
+
"integrity": "sha512-nOb6ONKBRJHRlukW1sVawUkBqReLlLx6hT35VS3imaNPwiXDxLnTK7lxw3Lrl9k5yugSBDQAkZAq3MPTEFSUBQ==",
187
+
"license": "MIT"
188
+
},
189
+
"node_modules/@atproto-labs/simple-store-memory": {
190
+
"version": "0.1.4",
191
+
"resolved": "https://registry.npmjs.org/@atproto-labs/simple-store-memory/-/simple-store-memory-0.1.4.tgz",
192
+
"integrity": "sha512-3mKY4dP8I7yKPFj9VKpYyCRzGJOi5CEpOLPlRhoJyLmgs3J4RzDrjn323Oakjz2Aj2JzRU/AIvWRAZVhpYNJHw==",
193
+
"license": "MIT",
194
+
"dependencies": {
195
+
"@atproto-labs/simple-store": "0.3.0",
196
+
"lru-cache": "^10.2.0"
197
+
}
198
+
},
199
+
"node_modules/@atproto-labs/simple-store-memory/node_modules/lru-cache": {
200
+
"version": "10.4.3",
201
+
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
202
+
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
203
+
"license": "ISC"
204
+
},
205
"node_modules/@atproto/api": {
206
"version": "0.16.6",
207
"resolved": "https://registry.npmjs.org/@atproto/api/-/api-0.16.6.tgz",
···
219
}
220
},
221
"node_modules/@atproto/common-web": {
222
+
"version": "0.4.3",
223
+
"resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.4.3.tgz",
224
+
"integrity": "sha512-nRDINmSe4VycJzPo6fP/hEltBcULFxt9Kw7fQk6405FyAWZiTluYHlXOnU7GkQfeUK44OENG1qFTBcmCJ7e8pg==",
225
"license": "MIT",
226
"dependencies": {
227
"graphemer": "^1.4.0",
···
230
"zod": "^3.23.8"
231
}
232
},
233
+
"node_modules/@atproto/did": {
234
+
"version": "0.2.1",
235
+
"resolved": "https://registry.npmjs.org/@atproto/did/-/did-0.2.1.tgz",
236
+
"integrity": "sha512-1i5BTU2GnBaaeYWhxUOnuEKFVq9euT5+dQPFabHpa927BlJ54PmLGyBBaOI7/NbLmN5HWwBa18SBkMpg3jGZRA==",
237
+
"license": "MIT",
238
+
"dependencies": {
239
+
"zod": "^3.23.8"
240
+
}
241
+
},
242
+
"node_modules/@atproto/jwk": {
243
+
"version": "0.6.0",
244
+
"resolved": "https://registry.npmjs.org/@atproto/jwk/-/jwk-0.6.0.tgz",
245
+
"integrity": "sha512-bDoJPvt7TrQVi/rBfBrSSpGykhtIriKxeYCYQTiPRKFfyRhbgpElF0wPXADjIswnbzZdOwbY63az4E/CFVT3Tw==",
246
+
"license": "MIT",
247
+
"dependencies": {
248
+
"multiformats": "^9.9.0",
249
+
"zod": "^3.23.8"
250
+
}
251
+
},
252
+
"node_modules/@atproto/jwk-jose": {
253
+
"version": "0.1.11",
254
+
"resolved": "https://registry.npmjs.org/@atproto/jwk-jose/-/jwk-jose-0.1.11.tgz",
255
+
"integrity": "sha512-i4Fnr2sTBYmMmHXl7NJh8GrCH+tDQEVWrcDMDnV5DjJfkgT17wIqvojIw9SNbSL4Uf0OtfEv6AgG0A+mgh8b5Q==",
256
+
"license": "MIT",
257
+
"dependencies": {
258
+
"@atproto/jwk": "0.6.0",
259
+
"jose": "^5.2.0"
260
+
}
261
+
},
262
+
"node_modules/@atproto/jwk-webcrypto": {
263
+
"version": "0.2.0",
264
+
"resolved": "https://registry.npmjs.org/@atproto/jwk-webcrypto/-/jwk-webcrypto-0.2.0.tgz",
265
+
"integrity": "sha512-UmgRrrEAkWvxwhlwe30UmDOdTEFidlIzBC7C3cCbeJMcBN1x8B3KH+crXrsTqfWQBG58mXgt8wgSK3Kxs2LhFg==",
266
+
"license": "MIT",
267
+
"dependencies": {
268
+
"@atproto/jwk": "0.6.0",
269
+
"@atproto/jwk-jose": "0.1.11",
270
+
"zod": "^3.23.8"
271
+
}
272
+
},
273
"node_modules/@atproto/lexicon": {
274
+
"version": "0.5.1",
275
+
"resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.5.1.tgz",
276
+
"integrity": "sha512-y8AEtYmfgVl4fqFxqXAeGvhesiGkxiy3CWoJIfsFDDdTlZUC8DFnZrYhcqkIop3OlCkkljvpSJi1hbeC1tbi8A==",
277
"license": "MIT",
278
"dependencies": {
279
+
"@atproto/common-web": "^0.4.3",
280
"@atproto/syntax": "^0.4.1",
281
"iso-datestring-validator": "^2.2.2",
282
"multiformats": "^9.9.0",
283
"zod": "^3.23.8"
284
}
285
},
286
+
"node_modules/@atproto/oauth-client": {
287
+
"version": "0.5.7",
288
+
"resolved": "https://registry.npmjs.org/@atproto/oauth-client/-/oauth-client-0.5.7.tgz",
289
+
"integrity": "sha512-pDvbvy9DCxrAJv7bAbBUzWrHZKhFy091HvEMZhr+EyZA6gSCGYmmQJG/coDj0oICSVQeafAZd+IxR0YUCWwmEg==",
290
+
"license": "MIT",
291
+
"dependencies": {
292
+
"@atproto-labs/did-resolver": "0.2.2",
293
+
"@atproto-labs/fetch": "0.2.3",
294
+
"@atproto-labs/handle-resolver": "0.3.2",
295
+
"@atproto-labs/identity-resolver": "0.3.2",
296
+
"@atproto-labs/simple-store": "0.3.0",
297
+
"@atproto-labs/simple-store-memory": "0.1.4",
298
+
"@atproto/did": "0.2.1",
299
+
"@atproto/jwk": "0.6.0",
300
+
"@atproto/oauth-types": "0.4.2",
301
+
"@atproto/xrpc": "0.7.5",
302
+
"core-js": "^3",
303
+
"multiformats": "^9.9.0",
304
+
"zod": "^3.23.8"
305
+
}
306
+
},
307
+
"node_modules/@atproto/oauth-client-browser": {
308
+
"version": "0.3.33",
309
+
"resolved": "https://registry.npmjs.org/@atproto/oauth-client-browser/-/oauth-client-browser-0.3.33.tgz",
310
+
"integrity": "sha512-IvHn/5W3e9GXFUGXQ4MV19E4HXY4zJFgu+eZRWexIXnZl4GwgTH7op8J1SosczdOK1Ngu+LnHE6npcNhUGGd6Q==",
311
+
"license": "MIT",
312
+
"dependencies": {
313
+
"@atproto-labs/did-resolver": "0.2.2",
314
+
"@atproto-labs/handle-resolver": "0.3.2",
315
+
"@atproto-labs/simple-store": "0.3.0",
316
+
"@atproto/did": "0.2.1",
317
+
"@atproto/jwk": "0.6.0",
318
+
"@atproto/jwk-webcrypto": "0.2.0",
319
+
"@atproto/oauth-client": "0.5.7",
320
+
"@atproto/oauth-types": "0.4.2",
321
+
"core-js": "^3"
322
+
}
323
+
},
324
+
"node_modules/@atproto/oauth-types": {
325
+
"version": "0.4.2",
326
+
"resolved": "https://registry.npmjs.org/@atproto/oauth-types/-/oauth-types-0.4.2.tgz",
327
+
"integrity": "sha512-gcfNTyFsPJcYDf79M0iKHykWqzxloscioKoerdIN3MTS3htiNOSgZjm2p8ho7pdrElLzea3qktuhTQI39j1XFQ==",
328
+
"license": "MIT",
329
+
"dependencies": {
330
+
"@atproto/did": "0.2.1",
331
+
"@atproto/jwk": "0.6.0",
332
+
"zod": "^3.23.8"
333
+
}
334
+
},
335
"node_modules/@atproto/syntax": {
336
"version": "0.4.1",
337
"resolved": "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.4.1.tgz",
···
339
"license": "MIT"
340
},
341
"node_modules/@atproto/xrpc": {
342
+
"version": "0.7.5",
343
+
"resolved": "https://registry.npmjs.org/@atproto/xrpc/-/xrpc-0.7.5.tgz",
344
+
"integrity": "sha512-MUYNn5d2hv8yVegRL0ccHvTHAVj5JSnW07bkbiaz96UH45lvYNRVwt44z+yYVnb0/mvBzyD3/ZQ55TRGt7fHkA==",
345
"license": "MIT",
346
"dependencies": {
347
+
"@atproto/lexicon": "^0.5.1",
348
"zod": "^3.23.8"
349
}
350
},
···
1326
"node": ">=18"
1327
}
1328
},
1329
+
"node_modules/@eslint-community/eslint-utils": {
1330
+
"version": "4.9.0",
1331
+
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
1332
+
"integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
1333
+
"dev": true,
1334
+
"license": "MIT",
1335
+
"dependencies": {
1336
+
"eslint-visitor-keys": "^3.4.3"
1337
+
},
1338
+
"engines": {
1339
+
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1340
+
},
1341
+
"funding": {
1342
+
"url": "https://opencollective.com/eslint"
1343
+
},
1344
+
"peerDependencies": {
1345
+
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
1346
+
}
1347
+
},
1348
+
"node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
1349
+
"version": "3.4.3",
1350
+
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
1351
+
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
1352
+
"dev": true,
1353
+
"license": "Apache-2.0",
1354
+
"engines": {
1355
+
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
1356
+
},
1357
+
"funding": {
1358
+
"url": "https://opencollective.com/eslint"
1359
+
}
1360
+
},
1361
+
"node_modules/@eslint-community/regexpp": {
1362
+
"version": "4.12.1",
1363
+
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
1364
+
"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
1365
+
"dev": true,
1366
+
"license": "MIT",
1367
+
"engines": {
1368
+
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
1369
+
}
1370
+
},
1371
+
"node_modules/@eslint-react/ast": {
1372
+
"version": "2.2.1",
1373
+
"resolved": "https://registry.npmjs.org/@eslint-react/ast/-/ast-2.2.1.tgz",
1374
+
"integrity": "sha512-bjzSAdtTT/gIU0/olh8Kki57Mnadl5BIjJxcA3wqxcAvNwYAt3yl0CM4LRqVqW4kJneslCNqB5UriRJJPSKhuA==",
1375
+
"dev": true,
1376
+
"license": "MIT",
1377
+
"dependencies": {
1378
+
"@eslint-react/eff": "2.2.1",
1379
+
"@typescript-eslint/types": "^8.46.0",
1380
+
"@typescript-eslint/typescript-estree": "^8.46.0",
1381
+
"@typescript-eslint/utils": "^8.46.0",
1382
+
"string-ts": "^2.2.1"
1383
+
},
1384
+
"engines": {
1385
+
"node": ">=20.19.0"
1386
+
}
1387
+
},
1388
+
"node_modules/@eslint-react/core": {
1389
+
"version": "2.2.1",
1390
+
"resolved": "https://registry.npmjs.org/@eslint-react/core/-/core-2.2.1.tgz",
1391
+
"integrity": "sha512-slP1G7sReKgijlDx56SDhgkpS6OjoNCEqItuY6Ayo4viIIYMyQ5LkPJ2BJ5xbBxSklyszQ/yP+8UFDK6uzYChQ==",
1392
+
"dev": true,
1393
+
"license": "MIT",
1394
+
"dependencies": {
1395
+
"@eslint-react/ast": "2.2.1",
1396
+
"@eslint-react/eff": "2.2.1",
1397
+
"@eslint-react/shared": "2.2.1",
1398
+
"@eslint-react/var": "2.2.1",
1399
+
"@typescript-eslint/scope-manager": "^8.46.0",
1400
+
"@typescript-eslint/types": "^8.46.0",
1401
+
"@typescript-eslint/utils": "^8.46.0",
1402
+
"birecord": "^0.1.1",
1403
+
"ts-pattern": "^5.8.0"
1404
+
},
1405
+
"engines": {
1406
+
"node": ">=20.19.0"
1407
+
}
1408
+
},
1409
+
"node_modules/@eslint-react/eff": {
1410
+
"version": "2.2.1",
1411
+
"resolved": "https://registry.npmjs.org/@eslint-react/eff/-/eff-2.2.1.tgz",
1412
+
"integrity": "sha512-u9IJB9O8Jwo4b40CLIoF1HePsOvFLdbRKdCVUBEv2TPihae/ltYRD45mCI0bHLroYUxevC1nvD/cQRfwJPH0zg==",
1413
+
"dev": true,
1414
+
"license": "MIT",
1415
+
"engines": {
1416
+
"node": ">=20.19.0"
1417
+
}
1418
+
},
1419
+
"node_modules/@eslint-react/eslint-plugin": {
1420
+
"version": "2.2.1",
1421
+
"resolved": "https://registry.npmjs.org/@eslint-react/eslint-plugin/-/eslint-plugin-2.2.1.tgz",
1422
+
"integrity": "sha512-BjIwFBvgo2b8d5KaTm3qkqKHMFT0HJmAYUZ6TT5j+C/2lWQK3mANxoPwD9Kq4tuI/zw5dINyKxQp6Kr8yGybHQ==",
1423
+
"dev": true,
1424
+
"license": "MIT",
1425
+
"dependencies": {
1426
+
"@eslint-react/eff": "2.2.1",
1427
+
"@eslint-react/shared": "2.2.1",
1428
+
"@typescript-eslint/scope-manager": "^8.46.0",
1429
+
"@typescript-eslint/type-utils": "^8.46.0",
1430
+
"@typescript-eslint/types": "^8.46.0",
1431
+
"@typescript-eslint/utils": "^8.46.0",
1432
+
"eslint-plugin-react-dom": "2.2.1",
1433
+
"eslint-plugin-react-hooks-extra": "2.2.1",
1434
+
"eslint-plugin-react-naming-convention": "2.2.1",
1435
+
"eslint-plugin-react-web-api": "2.2.1",
1436
+
"eslint-plugin-react-x": "2.2.1",
1437
+
"ts-api-utils": "^2.1.0"
1438
+
},
1439
+
"engines": {
1440
+
"node": ">=20.19.0"
1441
+
},
1442
+
"peerDependencies": {
1443
+
"eslint": "^9.37.0",
1444
+
"typescript": "^5.9.3"
1445
+
}
1446
+
},
1447
+
"node_modules/@eslint-react/shared": {
1448
+
"version": "2.2.1",
1449
+
"resolved": "https://registry.npmjs.org/@eslint-react/shared/-/shared-2.2.1.tgz",
1450
+
"integrity": "sha512-YxYo4Svw2OzV0XDj4HLJKcmB4vtAyQghSE1ZFKN5i90CIbfp/RYBNK6VVrIbxtXu6tAsJ0lSBZiepHfn3i/l8w==",
1451
+
"dev": true,
1452
+
"license": "MIT",
1453
+
"dependencies": {
1454
+
"@eslint-react/eff": "2.2.1",
1455
+
"@typescript-eslint/utils": "^8.46.0",
1456
+
"ts-pattern": "^5.8.0",
1457
+
"zod": "^4.1.12"
1458
+
},
1459
+
"engines": {
1460
+
"node": ">=20.19.0"
1461
+
}
1462
+
},
1463
+
"node_modules/@eslint-react/shared/node_modules/zod": {
1464
+
"version": "4.1.12",
1465
+
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz",
1466
+
"integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==",
1467
+
"dev": true,
1468
+
"license": "MIT",
1469
+
"funding": {
1470
+
"url": "https://github.com/sponsors/colinhacks"
1471
+
}
1472
+
},
1473
+
"node_modules/@eslint-react/var": {
1474
+
"version": "2.2.1",
1475
+
"resolved": "https://registry.npmjs.org/@eslint-react/var/-/var-2.2.1.tgz",
1476
+
"integrity": "sha512-u5o1z01mNE0F+6DG1sDPnIGDbTaI3s0IOJnGCU4FfcsH7DOf96F4aB1szdJfznJBgVCrcBbyhO9oKKlYZoW0hQ==",
1477
+
"dev": true,
1478
+
"license": "MIT",
1479
+
"dependencies": {
1480
+
"@eslint-react/ast": "2.2.1",
1481
+
"@eslint-react/eff": "2.2.1",
1482
+
"@typescript-eslint/scope-manager": "^8.46.0",
1483
+
"@typescript-eslint/types": "^8.46.0",
1484
+
"@typescript-eslint/utils": "^8.46.0",
1485
+
"ts-pattern": "^5.8.0"
1486
+
},
1487
+
"engines": {
1488
+
"node": ">=20.19.0"
1489
+
}
1490
+
},
1491
+
"node_modules/@eslint/config-array": {
1492
+
"version": "0.21.0",
1493
+
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
1494
+
"integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
1495
+
"dev": true,
1496
+
"license": "Apache-2.0",
1497
+
"peer": true,
1498
+
"dependencies": {
1499
+
"@eslint/object-schema": "^2.1.6",
1500
+
"debug": "^4.3.1",
1501
+
"minimatch": "^3.1.2"
1502
+
},
1503
+
"engines": {
1504
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1505
+
}
1506
+
},
1507
+
"node_modules/@eslint/config-helpers": {
1508
+
"version": "0.4.0",
1509
+
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz",
1510
+
"integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==",
1511
+
"dev": true,
1512
+
"license": "Apache-2.0",
1513
+
"peer": true,
1514
+
"dependencies": {
1515
+
"@eslint/core": "^0.16.0"
1516
+
},
1517
+
"engines": {
1518
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1519
+
}
1520
+
},
1521
+
"node_modules/@eslint/core": {
1522
+
"version": "0.16.0",
1523
+
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz",
1524
+
"integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==",
1525
+
"dev": true,
1526
+
"license": "Apache-2.0",
1527
+
"peer": true,
1528
+
"dependencies": {
1529
+
"@types/json-schema": "^7.0.15"
1530
+
},
1531
+
"engines": {
1532
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1533
+
}
1534
+
},
1535
+
"node_modules/@eslint/eslintrc": {
1536
+
"version": "3.3.1",
1537
+
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
1538
+
"integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
1539
+
"dev": true,
1540
+
"license": "MIT",
1541
+
"peer": true,
1542
+
"dependencies": {
1543
+
"ajv": "^6.12.4",
1544
+
"debug": "^4.3.2",
1545
+
"espree": "^10.0.1",
1546
+
"globals": "^14.0.0",
1547
+
"ignore": "^5.2.0",
1548
+
"import-fresh": "^3.2.1",
1549
+
"js-yaml": "^4.1.0",
1550
+
"minimatch": "^3.1.2",
1551
+
"strip-json-comments": "^3.1.1"
1552
+
},
1553
+
"engines": {
1554
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1555
+
},
1556
+
"funding": {
1557
+
"url": "https://opencollective.com/eslint"
1558
+
}
1559
+
},
1560
+
"node_modules/@eslint/js": {
1561
+
"version": "9.37.0",
1562
+
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz",
1563
+
"integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==",
1564
+
"dev": true,
1565
+
"license": "MIT",
1566
+
"peer": true,
1567
+
"engines": {
1568
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1569
+
},
1570
+
"funding": {
1571
+
"url": "https://eslint.org/donate"
1572
+
}
1573
+
},
1574
+
"node_modules/@eslint/object-schema": {
1575
+
"version": "2.1.6",
1576
+
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
1577
+
"integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
1578
+
"dev": true,
1579
+
"license": "Apache-2.0",
1580
+
"peer": true,
1581
+
"engines": {
1582
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1583
+
}
1584
+
},
1585
+
"node_modules/@eslint/plugin-kit": {
1586
+
"version": "0.4.0",
1587
+
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz",
1588
+
"integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==",
1589
+
"dev": true,
1590
+
"license": "Apache-2.0",
1591
+
"peer": true,
1592
+
"dependencies": {
1593
+
"@eslint/core": "^0.16.0",
1594
+
"levn": "^0.4.1"
1595
+
},
1596
+
"engines": {
1597
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1598
+
}
1599
+
},
1600
+
"node_modules/@floating-ui/core": {
1601
+
"version": "1.7.3",
1602
+
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
1603
+
"integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
1604
+
"dependencies": {
1605
+
"@floating-ui/utils": "^0.2.10"
1606
+
}
1607
+
},
1608
+
"node_modules/@floating-ui/dom": {
1609
+
"version": "1.7.4",
1610
+
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz",
1611
+
"integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
1612
+
"dependencies": {
1613
+
"@floating-ui/core": "^1.7.3",
1614
+
"@floating-ui/utils": "^0.2.10"
1615
+
}
1616
+
},
1617
+
"node_modules/@floating-ui/react-dom": {
1618
+
"version": "2.1.6",
1619
+
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz",
1620
+
"integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==",
1621
+
"dependencies": {
1622
+
"@floating-ui/dom": "^1.7.4"
1623
+
},
1624
+
"peerDependencies": {
1625
+
"react": ">=16.8.0",
1626
+
"react-dom": ">=16.8.0"
1627
+
}
1628
+
},
1629
+
"node_modules/@floating-ui/utils": {
1630
+
"version": "0.2.10",
1631
+
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
1632
+
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="
1633
+
},
1634
+
"node_modules/@humanfs/core": {
1635
+
"version": "0.19.1",
1636
+
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
1637
+
"integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
1638
+
"dev": true,
1639
+
"license": "Apache-2.0",
1640
+
"peer": true,
1641
+
"engines": {
1642
+
"node": ">=18.18.0"
1643
+
}
1644
+
},
1645
+
"node_modules/@humanfs/node": {
1646
+
"version": "0.16.7",
1647
+
"resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
1648
+
"integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
1649
+
"dev": true,
1650
+
"license": "Apache-2.0",
1651
+
"peer": true,
1652
+
"dependencies": {
1653
+
"@humanfs/core": "^0.19.1",
1654
+
"@humanwhocodes/retry": "^0.4.0"
1655
+
},
1656
+
"engines": {
1657
+
"node": ">=18.18.0"
1658
+
}
1659
+
},
1660
+
"node_modules/@humanwhocodes/module-importer": {
1661
+
"version": "1.0.1",
1662
+
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
1663
+
"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
1664
+
"dev": true,
1665
+
"license": "Apache-2.0",
1666
+
"peer": true,
1667
+
"engines": {
1668
+
"node": ">=12.22"
1669
+
},
1670
+
"funding": {
1671
+
"type": "github",
1672
+
"url": "https://github.com/sponsors/nzakas"
1673
+
}
1674
+
},
1675
+
"node_modules/@humanwhocodes/retry": {
1676
+
"version": "0.4.3",
1677
+
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
1678
+
"integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
1679
+
"dev": true,
1680
+
"license": "Apache-2.0",
1681
+
"peer": true,
1682
+
"engines": {
1683
+
"node": ">=18.18"
1684
+
},
1685
+
"funding": {
1686
+
"type": "github",
1687
+
"url": "https://github.com/sponsors/nzakas"
1688
+
}
1689
+
},
1690
+
"node_modules/@iconify-icon/react": {
1691
+
"version": "3.0.1",
1692
+
"resolved": "https://registry.npmjs.org/@iconify-icon/react/-/react-3.0.1.tgz",
1693
+
"integrity": "sha512-/4CAVpk8HDyKS78r1G0rZhML7hI6jLxb8kAmjEXsCtuVUDwdGqicGCRg0T14mqeHNImrQPR49MhbuSSS++JlUA==",
1694
+
"dev": true,
1695
+
"license": "MIT",
1696
+
"dependencies": {
1697
+
"iconify-icon": "^3.0.1"
1698
+
},
1699
+
"funding": {
1700
+
"url": "https://github.com/sponsors/cyberalien"
1701
+
},
1702
+
"peerDependencies": {
1703
+
"react": ">=16"
1704
+
}
1705
+
},
1706
+
"node_modules/@iconify-json/material-symbols": {
1707
+
"version": "1.2.42",
1708
+
"resolved": "https://registry.npmjs.org/@iconify-json/material-symbols/-/material-symbols-1.2.42.tgz",
1709
+
"integrity": "sha512-FDRfnQqy8iXaq/swVPFWaHftqP9tk3qDCRhC30s3UZL2j4mvGZk5gVECRXCkZv5jnsAiTpZxGQM8HrMiwE7GtA==",
1710
+
"dev": true,
1711
+
"license": "Apache-2.0",
1712
+
"dependencies": {
1713
+
"@iconify/types": "*"
1714
+
}
1715
+
},
1716
+
"node_modules/@iconify-json/mdi": {
1717
+
"version": "1.2.3",
1718
+
"resolved": "https://registry.npmjs.org/@iconify-json/mdi/-/mdi-1.2.3.tgz",
1719
+
"integrity": "sha512-O3cLwbDOK7NNDf2ihaQOH5F9JglnulNDFV7WprU2dSoZu3h3cWH//h74uQAB87brHmvFVxIOkuBX2sZSzYhScg==",
1720
+
"dev": true,
1721
+
"license": "Apache-2.0",
1722
+
"dependencies": {
1723
+
"@iconify/types": "*"
1724
+
}
1725
+
},
1726
+
"node_modules/@iconify/json": {
1727
+
"version": "2.2.396",
1728
+
"resolved": "https://registry.npmjs.org/@iconify/json/-/json-2.2.396.tgz",
1729
+
"integrity": "sha512-tijg77JFuYIt32S9N8p7La8C0zp9zKZsX6UP8ip5GVB1F6Mp3pZA5Vc5eAquTY50NoDJX58U6z4Qn3d6Wyossg==",
1730
+
"dev": true,
1731
+
"license": "MIT",
1732
+
"dependencies": {
1733
+
"@iconify/types": "*",
1734
+
"pathe": "^2.0.0"
1735
+
}
1736
+
},
1737
+
"node_modules/@iconify/types": {
1738
+
"version": "2.0.0",
1739
+
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
1740
+
"integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
1741
+
"dev": true,
1742
+
"license": "MIT"
1743
+
},
1744
+
"node_modules/@iconify/utils": {
1745
+
"version": "3.0.2",
1746
+
"resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.0.2.tgz",
1747
+
"integrity": "sha512-EfJS0rLfVuRuJRn4psJHtK2A9TqVnkxPpHY6lYHiB9+8eSuudsxbwMiavocG45ujOo6FJ+CIRlRnlOGinzkaGQ==",
1748
+
"dev": true,
1749
+
"license": "MIT",
1750
+
"dependencies": {
1751
+
"@antfu/install-pkg": "^1.1.0",
1752
+
"@antfu/utils": "^9.2.0",
1753
+
"@iconify/types": "^2.0.0",
1754
+
"debug": "^4.4.1",
1755
+
"globals": "^15.15.0",
1756
+
"kolorist": "^1.8.0",
1757
+
"local-pkg": "^1.1.1",
1758
+
"mlly": "^1.7.4"
1759
+
}
1760
+
},
1761
+
"node_modules/@iconify/utils/node_modules/globals": {
1762
+
"version": "15.15.0",
1763
+
"resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
1764
+
"integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
1765
+
"dev": true,
1766
+
"license": "MIT",
1767
+
"engines": {
1768
+
"node": ">=18"
1769
+
},
1770
+
"funding": {
1771
+
"url": "https://github.com/sponsors/sindresorhus"
1772
+
}
1773
+
},
1774
"node_modules/@isaacs/fs-minipass": {
1775
"version": "4.0.1",
1776
"resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
···
1896
"mux-embed": "^5.8.3"
1897
}
1898
},
1899
+
"node_modules/@nodelib/fs.scandir": {
1900
+
"version": "2.1.5",
1901
+
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
1902
+
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
1903
+
"dev": true,
1904
+
"license": "MIT",
1905
+
"dependencies": {
1906
+
"@nodelib/fs.stat": "2.0.5",
1907
+
"run-parallel": "^1.1.9"
1908
+
},
1909
+
"engines": {
1910
+
"node": ">= 8"
1911
+
}
1912
+
},
1913
+
"node_modules/@nodelib/fs.stat": {
1914
+
"version": "2.0.5",
1915
+
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
1916
+
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
1917
+
"dev": true,
1918
+
"license": "MIT",
1919
+
"engines": {
1920
+
"node": ">= 8"
1921
+
}
1922
+
},
1923
+
"node_modules/@nodelib/fs.walk": {
1924
+
"version": "1.2.8",
1925
+
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
1926
+
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
1927
+
"dev": true,
1928
+
"license": "MIT",
1929
+
"dependencies": {
1930
+
"@nodelib/fs.scandir": "2.1.5",
1931
+
"fastq": "^1.6.0"
1932
+
},
1933
+
"engines": {
1934
+
"node": ">= 8"
1935
+
}
1936
+
},
1937
+
"node_modules/@radix-ui/number": {
1938
+
"version": "1.1.1",
1939
+
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
1940
+
"integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="
1941
+
},
1942
+
"node_modules/@radix-ui/primitive": {
1943
+
"version": "1.1.3",
1944
+
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
1945
+
"integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="
1946
+
},
1947
+
"node_modules/@radix-ui/react-accessible-icon": {
1948
+
"version": "1.1.7",
1949
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-accessible-icon/-/react-accessible-icon-1.1.7.tgz",
1950
+
"integrity": "sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A==",
1951
+
"dependencies": {
1952
+
"@radix-ui/react-visually-hidden": "1.2.3"
1953
+
},
1954
+
"peerDependencies": {
1955
+
"@types/react": "*",
1956
+
"@types/react-dom": "*",
1957
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1958
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1959
+
},
1960
+
"peerDependenciesMeta": {
1961
+
"@types/react": {
1962
+
"optional": true
1963
+
},
1964
+
"@types/react-dom": {
1965
+
"optional": true
1966
+
}
1967
+
}
1968
+
},
1969
+
"node_modules/@radix-ui/react-accordion": {
1970
+
"version": "1.2.12",
1971
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz",
1972
+
"integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==",
1973
+
"dependencies": {
1974
+
"@radix-ui/primitive": "1.1.3",
1975
+
"@radix-ui/react-collapsible": "1.1.12",
1976
+
"@radix-ui/react-collection": "1.1.7",
1977
+
"@radix-ui/react-compose-refs": "1.1.2",
1978
+
"@radix-ui/react-context": "1.1.2",
1979
+
"@radix-ui/react-direction": "1.1.1",
1980
+
"@radix-ui/react-id": "1.1.1",
1981
+
"@radix-ui/react-primitive": "2.1.3",
1982
+
"@radix-ui/react-use-controllable-state": "1.2.2"
1983
+
},
1984
+
"peerDependencies": {
1985
+
"@types/react": "*",
1986
+
"@types/react-dom": "*",
1987
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1988
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1989
+
},
1990
+
"peerDependenciesMeta": {
1991
+
"@types/react": {
1992
+
"optional": true
1993
+
},
1994
+
"@types/react-dom": {
1995
+
"optional": true
1996
+
}
1997
+
}
1998
+
},
1999
+
"node_modules/@radix-ui/react-alert-dialog": {
2000
+
"version": "1.1.15",
2001
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz",
2002
+
"integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==",
2003
+
"dependencies": {
2004
+
"@radix-ui/primitive": "1.1.3",
2005
+
"@radix-ui/react-compose-refs": "1.1.2",
2006
+
"@radix-ui/react-context": "1.1.2",
2007
+
"@radix-ui/react-dialog": "1.1.15",
2008
+
"@radix-ui/react-primitive": "2.1.3",
2009
+
"@radix-ui/react-slot": "1.2.3"
2010
+
},
2011
+
"peerDependencies": {
2012
+
"@types/react": "*",
2013
+
"@types/react-dom": "*",
2014
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2015
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2016
+
},
2017
+
"peerDependenciesMeta": {
2018
+
"@types/react": {
2019
+
"optional": true
2020
+
},
2021
+
"@types/react-dom": {
2022
+
"optional": true
2023
+
}
2024
+
}
2025
+
},
2026
+
"node_modules/@radix-ui/react-arrow": {
2027
+
"version": "1.1.7",
2028
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
2029
+
"integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
2030
+
"dependencies": {
2031
+
"@radix-ui/react-primitive": "2.1.3"
2032
+
},
2033
+
"peerDependencies": {
2034
+
"@types/react": "*",
2035
+
"@types/react-dom": "*",
2036
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2037
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2038
+
},
2039
+
"peerDependenciesMeta": {
2040
+
"@types/react": {
2041
+
"optional": true
2042
+
},
2043
+
"@types/react-dom": {
2044
+
"optional": true
2045
+
}
2046
+
}
2047
+
},
2048
+
"node_modules/@radix-ui/react-aspect-ratio": {
2049
+
"version": "1.1.7",
2050
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.7.tgz",
2051
+
"integrity": "sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g==",
2052
+
"dependencies": {
2053
+
"@radix-ui/react-primitive": "2.1.3"
2054
+
},
2055
+
"peerDependencies": {
2056
+
"@types/react": "*",
2057
+
"@types/react-dom": "*",
2058
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2059
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2060
+
},
2061
+
"peerDependenciesMeta": {
2062
+
"@types/react": {
2063
+
"optional": true
2064
+
},
2065
+
"@types/react-dom": {
2066
+
"optional": true
2067
+
}
2068
+
}
2069
+
},
2070
+
"node_modules/@radix-ui/react-avatar": {
2071
+
"version": "1.1.10",
2072
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz",
2073
+
"integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==",
2074
+
"dependencies": {
2075
+
"@radix-ui/react-context": "1.1.2",
2076
+
"@radix-ui/react-primitive": "2.1.3",
2077
+
"@radix-ui/react-use-callback-ref": "1.1.1",
2078
+
"@radix-ui/react-use-is-hydrated": "0.1.0",
2079
+
"@radix-ui/react-use-layout-effect": "1.1.1"
2080
+
},
2081
+
"peerDependencies": {
2082
+
"@types/react": "*",
2083
+
"@types/react-dom": "*",
2084
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2085
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2086
+
},
2087
+
"peerDependenciesMeta": {
2088
+
"@types/react": {
2089
+
"optional": true
2090
+
},
2091
+
"@types/react-dom": {
2092
+
"optional": true
2093
+
}
2094
+
}
2095
+
},
2096
+
"node_modules/@radix-ui/react-checkbox": {
2097
+
"version": "1.3.3",
2098
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz",
2099
+
"integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==",
2100
+
"dependencies": {
2101
+
"@radix-ui/primitive": "1.1.3",
2102
+
"@radix-ui/react-compose-refs": "1.1.2",
2103
+
"@radix-ui/react-context": "1.1.2",
2104
+
"@radix-ui/react-presence": "1.1.5",
2105
+
"@radix-ui/react-primitive": "2.1.3",
2106
+
"@radix-ui/react-use-controllable-state": "1.2.2",
2107
+
"@radix-ui/react-use-previous": "1.1.1",
2108
+
"@radix-ui/react-use-size": "1.1.1"
2109
+
},
2110
+
"peerDependencies": {
2111
+
"@types/react": "*",
2112
+
"@types/react-dom": "*",
2113
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2114
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2115
+
},
2116
+
"peerDependenciesMeta": {
2117
+
"@types/react": {
2118
+
"optional": true
2119
+
},
2120
+
"@types/react-dom": {
2121
+
"optional": true
2122
+
}
2123
+
}
2124
+
},
2125
+
"node_modules/@radix-ui/react-collapsible": {
2126
+
"version": "1.1.12",
2127
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz",
2128
+
"integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==",
2129
+
"dependencies": {
2130
+
"@radix-ui/primitive": "1.1.3",
2131
+
"@radix-ui/react-compose-refs": "1.1.2",
2132
+
"@radix-ui/react-context": "1.1.2",
2133
+
"@radix-ui/react-id": "1.1.1",
2134
+
"@radix-ui/react-presence": "1.1.5",
2135
+
"@radix-ui/react-primitive": "2.1.3",
2136
+
"@radix-ui/react-use-controllable-state": "1.2.2",
2137
+
"@radix-ui/react-use-layout-effect": "1.1.1"
2138
+
},
2139
+
"peerDependencies": {
2140
+
"@types/react": "*",
2141
+
"@types/react-dom": "*",
2142
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2143
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2144
+
},
2145
+
"peerDependenciesMeta": {
2146
+
"@types/react": {
2147
+
"optional": true
2148
+
},
2149
+
"@types/react-dom": {
2150
+
"optional": true
2151
+
}
2152
+
}
2153
+
},
2154
+
"node_modules/@radix-ui/react-collection": {
2155
+
"version": "1.1.7",
2156
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
2157
+
"integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
2158
+
"dependencies": {
2159
+
"@radix-ui/react-compose-refs": "1.1.2",
2160
+
"@radix-ui/react-context": "1.1.2",
2161
+
"@radix-ui/react-primitive": "2.1.3",
2162
+
"@radix-ui/react-slot": "1.2.3"
2163
+
},
2164
+
"peerDependencies": {
2165
+
"@types/react": "*",
2166
+
"@types/react-dom": "*",
2167
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2168
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2169
+
},
2170
+
"peerDependenciesMeta": {
2171
+
"@types/react": {
2172
+
"optional": true
2173
+
},
2174
+
"@types/react-dom": {
2175
+
"optional": true
2176
+
}
2177
+
}
2178
+
},
2179
+
"node_modules/@radix-ui/react-compose-refs": {
2180
+
"version": "1.1.2",
2181
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
2182
+
"integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
2183
+
"peerDependencies": {
2184
+
"@types/react": "*",
2185
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2186
+
},
2187
+
"peerDependenciesMeta": {
2188
+
"@types/react": {
2189
+
"optional": true
2190
+
}
2191
+
}
2192
+
},
2193
+
"node_modules/@radix-ui/react-context": {
2194
+
"version": "1.1.2",
2195
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
2196
+
"integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
2197
+
"peerDependencies": {
2198
+
"@types/react": "*",
2199
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2200
+
},
2201
+
"peerDependenciesMeta": {
2202
+
"@types/react": {
2203
+
"optional": true
2204
+
}
2205
+
}
2206
+
},
2207
+
"node_modules/@radix-ui/react-context-menu": {
2208
+
"version": "2.2.16",
2209
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz",
2210
+
"integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==",
2211
+
"dependencies": {
2212
+
"@radix-ui/primitive": "1.1.3",
2213
+
"@radix-ui/react-context": "1.1.2",
2214
+
"@radix-ui/react-menu": "2.1.16",
2215
+
"@radix-ui/react-primitive": "2.1.3",
2216
+
"@radix-ui/react-use-callback-ref": "1.1.1",
2217
+
"@radix-ui/react-use-controllable-state": "1.2.2"
2218
+
},
2219
+
"peerDependencies": {
2220
+
"@types/react": "*",
2221
+
"@types/react-dom": "*",
2222
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2223
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2224
+
},
2225
+
"peerDependenciesMeta": {
2226
+
"@types/react": {
2227
+
"optional": true
2228
+
},
2229
+
"@types/react-dom": {
2230
+
"optional": true
2231
+
}
2232
+
}
2233
+
},
2234
+
"node_modules/@radix-ui/react-dialog": {
2235
+
"version": "1.1.15",
2236
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
2237
+
"integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==",
2238
+
"dependencies": {
2239
+
"@radix-ui/primitive": "1.1.3",
2240
+
"@radix-ui/react-compose-refs": "1.1.2",
2241
+
"@radix-ui/react-context": "1.1.2",
2242
+
"@radix-ui/react-dismissable-layer": "1.1.11",
2243
+
"@radix-ui/react-focus-guards": "1.1.3",
2244
+
"@radix-ui/react-focus-scope": "1.1.7",
2245
+
"@radix-ui/react-id": "1.1.1",
2246
+
"@radix-ui/react-portal": "1.1.9",
2247
+
"@radix-ui/react-presence": "1.1.5",
2248
+
"@radix-ui/react-primitive": "2.1.3",
2249
+
"@radix-ui/react-slot": "1.2.3",
2250
+
"@radix-ui/react-use-controllable-state": "1.2.2",
2251
+
"aria-hidden": "^1.2.4",
2252
+
"react-remove-scroll": "^2.6.3"
2253
+
},
2254
+
"peerDependencies": {
2255
+
"@types/react": "*",
2256
+
"@types/react-dom": "*",
2257
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2258
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2259
+
},
2260
+
"peerDependenciesMeta": {
2261
+
"@types/react": {
2262
+
"optional": true
2263
+
},
2264
+
"@types/react-dom": {
2265
+
"optional": true
2266
+
}
2267
+
}
2268
+
},
2269
+
"node_modules/@radix-ui/react-direction": {
2270
+
"version": "1.1.1",
2271
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
2272
+
"integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
2273
+
"peerDependencies": {
2274
+
"@types/react": "*",
2275
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2276
+
},
2277
+
"peerDependenciesMeta": {
2278
+
"@types/react": {
2279
+
"optional": true
2280
+
}
2281
+
}
2282
+
},
2283
+
"node_modules/@radix-ui/react-dismissable-layer": {
2284
+
"version": "1.1.11",
2285
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
2286
+
"integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
2287
+
"dependencies": {
2288
+
"@radix-ui/primitive": "1.1.3",
2289
+
"@radix-ui/react-compose-refs": "1.1.2",
2290
+
"@radix-ui/react-primitive": "2.1.3",
2291
+
"@radix-ui/react-use-callback-ref": "1.1.1",
2292
+
"@radix-ui/react-use-escape-keydown": "1.1.1"
2293
+
},
2294
+
"peerDependencies": {
2295
+
"@types/react": "*",
2296
+
"@types/react-dom": "*",
2297
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2298
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2299
+
},
2300
+
"peerDependenciesMeta": {
2301
+
"@types/react": {
2302
+
"optional": true
2303
+
},
2304
+
"@types/react-dom": {
2305
+
"optional": true
2306
+
}
2307
+
}
2308
+
},
2309
+
"node_modules/@radix-ui/react-dropdown-menu": {
2310
+
"version": "2.1.16",
2311
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz",
2312
+
"integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==",
2313
+
"dependencies": {
2314
+
"@radix-ui/primitive": "1.1.3",
2315
+
"@radix-ui/react-compose-refs": "1.1.2",
2316
+
"@radix-ui/react-context": "1.1.2",
2317
+
"@radix-ui/react-id": "1.1.1",
2318
+
"@radix-ui/react-menu": "2.1.16",
2319
+
"@radix-ui/react-primitive": "2.1.3",
2320
+
"@radix-ui/react-use-controllable-state": "1.2.2"
2321
+
},
2322
+
"peerDependencies": {
2323
+
"@types/react": "*",
2324
+
"@types/react-dom": "*",
2325
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2326
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2327
+
},
2328
+
"peerDependenciesMeta": {
2329
+
"@types/react": {
2330
+
"optional": true
2331
+
},
2332
+
"@types/react-dom": {
2333
+
"optional": true
2334
+
}
2335
+
}
2336
+
},
2337
+
"node_modules/@radix-ui/react-focus-guards": {
2338
+
"version": "1.1.3",
2339
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
2340
+
"integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
2341
+
"peerDependencies": {
2342
+
"@types/react": "*",
2343
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2344
+
},
2345
+
"peerDependenciesMeta": {
2346
+
"@types/react": {
2347
+
"optional": true
2348
+
}
2349
+
}
2350
+
},
2351
+
"node_modules/@radix-ui/react-focus-scope": {
2352
+
"version": "1.1.7",
2353
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
2354
+
"integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
2355
+
"dependencies": {
2356
+
"@radix-ui/react-compose-refs": "1.1.2",
2357
+
"@radix-ui/react-primitive": "2.1.3",
2358
+
"@radix-ui/react-use-callback-ref": "1.1.1"
2359
+
},
2360
+
"peerDependencies": {
2361
+
"@types/react": "*",
2362
+
"@types/react-dom": "*",
2363
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2364
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2365
+
},
2366
+
"peerDependenciesMeta": {
2367
+
"@types/react": {
2368
+
"optional": true
2369
+
},
2370
+
"@types/react-dom": {
2371
+
"optional": true
2372
+
}
2373
+
}
2374
+
},
2375
+
"node_modules/@radix-ui/react-form": {
2376
+
"version": "0.1.8",
2377
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-form/-/react-form-0.1.8.tgz",
2378
+
"integrity": "sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==",
2379
+
"dependencies": {
2380
+
"@radix-ui/primitive": "1.1.3",
2381
+
"@radix-ui/react-compose-refs": "1.1.2",
2382
+
"@radix-ui/react-context": "1.1.2",
2383
+
"@radix-ui/react-id": "1.1.1",
2384
+
"@radix-ui/react-label": "2.1.7",
2385
+
"@radix-ui/react-primitive": "2.1.3"
2386
+
},
2387
+
"peerDependencies": {
2388
+
"@types/react": "*",
2389
+
"@types/react-dom": "*",
2390
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2391
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2392
+
},
2393
+
"peerDependenciesMeta": {
2394
+
"@types/react": {
2395
+
"optional": true
2396
+
},
2397
+
"@types/react-dom": {
2398
+
"optional": true
2399
+
}
2400
+
}
2401
+
},
2402
+
"node_modules/@radix-ui/react-hover-card": {
2403
+
"version": "1.1.15",
2404
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz",
2405
+
"integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==",
2406
+
"license": "MIT",
2407
+
"dependencies": {
2408
+
"@radix-ui/primitive": "1.1.3",
2409
+
"@radix-ui/react-compose-refs": "1.1.2",
2410
+
"@radix-ui/react-context": "1.1.2",
2411
+
"@radix-ui/react-dismissable-layer": "1.1.11",
2412
+
"@radix-ui/react-popper": "1.2.8",
2413
+
"@radix-ui/react-portal": "1.1.9",
2414
+
"@radix-ui/react-presence": "1.1.5",
2415
+
"@radix-ui/react-primitive": "2.1.3",
2416
+
"@radix-ui/react-use-controllable-state": "1.2.2"
2417
+
},
2418
+
"peerDependencies": {
2419
+
"@types/react": "*",
2420
+
"@types/react-dom": "*",
2421
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2422
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2423
+
},
2424
+
"peerDependenciesMeta": {
2425
+
"@types/react": {
2426
+
"optional": true
2427
+
},
2428
+
"@types/react-dom": {
2429
+
"optional": true
2430
+
}
2431
+
}
2432
+
},
2433
+
"node_modules/@radix-ui/react-id": {
2434
+
"version": "1.1.1",
2435
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
2436
+
"integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
2437
+
"dependencies": {
2438
+
"@radix-ui/react-use-layout-effect": "1.1.1"
2439
+
},
2440
+
"peerDependencies": {
2441
+
"@types/react": "*",
2442
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2443
+
},
2444
+
"peerDependenciesMeta": {
2445
+
"@types/react": {
2446
+
"optional": true
2447
+
}
2448
+
}
2449
+
},
2450
+
"node_modules/@radix-ui/react-label": {
2451
+
"version": "2.1.7",
2452
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz",
2453
+
"integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==",
2454
+
"dependencies": {
2455
+
"@radix-ui/react-primitive": "2.1.3"
2456
+
},
2457
+
"peerDependencies": {
2458
+
"@types/react": "*",
2459
+
"@types/react-dom": "*",
2460
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2461
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2462
+
},
2463
+
"peerDependenciesMeta": {
2464
+
"@types/react": {
2465
+
"optional": true
2466
+
},
2467
+
"@types/react-dom": {
2468
+
"optional": true
2469
+
}
2470
+
}
2471
+
},
2472
+
"node_modules/@radix-ui/react-menu": {
2473
+
"version": "2.1.16",
2474
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz",
2475
+
"integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==",
2476
+
"dependencies": {
2477
+
"@radix-ui/primitive": "1.1.3",
2478
+
"@radix-ui/react-collection": "1.1.7",
2479
+
"@radix-ui/react-compose-refs": "1.1.2",
2480
+
"@radix-ui/react-context": "1.1.2",
2481
+
"@radix-ui/react-direction": "1.1.1",
2482
+
"@radix-ui/react-dismissable-layer": "1.1.11",
2483
+
"@radix-ui/react-focus-guards": "1.1.3",
2484
+
"@radix-ui/react-focus-scope": "1.1.7",
2485
+
"@radix-ui/react-id": "1.1.1",
2486
+
"@radix-ui/react-popper": "1.2.8",
2487
+
"@radix-ui/react-portal": "1.1.9",
2488
+
"@radix-ui/react-presence": "1.1.5",
2489
+
"@radix-ui/react-primitive": "2.1.3",
2490
+
"@radix-ui/react-roving-focus": "1.1.11",
2491
+
"@radix-ui/react-slot": "1.2.3",
2492
+
"@radix-ui/react-use-callback-ref": "1.1.1",
2493
+
"aria-hidden": "^1.2.4",
2494
+
"react-remove-scroll": "^2.6.3"
2495
+
},
2496
+
"peerDependencies": {
2497
+
"@types/react": "*",
2498
+
"@types/react-dom": "*",
2499
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2500
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2501
+
},
2502
+
"peerDependenciesMeta": {
2503
+
"@types/react": {
2504
+
"optional": true
2505
+
},
2506
+
"@types/react-dom": {
2507
+
"optional": true
2508
+
}
2509
+
}
2510
+
},
2511
+
"node_modules/@radix-ui/react-menubar": {
2512
+
"version": "1.1.16",
2513
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.16.tgz",
2514
+
"integrity": "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==",
2515
+
"dependencies": {
2516
+
"@radix-ui/primitive": "1.1.3",
2517
+
"@radix-ui/react-collection": "1.1.7",
2518
+
"@radix-ui/react-compose-refs": "1.1.2",
2519
+
"@radix-ui/react-context": "1.1.2",
2520
+
"@radix-ui/react-direction": "1.1.1",
2521
+
"@radix-ui/react-id": "1.1.1",
2522
+
"@radix-ui/react-menu": "2.1.16",
2523
+
"@radix-ui/react-primitive": "2.1.3",
2524
+
"@radix-ui/react-roving-focus": "1.1.11",
2525
+
"@radix-ui/react-use-controllable-state": "1.2.2"
2526
+
},
2527
+
"peerDependencies": {
2528
+
"@types/react": "*",
2529
+
"@types/react-dom": "*",
2530
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2531
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2532
+
},
2533
+
"peerDependenciesMeta": {
2534
+
"@types/react": {
2535
+
"optional": true
2536
+
},
2537
+
"@types/react-dom": {
2538
+
"optional": true
2539
+
}
2540
+
}
2541
+
},
2542
+
"node_modules/@radix-ui/react-navigation-menu": {
2543
+
"version": "1.2.14",
2544
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz",
2545
+
"integrity": "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==",
2546
+
"dependencies": {
2547
+
"@radix-ui/primitive": "1.1.3",
2548
+
"@radix-ui/react-collection": "1.1.7",
2549
+
"@radix-ui/react-compose-refs": "1.1.2",
2550
+
"@radix-ui/react-context": "1.1.2",
2551
+
"@radix-ui/react-direction": "1.1.1",
2552
+
"@radix-ui/react-dismissable-layer": "1.1.11",
2553
+
"@radix-ui/react-id": "1.1.1",
2554
+
"@radix-ui/react-presence": "1.1.5",
2555
+
"@radix-ui/react-primitive": "2.1.3",
2556
+
"@radix-ui/react-use-callback-ref": "1.1.1",
2557
+
"@radix-ui/react-use-controllable-state": "1.2.2",
2558
+
"@radix-ui/react-use-layout-effect": "1.1.1",
2559
+
"@radix-ui/react-use-previous": "1.1.1",
2560
+
"@radix-ui/react-visually-hidden": "1.2.3"
2561
+
},
2562
+
"peerDependencies": {
2563
+
"@types/react": "*",
2564
+
"@types/react-dom": "*",
2565
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2566
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2567
+
},
2568
+
"peerDependenciesMeta": {
2569
+
"@types/react": {
2570
+
"optional": true
2571
+
},
2572
+
"@types/react-dom": {
2573
+
"optional": true
2574
+
}
2575
+
}
2576
+
},
2577
+
"node_modules/@radix-ui/react-one-time-password-field": {
2578
+
"version": "0.1.8",
2579
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-one-time-password-field/-/react-one-time-password-field-0.1.8.tgz",
2580
+
"integrity": "sha512-ycS4rbwURavDPVjCb5iS3aG4lURFDILi6sKI/WITUMZ13gMmn/xGjpLoqBAalhJaDk8I3UbCM5GzKHrnzwHbvg==",
2581
+
"dependencies": {
2582
+
"@radix-ui/number": "1.1.1",
2583
+
"@radix-ui/primitive": "1.1.3",
2584
+
"@radix-ui/react-collection": "1.1.7",
2585
+
"@radix-ui/react-compose-refs": "1.1.2",
2586
+
"@radix-ui/react-context": "1.1.2",
2587
+
"@radix-ui/react-direction": "1.1.1",
2588
+
"@radix-ui/react-primitive": "2.1.3",
2589
+
"@radix-ui/react-roving-focus": "1.1.11",
2590
+
"@radix-ui/react-use-controllable-state": "1.2.2",
2591
+
"@radix-ui/react-use-effect-event": "0.0.2",
2592
+
"@radix-ui/react-use-is-hydrated": "0.1.0",
2593
+
"@radix-ui/react-use-layout-effect": "1.1.1"
2594
+
},
2595
+
"peerDependencies": {
2596
+
"@types/react": "*",
2597
+
"@types/react-dom": "*",
2598
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2599
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2600
+
},
2601
+
"peerDependenciesMeta": {
2602
+
"@types/react": {
2603
+
"optional": true
2604
+
},
2605
+
"@types/react-dom": {
2606
+
"optional": true
2607
+
}
2608
+
}
2609
+
},
2610
+
"node_modules/@radix-ui/react-password-toggle-field": {
2611
+
"version": "0.1.3",
2612
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-password-toggle-field/-/react-password-toggle-field-0.1.3.tgz",
2613
+
"integrity": "sha512-/UuCrDBWravcaMix4TdT+qlNdVwOM1Nck9kWx/vafXsdfj1ChfhOdfi3cy9SGBpWgTXwYCuboT/oYpJy3clqfw==",
2614
+
"dependencies": {
2615
+
"@radix-ui/primitive": "1.1.3",
2616
+
"@radix-ui/react-compose-refs": "1.1.2",
2617
+
"@radix-ui/react-context": "1.1.2",
2618
+
"@radix-ui/react-id": "1.1.1",
2619
+
"@radix-ui/react-primitive": "2.1.3",
2620
+
"@radix-ui/react-use-controllable-state": "1.2.2",
2621
+
"@radix-ui/react-use-effect-event": "0.0.2",
2622
+
"@radix-ui/react-use-is-hydrated": "0.1.0"
2623
+
},
2624
+
"peerDependencies": {
2625
+
"@types/react": "*",
2626
+
"@types/react-dom": "*",
2627
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2628
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2629
+
},
2630
+
"peerDependenciesMeta": {
2631
+
"@types/react": {
2632
+
"optional": true
2633
+
},
2634
+
"@types/react-dom": {
2635
+
"optional": true
2636
+
}
2637
+
}
2638
+
},
2639
+
"node_modules/@radix-ui/react-popover": {
2640
+
"version": "1.1.15",
2641
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz",
2642
+
"integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==",
2643
+
"dependencies": {
2644
+
"@radix-ui/primitive": "1.1.3",
2645
+
"@radix-ui/react-compose-refs": "1.1.2",
2646
+
"@radix-ui/react-context": "1.1.2",
2647
+
"@radix-ui/react-dismissable-layer": "1.1.11",
2648
+
"@radix-ui/react-focus-guards": "1.1.3",
2649
+
"@radix-ui/react-focus-scope": "1.1.7",
2650
+
"@radix-ui/react-id": "1.1.1",
2651
+
"@radix-ui/react-popper": "1.2.8",
2652
+
"@radix-ui/react-portal": "1.1.9",
2653
+
"@radix-ui/react-presence": "1.1.5",
2654
+
"@radix-ui/react-primitive": "2.1.3",
2655
+
"@radix-ui/react-slot": "1.2.3",
2656
+
"@radix-ui/react-use-controllable-state": "1.2.2",
2657
+
"aria-hidden": "^1.2.4",
2658
+
"react-remove-scroll": "^2.6.3"
2659
+
},
2660
+
"peerDependencies": {
2661
+
"@types/react": "*",
2662
+
"@types/react-dom": "*",
2663
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2664
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2665
+
},
2666
+
"peerDependenciesMeta": {
2667
+
"@types/react": {
2668
+
"optional": true
2669
+
},
2670
+
"@types/react-dom": {
2671
+
"optional": true
2672
+
}
2673
+
}
2674
+
},
2675
+
"node_modules/@radix-ui/react-popper": {
2676
+
"version": "1.2.8",
2677
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
2678
+
"integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
2679
+
"dependencies": {
2680
+
"@floating-ui/react-dom": "^2.0.0",
2681
+
"@radix-ui/react-arrow": "1.1.7",
2682
+
"@radix-ui/react-compose-refs": "1.1.2",
2683
+
"@radix-ui/react-context": "1.1.2",
2684
+
"@radix-ui/react-primitive": "2.1.3",
2685
+
"@radix-ui/react-use-callback-ref": "1.1.1",
2686
+
"@radix-ui/react-use-layout-effect": "1.1.1",
2687
+
"@radix-ui/react-use-rect": "1.1.1",
2688
+
"@radix-ui/react-use-size": "1.1.1",
2689
+
"@radix-ui/rect": "1.1.1"
2690
+
},
2691
+
"peerDependencies": {
2692
+
"@types/react": "*",
2693
+
"@types/react-dom": "*",
2694
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2695
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2696
+
},
2697
+
"peerDependenciesMeta": {
2698
+
"@types/react": {
2699
+
"optional": true
2700
+
},
2701
+
"@types/react-dom": {
2702
+
"optional": true
2703
+
}
2704
+
}
2705
+
},
2706
+
"node_modules/@radix-ui/react-portal": {
2707
+
"version": "1.1.9",
2708
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
2709
+
"integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
2710
+
"dependencies": {
2711
+
"@radix-ui/react-primitive": "2.1.3",
2712
+
"@radix-ui/react-use-layout-effect": "1.1.1"
2713
+
},
2714
+
"peerDependencies": {
2715
+
"@types/react": "*",
2716
+
"@types/react-dom": "*",
2717
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2718
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2719
+
},
2720
+
"peerDependenciesMeta": {
2721
+
"@types/react": {
2722
+
"optional": true
2723
+
},
2724
+
"@types/react-dom": {
2725
+
"optional": true
2726
+
}
2727
+
}
2728
+
},
2729
+
"node_modules/@radix-ui/react-presence": {
2730
+
"version": "1.1.5",
2731
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
2732
+
"integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
2733
+
"dependencies": {
2734
+
"@radix-ui/react-compose-refs": "1.1.2",
2735
+
"@radix-ui/react-use-layout-effect": "1.1.1"
2736
+
},
2737
+
"peerDependencies": {
2738
+
"@types/react": "*",
2739
+
"@types/react-dom": "*",
2740
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2741
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2742
+
},
2743
+
"peerDependenciesMeta": {
2744
+
"@types/react": {
2745
+
"optional": true
2746
+
},
2747
+
"@types/react-dom": {
2748
+
"optional": true
2749
+
}
2750
+
}
2751
+
},
2752
+
"node_modules/@radix-ui/react-primitive": {
2753
+
"version": "2.1.3",
2754
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
2755
+
"integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
2756
+
"dependencies": {
2757
+
"@radix-ui/react-slot": "1.2.3"
2758
+
},
2759
+
"peerDependencies": {
2760
+
"@types/react": "*",
2761
+
"@types/react-dom": "*",
2762
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2763
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2764
+
},
2765
+
"peerDependenciesMeta": {
2766
+
"@types/react": {
2767
+
"optional": true
2768
+
},
2769
+
"@types/react-dom": {
2770
+
"optional": true
2771
+
}
2772
+
}
2773
+
},
2774
+
"node_modules/@radix-ui/react-progress": {
2775
+
"version": "1.1.7",
2776
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz",
2777
+
"integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==",
2778
+
"dependencies": {
2779
+
"@radix-ui/react-context": "1.1.2",
2780
+
"@radix-ui/react-primitive": "2.1.3"
2781
+
},
2782
+
"peerDependencies": {
2783
+
"@types/react": "*",
2784
+
"@types/react-dom": "*",
2785
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2786
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2787
+
},
2788
+
"peerDependenciesMeta": {
2789
+
"@types/react": {
2790
+
"optional": true
2791
+
},
2792
+
"@types/react-dom": {
2793
+
"optional": true
2794
+
}
2795
+
}
2796
+
},
2797
+
"node_modules/@radix-ui/react-radio-group": {
2798
+
"version": "1.3.8",
2799
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz",
2800
+
"integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==",
2801
+
"dependencies": {
2802
+
"@radix-ui/primitive": "1.1.3",
2803
+
"@radix-ui/react-compose-refs": "1.1.2",
2804
+
"@radix-ui/react-context": "1.1.2",
2805
+
"@radix-ui/react-direction": "1.1.1",
2806
+
"@radix-ui/react-presence": "1.1.5",
2807
+
"@radix-ui/react-primitive": "2.1.3",
2808
+
"@radix-ui/react-roving-focus": "1.1.11",
2809
+
"@radix-ui/react-use-controllable-state": "1.2.2",
2810
+
"@radix-ui/react-use-previous": "1.1.1",
2811
+
"@radix-ui/react-use-size": "1.1.1"
2812
+
},
2813
+
"peerDependencies": {
2814
+
"@types/react": "*",
2815
+
"@types/react-dom": "*",
2816
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2817
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2818
+
},
2819
+
"peerDependenciesMeta": {
2820
+
"@types/react": {
2821
+
"optional": true
2822
+
},
2823
+
"@types/react-dom": {
2824
+
"optional": true
2825
+
}
2826
+
}
2827
+
},
2828
+
"node_modules/@radix-ui/react-roving-focus": {
2829
+
"version": "1.1.11",
2830
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz",
2831
+
"integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==",
2832
+
"dependencies": {
2833
+
"@radix-ui/primitive": "1.1.3",
2834
+
"@radix-ui/react-collection": "1.1.7",
2835
+
"@radix-ui/react-compose-refs": "1.1.2",
2836
+
"@radix-ui/react-context": "1.1.2",
2837
+
"@radix-ui/react-direction": "1.1.1",
2838
+
"@radix-ui/react-id": "1.1.1",
2839
+
"@radix-ui/react-primitive": "2.1.3",
2840
+
"@radix-ui/react-use-callback-ref": "1.1.1",
2841
+
"@radix-ui/react-use-controllable-state": "1.2.2"
2842
+
},
2843
+
"peerDependencies": {
2844
+
"@types/react": "*",
2845
+
"@types/react-dom": "*",
2846
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2847
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2848
+
},
2849
+
"peerDependenciesMeta": {
2850
+
"@types/react": {
2851
+
"optional": true
2852
+
},
2853
+
"@types/react-dom": {
2854
+
"optional": true
2855
+
}
2856
+
}
2857
+
},
2858
+
"node_modules/@radix-ui/react-scroll-area": {
2859
+
"version": "1.2.10",
2860
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz",
2861
+
"integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==",
2862
+
"dependencies": {
2863
+
"@radix-ui/number": "1.1.1",
2864
+
"@radix-ui/primitive": "1.1.3",
2865
+
"@radix-ui/react-compose-refs": "1.1.2",
2866
+
"@radix-ui/react-context": "1.1.2",
2867
+
"@radix-ui/react-direction": "1.1.1",
2868
+
"@radix-ui/react-presence": "1.1.5",
2869
+
"@radix-ui/react-primitive": "2.1.3",
2870
+
"@radix-ui/react-use-callback-ref": "1.1.1",
2871
+
"@radix-ui/react-use-layout-effect": "1.1.1"
2872
+
},
2873
+
"peerDependencies": {
2874
+
"@types/react": "*",
2875
+
"@types/react-dom": "*",
2876
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2877
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2878
+
},
2879
+
"peerDependenciesMeta": {
2880
+
"@types/react": {
2881
+
"optional": true
2882
+
},
2883
+
"@types/react-dom": {
2884
+
"optional": true
2885
+
}
2886
+
}
2887
+
},
2888
+
"node_modules/@radix-ui/react-select": {
2889
+
"version": "2.2.6",
2890
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz",
2891
+
"integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==",
2892
+
"dependencies": {
2893
+
"@radix-ui/number": "1.1.1",
2894
+
"@radix-ui/primitive": "1.1.3",
2895
+
"@radix-ui/react-collection": "1.1.7",
2896
+
"@radix-ui/react-compose-refs": "1.1.2",
2897
+
"@radix-ui/react-context": "1.1.2",
2898
+
"@radix-ui/react-direction": "1.1.1",
2899
+
"@radix-ui/react-dismissable-layer": "1.1.11",
2900
+
"@radix-ui/react-focus-guards": "1.1.3",
2901
+
"@radix-ui/react-focus-scope": "1.1.7",
2902
+
"@radix-ui/react-id": "1.1.1",
2903
+
"@radix-ui/react-popper": "1.2.8",
2904
+
"@radix-ui/react-portal": "1.1.9",
2905
+
"@radix-ui/react-primitive": "2.1.3",
2906
+
"@radix-ui/react-slot": "1.2.3",
2907
+
"@radix-ui/react-use-callback-ref": "1.1.1",
2908
+
"@radix-ui/react-use-controllable-state": "1.2.2",
2909
+
"@radix-ui/react-use-layout-effect": "1.1.1",
2910
+
"@radix-ui/react-use-previous": "1.1.1",
2911
+
"@radix-ui/react-visually-hidden": "1.2.3",
2912
+
"aria-hidden": "^1.2.4",
2913
+
"react-remove-scroll": "^2.6.3"
2914
+
},
2915
+
"peerDependencies": {
2916
+
"@types/react": "*",
2917
+
"@types/react-dom": "*",
2918
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2919
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2920
+
},
2921
+
"peerDependenciesMeta": {
2922
+
"@types/react": {
2923
+
"optional": true
2924
+
},
2925
+
"@types/react-dom": {
2926
+
"optional": true
2927
+
}
2928
+
}
2929
+
},
2930
+
"node_modules/@radix-ui/react-separator": {
2931
+
"version": "1.1.7",
2932
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz",
2933
+
"integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==",
2934
+
"dependencies": {
2935
+
"@radix-ui/react-primitive": "2.1.3"
2936
+
},
2937
+
"peerDependencies": {
2938
+
"@types/react": "*",
2939
+
"@types/react-dom": "*",
2940
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2941
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2942
+
},
2943
+
"peerDependenciesMeta": {
2944
+
"@types/react": {
2945
+
"optional": true
2946
+
},
2947
+
"@types/react-dom": {
2948
+
"optional": true
2949
+
}
2950
+
}
2951
+
},
2952
+
"node_modules/@radix-ui/react-slider": {
2953
+
"version": "1.3.6",
2954
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz",
2955
+
"integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==",
2956
+
"dependencies": {
2957
+
"@radix-ui/number": "1.1.1",
2958
+
"@radix-ui/primitive": "1.1.3",
2959
+
"@radix-ui/react-collection": "1.1.7",
2960
+
"@radix-ui/react-compose-refs": "1.1.2",
2961
+
"@radix-ui/react-context": "1.1.2",
2962
+
"@radix-ui/react-direction": "1.1.1",
2963
+
"@radix-ui/react-primitive": "2.1.3",
2964
+
"@radix-ui/react-use-controllable-state": "1.2.2",
2965
+
"@radix-ui/react-use-layout-effect": "1.1.1",
2966
+
"@radix-ui/react-use-previous": "1.1.1",
2967
+
"@radix-ui/react-use-size": "1.1.1"
2968
+
},
2969
+
"peerDependencies": {
2970
+
"@types/react": "*",
2971
+
"@types/react-dom": "*",
2972
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
2973
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2974
+
},
2975
+
"peerDependenciesMeta": {
2976
+
"@types/react": {
2977
+
"optional": true
2978
+
},
2979
+
"@types/react-dom": {
2980
+
"optional": true
2981
+
}
2982
+
}
2983
+
},
2984
+
"node_modules/@radix-ui/react-slot": {
2985
+
"version": "1.2.3",
2986
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
2987
+
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
2988
+
"dependencies": {
2989
+
"@radix-ui/react-compose-refs": "1.1.2"
2990
+
},
2991
+
"peerDependencies": {
2992
+
"@types/react": "*",
2993
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
2994
+
},
2995
+
"peerDependenciesMeta": {
2996
+
"@types/react": {
2997
+
"optional": true
2998
+
}
2999
+
}
3000
+
},
3001
+
"node_modules/@radix-ui/react-switch": {
3002
+
"version": "1.2.6",
3003
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz",
3004
+
"integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==",
3005
+
"dependencies": {
3006
+
"@radix-ui/primitive": "1.1.3",
3007
+
"@radix-ui/react-compose-refs": "1.1.2",
3008
+
"@radix-ui/react-context": "1.1.2",
3009
+
"@radix-ui/react-primitive": "2.1.3",
3010
+
"@radix-ui/react-use-controllable-state": "1.2.2",
3011
+
"@radix-ui/react-use-previous": "1.1.1",
3012
+
"@radix-ui/react-use-size": "1.1.1"
3013
+
},
3014
+
"peerDependencies": {
3015
+
"@types/react": "*",
3016
+
"@types/react-dom": "*",
3017
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
3018
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3019
+
},
3020
+
"peerDependenciesMeta": {
3021
+
"@types/react": {
3022
+
"optional": true
3023
+
},
3024
+
"@types/react-dom": {
3025
+
"optional": true
3026
+
}
3027
+
}
3028
+
},
3029
+
"node_modules/@radix-ui/react-tabs": {
3030
+
"version": "1.1.13",
3031
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz",
3032
+
"integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==",
3033
+
"dependencies": {
3034
+
"@radix-ui/primitive": "1.1.3",
3035
+
"@radix-ui/react-context": "1.1.2",
3036
+
"@radix-ui/react-direction": "1.1.1",
3037
+
"@radix-ui/react-id": "1.1.1",
3038
+
"@radix-ui/react-presence": "1.1.5",
3039
+
"@radix-ui/react-primitive": "2.1.3",
3040
+
"@radix-ui/react-roving-focus": "1.1.11",
3041
+
"@radix-ui/react-use-controllable-state": "1.2.2"
3042
+
},
3043
+
"peerDependencies": {
3044
+
"@types/react": "*",
3045
+
"@types/react-dom": "*",
3046
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
3047
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3048
+
},
3049
+
"peerDependenciesMeta": {
3050
+
"@types/react": {
3051
+
"optional": true
3052
+
},
3053
+
"@types/react-dom": {
3054
+
"optional": true
3055
+
}
3056
+
}
3057
+
},
3058
+
"node_modules/@radix-ui/react-toast": {
3059
+
"version": "1.2.15",
3060
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.15.tgz",
3061
+
"integrity": "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==",
3062
+
"dependencies": {
3063
+
"@radix-ui/primitive": "1.1.3",
3064
+
"@radix-ui/react-collection": "1.1.7",
3065
+
"@radix-ui/react-compose-refs": "1.1.2",
3066
+
"@radix-ui/react-context": "1.1.2",
3067
+
"@radix-ui/react-dismissable-layer": "1.1.11",
3068
+
"@radix-ui/react-portal": "1.1.9",
3069
+
"@radix-ui/react-presence": "1.1.5",
3070
+
"@radix-ui/react-primitive": "2.1.3",
3071
+
"@radix-ui/react-use-callback-ref": "1.1.1",
3072
+
"@radix-ui/react-use-controllable-state": "1.2.2",
3073
+
"@radix-ui/react-use-layout-effect": "1.1.1",
3074
+
"@radix-ui/react-visually-hidden": "1.2.3"
3075
+
},
3076
+
"peerDependencies": {
3077
+
"@types/react": "*",
3078
+
"@types/react-dom": "*",
3079
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
3080
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3081
+
},
3082
+
"peerDependenciesMeta": {
3083
+
"@types/react": {
3084
+
"optional": true
3085
+
},
3086
+
"@types/react-dom": {
3087
+
"optional": true
3088
+
}
3089
+
}
3090
+
},
3091
+
"node_modules/@radix-ui/react-toggle": {
3092
+
"version": "1.1.10",
3093
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.10.tgz",
3094
+
"integrity": "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==",
3095
+
"dependencies": {
3096
+
"@radix-ui/primitive": "1.1.3",
3097
+
"@radix-ui/react-primitive": "2.1.3",
3098
+
"@radix-ui/react-use-controllable-state": "1.2.2"
3099
+
},
3100
+
"peerDependencies": {
3101
+
"@types/react": "*",
3102
+
"@types/react-dom": "*",
3103
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
3104
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3105
+
},
3106
+
"peerDependenciesMeta": {
3107
+
"@types/react": {
3108
+
"optional": true
3109
+
},
3110
+
"@types/react-dom": {
3111
+
"optional": true
3112
+
}
3113
+
}
3114
+
},
3115
+
"node_modules/@radix-ui/react-toggle-group": {
3116
+
"version": "1.1.11",
3117
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.11.tgz",
3118
+
"integrity": "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==",
3119
+
"dependencies": {
3120
+
"@radix-ui/primitive": "1.1.3",
3121
+
"@radix-ui/react-context": "1.1.2",
3122
+
"@radix-ui/react-direction": "1.1.1",
3123
+
"@radix-ui/react-primitive": "2.1.3",
3124
+
"@radix-ui/react-roving-focus": "1.1.11",
3125
+
"@radix-ui/react-toggle": "1.1.10",
3126
+
"@radix-ui/react-use-controllable-state": "1.2.2"
3127
+
},
3128
+
"peerDependencies": {
3129
+
"@types/react": "*",
3130
+
"@types/react-dom": "*",
3131
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
3132
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3133
+
},
3134
+
"peerDependenciesMeta": {
3135
+
"@types/react": {
3136
+
"optional": true
3137
+
},
3138
+
"@types/react-dom": {
3139
+
"optional": true
3140
+
}
3141
+
}
3142
+
},
3143
+
"node_modules/@radix-ui/react-toolbar": {
3144
+
"version": "1.1.11",
3145
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-toolbar/-/react-toolbar-1.1.11.tgz",
3146
+
"integrity": "sha512-4ol06/1bLoFu1nwUqzdD4Y5RZ9oDdKeiHIsntug54Hcr1pgaHiPqHFEaXI1IFP/EsOfROQZ8Mig9VTIRza6Tjg==",
3147
+
"dependencies": {
3148
+
"@radix-ui/primitive": "1.1.3",
3149
+
"@radix-ui/react-context": "1.1.2",
3150
+
"@radix-ui/react-direction": "1.1.1",
3151
+
"@radix-ui/react-primitive": "2.1.3",
3152
+
"@radix-ui/react-roving-focus": "1.1.11",
3153
+
"@radix-ui/react-separator": "1.1.7",
3154
+
"@radix-ui/react-toggle-group": "1.1.11"
3155
+
},
3156
+
"peerDependencies": {
3157
+
"@types/react": "*",
3158
+
"@types/react-dom": "*",
3159
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
3160
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3161
+
},
3162
+
"peerDependenciesMeta": {
3163
+
"@types/react": {
3164
+
"optional": true
3165
+
},
3166
+
"@types/react-dom": {
3167
+
"optional": true
3168
+
}
3169
+
}
3170
+
},
3171
+
"node_modules/@radix-ui/react-tooltip": {
3172
+
"version": "1.2.8",
3173
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
3174
+
"integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
3175
+
"dependencies": {
3176
+
"@radix-ui/primitive": "1.1.3",
3177
+
"@radix-ui/react-compose-refs": "1.1.2",
3178
+
"@radix-ui/react-context": "1.1.2",
3179
+
"@radix-ui/react-dismissable-layer": "1.1.11",
3180
+
"@radix-ui/react-id": "1.1.1",
3181
+
"@radix-ui/react-popper": "1.2.8",
3182
+
"@radix-ui/react-portal": "1.1.9",
3183
+
"@radix-ui/react-presence": "1.1.5",
3184
+
"@radix-ui/react-primitive": "2.1.3",
3185
+
"@radix-ui/react-slot": "1.2.3",
3186
+
"@radix-ui/react-use-controllable-state": "1.2.2",
3187
+
"@radix-ui/react-visually-hidden": "1.2.3"
3188
+
},
3189
+
"peerDependencies": {
3190
+
"@types/react": "*",
3191
+
"@types/react-dom": "*",
3192
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
3193
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3194
+
},
3195
+
"peerDependenciesMeta": {
3196
+
"@types/react": {
3197
+
"optional": true
3198
+
},
3199
+
"@types/react-dom": {
3200
+
"optional": true
3201
+
}
3202
+
}
3203
+
},
3204
+
"node_modules/@radix-ui/react-use-callback-ref": {
3205
+
"version": "1.1.1",
3206
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
3207
+
"integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
3208
+
"peerDependencies": {
3209
+
"@types/react": "*",
3210
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3211
+
},
3212
+
"peerDependenciesMeta": {
3213
+
"@types/react": {
3214
+
"optional": true
3215
+
}
3216
+
}
3217
+
},
3218
+
"node_modules/@radix-ui/react-use-controllable-state": {
3219
+
"version": "1.2.2",
3220
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
3221
+
"integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
3222
+
"dependencies": {
3223
+
"@radix-ui/react-use-effect-event": "0.0.2",
3224
+
"@radix-ui/react-use-layout-effect": "1.1.1"
3225
+
},
3226
+
"peerDependencies": {
3227
+
"@types/react": "*",
3228
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3229
+
},
3230
+
"peerDependenciesMeta": {
3231
+
"@types/react": {
3232
+
"optional": true
3233
+
}
3234
+
}
3235
+
},
3236
+
"node_modules/@radix-ui/react-use-effect-event": {
3237
+
"version": "0.0.2",
3238
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
3239
+
"integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
3240
+
"dependencies": {
3241
+
"@radix-ui/react-use-layout-effect": "1.1.1"
3242
+
},
3243
+
"peerDependencies": {
3244
+
"@types/react": "*",
3245
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3246
+
},
3247
+
"peerDependenciesMeta": {
3248
+
"@types/react": {
3249
+
"optional": true
3250
+
}
3251
+
}
3252
+
},
3253
+
"node_modules/@radix-ui/react-use-escape-keydown": {
3254
+
"version": "1.1.1",
3255
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
3256
+
"integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
3257
+
"dependencies": {
3258
+
"@radix-ui/react-use-callback-ref": "1.1.1"
3259
+
},
3260
+
"peerDependencies": {
3261
+
"@types/react": "*",
3262
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3263
+
},
3264
+
"peerDependenciesMeta": {
3265
+
"@types/react": {
3266
+
"optional": true
3267
+
}
3268
+
}
3269
+
},
3270
+
"node_modules/@radix-ui/react-use-is-hydrated": {
3271
+
"version": "0.1.0",
3272
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz",
3273
+
"integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==",
3274
+
"dependencies": {
3275
+
"use-sync-external-store": "^1.5.0"
3276
+
},
3277
+
"peerDependencies": {
3278
+
"@types/react": "*",
3279
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3280
+
},
3281
+
"peerDependenciesMeta": {
3282
+
"@types/react": {
3283
+
"optional": true
3284
+
}
3285
+
}
3286
+
},
3287
+
"node_modules/@radix-ui/react-use-layout-effect": {
3288
+
"version": "1.1.1",
3289
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
3290
+
"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
3291
+
"peerDependencies": {
3292
+
"@types/react": "*",
3293
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3294
+
},
3295
+
"peerDependenciesMeta": {
3296
+
"@types/react": {
3297
+
"optional": true
3298
+
}
3299
+
}
3300
+
},
3301
+
"node_modules/@radix-ui/react-use-previous": {
3302
+
"version": "1.1.1",
3303
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
3304
+
"integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
3305
+
"peerDependencies": {
3306
+
"@types/react": "*",
3307
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3308
+
},
3309
+
"peerDependenciesMeta": {
3310
+
"@types/react": {
3311
+
"optional": true
3312
+
}
3313
+
}
3314
+
},
3315
+
"node_modules/@radix-ui/react-use-rect": {
3316
+
"version": "1.1.1",
3317
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
3318
+
"integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
3319
+
"dependencies": {
3320
+
"@radix-ui/rect": "1.1.1"
3321
+
},
3322
+
"peerDependencies": {
3323
+
"@types/react": "*",
3324
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3325
+
},
3326
+
"peerDependenciesMeta": {
3327
+
"@types/react": {
3328
+
"optional": true
3329
+
}
3330
+
}
3331
+
},
3332
+
"node_modules/@radix-ui/react-use-size": {
3333
+
"version": "1.1.1",
3334
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
3335
+
"integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
3336
+
"dependencies": {
3337
+
"@radix-ui/react-use-layout-effect": "1.1.1"
3338
+
},
3339
+
"peerDependencies": {
3340
+
"@types/react": "*",
3341
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3342
+
},
3343
+
"peerDependenciesMeta": {
3344
+
"@types/react": {
3345
+
"optional": true
3346
+
}
3347
+
}
3348
+
},
3349
+
"node_modules/@radix-ui/react-visually-hidden": {
3350
+
"version": "1.2.3",
3351
+
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
3352
+
"integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
3353
+
"dependencies": {
3354
+
"@radix-ui/react-primitive": "2.1.3"
3355
+
},
3356
+
"peerDependencies": {
3357
+
"@types/react": "*",
3358
+
"@types/react-dom": "*",
3359
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
3360
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
3361
+
},
3362
+
"peerDependenciesMeta": {
3363
+
"@types/react": {
3364
+
"optional": true
3365
+
},
3366
+
"@types/react-dom": {
3367
+
"optional": true
3368
+
}
3369
+
}
3370
+
},
3371
+
"node_modules/@radix-ui/rect": {
3372
+
"version": "1.1.1",
3373
+
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
3374
+
"integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="
3375
+
},
3376
"node_modules/@rolldown/pluginutils": {
3377
"version": "1.0.0-beta.27",
3378
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
···
3687
"solid-js": "^1.6.12"
3688
}
3689
},
3690
+
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
3691
+
"version": "8.0.0",
3692
+
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
3693
+
"integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==",
3694
+
"dev": true,
3695
+
"license": "MIT",
3696
+
"engines": {
3697
+
"node": ">=14"
3698
+
},
3699
+
"funding": {
3700
+
"type": "github",
3701
+
"url": "https://github.com/sponsors/gregberge"
3702
+
},
3703
+
"peerDependencies": {
3704
+
"@babel/core": "^7.0.0-0"
3705
+
}
3706
+
},
3707
+
"node_modules/@svgr/babel-plugin-remove-jsx-attribute": {
3708
+
"version": "8.0.0",
3709
+
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz",
3710
+
"integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==",
3711
+
"dev": true,
3712
+
"license": "MIT",
3713
+
"engines": {
3714
+
"node": ">=14"
3715
+
},
3716
+
"funding": {
3717
+
"type": "github",
3718
+
"url": "https://github.com/sponsors/gregberge"
3719
+
},
3720
+
"peerDependencies": {
3721
+
"@babel/core": "^7.0.0-0"
3722
+
}
3723
+
},
3724
+
"node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": {
3725
+
"version": "8.0.0",
3726
+
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz",
3727
+
"integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==",
3728
+
"dev": true,
3729
+
"license": "MIT",
3730
+
"engines": {
3731
+
"node": ">=14"
3732
+
},
3733
+
"funding": {
3734
+
"type": "github",
3735
+
"url": "https://github.com/sponsors/gregberge"
3736
+
},
3737
+
"peerDependencies": {
3738
+
"@babel/core": "^7.0.0-0"
3739
+
}
3740
+
},
3741
+
"node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": {
3742
+
"version": "8.0.0",
3743
+
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz",
3744
+
"integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==",
3745
+
"dev": true,
3746
+
"license": "MIT",
3747
+
"engines": {
3748
+
"node": ">=14"
3749
+
},
3750
+
"funding": {
3751
+
"type": "github",
3752
+
"url": "https://github.com/sponsors/gregberge"
3753
+
},
3754
+
"peerDependencies": {
3755
+
"@babel/core": "^7.0.0-0"
3756
+
}
3757
+
},
3758
+
"node_modules/@svgr/babel-plugin-svg-dynamic-title": {
3759
+
"version": "8.0.0",
3760
+
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz",
3761
+
"integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==",
3762
+
"dev": true,
3763
+
"license": "MIT",
3764
+
"engines": {
3765
+
"node": ">=14"
3766
+
},
3767
+
"funding": {
3768
+
"type": "github",
3769
+
"url": "https://github.com/sponsors/gregberge"
3770
+
},
3771
+
"peerDependencies": {
3772
+
"@babel/core": "^7.0.0-0"
3773
+
}
3774
+
},
3775
+
"node_modules/@svgr/babel-plugin-svg-em-dimensions": {
3776
+
"version": "8.0.0",
3777
+
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz",
3778
+
"integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==",
3779
+
"dev": true,
3780
+
"license": "MIT",
3781
+
"engines": {
3782
+
"node": ">=14"
3783
+
},
3784
+
"funding": {
3785
+
"type": "github",
3786
+
"url": "https://github.com/sponsors/gregberge"
3787
+
},
3788
+
"peerDependencies": {
3789
+
"@babel/core": "^7.0.0-0"
3790
+
}
3791
+
},
3792
+
"node_modules/@svgr/babel-plugin-transform-react-native-svg": {
3793
+
"version": "8.1.0",
3794
+
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz",
3795
+
"integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==",
3796
+
"dev": true,
3797
+
"license": "MIT",
3798
+
"engines": {
3799
+
"node": ">=14"
3800
+
},
3801
+
"funding": {
3802
+
"type": "github",
3803
+
"url": "https://github.com/sponsors/gregberge"
3804
+
},
3805
+
"peerDependencies": {
3806
+
"@babel/core": "^7.0.0-0"
3807
+
}
3808
+
},
3809
+
"node_modules/@svgr/babel-plugin-transform-svg-component": {
3810
+
"version": "8.0.0",
3811
+
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz",
3812
+
"integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==",
3813
+
"dev": true,
3814
+
"license": "MIT",
3815
+
"engines": {
3816
+
"node": ">=12"
3817
+
},
3818
+
"funding": {
3819
+
"type": "github",
3820
+
"url": "https://github.com/sponsors/gregberge"
3821
+
},
3822
+
"peerDependencies": {
3823
+
"@babel/core": "^7.0.0-0"
3824
+
}
3825
+
},
3826
+
"node_modules/@svgr/babel-preset": {
3827
+
"version": "8.1.0",
3828
+
"resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz",
3829
+
"integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==",
3830
+
"dev": true,
3831
+
"license": "MIT",
3832
+
"dependencies": {
3833
+
"@svgr/babel-plugin-add-jsx-attribute": "8.0.0",
3834
+
"@svgr/babel-plugin-remove-jsx-attribute": "8.0.0",
3835
+
"@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0",
3836
+
"@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0",
3837
+
"@svgr/babel-plugin-svg-dynamic-title": "8.0.0",
3838
+
"@svgr/babel-plugin-svg-em-dimensions": "8.0.0",
3839
+
"@svgr/babel-plugin-transform-react-native-svg": "8.1.0",
3840
+
"@svgr/babel-plugin-transform-svg-component": "8.0.0"
3841
+
},
3842
+
"engines": {
3843
+
"node": ">=14"
3844
+
},
3845
+
"funding": {
3846
+
"type": "github",
3847
+
"url": "https://github.com/sponsors/gregberge"
3848
+
},
3849
+
"peerDependencies": {
3850
+
"@babel/core": "^7.0.0-0"
3851
+
}
3852
+
},
3853
+
"node_modules/@svgr/core": {
3854
+
"version": "8.1.0",
3855
+
"resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz",
3856
+
"integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==",
3857
+
"dev": true,
3858
+
"license": "MIT",
3859
+
"dependencies": {
3860
+
"@babel/core": "^7.21.3",
3861
+
"@svgr/babel-preset": "8.1.0",
3862
+
"camelcase": "^6.2.0",
3863
+
"cosmiconfig": "^8.1.3",
3864
+
"snake-case": "^3.0.4"
3865
+
},
3866
+
"engines": {
3867
+
"node": ">=14"
3868
+
},
3869
+
"funding": {
3870
+
"type": "github",
3871
+
"url": "https://github.com/sponsors/gregberge"
3872
+
}
3873
+
},
3874
+
"node_modules/@svgr/hast-util-to-babel-ast": {
3875
+
"version": "8.0.0",
3876
+
"resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz",
3877
+
"integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==",
3878
+
"dev": true,
3879
+
"license": "MIT",
3880
+
"dependencies": {
3881
+
"@babel/types": "^7.21.3",
3882
+
"entities": "^4.4.0"
3883
+
},
3884
+
"engines": {
3885
+
"node": ">=14"
3886
+
},
3887
+
"funding": {
3888
+
"type": "github",
3889
+
"url": "https://github.com/sponsors/gregberge"
3890
+
}
3891
+
},
3892
+
"node_modules/@svgr/hast-util-to-babel-ast/node_modules/entities": {
3893
+
"version": "4.5.0",
3894
+
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
3895
+
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
3896
+
"dev": true,
3897
+
"license": "BSD-2-Clause",
3898
+
"engines": {
3899
+
"node": ">=0.12"
3900
+
},
3901
+
"funding": {
3902
+
"url": "https://github.com/fb55/entities?sponsor=1"
3903
+
}
3904
+
},
3905
+
"node_modules/@svgr/plugin-jsx": {
3906
+
"version": "8.1.0",
3907
+
"resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz",
3908
+
"integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==",
3909
+
"dev": true,
3910
+
"license": "MIT",
3911
+
"dependencies": {
3912
+
"@babel/core": "^7.21.3",
3913
+
"@svgr/babel-preset": "8.1.0",
3914
+
"@svgr/hast-util-to-babel-ast": "8.0.0",
3915
+
"svg-parser": "^2.0.4"
3916
+
},
3917
+
"engines": {
3918
+
"node": ">=14"
3919
+
},
3920
+
"funding": {
3921
+
"type": "github",
3922
+
"url": "https://github.com/sponsors/gregberge"
3923
+
},
3924
+
"peerDependencies": {
3925
+
"@svgr/core": "*"
3926
+
}
3927
+
},
3928
"node_modules/@svta/common-media-library": {
3929
"version": "0.12.4",
3930
"resolved": "https://registry.npmjs.org/@svta/common-media-library/-/common-media-library-0.12.4.tgz",
···
4276
"url": "https://github.com/sponsors/tannerlinsley"
4277
}
4278
},
4279
+
"node_modules/@tanstack/query-persist-client-core": {
4280
+
"version": "5.85.6",
4281
+
"resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-5.85.6.tgz",
4282
+
"integrity": "sha512-wUdoEurIC0YCNZzR020Xcg3OsJeF4SXmEPqlNwZ6EaGKgWeNjU17hVdK+X4ZeirUm+h0muiEQx+aIQU1lk7roQ==",
4283
+
"license": "MIT",
4284
+
"dependencies": {
4285
+
"@tanstack/query-core": "5.85.6"
4286
+
},
4287
+
"funding": {
4288
+
"type": "github",
4289
+
"url": "https://github.com/sponsors/tannerlinsley"
4290
+
}
4291
+
},
4292
+
"node_modules/@tanstack/query-sync-storage-persister": {
4293
+
"version": "5.85.6",
4294
+
"resolved": "https://registry.npmjs.org/@tanstack/query-sync-storage-persister/-/query-sync-storage-persister-5.85.6.tgz",
4295
+
"integrity": "sha512-Gj/p0paYsdzj3IbRn6SjMMNdjZ0nVQWszn17qbHLiu3Mt6H0b/YbLL3g9uRWcoyYcaB004RawgM0MuA+xJt5iw==",
4296
+
"license": "MIT",
4297
+
"dependencies": {
4298
+
"@tanstack/query-core": "5.85.6",
4299
+
"@tanstack/query-persist-client-core": "5.85.6"
4300
+
},
4301
+
"funding": {
4302
+
"type": "github",
4303
+
"url": "https://github.com/sponsors/tannerlinsley"
4304
+
}
4305
+
},
4306
"node_modules/@tanstack/react-devtools": {
4307
"version": "0.2.2",
4308
"resolved": "https://registry.npmjs.org/@tanstack/react-devtools/-/react-devtools-0.2.2.tgz",
···
4338
"url": "https://github.com/sponsors/tannerlinsley"
4339
},
4340
"peerDependencies": {
4341
+
"react": "^18 || ^19"
4342
+
}
4343
+
},
4344
+
"node_modules/@tanstack/react-query-persist-client": {
4345
+
"version": "5.85.6",
4346
+
"resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-5.85.6.tgz",
4347
+
"integrity": "sha512-zLUfm8JlI6/s0AqvX5l5CcazdHwj5gwcv0mWYOaJJvADyFzl2wwQKqB/H4nYSeygUtrepBgPwVQKNqH9ZwlZpQ==",
4348
+
"license": "MIT",
4349
+
"dependencies": {
4350
+
"@tanstack/query-persist-client-core": "5.85.6"
4351
+
},
4352
+
"funding": {
4353
+
"type": "github",
4354
+
"url": "https://github.com/sponsors/tannerlinsley"
4355
+
},
4356
+
"peerDependencies": {
4357
+
"@tanstack/react-query": "^5.85.6",
4358
"react": "^18 || ^19"
4359
}
4360
},
···
4716
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
4717
"license": "MIT"
4718
},
4719
+
"node_modules/@types/json-schema": {
4720
+
"version": "7.0.15",
4721
+
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
4722
+
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
4723
+
"dev": true,
4724
+
"license": "MIT",
4725
+
"peer": true
4726
+
},
4727
"node_modules/@types/node": {
4728
"version": "24.3.0",
4729
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz",
···
4752
"@types/react": "^19.0.0"
4753
}
4754
},
4755
+
"node_modules/@types/trusted-types": {
4756
+
"version": "2.0.7",
4757
+
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
4758
+
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
4759
+
"license": "MIT",
4760
+
"optional": true
4761
+
},
4762
+
"node_modules/@typescript-eslint/eslint-plugin": {
4763
+
"version": "8.46.1",
4764
+
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.1.tgz",
4765
+
"integrity": "sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==",
4766
+
"dev": true,
4767
+
"license": "MIT",
4768
+
"dependencies": {
4769
+
"@eslint-community/regexpp": "^4.10.0",
4770
+
"@typescript-eslint/scope-manager": "8.46.1",
4771
+
"@typescript-eslint/type-utils": "8.46.1",
4772
+
"@typescript-eslint/utils": "8.46.1",
4773
+
"@typescript-eslint/visitor-keys": "8.46.1",
4774
+
"graphemer": "^1.4.0",
4775
+
"ignore": "^7.0.0",
4776
+
"natural-compare": "^1.4.0",
4777
+
"ts-api-utils": "^2.1.0"
4778
+
},
4779
+
"engines": {
4780
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
4781
+
},
4782
+
"funding": {
4783
+
"type": "opencollective",
4784
+
"url": "https://opencollective.com/typescript-eslint"
4785
+
},
4786
+
"peerDependencies": {
4787
+
"@typescript-eslint/parser": "^8.46.1",
4788
+
"eslint": "^8.57.0 || ^9.0.0",
4789
+
"typescript": ">=4.8.4 <6.0.0"
4790
+
}
4791
+
},
4792
+
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
4793
+
"version": "7.0.5",
4794
+
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
4795
+
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
4796
+
"dev": true,
4797
+
"license": "MIT",
4798
+
"engines": {
4799
+
"node": ">= 4"
4800
+
}
4801
+
},
4802
+
"node_modules/@typescript-eslint/parser": {
4803
+
"version": "8.46.1",
4804
+
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.1.tgz",
4805
+
"integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==",
4806
+
"dev": true,
4807
+
"license": "MIT",
4808
+
"dependencies": {
4809
+
"@typescript-eslint/scope-manager": "8.46.1",
4810
+
"@typescript-eslint/types": "8.46.1",
4811
+
"@typescript-eslint/typescript-estree": "8.46.1",
4812
+
"@typescript-eslint/visitor-keys": "8.46.1",
4813
+
"debug": "^4.3.4"
4814
+
},
4815
+
"engines": {
4816
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
4817
+
},
4818
+
"funding": {
4819
+
"type": "opencollective",
4820
+
"url": "https://opencollective.com/typescript-eslint"
4821
+
},
4822
+
"peerDependencies": {
4823
+
"eslint": "^8.57.0 || ^9.0.0",
4824
+
"typescript": ">=4.8.4 <6.0.0"
4825
+
}
4826
+
},
4827
+
"node_modules/@typescript-eslint/project-service": {
4828
+
"version": "8.46.1",
4829
+
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.1.tgz",
4830
+
"integrity": "sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==",
4831
+
"dev": true,
4832
+
"license": "MIT",
4833
+
"dependencies": {
4834
+
"@typescript-eslint/tsconfig-utils": "^8.46.1",
4835
+
"@typescript-eslint/types": "^8.46.1",
4836
+
"debug": "^4.3.4"
4837
+
},
4838
+
"engines": {
4839
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
4840
+
},
4841
+
"funding": {
4842
+
"type": "opencollective",
4843
+
"url": "https://opencollective.com/typescript-eslint"
4844
+
},
4845
+
"peerDependencies": {
4846
+
"typescript": ">=4.8.4 <6.0.0"
4847
+
}
4848
+
},
4849
+
"node_modules/@typescript-eslint/scope-manager": {
4850
+
"version": "8.46.1",
4851
+
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.1.tgz",
4852
+
"integrity": "sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==",
4853
+
"dev": true,
4854
+
"license": "MIT",
4855
+
"dependencies": {
4856
+
"@typescript-eslint/types": "8.46.1",
4857
+
"@typescript-eslint/visitor-keys": "8.46.1"
4858
+
},
4859
+
"engines": {
4860
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
4861
+
},
4862
+
"funding": {
4863
+
"type": "opencollective",
4864
+
"url": "https://opencollective.com/typescript-eslint"
4865
+
}
4866
+
},
4867
+
"node_modules/@typescript-eslint/tsconfig-utils": {
4868
+
"version": "8.46.1",
4869
+
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.1.tgz",
4870
+
"integrity": "sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==",
4871
+
"dev": true,
4872
+
"license": "MIT",
4873
+
"engines": {
4874
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
4875
+
},
4876
+
"funding": {
4877
+
"type": "opencollective",
4878
+
"url": "https://opencollective.com/typescript-eslint"
4879
+
},
4880
+
"peerDependencies": {
4881
+
"typescript": ">=4.8.4 <6.0.0"
4882
+
}
4883
+
},
4884
+
"node_modules/@typescript-eslint/type-utils": {
4885
+
"version": "8.46.1",
4886
+
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.1.tgz",
4887
+
"integrity": "sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw==",
4888
+
"dev": true,
4889
+
"license": "MIT",
4890
+
"dependencies": {
4891
+
"@typescript-eslint/types": "8.46.1",
4892
+
"@typescript-eslint/typescript-estree": "8.46.1",
4893
+
"@typescript-eslint/utils": "8.46.1",
4894
+
"debug": "^4.3.4",
4895
+
"ts-api-utils": "^2.1.0"
4896
+
},
4897
+
"engines": {
4898
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
4899
+
},
4900
+
"funding": {
4901
+
"type": "opencollective",
4902
+
"url": "https://opencollective.com/typescript-eslint"
4903
+
},
4904
+
"peerDependencies": {
4905
+
"eslint": "^8.57.0 || ^9.0.0",
4906
+
"typescript": ">=4.8.4 <6.0.0"
4907
+
}
4908
+
},
4909
+
"node_modules/@typescript-eslint/types": {
4910
+
"version": "8.46.1",
4911
+
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.1.tgz",
4912
+
"integrity": "sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==",
4913
+
"dev": true,
4914
+
"license": "MIT",
4915
+
"engines": {
4916
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
4917
+
},
4918
+
"funding": {
4919
+
"type": "opencollective",
4920
+
"url": "https://opencollective.com/typescript-eslint"
4921
+
}
4922
+
},
4923
+
"node_modules/@typescript-eslint/typescript-estree": {
4924
+
"version": "8.46.1",
4925
+
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.1.tgz",
4926
+
"integrity": "sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==",
4927
+
"dev": true,
4928
+
"license": "MIT",
4929
+
"dependencies": {
4930
+
"@typescript-eslint/project-service": "8.46.1",
4931
+
"@typescript-eslint/tsconfig-utils": "8.46.1",
4932
+
"@typescript-eslint/types": "8.46.1",
4933
+
"@typescript-eslint/visitor-keys": "8.46.1",
4934
+
"debug": "^4.3.4",
4935
+
"fast-glob": "^3.3.2",
4936
+
"is-glob": "^4.0.3",
4937
+
"minimatch": "^9.0.4",
4938
+
"semver": "^7.6.0",
4939
+
"ts-api-utils": "^2.1.0"
4940
+
},
4941
+
"engines": {
4942
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
4943
+
},
4944
+
"funding": {
4945
+
"type": "opencollective",
4946
+
"url": "https://opencollective.com/typescript-eslint"
4947
+
},
4948
+
"peerDependencies": {
4949
+
"typescript": ">=4.8.4 <6.0.0"
4950
+
}
4951
+
},
4952
+
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
4953
+
"version": "2.0.2",
4954
+
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
4955
+
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
4956
+
"dev": true,
4957
+
"license": "MIT",
4958
+
"dependencies": {
4959
+
"balanced-match": "^1.0.0"
4960
+
}
4961
+
},
4962
+
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
4963
+
"version": "9.0.5",
4964
+
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
4965
+
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
4966
+
"dev": true,
4967
+
"license": "ISC",
4968
+
"dependencies": {
4969
+
"brace-expansion": "^2.0.1"
4970
+
},
4971
+
"engines": {
4972
+
"node": ">=16 || 14 >=14.17"
4973
+
},
4974
+
"funding": {
4975
+
"url": "https://github.com/sponsors/isaacs"
4976
+
}
4977
+
},
4978
+
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
4979
+
"version": "7.7.3",
4980
+
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
4981
+
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
4982
+
"dev": true,
4983
+
"license": "ISC",
4984
+
"bin": {
4985
+
"semver": "bin/semver.js"
4986
+
},
4987
+
"engines": {
4988
+
"node": ">=10"
4989
+
}
4990
+
},
4991
+
"node_modules/@typescript-eslint/utils": {
4992
+
"version": "8.46.1",
4993
+
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.1.tgz",
4994
+
"integrity": "sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==",
4995
+
"dev": true,
4996
+
"license": "MIT",
4997
+
"dependencies": {
4998
+
"@eslint-community/eslint-utils": "^4.7.0",
4999
+
"@typescript-eslint/scope-manager": "8.46.1",
5000
+
"@typescript-eslint/types": "8.46.1",
5001
+
"@typescript-eslint/typescript-estree": "8.46.1"
5002
+
},
5003
+
"engines": {
5004
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
5005
+
},
5006
+
"funding": {
5007
+
"type": "opencollective",
5008
+
"url": "https://opencollective.com/typescript-eslint"
5009
+
},
5010
+
"peerDependencies": {
5011
+
"eslint": "^8.57.0 || ^9.0.0",
5012
+
"typescript": ">=4.8.4 <6.0.0"
5013
+
}
5014
+
},
5015
+
"node_modules/@typescript-eslint/visitor-keys": {
5016
+
"version": "8.46.1",
5017
+
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz",
5018
+
"integrity": "sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==",
5019
+
"dev": true,
5020
+
"license": "MIT",
5021
+
"dependencies": {
5022
+
"@typescript-eslint/types": "8.46.1",
5023
+
"eslint-visitor-keys": "^4.2.1"
5024
+
},
5025
+
"engines": {
5026
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
5027
+
},
5028
+
"funding": {
5029
+
"type": "opencollective",
5030
+
"url": "https://opencollective.com/typescript-eslint"
5031
+
}
5032
+
},
5033
"node_modules/@vercel/edge": {
5034
"version": "1.2.2",
5035
"resolved": "https://registry.npmjs.org/@vercel/edge/-/edge-1.2.2.tgz",
···
5194
"node": ">=0.4.0"
5195
}
5196
},
5197
+
"node_modules/acorn-jsx": {
5198
+
"version": "5.3.2",
5199
+
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
5200
+
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
5201
+
"dev": true,
5202
+
"license": "MIT",
5203
+
"peer": true,
5204
+
"peerDependencies": {
5205
+
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
5206
+
}
5207
+
},
5208
"node_modules/agent-base": {
5209
"version": "7.1.4",
5210
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
···
5215
"node": ">= 14"
5216
}
5217
},
5218
+
"node_modules/ajv": {
5219
+
"version": "6.12.6",
5220
+
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
5221
+
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
5222
+
"dev": true,
5223
+
"license": "MIT",
5224
+
"peer": true,
5225
+
"dependencies": {
5226
+
"fast-deep-equal": "^3.1.1",
5227
+
"fast-json-stable-stringify": "^2.0.0",
5228
+
"json-schema-traverse": "^0.4.1",
5229
+
"uri-js": "^4.2.2"
5230
+
},
5231
+
"funding": {
5232
+
"type": "github",
5233
+
"url": "https://github.com/sponsors/epoberezkin"
5234
+
}
5235
+
},
5236
"node_modules/ansi-regex": {
5237
"version": "5.0.1",
5238
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
···
5278
"node": ">= 8"
5279
}
5280
},
5281
+
"node_modules/argparse": {
5282
+
"version": "2.0.1",
5283
+
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
5284
+
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
5285
+
"dev": true,
5286
+
"license": "Python-2.0"
5287
+
},
5288
+
"node_modules/aria-hidden": {
5289
+
"version": "1.2.6",
5290
+
"resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
5291
+
"integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
5292
+
"dependencies": {
5293
+
"tslib": "^2.0.0"
5294
+
},
5295
+
"engines": {
5296
+
"node": ">=10"
5297
+
}
5298
+
},
5299
"node_modules/aria-query": {
5300
"version": "5.3.0",
5301
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
···
5306
"dequal": "^2.0.3"
5307
}
5308
},
5309
+
"node_modules/array-buffer-byte-length": {
5310
+
"version": "1.0.2",
5311
+
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
5312
+
"integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
5313
+
"dev": true,
5314
+
"license": "MIT",
5315
+
"dependencies": {
5316
+
"call-bound": "^1.0.3",
5317
+
"is-array-buffer": "^3.0.5"
5318
+
},
5319
+
"engines": {
5320
+
"node": ">= 0.4"
5321
+
},
5322
+
"funding": {
5323
+
"url": "https://github.com/sponsors/ljharb"
5324
+
}
5325
+
},
5326
+
"node_modules/array-includes": {
5327
+
"version": "3.1.9",
5328
+
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
5329
+
"integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
5330
+
"dev": true,
5331
+
"license": "MIT",
5332
+
"dependencies": {
5333
+
"call-bind": "^1.0.8",
5334
+
"call-bound": "^1.0.4",
5335
+
"define-properties": "^1.2.1",
5336
+
"es-abstract": "^1.24.0",
5337
+
"es-object-atoms": "^1.1.1",
5338
+
"get-intrinsic": "^1.3.0",
5339
+
"is-string": "^1.1.1",
5340
+
"math-intrinsics": "^1.1.0"
5341
+
},
5342
+
"engines": {
5343
+
"node": ">= 0.4"
5344
+
},
5345
+
"funding": {
5346
+
"url": "https://github.com/sponsors/ljharb"
5347
+
}
5348
+
},
5349
+
"node_modules/array.prototype.findlast": {
5350
+
"version": "1.2.5",
5351
+
"resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
5352
+
"integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
5353
+
"dev": true,
5354
+
"license": "MIT",
5355
+
"dependencies": {
5356
+
"call-bind": "^1.0.7",
5357
+
"define-properties": "^1.2.1",
5358
+
"es-abstract": "^1.23.2",
5359
+
"es-errors": "^1.3.0",
5360
+
"es-object-atoms": "^1.0.0",
5361
+
"es-shim-unscopables": "^1.0.2"
5362
+
},
5363
+
"engines": {
5364
+
"node": ">= 0.4"
5365
+
},
5366
+
"funding": {
5367
+
"url": "https://github.com/sponsors/ljharb"
5368
+
}
5369
+
},
5370
+
"node_modules/array.prototype.flat": {
5371
+
"version": "1.3.3",
5372
+
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
5373
+
"integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
5374
+
"dev": true,
5375
+
"license": "MIT",
5376
+
"dependencies": {
5377
+
"call-bind": "^1.0.8",
5378
+
"define-properties": "^1.2.1",
5379
+
"es-abstract": "^1.23.5",
5380
+
"es-shim-unscopables": "^1.0.2"
5381
+
},
5382
+
"engines": {
5383
+
"node": ">= 0.4"
5384
+
},
5385
+
"funding": {
5386
+
"url": "https://github.com/sponsors/ljharb"
5387
+
}
5388
+
},
5389
+
"node_modules/array.prototype.flatmap": {
5390
+
"version": "1.3.3",
5391
+
"resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
5392
+
"integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
5393
+
"dev": true,
5394
+
"license": "MIT",
5395
+
"dependencies": {
5396
+
"call-bind": "^1.0.8",
5397
+
"define-properties": "^1.2.1",
5398
+
"es-abstract": "^1.23.5",
5399
+
"es-shim-unscopables": "^1.0.2"
5400
+
},
5401
+
"engines": {
5402
+
"node": ">= 0.4"
5403
+
},
5404
+
"funding": {
5405
+
"url": "https://github.com/sponsors/ljharb"
5406
+
}
5407
+
},
5408
+
"node_modules/array.prototype.tosorted": {
5409
+
"version": "1.1.4",
5410
+
"resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
5411
+
"integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
5412
+
"dev": true,
5413
+
"license": "MIT",
5414
+
"dependencies": {
5415
+
"call-bind": "^1.0.7",
5416
+
"define-properties": "^1.2.1",
5417
+
"es-abstract": "^1.23.3",
5418
+
"es-errors": "^1.3.0",
5419
+
"es-shim-unscopables": "^1.0.2"
5420
+
},
5421
+
"engines": {
5422
+
"node": ">= 0.4"
5423
+
}
5424
+
},
5425
+
"node_modules/arraybuffer.prototype.slice": {
5426
+
"version": "1.0.4",
5427
+
"resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
5428
+
"integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
5429
+
"dev": true,
5430
+
"license": "MIT",
5431
+
"dependencies": {
5432
+
"array-buffer-byte-length": "^1.0.1",
5433
+
"call-bind": "^1.0.8",
5434
+
"define-properties": "^1.2.1",
5435
+
"es-abstract": "^1.23.5",
5436
+
"es-errors": "^1.3.0",
5437
+
"get-intrinsic": "^1.2.6",
5438
+
"is-array-buffer": "^3.0.4"
5439
+
},
5440
+
"engines": {
5441
+
"node": ">= 0.4"
5442
+
},
5443
+
"funding": {
5444
+
"url": "https://github.com/sponsors/ljharb"
5445
+
}
5446
+
},
5447
"node_modules/assertion-error": {
5448
"version": "2.0.1",
5449
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
···
5466
"node": ">=4"
5467
}
5468
},
5469
+
"node_modules/async-function": {
5470
+
"version": "1.0.0",
5471
+
"resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
5472
+
"integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
5473
+
"dev": true,
5474
+
"license": "MIT",
5475
+
"engines": {
5476
+
"node": ">= 0.4"
5477
+
}
5478
+
},
5479
+
"node_modules/available-typed-arrays": {
5480
+
"version": "1.0.7",
5481
+
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
5482
+
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
5483
+
"dev": true,
5484
+
"license": "MIT",
5485
+
"dependencies": {
5486
+
"possible-typed-array-names": "^1.0.0"
5487
+
},
5488
+
"engines": {
5489
+
"node": ">= 0.4"
5490
+
},
5491
+
"funding": {
5492
+
"url": "https://github.com/sponsors/ljharb"
5493
+
}
5494
+
},
5495
"node_modules/await-lock": {
5496
"version": "2.2.2",
5497
"resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz",
···
5509
"@babel/traverse": "^7.23.7",
5510
"@babel/types": "^7.23.6"
5511
}
5512
+
},
5513
+
"node_modules/babel-plugin-react-compiler": {
5514
+
"version": "1.0.0",
5515
+
"resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz",
5516
+
"integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==",
5517
+
"dev": true,
5518
+
"license": "MIT",
5519
+
"dependencies": {
5520
+
"@babel/types": "^7.26.0"
5521
+
}
5522
+
},
5523
+
"node_modules/balanced-match": {
5524
+
"version": "1.0.2",
5525
+
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
5526
+
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
5527
+
"dev": true,
5528
+
"license": "MIT"
5529
},
5530
"node_modules/bcp-47": {
5531
"version": "2.1.0",
···
5578
"url": "https://github.com/sponsors/sindresorhus"
5579
}
5580
},
5581
+
"node_modules/birecord": {
5582
+
"version": "0.1.1",
5583
+
"resolved": "https://registry.npmjs.org/birecord/-/birecord-0.1.1.tgz",
5584
+
"integrity": "sha512-VUpsf/qykW0heRlC8LooCq28Kxn3mAqKohhDG/49rrsQ1dT1CXyj/pgXS+5BSRzFTR/3DyIBOqQOrGyZOh71Aw==",
5585
+
"dev": true,
5586
+
"license": "(MIT OR Apache-2.0)"
5587
+
},
5588
+
"node_modules/brace-expansion": {
5589
+
"version": "1.1.12",
5590
+
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
5591
+
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
5592
+
"dev": true,
5593
+
"license": "MIT",
5594
+
"dependencies": {
5595
+
"balanced-match": "^1.0.0",
5596
+
"concat-map": "0.0.1"
5597
+
}
5598
+
},
5599
"node_modules/braces": {
5600
"version": "3.0.3",
5601
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
···
5650
"node": ">=8"
5651
}
5652
},
5653
+
"node_modules/call-bind": {
5654
+
"version": "1.0.8",
5655
+
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
5656
+
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
5657
+
"dev": true,
5658
+
"license": "MIT",
5659
+
"dependencies": {
5660
+
"call-bind-apply-helpers": "^1.0.0",
5661
+
"es-define-property": "^1.0.0",
5662
+
"get-intrinsic": "^1.2.4",
5663
+
"set-function-length": "^1.2.2"
5664
+
},
5665
+
"engines": {
5666
+
"node": ">= 0.4"
5667
+
},
5668
+
"funding": {
5669
+
"url": "https://github.com/sponsors/ljharb"
5670
+
}
5671
+
},
5672
+
"node_modules/call-bind-apply-helpers": {
5673
+
"version": "1.0.2",
5674
+
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
5675
+
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
5676
+
"dev": true,
5677
+
"license": "MIT",
5678
+
"dependencies": {
5679
+
"es-errors": "^1.3.0",
5680
+
"function-bind": "^1.1.2"
5681
+
},
5682
+
"engines": {
5683
+
"node": ">= 0.4"
5684
+
}
5685
+
},
5686
+
"node_modules/call-bound": {
5687
+
"version": "1.0.4",
5688
+
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
5689
+
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
5690
+
"dev": true,
5691
+
"license": "MIT",
5692
+
"dependencies": {
5693
+
"call-bind-apply-helpers": "^1.0.2",
5694
+
"get-intrinsic": "^1.3.0"
5695
+
},
5696
+
"engines": {
5697
+
"node": ">= 0.4"
5698
+
},
5699
+
"funding": {
5700
+
"url": "https://github.com/sponsors/ljharb"
5701
+
}
5702
+
},
5703
+
"node_modules/callsites": {
5704
+
"version": "3.1.0",
5705
+
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
5706
+
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
5707
+
"dev": true,
5708
+
"license": "MIT",
5709
+
"engines": {
5710
+
"node": ">=6"
5711
+
}
5712
+
},
5713
+
"node_modules/camelcase": {
5714
+
"version": "6.3.0",
5715
+
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
5716
+
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
5717
+
"dev": true,
5718
+
"license": "MIT",
5719
+
"engines": {
5720
+
"node": ">=10"
5721
+
},
5722
+
"funding": {
5723
+
"url": "https://github.com/sponsors/sindresorhus"
5724
+
}
5725
+
},
5726
"node_modules/caniuse-lite": {
5727
"version": "1.0.30001737",
5728
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001737.tgz",
···
5778
"node": ">=18"
5779
}
5780
},
5781
+
"node_modules/chalk": {
5782
+
"version": "4.1.2",
5783
+
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
5784
+
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
5785
+
"dev": true,
5786
+
"license": "MIT",
5787
+
"peer": true,
5788
+
"dependencies": {
5789
+
"ansi-styles": "^4.1.0",
5790
+
"supports-color": "^7.1.0"
5791
+
},
5792
+
"engines": {
5793
+
"node": ">=10"
5794
+
},
5795
+
"funding": {
5796
+
"url": "https://github.com/chalk/chalk?sponsor=1"
5797
+
}
5798
+
},
5799
+
"node_modules/chalk/node_modules/ansi-styles": {
5800
+
"version": "4.3.0",
5801
+
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
5802
+
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
5803
+
"dev": true,
5804
+
"license": "MIT",
5805
+
"peer": true,
5806
+
"dependencies": {
5807
+
"color-convert": "^2.0.1"
5808
+
},
5809
+
"engines": {
5810
+
"node": ">=8"
5811
+
},
5812
+
"funding": {
5813
+
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
5814
+
}
5815
+
},
5816
"node_modules/check-error": {
5817
"version": "2.1.1",
5818
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
···
5877
"integrity": "sha512-eNk3TRV+xQMJ1PEj0FQGY8KD4m0GPxT487XJ+Iftm7mVa9WpPFDMWqPt+46buiP5j5Wzqe5oMIhqBcAeKfygSA==",
5878
"license": "MIT"
5879
},
5880
+
"node_modules/color-convert": {
5881
+
"version": "2.0.1",
5882
+
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
5883
+
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
5884
+
"dev": true,
5885
+
"license": "MIT",
5886
+
"peer": true,
5887
+
"dependencies": {
5888
+
"color-name": "~1.1.4"
5889
+
},
5890
+
"engines": {
5891
+
"node": ">=7.0.0"
5892
+
}
5893
+
},
5894
+
"node_modules/color-name": {
5895
+
"version": "1.1.4",
5896
+
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
5897
+
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
5898
+
"dev": true,
5899
+
"license": "MIT",
5900
+
"peer": true
5901
+
},
5902
+
"node_modules/compare-versions": {
5903
+
"version": "6.1.1",
5904
+
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz",
5905
+
"integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==",
5906
+
"dev": true,
5907
+
"license": "MIT"
5908
+
},
5909
+
"node_modules/concat-map": {
5910
+
"version": "0.0.1",
5911
+
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
5912
+
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
5913
+
"dev": true,
5914
+
"license": "MIT"
5915
+
},
5916
+
"node_modules/confbox": {
5917
+
"version": "0.2.2",
5918
+
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz",
5919
+
"integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==",
5920
+
"dev": true,
5921
+
"license": "MIT"
5922
+
},
5923
"node_modules/convert-source-map": {
5924
"version": "2.0.0",
5925
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
···
5932
"integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==",
5933
"license": "MIT"
5934
},
5935
+
"node_modules/core-js": {
5936
+
"version": "3.46.0",
5937
+
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.46.0.tgz",
5938
+
"integrity": "sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA==",
5939
+
"hasInstallScript": true,
5940
+
"license": "MIT",
5941
+
"funding": {
5942
+
"type": "opencollective",
5943
+
"url": "https://opencollective.com/core-js"
5944
+
}
5945
+
},
5946
+
"node_modules/cosmiconfig": {
5947
+
"version": "8.3.6",
5948
+
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
5949
+
"integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
5950
+
"dev": true,
5951
+
"license": "MIT",
5952
+
"dependencies": {
5953
+
"import-fresh": "^3.3.0",
5954
+
"js-yaml": "^4.1.0",
5955
+
"parse-json": "^5.2.0",
5956
+
"path-type": "^4.0.0"
5957
+
},
5958
+
"engines": {
5959
+
"node": ">=14"
5960
+
},
5961
+
"funding": {
5962
+
"url": "https://github.com/sponsors/d-fischer"
5963
+
},
5964
+
"peerDependencies": {
5965
+
"typescript": ">=4.9.5"
5966
+
},
5967
+
"peerDependenciesMeta": {
5968
+
"typescript": {
5969
+
"optional": true
5970
+
}
5971
+
}
5972
+
},
5973
+
"node_modules/cross-spawn": {
5974
+
"version": "7.0.6",
5975
+
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
5976
+
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
5977
+
"dev": true,
5978
+
"license": "MIT",
5979
+
"peer": true,
5980
+
"dependencies": {
5981
+
"path-key": "^3.1.0",
5982
+
"shebang-command": "^2.0.0",
5983
+
"which": "^2.0.1"
5984
+
},
5985
+
"engines": {
5986
+
"node": ">= 8"
5987
+
}
5988
+
},
5989
"node_modules/cssstyle": {
5990
"version": "4.6.0",
5991
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz",
···
6054
"node": ">=18"
6055
}
6056
},
6057
+
"node_modules/data-view-buffer": {
6058
+
"version": "1.0.2",
6059
+
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
6060
+
"integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
6061
+
"dev": true,
6062
+
"license": "MIT",
6063
+
"dependencies": {
6064
+
"call-bound": "^1.0.3",
6065
+
"es-errors": "^1.3.0",
6066
+
"is-data-view": "^1.0.2"
6067
+
},
6068
+
"engines": {
6069
+
"node": ">= 0.4"
6070
+
},
6071
+
"funding": {
6072
+
"url": "https://github.com/sponsors/ljharb"
6073
+
}
6074
+
},
6075
+
"node_modules/data-view-byte-length": {
6076
+
"version": "1.0.2",
6077
+
"resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
6078
+
"integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
6079
+
"dev": true,
6080
+
"license": "MIT",
6081
+
"dependencies": {
6082
+
"call-bound": "^1.0.3",
6083
+
"es-errors": "^1.3.0",
6084
+
"is-data-view": "^1.0.2"
6085
+
},
6086
+
"engines": {
6087
+
"node": ">= 0.4"
6088
+
},
6089
+
"funding": {
6090
+
"url": "https://github.com/sponsors/inspect-js"
6091
+
}
6092
+
},
6093
+
"node_modules/data-view-byte-offset": {
6094
+
"version": "1.0.1",
6095
+
"resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
6096
+
"integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
6097
+
"dev": true,
6098
+
"license": "MIT",
6099
+
"dependencies": {
6100
+
"call-bound": "^1.0.2",
6101
+
"es-errors": "^1.3.0",
6102
+
"is-data-view": "^1.0.1"
6103
+
},
6104
+
"engines": {
6105
+
"node": ">= 0.4"
6106
+
},
6107
+
"funding": {
6108
+
"url": "https://github.com/sponsors/ljharb"
6109
+
}
6110
+
},
6111
"node_modules/debug": {
6112
+
"version": "4.4.3",
6113
+
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
6114
+
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
6115
"license": "MIT",
6116
"dependencies": {
6117
"ms": "^2.1.3"
···
6142
"node": ">=6"
6143
}
6144
},
6145
+
"node_modules/deep-is": {
6146
+
"version": "0.1.4",
6147
+
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
6148
+
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
6149
+
"dev": true,
6150
+
"license": "MIT",
6151
+
"peer": true
6152
+
},
6153
+
"node_modules/define-data-property": {
6154
+
"version": "1.1.4",
6155
+
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
6156
+
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
6157
+
"dev": true,
6158
+
"license": "MIT",
6159
+
"dependencies": {
6160
+
"es-define-property": "^1.0.0",
6161
+
"es-errors": "^1.3.0",
6162
+
"gopd": "^1.0.1"
6163
+
},
6164
+
"engines": {
6165
+
"node": ">= 0.4"
6166
+
},
6167
+
"funding": {
6168
+
"url": "https://github.com/sponsors/ljharb"
6169
+
}
6170
+
},
6171
+
"node_modules/define-properties": {
6172
+
"version": "1.2.1",
6173
+
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
6174
+
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
6175
+
"dev": true,
6176
+
"license": "MIT",
6177
+
"dependencies": {
6178
+
"define-data-property": "^1.0.1",
6179
+
"has-property-descriptors": "^1.0.0",
6180
+
"object-keys": "^1.1.1"
6181
+
},
6182
+
"engines": {
6183
+
"node": ">= 0.4"
6184
+
},
6185
+
"funding": {
6186
+
"url": "https://github.com/sponsors/ljharb"
6187
+
}
6188
+
},
6189
"node_modules/dequal": {
6190
"version": "2.0.3",
6191
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
···
6205
"node": ">=8"
6206
}
6207
},
6208
+
"node_modules/detect-node-es": {
6209
+
"version": "1.1.0",
6210
+
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
6211
+
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
6212
+
},
6213
"node_modules/diff": {
6214
"version": "8.0.2",
6215
"resolved": "https://registry.npmjs.org/diff/-/diff-8.0.2.tgz",
···
6219
"node": ">=0.3.1"
6220
}
6221
},
6222
+
"node_modules/doctrine": {
6223
+
"version": "2.1.0",
6224
+
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
6225
+
"integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
6226
+
"dev": true,
6227
+
"license": "Apache-2.0",
6228
+
"dependencies": {
6229
+
"esutils": "^2.0.2"
6230
+
},
6231
+
"engines": {
6232
+
"node": ">=0.10.0"
6233
+
}
6234
+
},
6235
"node_modules/dom-accessibility-api": {
6236
"version": "0.5.16",
6237
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
···
6239
"dev": true,
6240
"license": "MIT"
6241
},
6242
+
"node_modules/dompurify": {
6243
+
"version": "3.3.0",
6244
+
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.0.tgz",
6245
+
"integrity": "sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==",
6246
+
"license": "(MPL-2.0 OR Apache-2.0)",
6247
+
"optionalDependencies": {
6248
+
"@types/trusted-types": "^2.0.7"
6249
+
}
6250
+
},
6251
+
"node_modules/dot-case": {
6252
+
"version": "3.0.4",
6253
+
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
6254
+
"integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
6255
+
"dev": true,
6256
+
"license": "MIT",
6257
+
"dependencies": {
6258
+
"no-case": "^3.0.4",
6259
+
"tslib": "^2.0.3"
6260
+
}
6261
+
},
6262
+
"node_modules/dunder-proto": {
6263
+
"version": "1.0.1",
6264
+
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
6265
+
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
6266
+
"dev": true,
6267
+
"license": "MIT",
6268
+
"dependencies": {
6269
+
"call-bind-apply-helpers": "^1.0.1",
6270
+
"es-errors": "^1.3.0",
6271
+
"gopd": "^1.2.0"
6272
+
},
6273
+
"engines": {
6274
+
"node": ">= 0.4"
6275
+
}
6276
+
},
6277
"node_modules/electron-to-chromium": {
6278
"version": "1.5.211",
6279
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.211.tgz",
···
6306
"url": "https://github.com/fb55/entities?sponsor=1"
6307
}
6308
},
6309
+
"node_modules/error-ex": {
6310
+
"version": "1.3.4",
6311
+
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
6312
+
"integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
6313
+
"dev": true,
6314
+
"license": "MIT",
6315
+
"dependencies": {
6316
+
"is-arrayish": "^0.2.1"
6317
+
}
6318
+
},
6319
+
"node_modules/es-abstract": {
6320
+
"version": "1.24.0",
6321
+
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz",
6322
+
"integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==",
6323
+
"dev": true,
6324
+
"license": "MIT",
6325
+
"dependencies": {
6326
+
"array-buffer-byte-length": "^1.0.2",
6327
+
"arraybuffer.prototype.slice": "^1.0.4",
6328
+
"available-typed-arrays": "^1.0.7",
6329
+
"call-bind": "^1.0.8",
6330
+
"call-bound": "^1.0.4",
6331
+
"data-view-buffer": "^1.0.2",
6332
+
"data-view-byte-length": "^1.0.2",
6333
+
"data-view-byte-offset": "^1.0.1",
6334
+
"es-define-property": "^1.0.1",
6335
+
"es-errors": "^1.3.0",
6336
+
"es-object-atoms": "^1.1.1",
6337
+
"es-set-tostringtag": "^2.1.0",
6338
+
"es-to-primitive": "^1.3.0",
6339
+
"function.prototype.name": "^1.1.8",
6340
+
"get-intrinsic": "^1.3.0",
6341
+
"get-proto": "^1.0.1",
6342
+
"get-symbol-description": "^1.1.0",
6343
+
"globalthis": "^1.0.4",
6344
+
"gopd": "^1.2.0",
6345
+
"has-property-descriptors": "^1.0.2",
6346
+
"has-proto": "^1.2.0",
6347
+
"has-symbols": "^1.1.0",
6348
+
"hasown": "^2.0.2",
6349
+
"internal-slot": "^1.1.0",
6350
+
"is-array-buffer": "^3.0.5",
6351
+
"is-callable": "^1.2.7",
6352
+
"is-data-view": "^1.0.2",
6353
+
"is-negative-zero": "^2.0.3",
6354
+
"is-regex": "^1.2.1",
6355
+
"is-set": "^2.0.3",
6356
+
"is-shared-array-buffer": "^1.0.4",
6357
+
"is-string": "^1.1.1",
6358
+
"is-typed-array": "^1.1.15",
6359
+
"is-weakref": "^1.1.1",
6360
+
"math-intrinsics": "^1.1.0",
6361
+
"object-inspect": "^1.13.4",
6362
+
"object-keys": "^1.1.1",
6363
+
"object.assign": "^4.1.7",
6364
+
"own-keys": "^1.0.1",
6365
+
"regexp.prototype.flags": "^1.5.4",
6366
+
"safe-array-concat": "^1.1.3",
6367
+
"safe-push-apply": "^1.0.0",
6368
+
"safe-regex-test": "^1.1.0",
6369
+
"set-proto": "^1.0.0",
6370
+
"stop-iteration-iterator": "^1.1.0",
6371
+
"string.prototype.trim": "^1.2.10",
6372
+
"string.prototype.trimend": "^1.0.9",
6373
+
"string.prototype.trimstart": "^1.0.8",
6374
+
"typed-array-buffer": "^1.0.3",
6375
+
"typed-array-byte-length": "^1.0.3",
6376
+
"typed-array-byte-offset": "^1.0.4",
6377
+
"typed-array-length": "^1.0.7",
6378
+
"unbox-primitive": "^1.1.0",
6379
+
"which-typed-array": "^1.1.19"
6380
+
},
6381
+
"engines": {
6382
+
"node": ">= 0.4"
6383
+
},
6384
+
"funding": {
6385
+
"url": "https://github.com/sponsors/ljharb"
6386
+
}
6387
+
},
6388
+
"node_modules/es-define-property": {
6389
+
"version": "1.0.1",
6390
+
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
6391
+
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
6392
+
"dev": true,
6393
+
"license": "MIT",
6394
+
"engines": {
6395
+
"node": ">= 0.4"
6396
+
}
6397
+
},
6398
+
"node_modules/es-errors": {
6399
+
"version": "1.3.0",
6400
+
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
6401
+
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
6402
+
"dev": true,
6403
+
"license": "MIT",
6404
+
"engines": {
6405
+
"node": ">= 0.4"
6406
+
}
6407
+
},
6408
+
"node_modules/es-iterator-helpers": {
6409
+
"version": "1.2.1",
6410
+
"resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz",
6411
+
"integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==",
6412
+
"dev": true,
6413
+
"license": "MIT",
6414
+
"dependencies": {
6415
+
"call-bind": "^1.0.8",
6416
+
"call-bound": "^1.0.3",
6417
+
"define-properties": "^1.2.1",
6418
+
"es-abstract": "^1.23.6",
6419
+
"es-errors": "^1.3.0",
6420
+
"es-set-tostringtag": "^2.0.3",
6421
+
"function-bind": "^1.1.2",
6422
+
"get-intrinsic": "^1.2.6",
6423
+
"globalthis": "^1.0.4",
6424
+
"gopd": "^1.2.0",
6425
+
"has-property-descriptors": "^1.0.2",
6426
+
"has-proto": "^1.2.0",
6427
+
"has-symbols": "^1.1.0",
6428
+
"internal-slot": "^1.1.0",
6429
+
"iterator.prototype": "^1.1.4",
6430
+
"safe-array-concat": "^1.1.3"
6431
+
},
6432
+
"engines": {
6433
+
"node": ">= 0.4"
6434
+
}
6435
+
},
6436
"node_modules/es-module-lexer": {
6437
"version": "1.7.0",
6438
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
···
6440
"dev": true,
6441
"license": "MIT"
6442
},
6443
+
"node_modules/es-object-atoms": {
6444
+
"version": "1.1.1",
6445
+
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
6446
+
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
6447
+
"dev": true,
6448
+
"license": "MIT",
6449
+
"dependencies": {
6450
+
"es-errors": "^1.3.0"
6451
+
},
6452
+
"engines": {
6453
+
"node": ">= 0.4"
6454
+
}
6455
+
},
6456
+
"node_modules/es-set-tostringtag": {
6457
+
"version": "2.1.0",
6458
+
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
6459
+
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
6460
+
"dev": true,
6461
+
"license": "MIT",
6462
+
"dependencies": {
6463
+
"es-errors": "^1.3.0",
6464
+
"get-intrinsic": "^1.2.6",
6465
+
"has-tostringtag": "^1.0.2",
6466
+
"hasown": "^2.0.2"
6467
+
},
6468
+
"engines": {
6469
+
"node": ">= 0.4"
6470
+
}
6471
+
},
6472
+
"node_modules/es-shim-unscopables": {
6473
+
"version": "1.1.0",
6474
+
"resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
6475
+
"integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
6476
+
"dev": true,
6477
+
"license": "MIT",
6478
+
"dependencies": {
6479
+
"hasown": "^2.0.2"
6480
+
},
6481
+
"engines": {
6482
+
"node": ">= 0.4"
6483
+
}
6484
+
},
6485
+
"node_modules/es-to-primitive": {
6486
+
"version": "1.3.0",
6487
+
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
6488
+
"integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
6489
+
"dev": true,
6490
+
"license": "MIT",
6491
+
"dependencies": {
6492
+
"is-callable": "^1.2.7",
6493
+
"is-date-object": "^1.0.5",
6494
+
"is-symbol": "^1.0.4"
6495
+
},
6496
+
"engines": {
6497
+
"node": ">= 0.4"
6498
+
},
6499
+
"funding": {
6500
+
"url": "https://github.com/sponsors/ljharb"
6501
+
}
6502
+
},
6503
"node_modules/esbuild": {
6504
"version": "0.25.9",
6505
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
···
6550
"node": ">=6"
6551
}
6552
},
6553
+
"node_modules/escape-string-regexp": {
6554
+
"version": "4.0.0",
6555
+
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
6556
+
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
6557
+
"dev": true,
6558
+
"license": "MIT",
6559
+
"peer": true,
6560
+
"engines": {
6561
+
"node": ">=10"
6562
+
},
6563
+
"funding": {
6564
+
"url": "https://github.com/sponsors/sindresorhus"
6565
+
}
6566
+
},
6567
+
"node_modules/eslint": {
6568
+
"version": "9.37.0",
6569
+
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz",
6570
+
"integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==",
6571
+
"dev": true,
6572
+
"license": "MIT",
6573
+
"peer": true,
6574
+
"dependencies": {
6575
+
"@eslint-community/eslint-utils": "^4.8.0",
6576
+
"@eslint-community/regexpp": "^4.12.1",
6577
+
"@eslint/config-array": "^0.21.0",
6578
+
"@eslint/config-helpers": "^0.4.0",
6579
+
"@eslint/core": "^0.16.0",
6580
+
"@eslint/eslintrc": "^3.3.1",
6581
+
"@eslint/js": "9.37.0",
6582
+
"@eslint/plugin-kit": "^0.4.0",
6583
+
"@humanfs/node": "^0.16.6",
6584
+
"@humanwhocodes/module-importer": "^1.0.1",
6585
+
"@humanwhocodes/retry": "^0.4.2",
6586
+
"@types/estree": "^1.0.6",
6587
+
"@types/json-schema": "^7.0.15",
6588
+
"ajv": "^6.12.4",
6589
+
"chalk": "^4.0.0",
6590
+
"cross-spawn": "^7.0.6",
6591
+
"debug": "^4.3.2",
6592
+
"escape-string-regexp": "^4.0.0",
6593
+
"eslint-scope": "^8.4.0",
6594
+
"eslint-visitor-keys": "^4.2.1",
6595
+
"espree": "^10.4.0",
6596
+
"esquery": "^1.5.0",
6597
+
"esutils": "^2.0.2",
6598
+
"fast-deep-equal": "^3.1.3",
6599
+
"file-entry-cache": "^8.0.0",
6600
+
"find-up": "^5.0.0",
6601
+
"glob-parent": "^6.0.2",
6602
+
"ignore": "^5.2.0",
6603
+
"imurmurhash": "^0.1.4",
6604
+
"is-glob": "^4.0.0",
6605
+
"json-stable-stringify-without-jsonify": "^1.0.1",
6606
+
"lodash.merge": "^4.6.2",
6607
+
"minimatch": "^3.1.2",
6608
+
"natural-compare": "^1.4.0",
6609
+
"optionator": "^0.9.3"
6610
+
},
6611
+
"bin": {
6612
+
"eslint": "bin/eslint.js"
6613
+
},
6614
+
"engines": {
6615
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
6616
+
},
6617
+
"funding": {
6618
+
"url": "https://eslint.org/donate"
6619
+
},
6620
+
"peerDependencies": {
6621
+
"jiti": "*"
6622
+
},
6623
+
"peerDependenciesMeta": {
6624
+
"jiti": {
6625
+
"optional": true
6626
+
}
6627
+
}
6628
+
},
6629
+
"node_modules/eslint-plugin-react": {
6630
+
"version": "7.37.5",
6631
+
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
6632
+
"integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
6633
+
"dev": true,
6634
+
"license": "MIT",
6635
+
"dependencies": {
6636
+
"array-includes": "^3.1.8",
6637
+
"array.prototype.findlast": "^1.2.5",
6638
+
"array.prototype.flatmap": "^1.3.3",
6639
+
"array.prototype.tosorted": "^1.1.4",
6640
+
"doctrine": "^2.1.0",
6641
+
"es-iterator-helpers": "^1.2.1",
6642
+
"estraverse": "^5.3.0",
6643
+
"hasown": "^2.0.2",
6644
+
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
6645
+
"minimatch": "^3.1.2",
6646
+
"object.entries": "^1.1.9",
6647
+
"object.fromentries": "^2.0.8",
6648
+
"object.values": "^1.2.1",
6649
+
"prop-types": "^15.8.1",
6650
+
"resolve": "^2.0.0-next.5",
6651
+
"semver": "^6.3.1",
6652
+
"string.prototype.matchall": "^4.0.12",
6653
+
"string.prototype.repeat": "^1.0.0"
6654
+
},
6655
+
"engines": {
6656
+
"node": ">=4"
6657
+
},
6658
+
"peerDependencies": {
6659
+
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
6660
+
}
6661
+
},
6662
+
"node_modules/eslint-plugin-react-dom": {
6663
+
"version": "2.2.1",
6664
+
"resolved": "https://registry.npmjs.org/eslint-plugin-react-dom/-/eslint-plugin-react-dom-2.2.1.tgz",
6665
+
"integrity": "sha512-g6B4yTLHWhgqu3mN0kUJvrQp285uFMQYXzWVAIBqziV6n93sgPH8Eb8ht3gTzRUfA9Rt3JQr8QaxBxpfSkp67w==",
6666
+
"dev": true,
6667
+
"license": "MIT",
6668
+
"dependencies": {
6669
+
"@eslint-react/ast": "2.2.1",
6670
+
"@eslint-react/core": "2.2.1",
6671
+
"@eslint-react/eff": "2.2.1",
6672
+
"@eslint-react/shared": "2.2.1",
6673
+
"@eslint-react/var": "2.2.1",
6674
+
"@typescript-eslint/scope-manager": "^8.46.0",
6675
+
"@typescript-eslint/types": "^8.46.0",
6676
+
"@typescript-eslint/utils": "^8.46.0",
6677
+
"compare-versions": "^6.1.1",
6678
+
"string-ts": "^2.2.1",
6679
+
"ts-pattern": "^5.8.0"
6680
+
},
6681
+
"engines": {
6682
+
"node": ">=20.19.0"
6683
+
},
6684
+
"peerDependencies": {
6685
+
"eslint": "^9.37.0",
6686
+
"typescript": "^5.9.3"
6687
+
}
6688
+
},
6689
+
"node_modules/eslint-plugin-react-hooks": {
6690
+
"version": "7.0.0",
6691
+
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.0.tgz",
6692
+
"integrity": "sha512-fNXaOwvKwq2+pXiRpXc825Vd63+KM4DLL40Rtlycb8m7fYpp6efrTp1sa6ZbP/Ap58K2bEKFXRmhURE+CJAQWw==",
6693
+
"dev": true,
6694
+
"license": "MIT",
6695
+
"dependencies": {
6696
+
"@babel/core": "^7.24.4",
6697
+
"@babel/parser": "^7.24.4",
6698
+
"hermes-parser": "^0.25.1",
6699
+
"zod": "^3.22.4 || ^4.0.0",
6700
+
"zod-validation-error": "^3.0.3 || ^4.0.0"
6701
+
},
6702
+
"engines": {
6703
+
"node": ">=18"
6704
+
},
6705
+
"peerDependencies": {
6706
+
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
6707
+
}
6708
+
},
6709
+
"node_modules/eslint-plugin-react-hooks-extra": {
6710
+
"version": "2.2.1",
6711
+
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks-extra/-/eslint-plugin-react-hooks-extra-2.2.1.tgz",
6712
+
"integrity": "sha512-MfUbjKIEhF0qEpfXIPgcmmteCx5h9lMuuMGLaau4KmOKh3vewj6DW/JubVuhQ+7eaHqpuCz8/0uBH0k2lfavjg==",
6713
+
"dev": true,
6714
+
"license": "MIT",
6715
+
"dependencies": {
6716
+
"@eslint-react/ast": "2.2.1",
6717
+
"@eslint-react/core": "2.2.1",
6718
+
"@eslint-react/eff": "2.2.1",
6719
+
"@eslint-react/shared": "2.2.1",
6720
+
"@eslint-react/var": "2.2.1",
6721
+
"@typescript-eslint/scope-manager": "^8.46.0",
6722
+
"@typescript-eslint/type-utils": "^8.46.0",
6723
+
"@typescript-eslint/types": "^8.46.0",
6724
+
"@typescript-eslint/utils": "^8.46.0",
6725
+
"string-ts": "^2.2.1",
6726
+
"ts-pattern": "^5.8.0"
6727
+
},
6728
+
"engines": {
6729
+
"node": ">=20.0.0"
6730
+
},
6731
+
"peerDependencies": {
6732
+
"eslint": "^9.37.0",
6733
+
"typescript": "^5.9.3"
6734
+
}
6735
+
},
6736
+
"node_modules/eslint-plugin-react-naming-convention": {
6737
+
"version": "2.2.1",
6738
+
"resolved": "https://registry.npmjs.org/eslint-plugin-react-naming-convention/-/eslint-plugin-react-naming-convention-2.2.1.tgz",
6739
+
"integrity": "sha512-yjNfzPmYAJDFp7yZ4BkmwBRmK3mAGYGXFDyb5Ws2vZBj6R8BKbh5Ao/Chmemo/LmW7a2IoySICuBp6wxuBC9Yg==",
6740
+
"dev": true,
6741
+
"license": "MIT",
6742
+
"dependencies": {
6743
+
"@eslint-react/ast": "2.2.1",
6744
+
"@eslint-react/core": "2.2.1",
6745
+
"@eslint-react/eff": "2.2.1",
6746
+
"@eslint-react/shared": "2.2.1",
6747
+
"@eslint-react/var": "2.2.1",
6748
+
"@typescript-eslint/scope-manager": "^8.46.0",
6749
+
"@typescript-eslint/type-utils": "^8.46.0",
6750
+
"@typescript-eslint/types": "^8.46.0",
6751
+
"@typescript-eslint/utils": "^8.46.0",
6752
+
"string-ts": "^2.2.1",
6753
+
"ts-pattern": "^5.8.0"
6754
+
},
6755
+
"engines": {
6756
+
"node": ">=20.19.0"
6757
+
},
6758
+
"peerDependencies": {
6759
+
"eslint": "^9.37.0",
6760
+
"typescript": "^5.9.3"
6761
+
}
6762
+
},
6763
+
"node_modules/eslint-plugin-react-web-api": {
6764
+
"version": "2.2.1",
6765
+
"resolved": "https://registry.npmjs.org/eslint-plugin-react-web-api/-/eslint-plugin-react-web-api-2.2.1.tgz",
6766
+
"integrity": "sha512-JGRufRDJ8rmckQ82R+3kKhl9ybVeCjRt8fo8/IvxCQJukyyL4Y5b+mOwnPTRDJLQMeDzql4VDeeLegcjweTmAw==",
6767
+
"dev": true,
6768
+
"license": "MIT",
6769
+
"dependencies": {
6770
+
"@eslint-react/ast": "2.2.1",
6771
+
"@eslint-react/core": "2.2.1",
6772
+
"@eslint-react/eff": "2.2.1",
6773
+
"@eslint-react/shared": "2.2.1",
6774
+
"@eslint-react/var": "2.2.1",
6775
+
"@typescript-eslint/scope-manager": "^8.46.0",
6776
+
"@typescript-eslint/types": "^8.46.0",
6777
+
"@typescript-eslint/utils": "^8.46.0",
6778
+
"string-ts": "^2.2.1",
6779
+
"ts-pattern": "^5.8.0"
6780
+
},
6781
+
"engines": {
6782
+
"node": ">=20.19.0"
6783
+
},
6784
+
"peerDependencies": {
6785
+
"eslint": "^9.37.0",
6786
+
"typescript": "^5.9.3"
6787
+
}
6788
+
},
6789
+
"node_modules/eslint-plugin-react-x": {
6790
+
"version": "2.2.1",
6791
+
"resolved": "https://registry.npmjs.org/eslint-plugin-react-x/-/eslint-plugin-react-x-2.2.1.tgz",
6792
+
"integrity": "sha512-Bz5MoLgimALqiJ5O7/KQ/JhZ7AC24qILvA7KHsjT5n0XEQKrktGKGZEm4AKiKsTmboAitpVbHDB9kGpwXIrFXw==",
6793
+
"dev": true,
6794
+
"license": "MIT",
6795
+
"dependencies": {
6796
+
"@eslint-react/ast": "2.2.1",
6797
+
"@eslint-react/core": "2.2.1",
6798
+
"@eslint-react/eff": "2.2.1",
6799
+
"@eslint-react/shared": "2.2.1",
6800
+
"@eslint-react/var": "2.2.1",
6801
+
"@typescript-eslint/scope-manager": "^8.46.0",
6802
+
"@typescript-eslint/type-utils": "^8.46.0",
6803
+
"@typescript-eslint/types": "^8.46.0",
6804
+
"@typescript-eslint/utils": "^8.46.0",
6805
+
"compare-versions": "^6.1.1",
6806
+
"is-immutable-type": "^5.0.1",
6807
+
"string-ts": "^2.2.1",
6808
+
"ts-api-utils": "^2.1.0",
6809
+
"ts-pattern": "^5.8.0"
6810
+
},
6811
+
"engines": {
6812
+
"node": ">=20.19.0"
6813
+
},
6814
+
"peerDependencies": {
6815
+
"eslint": "^9.37.0",
6816
+
"typescript": "^5.9.3"
6817
+
}
6818
+
},
6819
+
"node_modules/eslint-plugin-simple-import-sort": {
6820
+
"version": "12.1.1",
6821
+
"resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz",
6822
+
"integrity": "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==",
6823
+
"dev": true,
6824
+
"license": "MIT",
6825
+
"peerDependencies": {
6826
+
"eslint": ">=5.0.0"
6827
+
}
6828
+
},
6829
+
"node_modules/eslint-plugin-unused-imports": {
6830
+
"version": "4.2.0",
6831
+
"resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.2.0.tgz",
6832
+
"integrity": "sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w==",
6833
+
"dev": true,
6834
+
"license": "MIT",
6835
+
"peerDependencies": {
6836
+
"@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0",
6837
+
"eslint": "^9.0.0 || ^8.0.0"
6838
+
},
6839
+
"peerDependenciesMeta": {
6840
+
"@typescript-eslint/eslint-plugin": {
6841
+
"optional": true
6842
+
}
6843
+
}
6844
+
},
6845
+
"node_modules/eslint-scope": {
6846
+
"version": "8.4.0",
6847
+
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
6848
+
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
6849
+
"dev": true,
6850
+
"license": "BSD-2-Clause",
6851
+
"peer": true,
6852
+
"dependencies": {
6853
+
"esrecurse": "^4.3.0",
6854
+
"estraverse": "^5.2.0"
6855
+
},
6856
+
"engines": {
6857
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
6858
+
},
6859
+
"funding": {
6860
+
"url": "https://opencollective.com/eslint"
6861
+
}
6862
+
},
6863
+
"node_modules/eslint-visitor-keys": {
6864
+
"version": "4.2.1",
6865
+
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
6866
+
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
6867
+
"dev": true,
6868
+
"license": "Apache-2.0",
6869
+
"engines": {
6870
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
6871
+
},
6872
+
"funding": {
6873
+
"url": "https://opencollective.com/eslint"
6874
+
}
6875
+
},
6876
+
"node_modules/eslint/node_modules/glob-parent": {
6877
+
"version": "6.0.2",
6878
+
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
6879
+
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
6880
+
"dev": true,
6881
+
"license": "ISC",
6882
+
"peer": true,
6883
+
"dependencies": {
6884
+
"is-glob": "^4.0.3"
6885
+
},
6886
+
"engines": {
6887
+
"node": ">=10.13.0"
6888
+
}
6889
+
},
6890
+
"node_modules/espree": {
6891
+
"version": "10.4.0",
6892
+
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
6893
+
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
6894
+
"dev": true,
6895
+
"license": "BSD-2-Clause",
6896
+
"peer": true,
6897
+
"dependencies": {
6898
+
"acorn": "^8.15.0",
6899
+
"acorn-jsx": "^5.3.2",
6900
+
"eslint-visitor-keys": "^4.2.1"
6901
+
},
6902
+
"engines": {
6903
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
6904
+
},
6905
+
"funding": {
6906
+
"url": "https://opencollective.com/eslint"
6907
+
}
6908
+
},
6909
"node_modules/esprima": {
6910
"version": "4.0.1",
6911
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
···
6919
"node": ">=4"
6920
}
6921
},
6922
+
"node_modules/esquery": {
6923
+
"version": "1.6.0",
6924
+
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
6925
+
"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
6926
+
"dev": true,
6927
+
"license": "BSD-3-Clause",
6928
+
"peer": true,
6929
+
"dependencies": {
6930
+
"estraverse": "^5.1.0"
6931
+
},
6932
+
"engines": {
6933
+
"node": ">=0.10"
6934
+
}
6935
+
},
6936
+
"node_modules/esrecurse": {
6937
+
"version": "4.3.0",
6938
+
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
6939
+
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
6940
+
"dev": true,
6941
+
"license": "BSD-2-Clause",
6942
+
"peer": true,
6943
+
"dependencies": {
6944
+
"estraverse": "^5.2.0"
6945
+
},
6946
+
"engines": {
6947
+
"node": ">=4.0"
6948
+
}
6949
+
},
6950
+
"node_modules/estraverse": {
6951
+
"version": "5.3.0",
6952
+
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
6953
+
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
6954
+
"dev": true,
6955
+
"license": "BSD-2-Clause",
6956
+
"engines": {
6957
+
"node": ">=4.0"
6958
+
}
6959
+
},
6960
"node_modules/estree-walker": {
6961
"version": "3.0.3",
6962
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
···
6967
"@types/estree": "^1.0.0"
6968
}
6969
},
6970
+
"node_modules/esutils": {
6971
+
"version": "2.0.3",
6972
+
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
6973
+
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
6974
+
"dev": true,
6975
+
"license": "BSD-2-Clause",
6976
+
"engines": {
6977
+
"node": ">=0.10.0"
6978
+
}
6979
+
},
6980
+
"node_modules/eventemitter3": {
6981
+
"version": "5.0.1",
6982
+
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
6983
+
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
6984
+
"license": "MIT"
6985
+
},
6986
"node_modules/expect-type": {
6987
"version": "1.2.2",
6988
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz",
···
6993
"node": ">=12.0.0"
6994
}
6995
},
6996
+
"node_modules/exsolve": {
6997
+
"version": "1.0.7",
6998
+
"resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz",
6999
+
"integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==",
7000
+
"dev": true,
7001
+
"license": "MIT"
7002
+
},
7003
"node_modules/fast-deep-equal": {
7004
"version": "3.1.3",
7005
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
7006
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
7007
"license": "MIT"
7008
},
7009
+
"node_modules/fast-glob": {
7010
+
"version": "3.3.3",
7011
+
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
7012
+
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
7013
+
"dev": true,
7014
+
"license": "MIT",
7015
+
"dependencies": {
7016
+
"@nodelib/fs.stat": "^2.0.2",
7017
+
"@nodelib/fs.walk": "^1.2.3",
7018
+
"glob-parent": "^5.1.2",
7019
+
"merge2": "^1.3.0",
7020
+
"micromatch": "^4.0.8"
7021
+
},
7022
+
"engines": {
7023
+
"node": ">=8.6.0"
7024
+
}
7025
+
},
7026
+
"node_modules/fast-json-stable-stringify": {
7027
+
"version": "2.1.0",
7028
+
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
7029
+
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
7030
+
"dev": true,
7031
+
"license": "MIT",
7032
+
"peer": true
7033
+
},
7034
+
"node_modules/fast-levenshtein": {
7035
+
"version": "2.0.6",
7036
+
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
7037
+
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
7038
+
"dev": true,
7039
+
"license": "MIT",
7040
+
"peer": true
7041
+
},
7042
+
"node_modules/fastq": {
7043
+
"version": "1.19.1",
7044
+
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
7045
+
"integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
7046
+
"dev": true,
7047
+
"license": "ISC",
7048
+
"dependencies": {
7049
+
"reusify": "^1.0.4"
7050
+
}
7051
+
},
7052
+
"node_modules/file-entry-cache": {
7053
+
"version": "8.0.0",
7054
+
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
7055
+
"integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
7056
+
"dev": true,
7057
+
"license": "MIT",
7058
+
"peer": true,
7059
+
"dependencies": {
7060
+
"flat-cache": "^4.0.0"
7061
+
},
7062
+
"engines": {
7063
+
"node": ">=16.0.0"
7064
+
}
7065
+
},
7066
"node_modules/fill-range": {
7067
"version": "7.1.1",
7068
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
···
7075
"node": ">=8"
7076
}
7077
},
7078
+
"node_modules/find-up": {
7079
+
"version": "5.0.0",
7080
+
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
7081
+
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
7082
+
"dev": true,
7083
+
"license": "MIT",
7084
+
"peer": true,
7085
+
"dependencies": {
7086
+
"locate-path": "^6.0.0",
7087
+
"path-exists": "^4.0.0"
7088
+
},
7089
+
"engines": {
7090
+
"node": ">=10"
7091
+
},
7092
+
"funding": {
7093
+
"url": "https://github.com/sponsors/sindresorhus"
7094
+
}
7095
+
},
7096
+
"node_modules/flat-cache": {
7097
+
"version": "4.0.1",
7098
+
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
7099
+
"integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
7100
+
"dev": true,
7101
+
"license": "MIT",
7102
+
"peer": true,
7103
+
"dependencies": {
7104
+
"flatted": "^3.2.9",
7105
+
"keyv": "^4.5.4"
7106
+
},
7107
+
"engines": {
7108
+
"node": ">=16"
7109
+
}
7110
+
},
7111
+
"node_modules/flatted": {
7112
+
"version": "3.3.3",
7113
+
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
7114
+
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
7115
+
"dev": true,
7116
+
"license": "ISC",
7117
+
"peer": true
7118
+
},
7119
+
"node_modules/for-each": {
7120
+
"version": "0.3.5",
7121
+
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
7122
+
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
7123
+
"dev": true,
7124
+
"license": "MIT",
7125
+
"dependencies": {
7126
+
"is-callable": "^1.2.7"
7127
+
},
7128
+
"engines": {
7129
+
"node": ">= 0.4"
7130
+
},
7131
+
"funding": {
7132
+
"url": "https://github.com/sponsors/ljharb"
7133
+
}
7134
+
},
7135
"node_modules/fsevents": {
7136
"version": "2.3.3",
7137
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
···
7146
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
7147
}
7148
},
7149
+
"node_modules/function-bind": {
7150
+
"version": "1.1.2",
7151
+
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
7152
+
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
7153
+
"dev": true,
7154
+
"license": "MIT",
7155
+
"funding": {
7156
+
"url": "https://github.com/sponsors/ljharb"
7157
+
}
7158
+
},
7159
+
"node_modules/function.prototype.name": {
7160
+
"version": "1.1.8",
7161
+
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
7162
+
"integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
7163
+
"dev": true,
7164
+
"license": "MIT",
7165
+
"dependencies": {
7166
+
"call-bind": "^1.0.8",
7167
+
"call-bound": "^1.0.3",
7168
+
"define-properties": "^1.2.1",
7169
+
"functions-have-names": "^1.2.3",
7170
+
"hasown": "^2.0.2",
7171
+
"is-callable": "^1.2.7"
7172
+
},
7173
+
"engines": {
7174
+
"node": ">= 0.4"
7175
+
},
7176
+
"funding": {
7177
+
"url": "https://github.com/sponsors/ljharb"
7178
+
}
7179
+
},
7180
+
"node_modules/functions-have-names": {
7181
+
"version": "1.2.3",
7182
+
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
7183
+
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
7184
+
"dev": true,
7185
+
"license": "MIT",
7186
+
"funding": {
7187
+
"url": "https://github.com/sponsors/ljharb"
7188
+
}
7189
+
},
7190
+
"node_modules/generator-function": {
7191
+
"version": "2.0.1",
7192
+
"resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
7193
+
"integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
7194
+
"dev": true,
7195
+
"license": "MIT",
7196
+
"engines": {
7197
+
"node": ">= 0.4"
7198
+
}
7199
+
},
7200
"node_modules/gensync": {
7201
"version": "1.0.0-beta.2",
7202
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
···
7206
"node": ">=6.9.0"
7207
}
7208
},
7209
+
"node_modules/get-intrinsic": {
7210
+
"version": "1.3.0",
7211
+
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
7212
+
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
7213
+
"dev": true,
7214
+
"license": "MIT",
7215
+
"dependencies": {
7216
+
"call-bind-apply-helpers": "^1.0.2",
7217
+
"es-define-property": "^1.0.1",
7218
+
"es-errors": "^1.3.0",
7219
+
"es-object-atoms": "^1.1.1",
7220
+
"function-bind": "^1.1.2",
7221
+
"get-proto": "^1.0.1",
7222
+
"gopd": "^1.2.0",
7223
+
"has-symbols": "^1.1.0",
7224
+
"hasown": "^2.0.2",
7225
+
"math-intrinsics": "^1.1.0"
7226
+
},
7227
+
"engines": {
7228
+
"node": ">= 0.4"
7229
+
},
7230
+
"funding": {
7231
+
"url": "https://github.com/sponsors/ljharb"
7232
+
}
7233
+
},
7234
+
"node_modules/get-nonce": {
7235
+
"version": "1.0.1",
7236
+
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
7237
+
"integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
7238
+
"engines": {
7239
+
"node": ">=6"
7240
+
}
7241
+
},
7242
+
"node_modules/get-proto": {
7243
+
"version": "1.0.1",
7244
+
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
7245
+
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
7246
+
"dev": true,
7247
+
"license": "MIT",
7248
+
"dependencies": {
7249
+
"dunder-proto": "^1.0.1",
7250
+
"es-object-atoms": "^1.0.0"
7251
+
},
7252
+
"engines": {
7253
+
"node": ">= 0.4"
7254
+
}
7255
+
},
7256
+
"node_modules/get-symbol-description": {
7257
+
"version": "1.1.0",
7258
+
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
7259
+
"integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
7260
+
"dev": true,
7261
+
"license": "MIT",
7262
+
"dependencies": {
7263
+
"call-bound": "^1.0.3",
7264
+
"es-errors": "^1.3.0",
7265
+
"get-intrinsic": "^1.2.6"
7266
+
},
7267
+
"engines": {
7268
+
"node": ">= 0.4"
7269
+
},
7270
+
"funding": {
7271
+
"url": "https://github.com/sponsors/ljharb"
7272
+
}
7273
+
},
7274
"node_modules/get-tsconfig": {
7275
"version": "4.10.1",
7276
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz",
···
7295
"node": ">= 6"
7296
}
7297
},
7298
+
"node_modules/globals": {
7299
+
"version": "14.0.0",
7300
+
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
7301
+
"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
7302
+
"dev": true,
7303
+
"license": "MIT",
7304
+
"peer": true,
7305
+
"engines": {
7306
+
"node": ">=18"
7307
+
},
7308
+
"funding": {
7309
+
"url": "https://github.com/sponsors/sindresorhus"
7310
+
}
7311
+
},
7312
+
"node_modules/globalthis": {
7313
+
"version": "1.0.4",
7314
+
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
7315
+
"integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
7316
+
"dev": true,
7317
+
"license": "MIT",
7318
+
"dependencies": {
7319
+
"define-properties": "^1.2.1",
7320
+
"gopd": "^1.0.1"
7321
+
},
7322
+
"engines": {
7323
+
"node": ">= 0.4"
7324
+
},
7325
+
"funding": {
7326
+
"url": "https://github.com/sponsors/ljharb"
7327
+
}
7328
+
},
7329
"node_modules/goober": {
7330
"version": "2.1.16",
7331
"resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz",
···
7335
"csstype": "^3.0.10"
7336
}
7337
},
7338
+
"node_modules/gopd": {
7339
+
"version": "1.2.0",
7340
+
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
7341
+
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
7342
+
"dev": true,
7343
+
"license": "MIT",
7344
+
"engines": {
7345
+
"node": ">= 0.4"
7346
+
},
7347
+
"funding": {
7348
+
"url": "https://github.com/sponsors/ljharb"
7349
+
}
7350
+
},
7351
"node_modules/graceful-fs": {
7352
"version": "4.2.11",
7353
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
···
7360
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
7361
"license": "MIT"
7362
},
7363
+
"node_modules/has-bigints": {
7364
+
"version": "1.1.0",
7365
+
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
7366
+
"integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
7367
+
"dev": true,
7368
+
"license": "MIT",
7369
+
"engines": {
7370
+
"node": ">= 0.4"
7371
+
},
7372
+
"funding": {
7373
+
"url": "https://github.com/sponsors/ljharb"
7374
+
}
7375
+
},
7376
+
"node_modules/has-flag": {
7377
+
"version": "4.0.0",
7378
+
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
7379
+
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
7380
+
"dev": true,
7381
+
"license": "MIT",
7382
+
"peer": true,
7383
+
"engines": {
7384
+
"node": ">=8"
7385
+
}
7386
+
},
7387
+
"node_modules/has-property-descriptors": {
7388
+
"version": "1.0.2",
7389
+
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
7390
+
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
7391
+
"dev": true,
7392
+
"license": "MIT",
7393
+
"dependencies": {
7394
+
"es-define-property": "^1.0.0"
7395
+
},
7396
+
"funding": {
7397
+
"url": "https://github.com/sponsors/ljharb"
7398
+
}
7399
+
},
7400
+
"node_modules/has-proto": {
7401
+
"version": "1.2.0",
7402
+
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
7403
+
"integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
7404
+
"dev": true,
7405
+
"license": "MIT",
7406
+
"dependencies": {
7407
+
"dunder-proto": "^1.0.0"
7408
+
},
7409
+
"engines": {
7410
+
"node": ">= 0.4"
7411
+
},
7412
+
"funding": {
7413
+
"url": "https://github.com/sponsors/ljharb"
7414
+
}
7415
+
},
7416
+
"node_modules/has-symbols": {
7417
+
"version": "1.1.0",
7418
+
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
7419
+
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
7420
+
"dev": true,
7421
+
"license": "MIT",
7422
+
"engines": {
7423
+
"node": ">= 0.4"
7424
+
},
7425
+
"funding": {
7426
+
"url": "https://github.com/sponsors/ljharb"
7427
+
}
7428
+
},
7429
+
"node_modules/has-tostringtag": {
7430
+
"version": "1.0.2",
7431
+
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
7432
+
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
7433
+
"dev": true,
7434
+
"license": "MIT",
7435
+
"dependencies": {
7436
+
"has-symbols": "^1.0.3"
7437
+
},
7438
+
"engines": {
7439
+
"node": ">= 0.4"
7440
+
},
7441
+
"funding": {
7442
+
"url": "https://github.com/sponsors/ljharb"
7443
+
}
7444
+
},
7445
+
"node_modules/hasown": {
7446
+
"version": "2.0.2",
7447
+
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
7448
+
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
7449
+
"dev": true,
7450
+
"license": "MIT",
7451
+
"dependencies": {
7452
+
"function-bind": "^1.1.2"
7453
+
},
7454
+
"engines": {
7455
+
"node": ">= 0.4"
7456
+
}
7457
+
},
7458
+
"node_modules/hermes-estree": {
7459
+
"version": "0.25.1",
7460
+
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
7461
+
"integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
7462
+
"dev": true,
7463
+
"license": "MIT"
7464
+
},
7465
+
"node_modules/hermes-parser": {
7466
+
"version": "0.25.1",
7467
+
"resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
7468
+
"integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
7469
+
"dev": true,
7470
+
"license": "MIT",
7471
+
"dependencies": {
7472
+
"hermes-estree": "0.25.1"
7473
+
}
7474
+
},
7475
"node_modules/hls-video-element": {
7476
"version": "1.5.7",
7477
"resolved": "https://registry.npmjs.org/hls-video-element/-/hls-video-element-1.5.7.tgz",
···
7546
"node": ">= 14"
7547
}
7548
},
7549
+
"node_modules/i": {
7550
+
"version": "0.3.7",
7551
+
"resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz",
7552
+
"integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==",
7553
+
"engines": {
7554
+
"node": ">=0.4"
7555
+
}
7556
+
},
7557
+
"node_modules/iconify-icon": {
7558
+
"version": "3.0.1",
7559
+
"resolved": "https://registry.npmjs.org/iconify-icon/-/iconify-icon-3.0.1.tgz",
7560
+
"integrity": "sha512-M3/kH3C+e/ufhmQuOSYSb1Ri1ImJ+ZEQYcVRMKnlSc8Nrdoy+iY9YvFnplX8t/3aCRuo5wN4RVPtCSHGnbt8dg==",
7561
+
"dev": true,
7562
+
"license": "MIT",
7563
+
"dependencies": {
7564
+
"@iconify/types": "^2.0.0"
7565
+
},
7566
+
"funding": {
7567
+
"url": "https://github.com/sponsors/cyberalien"
7568
+
}
7569
+
},
7570
"node_modules/iconv-lite": {
7571
"version": "0.6.3",
7572
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
···
7586
"integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==",
7587
"license": "Apache-2.0"
7588
},
7589
+
"node_modules/ignore": {
7590
+
"version": "5.3.2",
7591
+
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
7592
+
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
7593
+
"dev": true,
7594
+
"license": "MIT",
7595
+
"peer": true,
7596
+
"engines": {
7597
+
"node": ">= 4"
7598
+
}
7599
+
},
7600
"node_modules/immediate": {
7601
"version": "3.0.6",
7602
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
7603
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
7604
"license": "MIT"
7605
},
7606
+
"node_modules/import-fresh": {
7607
+
"version": "3.3.1",
7608
+
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
7609
+
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
7610
+
"dev": true,
7611
+
"license": "MIT",
7612
+
"dependencies": {
7613
+
"parent-module": "^1.0.0",
7614
+
"resolve-from": "^4.0.0"
7615
+
},
7616
+
"engines": {
7617
+
"node": ">=6"
7618
+
},
7619
+
"funding": {
7620
+
"url": "https://github.com/sponsors/sindresorhus"
7621
+
}
7622
+
},
7623
"node_modules/imsc": {
7624
"version": "1.1.5",
7625
"resolved": "https://registry.npmjs.org/imsc/-/imsc-1.1.5.tgz",
···
7629
"sax": "1.2.1"
7630
}
7631
},
7632
+
"node_modules/imurmurhash": {
7633
+
"version": "0.1.4",
7634
+
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
7635
+
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
7636
+
"dev": true,
7637
+
"license": "MIT",
7638
+
"peer": true,
7639
+
"engines": {
7640
+
"node": ">=0.8.19"
7641
+
}
7642
+
},
7643
+
"node_modules/internal-slot": {
7644
+
"version": "1.1.0",
7645
+
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
7646
+
"integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
7647
+
"dev": true,
7648
+
"license": "MIT",
7649
+
"dependencies": {
7650
+
"es-errors": "^1.3.0",
7651
+
"hasown": "^2.0.2",
7652
+
"side-channel": "^1.1.0"
7653
+
},
7654
+
"engines": {
7655
+
"node": ">= 0.4"
7656
+
}
7657
+
},
7658
"node_modules/is-alphabetical": {
7659
"version": "2.0.1",
7660
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
···
7679
"url": "https://github.com/sponsors/wooorm"
7680
}
7681
},
7682
+
"node_modules/is-array-buffer": {
7683
+
"version": "3.0.5",
7684
+
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
7685
+
"integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
7686
+
"dev": true,
7687
+
"license": "MIT",
7688
+
"dependencies": {
7689
+
"call-bind": "^1.0.8",
7690
+
"call-bound": "^1.0.3",
7691
+
"get-intrinsic": "^1.2.6"
7692
+
},
7693
+
"engines": {
7694
+
"node": ">= 0.4"
7695
+
},
7696
+
"funding": {
7697
+
"url": "https://github.com/sponsors/ljharb"
7698
+
}
7699
+
},
7700
+
"node_modules/is-arrayish": {
7701
+
"version": "0.2.1",
7702
+
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
7703
+
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
7704
+
"dev": true,
7705
+
"license": "MIT"
7706
+
},
7707
+
"node_modules/is-async-function": {
7708
+
"version": "2.1.1",
7709
+
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
7710
+
"integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
7711
+
"dev": true,
7712
+
"license": "MIT",
7713
+
"dependencies": {
7714
+
"async-function": "^1.0.0",
7715
+
"call-bound": "^1.0.3",
7716
+
"get-proto": "^1.0.1",
7717
+
"has-tostringtag": "^1.0.2",
7718
+
"safe-regex-test": "^1.1.0"
7719
+
},
7720
+
"engines": {
7721
+
"node": ">= 0.4"
7722
+
},
7723
+
"funding": {
7724
+
"url": "https://github.com/sponsors/ljharb"
7725
+
}
7726
+
},
7727
+
"node_modules/is-bigint": {
7728
+
"version": "1.1.0",
7729
+
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
7730
+
"integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
7731
+
"dev": true,
7732
+
"license": "MIT",
7733
+
"dependencies": {
7734
+
"has-bigints": "^1.0.2"
7735
+
},
7736
+
"engines": {
7737
+
"node": ">= 0.4"
7738
+
},
7739
+
"funding": {
7740
+
"url": "https://github.com/sponsors/ljharb"
7741
+
}
7742
+
},
7743
"node_modules/is-binary-path": {
7744
"version": "2.1.0",
7745
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
···
7752
"node": ">=8"
7753
}
7754
},
7755
+
"node_modules/is-boolean-object": {
7756
+
"version": "1.2.2",
7757
+
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
7758
+
"integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
7759
+
"dev": true,
7760
+
"license": "MIT",
7761
+
"dependencies": {
7762
+
"call-bound": "^1.0.3",
7763
+
"has-tostringtag": "^1.0.2"
7764
+
},
7765
+
"engines": {
7766
+
"node": ">= 0.4"
7767
+
},
7768
+
"funding": {
7769
+
"url": "https://github.com/sponsors/ljharb"
7770
+
}
7771
+
},
7772
+
"node_modules/is-callable": {
7773
+
"version": "1.2.7",
7774
+
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
7775
+
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
7776
+
"dev": true,
7777
+
"license": "MIT",
7778
+
"engines": {
7779
+
"node": ">= 0.4"
7780
+
},
7781
+
"funding": {
7782
+
"url": "https://github.com/sponsors/ljharb"
7783
+
}
7784
+
},
7785
+
"node_modules/is-core-module": {
7786
+
"version": "2.16.1",
7787
+
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
7788
+
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
7789
+
"dev": true,
7790
+
"license": "MIT",
7791
+
"dependencies": {
7792
+
"hasown": "^2.0.2"
7793
+
},
7794
+
"engines": {
7795
+
"node": ">= 0.4"
7796
+
},
7797
+
"funding": {
7798
+
"url": "https://github.com/sponsors/ljharb"
7799
+
}
7800
+
},
7801
+
"node_modules/is-data-view": {
7802
+
"version": "1.0.2",
7803
+
"resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
7804
+
"integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
7805
+
"dev": true,
7806
+
"license": "MIT",
7807
+
"dependencies": {
7808
+
"call-bound": "^1.0.2",
7809
+
"get-intrinsic": "^1.2.6",
7810
+
"is-typed-array": "^1.1.13"
7811
+
},
7812
+
"engines": {
7813
+
"node": ">= 0.4"
7814
+
},
7815
+
"funding": {
7816
+
"url": "https://github.com/sponsors/ljharb"
7817
+
}
7818
+
},
7819
+
"node_modules/is-date-object": {
7820
+
"version": "1.1.0",
7821
+
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
7822
+
"integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
7823
+
"dev": true,
7824
+
"license": "MIT",
7825
+
"dependencies": {
7826
+
"call-bound": "^1.0.2",
7827
+
"has-tostringtag": "^1.0.2"
7828
+
},
7829
+
"engines": {
7830
+
"node": ">= 0.4"
7831
+
},
7832
+
"funding": {
7833
+
"url": "https://github.com/sponsors/ljharb"
7834
+
}
7835
+
},
7836
"node_modules/is-decimal": {
7837
"version": "2.0.1",
7838
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
···
7852
"node": ">=0.10.0"
7853
}
7854
},
7855
+
"node_modules/is-finalizationregistry": {
7856
+
"version": "1.1.1",
7857
+
"resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
7858
+
"integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
7859
+
"dev": true,
7860
+
"license": "MIT",
7861
+
"dependencies": {
7862
+
"call-bound": "^1.0.3"
7863
+
},
7864
+
"engines": {
7865
+
"node": ">= 0.4"
7866
+
},
7867
+
"funding": {
7868
+
"url": "https://github.com/sponsors/ljharb"
7869
+
}
7870
+
},
7871
+
"node_modules/is-generator-function": {
7872
+
"version": "1.1.2",
7873
+
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
7874
+
"integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
7875
+
"dev": true,
7876
+
"license": "MIT",
7877
+
"dependencies": {
7878
+
"call-bound": "^1.0.4",
7879
+
"generator-function": "^2.0.0",
7880
+
"get-proto": "^1.0.1",
7881
+
"has-tostringtag": "^1.0.2",
7882
+
"safe-regex-test": "^1.1.0"
7883
+
},
7884
+
"engines": {
7885
+
"node": ">= 0.4"
7886
+
},
7887
+
"funding": {
7888
+
"url": "https://github.com/sponsors/ljharb"
7889
+
}
7890
+
},
7891
"node_modules/is-glob": {
7892
"version": "4.0.3",
7893
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
···
7900
"node": ">=0.10.0"
7901
}
7902
},
7903
+
"node_modules/is-immutable-type": {
7904
+
"version": "5.0.1",
7905
+
"resolved": "https://registry.npmjs.org/is-immutable-type/-/is-immutable-type-5.0.1.tgz",
7906
+
"integrity": "sha512-LkHEOGVZZXxGl8vDs+10k3DvP++SEoYEAJLRk6buTFi6kD7QekThV7xHS0j6gpnUCQ0zpud/gMDGiV4dQneLTg==",
7907
+
"dev": true,
7908
+
"license": "BSD-3-Clause",
7909
+
"dependencies": {
7910
+
"@typescript-eslint/type-utils": "^8.0.0",
7911
+
"ts-api-utils": "^2.0.0",
7912
+
"ts-declaration-location": "^1.0.4"
7913
+
},
7914
+
"peerDependencies": {
7915
+
"eslint": "*",
7916
+
"typescript": ">=4.7.4"
7917
+
}
7918
+
},
7919
+
"node_modules/is-map": {
7920
+
"version": "2.0.3",
7921
+
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
7922
+
"integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
7923
+
"dev": true,
7924
+
"license": "MIT",
7925
+
"engines": {
7926
+
"node": ">= 0.4"
7927
+
},
7928
+
"funding": {
7929
+
"url": "https://github.com/sponsors/ljharb"
7930
+
}
7931
+
},
7932
+
"node_modules/is-negative-zero": {
7933
+
"version": "2.0.3",
7934
+
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
7935
+
"integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
7936
+
"dev": true,
7937
+
"license": "MIT",
7938
+
"engines": {
7939
+
"node": ">= 0.4"
7940
+
},
7941
+
"funding": {
7942
+
"url": "https://github.com/sponsors/ljharb"
7943
+
}
7944
+
},
7945
"node_modules/is-number": {
7946
"version": "7.0.0",
7947
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
···
7951
"node": ">=0.12.0"
7952
}
7953
},
7954
+
"node_modules/is-number-object": {
7955
+
"version": "1.1.1",
7956
+
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
7957
+
"integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
7958
+
"dev": true,
7959
+
"license": "MIT",
7960
+
"dependencies": {
7961
+
"call-bound": "^1.0.3",
7962
+
"has-tostringtag": "^1.0.2"
7963
+
},
7964
+
"engines": {
7965
+
"node": ">= 0.4"
7966
+
},
7967
+
"funding": {
7968
+
"url": "https://github.com/sponsors/ljharb"
7969
+
}
7970
+
},
7971
"node_modules/is-potential-custom-element-name": {
7972
"version": "1.0.1",
7973
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
···
7975
"dev": true,
7976
"license": "MIT"
7977
},
7978
+
"node_modules/is-regex": {
7979
+
"version": "1.2.1",
7980
+
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
7981
+
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
7982
+
"dev": true,
7983
+
"license": "MIT",
7984
+
"dependencies": {
7985
+
"call-bound": "^1.0.2",
7986
+
"gopd": "^1.2.0",
7987
+
"has-tostringtag": "^1.0.2",
7988
+
"hasown": "^2.0.2"
7989
+
},
7990
+
"engines": {
7991
+
"node": ">= 0.4"
7992
+
},
7993
+
"funding": {
7994
+
"url": "https://github.com/sponsors/ljharb"
7995
+
}
7996
+
},
7997
+
"node_modules/is-set": {
7998
+
"version": "2.0.3",
7999
+
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
8000
+
"integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
8001
+
"dev": true,
8002
+
"license": "MIT",
8003
+
"engines": {
8004
+
"node": ">= 0.4"
8005
+
},
8006
+
"funding": {
8007
+
"url": "https://github.com/sponsors/ljharb"
8008
+
}
8009
+
},
8010
+
"node_modules/is-shared-array-buffer": {
8011
+
"version": "1.0.4",
8012
+
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
8013
+
"integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
8014
+
"dev": true,
8015
+
"license": "MIT",
8016
+
"dependencies": {
8017
+
"call-bound": "^1.0.3"
8018
+
},
8019
+
"engines": {
8020
+
"node": ">= 0.4"
8021
+
},
8022
+
"funding": {
8023
+
"url": "https://github.com/sponsors/ljharb"
8024
+
}
8025
+
},
8026
+
"node_modules/is-string": {
8027
+
"version": "1.1.1",
8028
+
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
8029
+
"integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
8030
+
"dev": true,
8031
+
"license": "MIT",
8032
+
"dependencies": {
8033
+
"call-bound": "^1.0.3",
8034
+
"has-tostringtag": "^1.0.2"
8035
+
},
8036
+
"engines": {
8037
+
"node": ">= 0.4"
8038
+
},
8039
+
"funding": {
8040
+
"url": "https://github.com/sponsors/ljharb"
8041
+
}
8042
+
},
8043
+
"node_modules/is-symbol": {
8044
+
"version": "1.1.1",
8045
+
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
8046
+
"integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
8047
+
"dev": true,
8048
+
"license": "MIT",
8049
+
"dependencies": {
8050
+
"call-bound": "^1.0.2",
8051
+
"has-symbols": "^1.1.0",
8052
+
"safe-regex-test": "^1.1.0"
8053
+
},
8054
+
"engines": {
8055
+
"node": ">= 0.4"
8056
+
},
8057
+
"funding": {
8058
+
"url": "https://github.com/sponsors/ljharb"
8059
+
}
8060
+
},
8061
+
"node_modules/is-typed-array": {
8062
+
"version": "1.1.15",
8063
+
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
8064
+
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
8065
+
"dev": true,
8066
+
"license": "MIT",
8067
+
"dependencies": {
8068
+
"which-typed-array": "^1.1.16"
8069
+
},
8070
+
"engines": {
8071
+
"node": ">= 0.4"
8072
+
},
8073
+
"funding": {
8074
+
"url": "https://github.com/sponsors/ljharb"
8075
+
}
8076
+
},
8077
+
"node_modules/is-weakmap": {
8078
+
"version": "2.0.2",
8079
+
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
8080
+
"integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
8081
+
"dev": true,
8082
+
"license": "MIT",
8083
+
"engines": {
8084
+
"node": ">= 0.4"
8085
+
},
8086
+
"funding": {
8087
+
"url": "https://github.com/sponsors/ljharb"
8088
+
}
8089
+
},
8090
+
"node_modules/is-weakref": {
8091
+
"version": "1.1.1",
8092
+
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
8093
+
"integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
8094
+
"dev": true,
8095
+
"license": "MIT",
8096
+
"dependencies": {
8097
+
"call-bound": "^1.0.3"
8098
+
},
8099
+
"engines": {
8100
+
"node": ">= 0.4"
8101
+
},
8102
+
"funding": {
8103
+
"url": "https://github.com/sponsors/ljharb"
8104
+
}
8105
+
},
8106
+
"node_modules/is-weakset": {
8107
+
"version": "2.0.4",
8108
+
"resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
8109
+
"integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
8110
+
"dev": true,
8111
+
"license": "MIT",
8112
+
"dependencies": {
8113
+
"call-bound": "^1.0.3",
8114
+
"get-intrinsic": "^1.2.6"
8115
+
},
8116
+
"engines": {
8117
+
"node": ">= 0.4"
8118
+
},
8119
+
"funding": {
8120
+
"url": "https://github.com/sponsors/ljharb"
8121
+
}
8122
+
},
8123
+
"node_modules/isarray": {
8124
+
"version": "2.0.5",
8125
+
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
8126
+
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
8127
+
"dev": true,
8128
+
"license": "MIT"
8129
+
},
8130
"node_modules/isbot": {
8131
"version": "5.1.30",
8132
"resolved": "https://registry.npmjs.org/isbot/-/isbot-5.1.30.tgz",
···
8136
"node": ">=18"
8137
}
8138
},
8139
+
"node_modules/isexe": {
8140
+
"version": "2.0.0",
8141
+
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
8142
+
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
8143
+
"dev": true,
8144
+
"license": "ISC",
8145
+
"peer": true
8146
+
},
8147
"node_modules/iso-datestring-validator": {
8148
"version": "2.2.2",
8149
"resolved": "https://registry.npmjs.org/iso-datestring-validator/-/iso-datestring-validator-2.2.2.tgz",
8150
"integrity": "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==",
8151
"license": "MIT"
8152
},
8153
+
"node_modules/iterator.prototype": {
8154
+
"version": "1.1.5",
8155
+
"resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
8156
+
"integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
8157
+
"dev": true,
8158
+
"license": "MIT",
8159
+
"dependencies": {
8160
+
"define-data-property": "^1.1.4",
8161
+
"es-object-atoms": "^1.0.0",
8162
+
"get-intrinsic": "^1.2.6",
8163
+
"get-proto": "^1.0.0",
8164
+
"has-symbols": "^1.1.0",
8165
+
"set-function-name": "^2.0.2"
8166
+
},
8167
+
"engines": {
8168
+
"node": ">= 0.4"
8169
+
}
8170
+
},
8171
"node_modules/jiti": {
8172
"version": "2.5.1",
8173
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz",
···
8175
"license": "MIT",
8176
"bin": {
8177
"jiti": "lib/jiti-cli.mjs"
8178
+
}
8179
+
},
8180
+
"node_modules/jose": {
8181
+
"version": "5.10.0",
8182
+
"resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz",
8183
+
"integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==",
8184
+
"license": "MIT",
8185
+
"funding": {
8186
+
"url": "https://github.com/sponsors/panva"
8187
}
8188
},
8189
"node_modules/jotai": {
···
8221
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
8222
"license": "MIT"
8223
},
8224
+
"node_modules/js-yaml": {
8225
+
"version": "4.1.0",
8226
+
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
8227
+
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
8228
+
"dev": true,
8229
+
"license": "MIT",
8230
+
"dependencies": {
8231
+
"argparse": "^2.0.1"
8232
+
},
8233
+
"bin": {
8234
+
"js-yaml": "bin/js-yaml.js"
8235
+
}
8236
+
},
8237
"node_modules/jsdom": {
8238
"version": "26.1.0",
8239
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz",
···
8286
"node": ">=6"
8287
}
8288
},
8289
+
"node_modules/json-buffer": {
8290
+
"version": "3.0.1",
8291
+
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
8292
+
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
8293
+
"dev": true,
8294
+
"license": "MIT",
8295
+
"peer": true
8296
+
},
8297
+
"node_modules/json-parse-even-better-errors": {
8298
+
"version": "2.3.1",
8299
+
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
8300
+
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
8301
+
"dev": true,
8302
+
"license": "MIT"
8303
+
},
8304
+
"node_modules/json-schema-traverse": {
8305
+
"version": "0.4.1",
8306
+
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
8307
+
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
8308
+
"dev": true,
8309
+
"license": "MIT",
8310
+
"peer": true
8311
+
},
8312
+
"node_modules/json-stable-stringify-without-jsonify": {
8313
+
"version": "1.0.1",
8314
+
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
8315
+
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
8316
+
"dev": true,
8317
+
"license": "MIT",
8318
+
"peer": true
8319
+
},
8320
"node_modules/json5": {
8321
"version": "2.2.3",
8322
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
···
8329
"node": ">=6"
8330
}
8331
},
8332
+
"node_modules/jsx-ast-utils": {
8333
+
"version": "3.3.5",
8334
+
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
8335
+
"integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
8336
+
"dev": true,
8337
+
"license": "MIT",
8338
+
"dependencies": {
8339
+
"array-includes": "^3.1.6",
8340
+
"array.prototype.flat": "^1.3.1",
8341
+
"object.assign": "^4.1.4",
8342
+
"object.values": "^1.1.6"
8343
+
},
8344
+
"engines": {
8345
+
"node": ">=4.0"
8346
+
}
8347
+
},
8348
+
"node_modules/keyv": {
8349
+
"version": "4.5.4",
8350
+
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
8351
+
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
8352
+
"dev": true,
8353
+
"license": "MIT",
8354
+
"peer": true,
8355
+
"dependencies": {
8356
+
"json-buffer": "3.0.1"
8357
+
}
8358
+
},
8359
+
"node_modules/kolorist": {
8360
+
"version": "1.8.0",
8361
+
"resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz",
8362
+
"integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==",
8363
+
"dev": true,
8364
+
"license": "MIT"
8365
+
},
8366
+
"node_modules/levn": {
8367
+
"version": "0.4.1",
8368
+
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
8369
+
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
8370
+
"dev": true,
8371
+
"license": "MIT",
8372
+
"peer": true,
8373
+
"dependencies": {
8374
+
"prelude-ls": "^1.2.1",
8375
+
"type-check": "~0.4.0"
8376
+
},
8377
+
"engines": {
8378
+
"node": ">= 0.8.0"
8379
+
}
8380
+
},
8381
"node_modules/lie": {
8382
"version": "3.1.1",
8383
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
···
8615
"url": "https://opencollective.com/parcel"
8616
}
8617
},
8618
+
"node_modules/lines-and-columns": {
8619
+
"version": "1.2.4",
8620
+
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
8621
+
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
8622
+
"dev": true,
8623
+
"license": "MIT"
8624
+
},
8625
+
"node_modules/local-pkg": {
8626
+
"version": "1.1.2",
8627
+
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz",
8628
+
"integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==",
8629
+
"dev": true,
8630
+
"license": "MIT",
8631
+
"dependencies": {
8632
+
"mlly": "^1.7.4",
8633
+
"pkg-types": "^2.3.0",
8634
+
"quansync": "^0.2.11"
8635
+
},
8636
+
"engines": {
8637
+
"node": ">=14"
8638
+
},
8639
+
"funding": {
8640
+
"url": "https://github.com/sponsors/antfu"
8641
+
}
8642
+
},
8643
"node_modules/localforage": {
8644
"version": "1.10.0",
8645
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
···
8649
"lie": "3.1.1"
8650
}
8651
},
8652
+
"node_modules/locate-path": {
8653
+
"version": "6.0.0",
8654
+
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
8655
+
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
8656
+
"dev": true,
8657
+
"license": "MIT",
8658
+
"peer": true,
8659
+
"dependencies": {
8660
+
"p-locate": "^5.0.0"
8661
+
},
8662
+
"engines": {
8663
+
"node": ">=10"
8664
+
},
8665
+
"funding": {
8666
+
"url": "https://github.com/sponsors/sindresorhus"
8667
+
}
8668
+
},
8669
+
"node_modules/lodash.clonedeep": {
8670
+
"version": "4.5.0",
8671
+
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
8672
+
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
8673
+
"license": "MIT"
8674
+
},
8675
+
"node_modules/lodash.merge": {
8676
+
"version": "4.6.2",
8677
+
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
8678
+
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
8679
+
"dev": true,
8680
+
"license": "MIT",
8681
+
"peer": true
8682
+
},
8683
"node_modules/loose-envify": {
8684
"version": "1.4.0",
8685
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
···
8699
"dev": true,
8700
"license": "MIT"
8701
},
8702
+
"node_modules/lower-case": {
8703
+
"version": "2.0.2",
8704
+
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
8705
+
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
8706
+
"dev": true,
8707
+
"license": "MIT",
8708
+
"dependencies": {
8709
+
"tslib": "^2.0.3"
8710
+
}
8711
+
},
8712
"node_modules/lru-cache": {
8713
"version": "5.1.1",
8714
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
···
8729
}
8730
},
8731
"node_modules/magic-string": {
8732
+
"version": "0.30.19",
8733
+
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
8734
+
"integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
8735
"license": "MIT",
8736
"dependencies": {
8737
"@jridgewell/sourcemap-codec": "^1.5.5"
8738
+
}
8739
+
},
8740
+
"node_modules/math-intrinsics": {
8741
+
"version": "1.1.0",
8742
+
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
8743
+
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
8744
+
"dev": true,
8745
+
"license": "MIT",
8746
+
"engines": {
8747
+
"node": ">= 0.4"
8748
}
8749
},
8750
"node_modules/media-chrome": {
···
8763
"integrity": "sha512-9P2FuUHnZZ3iji+2RQk7Zkh5AmZTnOG5fODACnjhCVveX1McY3jmCRHofIEI+yTBqplz7LXy48c7fQ3Uigp88w==",
8764
"license": "MIT"
8765
},
8766
+
"node_modules/merge2": {
8767
+
"version": "1.4.1",
8768
+
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
8769
+
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
8770
+
"dev": true,
8771
+
"license": "MIT",
8772
+
"engines": {
8773
+
"node": ">= 8"
8774
+
}
8775
+
},
8776
+
"node_modules/micromatch": {
8777
+
"version": "4.0.8",
8778
+
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
8779
+
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
8780
+
"dev": true,
8781
+
"license": "MIT",
8782
+
"dependencies": {
8783
+
"braces": "^3.0.3",
8784
+
"picomatch": "^2.3.1"
8785
+
},
8786
+
"engines": {
8787
+
"node": ">=8.6"
8788
+
}
8789
+
},
8790
+
"node_modules/minimatch": {
8791
+
"version": "3.1.2",
8792
+
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
8793
+
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
8794
+
"dev": true,
8795
+
"license": "ISC",
8796
+
"dependencies": {
8797
+
"brace-expansion": "^1.1.7"
8798
+
},
8799
+
"engines": {
8800
+
"node": "*"
8801
+
}
8802
+
},
8803
"node_modules/minipass": {
8804
"version": "7.1.2",
8805
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
···
8836
"url": "https://github.com/sponsors/isaacs"
8837
}
8838
},
8839
+
"node_modules/mlly": {
8840
+
"version": "1.8.0",
8841
+
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz",
8842
+
"integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==",
8843
+
"dev": true,
8844
+
"license": "MIT",
8845
+
"dependencies": {
8846
+
"acorn": "^8.15.0",
8847
+
"pathe": "^2.0.3",
8848
+
"pkg-types": "^1.3.1",
8849
+
"ufo": "^1.6.1"
8850
+
}
8851
+
},
8852
+
"node_modules/mlly/node_modules/confbox": {
8853
+
"version": "0.1.8",
8854
+
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
8855
+
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
8856
+
"dev": true,
8857
+
"license": "MIT"
8858
+
},
8859
+
"node_modules/mlly/node_modules/pkg-types": {
8860
+
"version": "1.3.1",
8861
+
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
8862
+
"integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
8863
+
"dev": true,
8864
+
"license": "MIT",
8865
+
"dependencies": {
8866
+
"confbox": "^0.1.8",
8867
+
"mlly": "^1.7.4",
8868
+
"pathe": "^2.0.1"
8869
+
}
8870
+
},
8871
"node_modules/ms": {
8872
"version": "2.1.3",
8873
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
···
8910
"integrity": "sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==",
8911
"license": "MIT"
8912
},
8913
+
"node_modules/natural-compare": {
8914
+
"version": "1.4.0",
8915
+
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
8916
+
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
8917
+
"dev": true,
8918
+
"license": "MIT"
8919
+
},
8920
+
"node_modules/no-case": {
8921
+
"version": "3.0.4",
8922
+
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
8923
+
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
8924
+
"dev": true,
8925
+
"license": "MIT",
8926
+
"dependencies": {
8927
+
"lower-case": "^2.0.2",
8928
+
"tslib": "^2.0.3"
8929
+
}
8930
+
},
8931
"node_modules/node-releases": {
8932
"version": "2.0.19",
8933
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
···
8943
"node": ">=0.10.0"
8944
}
8945
},
8946
+
"node_modules/npm": {
8947
+
"version": "11.6.2",
8948
+
"resolved": "https://registry.npmjs.org/npm/-/npm-11.6.2.tgz",
8949
+
"integrity": "sha512-7iKzNfy8lWYs3zq4oFPa8EXZz5xt9gQNKJZau3B1ErLBb6bF7sBJ00x09485DOvRT2l5Gerbl3VlZNT57MxJVA==",
8950
+
"bundleDependencies": [
8951
+
"@isaacs/string-locale-compare",
8952
+
"@npmcli/arborist",
8953
+
"@npmcli/config",
8954
+
"@npmcli/fs",
8955
+
"@npmcli/map-workspaces",
8956
+
"@npmcli/package-json",
8957
+
"@npmcli/promise-spawn",
8958
+
"@npmcli/redact",
8959
+
"@npmcli/run-script",
8960
+
"@sigstore/tuf",
8961
+
"abbrev",
8962
+
"archy",
8963
+
"cacache",
8964
+
"chalk",
8965
+
"ci-info",
8966
+
"cli-columns",
8967
+
"fastest-levenshtein",
8968
+
"fs-minipass",
8969
+
"glob",
8970
+
"graceful-fs",
8971
+
"hosted-git-info",
8972
+
"ini",
8973
+
"init-package-json",
8974
+
"is-cidr",
8975
+
"json-parse-even-better-errors",
8976
+
"libnpmaccess",
8977
+
"libnpmdiff",
8978
+
"libnpmexec",
8979
+
"libnpmfund",
8980
+
"libnpmorg",
8981
+
"libnpmpack",
8982
+
"libnpmpublish",
8983
+
"libnpmsearch",
8984
+
"libnpmteam",
8985
+
"libnpmversion",
8986
+
"make-fetch-happen",
8987
+
"minimatch",
8988
+
"minipass",
8989
+
"minipass-pipeline",
8990
+
"ms",
8991
+
"node-gyp",
8992
+
"nopt",
8993
+
"npm-audit-report",
8994
+
"npm-install-checks",
8995
+
"npm-package-arg",
8996
+
"npm-pick-manifest",
8997
+
"npm-profile",
8998
+
"npm-registry-fetch",
8999
+
"npm-user-validate",
9000
+
"p-map",
9001
+
"pacote",
9002
+
"parse-conflict-json",
9003
+
"proc-log",
9004
+
"qrcode-terminal",
9005
+
"read",
9006
+
"semver",
9007
+
"spdx-expression-parse",
9008
+
"ssri",
9009
+
"supports-color",
9010
+
"tar",
9011
+
"text-table",
9012
+
"tiny-relative-date",
9013
+
"treeverse",
9014
+
"validate-npm-package-name",
9015
+
"which"
9016
+
],
9017
+
"license": "Artistic-2.0",
9018
+
"workspaces": [
9019
+
"docs",
9020
+
"smoke-tests",
9021
+
"mock-globals",
9022
+
"mock-registry",
9023
+
"workspaces/*"
9024
+
],
9025
+
"dependencies": {
9026
+
"@isaacs/string-locale-compare": "^1.1.0",
9027
+
"@npmcli/arborist": "^9.1.6",
9028
+
"@npmcli/config": "^10.4.2",
9029
+
"@npmcli/fs": "^4.0.0",
9030
+
"@npmcli/map-workspaces": "^5.0.0",
9031
+
"@npmcli/package-json": "^7.0.1",
9032
+
"@npmcli/promise-spawn": "^8.0.3",
9033
+
"@npmcli/redact": "^3.2.2",
9034
+
"@npmcli/run-script": "^10.0.0",
9035
+
"@sigstore/tuf": "^4.0.0",
9036
+
"abbrev": "^3.0.1",
9037
+
"archy": "~1.0.0",
9038
+
"cacache": "^20.0.1",
9039
+
"chalk": "^5.6.2",
9040
+
"ci-info": "^4.3.1",
9041
+
"cli-columns": "^4.0.0",
9042
+
"fastest-levenshtein": "^1.0.16",
9043
+
"fs-minipass": "^3.0.3",
9044
+
"glob": "^11.0.3",
9045
+
"graceful-fs": "^4.2.11",
9046
+
"hosted-git-info": "^9.0.2",
9047
+
"ini": "^5.0.0",
9048
+
"init-package-json": "^8.2.2",
9049
+
"is-cidr": "^6.0.1",
9050
+
"json-parse-even-better-errors": "^4.0.0",
9051
+
"libnpmaccess": "^10.0.3",
9052
+
"libnpmdiff": "^8.0.9",
9053
+
"libnpmexec": "^10.1.8",
9054
+
"libnpmfund": "^7.0.9",
9055
+
"libnpmorg": "^8.0.1",
9056
+
"libnpmpack": "^9.0.9",
9057
+
"libnpmpublish": "^11.1.2",
9058
+
"libnpmsearch": "^9.0.1",
9059
+
"libnpmteam": "^8.0.2",
9060
+
"libnpmversion": "^8.0.2",
9061
+
"make-fetch-happen": "^15.0.2",
9062
+
"minimatch": "^10.0.3",
9063
+
"minipass": "^7.1.1",
9064
+
"minipass-pipeline": "^1.2.4",
9065
+
"ms": "^2.1.2",
9066
+
"node-gyp": "^11.4.2",
9067
+
"nopt": "^8.1.0",
9068
+
"npm-audit-report": "^6.0.0",
9069
+
"npm-install-checks": "^7.1.2",
9070
+
"npm-package-arg": "^13.0.1",
9071
+
"npm-pick-manifest": "^11.0.1",
9072
+
"npm-profile": "^12.0.0",
9073
+
"npm-registry-fetch": "^19.0.0",
9074
+
"npm-user-validate": "^3.0.0",
9075
+
"p-map": "^7.0.3",
9076
+
"pacote": "^21.0.3",
9077
+
"parse-conflict-json": "^4.0.0",
9078
+
"proc-log": "^5.0.0",
9079
+
"qrcode-terminal": "^0.12.0",
9080
+
"read": "^4.1.0",
9081
+
"semver": "^7.7.3",
9082
+
"spdx-expression-parse": "^4.0.0",
9083
+
"ssri": "^12.0.0",
9084
+
"supports-color": "^10.2.2",
9085
+
"tar": "^7.5.1",
9086
+
"text-table": "~0.2.0",
9087
+
"tiny-relative-date": "^2.0.2",
9088
+
"treeverse": "^3.0.0",
9089
+
"validate-npm-package-name": "^6.0.2",
9090
+
"which": "^5.0.0"
9091
+
},
9092
+
"bin": {
9093
+
"npm": "bin/npm-cli.js",
9094
+
"npx": "bin/npx-cli.js"
9095
+
},
9096
+
"engines": {
9097
+
"node": "^20.17.0 || >=22.9.0"
9098
+
}
9099
+
},
9100
+
"node_modules/npm/node_modules/@isaacs/balanced-match": {
9101
+
"version": "4.0.1",
9102
+
"inBundle": true,
9103
+
"license": "MIT",
9104
+
"engines": {
9105
+
"node": "20 || >=22"
9106
+
}
9107
+
},
9108
+
"node_modules/npm/node_modules/@isaacs/brace-expansion": {
9109
+
"version": "5.0.0",
9110
+
"inBundle": true,
9111
+
"license": "MIT",
9112
+
"dependencies": {
9113
+
"@isaacs/balanced-match": "^4.0.1"
9114
+
},
9115
+
"engines": {
9116
+
"node": "20 || >=22"
9117
+
}
9118
+
},
9119
+
"node_modules/npm/node_modules/@isaacs/cliui": {
9120
+
"version": "8.0.2",
9121
+
"inBundle": true,
9122
+
"license": "ISC",
9123
+
"dependencies": {
9124
+
"string-width": "^5.1.2",
9125
+
"string-width-cjs": "npm:string-width@^4.2.0",
9126
+
"strip-ansi": "^7.0.1",
9127
+
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
9128
+
"wrap-ansi": "^8.1.0",
9129
+
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
9130
+
},
9131
+
"engines": {
9132
+
"node": ">=12"
9133
+
}
9134
+
},
9135
+
"node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": {
9136
+
"version": "6.2.2",
9137
+
"inBundle": true,
9138
+
"license": "MIT",
9139
+
"engines": {
9140
+
"node": ">=12"
9141
+
},
9142
+
"funding": {
9143
+
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
9144
+
}
9145
+
},
9146
+
"node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": {
9147
+
"version": "9.2.2",
9148
+
"inBundle": true,
9149
+
"license": "MIT"
9150
+
},
9151
+
"node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": {
9152
+
"version": "5.1.2",
9153
+
"inBundle": true,
9154
+
"license": "MIT",
9155
+
"dependencies": {
9156
+
"eastasianwidth": "^0.2.0",
9157
+
"emoji-regex": "^9.2.2",
9158
+
"strip-ansi": "^7.0.1"
9159
+
},
9160
+
"engines": {
9161
+
"node": ">=12"
9162
+
},
9163
+
"funding": {
9164
+
"url": "https://github.com/sponsors/sindresorhus"
9165
+
}
9166
+
},
9167
+
"node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": {
9168
+
"version": "7.1.2",
9169
+
"inBundle": true,
9170
+
"license": "MIT",
9171
+
"dependencies": {
9172
+
"ansi-regex": "^6.0.1"
9173
+
},
9174
+
"engines": {
9175
+
"node": ">=12"
9176
+
},
9177
+
"funding": {
9178
+
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
9179
+
}
9180
+
},
9181
+
"node_modules/npm/node_modules/@isaacs/fs-minipass": {
9182
+
"version": "4.0.1",
9183
+
"inBundle": true,
9184
+
"license": "ISC",
9185
+
"dependencies": {
9186
+
"minipass": "^7.0.4"
9187
+
},
9188
+
"engines": {
9189
+
"node": ">=18.0.0"
9190
+
}
9191
+
},
9192
+
"node_modules/npm/node_modules/@isaacs/string-locale-compare": {
9193
+
"version": "1.1.0",
9194
+
"inBundle": true,
9195
+
"license": "ISC"
9196
+
},
9197
+
"node_modules/npm/node_modules/@npmcli/agent": {
9198
+
"version": "4.0.0",
9199
+
"inBundle": true,
9200
+
"license": "ISC",
9201
+
"dependencies": {
9202
+
"agent-base": "^7.1.0",
9203
+
"http-proxy-agent": "^7.0.0",
9204
+
"https-proxy-agent": "^7.0.1",
9205
+
"lru-cache": "^11.2.1",
9206
+
"socks-proxy-agent": "^8.0.3"
9207
+
},
9208
+
"engines": {
9209
+
"node": "^20.17.0 || >=22.9.0"
9210
+
}
9211
+
},
9212
+
"node_modules/npm/node_modules/@npmcli/arborist": {
9213
+
"version": "9.1.6",
9214
+
"inBundle": true,
9215
+
"license": "ISC",
9216
+
"dependencies": {
9217
+
"@isaacs/string-locale-compare": "^1.1.0",
9218
+
"@npmcli/fs": "^4.0.0",
9219
+
"@npmcli/installed-package-contents": "^3.0.0",
9220
+
"@npmcli/map-workspaces": "^5.0.0",
9221
+
"@npmcli/metavuln-calculator": "^9.0.2",
9222
+
"@npmcli/name-from-folder": "^3.0.0",
9223
+
"@npmcli/node-gyp": "^4.0.0",
9224
+
"@npmcli/package-json": "^7.0.0",
9225
+
"@npmcli/query": "^4.0.0",
9226
+
"@npmcli/redact": "^3.0.0",
9227
+
"@npmcli/run-script": "^10.0.0",
9228
+
"bin-links": "^5.0.0",
9229
+
"cacache": "^20.0.1",
9230
+
"common-ancestor-path": "^1.0.1",
9231
+
"hosted-git-info": "^9.0.0",
9232
+
"json-stringify-nice": "^1.1.4",
9233
+
"lru-cache": "^11.2.1",
9234
+
"minimatch": "^10.0.3",
9235
+
"nopt": "^8.0.0",
9236
+
"npm-install-checks": "^7.1.0",
9237
+
"npm-package-arg": "^13.0.0",
9238
+
"npm-pick-manifest": "^11.0.1",
9239
+
"npm-registry-fetch": "^19.0.0",
9240
+
"pacote": "^21.0.2",
9241
+
"parse-conflict-json": "^4.0.0",
9242
+
"proc-log": "^5.0.0",
9243
+
"proggy": "^3.0.0",
9244
+
"promise-all-reject-late": "^1.0.0",
9245
+
"promise-call-limit": "^3.0.1",
9246
+
"semver": "^7.3.7",
9247
+
"ssri": "^12.0.0",
9248
+
"treeverse": "^3.0.0",
9249
+
"walk-up-path": "^4.0.0"
9250
+
},
9251
+
"bin": {
9252
+
"arborist": "bin/index.js"
9253
+
},
9254
+
"engines": {
9255
+
"node": "^20.17.0 || >=22.9.0"
9256
+
}
9257
+
},
9258
+
"node_modules/npm/node_modules/@npmcli/config": {
9259
+
"version": "10.4.2",
9260
+
"inBundle": true,
9261
+
"license": "ISC",
9262
+
"dependencies": {
9263
+
"@npmcli/map-workspaces": "^5.0.0",
9264
+
"@npmcli/package-json": "^7.0.0",
9265
+
"ci-info": "^4.0.0",
9266
+
"ini": "^5.0.0",
9267
+
"nopt": "^8.1.0",
9268
+
"proc-log": "^5.0.0",
9269
+
"semver": "^7.3.5",
9270
+
"walk-up-path": "^4.0.0"
9271
+
},
9272
+
"engines": {
9273
+
"node": "^20.17.0 || >=22.9.0"
9274
+
}
9275
+
},
9276
+
"node_modules/npm/node_modules/@npmcli/fs": {
9277
+
"version": "4.0.0",
9278
+
"inBundle": true,
9279
+
"license": "ISC",
9280
+
"dependencies": {
9281
+
"semver": "^7.3.5"
9282
+
},
9283
+
"engines": {
9284
+
"node": "^18.17.0 || >=20.5.0"
9285
+
}
9286
+
},
9287
+
"node_modules/npm/node_modules/@npmcli/git": {
9288
+
"version": "7.0.0",
9289
+
"inBundle": true,
9290
+
"license": "ISC",
9291
+
"dependencies": {
9292
+
"@npmcli/promise-spawn": "^8.0.0",
9293
+
"ini": "^5.0.0",
9294
+
"lru-cache": "^11.2.1",
9295
+
"npm-pick-manifest": "^11.0.1",
9296
+
"proc-log": "^5.0.0",
9297
+
"promise-retry": "^2.0.1",
9298
+
"semver": "^7.3.5",
9299
+
"which": "^5.0.0"
9300
+
},
9301
+
"engines": {
9302
+
"node": "^20.17.0 || >=22.9.0"
9303
+
}
9304
+
},
9305
+
"node_modules/npm/node_modules/@npmcli/installed-package-contents": {
9306
+
"version": "3.0.0",
9307
+
"inBundle": true,
9308
+
"license": "ISC",
9309
+
"dependencies": {
9310
+
"npm-bundled": "^4.0.0",
9311
+
"npm-normalize-package-bin": "^4.0.0"
9312
+
},
9313
+
"bin": {
9314
+
"installed-package-contents": "bin/index.js"
9315
+
},
9316
+
"engines": {
9317
+
"node": "^18.17.0 || >=20.5.0"
9318
+
}
9319
+
},
9320
+
"node_modules/npm/node_modules/@npmcli/map-workspaces": {
9321
+
"version": "5.0.0",
9322
+
"inBundle": true,
9323
+
"license": "ISC",
9324
+
"dependencies": {
9325
+
"@npmcli/name-from-folder": "^3.0.0",
9326
+
"@npmcli/package-json": "^7.0.0",
9327
+
"glob": "^11.0.3",
9328
+
"minimatch": "^10.0.3"
9329
+
},
9330
+
"engines": {
9331
+
"node": "^20.17.0 || >=22.9.0"
9332
+
}
9333
+
},
9334
+
"node_modules/npm/node_modules/@npmcli/metavuln-calculator": {
9335
+
"version": "9.0.2",
9336
+
"inBundle": true,
9337
+
"license": "ISC",
9338
+
"dependencies": {
9339
+
"cacache": "^20.0.0",
9340
+
"json-parse-even-better-errors": "^4.0.0",
9341
+
"pacote": "^21.0.0",
9342
+
"proc-log": "^5.0.0",
9343
+
"semver": "^7.3.5"
9344
+
},
9345
+
"engines": {
9346
+
"node": "^20.17.0 || >=22.9.0"
9347
+
}
9348
+
},
9349
+
"node_modules/npm/node_modules/@npmcli/name-from-folder": {
9350
+
"version": "3.0.0",
9351
+
"inBundle": true,
9352
+
"license": "ISC",
9353
+
"engines": {
9354
+
"node": "^18.17.0 || >=20.5.0"
9355
+
}
9356
+
},
9357
+
"node_modules/npm/node_modules/@npmcli/node-gyp": {
9358
+
"version": "4.0.0",
9359
+
"inBundle": true,
9360
+
"license": "ISC",
9361
+
"engines": {
9362
+
"node": "^18.17.0 || >=20.5.0"
9363
+
}
9364
+
},
9365
+
"node_modules/npm/node_modules/@npmcli/package-json": {
9366
+
"version": "7.0.1",
9367
+
"inBundle": true,
9368
+
"license": "ISC",
9369
+
"dependencies": {
9370
+
"@npmcli/git": "^7.0.0",
9371
+
"glob": "^11.0.3",
9372
+
"hosted-git-info": "^9.0.0",
9373
+
"json-parse-even-better-errors": "^4.0.0",
9374
+
"proc-log": "^5.0.0",
9375
+
"semver": "^7.5.3",
9376
+
"validate-npm-package-license": "^3.0.4"
9377
+
},
9378
+
"engines": {
9379
+
"node": "^20.17.0 || >=22.9.0"
9380
+
}
9381
+
},
9382
+
"node_modules/npm/node_modules/@npmcli/promise-spawn": {
9383
+
"version": "8.0.3",
9384
+
"inBundle": true,
9385
+
"license": "ISC",
9386
+
"dependencies": {
9387
+
"which": "^5.0.0"
9388
+
},
9389
+
"engines": {
9390
+
"node": "^18.17.0 || >=20.5.0"
9391
+
}
9392
+
},
9393
+
"node_modules/npm/node_modules/@npmcli/query": {
9394
+
"version": "4.0.1",
9395
+
"inBundle": true,
9396
+
"license": "ISC",
9397
+
"dependencies": {
9398
+
"postcss-selector-parser": "^7.0.0"
9399
+
},
9400
+
"engines": {
9401
+
"node": "^18.17.0 || >=20.5.0"
9402
+
}
9403
+
},
9404
+
"node_modules/npm/node_modules/@npmcli/redact": {
9405
+
"version": "3.2.2",
9406
+
"inBundle": true,
9407
+
"license": "ISC",
9408
+
"engines": {
9409
+
"node": "^18.17.0 || >=20.5.0"
9410
+
}
9411
+
},
9412
+
"node_modules/npm/node_modules/@npmcli/run-script": {
9413
+
"version": "10.0.0",
9414
+
"inBundle": true,
9415
+
"license": "ISC",
9416
+
"dependencies": {
9417
+
"@npmcli/node-gyp": "^4.0.0",
9418
+
"@npmcli/package-json": "^7.0.0",
9419
+
"@npmcli/promise-spawn": "^8.0.0",
9420
+
"node-gyp": "^11.0.0",
9421
+
"proc-log": "^5.0.0",
9422
+
"which": "^5.0.0"
9423
+
},
9424
+
"engines": {
9425
+
"node": "^20.17.0 || >=22.9.0"
9426
+
}
9427
+
},
9428
+
"node_modules/npm/node_modules/@pkgjs/parseargs": {
9429
+
"version": "0.11.0",
9430
+
"inBundle": true,
9431
+
"license": "MIT",
9432
+
"optional": true,
9433
+
"engines": {
9434
+
"node": ">=14"
9435
+
}
9436
+
},
9437
+
"node_modules/npm/node_modules/@sigstore/bundle": {
9438
+
"version": "4.0.0",
9439
+
"inBundle": true,
9440
+
"license": "Apache-2.0",
9441
+
"dependencies": {
9442
+
"@sigstore/protobuf-specs": "^0.5.0"
9443
+
},
9444
+
"engines": {
9445
+
"node": "^20.17.0 || >=22.9.0"
9446
+
}
9447
+
},
9448
+
"node_modules/npm/node_modules/@sigstore/core": {
9449
+
"version": "3.0.0",
9450
+
"inBundle": true,
9451
+
"license": "Apache-2.0",
9452
+
"engines": {
9453
+
"node": "^20.17.0 || >=22.9.0"
9454
+
}
9455
+
},
9456
+
"node_modules/npm/node_modules/@sigstore/protobuf-specs": {
9457
+
"version": "0.5.0",
9458
+
"inBundle": true,
9459
+
"license": "Apache-2.0",
9460
+
"engines": {
9461
+
"node": "^18.17.0 || >=20.5.0"
9462
+
}
9463
+
},
9464
+
"node_modules/npm/node_modules/@sigstore/sign": {
9465
+
"version": "4.0.1",
9466
+
"inBundle": true,
9467
+
"license": "Apache-2.0",
9468
+
"dependencies": {
9469
+
"@sigstore/bundle": "^4.0.0",
9470
+
"@sigstore/core": "^3.0.0",
9471
+
"@sigstore/protobuf-specs": "^0.5.0",
9472
+
"make-fetch-happen": "^15.0.2",
9473
+
"proc-log": "^5.0.0",
9474
+
"promise-retry": "^2.0.1"
9475
+
},
9476
+
"engines": {
9477
+
"node": "^20.17.0 || >=22.9.0"
9478
+
}
9479
+
},
9480
+
"node_modules/npm/node_modules/@sigstore/tuf": {
9481
+
"version": "4.0.0",
9482
+
"inBundle": true,
9483
+
"license": "Apache-2.0",
9484
+
"dependencies": {
9485
+
"@sigstore/protobuf-specs": "^0.5.0",
9486
+
"tuf-js": "^4.0.0"
9487
+
},
9488
+
"engines": {
9489
+
"node": "^20.17.0 || >=22.9.0"
9490
+
}
9491
+
},
9492
+
"node_modules/npm/node_modules/@sigstore/verify": {
9493
+
"version": "3.0.0",
9494
+
"inBundle": true,
9495
+
"license": "Apache-2.0",
9496
+
"dependencies": {
9497
+
"@sigstore/bundle": "^4.0.0",
9498
+
"@sigstore/core": "^3.0.0",
9499
+
"@sigstore/protobuf-specs": "^0.5.0"
9500
+
},
9501
+
"engines": {
9502
+
"node": "^20.17.0 || >=22.9.0"
9503
+
}
9504
+
},
9505
+
"node_modules/npm/node_modules/@tufjs/canonical-json": {
9506
+
"version": "2.0.0",
9507
+
"inBundle": true,
9508
+
"license": "MIT",
9509
+
"engines": {
9510
+
"node": "^16.14.0 || >=18.0.0"
9511
+
}
9512
+
},
9513
+
"node_modules/npm/node_modules/@tufjs/models": {
9514
+
"version": "4.0.0",
9515
+
"inBundle": true,
9516
+
"license": "MIT",
9517
+
"dependencies": {
9518
+
"@tufjs/canonical-json": "2.0.0",
9519
+
"minimatch": "^9.0.5"
9520
+
},
9521
+
"engines": {
9522
+
"node": "^20.17.0 || >=22.9.0"
9523
+
}
9524
+
},
9525
+
"node_modules/npm/node_modules/@tufjs/models/node_modules/minimatch": {
9526
+
"version": "9.0.5",
9527
+
"inBundle": true,
9528
+
"license": "ISC",
9529
+
"dependencies": {
9530
+
"brace-expansion": "^2.0.1"
9531
+
},
9532
+
"engines": {
9533
+
"node": ">=16 || 14 >=14.17"
9534
+
},
9535
+
"funding": {
9536
+
"url": "https://github.com/sponsors/isaacs"
9537
+
}
9538
+
},
9539
+
"node_modules/npm/node_modules/abbrev": {
9540
+
"version": "3.0.1",
9541
+
"inBundle": true,
9542
+
"license": "ISC",
9543
+
"engines": {
9544
+
"node": "^18.17.0 || >=20.5.0"
9545
+
}
9546
+
},
9547
+
"node_modules/npm/node_modules/agent-base": {
9548
+
"version": "7.1.4",
9549
+
"inBundle": true,
9550
+
"license": "MIT",
9551
+
"engines": {
9552
+
"node": ">= 14"
9553
+
}
9554
+
},
9555
+
"node_modules/npm/node_modules/ansi-regex": {
9556
+
"version": "5.0.1",
9557
+
"inBundle": true,
9558
+
"license": "MIT",
9559
+
"engines": {
9560
+
"node": ">=8"
9561
+
}
9562
+
},
9563
+
"node_modules/npm/node_modules/ansi-styles": {
9564
+
"version": "6.2.3",
9565
+
"inBundle": true,
9566
+
"license": "MIT",
9567
+
"engines": {
9568
+
"node": ">=12"
9569
+
},
9570
+
"funding": {
9571
+
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
9572
+
}
9573
+
},
9574
+
"node_modules/npm/node_modules/aproba": {
9575
+
"version": "2.1.0",
9576
+
"inBundle": true,
9577
+
"license": "ISC"
9578
+
},
9579
+
"node_modules/npm/node_modules/archy": {
9580
+
"version": "1.0.0",
9581
+
"inBundle": true,
9582
+
"license": "MIT"
9583
+
},
9584
+
"node_modules/npm/node_modules/balanced-match": {
9585
+
"version": "1.0.2",
9586
+
"inBundle": true,
9587
+
"license": "MIT"
9588
+
},
9589
+
"node_modules/npm/node_modules/bin-links": {
9590
+
"version": "5.0.0",
9591
+
"inBundle": true,
9592
+
"license": "ISC",
9593
+
"dependencies": {
9594
+
"cmd-shim": "^7.0.0",
9595
+
"npm-normalize-package-bin": "^4.0.0",
9596
+
"proc-log": "^5.0.0",
9597
+
"read-cmd-shim": "^5.0.0",
9598
+
"write-file-atomic": "^6.0.0"
9599
+
},
9600
+
"engines": {
9601
+
"node": "^18.17.0 || >=20.5.0"
9602
+
}
9603
+
},
9604
+
"node_modules/npm/node_modules/binary-extensions": {
9605
+
"version": "3.1.0",
9606
+
"inBundle": true,
9607
+
"license": "MIT",
9608
+
"engines": {
9609
+
"node": ">=18.20"
9610
+
},
9611
+
"funding": {
9612
+
"url": "https://github.com/sponsors/sindresorhus"
9613
+
}
9614
+
},
9615
+
"node_modules/npm/node_modules/brace-expansion": {
9616
+
"version": "2.0.2",
9617
+
"inBundle": true,
9618
+
"license": "MIT",
9619
+
"dependencies": {
9620
+
"balanced-match": "^1.0.0"
9621
+
}
9622
+
},
9623
+
"node_modules/npm/node_modules/cacache": {
9624
+
"version": "20.0.1",
9625
+
"inBundle": true,
9626
+
"license": "ISC",
9627
+
"dependencies": {
9628
+
"@npmcli/fs": "^4.0.0",
9629
+
"fs-minipass": "^3.0.0",
9630
+
"glob": "^11.0.3",
9631
+
"lru-cache": "^11.1.0",
9632
+
"minipass": "^7.0.3",
9633
+
"minipass-collect": "^2.0.1",
9634
+
"minipass-flush": "^1.0.5",
9635
+
"minipass-pipeline": "^1.2.4",
9636
+
"p-map": "^7.0.2",
9637
+
"ssri": "^12.0.0",
9638
+
"unique-filename": "^4.0.0"
9639
+
},
9640
+
"engines": {
9641
+
"node": "^20.17.0 || >=22.9.0"
9642
+
}
9643
+
},
9644
+
"node_modules/npm/node_modules/chalk": {
9645
+
"version": "5.6.2",
9646
+
"inBundle": true,
9647
+
"license": "MIT",
9648
+
"engines": {
9649
+
"node": "^12.17.0 || ^14.13 || >=16.0.0"
9650
+
},
9651
+
"funding": {
9652
+
"url": "https://github.com/chalk/chalk?sponsor=1"
9653
+
}
9654
+
},
9655
+
"node_modules/npm/node_modules/chownr": {
9656
+
"version": "3.0.0",
9657
+
"inBundle": true,
9658
+
"license": "BlueOak-1.0.0",
9659
+
"engines": {
9660
+
"node": ">=18"
9661
+
}
9662
+
},
9663
+
"node_modules/npm/node_modules/ci-info": {
9664
+
"version": "4.3.1",
9665
+
"funding": [
9666
+
{
9667
+
"type": "github",
9668
+
"url": "https://github.com/sponsors/sibiraj-s"
9669
+
}
9670
+
],
9671
+
"inBundle": true,
9672
+
"license": "MIT",
9673
+
"engines": {
9674
+
"node": ">=8"
9675
+
}
9676
+
},
9677
+
"node_modules/npm/node_modules/cidr-regex": {
9678
+
"version": "5.0.1",
9679
+
"inBundle": true,
9680
+
"license": "BSD-2-Clause",
9681
+
"dependencies": {
9682
+
"ip-regex": "5.0.0"
9683
+
},
9684
+
"engines": {
9685
+
"node": ">=20"
9686
+
}
9687
+
},
9688
+
"node_modules/npm/node_modules/cli-columns": {
9689
+
"version": "4.0.0",
9690
+
"inBundle": true,
9691
+
"license": "MIT",
9692
+
"dependencies": {
9693
+
"string-width": "^4.2.3",
9694
+
"strip-ansi": "^6.0.1"
9695
+
},
9696
+
"engines": {
9697
+
"node": ">= 10"
9698
+
}
9699
+
},
9700
+
"node_modules/npm/node_modules/cmd-shim": {
9701
+
"version": "7.0.0",
9702
+
"inBundle": true,
9703
+
"license": "ISC",
9704
+
"engines": {
9705
+
"node": "^18.17.0 || >=20.5.0"
9706
+
}
9707
+
},
9708
+
"node_modules/npm/node_modules/color-convert": {
9709
+
"version": "2.0.1",
9710
+
"inBundle": true,
9711
+
"license": "MIT",
9712
+
"dependencies": {
9713
+
"color-name": "~1.1.4"
9714
+
},
9715
+
"engines": {
9716
+
"node": ">=7.0.0"
9717
+
}
9718
+
},
9719
+
"node_modules/npm/node_modules/color-name": {
9720
+
"version": "1.1.4",
9721
+
"inBundle": true,
9722
+
"license": "MIT"
9723
+
},
9724
+
"node_modules/npm/node_modules/common-ancestor-path": {
9725
+
"version": "1.0.1",
9726
+
"inBundle": true,
9727
+
"license": "ISC"
9728
+
},
9729
+
"node_modules/npm/node_modules/cross-spawn": {
9730
+
"version": "7.0.6",
9731
+
"inBundle": true,
9732
+
"license": "MIT",
9733
+
"dependencies": {
9734
+
"path-key": "^3.1.0",
9735
+
"shebang-command": "^2.0.0",
9736
+
"which": "^2.0.1"
9737
+
},
9738
+
"engines": {
9739
+
"node": ">= 8"
9740
+
}
9741
+
},
9742
+
"node_modules/npm/node_modules/cross-spawn/node_modules/isexe": {
9743
+
"version": "2.0.0",
9744
+
"inBundle": true,
9745
+
"license": "ISC"
9746
+
},
9747
+
"node_modules/npm/node_modules/cross-spawn/node_modules/which": {
9748
+
"version": "2.0.2",
9749
+
"inBundle": true,
9750
+
"license": "ISC",
9751
+
"dependencies": {
9752
+
"isexe": "^2.0.0"
9753
+
},
9754
+
"bin": {
9755
+
"node-which": "bin/node-which"
9756
+
},
9757
+
"engines": {
9758
+
"node": ">= 8"
9759
+
}
9760
+
},
9761
+
"node_modules/npm/node_modules/cssesc": {
9762
+
"version": "3.0.0",
9763
+
"inBundle": true,
9764
+
"license": "MIT",
9765
+
"bin": {
9766
+
"cssesc": "bin/cssesc"
9767
+
},
9768
+
"engines": {
9769
+
"node": ">=4"
9770
+
}
9771
+
},
9772
+
"node_modules/npm/node_modules/debug": {
9773
+
"version": "4.4.3",
9774
+
"inBundle": true,
9775
+
"license": "MIT",
9776
+
"dependencies": {
9777
+
"ms": "^2.1.3"
9778
+
},
9779
+
"engines": {
9780
+
"node": ">=6.0"
9781
+
},
9782
+
"peerDependenciesMeta": {
9783
+
"supports-color": {
9784
+
"optional": true
9785
+
}
9786
+
}
9787
+
},
9788
+
"node_modules/npm/node_modules/diff": {
9789
+
"version": "8.0.2",
9790
+
"inBundle": true,
9791
+
"license": "BSD-3-Clause",
9792
+
"engines": {
9793
+
"node": ">=0.3.1"
9794
+
}
9795
+
},
9796
+
"node_modules/npm/node_modules/eastasianwidth": {
9797
+
"version": "0.2.0",
9798
+
"inBundle": true,
9799
+
"license": "MIT"
9800
+
},
9801
+
"node_modules/npm/node_modules/emoji-regex": {
9802
+
"version": "8.0.0",
9803
+
"inBundle": true,
9804
+
"license": "MIT"
9805
+
},
9806
+
"node_modules/npm/node_modules/encoding": {
9807
+
"version": "0.1.13",
9808
+
"inBundle": true,
9809
+
"license": "MIT",
9810
+
"optional": true,
9811
+
"dependencies": {
9812
+
"iconv-lite": "^0.6.2"
9813
+
}
9814
+
},
9815
+
"node_modules/npm/node_modules/env-paths": {
9816
+
"version": "2.2.1",
9817
+
"inBundle": true,
9818
+
"license": "MIT",
9819
+
"engines": {
9820
+
"node": ">=6"
9821
+
}
9822
+
},
9823
+
"node_modules/npm/node_modules/err-code": {
9824
+
"version": "2.0.3",
9825
+
"inBundle": true,
9826
+
"license": "MIT"
9827
+
},
9828
+
"node_modules/npm/node_modules/exponential-backoff": {
9829
+
"version": "3.1.2",
9830
+
"inBundle": true,
9831
+
"license": "Apache-2.0"
9832
+
},
9833
+
"node_modules/npm/node_modules/fastest-levenshtein": {
9834
+
"version": "1.0.16",
9835
+
"inBundle": true,
9836
+
"license": "MIT",
9837
+
"engines": {
9838
+
"node": ">= 4.9.1"
9839
+
}
9840
+
},
9841
+
"node_modules/npm/node_modules/foreground-child": {
9842
+
"version": "3.3.1",
9843
+
"inBundle": true,
9844
+
"license": "ISC",
9845
+
"dependencies": {
9846
+
"cross-spawn": "^7.0.6",
9847
+
"signal-exit": "^4.0.1"
9848
+
},
9849
+
"engines": {
9850
+
"node": ">=14"
9851
+
},
9852
+
"funding": {
9853
+
"url": "https://github.com/sponsors/isaacs"
9854
+
}
9855
+
},
9856
+
"node_modules/npm/node_modules/fs-minipass": {
9857
+
"version": "3.0.3",
9858
+
"inBundle": true,
9859
+
"license": "ISC",
9860
+
"dependencies": {
9861
+
"minipass": "^7.0.3"
9862
+
},
9863
+
"engines": {
9864
+
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
9865
+
}
9866
+
},
9867
+
"node_modules/npm/node_modules/glob": {
9868
+
"version": "11.0.3",
9869
+
"inBundle": true,
9870
+
"license": "ISC",
9871
+
"dependencies": {
9872
+
"foreground-child": "^3.3.1",
9873
+
"jackspeak": "^4.1.1",
9874
+
"minimatch": "^10.0.3",
9875
+
"minipass": "^7.1.2",
9876
+
"package-json-from-dist": "^1.0.0",
9877
+
"path-scurry": "^2.0.0"
9878
+
},
9879
+
"bin": {
9880
+
"glob": "dist/esm/bin.mjs"
9881
+
},
9882
+
"engines": {
9883
+
"node": "20 || >=22"
9884
+
},
9885
+
"funding": {
9886
+
"url": "https://github.com/sponsors/isaacs"
9887
+
}
9888
+
},
9889
+
"node_modules/npm/node_modules/graceful-fs": {
9890
+
"version": "4.2.11",
9891
+
"inBundle": true,
9892
+
"license": "ISC"
9893
+
},
9894
+
"node_modules/npm/node_modules/hosted-git-info": {
9895
+
"version": "9.0.2",
9896
+
"inBundle": true,
9897
+
"license": "ISC",
9898
+
"dependencies": {
9899
+
"lru-cache": "^11.1.0"
9900
+
},
9901
+
"engines": {
9902
+
"node": "^20.17.0 || >=22.9.0"
9903
+
}
9904
+
},
9905
+
"node_modules/npm/node_modules/http-cache-semantics": {
9906
+
"version": "4.2.0",
9907
+
"inBundle": true,
9908
+
"license": "BSD-2-Clause"
9909
+
},
9910
+
"node_modules/npm/node_modules/http-proxy-agent": {
9911
+
"version": "7.0.2",
9912
+
"inBundle": true,
9913
+
"license": "MIT",
9914
+
"dependencies": {
9915
+
"agent-base": "^7.1.0",
9916
+
"debug": "^4.3.4"
9917
+
},
9918
+
"engines": {
9919
+
"node": ">= 14"
9920
+
}
9921
+
},
9922
+
"node_modules/npm/node_modules/https-proxy-agent": {
9923
+
"version": "7.0.6",
9924
+
"inBundle": true,
9925
+
"license": "MIT",
9926
+
"dependencies": {
9927
+
"agent-base": "^7.1.2",
9928
+
"debug": "4"
9929
+
},
9930
+
"engines": {
9931
+
"node": ">= 14"
9932
+
}
9933
+
},
9934
+
"node_modules/npm/node_modules/iconv-lite": {
9935
+
"version": "0.6.3",
9936
+
"inBundle": true,
9937
+
"license": "MIT",
9938
+
"optional": true,
9939
+
"dependencies": {
9940
+
"safer-buffer": ">= 2.1.2 < 3.0.0"
9941
+
},
9942
+
"engines": {
9943
+
"node": ">=0.10.0"
9944
+
}
9945
+
},
9946
+
"node_modules/npm/node_modules/ignore-walk": {
9947
+
"version": "8.0.0",
9948
+
"inBundle": true,
9949
+
"license": "ISC",
9950
+
"dependencies": {
9951
+
"minimatch": "^10.0.3"
9952
+
},
9953
+
"engines": {
9954
+
"node": "^20.17.0 || >=22.9.0"
9955
+
}
9956
+
},
9957
+
"node_modules/npm/node_modules/imurmurhash": {
9958
+
"version": "0.1.4",
9959
+
"inBundle": true,
9960
+
"license": "MIT",
9961
+
"engines": {
9962
+
"node": ">=0.8.19"
9963
+
}
9964
+
},
9965
+
"node_modules/npm/node_modules/ini": {
9966
+
"version": "5.0.0",
9967
+
"inBundle": true,
9968
+
"license": "ISC",
9969
+
"engines": {
9970
+
"node": "^18.17.0 || >=20.5.0"
9971
+
}
9972
+
},
9973
+
"node_modules/npm/node_modules/init-package-json": {
9974
+
"version": "8.2.2",
9975
+
"inBundle": true,
9976
+
"license": "ISC",
9977
+
"dependencies": {
9978
+
"@npmcli/package-json": "^7.0.0",
9979
+
"npm-package-arg": "^13.0.0",
9980
+
"promzard": "^2.0.0",
9981
+
"read": "^4.0.0",
9982
+
"semver": "^7.7.2",
9983
+
"validate-npm-package-license": "^3.0.4",
9984
+
"validate-npm-package-name": "^6.0.2"
9985
+
},
9986
+
"engines": {
9987
+
"node": "^20.17.0 || >=22.9.0"
9988
+
}
9989
+
},
9990
+
"node_modules/npm/node_modules/ip-address": {
9991
+
"version": "10.0.1",
9992
+
"inBundle": true,
9993
+
"license": "MIT",
9994
+
"engines": {
9995
+
"node": ">= 12"
9996
+
}
9997
+
},
9998
+
"node_modules/npm/node_modules/ip-regex": {
9999
+
"version": "5.0.0",
10000
+
"inBundle": true,
10001
+
"license": "MIT",
10002
+
"engines": {
10003
+
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
10004
+
},
10005
+
"funding": {
10006
+
"url": "https://github.com/sponsors/sindresorhus"
10007
+
}
10008
+
},
10009
+
"node_modules/npm/node_modules/is-cidr": {
10010
+
"version": "6.0.1",
10011
+
"inBundle": true,
10012
+
"license": "BSD-2-Clause",
10013
+
"dependencies": {
10014
+
"cidr-regex": "5.0.1"
10015
+
},
10016
+
"engines": {
10017
+
"node": ">=20"
10018
+
}
10019
+
},
10020
+
"node_modules/npm/node_modules/is-fullwidth-code-point": {
10021
+
"version": "3.0.0",
10022
+
"inBundle": true,
10023
+
"license": "MIT",
10024
+
"engines": {
10025
+
"node": ">=8"
10026
+
}
10027
+
},
10028
+
"node_modules/npm/node_modules/isexe": {
10029
+
"version": "3.1.1",
10030
+
"inBundle": true,
10031
+
"license": "ISC",
10032
+
"engines": {
10033
+
"node": ">=16"
10034
+
}
10035
+
},
10036
+
"node_modules/npm/node_modules/jackspeak": {
10037
+
"version": "4.1.1",
10038
+
"inBundle": true,
10039
+
"license": "BlueOak-1.0.0",
10040
+
"dependencies": {
10041
+
"@isaacs/cliui": "^8.0.2"
10042
+
},
10043
+
"engines": {
10044
+
"node": "20 || >=22"
10045
+
},
10046
+
"funding": {
10047
+
"url": "https://github.com/sponsors/isaacs"
10048
+
}
10049
+
},
10050
+
"node_modules/npm/node_modules/json-parse-even-better-errors": {
10051
+
"version": "4.0.0",
10052
+
"inBundle": true,
10053
+
"license": "MIT",
10054
+
"engines": {
10055
+
"node": "^18.17.0 || >=20.5.0"
10056
+
}
10057
+
},
10058
+
"node_modules/npm/node_modules/json-stringify-nice": {
10059
+
"version": "1.1.4",
10060
+
"inBundle": true,
10061
+
"license": "ISC",
10062
+
"funding": {
10063
+
"url": "https://github.com/sponsors/isaacs"
10064
+
}
10065
+
},
10066
+
"node_modules/npm/node_modules/jsonparse": {
10067
+
"version": "1.3.1",
10068
+
"engines": [
10069
+
"node >= 0.2.0"
10070
+
],
10071
+
"inBundle": true,
10072
+
"license": "MIT"
10073
+
},
10074
+
"node_modules/npm/node_modules/just-diff": {
10075
+
"version": "6.0.2",
10076
+
"inBundle": true,
10077
+
"license": "MIT"
10078
+
},
10079
+
"node_modules/npm/node_modules/just-diff-apply": {
10080
+
"version": "5.5.0",
10081
+
"inBundle": true,
10082
+
"license": "MIT"
10083
+
},
10084
+
"node_modules/npm/node_modules/libnpmaccess": {
10085
+
"version": "10.0.3",
10086
+
"inBundle": true,
10087
+
"license": "ISC",
10088
+
"dependencies": {
10089
+
"npm-package-arg": "^13.0.0",
10090
+
"npm-registry-fetch": "^19.0.0"
10091
+
},
10092
+
"engines": {
10093
+
"node": "^20.17.0 || >=22.9.0"
10094
+
}
10095
+
},
10096
+
"node_modules/npm/node_modules/libnpmdiff": {
10097
+
"version": "8.0.9",
10098
+
"inBundle": true,
10099
+
"license": "ISC",
10100
+
"dependencies": {
10101
+
"@npmcli/arborist": "^9.1.6",
10102
+
"@npmcli/installed-package-contents": "^3.0.0",
10103
+
"binary-extensions": "^3.0.0",
10104
+
"diff": "^8.0.2",
10105
+
"minimatch": "^10.0.3",
10106
+
"npm-package-arg": "^13.0.0",
10107
+
"pacote": "^21.0.2",
10108
+
"tar": "^7.5.1"
10109
+
},
10110
+
"engines": {
10111
+
"node": "^20.17.0 || >=22.9.0"
10112
+
}
10113
+
},
10114
+
"node_modules/npm/node_modules/libnpmexec": {
10115
+
"version": "10.1.8",
10116
+
"inBundle": true,
10117
+
"license": "ISC",
10118
+
"dependencies": {
10119
+
"@npmcli/arborist": "^9.1.6",
10120
+
"@npmcli/package-json": "^7.0.0",
10121
+
"@npmcli/run-script": "^10.0.0",
10122
+
"ci-info": "^4.0.0",
10123
+
"npm-package-arg": "^13.0.0",
10124
+
"pacote": "^21.0.2",
10125
+
"proc-log": "^5.0.0",
10126
+
"promise-retry": "^2.0.1",
10127
+
"read": "^4.0.0",
10128
+
"semver": "^7.3.7",
10129
+
"signal-exit": "^4.1.0",
10130
+
"walk-up-path": "^4.0.0"
10131
+
},
10132
+
"engines": {
10133
+
"node": "^20.17.0 || >=22.9.0"
10134
+
}
10135
+
},
10136
+
"node_modules/npm/node_modules/libnpmfund": {
10137
+
"version": "7.0.9",
10138
+
"inBundle": true,
10139
+
"license": "ISC",
10140
+
"dependencies": {
10141
+
"@npmcli/arborist": "^9.1.6"
10142
+
},
10143
+
"engines": {
10144
+
"node": "^20.17.0 || >=22.9.0"
10145
+
}
10146
+
},
10147
+
"node_modules/npm/node_modules/libnpmorg": {
10148
+
"version": "8.0.1",
10149
+
"inBundle": true,
10150
+
"license": "ISC",
10151
+
"dependencies": {
10152
+
"aproba": "^2.0.0",
10153
+
"npm-registry-fetch": "^19.0.0"
10154
+
},
10155
+
"engines": {
10156
+
"node": "^20.17.0 || >=22.9.0"
10157
+
}
10158
+
},
10159
+
"node_modules/npm/node_modules/libnpmpack": {
10160
+
"version": "9.0.9",
10161
+
"inBundle": true,
10162
+
"license": "ISC",
10163
+
"dependencies": {
10164
+
"@npmcli/arborist": "^9.1.6",
10165
+
"@npmcli/run-script": "^10.0.0",
10166
+
"npm-package-arg": "^13.0.0",
10167
+
"pacote": "^21.0.2"
10168
+
},
10169
+
"engines": {
10170
+
"node": "^20.17.0 || >=22.9.0"
10171
+
}
10172
+
},
10173
+
"node_modules/npm/node_modules/libnpmpublish": {
10174
+
"version": "11.1.2",
10175
+
"inBundle": true,
10176
+
"license": "ISC",
10177
+
"dependencies": {
10178
+
"@npmcli/package-json": "^7.0.0",
10179
+
"ci-info": "^4.0.0",
10180
+
"npm-package-arg": "^13.0.0",
10181
+
"npm-registry-fetch": "^19.0.0",
10182
+
"proc-log": "^5.0.0",
10183
+
"semver": "^7.3.7",
10184
+
"sigstore": "^4.0.0",
10185
+
"ssri": "^12.0.0"
10186
+
},
10187
+
"engines": {
10188
+
"node": "^20.17.0 || >=22.9.0"
10189
+
}
10190
+
},
10191
+
"node_modules/npm/node_modules/libnpmsearch": {
10192
+
"version": "9.0.1",
10193
+
"inBundle": true,
10194
+
"license": "ISC",
10195
+
"dependencies": {
10196
+
"npm-registry-fetch": "^19.0.0"
10197
+
},
10198
+
"engines": {
10199
+
"node": "^20.17.0 || >=22.9.0"
10200
+
}
10201
+
},
10202
+
"node_modules/npm/node_modules/libnpmteam": {
10203
+
"version": "8.0.2",
10204
+
"inBundle": true,
10205
+
"license": "ISC",
10206
+
"dependencies": {
10207
+
"aproba": "^2.0.0",
10208
+
"npm-registry-fetch": "^19.0.0"
10209
+
},
10210
+
"engines": {
10211
+
"node": "^20.17.0 || >=22.9.0"
10212
+
}
10213
+
},
10214
+
"node_modules/npm/node_modules/libnpmversion": {
10215
+
"version": "8.0.2",
10216
+
"inBundle": true,
10217
+
"license": "ISC",
10218
+
"dependencies": {
10219
+
"@npmcli/git": "^7.0.0",
10220
+
"@npmcli/run-script": "^10.0.0",
10221
+
"json-parse-even-better-errors": "^4.0.0",
10222
+
"proc-log": "^5.0.0",
10223
+
"semver": "^7.3.7"
10224
+
},
10225
+
"engines": {
10226
+
"node": "^20.17.0 || >=22.9.0"
10227
+
}
10228
+
},
10229
+
"node_modules/npm/node_modules/lru-cache": {
10230
+
"version": "11.2.2",
10231
+
"inBundle": true,
10232
+
"license": "ISC",
10233
+
"engines": {
10234
+
"node": "20 || >=22"
10235
+
}
10236
+
},
10237
+
"node_modules/npm/node_modules/make-fetch-happen": {
10238
+
"version": "15.0.2",
10239
+
"inBundle": true,
10240
+
"license": "ISC",
10241
+
"dependencies": {
10242
+
"@npmcli/agent": "^4.0.0",
10243
+
"cacache": "^20.0.1",
10244
+
"http-cache-semantics": "^4.1.1",
10245
+
"minipass": "^7.0.2",
10246
+
"minipass-fetch": "^4.0.0",
10247
+
"minipass-flush": "^1.0.5",
10248
+
"minipass-pipeline": "^1.2.4",
10249
+
"negotiator": "^1.0.0",
10250
+
"proc-log": "^5.0.0",
10251
+
"promise-retry": "^2.0.1",
10252
+
"ssri": "^12.0.0"
10253
+
},
10254
+
"engines": {
10255
+
"node": "^20.17.0 || >=22.9.0"
10256
+
}
10257
+
},
10258
+
"node_modules/npm/node_modules/minimatch": {
10259
+
"version": "10.0.3",
10260
+
"inBundle": true,
10261
+
"license": "ISC",
10262
+
"dependencies": {
10263
+
"@isaacs/brace-expansion": "^5.0.0"
10264
+
},
10265
+
"engines": {
10266
+
"node": "20 || >=22"
10267
+
},
10268
+
"funding": {
10269
+
"url": "https://github.com/sponsors/isaacs"
10270
+
}
10271
+
},
10272
+
"node_modules/npm/node_modules/minipass": {
10273
+
"version": "7.1.2",
10274
+
"inBundle": true,
10275
+
"license": "ISC",
10276
+
"engines": {
10277
+
"node": ">=16 || 14 >=14.17"
10278
+
}
10279
+
},
10280
+
"node_modules/npm/node_modules/minipass-collect": {
10281
+
"version": "2.0.1",
10282
+
"inBundle": true,
10283
+
"license": "ISC",
10284
+
"dependencies": {
10285
+
"minipass": "^7.0.3"
10286
+
},
10287
+
"engines": {
10288
+
"node": ">=16 || 14 >=14.17"
10289
+
}
10290
+
},
10291
+
"node_modules/npm/node_modules/minipass-fetch": {
10292
+
"version": "4.0.1",
10293
+
"inBundle": true,
10294
+
"license": "MIT",
10295
+
"dependencies": {
10296
+
"minipass": "^7.0.3",
10297
+
"minipass-sized": "^1.0.3",
10298
+
"minizlib": "^3.0.1"
10299
+
},
10300
+
"engines": {
10301
+
"node": "^18.17.0 || >=20.5.0"
10302
+
},
10303
+
"optionalDependencies": {
10304
+
"encoding": "^0.1.13"
10305
+
}
10306
+
},
10307
+
"node_modules/npm/node_modules/minipass-flush": {
10308
+
"version": "1.0.5",
10309
+
"inBundle": true,
10310
+
"license": "ISC",
10311
+
"dependencies": {
10312
+
"minipass": "^3.0.0"
10313
+
},
10314
+
"engines": {
10315
+
"node": ">= 8"
10316
+
}
10317
+
},
10318
+
"node_modules/npm/node_modules/minipass-flush/node_modules/minipass": {
10319
+
"version": "3.3.6",
10320
+
"inBundle": true,
10321
+
"license": "ISC",
10322
+
"dependencies": {
10323
+
"yallist": "^4.0.0"
10324
+
},
10325
+
"engines": {
10326
+
"node": ">=8"
10327
+
}
10328
+
},
10329
+
"node_modules/npm/node_modules/minipass-pipeline": {
10330
+
"version": "1.2.4",
10331
+
"inBundle": true,
10332
+
"license": "ISC",
10333
+
"dependencies": {
10334
+
"minipass": "^3.0.0"
10335
+
},
10336
+
"engines": {
10337
+
"node": ">=8"
10338
+
}
10339
+
},
10340
+
"node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": {
10341
+
"version": "3.3.6",
10342
+
"inBundle": true,
10343
+
"license": "ISC",
10344
+
"dependencies": {
10345
+
"yallist": "^4.0.0"
10346
+
},
10347
+
"engines": {
10348
+
"node": ">=8"
10349
+
}
10350
+
},
10351
+
"node_modules/npm/node_modules/minipass-sized": {
10352
+
"version": "1.0.3",
10353
+
"inBundle": true,
10354
+
"license": "ISC",
10355
+
"dependencies": {
10356
+
"minipass": "^3.0.0"
10357
+
},
10358
+
"engines": {
10359
+
"node": ">=8"
10360
+
}
10361
+
},
10362
+
"node_modules/npm/node_modules/minipass-sized/node_modules/minipass": {
10363
+
"version": "3.3.6",
10364
+
"inBundle": true,
10365
+
"license": "ISC",
10366
+
"dependencies": {
10367
+
"yallist": "^4.0.0"
10368
+
},
10369
+
"engines": {
10370
+
"node": ">=8"
10371
+
}
10372
+
},
10373
+
"node_modules/npm/node_modules/minizlib": {
10374
+
"version": "3.1.0",
10375
+
"inBundle": true,
10376
+
"license": "MIT",
10377
+
"dependencies": {
10378
+
"minipass": "^7.1.2"
10379
+
},
10380
+
"engines": {
10381
+
"node": ">= 18"
10382
+
}
10383
+
},
10384
+
"node_modules/npm/node_modules/ms": {
10385
+
"version": "2.1.3",
10386
+
"inBundle": true,
10387
+
"license": "MIT"
10388
+
},
10389
+
"node_modules/npm/node_modules/mute-stream": {
10390
+
"version": "2.0.0",
10391
+
"inBundle": true,
10392
+
"license": "ISC",
10393
+
"engines": {
10394
+
"node": "^18.17.0 || >=20.5.0"
10395
+
}
10396
+
},
10397
+
"node_modules/npm/node_modules/negotiator": {
10398
+
"version": "1.0.0",
10399
+
"inBundle": true,
10400
+
"license": "MIT",
10401
+
"engines": {
10402
+
"node": ">= 0.6"
10403
+
}
10404
+
},
10405
+
"node_modules/npm/node_modules/node-gyp": {
10406
+
"version": "11.4.2",
10407
+
"inBundle": true,
10408
+
"license": "MIT",
10409
+
"dependencies": {
10410
+
"env-paths": "^2.2.0",
10411
+
"exponential-backoff": "^3.1.1",
10412
+
"graceful-fs": "^4.2.6",
10413
+
"make-fetch-happen": "^14.0.3",
10414
+
"nopt": "^8.0.0",
10415
+
"proc-log": "^5.0.0",
10416
+
"semver": "^7.3.5",
10417
+
"tar": "^7.4.3",
10418
+
"tinyglobby": "^0.2.12",
10419
+
"which": "^5.0.0"
10420
+
},
10421
+
"bin": {
10422
+
"node-gyp": "bin/node-gyp.js"
10423
+
},
10424
+
"engines": {
10425
+
"node": "^18.17.0 || >=20.5.0"
10426
+
}
10427
+
},
10428
+
"node_modules/npm/node_modules/node-gyp/node_modules/@npmcli/agent": {
10429
+
"version": "3.0.0",
10430
+
"inBundle": true,
10431
+
"license": "ISC",
10432
+
"dependencies": {
10433
+
"agent-base": "^7.1.0",
10434
+
"http-proxy-agent": "^7.0.0",
10435
+
"https-proxy-agent": "^7.0.1",
10436
+
"lru-cache": "^10.0.1",
10437
+
"socks-proxy-agent": "^8.0.3"
10438
+
},
10439
+
"engines": {
10440
+
"node": "^18.17.0 || >=20.5.0"
10441
+
}
10442
+
},
10443
+
"node_modules/npm/node_modules/node-gyp/node_modules/cacache": {
10444
+
"version": "19.0.1",
10445
+
"inBundle": true,
10446
+
"license": "ISC",
10447
+
"dependencies": {
10448
+
"@npmcli/fs": "^4.0.0",
10449
+
"fs-minipass": "^3.0.0",
10450
+
"glob": "^10.2.2",
10451
+
"lru-cache": "^10.0.1",
10452
+
"minipass": "^7.0.3",
10453
+
"minipass-collect": "^2.0.1",
10454
+
"minipass-flush": "^1.0.5",
10455
+
"minipass-pipeline": "^1.2.4",
10456
+
"p-map": "^7.0.2",
10457
+
"ssri": "^12.0.0",
10458
+
"tar": "^7.4.3",
10459
+
"unique-filename": "^4.0.0"
10460
+
},
10461
+
"engines": {
10462
+
"node": "^18.17.0 || >=20.5.0"
10463
+
}
10464
+
},
10465
+
"node_modules/npm/node_modules/node-gyp/node_modules/glob": {
10466
+
"version": "10.4.5",
10467
+
"inBundle": true,
10468
+
"license": "ISC",
10469
+
"dependencies": {
10470
+
"foreground-child": "^3.1.0",
10471
+
"jackspeak": "^3.1.2",
10472
+
"minimatch": "^9.0.4",
10473
+
"minipass": "^7.1.2",
10474
+
"package-json-from-dist": "^1.0.0",
10475
+
"path-scurry": "^1.11.1"
10476
+
},
10477
+
"bin": {
10478
+
"glob": "dist/esm/bin.mjs"
10479
+
},
10480
+
"funding": {
10481
+
"url": "https://github.com/sponsors/isaacs"
10482
+
}
10483
+
},
10484
+
"node_modules/npm/node_modules/node-gyp/node_modules/jackspeak": {
10485
+
"version": "3.4.3",
10486
+
"inBundle": true,
10487
+
"license": "BlueOak-1.0.0",
10488
+
"dependencies": {
10489
+
"@isaacs/cliui": "^8.0.2"
10490
+
},
10491
+
"funding": {
10492
+
"url": "https://github.com/sponsors/isaacs"
10493
+
},
10494
+
"optionalDependencies": {
10495
+
"@pkgjs/parseargs": "^0.11.0"
10496
+
}
10497
+
},
10498
+
"node_modules/npm/node_modules/node-gyp/node_modules/lru-cache": {
10499
+
"version": "10.4.3",
10500
+
"inBundle": true,
10501
+
"license": "ISC"
10502
+
},
10503
+
"node_modules/npm/node_modules/node-gyp/node_modules/make-fetch-happen": {
10504
+
"version": "14.0.3",
10505
+
"inBundle": true,
10506
+
"license": "ISC",
10507
+
"dependencies": {
10508
+
"@npmcli/agent": "^3.0.0",
10509
+
"cacache": "^19.0.1",
10510
+
"http-cache-semantics": "^4.1.1",
10511
+
"minipass": "^7.0.2",
10512
+
"minipass-fetch": "^4.0.0",
10513
+
"minipass-flush": "^1.0.5",
10514
+
"minipass-pipeline": "^1.2.4",
10515
+
"negotiator": "^1.0.0",
10516
+
"proc-log": "^5.0.0",
10517
+
"promise-retry": "^2.0.1",
10518
+
"ssri": "^12.0.0"
10519
+
},
10520
+
"engines": {
10521
+
"node": "^18.17.0 || >=20.5.0"
10522
+
}
10523
+
},
10524
+
"node_modules/npm/node_modules/node-gyp/node_modules/minimatch": {
10525
+
"version": "9.0.5",
10526
+
"inBundle": true,
10527
+
"license": "ISC",
10528
+
"dependencies": {
10529
+
"brace-expansion": "^2.0.1"
10530
+
},
10531
+
"engines": {
10532
+
"node": ">=16 || 14 >=14.17"
10533
+
},
10534
+
"funding": {
10535
+
"url": "https://github.com/sponsors/isaacs"
10536
+
}
10537
+
},
10538
+
"node_modules/npm/node_modules/node-gyp/node_modules/path-scurry": {
10539
+
"version": "1.11.1",
10540
+
"inBundle": true,
10541
+
"license": "BlueOak-1.0.0",
10542
+
"dependencies": {
10543
+
"lru-cache": "^10.2.0",
10544
+
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
10545
+
},
10546
+
"engines": {
10547
+
"node": ">=16 || 14 >=14.18"
10548
+
},
10549
+
"funding": {
10550
+
"url": "https://github.com/sponsors/isaacs"
10551
+
}
10552
+
},
10553
+
"node_modules/npm/node_modules/nopt": {
10554
+
"version": "8.1.0",
10555
+
"inBundle": true,
10556
+
"license": "ISC",
10557
+
"dependencies": {
10558
+
"abbrev": "^3.0.0"
10559
+
},
10560
+
"bin": {
10561
+
"nopt": "bin/nopt.js"
10562
+
},
10563
+
"engines": {
10564
+
"node": "^18.17.0 || >=20.5.0"
10565
+
}
10566
+
},
10567
+
"node_modules/npm/node_modules/npm-audit-report": {
10568
+
"version": "6.0.0",
10569
+
"inBundle": true,
10570
+
"license": "ISC",
10571
+
"engines": {
10572
+
"node": "^18.17.0 || >=20.5.0"
10573
+
}
10574
+
},
10575
+
"node_modules/npm/node_modules/npm-bundled": {
10576
+
"version": "4.0.0",
10577
+
"inBundle": true,
10578
+
"license": "ISC",
10579
+
"dependencies": {
10580
+
"npm-normalize-package-bin": "^4.0.0"
10581
+
},
10582
+
"engines": {
10583
+
"node": "^18.17.0 || >=20.5.0"
10584
+
}
10585
+
},
10586
+
"node_modules/npm/node_modules/npm-install-checks": {
10587
+
"version": "7.1.2",
10588
+
"inBundle": true,
10589
+
"license": "BSD-2-Clause",
10590
+
"dependencies": {
10591
+
"semver": "^7.1.1"
10592
+
},
10593
+
"engines": {
10594
+
"node": "^18.17.0 || >=20.5.0"
10595
+
}
10596
+
},
10597
+
"node_modules/npm/node_modules/npm-normalize-package-bin": {
10598
+
"version": "4.0.0",
10599
+
"inBundle": true,
10600
+
"license": "ISC",
10601
+
"engines": {
10602
+
"node": "^18.17.0 || >=20.5.0"
10603
+
}
10604
+
},
10605
+
"node_modules/npm/node_modules/npm-package-arg": {
10606
+
"version": "13.0.1",
10607
+
"inBundle": true,
10608
+
"license": "ISC",
10609
+
"dependencies": {
10610
+
"hosted-git-info": "^9.0.0",
10611
+
"proc-log": "^5.0.0",
10612
+
"semver": "^7.3.5",
10613
+
"validate-npm-package-name": "^6.0.0"
10614
+
},
10615
+
"engines": {
10616
+
"node": "^20.17.0 || >=22.9.0"
10617
+
}
10618
+
},
10619
+
"node_modules/npm/node_modules/npm-packlist": {
10620
+
"version": "10.0.2",
10621
+
"inBundle": true,
10622
+
"license": "ISC",
10623
+
"dependencies": {
10624
+
"ignore-walk": "^8.0.0",
10625
+
"proc-log": "^5.0.0"
10626
+
},
10627
+
"engines": {
10628
+
"node": "^20.17.0 || >=22.9.0"
10629
+
}
10630
+
},
10631
+
"node_modules/npm/node_modules/npm-pick-manifest": {
10632
+
"version": "11.0.1",
10633
+
"inBundle": true,
10634
+
"license": "ISC",
10635
+
"dependencies": {
10636
+
"npm-install-checks": "^7.1.0",
10637
+
"npm-normalize-package-bin": "^4.0.0",
10638
+
"npm-package-arg": "^13.0.0",
10639
+
"semver": "^7.3.5"
10640
+
},
10641
+
"engines": {
10642
+
"node": "^20.17.0 || >=22.9.0"
10643
+
}
10644
+
},
10645
+
"node_modules/npm/node_modules/npm-profile": {
10646
+
"version": "12.0.0",
10647
+
"inBundle": true,
10648
+
"license": "ISC",
10649
+
"dependencies": {
10650
+
"npm-registry-fetch": "^19.0.0",
10651
+
"proc-log": "^5.0.0"
10652
+
},
10653
+
"engines": {
10654
+
"node": "^20.17.0 || >=22.9.0"
10655
+
}
10656
+
},
10657
+
"node_modules/npm/node_modules/npm-registry-fetch": {
10658
+
"version": "19.0.0",
10659
+
"inBundle": true,
10660
+
"license": "ISC",
10661
+
"dependencies": {
10662
+
"@npmcli/redact": "^3.0.0",
10663
+
"jsonparse": "^1.3.1",
10664
+
"make-fetch-happen": "^15.0.0",
10665
+
"minipass": "^7.0.2",
10666
+
"minipass-fetch": "^4.0.0",
10667
+
"minizlib": "^3.0.1",
10668
+
"npm-package-arg": "^13.0.0",
10669
+
"proc-log": "^5.0.0"
10670
+
},
10671
+
"engines": {
10672
+
"node": "^20.17.0 || >=22.9.0"
10673
+
}
10674
+
},
10675
+
"node_modules/npm/node_modules/npm-user-validate": {
10676
+
"version": "3.0.0",
10677
+
"inBundle": true,
10678
+
"license": "BSD-2-Clause",
10679
+
"engines": {
10680
+
"node": "^18.17.0 || >=20.5.0"
10681
+
}
10682
+
},
10683
+
"node_modules/npm/node_modules/p-map": {
10684
+
"version": "7.0.3",
10685
+
"inBundle": true,
10686
+
"license": "MIT",
10687
+
"engines": {
10688
+
"node": ">=18"
10689
+
},
10690
+
"funding": {
10691
+
"url": "https://github.com/sponsors/sindresorhus"
10692
+
}
10693
+
},
10694
+
"node_modules/npm/node_modules/package-json-from-dist": {
10695
+
"version": "1.0.1",
10696
+
"inBundle": true,
10697
+
"license": "BlueOak-1.0.0"
10698
+
},
10699
+
"node_modules/npm/node_modules/pacote": {
10700
+
"version": "21.0.3",
10701
+
"inBundle": true,
10702
+
"license": "ISC",
10703
+
"dependencies": {
10704
+
"@npmcli/git": "^7.0.0",
10705
+
"@npmcli/installed-package-contents": "^3.0.0",
10706
+
"@npmcli/package-json": "^7.0.0",
10707
+
"@npmcli/promise-spawn": "^8.0.0",
10708
+
"@npmcli/run-script": "^10.0.0",
10709
+
"cacache": "^20.0.0",
10710
+
"fs-minipass": "^3.0.0",
10711
+
"minipass": "^7.0.2",
10712
+
"npm-package-arg": "^13.0.0",
10713
+
"npm-packlist": "^10.0.1",
10714
+
"npm-pick-manifest": "^11.0.1",
10715
+
"npm-registry-fetch": "^19.0.0",
10716
+
"proc-log": "^5.0.0",
10717
+
"promise-retry": "^2.0.1",
10718
+
"sigstore": "^4.0.0",
10719
+
"ssri": "^12.0.0",
10720
+
"tar": "^7.4.3"
10721
+
},
10722
+
"bin": {
10723
+
"pacote": "bin/index.js"
10724
+
},
10725
+
"engines": {
10726
+
"node": "^20.17.0 || >=22.9.0"
10727
+
}
10728
+
},
10729
+
"node_modules/npm/node_modules/parse-conflict-json": {
10730
+
"version": "4.0.0",
10731
+
"inBundle": true,
10732
+
"license": "ISC",
10733
+
"dependencies": {
10734
+
"json-parse-even-better-errors": "^4.0.0",
10735
+
"just-diff": "^6.0.0",
10736
+
"just-diff-apply": "^5.2.0"
10737
+
},
10738
+
"engines": {
10739
+
"node": "^18.17.0 || >=20.5.0"
10740
+
}
10741
+
},
10742
+
"node_modules/npm/node_modules/path-key": {
10743
+
"version": "3.1.1",
10744
+
"inBundle": true,
10745
+
"license": "MIT",
10746
+
"engines": {
10747
+
"node": ">=8"
10748
+
}
10749
+
},
10750
+
"node_modules/npm/node_modules/path-scurry": {
10751
+
"version": "2.0.0",
10752
+
"inBundle": true,
10753
+
"license": "BlueOak-1.0.0",
10754
+
"dependencies": {
10755
+
"lru-cache": "^11.0.0",
10756
+
"minipass": "^7.1.2"
10757
+
},
10758
+
"engines": {
10759
+
"node": "20 || >=22"
10760
+
},
10761
+
"funding": {
10762
+
"url": "https://github.com/sponsors/isaacs"
10763
+
}
10764
+
},
10765
+
"node_modules/npm/node_modules/postcss-selector-parser": {
10766
+
"version": "7.1.0",
10767
+
"inBundle": true,
10768
+
"license": "MIT",
10769
+
"dependencies": {
10770
+
"cssesc": "^3.0.0",
10771
+
"util-deprecate": "^1.0.2"
10772
+
},
10773
+
"engines": {
10774
+
"node": ">=4"
10775
+
}
10776
+
},
10777
+
"node_modules/npm/node_modules/proc-log": {
10778
+
"version": "5.0.0",
10779
+
"inBundle": true,
10780
+
"license": "ISC",
10781
+
"engines": {
10782
+
"node": "^18.17.0 || >=20.5.0"
10783
+
}
10784
+
},
10785
+
"node_modules/npm/node_modules/proggy": {
10786
+
"version": "3.0.0",
10787
+
"inBundle": true,
10788
+
"license": "ISC",
10789
+
"engines": {
10790
+
"node": "^18.17.0 || >=20.5.0"
10791
+
}
10792
+
},
10793
+
"node_modules/npm/node_modules/promise-all-reject-late": {
10794
+
"version": "1.0.1",
10795
+
"inBundle": true,
10796
+
"license": "ISC",
10797
+
"funding": {
10798
+
"url": "https://github.com/sponsors/isaacs"
10799
+
}
10800
+
},
10801
+
"node_modules/npm/node_modules/promise-call-limit": {
10802
+
"version": "3.0.2",
10803
+
"inBundle": true,
10804
+
"license": "ISC",
10805
+
"funding": {
10806
+
"url": "https://github.com/sponsors/isaacs"
10807
+
}
10808
+
},
10809
+
"node_modules/npm/node_modules/promise-retry": {
10810
+
"version": "2.0.1",
10811
+
"inBundle": true,
10812
+
"license": "MIT",
10813
+
"dependencies": {
10814
+
"err-code": "^2.0.2",
10815
+
"retry": "^0.12.0"
10816
+
},
10817
+
"engines": {
10818
+
"node": ">=10"
10819
+
}
10820
+
},
10821
+
"node_modules/npm/node_modules/promzard": {
10822
+
"version": "2.0.0",
10823
+
"inBundle": true,
10824
+
"license": "ISC",
10825
+
"dependencies": {
10826
+
"read": "^4.0.0"
10827
+
},
10828
+
"engines": {
10829
+
"node": "^18.17.0 || >=20.5.0"
10830
+
}
10831
+
},
10832
+
"node_modules/npm/node_modules/qrcode-terminal": {
10833
+
"version": "0.12.0",
10834
+
"inBundle": true,
10835
+
"bin": {
10836
+
"qrcode-terminal": "bin/qrcode-terminal.js"
10837
+
}
10838
+
},
10839
+
"node_modules/npm/node_modules/read": {
10840
+
"version": "4.1.0",
10841
+
"inBundle": true,
10842
+
"license": "ISC",
10843
+
"dependencies": {
10844
+
"mute-stream": "^2.0.0"
10845
+
},
10846
+
"engines": {
10847
+
"node": "^18.17.0 || >=20.5.0"
10848
+
}
10849
+
},
10850
+
"node_modules/npm/node_modules/read-cmd-shim": {
10851
+
"version": "5.0.0",
10852
+
"inBundle": true,
10853
+
"license": "ISC",
10854
+
"engines": {
10855
+
"node": "^18.17.0 || >=20.5.0"
10856
+
}
10857
+
},
10858
+
"node_modules/npm/node_modules/retry": {
10859
+
"version": "0.12.0",
10860
+
"inBundle": true,
10861
+
"license": "MIT",
10862
+
"engines": {
10863
+
"node": ">= 4"
10864
+
}
10865
+
},
10866
+
"node_modules/npm/node_modules/safer-buffer": {
10867
+
"version": "2.1.2",
10868
+
"inBundle": true,
10869
+
"license": "MIT",
10870
+
"optional": true
10871
+
},
10872
+
"node_modules/npm/node_modules/semver": {
10873
+
"version": "7.7.3",
10874
+
"inBundle": true,
10875
+
"license": "ISC",
10876
+
"bin": {
10877
+
"semver": "bin/semver.js"
10878
+
},
10879
+
"engines": {
10880
+
"node": ">=10"
10881
+
}
10882
+
},
10883
+
"node_modules/npm/node_modules/shebang-command": {
10884
+
"version": "2.0.0",
10885
+
"inBundle": true,
10886
+
"license": "MIT",
10887
+
"dependencies": {
10888
+
"shebang-regex": "^3.0.0"
10889
+
},
10890
+
"engines": {
10891
+
"node": ">=8"
10892
+
}
10893
+
},
10894
+
"node_modules/npm/node_modules/shebang-regex": {
10895
+
"version": "3.0.0",
10896
+
"inBundle": true,
10897
+
"license": "MIT",
10898
+
"engines": {
10899
+
"node": ">=8"
10900
+
}
10901
+
},
10902
+
"node_modules/npm/node_modules/signal-exit": {
10903
+
"version": "4.1.0",
10904
+
"inBundle": true,
10905
+
"license": "ISC",
10906
+
"engines": {
10907
+
"node": ">=14"
10908
+
},
10909
+
"funding": {
10910
+
"url": "https://github.com/sponsors/isaacs"
10911
+
}
10912
+
},
10913
+
"node_modules/npm/node_modules/sigstore": {
10914
+
"version": "4.0.0",
10915
+
"inBundle": true,
10916
+
"license": "Apache-2.0",
10917
+
"dependencies": {
10918
+
"@sigstore/bundle": "^4.0.0",
10919
+
"@sigstore/core": "^3.0.0",
10920
+
"@sigstore/protobuf-specs": "^0.5.0",
10921
+
"@sigstore/sign": "^4.0.0",
10922
+
"@sigstore/tuf": "^4.0.0",
10923
+
"@sigstore/verify": "^3.0.0"
10924
+
},
10925
+
"engines": {
10926
+
"node": "^20.17.0 || >=22.9.0"
10927
+
}
10928
+
},
10929
+
"node_modules/npm/node_modules/smart-buffer": {
10930
+
"version": "4.2.0",
10931
+
"inBundle": true,
10932
+
"license": "MIT",
10933
+
"engines": {
10934
+
"node": ">= 6.0.0",
10935
+
"npm": ">= 3.0.0"
10936
+
}
10937
+
},
10938
+
"node_modules/npm/node_modules/socks": {
10939
+
"version": "2.8.7",
10940
+
"inBundle": true,
10941
+
"license": "MIT",
10942
+
"dependencies": {
10943
+
"ip-address": "^10.0.1",
10944
+
"smart-buffer": "^4.2.0"
10945
+
},
10946
+
"engines": {
10947
+
"node": ">= 10.0.0",
10948
+
"npm": ">= 3.0.0"
10949
+
}
10950
+
},
10951
+
"node_modules/npm/node_modules/socks-proxy-agent": {
10952
+
"version": "8.0.5",
10953
+
"inBundle": true,
10954
+
"license": "MIT",
10955
+
"dependencies": {
10956
+
"agent-base": "^7.1.2",
10957
+
"debug": "^4.3.4",
10958
+
"socks": "^2.8.3"
10959
+
},
10960
+
"engines": {
10961
+
"node": ">= 14"
10962
+
}
10963
+
},
10964
+
"node_modules/npm/node_modules/spdx-correct": {
10965
+
"version": "3.2.0",
10966
+
"inBundle": true,
10967
+
"license": "Apache-2.0",
10968
+
"dependencies": {
10969
+
"spdx-expression-parse": "^3.0.0",
10970
+
"spdx-license-ids": "^3.0.0"
10971
+
}
10972
+
},
10973
+
"node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": {
10974
+
"version": "3.0.1",
10975
+
"inBundle": true,
10976
+
"license": "MIT",
10977
+
"dependencies": {
10978
+
"spdx-exceptions": "^2.1.0",
10979
+
"spdx-license-ids": "^3.0.0"
10980
+
}
10981
+
},
10982
+
"node_modules/npm/node_modules/spdx-exceptions": {
10983
+
"version": "2.5.0",
10984
+
"inBundle": true,
10985
+
"license": "CC-BY-3.0"
10986
+
},
10987
+
"node_modules/npm/node_modules/spdx-expression-parse": {
10988
+
"version": "4.0.0",
10989
+
"inBundle": true,
10990
+
"license": "MIT",
10991
+
"dependencies": {
10992
+
"spdx-exceptions": "^2.1.0",
10993
+
"spdx-license-ids": "^3.0.0"
10994
+
}
10995
+
},
10996
+
"node_modules/npm/node_modules/spdx-license-ids": {
10997
+
"version": "3.0.22",
10998
+
"inBundle": true,
10999
+
"license": "CC0-1.0"
11000
+
},
11001
+
"node_modules/npm/node_modules/ssri": {
11002
+
"version": "12.0.0",
11003
+
"inBundle": true,
11004
+
"license": "ISC",
11005
+
"dependencies": {
11006
+
"minipass": "^7.0.3"
11007
+
},
11008
+
"engines": {
11009
+
"node": "^18.17.0 || >=20.5.0"
11010
+
}
11011
+
},
11012
+
"node_modules/npm/node_modules/string-width": {
11013
+
"version": "4.2.3",
11014
+
"inBundle": true,
11015
+
"license": "MIT",
11016
+
"dependencies": {
11017
+
"emoji-regex": "^8.0.0",
11018
+
"is-fullwidth-code-point": "^3.0.0",
11019
+
"strip-ansi": "^6.0.1"
11020
+
},
11021
+
"engines": {
11022
+
"node": ">=8"
11023
+
}
11024
+
},
11025
+
"node_modules/npm/node_modules/string-width-cjs": {
11026
+
"name": "string-width",
11027
+
"version": "4.2.3",
11028
+
"inBundle": true,
11029
+
"license": "MIT",
11030
+
"dependencies": {
11031
+
"emoji-regex": "^8.0.0",
11032
+
"is-fullwidth-code-point": "^3.0.0",
11033
+
"strip-ansi": "^6.0.1"
11034
+
},
11035
+
"engines": {
11036
+
"node": ">=8"
11037
+
}
11038
+
},
11039
+
"node_modules/npm/node_modules/strip-ansi": {
11040
+
"version": "6.0.1",
11041
+
"inBundle": true,
11042
+
"license": "MIT",
11043
+
"dependencies": {
11044
+
"ansi-regex": "^5.0.1"
11045
+
},
11046
+
"engines": {
11047
+
"node": ">=8"
11048
+
}
11049
+
},
11050
+
"node_modules/npm/node_modules/strip-ansi-cjs": {
11051
+
"name": "strip-ansi",
11052
+
"version": "6.0.1",
11053
+
"inBundle": true,
11054
+
"license": "MIT",
11055
+
"dependencies": {
11056
+
"ansi-regex": "^5.0.1"
11057
+
},
11058
+
"engines": {
11059
+
"node": ">=8"
11060
+
}
11061
+
},
11062
+
"node_modules/npm/node_modules/supports-color": {
11063
+
"version": "10.2.2",
11064
+
"inBundle": true,
11065
+
"license": "MIT",
11066
+
"engines": {
11067
+
"node": ">=18"
11068
+
},
11069
+
"funding": {
11070
+
"url": "https://github.com/chalk/supports-color?sponsor=1"
11071
+
}
11072
+
},
11073
+
"node_modules/npm/node_modules/tar": {
11074
+
"version": "7.5.1",
11075
+
"inBundle": true,
11076
+
"license": "ISC",
11077
+
"dependencies": {
11078
+
"@isaacs/fs-minipass": "^4.0.0",
11079
+
"chownr": "^3.0.0",
11080
+
"minipass": "^7.1.2",
11081
+
"minizlib": "^3.1.0",
11082
+
"yallist": "^5.0.0"
11083
+
},
11084
+
"engines": {
11085
+
"node": ">=18"
11086
+
}
11087
+
},
11088
+
"node_modules/npm/node_modules/tar/node_modules/yallist": {
11089
+
"version": "5.0.0",
11090
+
"inBundle": true,
11091
+
"license": "BlueOak-1.0.0",
11092
+
"engines": {
11093
+
"node": ">=18"
11094
+
}
11095
+
},
11096
+
"node_modules/npm/node_modules/text-table": {
11097
+
"version": "0.2.0",
11098
+
"inBundle": true,
11099
+
"license": "MIT"
11100
+
},
11101
+
"node_modules/npm/node_modules/tiny-relative-date": {
11102
+
"version": "2.0.2",
11103
+
"inBundle": true,
11104
+
"license": "MIT"
11105
+
},
11106
+
"node_modules/npm/node_modules/tinyglobby": {
11107
+
"version": "0.2.15",
11108
+
"inBundle": true,
11109
+
"license": "MIT",
11110
+
"dependencies": {
11111
+
"fdir": "^6.5.0",
11112
+
"picomatch": "^4.0.3"
11113
+
},
11114
+
"engines": {
11115
+
"node": ">=12.0.0"
11116
+
},
11117
+
"funding": {
11118
+
"url": "https://github.com/sponsors/SuperchupuDev"
11119
+
}
11120
+
},
11121
+
"node_modules/npm/node_modules/tinyglobby/node_modules/fdir": {
11122
+
"version": "6.5.0",
11123
+
"inBundle": true,
11124
+
"license": "MIT",
11125
+
"engines": {
11126
+
"node": ">=12.0.0"
11127
+
},
11128
+
"peerDependencies": {
11129
+
"picomatch": "^3 || ^4"
11130
+
},
11131
+
"peerDependenciesMeta": {
11132
+
"picomatch": {
11133
+
"optional": true
11134
+
}
11135
+
}
11136
+
},
11137
+
"node_modules/npm/node_modules/tinyglobby/node_modules/picomatch": {
11138
+
"version": "4.0.3",
11139
+
"inBundle": true,
11140
+
"license": "MIT",
11141
+
"engines": {
11142
+
"node": ">=12"
11143
+
},
11144
+
"funding": {
11145
+
"url": "https://github.com/sponsors/jonschlinkert"
11146
+
}
11147
+
},
11148
+
"node_modules/npm/node_modules/treeverse": {
11149
+
"version": "3.0.0",
11150
+
"inBundle": true,
11151
+
"license": "ISC",
11152
+
"engines": {
11153
+
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
11154
+
}
11155
+
},
11156
+
"node_modules/npm/node_modules/tuf-js": {
11157
+
"version": "4.0.0",
11158
+
"inBundle": true,
11159
+
"license": "MIT",
11160
+
"dependencies": {
11161
+
"@tufjs/models": "4.0.0",
11162
+
"debug": "^4.4.1",
11163
+
"make-fetch-happen": "^15.0.0"
11164
+
},
11165
+
"engines": {
11166
+
"node": "^20.17.0 || >=22.9.0"
11167
+
}
11168
+
},
11169
+
"node_modules/npm/node_modules/unique-filename": {
11170
+
"version": "4.0.0",
11171
+
"inBundle": true,
11172
+
"license": "ISC",
11173
+
"dependencies": {
11174
+
"unique-slug": "^5.0.0"
11175
+
},
11176
+
"engines": {
11177
+
"node": "^18.17.0 || >=20.5.0"
11178
+
}
11179
+
},
11180
+
"node_modules/npm/node_modules/unique-slug": {
11181
+
"version": "5.0.0",
11182
+
"inBundle": true,
11183
+
"license": "ISC",
11184
+
"dependencies": {
11185
+
"imurmurhash": "^0.1.4"
11186
+
},
11187
+
"engines": {
11188
+
"node": "^18.17.0 || >=20.5.0"
11189
+
}
11190
+
},
11191
+
"node_modules/npm/node_modules/util-deprecate": {
11192
+
"version": "1.0.2",
11193
+
"inBundle": true,
11194
+
"license": "MIT"
11195
+
},
11196
+
"node_modules/npm/node_modules/validate-npm-package-license": {
11197
+
"version": "3.0.4",
11198
+
"inBundle": true,
11199
+
"license": "Apache-2.0",
11200
+
"dependencies": {
11201
+
"spdx-correct": "^3.0.0",
11202
+
"spdx-expression-parse": "^3.0.0"
11203
+
}
11204
+
},
11205
+
"node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": {
11206
+
"version": "3.0.1",
11207
+
"inBundle": true,
11208
+
"license": "MIT",
11209
+
"dependencies": {
11210
+
"spdx-exceptions": "^2.1.0",
11211
+
"spdx-license-ids": "^3.0.0"
11212
+
}
11213
+
},
11214
+
"node_modules/npm/node_modules/validate-npm-package-name": {
11215
+
"version": "6.0.2",
11216
+
"inBundle": true,
11217
+
"license": "ISC",
11218
+
"engines": {
11219
+
"node": "^18.17.0 || >=20.5.0"
11220
+
}
11221
+
},
11222
+
"node_modules/npm/node_modules/walk-up-path": {
11223
+
"version": "4.0.0",
11224
+
"inBundle": true,
11225
+
"license": "ISC",
11226
+
"engines": {
11227
+
"node": "20 || >=22"
11228
+
}
11229
+
},
11230
+
"node_modules/npm/node_modules/which": {
11231
+
"version": "5.0.0",
11232
+
"inBundle": true,
11233
+
"license": "ISC",
11234
+
"dependencies": {
11235
+
"isexe": "^3.1.1"
11236
+
},
11237
+
"bin": {
11238
+
"node-which": "bin/which.js"
11239
+
},
11240
+
"engines": {
11241
+
"node": "^18.17.0 || >=20.5.0"
11242
+
}
11243
+
},
11244
+
"node_modules/npm/node_modules/wrap-ansi": {
11245
+
"version": "8.1.0",
11246
+
"inBundle": true,
11247
+
"license": "MIT",
11248
+
"dependencies": {
11249
+
"ansi-styles": "^6.1.0",
11250
+
"string-width": "^5.0.1",
11251
+
"strip-ansi": "^7.0.1"
11252
+
},
11253
+
"engines": {
11254
+
"node": ">=12"
11255
+
},
11256
+
"funding": {
11257
+
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
11258
+
}
11259
+
},
11260
+
"node_modules/npm/node_modules/wrap-ansi-cjs": {
11261
+
"name": "wrap-ansi",
11262
+
"version": "7.0.0",
11263
+
"inBundle": true,
11264
+
"license": "MIT",
11265
+
"dependencies": {
11266
+
"ansi-styles": "^4.0.0",
11267
+
"string-width": "^4.1.0",
11268
+
"strip-ansi": "^6.0.0"
11269
+
},
11270
+
"engines": {
11271
+
"node": ">=10"
11272
+
},
11273
+
"funding": {
11274
+
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
11275
+
}
11276
+
},
11277
+
"node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
11278
+
"version": "4.3.0",
11279
+
"inBundle": true,
11280
+
"license": "MIT",
11281
+
"dependencies": {
11282
+
"color-convert": "^2.0.1"
11283
+
},
11284
+
"engines": {
11285
+
"node": ">=8"
11286
+
},
11287
+
"funding": {
11288
+
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
11289
+
}
11290
+
},
11291
+
"node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": {
11292
+
"version": "6.2.2",
11293
+
"inBundle": true,
11294
+
"license": "MIT",
11295
+
"engines": {
11296
+
"node": ">=12"
11297
+
},
11298
+
"funding": {
11299
+
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
11300
+
}
11301
+
},
11302
+
"node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": {
11303
+
"version": "9.2.2",
11304
+
"inBundle": true,
11305
+
"license": "MIT"
11306
+
},
11307
+
"node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": {
11308
+
"version": "5.1.2",
11309
+
"inBundle": true,
11310
+
"license": "MIT",
11311
+
"dependencies": {
11312
+
"eastasianwidth": "^0.2.0",
11313
+
"emoji-regex": "^9.2.2",
11314
+
"strip-ansi": "^7.0.1"
11315
+
},
11316
+
"engines": {
11317
+
"node": ">=12"
11318
+
},
11319
+
"funding": {
11320
+
"url": "https://github.com/sponsors/sindresorhus"
11321
+
}
11322
+
},
11323
+
"node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": {
11324
+
"version": "7.1.2",
11325
+
"inBundle": true,
11326
+
"license": "MIT",
11327
+
"dependencies": {
11328
+
"ansi-regex": "^6.0.1"
11329
+
},
11330
+
"engines": {
11331
+
"node": ">=12"
11332
+
},
11333
+
"funding": {
11334
+
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
11335
+
}
11336
+
},
11337
+
"node_modules/npm/node_modules/write-file-atomic": {
11338
+
"version": "6.0.0",
11339
+
"inBundle": true,
11340
+
"license": "ISC",
11341
+
"dependencies": {
11342
+
"imurmurhash": "^0.1.4",
11343
+
"signal-exit": "^4.0.1"
11344
+
},
11345
+
"engines": {
11346
+
"node": "^18.17.0 || >=20.5.0"
11347
+
}
11348
+
},
11349
+
"node_modules/npm/node_modules/yallist": {
11350
+
"version": "4.0.0",
11351
+
"inBundle": true,
11352
+
"license": "ISC"
11353
+
},
11354
"node_modules/nwsapi": {
11355
"version": "2.2.21",
11356
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.21.tgz",
···
11367
"node": ">=0.10.0"
11368
}
11369
},
11370
+
"node_modules/object-inspect": {
11371
+
"version": "1.13.4",
11372
+
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
11373
+
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
11374
+
"dev": true,
11375
+
"license": "MIT",
11376
+
"engines": {
11377
+
"node": ">= 0.4"
11378
+
},
11379
+
"funding": {
11380
+
"url": "https://github.com/sponsors/ljharb"
11381
+
}
11382
+
},
11383
+
"node_modules/object-keys": {
11384
+
"version": "1.1.1",
11385
+
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
11386
+
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
11387
+
"dev": true,
11388
+
"license": "MIT",
11389
+
"engines": {
11390
+
"node": ">= 0.4"
11391
+
}
11392
+
},
11393
+
"node_modules/object.assign": {
11394
+
"version": "4.1.7",
11395
+
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
11396
+
"integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
11397
+
"dev": true,
11398
+
"license": "MIT",
11399
+
"dependencies": {
11400
+
"call-bind": "^1.0.8",
11401
+
"call-bound": "^1.0.3",
11402
+
"define-properties": "^1.2.1",
11403
+
"es-object-atoms": "^1.0.0",
11404
+
"has-symbols": "^1.1.0",
11405
+
"object-keys": "^1.1.1"
11406
+
},
11407
+
"engines": {
11408
+
"node": ">= 0.4"
11409
+
},
11410
+
"funding": {
11411
+
"url": "https://github.com/sponsors/ljharb"
11412
+
}
11413
+
},
11414
+
"node_modules/object.entries": {
11415
+
"version": "1.1.9",
11416
+
"resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
11417
+
"integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
11418
+
"dev": true,
11419
+
"license": "MIT",
11420
+
"dependencies": {
11421
+
"call-bind": "^1.0.8",
11422
+
"call-bound": "^1.0.4",
11423
+
"define-properties": "^1.2.1",
11424
+
"es-object-atoms": "^1.1.1"
11425
+
},
11426
+
"engines": {
11427
+
"node": ">= 0.4"
11428
+
}
11429
+
},
11430
+
"node_modules/object.fromentries": {
11431
+
"version": "2.0.8",
11432
+
"resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
11433
+
"integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
11434
+
"dev": true,
11435
+
"license": "MIT",
11436
+
"dependencies": {
11437
+
"call-bind": "^1.0.7",
11438
+
"define-properties": "^1.2.1",
11439
+
"es-abstract": "^1.23.2",
11440
+
"es-object-atoms": "^1.0.0"
11441
+
},
11442
+
"engines": {
11443
+
"node": ">= 0.4"
11444
+
},
11445
+
"funding": {
11446
+
"url": "https://github.com/sponsors/ljharb"
11447
+
}
11448
+
},
11449
+
"node_modules/object.values": {
11450
+
"version": "1.2.1",
11451
+
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
11452
+
"integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
11453
+
"dev": true,
11454
+
"license": "MIT",
11455
+
"dependencies": {
11456
+
"call-bind": "^1.0.8",
11457
+
"call-bound": "^1.0.3",
11458
+
"define-properties": "^1.2.1",
11459
+
"es-object-atoms": "^1.0.0"
11460
+
},
11461
+
"engines": {
11462
+
"node": ">= 0.4"
11463
+
},
11464
+
"funding": {
11465
+
"url": "https://github.com/sponsors/ljharb"
11466
+
}
11467
+
},
11468
+
"node_modules/optionator": {
11469
+
"version": "0.9.4",
11470
+
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
11471
+
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
11472
+
"dev": true,
11473
+
"license": "MIT",
11474
+
"peer": true,
11475
+
"dependencies": {
11476
+
"deep-is": "^0.1.3",
11477
+
"fast-levenshtein": "^2.0.6",
11478
+
"levn": "^0.4.1",
11479
+
"prelude-ls": "^1.2.1",
11480
+
"type-check": "^0.4.0",
11481
+
"word-wrap": "^1.2.5"
11482
+
},
11483
+
"engines": {
11484
+
"node": ">= 0.8.0"
11485
+
}
11486
+
},
11487
+
"node_modules/own-keys": {
11488
+
"version": "1.0.1",
11489
+
"resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
11490
+
"integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
11491
+
"dev": true,
11492
+
"license": "MIT",
11493
+
"dependencies": {
11494
+
"get-intrinsic": "^1.2.6",
11495
+
"object-keys": "^1.1.1",
11496
+
"safe-push-apply": "^1.0.0"
11497
+
},
11498
+
"engines": {
11499
+
"node": ">= 0.4"
11500
+
},
11501
+
"funding": {
11502
+
"url": "https://github.com/sponsors/ljharb"
11503
+
}
11504
+
},
11505
+
"node_modules/p-limit": {
11506
+
"version": "3.1.0",
11507
+
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
11508
+
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
11509
+
"dev": true,
11510
+
"license": "MIT",
11511
+
"peer": true,
11512
+
"dependencies": {
11513
+
"yocto-queue": "^0.1.0"
11514
+
},
11515
+
"engines": {
11516
+
"node": ">=10"
11517
+
},
11518
+
"funding": {
11519
+
"url": "https://github.com/sponsors/sindresorhus"
11520
+
}
11521
+
},
11522
+
"node_modules/p-locate": {
11523
+
"version": "5.0.0",
11524
+
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
11525
+
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
11526
+
"dev": true,
11527
+
"license": "MIT",
11528
+
"peer": true,
11529
+
"dependencies": {
11530
+
"p-limit": "^3.0.2"
11531
+
},
11532
+
"engines": {
11533
+
"node": ">=10"
11534
+
},
11535
+
"funding": {
11536
+
"url": "https://github.com/sponsors/sindresorhus"
11537
+
}
11538
+
},
11539
+
"node_modules/package-manager-detector": {
11540
+
"version": "1.4.1",
11541
+
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.4.1.tgz",
11542
+
"integrity": "sha512-dSMiVLBEA4XaNJ0PRb4N5cV/SEP4BWrWZKBmfF+OUm2pQTiZ6DDkKeWaltwu3JRhLoy59ayIkJ00cx9K9CaYTg==",
11543
+
"dev": true,
11544
+
"license": "MIT"
11545
+
},
11546
+
"node_modules/parent-module": {
11547
+
"version": "1.0.1",
11548
+
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
11549
+
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
11550
+
"dev": true,
11551
+
"license": "MIT",
11552
+
"dependencies": {
11553
+
"callsites": "^3.0.0"
11554
+
},
11555
+
"engines": {
11556
+
"node": ">=6"
11557
+
}
11558
+
},
11559
+
"node_modules/parse-json": {
11560
+
"version": "5.2.0",
11561
+
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
11562
+
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
11563
+
"dev": true,
11564
+
"license": "MIT",
11565
+
"dependencies": {
11566
+
"@babel/code-frame": "^7.0.0",
11567
+
"error-ex": "^1.3.1",
11568
+
"json-parse-even-better-errors": "^2.3.0",
11569
+
"lines-and-columns": "^1.1.6"
11570
+
},
11571
+
"engines": {
11572
+
"node": ">=8"
11573
+
},
11574
+
"funding": {
11575
+
"url": "https://github.com/sponsors/sindresorhus"
11576
+
}
11577
+
},
11578
"node_modules/parse5": {
11579
"version": "7.3.0",
11580
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
···
11594
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
11595
"license": "MIT"
11596
},
11597
+
"node_modules/path-exists": {
11598
+
"version": "4.0.0",
11599
+
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
11600
+
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
11601
+
"dev": true,
11602
+
"license": "MIT",
11603
+
"peer": true,
11604
+
"engines": {
11605
+
"node": ">=8"
11606
+
}
11607
+
},
11608
+
"node_modules/path-key": {
11609
+
"version": "3.1.1",
11610
+
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
11611
+
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
11612
+
"dev": true,
11613
+
"license": "MIT",
11614
+
"peer": true,
11615
+
"engines": {
11616
+
"node": ">=8"
11617
+
}
11618
+
},
11619
+
"node_modules/path-parse": {
11620
+
"version": "1.0.7",
11621
+
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
11622
+
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
11623
+
"dev": true,
11624
+
"license": "MIT"
11625
+
},
11626
+
"node_modules/path-type": {
11627
+
"version": "4.0.0",
11628
+
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
11629
+
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
11630
+
"dev": true,
11631
+
"license": "MIT",
11632
+
"engines": {
11633
+
"node": ">=8"
11634
+
}
11635
+
},
11636
"node_modules/pathe": {
11637
"version": "2.0.3",
11638
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
···
11668
"url": "https://github.com/sponsors/jonschlinkert"
11669
}
11670
},
11671
+
"node_modules/pkg-types": {
11672
+
"version": "2.3.0",
11673
+
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz",
11674
+
"integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==",
11675
+
"dev": true,
11676
+
"license": "MIT",
11677
+
"dependencies": {
11678
+
"confbox": "^0.2.2",
11679
+
"exsolve": "^1.0.7",
11680
+
"pathe": "^2.0.3"
11681
+
}
11682
+
},
11683
"node_modules/player.style": {
11684
"version": "0.1.10",
11685
"resolved": "https://registry.npmjs.org/player.style/-/player.style-0.1.10.tgz",
···
11696
"media-chrome": "~4.11.0"
11697
}
11698
},
11699
+
"node_modules/possible-typed-array-names": {
11700
+
"version": "1.1.0",
11701
+
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
11702
+
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
11703
+
"dev": true,
11704
+
"license": "MIT",
11705
+
"engines": {
11706
+
"node": ">= 0.4"
11707
+
}
11708
+
},
11709
"node_modules/postcss": {
11710
"version": "8.5.6",
11711
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
···
11734
"node": "^10 || ^12 || >=14"
11735
}
11736
},
11737
+
"node_modules/prelude-ls": {
11738
+
"version": "1.2.1",
11739
+
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
11740
+
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
11741
+
"dev": true,
11742
+
"license": "MIT",
11743
+
"peer": true,
11744
+
"engines": {
11745
+
"node": ">= 0.8.0"
11746
+
}
11747
+
},
11748
"node_modules/prettier": {
11749
"version": "3.6.2",
11750
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
···
11802
"node": ">=6"
11803
}
11804
},
11805
+
"node_modules/quansync": {
11806
+
"version": "0.2.11",
11807
+
"resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
11808
+
"integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==",
11809
+
"dev": true,
11810
+
"funding": [
11811
+
{
11812
+
"type": "individual",
11813
+
"url": "https://github.com/sponsors/antfu"
11814
+
},
11815
+
{
11816
+
"type": "individual",
11817
+
"url": "https://github.com/sponsors/sxzz"
11818
+
}
11819
+
],
11820
+
"license": "MIT"
11821
+
},
11822
+
"node_modules/queue-microtask": {
11823
+
"version": "1.2.3",
11824
+
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
11825
+
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
11826
+
"dev": true,
11827
+
"funding": [
11828
+
{
11829
+
"type": "github",
11830
+
"url": "https://github.com/sponsors/feross"
11831
+
},
11832
+
{
11833
+
"type": "patreon",
11834
+
"url": "https://www.patreon.com/feross"
11835
+
},
11836
+
{
11837
+
"type": "consulting",
11838
+
"url": "https://feross.org/support"
11839
+
}
11840
+
],
11841
+
"license": "MIT"
11842
+
},
11843
+
"node_modules/radix-ui": {
11844
+
"version": "1.4.3",
11845
+
"resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.4.3.tgz",
11846
+
"integrity": "sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA==",
11847
+
"dependencies": {
11848
+
"@radix-ui/primitive": "1.1.3",
11849
+
"@radix-ui/react-accessible-icon": "1.1.7",
11850
+
"@radix-ui/react-accordion": "1.2.12",
11851
+
"@radix-ui/react-alert-dialog": "1.1.15",
11852
+
"@radix-ui/react-arrow": "1.1.7",
11853
+
"@radix-ui/react-aspect-ratio": "1.1.7",
11854
+
"@radix-ui/react-avatar": "1.1.10",
11855
+
"@radix-ui/react-checkbox": "1.3.3",
11856
+
"@radix-ui/react-collapsible": "1.1.12",
11857
+
"@radix-ui/react-collection": "1.1.7",
11858
+
"@radix-ui/react-compose-refs": "1.1.2",
11859
+
"@radix-ui/react-context": "1.1.2",
11860
+
"@radix-ui/react-context-menu": "2.2.16",
11861
+
"@radix-ui/react-dialog": "1.1.15",
11862
+
"@radix-ui/react-direction": "1.1.1",
11863
+
"@radix-ui/react-dismissable-layer": "1.1.11",
11864
+
"@radix-ui/react-dropdown-menu": "2.1.16",
11865
+
"@radix-ui/react-focus-guards": "1.1.3",
11866
+
"@radix-ui/react-focus-scope": "1.1.7",
11867
+
"@radix-ui/react-form": "0.1.8",
11868
+
"@radix-ui/react-hover-card": "1.1.15",
11869
+
"@radix-ui/react-label": "2.1.7",
11870
+
"@radix-ui/react-menu": "2.1.16",
11871
+
"@radix-ui/react-menubar": "1.1.16",
11872
+
"@radix-ui/react-navigation-menu": "1.2.14",
11873
+
"@radix-ui/react-one-time-password-field": "0.1.8",
11874
+
"@radix-ui/react-password-toggle-field": "0.1.3",
11875
+
"@radix-ui/react-popover": "1.1.15",
11876
+
"@radix-ui/react-popper": "1.2.8",
11877
+
"@radix-ui/react-portal": "1.1.9",
11878
+
"@radix-ui/react-presence": "1.1.5",
11879
+
"@radix-ui/react-primitive": "2.1.3",
11880
+
"@radix-ui/react-progress": "1.1.7",
11881
+
"@radix-ui/react-radio-group": "1.3.8",
11882
+
"@radix-ui/react-roving-focus": "1.1.11",
11883
+
"@radix-ui/react-scroll-area": "1.2.10",
11884
+
"@radix-ui/react-select": "2.2.6",
11885
+
"@radix-ui/react-separator": "1.1.7",
11886
+
"@radix-ui/react-slider": "1.3.6",
11887
+
"@radix-ui/react-slot": "1.2.3",
11888
+
"@radix-ui/react-switch": "1.2.6",
11889
+
"@radix-ui/react-tabs": "1.1.13",
11890
+
"@radix-ui/react-toast": "1.2.15",
11891
+
"@radix-ui/react-toggle": "1.1.10",
11892
+
"@radix-ui/react-toggle-group": "1.1.11",
11893
+
"@radix-ui/react-toolbar": "1.1.11",
11894
+
"@radix-ui/react-tooltip": "1.2.8",
11895
+
"@radix-ui/react-use-callback-ref": "1.1.1",
11896
+
"@radix-ui/react-use-controllable-state": "1.2.2",
11897
+
"@radix-ui/react-use-effect-event": "0.0.2",
11898
+
"@radix-ui/react-use-escape-keydown": "1.1.1",
11899
+
"@radix-ui/react-use-is-hydrated": "0.1.0",
11900
+
"@radix-ui/react-use-layout-effect": "1.1.1",
11901
+
"@radix-ui/react-use-size": "1.1.1",
11902
+
"@radix-ui/react-visually-hidden": "1.2.3"
11903
+
},
11904
+
"peerDependencies": {
11905
+
"@types/react": "*",
11906
+
"@types/react-dom": "*",
11907
+
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
11908
+
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
11909
+
},
11910
+
"peerDependenciesMeta": {
11911
+
"@types/react": {
11912
+
"optional": true
11913
+
},
11914
+
"@types/react-dom": {
11915
+
"optional": true
11916
+
}
11917
+
}
11918
+
},
11919
"node_modules/react": {
11920
"version": "19.1.1",
11921
"resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
···
11977
"node": ">=0.10.0"
11978
}
11979
},
11980
+
"node_modules/react-remove-scroll": {
11981
+
"version": "2.7.1",
11982
+
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz",
11983
+
"integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==",
11984
+
"dependencies": {
11985
+
"react-remove-scroll-bar": "^2.3.7",
11986
+
"react-style-singleton": "^2.2.3",
11987
+
"tslib": "^2.1.0",
11988
+
"use-callback-ref": "^1.3.3",
11989
+
"use-sidecar": "^1.1.3"
11990
+
},
11991
+
"engines": {
11992
+
"node": ">=10"
11993
+
},
11994
+
"peerDependencies": {
11995
+
"@types/react": "*",
11996
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
11997
+
},
11998
+
"peerDependenciesMeta": {
11999
+
"@types/react": {
12000
+
"optional": true
12001
+
}
12002
+
}
12003
+
},
12004
+
"node_modules/react-remove-scroll-bar": {
12005
+
"version": "2.3.8",
12006
+
"resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
12007
+
"integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
12008
+
"dependencies": {
12009
+
"react-style-singleton": "^2.2.2",
12010
+
"tslib": "^2.0.0"
12011
+
},
12012
+
"engines": {
12013
+
"node": ">=10"
12014
+
},
12015
+
"peerDependencies": {
12016
+
"@types/react": "*",
12017
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
12018
+
},
12019
+
"peerDependenciesMeta": {
12020
+
"@types/react": {
12021
+
"optional": true
12022
+
}
12023
+
}
12024
+
},
12025
+
"node_modules/react-style-singleton": {
12026
+
"version": "2.2.3",
12027
+
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
12028
+
"integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
12029
+
"dependencies": {
12030
+
"get-nonce": "^1.0.0",
12031
+
"tslib": "^2.0.0"
12032
+
},
12033
+
"engines": {
12034
+
"node": ">=10"
12035
+
},
12036
+
"peerDependencies": {
12037
+
"@types/react": "*",
12038
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
12039
+
},
12040
+
"peerDependenciesMeta": {
12041
+
"@types/react": {
12042
+
"optional": true
12043
+
}
12044
+
}
12045
+
},
12046
"node_modules/readdirp": {
12047
"version": "3.6.0",
12048
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
···
12080
"node": ">=0.10.0"
12081
}
12082
},
12083
+
"node_modules/reflect.getprototypeof": {
12084
+
"version": "1.0.10",
12085
+
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
12086
+
"integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
12087
+
"dev": true,
12088
+
"license": "MIT",
12089
+
"dependencies": {
12090
+
"call-bind": "^1.0.8",
12091
+
"define-properties": "^1.2.1",
12092
+
"es-abstract": "^1.23.9",
12093
+
"es-errors": "^1.3.0",
12094
+
"es-object-atoms": "^1.0.0",
12095
+
"get-intrinsic": "^1.2.7",
12096
+
"get-proto": "^1.0.1",
12097
+
"which-builtin-type": "^1.2.1"
12098
+
},
12099
+
"engines": {
12100
+
"node": ">= 0.4"
12101
+
},
12102
+
"funding": {
12103
+
"url": "https://github.com/sponsors/ljharb"
12104
+
}
12105
+
},
12106
+
"node_modules/regexp.prototype.flags": {
12107
+
"version": "1.5.4",
12108
+
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
12109
+
"integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
12110
+
"dev": true,
12111
+
"license": "MIT",
12112
+
"dependencies": {
12113
+
"call-bind": "^1.0.8",
12114
+
"define-properties": "^1.2.1",
12115
+
"es-errors": "^1.3.0",
12116
+
"get-proto": "^1.0.1",
12117
+
"gopd": "^1.2.0",
12118
+
"set-function-name": "^2.0.2"
12119
+
},
12120
+
"engines": {
12121
+
"node": ">= 0.4"
12122
+
},
12123
+
"funding": {
12124
+
"url": "https://github.com/sponsors/ljharb"
12125
+
}
12126
+
},
12127
+
"node_modules/resolve": {
12128
+
"version": "2.0.0-next.5",
12129
+
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
12130
+
"integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
12131
+
"dev": true,
12132
+
"license": "MIT",
12133
+
"dependencies": {
12134
+
"is-core-module": "^2.13.0",
12135
+
"path-parse": "^1.0.7",
12136
+
"supports-preserve-symlinks-flag": "^1.0.0"
12137
+
},
12138
+
"bin": {
12139
+
"resolve": "bin/resolve"
12140
+
},
12141
+
"funding": {
12142
+
"url": "https://github.com/sponsors/ljharb"
12143
+
}
12144
+
},
12145
+
"node_modules/resolve-from": {
12146
+
"version": "4.0.0",
12147
+
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
12148
+
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
12149
+
"dev": true,
12150
+
"license": "MIT",
12151
+
"engines": {
12152
+
"node": ">=4"
12153
+
}
12154
+
},
12155
"node_modules/resolve-pkg-maps": {
12156
"version": "1.0.0",
12157
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
···
12161
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
12162
}
12163
},
12164
+
"node_modules/reusify": {
12165
+
"version": "1.1.0",
12166
+
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
12167
+
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
12168
+
"dev": true,
12169
+
"license": "MIT",
12170
+
"engines": {
12171
+
"iojs": ">=1.0.0",
12172
+
"node": ">=0.10.0"
12173
+
}
12174
+
},
12175
"node_modules/rollup": {
12176
"version": "4.49.0",
12177
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.49.0.tgz",
···
12218
"dev": true,
12219
"license": "MIT"
12220
},
12221
+
"node_modules/run-parallel": {
12222
+
"version": "1.2.0",
12223
+
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
12224
+
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
12225
+
"dev": true,
12226
+
"funding": [
12227
+
{
12228
+
"type": "github",
12229
+
"url": "https://github.com/sponsors/feross"
12230
+
},
12231
+
{
12232
+
"type": "patreon",
12233
+
"url": "https://www.patreon.com/feross"
12234
+
},
12235
+
{
12236
+
"type": "consulting",
12237
+
"url": "https://feross.org/support"
12238
+
}
12239
+
],
12240
+
"license": "MIT",
12241
+
"dependencies": {
12242
+
"queue-microtask": "^1.2.2"
12243
+
}
12244
+
},
12245
+
"node_modules/safe-array-concat": {
12246
+
"version": "1.1.3",
12247
+
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
12248
+
"integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
12249
+
"dev": true,
12250
+
"license": "MIT",
12251
+
"dependencies": {
12252
+
"call-bind": "^1.0.8",
12253
+
"call-bound": "^1.0.2",
12254
+
"get-intrinsic": "^1.2.6",
12255
+
"has-symbols": "^1.1.0",
12256
+
"isarray": "^2.0.5"
12257
+
},
12258
+
"engines": {
12259
+
"node": ">=0.4"
12260
+
},
12261
+
"funding": {
12262
+
"url": "https://github.com/sponsors/ljharb"
12263
+
}
12264
+
},
12265
+
"node_modules/safe-push-apply": {
12266
+
"version": "1.0.0",
12267
+
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
12268
+
"integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
12269
+
"dev": true,
12270
+
"license": "MIT",
12271
+
"dependencies": {
12272
+
"es-errors": "^1.3.0",
12273
+
"isarray": "^2.0.5"
12274
+
},
12275
+
"engines": {
12276
+
"node": ">= 0.4"
12277
+
},
12278
+
"funding": {
12279
+
"url": "https://github.com/sponsors/ljharb"
12280
+
}
12281
+
},
12282
+
"node_modules/safe-regex-test": {
12283
+
"version": "1.1.0",
12284
+
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
12285
+
"integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
12286
+
"dev": true,
12287
+
"license": "MIT",
12288
+
"dependencies": {
12289
+
"call-bound": "^1.0.2",
12290
+
"es-errors": "^1.3.0",
12291
+
"is-regex": "^1.2.1"
12292
+
},
12293
+
"engines": {
12294
+
"node": ">= 0.4"
12295
+
},
12296
+
"funding": {
12297
+
"url": "https://github.com/sponsors/ljharb"
12298
+
}
12299
+
},
12300
"node_modules/safer-buffer": {
12301
"version": "2.1.2",
12302
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
···
12329
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
12330
"license": "MIT"
12331
},
12332
+
"node_modules/scule": {
12333
+
"version": "1.3.0",
12334
+
"resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz",
12335
+
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
12336
+
"dev": true,
12337
+
"license": "MIT"
12338
+
},
12339
"node_modules/semver": {
12340
"version": "6.3.1",
12341
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
···
12366
"seroval": "^1.0"
12367
}
12368
},
12369
+
"node_modules/set-function-length": {
12370
+
"version": "1.2.2",
12371
+
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
12372
+
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
12373
+
"dev": true,
12374
+
"license": "MIT",
12375
+
"dependencies": {
12376
+
"define-data-property": "^1.1.4",
12377
+
"es-errors": "^1.3.0",
12378
+
"function-bind": "^1.1.2",
12379
+
"get-intrinsic": "^1.2.4",
12380
+
"gopd": "^1.0.1",
12381
+
"has-property-descriptors": "^1.0.2"
12382
+
},
12383
+
"engines": {
12384
+
"node": ">= 0.4"
12385
+
}
12386
+
},
12387
+
"node_modules/set-function-name": {
12388
+
"version": "2.0.2",
12389
+
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
12390
+
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
12391
+
"dev": true,
12392
+
"license": "MIT",
12393
+
"dependencies": {
12394
+
"define-data-property": "^1.1.4",
12395
+
"es-errors": "^1.3.0",
12396
+
"functions-have-names": "^1.2.3",
12397
+
"has-property-descriptors": "^1.0.2"
12398
+
},
12399
+
"engines": {
12400
+
"node": ">= 0.4"
12401
+
}
12402
+
},
12403
+
"node_modules/set-proto": {
12404
+
"version": "1.0.0",
12405
+
"resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
12406
+
"integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
12407
+
"dev": true,
12408
+
"license": "MIT",
12409
+
"dependencies": {
12410
+
"dunder-proto": "^1.0.1",
12411
+
"es-errors": "^1.3.0",
12412
+
"es-object-atoms": "^1.0.0"
12413
+
},
12414
+
"engines": {
12415
+
"node": ">= 0.4"
12416
+
}
12417
+
},
12418
+
"node_modules/shebang-command": {
12419
+
"version": "2.0.0",
12420
+
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
12421
+
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
12422
+
"dev": true,
12423
+
"license": "MIT",
12424
+
"peer": true,
12425
+
"dependencies": {
12426
+
"shebang-regex": "^3.0.0"
12427
+
},
12428
+
"engines": {
12429
+
"node": ">=8"
12430
+
}
12431
+
},
12432
+
"node_modules/shebang-regex": {
12433
+
"version": "3.0.0",
12434
+
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
12435
+
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
12436
+
"dev": true,
12437
+
"license": "MIT",
12438
+
"peer": true,
12439
+
"engines": {
12440
+
"node": ">=8"
12441
+
}
12442
+
},
12443
+
"node_modules/side-channel": {
12444
+
"version": "1.1.0",
12445
+
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
12446
+
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
12447
+
"dev": true,
12448
+
"license": "MIT",
12449
+
"dependencies": {
12450
+
"es-errors": "^1.3.0",
12451
+
"object-inspect": "^1.13.3",
12452
+
"side-channel-list": "^1.0.0",
12453
+
"side-channel-map": "^1.0.1",
12454
+
"side-channel-weakmap": "^1.0.2"
12455
+
},
12456
+
"engines": {
12457
+
"node": ">= 0.4"
12458
+
},
12459
+
"funding": {
12460
+
"url": "https://github.com/sponsors/ljharb"
12461
+
}
12462
+
},
12463
+
"node_modules/side-channel-list": {
12464
+
"version": "1.0.0",
12465
+
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
12466
+
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
12467
+
"dev": true,
12468
+
"license": "MIT",
12469
+
"dependencies": {
12470
+
"es-errors": "^1.3.0",
12471
+
"object-inspect": "^1.13.3"
12472
+
},
12473
+
"engines": {
12474
+
"node": ">= 0.4"
12475
+
},
12476
+
"funding": {
12477
+
"url": "https://github.com/sponsors/ljharb"
12478
+
}
12479
+
},
12480
+
"node_modules/side-channel-map": {
12481
+
"version": "1.0.1",
12482
+
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
12483
+
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
12484
+
"dev": true,
12485
+
"license": "MIT",
12486
+
"dependencies": {
12487
+
"call-bound": "^1.0.2",
12488
+
"es-errors": "^1.3.0",
12489
+
"get-intrinsic": "^1.2.5",
12490
+
"object-inspect": "^1.13.3"
12491
+
},
12492
+
"engines": {
12493
+
"node": ">= 0.4"
12494
+
},
12495
+
"funding": {
12496
+
"url": "https://github.com/sponsors/ljharb"
12497
+
}
12498
+
},
12499
+
"node_modules/side-channel-weakmap": {
12500
+
"version": "1.0.2",
12501
+
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
12502
+
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
12503
+
"dev": true,
12504
+
"license": "MIT",
12505
+
"dependencies": {
12506
+
"call-bound": "^1.0.2",
12507
+
"es-errors": "^1.3.0",
12508
+
"get-intrinsic": "^1.2.5",
12509
+
"object-inspect": "^1.13.3",
12510
+
"side-channel-map": "^1.0.1"
12511
+
},
12512
+
"engines": {
12513
+
"node": ">= 0.4"
12514
+
},
12515
+
"funding": {
12516
+
"url": "https://github.com/sponsors/ljharb"
12517
+
}
12518
+
},
12519
"node_modules/siginfo": {
12520
"version": "2.0.0",
12521
"resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
···
12523
"dev": true,
12524
"license": "ISC"
12525
},
12526
+
"node_modules/snake-case": {
12527
+
"version": "3.0.4",
12528
+
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
12529
+
"integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
12530
+
"dev": true,
12531
+
"license": "MIT",
12532
+
"dependencies": {
12533
+
"dot-case": "^3.0.4",
12534
+
"tslib": "^2.0.3"
12535
+
}
12536
+
},
12537
"node_modules/solid-js": {
12538
"version": "1.9.9",
12539
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.9.tgz",
···
12583
"dev": true,
12584
"license": "MIT"
12585
},
12586
+
"node_modules/stop-iteration-iterator": {
12587
+
"version": "1.1.0",
12588
+
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
12589
+
"integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
12590
+
"dev": true,
12591
+
"license": "MIT",
12592
+
"dependencies": {
12593
+
"es-errors": "^1.3.0",
12594
+
"internal-slot": "^1.1.0"
12595
+
},
12596
+
"engines": {
12597
+
"node": ">= 0.4"
12598
+
}
12599
+
},
12600
+
"node_modules/string-ts": {
12601
+
"version": "2.2.1",
12602
+
"resolved": "https://registry.npmjs.org/string-ts/-/string-ts-2.2.1.tgz",
12603
+
"integrity": "sha512-Q2u0gko67PLLhbte5HmPfdOjNvUKbKQM+mCNQae6jE91DmoFHY6HH9GcdqCeNx87DZ2KKjiFxmA0R/42OneGWw==",
12604
+
"dev": true,
12605
+
"license": "MIT"
12606
+
},
12607
+
"node_modules/string.prototype.matchall": {
12608
+
"version": "4.0.12",
12609
+
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
12610
+
"integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
12611
+
"dev": true,
12612
+
"license": "MIT",
12613
+
"dependencies": {
12614
+
"call-bind": "^1.0.8",
12615
+
"call-bound": "^1.0.3",
12616
+
"define-properties": "^1.2.1",
12617
+
"es-abstract": "^1.23.6",
12618
+
"es-errors": "^1.3.0",
12619
+
"es-object-atoms": "^1.0.0",
12620
+
"get-intrinsic": "^1.2.6",
12621
+
"gopd": "^1.2.0",
12622
+
"has-symbols": "^1.1.0",
12623
+
"internal-slot": "^1.1.0",
12624
+
"regexp.prototype.flags": "^1.5.3",
12625
+
"set-function-name": "^2.0.2",
12626
+
"side-channel": "^1.1.0"
12627
+
},
12628
+
"engines": {
12629
+
"node": ">= 0.4"
12630
+
},
12631
+
"funding": {
12632
+
"url": "https://github.com/sponsors/ljharb"
12633
+
}
12634
+
},
12635
+
"node_modules/string.prototype.repeat": {
12636
+
"version": "1.0.0",
12637
+
"resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
12638
+
"integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
12639
+
"dev": true,
12640
+
"license": "MIT",
12641
+
"dependencies": {
12642
+
"define-properties": "^1.1.3",
12643
+
"es-abstract": "^1.17.5"
12644
+
}
12645
+
},
12646
+
"node_modules/string.prototype.trim": {
12647
+
"version": "1.2.10",
12648
+
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
12649
+
"integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
12650
+
"dev": true,
12651
+
"license": "MIT",
12652
+
"dependencies": {
12653
+
"call-bind": "^1.0.8",
12654
+
"call-bound": "^1.0.2",
12655
+
"define-data-property": "^1.1.4",
12656
+
"define-properties": "^1.2.1",
12657
+
"es-abstract": "^1.23.5",
12658
+
"es-object-atoms": "^1.0.0",
12659
+
"has-property-descriptors": "^1.0.2"
12660
+
},
12661
+
"engines": {
12662
+
"node": ">= 0.4"
12663
+
},
12664
+
"funding": {
12665
+
"url": "https://github.com/sponsors/ljharb"
12666
+
}
12667
+
},
12668
+
"node_modules/string.prototype.trimend": {
12669
+
"version": "1.0.9",
12670
+
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
12671
+
"integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
12672
+
"dev": true,
12673
+
"license": "MIT",
12674
+
"dependencies": {
12675
+
"call-bind": "^1.0.8",
12676
+
"call-bound": "^1.0.2",
12677
+
"define-properties": "^1.2.1",
12678
+
"es-object-atoms": "^1.0.0"
12679
+
},
12680
+
"engines": {
12681
+
"node": ">= 0.4"
12682
+
},
12683
+
"funding": {
12684
+
"url": "https://github.com/sponsors/ljharb"
12685
+
}
12686
+
},
12687
+
"node_modules/string.prototype.trimstart": {
12688
+
"version": "1.0.8",
12689
+
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
12690
+
"integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
12691
+
"dev": true,
12692
+
"license": "MIT",
12693
+
"dependencies": {
12694
+
"call-bind": "^1.0.7",
12695
+
"define-properties": "^1.2.1",
12696
+
"es-object-atoms": "^1.0.0"
12697
+
},
12698
+
"engines": {
12699
+
"node": ">= 0.4"
12700
+
},
12701
+
"funding": {
12702
+
"url": "https://github.com/sponsors/ljharb"
12703
+
}
12704
+
},
12705
+
"node_modules/strip-json-comments": {
12706
+
"version": "3.1.1",
12707
+
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
12708
+
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
12709
+
"dev": true,
12710
+
"license": "MIT",
12711
+
"peer": true,
12712
+
"engines": {
12713
+
"node": ">=8"
12714
+
},
12715
+
"funding": {
12716
+
"url": "https://github.com/sponsors/sindresorhus"
12717
+
}
12718
+
},
12719
"node_modules/strip-literal": {
12720
+
"version": "3.1.0",
12721
+
"resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz",
12722
+
"integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==",
12723
"dev": true,
12724
"license": "MIT",
12725
"dependencies": {
···
12742
"integrity": "sha512-9pP/CVNp4NF2MNlRzLwQkjiTgKKe9WYXrLh9+8QokWmMxz+zt2mf1utkWLco26IuA3AfVcTb//qtlTIjY3VHxA==",
12743
"license": "MIT"
12744
},
12745
+
"node_modules/supports-color": {
12746
+
"version": "7.2.0",
12747
+
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
12748
+
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
12749
+
"dev": true,
12750
+
"license": "MIT",
12751
+
"peer": true,
12752
+
"dependencies": {
12753
+
"has-flag": "^4.0.0"
12754
+
},
12755
+
"engines": {
12756
+
"node": ">=8"
12757
+
}
12758
+
},
12759
+
"node_modules/supports-preserve-symlinks-flag": {
12760
+
"version": "1.0.0",
12761
+
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
12762
+
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
12763
+
"dev": true,
12764
+
"license": "MIT",
12765
+
"engines": {
12766
+
"node": ">= 0.4"
12767
+
},
12768
+
"funding": {
12769
+
"url": "https://github.com/sponsors/ljharb"
12770
+
}
12771
+
},
12772
+
"node_modules/svg-parser": {
12773
+
"version": "2.0.4",
12774
+
"resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz",
12775
+
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==",
12776
+
"dev": true,
12777
+
"license": "MIT"
12778
+
},
12779
"node_modules/symbol-tree": {
12780
"version": "3.2.4",
12781
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
···
12788
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.12.tgz",
12789
"integrity": "sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==",
12790
"license": "MIT"
12791
+
},
12792
+
"node_modules/tanstack-router-keepalive": {
12793
+
"version": "1.0.0",
12794
+
"resolved": "https://registry.npmjs.org/tanstack-router-keepalive/-/tanstack-router-keepalive-1.0.0.tgz",
12795
+
"integrity": "sha512-SxMl9sgIZGjB4OZvGXufTz14ygmZi+eAbrhz3sjmXYZzhSQOekx5LYi9TvKcMXVu8fQR6W/itF5hdglqD6WB/w==",
12796
+
"license": "MIT",
12797
+
"dependencies": {
12798
+
"eventemitter3": "^5.0.1",
12799
+
"lodash.clonedeep": "^4.5.0"
12800
+
}
12801
},
12802
"node_modules/tapable": {
12803
"version": "2.2.3",
···
12871
"license": "MIT"
12872
},
12873
"node_modules/tinyglobby": {
12874
+
"version": "0.2.15",
12875
+
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
12876
+
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
12877
"license": "MIT",
12878
"dependencies": {
12879
+
"fdir": "^6.5.0",
12880
+
"picomatch": "^4.0.3"
12881
},
12882
"engines": {
12883
"node": ">=12.0.0"
···
13012
"node": ">=18"
13013
}
13014
},
13015
+
"node_modules/ts-api-utils": {
13016
+
"version": "2.1.0",
13017
+
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
13018
+
"integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
13019
+
"dev": true,
13020
+
"license": "MIT",
13021
+
"engines": {
13022
+
"node": ">=18.12"
13023
+
},
13024
+
"peerDependencies": {
13025
+
"typescript": ">=4.8.4"
13026
+
}
13027
+
},
13028
+
"node_modules/ts-declaration-location": {
13029
+
"version": "1.0.7",
13030
+
"resolved": "https://registry.npmjs.org/ts-declaration-location/-/ts-declaration-location-1.0.7.tgz",
13031
+
"integrity": "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==",
13032
+
"dev": true,
13033
+
"funding": [
13034
+
{
13035
+
"type": "ko-fi",
13036
+
"url": "https://ko-fi.com/rebeccastevens"
13037
+
},
13038
+
{
13039
+
"type": "tidelift",
13040
+
"url": "https://tidelift.com/funding/github/npm/ts-declaration-location"
13041
+
}
13042
+
],
13043
+
"license": "BSD-3-Clause",
13044
+
"dependencies": {
13045
+
"picomatch": "^4.0.2"
13046
+
},
13047
+
"peerDependencies": {
13048
+
"typescript": ">=4.0.0"
13049
+
}
13050
+
},
13051
+
"node_modules/ts-declaration-location/node_modules/picomatch": {
13052
+
"version": "4.0.3",
13053
+
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
13054
+
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
13055
+
"dev": true,
13056
+
"license": "MIT",
13057
+
"engines": {
13058
+
"node": ">=12"
13059
+
},
13060
+
"funding": {
13061
+
"url": "https://github.com/sponsors/jonschlinkert"
13062
+
}
13063
+
},
13064
+
"node_modules/ts-pattern": {
13065
+
"version": "5.8.0",
13066
+
"resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.8.0.tgz",
13067
+
"integrity": "sha512-kIjN2qmWiHnhgr5DAkAafF9fwb0T5OhMVSWrm8XEdTFnX6+wfXwYOFjeF86UZ54vduqiR7BfqScFmXSzSaH8oA==",
13068
+
"dev": true,
13069
+
"license": "MIT"
13070
+
},
13071
"node_modules/tslib": {
13072
"version": "2.8.1",
13073
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
···
13099
"integrity": "sha512-SDpZ4f7sZmwHF6XG5PF0KWuP18pH/kNG04MhTcpqJby7Lk/D3TS/lCYd+RSg0rIAAVi1LDgSIo1yJs9kmHlhgw==",
13100
"license": "MIT"
13101
},
13102
+
"node_modules/type-check": {
13103
+
"version": "0.4.0",
13104
+
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
13105
+
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
13106
+
"dev": true,
13107
+
"license": "MIT",
13108
+
"peer": true,
13109
+
"dependencies": {
13110
+
"prelude-ls": "^1.2.1"
13111
+
},
13112
+
"engines": {
13113
+
"node": ">= 0.8.0"
13114
+
}
13115
+
},
13116
+
"node_modules/typed-array-buffer": {
13117
+
"version": "1.0.3",
13118
+
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
13119
+
"integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
13120
+
"dev": true,
13121
+
"license": "MIT",
13122
+
"dependencies": {
13123
+
"call-bound": "^1.0.3",
13124
+
"es-errors": "^1.3.0",
13125
+
"is-typed-array": "^1.1.14"
13126
+
},
13127
+
"engines": {
13128
+
"node": ">= 0.4"
13129
+
}
13130
+
},
13131
+
"node_modules/typed-array-byte-length": {
13132
+
"version": "1.0.3",
13133
+
"resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
13134
+
"integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
13135
+
"dev": true,
13136
+
"license": "MIT",
13137
+
"dependencies": {
13138
+
"call-bind": "^1.0.8",
13139
+
"for-each": "^0.3.3",
13140
+
"gopd": "^1.2.0",
13141
+
"has-proto": "^1.2.0",
13142
+
"is-typed-array": "^1.1.14"
13143
+
},
13144
+
"engines": {
13145
+
"node": ">= 0.4"
13146
+
},
13147
+
"funding": {
13148
+
"url": "https://github.com/sponsors/ljharb"
13149
+
}
13150
+
},
13151
+
"node_modules/typed-array-byte-offset": {
13152
+
"version": "1.0.4",
13153
+
"resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
13154
+
"integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
13155
+
"dev": true,
13156
+
"license": "MIT",
13157
+
"dependencies": {
13158
+
"available-typed-arrays": "^1.0.7",
13159
+
"call-bind": "^1.0.8",
13160
+
"for-each": "^0.3.3",
13161
+
"gopd": "^1.2.0",
13162
+
"has-proto": "^1.2.0",
13163
+
"is-typed-array": "^1.1.15",
13164
+
"reflect.getprototypeof": "^1.0.9"
13165
+
},
13166
+
"engines": {
13167
+
"node": ">= 0.4"
13168
+
},
13169
+
"funding": {
13170
+
"url": "https://github.com/sponsors/ljharb"
13171
+
}
13172
+
},
13173
+
"node_modules/typed-array-length": {
13174
+
"version": "1.0.7",
13175
+
"resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
13176
+
"integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
13177
+
"dev": true,
13178
+
"license": "MIT",
13179
+
"dependencies": {
13180
+
"call-bind": "^1.0.7",
13181
+
"for-each": "^0.3.3",
13182
+
"gopd": "^1.0.1",
13183
+
"is-typed-array": "^1.1.13",
13184
+
"possible-typed-array-names": "^1.0.0",
13185
+
"reflect.getprototypeof": "^1.0.6"
13186
+
},
13187
+
"engines": {
13188
+
"node": ">= 0.4"
13189
+
},
13190
+
"funding": {
13191
+
"url": "https://github.com/sponsors/ljharb"
13192
+
}
13193
+
},
13194
"node_modules/typescript": {
13195
+
"version": "5.9.3",
13196
+
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
13197
+
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
13198
"dev": true,
13199
"license": "Apache-2.0",
13200
"bin": {
···
13205
"node": ">=14.17"
13206
}
13207
},
13208
+
"node_modules/typescript-eslint": {
13209
+
"version": "8.46.1",
13210
+
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.1.tgz",
13211
+
"integrity": "sha512-VHgijW803JafdSsDO8I761r3SHrgk4T00IdyQ+/UsthtgPRsBWQLqoSxOolxTpxRKi1kGXK0bSz4CoAc9ObqJA==",
13212
+
"dev": true,
13213
+
"license": "MIT",
13214
+
"dependencies": {
13215
+
"@typescript-eslint/eslint-plugin": "8.46.1",
13216
+
"@typescript-eslint/parser": "8.46.1",
13217
+
"@typescript-eslint/typescript-estree": "8.46.1",
13218
+
"@typescript-eslint/utils": "8.46.1"
13219
+
},
13220
+
"engines": {
13221
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
13222
+
},
13223
+
"funding": {
13224
+
"type": "opencollective",
13225
+
"url": "https://opencollective.com/typescript-eslint"
13226
+
},
13227
+
"peerDependencies": {
13228
+
"eslint": "^8.57.0 || ^9.0.0",
13229
+
"typescript": ">=4.8.4 <6.0.0"
13230
+
}
13231
+
},
13232
"node_modules/ua-parser-js": {
13233
"version": "1.0.41",
13234
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz",
···
13255
"node": "*"
13256
}
13257
},
13258
+
"node_modules/ufo": {
13259
+
"version": "1.6.1",
13260
+
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
13261
+
"integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==",
13262
+
"dev": true,
13263
+
"license": "MIT"
13264
+
},
13265
"node_modules/uint8arrays": {
13266
"version": "3.0.0",
13267
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz",
···
13271
"multiformats": "^9.4.2"
13272
}
13273
},
13274
+
"node_modules/unbox-primitive": {
13275
+
"version": "1.1.0",
13276
+
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
13277
+
"integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
13278
+
"dev": true,
13279
+
"license": "MIT",
13280
+
"dependencies": {
13281
+
"call-bound": "^1.0.3",
13282
+
"has-bigints": "^1.0.2",
13283
+
"has-symbols": "^1.1.0",
13284
+
"which-boxed-primitive": "^1.1.1"
13285
+
},
13286
+
"engines": {
13287
+
"node": ">= 0.4"
13288
+
},
13289
+
"funding": {
13290
+
"url": "https://github.com/sponsors/ljharb"
13291
+
}
13292
+
},
13293
"node_modules/undici-types": {
13294
"version": "7.10.0",
13295
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
···
13297
"devOptional": true,
13298
"license": "MIT"
13299
},
13300
+
"node_modules/unimport": {
13301
+
"version": "5.5.0",
13302
+
"resolved": "https://registry.npmjs.org/unimport/-/unimport-5.5.0.tgz",
13303
+
"integrity": "sha512-/JpWMG9s1nBSlXJAQ8EREFTFy3oy6USFd8T6AoBaw1q2GGcF4R9yp3ofg32UODZlYEO5VD0EWE1RpI9XDWyPYg==",
13304
+
"dev": true,
13305
+
"license": "MIT",
13306
+
"dependencies": {
13307
+
"acorn": "^8.15.0",
13308
+
"escape-string-regexp": "^5.0.0",
13309
+
"estree-walker": "^3.0.3",
13310
+
"local-pkg": "^1.1.2",
13311
+
"magic-string": "^0.30.19",
13312
+
"mlly": "^1.8.0",
13313
+
"pathe": "^2.0.3",
13314
+
"picomatch": "^4.0.3",
13315
+
"pkg-types": "^2.3.0",
13316
+
"scule": "^1.3.0",
13317
+
"strip-literal": "^3.1.0",
13318
+
"tinyglobby": "^0.2.15",
13319
+
"unplugin": "^2.3.10",
13320
+
"unplugin-utils": "^0.3.0"
13321
+
},
13322
+
"engines": {
13323
+
"node": ">=18.12.0"
13324
+
}
13325
+
},
13326
+
"node_modules/unimport/node_modules/escape-string-regexp": {
13327
+
"version": "5.0.0",
13328
+
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
13329
+
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
13330
+
"dev": true,
13331
+
"license": "MIT",
13332
+
"engines": {
13333
+
"node": ">=12"
13334
+
},
13335
+
"funding": {
13336
+
"url": "https://github.com/sponsors/sindresorhus"
13337
+
}
13338
+
},
13339
+
"node_modules/unimport/node_modules/picomatch": {
13340
+
"version": "4.0.3",
13341
+
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
13342
+
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
13343
+
"dev": true,
13344
+
"license": "MIT",
13345
+
"engines": {
13346
+
"node": ">=12"
13347
+
},
13348
+
"funding": {
13349
+
"url": "https://github.com/sponsors/jonschlinkert"
13350
+
}
13351
+
},
13352
"node_modules/unplugin": {
13353
+
"version": "2.3.10",
13354
+
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.10.tgz",
13355
+
"integrity": "sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==",
13356
"license": "MIT",
13357
"dependencies": {
13358
"@jridgewell/remapping": "^2.3.5",
···
13364
"node": ">=18.12.0"
13365
}
13366
},
13367
+
"node_modules/unplugin-auto-import": {
13368
+
"version": "20.2.0",
13369
+
"resolved": "https://registry.npmjs.org/unplugin-auto-import/-/unplugin-auto-import-20.2.0.tgz",
13370
+
"integrity": "sha512-vfBI/SvD9hJqYNinipVOAj5n8dS8DJXFlCKFR5iLDp2SaQwsfdnfLXgZ+34Kd3YY3YEY9omk8XQg0bwos3Q8ug==",
13371
+
"dev": true,
13372
+
"license": "MIT",
13373
+
"dependencies": {
13374
+
"local-pkg": "^1.1.2",
13375
+
"magic-string": "^0.30.19",
13376
+
"picomatch": "^4.0.3",
13377
+
"unimport": "^5.4.0",
13378
+
"unplugin": "^2.3.10",
13379
+
"unplugin-utils": "^0.3.0"
13380
+
},
13381
+
"engines": {
13382
+
"node": ">=14"
13383
+
},
13384
+
"funding": {
13385
+
"url": "https://github.com/sponsors/antfu"
13386
+
},
13387
+
"peerDependencies": {
13388
+
"@nuxt/kit": "^4.0.0",
13389
+
"@vueuse/core": "*"
13390
+
},
13391
+
"peerDependenciesMeta": {
13392
+
"@nuxt/kit": {
13393
+
"optional": true
13394
+
},
13395
+
"@vueuse/core": {
13396
+
"optional": true
13397
+
}
13398
+
}
13399
+
},
13400
+
"node_modules/unplugin-auto-import/node_modules/picomatch": {
13401
+
"version": "4.0.3",
13402
+
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
13403
+
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
13404
+
"dev": true,
13405
+
"license": "MIT",
13406
+
"engines": {
13407
+
"node": ">=12"
13408
+
},
13409
+
"funding": {
13410
+
"url": "https://github.com/sponsors/jonschlinkert"
13411
+
}
13412
+
},
13413
+
"node_modules/unplugin-icons": {
13414
+
"version": "22.4.2",
13415
+
"resolved": "https://registry.npmjs.org/unplugin-icons/-/unplugin-icons-22.4.2.tgz",
13416
+
"integrity": "sha512-Yv15405unO67Chme0Slk0JRA/H2AiAZLK5t7ebt8/ZpTDlBfM4d4En2qD3MX2rzOSkIteQ0syIm3q8MSofeoBA==",
13417
+
"dev": true,
13418
+
"license": "MIT",
13419
+
"dependencies": {
13420
+
"@antfu/install-pkg": "^1.1.0",
13421
+
"@iconify/utils": "^3.0.2",
13422
+
"debug": "^4.4.3",
13423
+
"local-pkg": "^1.1.2",
13424
+
"unplugin": "^2.3.10"
13425
+
},
13426
+
"funding": {
13427
+
"url": "https://github.com/sponsors/antfu"
13428
+
},
13429
+
"peerDependencies": {
13430
+
"@svgr/core": ">=7.0.0",
13431
+
"@svgx/core": "^1.0.1",
13432
+
"@vue/compiler-sfc": "^3.0.2 || ^2.7.0",
13433
+
"svelte": "^3.0.0 || ^4.0.0 || ^5.0.0",
13434
+
"vue-template-compiler": "^2.6.12",
13435
+
"vue-template-es2015-compiler": "^1.9.0"
13436
+
},
13437
+
"peerDependenciesMeta": {
13438
+
"@svgr/core": {
13439
+
"optional": true
13440
+
},
13441
+
"@svgx/core": {
13442
+
"optional": true
13443
+
},
13444
+
"@vue/compiler-sfc": {
13445
+
"optional": true
13446
+
},
13447
+
"svelte": {
13448
+
"optional": true
13449
+
},
13450
+
"vue-template-compiler": {
13451
+
"optional": true
13452
+
},
13453
+
"vue-template-es2015-compiler": {
13454
+
"optional": true
13455
+
}
13456
+
}
13457
+
},
13458
+
"node_modules/unplugin-utils": {
13459
+
"version": "0.3.1",
13460
+
"resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.1.tgz",
13461
+
"integrity": "sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==",
13462
+
"dev": true,
13463
+
"license": "MIT",
13464
+
"dependencies": {
13465
+
"pathe": "^2.0.3",
13466
+
"picomatch": "^4.0.3"
13467
+
},
13468
+
"engines": {
13469
+
"node": ">=20.19.0"
13470
+
},
13471
+
"funding": {
13472
+
"url": "https://github.com/sponsors/sxzz"
13473
+
}
13474
+
},
13475
+
"node_modules/unplugin-utils/node_modules/picomatch": {
13476
+
"version": "4.0.3",
13477
+
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
13478
+
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
13479
+
"dev": true,
13480
+
"license": "MIT",
13481
+
"engines": {
13482
+
"node": ">=12"
13483
+
},
13484
+
"funding": {
13485
+
"url": "https://github.com/sponsors/jonschlinkert"
13486
+
}
13487
+
},
13488
"node_modules/unplugin/node_modules/picomatch": {
13489
"version": "4.0.3",
13490
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
···
13525
},
13526
"peerDependencies": {
13527
"browserslist": ">= 4.21.0"
13528
+
}
13529
+
},
13530
+
"node_modules/uri-js": {
13531
+
"version": "4.4.1",
13532
+
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
13533
+
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
13534
+
"dev": true,
13535
+
"license": "BSD-2-Clause",
13536
+
"peer": true,
13537
+
"dependencies": {
13538
+
"punycode": "^2.1.0"
13539
+
}
13540
+
},
13541
+
"node_modules/use-callback-ref": {
13542
+
"version": "1.3.3",
13543
+
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
13544
+
"integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
13545
+
"dependencies": {
13546
+
"tslib": "^2.0.0"
13547
+
},
13548
+
"engines": {
13549
+
"node": ">=10"
13550
+
},
13551
+
"peerDependencies": {
13552
+
"@types/react": "*",
13553
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
13554
+
},
13555
+
"peerDependenciesMeta": {
13556
+
"@types/react": {
13557
+
"optional": true
13558
+
}
13559
+
}
13560
+
},
13561
+
"node_modules/use-sidecar": {
13562
+
"version": "1.1.3",
13563
+
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
13564
+
"integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
13565
+
"dependencies": {
13566
+
"detect-node-es": "^1.1.0",
13567
+
"tslib": "^2.0.0"
13568
+
},
13569
+
"engines": {
13570
+
"node": ">=10"
13571
+
},
13572
+
"peerDependencies": {
13573
+
"@types/react": "*",
13574
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
13575
+
},
13576
+
"peerDependenciesMeta": {
13577
+
"@types/react": {
13578
+
"optional": true
13579
+
}
13580
}
13581
},
13582
"node_modules/use-sync-external-store": {
···
13891
"node": ">=18"
13892
}
13893
},
13894
+
"node_modules/which": {
13895
+
"version": "2.0.2",
13896
+
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
13897
+
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
13898
+
"dev": true,
13899
+
"license": "ISC",
13900
+
"peer": true,
13901
+
"dependencies": {
13902
+
"isexe": "^2.0.0"
13903
+
},
13904
+
"bin": {
13905
+
"node-which": "bin/node-which"
13906
+
},
13907
+
"engines": {
13908
+
"node": ">= 8"
13909
+
}
13910
+
},
13911
+
"node_modules/which-boxed-primitive": {
13912
+
"version": "1.1.1",
13913
+
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
13914
+
"integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
13915
+
"dev": true,
13916
+
"license": "MIT",
13917
+
"dependencies": {
13918
+
"is-bigint": "^1.1.0",
13919
+
"is-boolean-object": "^1.2.1",
13920
+
"is-number-object": "^1.1.1",
13921
+
"is-string": "^1.1.1",
13922
+
"is-symbol": "^1.1.1"
13923
+
},
13924
+
"engines": {
13925
+
"node": ">= 0.4"
13926
+
},
13927
+
"funding": {
13928
+
"url": "https://github.com/sponsors/ljharb"
13929
+
}
13930
+
},
13931
+
"node_modules/which-builtin-type": {
13932
+
"version": "1.2.1",
13933
+
"resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
13934
+
"integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
13935
+
"dev": true,
13936
+
"license": "MIT",
13937
+
"dependencies": {
13938
+
"call-bound": "^1.0.2",
13939
+
"function.prototype.name": "^1.1.6",
13940
+
"has-tostringtag": "^1.0.2",
13941
+
"is-async-function": "^2.0.0",
13942
+
"is-date-object": "^1.1.0",
13943
+
"is-finalizationregistry": "^1.1.0",
13944
+
"is-generator-function": "^1.0.10",
13945
+
"is-regex": "^1.2.1",
13946
+
"is-weakref": "^1.0.2",
13947
+
"isarray": "^2.0.5",
13948
+
"which-boxed-primitive": "^1.1.0",
13949
+
"which-collection": "^1.0.2",
13950
+
"which-typed-array": "^1.1.16"
13951
+
},
13952
+
"engines": {
13953
+
"node": ">= 0.4"
13954
+
},
13955
+
"funding": {
13956
+
"url": "https://github.com/sponsors/ljharb"
13957
+
}
13958
+
},
13959
+
"node_modules/which-collection": {
13960
+
"version": "1.0.2",
13961
+
"resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
13962
+
"integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
13963
+
"dev": true,
13964
+
"license": "MIT",
13965
+
"dependencies": {
13966
+
"is-map": "^2.0.3",
13967
+
"is-set": "^2.0.3",
13968
+
"is-weakmap": "^2.0.2",
13969
+
"is-weakset": "^2.0.3"
13970
+
},
13971
+
"engines": {
13972
+
"node": ">= 0.4"
13973
+
},
13974
+
"funding": {
13975
+
"url": "https://github.com/sponsors/ljharb"
13976
+
}
13977
+
},
13978
+
"node_modules/which-typed-array": {
13979
+
"version": "1.1.19",
13980
+
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
13981
+
"integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
13982
+
"dev": true,
13983
+
"license": "MIT",
13984
+
"dependencies": {
13985
+
"available-typed-arrays": "^1.0.7",
13986
+
"call-bind": "^1.0.8",
13987
+
"call-bound": "^1.0.4",
13988
+
"for-each": "^0.3.5",
13989
+
"get-proto": "^1.0.1",
13990
+
"gopd": "^1.2.0",
13991
+
"has-tostringtag": "^1.0.2"
13992
+
},
13993
+
"engines": {
13994
+
"node": ">= 0.4"
13995
+
},
13996
+
"funding": {
13997
+
"url": "https://github.com/sponsors/ljharb"
13998
+
}
13999
+
},
14000
"node_modules/why-is-node-running": {
14001
"version": "2.3.0",
14002
"resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
···
14023
"super-media-element": "~1.4.2"
14024
}
14025
},
14026
+
"node_modules/word-wrap": {
14027
+
"version": "1.2.5",
14028
+
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
14029
+
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
14030
+
"dev": true,
14031
+
"license": "MIT",
14032
+
"peer": true,
14033
+
"engines": {
14034
+
"node": ">=0.10.0"
14035
+
}
14036
+
},
14037
"node_modules/ws": {
14038
"version": "8.18.3",
14039
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
···
14078
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
14079
"license": "ISC"
14080
},
14081
+
"node_modules/yocto-queue": {
14082
+
"version": "0.1.0",
14083
+
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
14084
+
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
14085
+
"dev": true,
14086
+
"license": "MIT",
14087
+
"peer": true,
14088
+
"engines": {
14089
+
"node": ">=10"
14090
+
},
14091
+
"funding": {
14092
+
"url": "https://github.com/sponsors/sindresorhus"
14093
+
}
14094
+
},
14095
"node_modules/youtube-video-element": {
14096
"version": "1.6.2",
14097
"resolved": "https://registry.npmjs.org/youtube-video-element/-/youtube-video-element-1.6.2.tgz",
···
14105
"license": "MIT",
14106
"funding": {
14107
"url": "https://github.com/sponsors/colinhacks"
14108
+
}
14109
+
},
14110
+
"node_modules/zod-validation-error": {
14111
+
"version": "4.0.2",
14112
+
"resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
14113
+
"integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
14114
+
"dev": true,
14115
+
"license": "MIT",
14116
+
"engines": {
14117
+
"node": ">=18.0.0"
14118
+
},
14119
+
"peerDependencies": {
14120
+
"zod": "^3.25.0 || ^4.0.0"
14121
}
14122
}
14123
}
+32
-3
package.json
+32
-3
package.json
···
3
"private": true,
4
"type": "module",
5
"scripts": {
6
-
"dev": "vite --port 3000",
7
-
"start": "vite --port 3000",
8
"build": "vite build && tsc",
9
"serve": "vite preview",
10
"test": "vitest run"
11
},
12
"dependencies": {
13
"@atproto/api": "^0.16.6",
14
"@tailwindcss/vite": "^4.0.6",
15
"@tanstack/react-devtools": "^0.2.2",
16
"@tanstack/react-query": "^5.85.6",
17
"@tanstack/react-router": "^1.130.2",
18
"@tanstack/react-router-devtools": "^1.131.5",
19
"@tanstack/router-plugin": "^1.121.2",
20
"idb-keyval": "^6.2.2",
21
"jotai": "^2.13.1",
22
"react": "^19.0.0",
23
"react-dom": "^19.0.0",
24
"react-player": "^3.3.2",
25
-
"tailwindcss": "^4.0.6"
26
},
27
"devDependencies": {
28
"@testing-library/dom": "^10.4.0",
29
"@testing-library/react": "^16.2.0",
30
"@types/node": "^24.3.0",
31
"@types/react": "^19.0.8",
32
"@types/react-dom": "^19.0.3",
33
"@vitejs/plugin-react": "^4.3.4",
34
"jsdom": "^26.0.0",
35
"prettier": "^3.6.2",
36
"typescript": "^5.7.2",
37
"vite": "^6.3.5",
38
"vitest": "^3.0.5",
39
"web-vitals": "^4.2.4"
···
3
"private": true,
4
"type": "module",
5
"scripts": {
6
+
"dev": "vite --port 3768",
7
+
"start": "vite --port 3768",
8
"build": "vite build && tsc",
9
"serve": "vite preview",
10
"test": "vitest run"
11
},
12
"dependencies": {
13
"@atproto/api": "^0.16.6",
14
+
"@atproto/oauth-client-browser": "^0.3.33",
15
+
"@radix-ui/react-dialog": "^1.1.15",
16
+
"@radix-ui/react-dropdown-menu": "^2.1.16",
17
+
"@radix-ui/react-hover-card": "^1.1.15",
18
+
"@radix-ui/react-slider": "^1.3.6",
19
"@tailwindcss/vite": "^4.0.6",
20
+
"@tanstack/query-sync-storage-persister": "^5.85.6",
21
"@tanstack/react-devtools": "^0.2.2",
22
"@tanstack/react-query": "^5.85.6",
23
+
"@tanstack/react-query-persist-client": "^5.85.6",
24
"@tanstack/react-router": "^1.130.2",
25
"@tanstack/react-router-devtools": "^1.131.5",
26
"@tanstack/router-plugin": "^1.121.2",
27
+
"dompurify": "^3.3.0",
28
+
"i": "^0.3.7",
29
"idb-keyval": "^6.2.2",
30
"jotai": "^2.13.1",
31
+
"npm": "^11.6.2",
32
+
"radix-ui": "^1.4.3",
33
"react": "^19.0.0",
34
"react-dom": "^19.0.0",
35
"react-player": "^3.3.2",
36
+
"tailwindcss": "^4.0.6",
37
+
"tanstack-router-keepalive": "^1.0.0"
38
},
39
"devDependencies": {
40
+
"@eslint-react/eslint-plugin": "^2.2.1",
41
+
"@iconify-icon/react": "^3.0.1",
42
+
"@iconify-json/material-symbols": "^1.2.42",
43
+
"@iconify-json/mdi": "^1.2.3",
44
+
"@iconify/json": "^2.2.396",
45
+
"@svgr/core": "^8.1.0",
46
+
"@svgr/plugin-jsx": "^8.1.0",
47
"@testing-library/dom": "^10.4.0",
48
"@testing-library/react": "^16.2.0",
49
"@types/node": "^24.3.0",
50
"@types/react": "^19.0.8",
51
"@types/react-dom": "^19.0.3",
52
+
"@typescript-eslint/eslint-plugin": "^8.46.1",
53
+
"@typescript-eslint/parser": "^8.46.1",
54
"@vitejs/plugin-react": "^4.3.4",
55
+
"babel-plugin-react-compiler": "^1.0.0",
56
+
"eslint-plugin-react": "^7.37.5",
57
+
"eslint-plugin-react-hooks": "^7.0.0",
58
+
"eslint-plugin-simple-import-sort": "^12.1.1",
59
+
"eslint-plugin-unused-imports": "^4.2.0",
60
"jsdom": "^26.0.0",
61
"prettier": "^3.6.2",
62
"typescript": "^5.7.2",
63
+
"typescript-eslint": "^8.46.1",
64
+
"unplugin-auto-import": "^20.2.0",
65
+
"unplugin-icons": "^22.4.2",
66
"vite": "^6.3.5",
67
"vitest": "^3.0.5",
68
"web-vitals": "^4.2.4"
+2
-2
public/manifest.json
+2
-2
public/manifest.json
public/screenshot.jpg
public/screenshot.jpg
This is a binary file and will not be displayed.
public/screenshot.png
public/screenshot.png
This is a binary file and will not be displayed.
+22
src/auto-imports.d.ts
+22
src/auto-imports.d.ts
···
···
1
+
/* eslint-disable */
2
+
/* prettier-ignore */
3
+
// @ts-nocheck
4
+
// noinspection JSUnusedGlobalSymbols
5
+
// Generated by unplugin-auto-import
6
+
// biome-ignore lint: disable
7
+
export {}
8
+
declare global {
9
+
const IconMaterialSymbolsAccountCircle: typeof import('~icons/material-symbols/account-circle.jsx').default
10
+
const IconMaterialSymbolsAccountCircleOutline: typeof import('~icons/material-symbols/account-circle-outline.jsx').default
11
+
const IconMaterialSymbolsArrowBack: typeof import('~icons/material-symbols/arrow-back.jsx').default
12
+
const IconMaterialSymbolsHome: typeof import('~icons/material-symbols/home.jsx').default
13
+
const IconMaterialSymbolsHomeOutline: typeof import('~icons/material-symbols/home-outline.jsx').default
14
+
const IconMaterialSymbolsNotifications: typeof import('~icons/material-symbols/notifications.jsx').default
15
+
const IconMaterialSymbolsNotificationsOutline: typeof import('~icons/material-symbols/notifications-outline.jsx').default
16
+
const IconMaterialSymbolsSearch: typeof import('~icons/material-symbols/search.jsx').default
17
+
const IconMaterialSymbolsSettings: typeof import('~icons/material-symbols/settings.jsx').default
18
+
const IconMaterialSymbolsSettingsOutline: typeof import('~icons/material-symbols/settings-outline.jsx').default
19
+
const IconMaterialSymbolsTag: typeof import('~icons/material-symbols/tag.jsx').default
20
+
const IconMdiAccountCircle: typeof import('~icons/mdi/account-circle.jsx').default
21
+
const IconMdiPencilOutline: typeof import('~icons/mdi/pencil-outline.jsx').default
22
+
}
+339
src/components/Composer.tsx
+339
src/components/Composer.tsx
···
···
1
+
import { AppBskyRichtextFacet, RichText } from "@atproto/api";
2
+
import { useAtom } from "jotai";
3
+
import { Dialog } from "radix-ui";
4
+
import { useEffect, useRef, useState } from "react";
5
+
6
+
import { useAuth } from "~/providers/UnifiedAuthProvider";
7
+
import { composerAtom } from "~/utils/atoms";
8
+
import { useQueryPost } from "~/utils/useQuery";
9
+
10
+
import { ProfileThing } from "./Login";
11
+
import { Button } from "./radix-m3-rd/Button";
12
+
import { UniversalPostRendererATURILoader } from "./UniversalPostRenderer";
13
+
14
+
const MAX_POST_LENGTH = 300;
15
+
16
+
export function Composer() {
17
+
const [composerState, setComposerState] = useAtom(composerAtom);
18
+
const [closeConfirmState, setCloseConfirmState] = useState<boolean>(false);
19
+
const { agent } = useAuth();
20
+
21
+
const [postText, setPostText] = useState("");
22
+
const [posting, setPosting] = useState(false);
23
+
const [postSuccess, setPostSuccess] = useState(false);
24
+
const [postError, setPostError] = useState<string | null>(null);
25
+
26
+
useEffect(() => {
27
+
setPostText("");
28
+
setPosting(false);
29
+
setPostSuccess(false);
30
+
setPostError(null);
31
+
}, [composerState.kind]);
32
+
33
+
const parentUri =
34
+
composerState.kind === "reply"
35
+
? composerState.parent
36
+
: composerState.kind === "quote"
37
+
? composerState.subject
38
+
: undefined;
39
+
40
+
const { data: parentPost, isLoading: isParentLoading } =
41
+
useQueryPost(parentUri);
42
+
43
+
async function handlePost() {
44
+
if (!agent || !postText.trim() || postText.length > MAX_POST_LENGTH) return;
45
+
46
+
setPosting(true);
47
+
setPostError(null);
48
+
49
+
try {
50
+
const rt = new RichText({ text: postText });
51
+
await rt.detectFacets(agent);
52
+
53
+
if (rt.facets?.length) {
54
+
rt.facets = rt.facets.filter((item) => {
55
+
if (item.$type !== "app.bsky.richtext.facet") return true;
56
+
if (!item.features?.length) return true;
57
+
58
+
item.features = item.features.filter((feature) => {
59
+
if (feature.$type !== "app.bsky.richtext.facet#mention") return true;
60
+
const did = feature.$type === "app.bsky.richtext.facet#mention" ? (feature as AppBskyRichtextFacet.Mention)?.did : undefined;
61
+
return typeof did === "string" && did.startsWith("did:");
62
+
});
63
+
64
+
return item.features.length > 0;
65
+
});
66
+
}
67
+
68
+
const record: Record<string, unknown> = {
69
+
$type: "app.bsky.feed.post",
70
+
text: rt.text,
71
+
facets: rt.facets,
72
+
createdAt: new Date().toISOString(),
73
+
};
74
+
75
+
if (composerState.kind === "reply" && parentPost) {
76
+
record.reply = {
77
+
root: parentPost.value?.reply?.root ?? {
78
+
uri: parentPost.uri,
79
+
cid: parentPost.cid,
80
+
},
81
+
parent: {
82
+
uri: parentPost.uri,
83
+
cid: parentPost.cid,
84
+
},
85
+
};
86
+
}
87
+
88
+
if (composerState.kind === "quote" && parentPost) {
89
+
record.embed = {
90
+
$type: "app.bsky.embed.record",
91
+
record: {
92
+
uri: parentPost.uri,
93
+
cid: parentPost.cid,
94
+
},
95
+
};
96
+
}
97
+
98
+
await agent.com.atproto.repo.createRecord({
99
+
collection: "app.bsky.feed.post",
100
+
repo: agent.assertDid,
101
+
record,
102
+
});
103
+
104
+
setPostSuccess(true);
105
+
setPostText("");
106
+
107
+
setTimeout(() => {
108
+
setPostSuccess(false);
109
+
setComposerState({ kind: "closed" });
110
+
}, 1500);
111
+
} catch (e: any) {
112
+
setPostError(e?.message || "Failed to post");
113
+
} finally {
114
+
setPosting(false);
115
+
}
116
+
}
117
+
118
+
const getPlaceholder = () => {
119
+
switch (composerState.kind) {
120
+
case "reply":
121
+
return "Post your reply";
122
+
case "quote":
123
+
return "Add a comment...";
124
+
case "root":
125
+
default:
126
+
return "What's happening?!";
127
+
}
128
+
};
129
+
130
+
const charsLeft = MAX_POST_LENGTH - postText.length;
131
+
const isPostButtonDisabled =
132
+
posting || !postText.trim() || isParentLoading || charsLeft < 0;
133
+
134
+
function handleAttemptClose() {
135
+
if (postText.trim() && !posting) {
136
+
setCloseConfirmState(true);
137
+
} else {
138
+
setComposerState({ kind: "closed" });
139
+
}
140
+
}
141
+
142
+
function handleConfirmClose() {
143
+
setComposerState({ kind: "closed" });
144
+
setCloseConfirmState(false);
145
+
setPostText("");
146
+
}
147
+
148
+
return (
149
+
<>
150
+
<Dialog.Root
151
+
open={composerState.kind !== "closed"}
152
+
onOpenChange={(open) => {
153
+
if (!open) handleAttemptClose();
154
+
}}
155
+
>
156
+
<Dialog.Portal>
157
+
<Dialog.Overlay className="disablegutter fixed inset-0 z-50 bg-black/40 dark:bg-black/50 data-[state=open]:animate-fadeIn" />
158
+
159
+
<Dialog.Content className="fixed overflow-y-auto gutter inset-0 z-50 flex items-start justify-center pt-10 sm:pt-20 pb-[50dvh] sm:pb-[50dvh]">
160
+
<div className="bg-gray-50 dark:bg-gray-950 border border-gray-200 dark:border-gray-700 rounded-2xl shadow-xl w-full max-w-xl relative mx-4">
161
+
<div className="flex flex-row justify-between p-2">
162
+
<Dialog.Close asChild>
163
+
<button
164
+
className="h-8 w-8 flex items-center justify-center rounded-full text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800"
165
+
disabled={posting}
166
+
aria-label="Close"
167
+
onClick={handleAttemptClose}
168
+
>
169
+
<svg
170
+
xmlns="http://www.w3.org/2000/svg"
171
+
width="20"
172
+
height="20"
173
+
viewBox="0 0 24 24"
174
+
fill="none"
175
+
stroke="currentColor"
176
+
strokeWidth="2.5"
177
+
strokeLinecap="round"
178
+
strokeLinejoin="round"
179
+
>
180
+
<line x1="18" y1="6" x2="6" y2="18"></line>
181
+
<line x1="6" y1="6" x2="18" y2="18"></line>
182
+
</svg>
183
+
</button>
184
+
</Dialog.Close>
185
+
186
+
<div className="flex-1" />
187
+
<div className="flex items-center gap-4">
188
+
<span
189
+
className={`text-sm ${charsLeft < 0 ? "text-red-500" : "text-gray-500"}`}
190
+
>
191
+
{charsLeft}
192
+
</span>
193
+
<Button
194
+
onClick={handlePost}
195
+
disabled={isPostButtonDisabled}
196
+
>
197
+
{posting ? "Posting..." : "Post"}
198
+
</Button>
199
+
</div>
200
+
</div>
201
+
202
+
{postSuccess ? (
203
+
<div className="flex flex-col items-center justify-center py-16">
204
+
<span className="text-gray-500 text-6xl mb-4">โ</span>
205
+
<span className="text-xl font-bold text-black dark:text-white">
206
+
Posted!
207
+
</span>
208
+
</div>
209
+
) : (
210
+
<div className="px-4">
211
+
{composerState.kind === "reply" && (
212
+
<div className="mb-1 -mx-4">
213
+
{isParentLoading ? (
214
+
<div className="text-sm text-gray-500 animate-pulse">
215
+
Loading parent post...
216
+
</div>
217
+
) : parentUri ? (
218
+
<UniversalPostRendererATURILoader
219
+
atUri={parentUri}
220
+
bottomReplyLine
221
+
bottomBorder={false}
222
+
/>
223
+
) : (
224
+
<div className="text-sm text-red-500 rounded-lg border border-red-500/50 p-3">
225
+
Could not load parent post.
226
+
</div>
227
+
)}
228
+
</div>
229
+
)}
230
+
231
+
<div className="flex w-full gap-1 flex-col">
232
+
<ProfileThing agent={agent} large />
233
+
<div className="flex pl-[50px]">
234
+
<AutoGrowTextarea
235
+
className="w-full text-lg bg-transparent focus:outline-none resize-none placeholder:text-gray-500 text-black dark:text-white pb-2"
236
+
rows={5}
237
+
placeholder={getPlaceholder()}
238
+
value={postText}
239
+
onChange={(e) => setPostText(e.target.value)}
240
+
disabled={posting}
241
+
autoFocus
242
+
/>
243
+
</div>
244
+
</div>
245
+
246
+
{composerState.kind === "quote" && (
247
+
<div className="mb-4 ml-[50px] rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden">
248
+
{isParentLoading ? (
249
+
<div className="text-sm text-gray-500 animate-pulse">
250
+
Loading parent post...
251
+
</div>
252
+
) : parentUri ? (
253
+
<UniversalPostRendererATURILoader
254
+
atUri={parentUri}
255
+
isQuote
256
+
/>
257
+
) : (
258
+
<div className="text-sm text-red-500 rounded-lg border border-red-500/50 p-3">
259
+
Could not load parent post.
260
+
</div>
261
+
)}
262
+
</div>
263
+
)}
264
+
265
+
{postError && (
266
+
<div className="text-red-500 text-sm my-2 text-center">
267
+
{postError}
268
+
</div>
269
+
)}
270
+
</div>
271
+
)}
272
+
</div>
273
+
</Dialog.Content>
274
+
</Dialog.Portal>
275
+
</Dialog.Root>
276
+
277
+
{/* Close confirmation dialog */}
278
+
<Dialog.Root open={closeConfirmState} onOpenChange={setCloseConfirmState}>
279
+
<Dialog.Portal>
280
+
281
+
<Dialog.Overlay className="disablegutter fixed inset-0 z-50 bg-black/40 dark:bg-black/50 data-[state=open]:animate-fadeIn" />
282
+
283
+
<Dialog.Content className="fixed gutter inset-0 z-50 flex items-start justify-center pt-30 sm:pt-40">
284
+
<div className="bg-gray-50 dark:bg-gray-950 border border-gray-200 dark:border-gray-700 rounded-2xl shadow-xl w-full max-w-md relative mx-4 py-6">
285
+
<div className="text-xl mb-4 text-center">
286
+
Discard your post?
287
+
</div>
288
+
<div className="text-md mb-4 text-center">
289
+
You will lose your draft
290
+
</div>
291
+
<div className="flex justify-end gap-2 px-6">
292
+
<Button
293
+
onClick={handleConfirmClose}
294
+
>
295
+
Discard
296
+
</Button>
297
+
<Button
298
+
variant={"outlined"}
299
+
onClick={() => setCloseConfirmState(false)}
300
+
>
301
+
Cancel
302
+
</Button>
303
+
</div>
304
+
</div>
305
+
</Dialog.Content>
306
+
</Dialog.Portal>
307
+
</Dialog.Root>
308
+
</>
309
+
);
310
+
}
311
+
312
+
function AutoGrowTextarea({
313
+
value,
314
+
className,
315
+
onChange,
316
+
...props
317
+
}: React.DetailedHTMLProps<
318
+
React.TextareaHTMLAttributes<HTMLTextAreaElement>,
319
+
HTMLTextAreaElement
320
+
>) {
321
+
const ref = useRef<HTMLTextAreaElement>(null);
322
+
323
+
useEffect(() => {
324
+
const el = ref.current;
325
+
if (!el) return;
326
+
el.style.height = "auto";
327
+
el.style.height = el.scrollHeight + "px";
328
+
}, [value]);
329
+
330
+
return (
331
+
<textarea
332
+
ref={ref}
333
+
className={className}
334
+
value={value}
335
+
onChange={onChange}
336
+
{...props}
337
+
/>
338
+
);
339
+
}
+33
src/components/Header.tsx
+33
src/components/Header.tsx
···
···
1
+
import { Link, useRouter } from "@tanstack/react-router";
2
+
import { useAtom } from "jotai";
3
+
4
+
import { isAtTopAtom } from "~/utils/atoms";
5
+
6
+
export function Header({
7
+
backButtonCallback,
8
+
title
9
+
}: {
10
+
backButtonCallback?: () => void;
11
+
title?: string;
12
+
}) {
13
+
const router = useRouter();
14
+
const [isAtTop] = useAtom(isAtTopAtom);
15
+
//const what = router.history.
16
+
return (
17
+
<div className={`flex items-center gap-3 px-3 py-3 h-[52px] sticky top-0 bg-[var(--header-bg-light)] dark:bg-[var(--header-bg-dark)] z-10 border-0 sm:border-b ${!isAtTop && "shadow-sm"} sm:shadow-none sm:dark:bg-gray-950 sm:bg-white border-gray-200 dark:border-gray-700`}>
18
+
{backButtonCallback ? (<Link
19
+
to=".."
20
+
//className="px-3 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-900 font-bold text-lg"
21
+
className="p-2 rounded-full hover:bg-gray-100 dark:hover:bg-gray-900 font-bold text-lg"
22
+
onClick={(e) => {
23
+
e.preventDefault();
24
+
backButtonCallback();
25
+
}}
26
+
aria-label="Go back"
27
+
>
28
+
<IconMaterialSymbolsArrowBack className="w-6 h-6" />
29
+
</Link>) : (<div className="w-[0px]" />)}
30
+
<span className="text-[21px] sm:text-[19px] sm:font-semibold font-roboto">{title}</span>
31
+
</div>
32
+
);
33
+
}
+150
src/components/Import.tsx
+150
src/components/Import.tsx
···
···
1
+
import { AtUri } from "@atproto/api";
2
+
import { useNavigate, type UseNavigateResult } from "@tanstack/react-router";
3
+
import { useState } from "react";
4
+
5
+
/**
6
+
* Basically the best equivalent to Search that i can do
7
+
*/
8
+
export function Import() {
9
+
const [textInput, setTextInput] = useState<string | undefined>();
10
+
const navigate = useNavigate();
11
+
12
+
const handleEnter = () => {
13
+
if (!textInput) return;
14
+
handleImport({
15
+
text: textInput,
16
+
navigate,
17
+
});
18
+
};
19
+
20
+
return (
21
+
<div className="w-full relative">
22
+
<IconMaterialSymbolsSearch className="w-5 h-5 absolute left-4 top-1/2 -translate-y-1/2 text-gray-400 dark:text-gray-500" />
23
+
24
+
<input
25
+
type="text"
26
+
placeholder="Import..."
27
+
value={textInput}
28
+
onChange={(e) => setTextInput(e.target.value)}
29
+
onKeyDown={(e) => {
30
+
if (e.key === "Enter") handleEnter();
31
+
}}
32
+
className="w-full h-12 pl-12 pr-4 rounded-full bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-gray-400 dark:focus:ring-gray-500 box-border transition"
33
+
/>
34
+
</div>
35
+
);
36
+
}
37
+
38
+
function handleImport({
39
+
text,
40
+
navigate,
41
+
}: {
42
+
text: string;
43
+
navigate: UseNavigateResult<string>;
44
+
}) {
45
+
const trimmed = text.trim();
46
+
// parse text
47
+
/**
48
+
* text might be
49
+
* 1. bsky dot app url (reddwarf link segments might be uri encoded,)
50
+
* 2. aturi
51
+
* 3. plain handle
52
+
* 4. plain did
53
+
*/
54
+
55
+
// 1. Check if itโs a URL
56
+
try {
57
+
const url = new URL(text);
58
+
const knownHosts = [
59
+
"bsky.app",
60
+
"social.daniela.lol",
61
+
"deer.social",
62
+
"reddwarf.whey.party",
63
+
"reddwarf.app",
64
+
"main.bsky.dev",
65
+
"catsky.social",
66
+
"blacksky.community",
67
+
"red-dwarf-social-app.whey.party",
68
+
"zeppelin.social",
69
+
];
70
+
if (knownHosts.includes(url.hostname)) {
71
+
// parse path to get URI or handle
72
+
const path = decodeURIComponent(url.pathname.slice(1)); // remove leading /
73
+
console.log("BSky URL path:", path);
74
+
navigate({
75
+
to: `/${path}`,
76
+
});
77
+
return;
78
+
}
79
+
} catch {
80
+
// not a URL, continue
81
+
}
82
+
83
+
// 2. Check if text looks like an at-uri
84
+
try {
85
+
if (text.startsWith("at://")) {
86
+
console.log("AT URI detected:", text);
87
+
const aturi = new AtUri(text);
88
+
switch (aturi.collection) {
89
+
case "app.bsky.feed.post": {
90
+
navigate({
91
+
to: "/profile/$did/post/$rkey",
92
+
params: {
93
+
did: aturi.host,
94
+
rkey: aturi.rkey,
95
+
},
96
+
});
97
+
return;
98
+
}
99
+
case "app.bsky.actor.profile": {
100
+
navigate({
101
+
to: "/profile/$did",
102
+
params: {
103
+
did: aturi.host,
104
+
},
105
+
});
106
+
return;
107
+
}
108
+
// todo add more handlers as more routes are added. like feeds, lists, etc etc thanks!
109
+
default: {
110
+
// continue
111
+
}
112
+
}
113
+
}
114
+
} catch {
115
+
// continue
116
+
}
117
+
118
+
// 3. Plain handle (starts with @)
119
+
try {
120
+
if (text.startsWith("@")) {
121
+
const handle = text.slice(1);
122
+
console.log("Handle detected:", handle);
123
+
navigate({ to: "/profile/$did", params: { did: handle } });
124
+
return;
125
+
}
126
+
} catch {
127
+
// continue
128
+
}
129
+
130
+
// 4. Plain DID (starts with did:)
131
+
try {
132
+
if (text.startsWith("did:")) {
133
+
console.log("did detected:", text);
134
+
navigate({ to: "/profile/$did", params: { did: text } });
135
+
return;
136
+
}
137
+
} catch {
138
+
// continue
139
+
}
140
+
141
+
// if all else fails
142
+
143
+
// try {
144
+
// // probably a user?
145
+
// navigate({ to: "/profile/$did", params: { did: text } });
146
+
// return;
147
+
// } catch {
148
+
// // continue
149
+
// }
150
+
}
+100
-13
src/components/InfiniteCustomFeed.tsx
+100
-13
src/components/InfiniteCustomFeed.tsx
···
1
import * as React from "react";
2
//import { useInView } from "react-intersection-observer";
3
import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer";
4
-
import { useAuth } from "~/providers/PassAuthProvider";
5
-
import { useQueryArbitrary, useQueryIdentity, useInfiniteQueryFeedSkeleton } from "~/utils/useQuery";
6
7
interface InfiniteCustomFeedProps {
8
feedUri: string;
···
10
feedServiceDid?: string;
11
}
12
13
-
export function InfiniteCustomFeed({ feedUri, pdsUrl, feedServiceDid }: InfiniteCustomFeedProps) {
14
-
const { agent, authed } = useAuth();
15
-
16
// const identityresultmaybe = useQueryIdentity(agent?.did);
17
// const identity = identityresultmaybe?.data;
18
// const feedGenGetRecordQuery = useQueryArbitrary(feedUri);
···
25
hasNextPage,
26
fetchNextPage,
27
isFetchingNextPage,
28
} = useInfiniteQueryFeedSkeleton({
29
feedUri: feedUri,
30
agent: agent ?? undefined,
···
32
pdsUrl: pdsUrl,
33
feedServiceDid: feedServiceDid,
34
});
35
36
//const { ref, inView } = useInView();
37
···
46
}
47
48
if (isError) {
49
-
return <div className="p-4 text-center text-red-500">Error: {error.message}</div>;
50
}
51
52
-
const allPosts = data?.pages.flatMap((page) => {if (page) return page.feed}) ?? [];
53
54
if (!allPosts || typeof allPosts !== "object" || allPosts.length === 0) {
55
-
return <div className="p-4 text-center text-gray-500">No posts in this feed.</div>;
56
}
57
58
return (
59
<>
60
{allPosts.map((item, i) => {
61
-
if (item) return (
62
-
<UniversalPostRendererATURILoader key={item.post || i} atUri={item.post} />
63
-
)})}
64
{/* allPosts?: {allPosts ? "true" : "false"}
65
hasNextPage?: {hasNextPage ? "true" : "false"}
66
isFetchingNextPage?: {isFetchingNextPage ? "true" : "false"} */}
···
75
Load More Posts
76
</button>
77
)}
78
-
{!hasNextPage && <div className="p-4 text-center text-gray-500">End of feed.</div>}
79
</>
80
);
81
-
}
···
1
+
import { useQueryClient } from "@tanstack/react-query";
2
import * as React from "react";
3
+
4
//import { useInView } from "react-intersection-observer";
5
import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer";
6
+
import { useAuth } from "~/providers/UnifiedAuthProvider";
7
+
import {
8
+
useInfiniteQueryFeedSkeleton,
9
+
// useQueryArbitrary,
10
+
// useQueryIdentity,
11
+
} from "~/utils/useQuery";
12
13
interface InfiniteCustomFeedProps {
14
feedUri: string;
···
16
feedServiceDid?: string;
17
}
18
19
+
export function InfiniteCustomFeed({
20
+
feedUri,
21
+
pdsUrl,
22
+
feedServiceDid,
23
+
}: InfiniteCustomFeedProps) {
24
+
const { agent } = useAuth();
25
+
const authed = !!agent?.did;
26
+
27
// const identityresultmaybe = useQueryIdentity(agent?.did);
28
// const identity = identityresultmaybe?.data;
29
// const feedGenGetRecordQuery = useQueryArbitrary(feedUri);
···
36
hasNextPage,
37
fetchNextPage,
38
isFetchingNextPage,
39
+
refetch,
40
+
isRefetching,
41
+
queryKey,
42
} = useInfiniteQueryFeedSkeleton({
43
feedUri: feedUri,
44
agent: agent ?? undefined,
···
46
pdsUrl: pdsUrl,
47
feedServiceDid: feedServiceDid,
48
});
49
+
const queryClient = useQueryClient();
50
+
51
+
52
+
const handleRefresh = () => {
53
+
queryClient.removeQueries({queryKey: queryKey});
54
+
//queryClient.invalidateQueries(["infinite-feed", feedUri] as const);
55
+
refetch();
56
+
};
57
+
58
+
const allPosts = React.useMemo(() => {
59
+
const flattenedPosts = data?.pages.flatMap((page) => page?.feed) ?? [];
60
+
61
+
const seenUris = new Set<string>();
62
+
63
+
return flattenedPosts.filter((item) => {
64
+
if (!item?.post) return false;
65
+
66
+
if (seenUris.has(item.post)) {
67
+
return false;
68
+
}
69
+
70
+
seenUris.add(item.post);
71
+
72
+
return true;
73
+
});
74
+
}, [data]);
75
76
//const { ref, inView } = useInView();
77
···
86
}
87
88
if (isError) {
89
+
return (
90
+
<div className="p-4 text-center text-red-500">Error: {error.message}</div>
91
+
);
92
}
93
94
+
// const allPosts =
95
+
// data?.pages.flatMap((page) => {
96
+
// if (page) return page.feed;
97
+
// }) ?? [];
98
99
if (!allPosts || typeof allPosts !== "object" || allPosts.length === 0) {
100
+
return (
101
+
<div className="p-4 text-center text-gray-500">
102
+
No posts in this feed.
103
+
</div>
104
+
);
105
}
106
107
return (
108
<>
109
{allPosts.map((item, i) => {
110
+
if (item)
111
+
return (
112
+
<UniversalPostRendererATURILoader
113
+
key={item.post || i}
114
+
atUri={item.post}
115
+
feedviewpost={true}
116
+
repostedby={!!item.reason?.$type && (item.reason as any)?.repost}
117
+
/>
118
+
);
119
+
})}
120
{/* allPosts?: {allPosts ? "true" : "false"}
121
hasNextPage?: {hasNextPage ? "true" : "false"}
122
isFetchingNextPage?: {isFetchingNextPage ? "true" : "false"} */}
···
131
Load More Posts
132
</button>
133
)}
134
+
{!hasNextPage && (
135
+
<div className="p-4 text-center text-gray-500">End of feed.</div>
136
+
)}
137
+
<button
138
+
onClick={handleRefresh}
139
+
disabled={isRefetching}
140
+
className="sticky lg:bottom-4 bottom-22 ml-4 w-[42px] h-[42px] z-10 bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 text-gray-50 p-[9px] rounded-full shadow-lg transition-transform duration-200 ease-in-out hover:scale-110 disabled:dark:bg-gray-900 disabled:bg-gray-100 disabled:cursor-not-allowed"
141
+
aria-label="Refresh feed"
142
+
>
143
+
<RefreshIcon
144
+
className={`h-6 w-6 text-gray-600 dark:text-gray-400 ${isRefetching && "animate-spin"}`}
145
+
/>
146
+
</button>
147
</>
148
);
149
+
}
150
+
151
+
const RefreshIcon = (props: React.SVGProps<SVGSVGElement>) => (
152
+
<svg
153
+
xmlns="http://www.w3.org/2000/svg"
154
+
//width={360}
155
+
//height={360}
156
+
viewBox="0 0 24 24"
157
+
{...props}
158
+
>
159
+
<path
160
+
fill="none"
161
+
stroke="currentColor"
162
+
strokeLinecap="round"
163
+
strokeLinejoin="round"
164
+
strokeWidth={2}
165
+
d="M20 11A8.1 8.1 0 0 0 4.5 9M4 5v4h4m-4 4a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4"
166
+
></path>
167
+
</svg>
168
+
);
+326
-170
src/components/Login.tsx
+326
-170
src/components/Login.tsx
···
1
-
import React, { useEffect, useState, useRef } from "react";
2
-
import { useAuth } from "~/providers/PassAuthProvider";
3
4
-
interface LoginProps {
5
compact?: boolean;
6
}
7
8
-
export default function Login({ compact = false }: LoginProps) {
9
-
const { loginStatus, login, logout, loading, authed } = useAuth();
10
-
const [user, setUser] = useState("");
11
-
const [password, setPassword] = useState("");
12
-
const [serviceURL, setServiceURL] = useState("bsky.social");
13
-
const [showLoginForm, setShowLoginForm] = useState(false);
14
const formRef = useRef<HTMLDivElement>(null);
15
16
useEffect(() => {
17
function handleClickOutside(event: MouseEvent) {
18
if (formRef.current && !formRef.current.contains(event.target as Node)) {
19
-
setShowLoginForm(false);
20
}
21
}
22
-
23
-
if (showLoginForm) {
24
document.addEventListener("mousedown", handleClickOutside);
25
}
26
-
27
return () => {
28
document.removeEventListener("mousedown", handleClickOutside);
29
};
30
-
}, [showLoginForm]);
31
32
-
if (loading) {
33
-
return (
34
-
<div className="flex items-center justify-center p-6 text-gray-500 dark:text-gray-400">
35
-
Loading...
36
-
</div>
37
-
);
38
-
}
39
40
-
if (compact) {
41
-
if (authed) {
42
-
return (
43
<button
44
-
onClick={logout}
45
-
className="text-sm bg-gray-600 hover:bg-gray-700 text-white rounded px-3 py-1 font-medium transition-colors"
46
>
47
-
Log out
48
</button>
49
-
);
50
-
} else {
51
-
return (
52
-
<div className="relative" ref={formRef}>
53
-
<button
54
-
onClick={() => setShowLoginForm(!showLoginForm)}
55
-
className="text-sm bg-gray-600 hover:bg-gray-700 text-white rounded px-3 py-1 font-medium transition-colors"
56
-
>
57
-
Log in
58
-
</button>
59
-
{showLoginForm && (
60
-
<div className="absolute top-full right-0 mt-2 w-80 bg-white dark:bg-gray-900 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 p-4 z-50">
61
-
<form
62
-
onSubmit={(e) => {
63
-
e.preventDefault();
64
-
login(user, password, `https://${serviceURL}`);
65
-
setShowLoginForm(false);
66
-
}}
67
-
className="flex flex-col gap-3"
68
-
>
69
-
<p className="text-xs text-gray-500 dark:text-gray-400">
70
-
sorry for the temporary login,
71
-
<br />
72
-
oauth will come soon enough i swear
73
-
</p>
74
-
<input
75
-
type="text"
76
-
placeholder="Username"
77
-
value={user}
78
-
onChange={(e) => setUser(e.target.value)}
79
-
className="px-3 py-2 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
80
-
autoComplete="username"
81
-
/>
82
-
<input
83
-
type="password"
84
-
placeholder="Password"
85
-
value={password}
86
-
onChange={(e) => setPassword(e.target.value)}
87
-
className="px-3 py-2 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
88
-
autoComplete="current-password"
89
-
/>
90
-
<input
91
-
type="text"
92
-
placeholder="bsky.social"
93
-
value={serviceURL}
94
-
onChange={(e) => setServiceURL(e.target.value)}
95
-
className="px-3 py-2 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
96
-
/>
97
-
<button
98
-
type="submit"
99
-
className="bg-gray-600 hover:bg-gray-700 text-white rounded px-4 py-2 font-medium text-sm transition-colors"
100
-
>
101
-
Log in
102
-
</button>
103
-
</form>
104
-
</div>
105
-
)}
106
-
</div>
107
-
);
108
}
109
-
}
110
111
return (
112
-
<div className="p-6 bg-gray-100 dark:bg-gray-900 rounded-xl shadow border border-gray-200 dark:border-gray-800 mt-6 mx-4">
113
-
{authed ? (
114
-
<div className="flex flex-col items-center justify-center text-center">
115
-
<p className="text-lg font-semibold mb-6 text-gray-800 dark:text-gray-100">
116
-
You are logged in!
117
-
</p>
118
-
<button
119
-
onClick={logout}
120
-
className="bg-gray-600 hover:bg-gray-700 text-white rounded px-6 py-2 font-semibold text-base transition-colors"
121
-
>
122
-
Log out
123
-
</button>
124
-
</div>
125
-
) : (
126
-
<form
127
-
onSubmit={(e) => {
128
-
e.preventDefault();
129
-
login(user, password, `https://${serviceURL}`);
130
-
}}
131
-
className="flex flex-col gap-4"
132
-
>
133
-
<p className="text-sm text-gray-500 dark:text-gray-400 mb-2">
134
-
sorry for the temporary login,
135
-
<br />
136
-
oauth will come soon enough i swear
137
-
</p>
138
<input
139
type="text"
140
-
placeholder="Username"
141
value={user}
142
onChange={(e) => setUser(e.target.value)}
143
-
className="px-3 py-2 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-base focus:outline-none focus:ring-2 focus:ring-blue-500"
144
-
autoComplete="username"
145
/>
146
<input
147
-
type="password"
148
-
placeholder="Password"
149
value={password}
150
onChange={(e) => setPassword(e.target.value)}
151
-
className="px-3 py-2 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-base focus:outline-none focus:ring-2 focus:ring-blue-500"
152
-
autoComplete="current-password"
153
/>
154
<input
155
type="text"
156
-
placeholder="bsky.social"
157
value={serviceURL}
158
onChange={(e) => setServiceURL(e.target.value)}
159
-
className="px-3 py-2 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-base focus:outline-none focus:ring-2 focus:ring-blue-500"
160
/>
161
-
<button
162
-
type="submit"
163
-
className="bg-gray-600 hover:bg-gray-700 text-white rounded px-6 py-2 font-semibold text-base transition-colors mt-2"
164
-
>
165
-
Log in
166
-
</button>
167
-
</form>
168
-
)}
169
-
</div>
170
);
171
-
}
172
173
-
export const ProfileThing = () => {
174
-
const { agent, loading, loginStatus, authed } = useAuth();
175
-
const [response, setResponse] = useState<any>(null);
176
177
-
useEffect(() => {
178
-
if (loginStatus && agent && !loading && authed) {
179
-
fetchUser();
180
-
}
181
-
// eslint-disable-next-line
182
-
}, [loginStatus, agent, loading, authed]);
183
-
184
-
const fetchUser = async () => {
185
-
if (!agent) {
186
-
console.error("Agent is null or undefined");
187
-
return;
188
-
}
189
-
const res = await agent.app.bsky.actor.getProfile({
190
-
actor: agent.assertDid,
191
-
});
192
-
setResponse(res.data);
193
-
};
194
195
-
if (!authed) {
196
-
return (
197
-
<div className="inline-block">
198
-
<span className="text-gray-100 text-base font-medium px-1.5">
199
-
Login
200
-
</span>
201
-
</div>
202
-
);
203
}
204
205
-
if (!response) {
206
return (
207
-
<div className="flex flex-col items-start gap-1.5">
208
-
<span className="w-5 h-5 border-2 border-gray-200 dark:border-gray-600 border-t-transparent rounded-full animate-spin inline-block" />
209
-
<span className="text-gray-100">Loading... </span>
210
</div>
211
);
212
}
213
214
return (
215
-
<div className="flex flex-row items-start gap-1.5">
216
<img
217
-
src={response?.avatar}
218
alt="avatar"
219
-
className="w-[30px] h-[30px] rounded-full object-cover"
220
/>
221
-
<div>
222
-
<div className="text-gray-100 text-xs">{response?.displayName}</div>
223
-
<div className="text-gray-100 text-xs">@{response?.handle}</div>
224
</div>
225
</div>
226
);
···
1
+
// src/components/Login.tsx
2
+
import AtpAgent, { Agent } from "@atproto/api";
3
+
import { useAtom } from "jotai";
4
+
import React, { useEffect, useRef, useState } from "react";
5
6
+
import { useAuth } from "~/providers/UnifiedAuthProvider";
7
+
import { imgCDNAtom } from "~/utils/atoms";
8
+
import { useQueryIdentity, useQueryProfile } from "~/utils/useQuery";
9
+
10
+
import { Button } from "./radix-m3-rd/Button";
11
+
12
+
// --- 1. The Main Component (Orchestrator with `compact` prop) ---
13
+
export default function Login({
14
+
compact = false,
15
+
popup = false,
16
+
}: {
17
compact?: boolean;
18
+
popup?: boolean;
19
+
}) {
20
+
const { status, agent, logout } = useAuth();
21
+
22
+
// Loading state can be styled differently based on the prop
23
+
if (status === "loading") {
24
+
return (
25
+
<div
26
+
className={
27
+
compact
28
+
? "flex items-center justify-center p-1"
29
+
: "p-6 bg-gray-100 dark:bg-gray-900 rounded-xl shadow border border-gray-200 dark:border-gray-800 mt-4 mx-4 flex justify-center items-center h-[280px]"
30
+
}
31
+
>
32
+
<span
33
+
className={`border-t-transparent rounded-full animate-spin ${
34
+
compact
35
+
? "w-5 h-5 border-2 border-gray-400"
36
+
: "w-8 h-8 border-4 border-gray-400"
37
+
}`}
38
+
/>
39
+
</div>
40
+
);
41
+
}
42
+
43
+
// --- LOGGED IN STATE ---
44
+
if (status === "signedIn") {
45
+
// Large view
46
+
if (!compact) {
47
+
return (
48
+
<div className="p-4 bg-gray-100 dark:bg-gray-900 rounded-xl border-gray-200 dark:border-gray-800 mt-4 mx-4">
49
+
<div className="flex flex-col items-center justify-center text-center">
50
+
<p className="text-lg font-semibold mb-4 text-gray-800 dark:text-gray-100">
51
+
You are logged in!
52
+
</p>
53
+
<ProfileThing agent={agent} large />
54
+
<Button
55
+
onClick={logout}
56
+
className="mt-4"
57
+
>
58
+
Log out
59
+
</Button>
60
+
</div>
61
+
</div>
62
+
);
63
+
}
64
+
// Compact view
65
+
return (
66
+
<div className="flex items-center gap-4">
67
+
<ProfileThing agent={agent} />
68
+
<button
69
+
onClick={logout}
70
+
className="text-sm bg-gray-600 hover:bg-gray-700 text-white rounded px-3 py-1 font-medium transition-colors"
71
+
>
72
+
Log out
73
+
</button>
74
+
</div>
75
+
);
76
+
}
77
+
78
+
// --- LOGGED OUT STATE ---
79
+
if (!compact) {
80
+
// Large view renders the form directly in the card
81
+
return (
82
+
<div className="p-4 bg-gray-100 dark:bg-gray-900 rounded-xl border-gray-200 dark:border-gray-800 mt-4 mx-4">
83
+
<UnifiedLoginForm />
84
+
</div>
85
+
);
86
+
}
87
+
88
+
// Compact view renders a button that toggles the form in a dropdown
89
+
return <CompactLoginButton popup={popup} />;
90
}
91
92
+
// --- 2. The Reusable, Self-Contained Login Form Component ---
93
+
export function UnifiedLoginForm() {
94
+
const [mode, setMode] = useState<"oauth" | "password">("oauth");
95
+
96
+
return (
97
+
<div>
98
+
<div className="flex bg-gray-300 rounded-full dark:bg-gray-700 mb-4">
99
+
<TabButton
100
+
label="OAuth"
101
+
active={mode === "oauth"}
102
+
onClick={() => setMode("oauth")}
103
+
/>
104
+
<TabButton
105
+
label="Password"
106
+
active={mode === "password"}
107
+
onClick={() => setMode("password")}
108
+
/>
109
+
</div>
110
+
{mode === "oauth" ? <OAuthForm /> : <PasswordForm />}
111
+
</div>
112
+
);
113
+
}
114
+
115
+
// --- 3. Helper components for layouts, forms, and UI ---
116
+
117
+
// A new component to contain the logic for the compact dropdown
118
+
const CompactLoginButton = ({ popup }: { popup?: boolean }) => {
119
+
const [showForm, setShowForm] = useState(false);
120
const formRef = useRef<HTMLDivElement>(null);
121
122
useEffect(() => {
123
function handleClickOutside(event: MouseEvent) {
124
if (formRef.current && !formRef.current.contains(event.target as Node)) {
125
+
setShowForm(false);
126
}
127
}
128
+
if (showForm) {
129
document.addEventListener("mousedown", handleClickOutside);
130
}
131
return () => {
132
document.removeEventListener("mousedown", handleClickOutside);
133
};
134
+
}, [showForm]);
135
136
+
return (
137
+
<div className="relative" ref={formRef}>
138
+
<button
139
+
onClick={() => setShowForm(!showForm)}
140
+
className="text-sm bg-gray-600 hover:bg-gray-700 text-white rounded-full px-3 py-1 font-medium transition-colors"
141
+
>
142
+
Log in
143
+
</button>
144
+
{showForm && (
145
+
<div
146
+
className={`absolute ${popup ? `bottom-[calc(100%)]` : `top-full`} right-0 mt-2 w-80 bg-white dark:bg-gray-900 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 p-4 z-50`}
147
+
>
148
+
<UnifiedLoginForm />
149
+
</div>
150
+
)}
151
+
</div>
152
+
);
153
+
};
154
155
+
const TabButton = ({
156
+
label,
157
+
active,
158
+
onClick,
159
+
}: {
160
+
label: string;
161
+
active: boolean;
162
+
onClick: () => void;
163
+
}) => (
164
+
<button
165
+
onClick={onClick}
166
+
className={`px-4 py-2 text-sm font-medium transition-colors rounded-full flex-1 ${
167
+
active
168
+
? "text-gray-50 dark:text-gray-200 border-gray-500 bg-gray-400 dark:bg-gray-500"
169
+
: "text-gray-600 dark:text-gray-300 hover:text-gray-700 dark:hover:text-gray-200"
170
+
}`}
171
+
>
172
+
{label}
173
+
</button>
174
+
);
175
+
176
+
const OAuthForm = () => {
177
+
const { loginWithOAuth } = useAuth();
178
+
const [handle, setHandle] = useState("");
179
+
180
+
useEffect(() => {
181
+
const lastHandle = localStorage.getItem("lastHandle");
182
+
if (lastHandle) setHandle(lastHandle);
183
+
}, []);
184
+
185
+
const handleSubmit = (e: React.FormEvent) => {
186
+
e.preventDefault();
187
+
if (handle.trim()) {
188
+
localStorage.setItem("lastHandle", handle);
189
+
loginWithOAuth(handle);
190
+
}
191
+
};
192
+
return (
193
+
<form onSubmit={handleSubmit} className="flex flex-col gap-3">
194
+
<p className="text-xs text-gray-500 dark:text-gray-400">
195
+
Sign in with AT. Your password is never shared.
196
+
</p>
197
+
{/* <input
198
+
type="text"
199
+
placeholder="handle.bsky.social"
200
+
value={handle}
201
+
onChange={(e) => setHandle(e.target.value)}
202
+
className="px-3 py-2 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-gray-500"
203
+
/> */}
204
+
<div className="flex flex-col gap-3">
205
+
<div className="m3input-field m3input-label m3input-border size-md flex-1">
206
+
<input
207
+
type="text"
208
+
placeholder=" "
209
+
value={handle}
210
+
onChange={(e) => setHandle(e.target.value)}
211
+
/>
212
+
<label>AT Handle</label>
213
+
</div>
214
<button
215
+
type="submit"
216
+
className="bg-gray-600 hover:bg-gray-700 text-white rounded-full px-4 py-2 font-medium text-sm transition-colors"
217
>
218
+
Log in
219
</button>
220
+
</div>
221
+
</form>
222
+
);
223
+
};
224
+
225
+
const PasswordForm = () => {
226
+
const { loginWithPassword } = useAuth();
227
+
const [user, setUser] = useState("");
228
+
const [password, setPassword] = useState("");
229
+
const [serviceURL, setServiceURL] = useState("bsky.social");
230
+
const [error, setError] = useState<string | null>(null);
231
+
232
+
useEffect(() => {
233
+
const lastHandle = localStorage.getItem("lastHandle");
234
+
if (lastHandle) setUser(lastHandle);
235
+
}, []);
236
+
237
+
const handleSubmit = async (e: React.FormEvent) => {
238
+
e.preventDefault();
239
+
setError(null);
240
+
try {
241
+
localStorage.setItem("lastHandle", user);
242
+
await loginWithPassword(user, password, `https://${serviceURL}`);
243
+
} catch (err) {
244
+
setError("Login failed. Check your handle and App Password.");
245
}
246
+
};
247
248
return (
249
+
<form onSubmit={handleSubmit} className="flex flex-col gap-3">
250
+
<p className="text-xs text-red-500 dark:text-red-400">
251
+
Warning: Less secure. Use an App Password.
252
+
</p>
253
+
{/* <input
254
+
type="text"
255
+
placeholder="handle.bsky.social"
256
+
value={user}
257
+
onChange={(e) => setUser(e.target.value)}
258
+
className="px-3 py-2 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-gray-500"
259
+
autoComplete="username"
260
+
/>
261
+
<input
262
+
type="password"
263
+
placeholder="App Password"
264
+
value={password}
265
+
onChange={(e) => setPassword(e.target.value)}
266
+
className="px-3 py-2 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-gray-500"
267
+
autoComplete="current-password"
268
+
/>
269
+
<input
270
+
type="text"
271
+
placeholder="PDS (e.g., bsky.social)"
272
+
value={serviceURL}
273
+
onChange={(e) => setServiceURL(e.target.value)}
274
+
className="px-3 py-2 rounded border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-gray-500"
275
+
/> */}
276
+
<div className="m3input-field m3input-label m3input-border size-md flex-1">
277
<input
278
type="text"
279
+
placeholder=" "
280
value={user}
281
onChange={(e) => setUser(e.target.value)}
282
/>
283
+
<label>AT Handle</label>
284
+
</div>
285
+
<div className="m3input-field m3input-label m3input-border size-md flex-1">
286
<input
287
+
type="text"
288
+
placeholder=" "
289
value={password}
290
onChange={(e) => setPassword(e.target.value)}
291
/>
292
+
<label>App Password</label>
293
+
</div>
294
+
<div className="m3input-field m3input-label m3input-border size-md flex-1">
295
<input
296
type="text"
297
+
placeholder=" "
298
value={serviceURL}
299
onChange={(e) => setServiceURL(e.target.value)}
300
/>
301
+
<label>PDS</label>
302
+
</div>
303
+
{error && <p className="text-xs text-red-500">{error}</p>}
304
+
<button
305
+
type="submit"
306
+
className="bg-gray-600 hover:bg-gray-700 text-white rounded-full px-4 py-2 font-medium text-sm transition-colors"
307
+
>
308
+
Log in
309
+
</button>
310
+
</form>
311
);
312
+
};
313
314
+
// --- Profile Component (now supports a `large` prop for styling) ---
315
+
export const ProfileThing = ({
316
+
agent,
317
+
large = false,
318
+
}: {
319
+
agent: Agent | null;
320
+
large?: boolean;
321
+
}) => {
322
+
const did = ((agent as AtpAgent)?.session?.did ??
323
+
(agent as AtpAgent)?.assertDid ??
324
+
agent?.did) as string | undefined;
325
+
const { data: identity } = useQueryIdentity(did);
326
+
const { data: profiledata } = useQueryProfile(
327
+
`at://${did}/app.bsky.actor.profile/self`
328
+
);
329
+
const profile = profiledata?.value;
330
331
+
const [imgcdn] = useAtom(imgCDNAtom)
332
333
+
function getAvatarUrl(p: typeof profile) {
334
+
const link = p?.avatar?.ref?.["$link"];
335
+
if (!link || !did) return null;
336
+
return `https://${imgcdn}/img/avatar/plain/${did}/${link}@jpeg`;
337
}
338
339
+
if (!profiledata) {
340
return (
341
+
// Skeleton loader
342
+
<div
343
+
className={`flex items-center gap-2.5 animate-pulse ${large ? "mb-1" : ""}`}
344
+
>
345
+
<div
346
+
className={`rounded-full bg-gray-300 dark:bg-gray-700 ${large ? "w-10 h-10" : "w-[30px] h-[30px]"}`}
347
+
/>
348
+
<div className="flex flex-col gap-2">
349
+
<div
350
+
className={`bg-gray-300 dark:bg-gray-700 rounded ${large ? "h-4 w-28" : "h-3 w-20"}`}
351
+
/>
352
+
<div
353
+
className={`bg-gray-300 dark:bg-gray-700 rounded ${large ? "h-4 w-20" : "h-3 w-16"}`}
354
+
/>
355
+
</div>
356
</div>
357
);
358
}
359
360
return (
361
+
<div
362
+
className={`flex flex-row items-center gap-2.5 ${large ? "mb-1" : ""}`}
363
+
>
364
<img
365
+
src={getAvatarUrl(profile) ?? undefined}
366
alt="avatar"
367
+
className={`object-cover rounded-full ${large ? "w-10 h-10" : "w-[30px] h-[30px]"}`}
368
/>
369
+
<div className="flex flex-col items-start text-left">
370
+
<div
371
+
className={`font-medium ${large ? "text-gray-800 dark:text-gray-100 text-md" : "text-gray-800 dark:text-gray-100 text-sm"}`}
372
+
>
373
+
{profile?.displayName}
374
+
</div>
375
+
<div
376
+
className={` ${large ? "text-gray-500 dark:text-gray-400 text-sm" : "text-gray-500 dark:text-gray-400 text-xs"}`}
377
+
>
378
+
@{identity?.handle}
379
+
</div>
380
</div>
381
</div>
382
);
+6
src/components/Star.tsx
+6
src/components/Star.tsx
···
···
1
+
import type { SVGProps } from 'react';
2
+
import React from 'react';
3
+
4
+
export function FluentEmojiHighContrastGlowingStar(props: SVGProps<SVGSVGElement>) {
5
+
return (<svg xmlns="http://www.w3.org/2000/svg" width={32} height={32} viewBox="0 0 32 32" {...props}><g fill="currentColor"><path d="m28.979 17.003l-3.108.214c-.834.06-1.178 1.079-.542 1.608l2.388 1.955c.521.428 1.314.204 1.523-.428l.709-2.127c.219-.632-.292-1.273-.97-1.222M21.75 2.691l-.72 2.9c-.2.78.66 1.41 1.34.98l2.54-1.58c.55-.34.58-1.14.05-1.52l-1.78-1.29a.912.912 0 0 0-1.43.51M6.43 4.995l2.53 1.58c.68.43 1.54-.19 1.35-.98l-.72-2.9a.92.92 0 0 0-1.43-.52l-1.78 1.29c-.53.4-.5 1.19.05 1.53M4.185 20.713l2.29-1.92c.62-.52.29-1.53-.51-1.58l-2.98-.21a.92.92 0 0 0-.94 1.2l.68 2.09c.2.62.97.84 1.46.42m13.61 7.292l-1.12-2.77c-.3-.75-1.36-.75-1.66 0l-1.12 2.77c-.24.6.2 1.26.85 1.26h2.2a.92.92 0 0 0 .85-1.26"></path><path d="m17.565 3.324l1.726 3.72c.326.694.967 1.18 1.717 1.29l4.056.624c1.835.278 2.575 2.53 1.293 3.859L23.268 16a2.28 2.28 0 0 0-.612 1.964l.71 4.374c.307 1.885-1.687 3.293-3.354 2.37l-3.405-1.894a2.25 2.25 0 0 0-2.21 0l-3.404 1.895c-1.668.922-3.661-.486-3.355-2.37l.71-4.375A2.28 2.28 0 0 0 7.736 16l-3.088-3.184c-1.293-1.34-.543-3.581 1.293-3.859l4.055-.625a2.3 2.3 0 0 0 1.717-1.29l1.727-3.719c.819-1.765 3.306-1.765 4.124 0"></path></g></svg>);
6
+
}
+911
-557
src/components/UniversalPostRenderer.tsx
+911
-557
src/components/UniversalPostRenderer.tsx
···
1
import * as React from "react";
2
-
import { usePersistentStore } from "~/providers/PersistentStoreProvider";
3
-
import { useNavigate } from "@tanstack/react-router";
4
import { type SVGProps } from "react";
5
import { useHydratedEmbed } from "~/utils/useHydrated";
6
import {
7
useQueryPost,
8
-
useQueryIdentity,
9
useQueryProfile,
10
-
useQueryConstellation,
11
} from "~/utils/useQuery";
12
13
function asTyped<T extends { $type: string }>(obj: T): $Typed<T> {
···
25
topReplyLine?: boolean;
26
bottomBorder?: boolean;
27
feedviewpost?: boolean;
28
}
29
30
// export async function cachedGetRecord({
···
128
topReplyLine,
129
bottomBorder = true,
130
feedviewpost = false,
131
}: UniversalPostRendererATURILoaderProps) {
132
-
console.log("atUri", atUri);
133
//const { get, set } = usePersistentStore();
134
//const [record, setRecord] = React.useState<any>(null);
135
//const [links, setLinks] = React.useState<any>(null);
···
142
// >(null);
143
//const router = useRouter();
144
145
-
const parsed = React.useMemo(() => parseAtUri(atUri), [atUri]);
146
-
const did = parsed?.did;
147
const rkey = parsed?.rkey;
148
-
console.log("did", did);
149
-
console.log("rkey", rkey);
150
151
// React.useEffect(() => {
152
// const checkCache = async () => {
···
154
// const cacheKey = `record:${postUri}`;
155
// const cached = await get(cacheKey);
156
// const now = Date.now();
157
-
// console.log(
158
// "UniversalPostRenderer checking cache for",
159
// cacheKey,
160
// "cached:",
···
167
// now - cached.time < CACHE_TIMEOUT
168
// ) {
169
// try {
170
-
// console.log("UniversalPostRenderer found cached data for", cacheKey);
171
// setRecord(JSON.parse(cached.value));
172
// } catch {
173
// setRecord(null);
···
353
const [replies, setReplies] = React.useState<number | null>(null);
354
355
React.useEffect(() => {
356
-
console.log(JSON.stringify(links, null, 2));
357
setLikes(
358
links
359
? links?.links?.["app.bsky.feed.like"]?.[".subject.uri"]?.records || 0
···
372
);
373
}, [links]);
374
375
// const navigateToProfile = (e: React.MouseEvent) => {
376
// e.stopPropagation();
377
// if (resolved?.did) {
···
381
// });
382
// }
383
// };
384
385
return (
386
-
<UniversalPostRendererRawRecordShim
387
-
detailed={detailed}
388
-
postRecord={postQuery}
389
-
profileRecord={opProfile}
390
-
aturi={atUri}
391
-
resolved={resolved}
392
-
likesCount={likes}
393
-
repostsCount={reposts}
394
-
repliesCount={replies}
395
-
bottomReplyLine={bottomReplyLine}
396
-
topReplyLine={topReplyLine}
397
-
bottomBorder={bottomBorder}
398
-
feedviewpost={feedviewpost}
399
-
/>
400
);
401
}
402
403
export function UniversalPostRendererRawRecordShim({
404
postRecord,
405
profileRecord,
···
413
topReplyLine = false,
414
bottomBorder = true,
415
feedviewpost = false,
416
}: {
417
postRecord: any;
418
profileRecord: any;
···
426
topReplyLine?: boolean;
427
bottomBorder?: boolean;
428
feedviewpost?: boolean;
429
}) {
430
-
console.log(`received aturi: ${aturi} of post content: ${postRecord}`);
431
const navigate = useNavigate();
432
433
//const { get, set } = usePersistentStore();
434
-
function getAvatarUrl(opProfile: any) {
435
-
const link = opProfile?.value?.avatar?.ref?.["$link"];
436
-
if (!link) return null;
437
-
return `https://cdn.bsky.app/img/avatar/plain/${resolved?.did}/${link}@jpeg`;
438
-
}
439
-
440
// const [hydratedEmbed, setHydratedEmbed] = useState<any>(undefined);
441
442
// useEffect(() => {
···
489
// result = hydrated instanceof Promise ? await hydrated : hydrated;
490
// }
491
492
-
// console.log(
493
// String(result) + " hydrateEmbedRecordWithMedia hey hyeh ye",
494
// );
495
// setHydratedEmbed(result);
···
508
error: embedError,
509
} = useHydratedEmbed(postRecord?.value?.embed, resolved?.did);
510
511
-
const parsedaturi = parseAtUri(aturi);
512
513
const fakepost = React.useMemo<AppBskyFeedDefs.PostView>(
514
() => ({
515
$type: "app.bsky.feed.defs#postView",
516
uri: aturi,
517
cid: postRecord?.cid || "",
518
-
author: {
519
-
did: resolved?.did || "",
520
-
handle: resolved?.handle || "",
521
-
displayName: profileRecord?.value?.displayName || "",
522
-
avatar: getAvatarUrl(profileRecord) || "",
523
-
viewer: undefined,
524
-
labels: profileRecord?.labels || undefined,
525
-
verification: undefined,
526
-
},
527
record: postRecord?.value || {},
528
embed: hydratedEmbed ?? undefined,
529
replyCount: repliesCount ?? 0,
···
537
}),
538
[
539
aturi,
540
-
postRecord,
541
-
profileRecord,
542
hydratedEmbed,
543
repliesCount,
544
repostsCount,
545
likesCount,
546
-
resolved,
547
]
548
);
549
···
583
feedviewpost ? feedviewpostreplydid : undefined
584
);
585
const feedviewpostreplyhandle = replyhookvalue?.data?.handle;
586
return (
587
<>
588
{/* <p>
···
594
parsedaturi &&
595
navigate({
596
to: "/profile/$did/post/$rkey",
597
-
params: { did: parsedaturi.did, rkey: parsedaturi.rkey },
598
})
599
}
600
// onProfileClick={() => parsedaturi && navigate({to: "/profile/$did",
···
605
if (parsedaturi) {
606
navigate({
607
to: "/profile/$did",
608
-
params: { did: parsedaturi.did },
609
});
610
}
611
}}
612
post={fakepost}
613
salt={aturi}
614
bottomReplyLine={bottomReplyLine}
615
topReplyLine={topReplyLine}
616
bottomBorder={bottomBorder}
617
//extraOptionalItemInfo={{reply: postRecord?.value?.reply as AppBskyFeedDefs.ReplyRef, post: fakepost}}
618
feedviewpostreplyhandle={feedviewpostreplyhandle}
619
/>
620
</>
621
);
622
}
623
624
-
export function parseAtUri(
625
-
atUri: string
626
-
): { did: string; collection: string; rkey: string } | null {
627
-
const PREFIX = "at://";
628
-
if (!atUri.startsWith(PREFIX)) {
629
-
return null;
630
-
}
631
632
-
const parts = atUri.slice(PREFIX.length).split("/");
633
634
-
if (parts.length !== 3) {
635
-
return null;
636
-
}
637
638
-
const [did, collection, rkey] = parts;
639
640
-
if (!did || !collection || !rkey) {
641
-
return null;
642
-
}
643
644
-
return { did, collection, rkey };
645
-
}
646
647
export function MdiCommentOutline(props: SVGProps<SVGSVGElement>) {
648
return (
···
654
{...props}
655
>
656
<path
657
-
fill="oklch(0.704 0.05 28)"
658
d="M9 22a1 1 0 0 1-1-1v-3H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-6.1l-3.7 3.71c-.2.19-.45.29-.7.29zm1-6v3.08L13.08 16H20V4H4v12z"
659
></path>
660
</svg>
···
671
{...props}
672
>
673
<path
674
-
fill="oklch(0.704 0.05 28)"
675
d="M17 17H7v-3l-4 4l4 4v-3h12v-6h-2M7 7h10v3l4-4l-4-4v3H5v6h2z"
676
></path>
677
</svg>
···
722
{...props}
723
>
724
<path
725
-
fill="oklch(0.704 0.05 28)"
726
d="m12.1 18.55l-.1.1l-.11-.1C7.14 14.24 4 11.39 4 8.5C4 6.5 5.5 5 7.5 5c1.54 0 3.04 1 3.57 2.36h1.86C13.46 6 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5c0 2.89-3.14 5.74-7.9 10.05M16.5 3c-1.74 0-3.41.81-4.5 2.08C10.91 3.81 9.24 3 7.5 3C4.42 3 2 5.41 2 8.5c0 3.77 3.4 6.86 8.55 11.53L12 21.35l1.45-1.32C18.6 15.36 22 12.27 22 8.5C22 5.41 19.58 3 16.5 3"
727
></path>
728
</svg>
···
739
{...props}
740
>
741
<path
742
-
fill="oklch(0.704 0.05 28)"
743
d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3a3 3 0 0 0-3-3a3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66c0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"
744
></path>
745
</svg>
···
756
{...props}
757
>
758
<path
759
-
fill="oklch(0.704 0.05 28)"
760
d="M16 12a2 2 0 0 1 2-2a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2m-6 0a2 2 0 0 1 2-2a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2m-6 0a2 2 0 0 1 2-2a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2"
761
></path>
762
</svg>
···
773
{...props}
774
>
775
<path
776
-
fill="oklch(0.704 0.05 28)"
777
d="M17.9 17.39c-.26-.8-1.01-1.39-1.9-1.39h-1v-3a1 1 0 0 0-1-1H8v-2h2a1 1 0 0 0 1-1V7h2a2 2 0 0 0 2-2v-.41a7.984 7.984 0 0 1 2.9 12.8M11 19.93c-3.95-.49-7-3.85-7-7.93c0-.62.08-1.22.21-1.79L9 15v1a2 2 0 0 0 2 2m1-16A10 10 0 0 0 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2"
778
></path>
779
</svg>
···
807
{...props}
808
>
809
<path
810
-
fill="oklch(0.704 0.05 28)"
811
d="M10 9V5l-7 7l7 7v-4.1c5 0 8.5 1.6 11 5.1c-1-5-4-10-11-11"
812
></path>
813
</svg>
···
861
{...props}
862
>
863
<path
864
-
fill="oklch(0.704 0.05 28)"
865
d="M17 17H7v-3l-4 4l4 4v-3h12v-6h-2M7 7h10v3l4-4l-4-4v3H5v6h2z"
866
></path>
867
</svg>
···
878
{...props}
879
>
880
<path
881
-
fill="oklch(0.704 0.05 28)"
882
d="M6 5.75L10.25 10H7v6h6.5l2 2H7a2 2 0 0 1-2-2v-6H1.75zm12 12.5L13.75 14H17V8h-6.5l-2-2H17a2 2 0 0 1 2 2v6h3.25z"
883
></path>
884
</svg>
···
903
}
904
905
/* what imported from testfront */
906
-
import defaultpfp from "~/../public/favicon.png";
907
-
908
//import Masonry from "@mui/lab/Masonry";
909
import {
910
AppBskyActorDefs,
911
-
AppBskyActorProfile,
912
AppBskyEmbedDefs,
913
AppBskyEmbedExternal,
914
AppBskyEmbedImages,
···
919
AppBskyFeedPost,
920
AppBskyGraphDefs,
921
AtUri,
922
//AppBskyLabelerDefs,
923
//AtUri,
924
//ComAtprotoRepoStrongRef,
925
ModerationDecision,
926
-
type $Typed,
927
-
type Facet,
928
} from "@atproto/api";
929
import type {
930
//BlockedPost,
···
933
PostView,
934
//ThreadViewPost,
935
} from "@atproto/api/dist/client/types/app/bsky/feed/defs";
936
import { useEffect, useRef, useState } from "react";
937
import ReactPlayer from "react-player";
938
-
import { useAuth } from "~/providers/PassAuthProvider";
939
// import type { OutputSchema } from "@atproto/api/dist/client/types/app/bsky/feed/getFeed";
940
// import type {
941
// ViewRecord,
···
1043
1044
function UniversalPostRenderer({
1045
post,
1046
//setMainItem,
1047
//isMainItem,
1048
onPostClick,
···
1058
bottomBorder = true,
1059
feedviewpostreplyhandle,
1060
depth = 0,
1061
}: {
1062
post: PostView;
1063
// optional for now because i havent ported every use to this yet
1064
// setMainItem?: React.Dispatch<
1065
// React.SetStateAction<AppBskyFeedDefs.FeedViewPost>
···
1076
bottomBorder?: boolean;
1077
feedviewpostreplyhandle?: string;
1078
depth?: number;
1079
}) {
1080
const navigate = useNavigate();
1081
-
const [hasRetweeted, setHasRetweeted] = useState<Boolean>(
1082
post.viewer?.repost ? true : false
1083
);
1084
-
const [hasLiked, setHasLiked] = useState<Boolean>(
1085
-
post.viewer?.like ? true : false
1086
);
1087
const { agent } = useAuth();
1088
const [likeUri, setLikeUri] = useState<string | undefined>(post.viewer?.like);
1089
const [retweetUri, setRetweetUri] = useState<string | undefined>(
···
1091
);
1092
1093
const likeOrUnlikePost = async () => {
1094
if (!agent) {
1095
console.error("Agent is null or undefined");
1096
return;
1097
}
1098
if (hasLiked) {
1099
if (likeUri) {
1100
await agent.deleteLike(likeUri);
1101
setHasLiked(false);
1102
}
1103
} else {
1104
const { uri } = await agent.like(post.uri, post.cid);
1105
setLikeUri(uri);
1106
setHasLiked(true);
1107
}
1108
};
1109
1110
const repostOrUnrepostPost = async () => {
···
1124
}
1125
};
1126
1127
-
const isRepost = extraOptionalItemInfo
1128
-
? AppBskyFeedDefs.isReasonRepost(extraOptionalItemInfo.reason)
1129
-
? extraOptionalItemInfo.reason?.by.displayName
1130
-
: undefined
1131
-
: undefined;
1132
const isReply = extraOptionalItemInfo
1133
? extraOptionalItemInfo.reply
1134
: undefined;
1135
1136
const emergencySalt = randomString();
1137
1138
/* fuck you */
1139
const isMainItem = false;
1140
const setMainItem = (any: any) => {};
1141
return (
1142
-
<div
1143
-
key={salt + "-" + (post.uri || emergencySalt)}
1144
-
onClick={
1145
-
isMainItem
1146
-
? onPostClick
1147
-
: setMainItem
1148
? onPostClick
1149
-
? (e) => {
1150
-
setMainItem({ post: post });
1151
-
onPostClick(e);
1152
-
}
1153
-
: () => {
1154
-
setMainItem({ post: post });
1155
-
}
1156
-
: undefined
1157
-
}
1158
-
style={{
1159
-
//border: "1px solid #e1e8ed",
1160
-
//borderRadius: 12,
1161
-
opacity: "1 !important",
1162
-
background: "transparent",
1163
-
paddingLeft: isQuote ? 12 : 16,
1164
-
paddingRight: isQuote ? 12 : 16,
1165
-
//paddingTop: 16,
1166
-
paddingTop: isRepost ? 10 : isQuote ? 12 : 16,
1167
-
//paddingBottom: bottomReplyLine ? 0 : 16,
1168
-
paddingBottom: 0,
1169
-
fontFamily: "system-ui, sans-serif",
1170
-
//boxShadow: "0 2px 8px rgba(0,0,0,0.04)",
1171
-
position: "relative",
1172
-
// dont cursor: "pointer",
1173
-
borderBottomWidth: bottomBorder ? (isQuote ? 0 : 1) : 0,
1174
-
}}
1175
-
className="border-gray-300 dark:border-gray-600"
1176
-
>
1177
-
{isRepost && (
1178
-
<div
1179
-
style={{
1180
-
marginLeft: 36,
1181
-
display: "flex",
1182
-
borderRadius: 12,
1183
-
paddingBottom: "calc(22px - 1rem)",
1184
-
fontSize: 14,
1185
-
maxHeight: "1rem",
1186
-
justifyContent: "flex-start",
1187
-
//color: theme.textSecondary,
1188
-
gap: 4,
1189
-
alignItems: "center",
1190
-
}}
1191
-
className="text-gray-500 dark:text-gray-400"
1192
-
>
1193
-
<MdiRepost /> Reposted by {isRepost}{" "}
1194
-
</div>
1195
-
)}
1196
-
{!isQuote && (
1197
-
<div
1198
-
style={{
1199
-
opacity: topReplyLine || (isReply && (true || expanded)) ? 0.5 : 0,
1200
-
position: "absolute",
1201
-
top: 0,
1202
-
left: 36, // why 36 ???
1203
-
//left: 16 + (42 / 2),
1204
-
width: 2,
1205
-
//height: "100%",
1206
-
height: isRepost ? "calc(16px + 1rem - 6px)" : 16 - 6,
1207
-
// background: theme.textSecondary,
1208
-
//opacity: 0.5,
1209
-
// no flex here
1210
-
}}
1211
-
className="bg-gray-500 dark:bg-gray-400"
1212
-
/>
1213
-
)}
1214
-
<div
1215
style={{
1216
-
position: "absolute",
1217
-
//top: isRepost ? "calc(16px + 1rem)" : 16,
1218
-
//left: 16,
1219
-
zIndex: 1,
1220
-
top: isRepost ? "calc(16px + 1rem)" : isQuote ? 12 : 16,
1221
-
left: isQuote ? 12 : 16,
1222
}}
1223
-
onClick={onProfileClick}
1224
>
1225
-
<img
1226
-
src={post.author.avatar || defaultpfp}
1227
-
alt="avatar"
1228
-
// transition={{
1229
-
// type: "spring",
1230
-
// stiffness: 260,
1231
-
// damping: 20,
1232
-
// }}
1233
-
style={{
1234
-
borderRadius: "50%",
1235
-
marginRight: 12,
1236
-
objectFit: "cover",
1237
-
//background: theme.border,
1238
-
//border: `1px solid ${theme.border}`,
1239
-
width: isQuote ? 16 : 42,
1240
-
height: isQuote ? 16 : 42,
1241
-
}}
1242
-
className="border border-gray-300 dark:border-gray-600 bg-gray-300 dark:bg-gray-600"
1243
-
/>
1244
-
</div>
1245
-
<div style={{ display: "flex", alignItems: "flex-start", zIndex: 2 }}>
1246
-
<div
1247
-
style={{
1248
-
display: "flex",
1249
-
flexDirection: "column",
1250
-
alignSelf: "stretch",
1251
-
alignItems: "center",
1252
-
overflow: "hidden",
1253
-
width: expanded || isQuote ? 0 : "auto",
1254
-
marginRight: expanded || isQuote ? 0 : 12,
1255
-
}}
1256
-
>
1257
-
{/* dummy for later use */}
1258
-
<div style={{ width: 42, height: 42 + 8, minHeight: 42 + 8 }} />
1259
-
{/* reply line !!!! bottomReplyLine */}
1260
-
{bottomReplyLine && (
1261
<div
1262
style={{
1263
-
width: 2,
1264
-
height: "100%",
1265
-
//background: theme.textSecondary,
1266
-
opacity: 0.5,
1267
-
// no flex here
1268
-
//color: "Red",
1269
-
//zIndex: 99
1270
}}
1271
-
className="bg-gray-500 dark:bg-gray-400"
1272
-
/>
1273
-
)}
1274
-
{/* <div
1275
layout
1276
transition={{ duration: 0.2 }}
1277
animate={{ height: expanded ? 0 : '100%' }}
···
1281
// no flex here
1282
}}
1283
/> */}
1284
-
</div>
1285
-
<div style={{ flex: 1, maxWidth: "100%" }}>
1286
-
<div
1287
-
style={{
1288
-
display: "flex",
1289
-
flexDirection: "row",
1290
-
alignItems: "center",
1291
-
flexWrap: "nowrap",
1292
-
maxWidth: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`,
1293
-
width: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`,
1294
-
marginLeft: !expanded ? (isQuote ? 26 : 0) : 54,
1295
-
marginBottom: !expanded ? 4 : 0,
1296
-
}}
1297
-
>
1298
<div
1299
style={{
1300
display: "flex",
1301
-
//overflow: "hidden", // hey why is overflow hidden unapplied
1302
-
overflow: "hidden",
1303
-
textOverflow: "ellipsis",
1304
-
flexShrink: 1,
1305
-
flexGrow: 1,
1306
-
flexBasis: 0,
1307
-
width: 0,
1308
-
gap: expanded ? 0 : 6,
1309
-
alignItems: expanded ? "flex-start" : "center",
1310
-
flexDirection: expanded ? "column" : "row",
1311
-
height: expanded ? 48 : "1rem",
1312
}}
1313
>
1314
-
<span
1315
style={{
1316
display: "flex",
1317
-
fontWeight: 700,
1318
-
fontSize: 16,
1319
overflow: "hidden",
1320
textOverflow: "ellipsis",
1321
-
whiteSpace: "nowrap",
1322
flexShrink: 1,
1323
-
minWidth: 0,
1324
-
gap: 4,
1325
-
alignItems: "center",
1326
-
//color: theme.text,
1327
}}
1328
-
className="text-gray-900 dark:text-gray-100"
1329
>
1330
-
{/* verified checkmark */}
1331
-
{post.author.displayName || post.author.handle}{" "}
1332
-
{post.author.verification?.verifiedStatus == "valid" && (
1333
-
<MdiVerified />
1334
-
)}
1335
-
</span>
1336
1337
-
<span
1338
style={{
1339
-
//color: theme.textSecondary,
1340
-
fontSize: 16,
1341
-
overflowX: "hidden",
1342
-
textOverflow: "ellipsis",
1343
-
whiteSpace: "nowrap",
1344
-
flexShrink: 1,
1345
-
flexGrow: 0,
1346
-
minWidth: 0,
1347
}}
1348
-
className="text-gray-500 dark:text-gray-400"
1349
>
1350
-
@{post.author.handle}
1351
-
</span>
1352
</div>
1353
-
<div
1354
-
style={{
1355
-
display: "flex",
1356
-
alignItems: "center",
1357
-
height: "1rem",
1358
-
}}
1359
-
>
1360
-
<span
1361
style={{
1362
//color: theme.textSecondary,
1363
-
fontSize: 16,
1364
-
marginLeft: 8,
1365
-
whiteSpace: "nowrap",
1366
-
flexShrink: 0,
1367
-
maxWidth: "100%",
1368
}}
1369
className="text-gray-500 dark:text-gray-400"
1370
>
1371
-
ยท {/* time placeholder */}
1372
-
{shortTimeAgo(post.indexedAt)}
1373
-
</span>
1374
-
</div>
1375
-
</div>
1376
-
{/* reply indicator */}
1377
-
{!!feedviewpostreplyhandle && (
1378
<div
1379
style={{
1380
-
display: "flex",
1381
-
borderRadius: 12,
1382
-
paddingBottom: 2,
1383
-
fontSize: 14,
1384
-
justifyContent: "flex-start",
1385
-
//color: theme.textSecondary,
1386
-
gap: 4,
1387
-
alignItems: "center",
1388
-
//marginLeft: 36,
1389
-
height:
1390
-
!(expanded || isQuote) && !!feedviewpostreplyhandle
1391
-
? "1rem"
1392
-
: 0,
1393
-
opacity:
1394
-
!(expanded || isQuote) && !!feedviewpostreplyhandle ? 1 : 0,
1395
}}
1396
-
className="text-gray-500 dark:text-gray-400"
1397
>
1398
-
<MdiReply /> Reply to {feedviewpostreplyhandle}
1399
</div>
1400
-
)}
1401
-
<div
1402
-
style={{
1403
-
fontSize: 16,
1404
-
marginBottom: !post.embed /*|| depth > 0*/ ? 0 : 8,
1405
-
whiteSpace: "pre-wrap",
1406
-
textAlign: "left",
1407
-
overflowWrap: "anywhere",
1408
-
wordBreak: "break-word",
1409
-
//color: theme.text,
1410
-
}}
1411
-
className="text-gray-900 dark:text-gray-100"
1412
-
>
1413
-
{renderTextWithFacets({
1414
-
text: (post.record as { text?: string }).text ?? "",
1415
-
facets: (post.record.facets as Facet[]) ?? [],
1416
-
navigate: navigate
1417
-
})}
1418
-
{}
1419
-
</div>
1420
-
{post.embed && depth < 1 ? (
1421
-
<PostEmbeds
1422
-
embed={post.embed}
1423
-
//moderation={moderation}
1424
-
viewContext={PostEmbedViewContext.Feed}
1425
-
salt={salt}
1426
-
navigate={navigate}
1427
-
/>
1428
-
) : null}
1429
-
{post.embed && depth > 0 && (
1430
-
<>
1431
-
<div className="border-gray-300 dark:border-gray-600 p-3 rounded-xl border italic text-gray-400">
1432
-
(there is an embed here thats too deep to render)
1433
-
</div>
1434
-
</>
1435
-
)}
1436
-
<div style={{ paddingTop: post.embed && depth < 1 ? 4 : 0 }}>
1437
-
<>
1438
-
{expanded && (
1439
<div
1440
style={{
1441
-
overflow: "hidden",
1442
-
//color: theme.textSecondary,
1443
-
fontSize: 14,
1444
display: "flex",
1445
-
borderBottomStyle: "solid",
1446
-
//borderBottomColor: theme.border,
1447
-
//background: "#f00",
1448
-
// height: "1rem",
1449
-
paddingTop: 4,
1450
-
paddingBottom: 8,
1451
-
borderBottomWidth: 1,
1452
-
marginBottom: 8,
1453
-
}} // important for height animation
1454
-
className="text-gray-500 dark:text-gray-400 border-gray-200 dark:border-gray-700"
1455
-
>
1456
-
{fullDateTimeFormat(post.indexedAt)}
1457
-
</div>
1458
-
)}
1459
-
</>
1460
-
{!isQuote && (
1461
-
<div
1462
-
style={{
1463
-
display: "flex",
1464
-
gap: 32,
1465
-
paddingTop: 8,
1466
-
//color: theme.textSecondary,
1467
-
fontSize: 15,
1468
-
justifyContent: "space-between",
1469
-
//background: "#0f0",
1470
-
}}
1471
-
className="text-gray-500 dark:text-gray-400"
1472
-
>
1473
-
<span style={btnstyle}>
1474
-
<MdiCommentOutline />
1475
-
{post.replyCount}
1476
-
</span>
1477
-
<HitSlopButton
1478
-
onClick={() => {
1479
-
repostOrUnrepostPost();
1480
-
}}
1481
-
style={{
1482
-
...btnstyle,
1483
-
...(hasRetweeted ? { color: "#5CEFAA" } : {}),
1484
}}
1485
-
>
1486
-
{hasRetweeted ? <MdiRepeatGreen /> : <MdiRepeat />}
1487
-
{(post.repostCount || 0) + (hasRetweeted ? 1 : 0)}
1488
-
</HitSlopButton>
1489
-
<HitSlopButton
1490
-
onClick={() => {
1491
-
likeOrUnlikePost();
1492
-
}}
1493
-
style={{
1494
-
...btnstyle,
1495
-
...(hasLiked ? { color: "#EC4899" } : {}),
1496
-
}}
1497
>
1498
-
{hasLiked ? <MdiCardsHeart /> : <MdiCardsHeartOutline />}
1499
-
{(post.likeCount || 0) + (hasLiked ? 1 : 0)}
1500
-
</HitSlopButton>
1501
-
<div style={{ display: "flex", gap: 8 }}>
1502
<HitSlopButton
1503
-
onClick={async (e) => {
1504
-
e.stopPropagation();
1505
-
try {
1506
-
await navigator.clipboard.writeText(
1507
-
"https://bsky.app" +
1508
-
"/profile/" +
1509
-
post.author.handle +
1510
-
"/post/" +
1511
-
post.uri.split("/").pop()
1512
-
);
1513
-
} catch {}
1514
}}
1515
style={{
1516
...btnstyle,
1517
}}
1518
>
1519
-
<MdiShareVariant />
1520
</HitSlopButton>
1521
-
<span style={btnstyle}>
1522
-
<MdiMoreHoriz />
1523
-
</span>
1524
</div>
1525
-
</div>
1526
-
)}
1527
</div>
1528
-
<div
1529
-
style={{
1530
-
//height: bottomReplyLine ? 16 : 0
1531
-
height: isQuote ? 12 : 16,
1532
-
}}
1533
-
/>
1534
</div>
1535
</div>
1536
</div>
···
1622
viewContext,
1623
salt,
1624
navigate,
1625
}: {
1626
embed?: Embed;
1627
moderation?: ModerationDecision;
···
1629
allowNestedQuotes?: boolean;
1630
viewContext?: PostEmbedViewContext;
1631
salt: string;
1632
-
navigate: ({}: any) => void;
1633
}) {
1634
-
const [lightboxIndex, setLightboxIndex] = useState<number | null>(null);
1635
if (
1636
AppBskyEmbedRecordWithMedia.isView(embed) &&
1637
AppBskyEmbedRecord.isViewRecord(embed.record.record) &&
···
1665
viewContext={viewContext}
1666
salt={salt}
1667
navigate={navigate}
1668
/>
1669
{/* padding empty div of 8px height */}
1670
<div style={{ height: 12 }} />
···
1678
//boxShadow: theme.cardShadow,
1679
overflow: "hidden",
1680
}}
1681
-
className="shadow border border-gray-200 dark:border-gray-700"
1682
>
1683
<UniversalPostRenderer
1684
post={post}
···
1686
salt={salt}
1687
onPostClick={(e) => {
1688
e.stopPropagation();
1689
-
const parsed = parseAtUri(post.uri);
1690
if (parsed) {
1691
navigate({
1692
to: "/profile/$did/post/$rkey",
1693
-
params: { did: parsed.did, rkey: parsed.rkey },
1694
});
1695
}
1696
}}
···
1795
//boxShadow: theme.cardShadow,
1796
overflow: "hidden",
1797
}}
1798
-
className="shadow border border-gray-200 dark:border-gray-700"
1799
>
1800
<UniversalPostRenderer
1801
post={post}
···
1803
salt={salt}
1804
onPostClick={(e) => {
1805
e.stopPropagation();
1806
-
const parsed = parseAtUri(post.uri);
1807
if (parsed) {
1808
navigate({
1809
to: "/profile/$did/post/$rkey",
1810
-
params: { did: parsed.did, rkey: parsed.rkey },
1811
});
1812
}
1813
}}
···
1839
src: img.fullsize,
1840
alt: img.alt,
1841
}));
1842
1843
if (images.length > 0) {
1844
// const items = embed.images.map(img => ({
···
1868
//border: `1px solid ${theme.border}`,
1869
overflow: "hidden",
1870
}}
1871
-
className="border border-gray-200 dark:border-gray-700 bg-gray-200 dark:bg-gray-900"
1872
>
1873
-
{lightboxIndex !== null && (
1874
<Lightbox
1875
images={lightboxImages}
1876
index={lightboxIndex}
1877
onClose={() => setLightboxIndex(null)}
1878
onNavigate={(newIndex) => setLightboxIndex(newIndex)}
1879
/>
1880
-
)}
1881
<img
1882
src={image.fullsize}
1883
alt={image.alt}
···
1908
overflow: "hidden",
1909
//border: `1px solid ${theme.border}`,
1910
}}
1911
-
className="border border-gray-200 dark:border-gray-700"
1912
>
1913
-
{lightboxIndex !== null && (
1914
<Lightbox
1915
images={lightboxImages}
1916
index={lightboxIndex}
1917
onClose={() => setLightboxIndex(null)}
1918
onNavigate={(newIndex) => setLightboxIndex(newIndex)}
1919
/>
1920
-
)}
1921
{images.map((img, i) => (
1922
<div
1923
key={i}
···
1957
//border: `1px solid ${theme.border}`,
1958
// height: 240, // fixed height for cropping
1959
}}
1960
-
className="border border-gray-200 dark:border-gray-700"
1961
>
1962
-
{lightboxIndex !== null && (
1963
<Lightbox
1964
images={lightboxImages}
1965
index={lightboxIndex}
1966
onClose={() => setLightboxIndex(null)}
1967
onNavigate={(newIndex) => setLightboxIndex(newIndex)}
1968
/>
1969
-
)}
1970
{/* Left: 1:1 */}
1971
<div
1972
style={{ flex: 1, aspectRatio: "1 / 1", position: "relative" }}
···
2041
//border: `1px solid ${theme.border}`,
2042
//aspectRatio: "3 / 2", // overall grid aspect
2043
}}
2044
-
className="border border-gray-200 dark:border-gray-700"
2045
>
2046
-
{lightboxIndex !== null && (
2047
<Lightbox
2048
images={lightboxImages}
2049
index={lightboxIndex}
2050
onClose={() => setLightboxIndex(null)}
2051
onNavigate={(newIndex) => setLightboxIndex(newIndex)}
2052
/>
2053
-
)}
2054
{images.map((img, i) => (
2055
<div
2056
key={i}
···
2141
return <div />;
2142
}
2143
2144
-
import { createPortal } from "react-dom";
2145
-
import type { Record } from "@atproto/api/dist/client/types/app/bsky/actor/profile";
2146
-
type LightboxProps = {
2147
-
images: { src: string; alt?: string }[];
2148
-
index: number;
2149
-
onClose: () => void;
2150
-
onNavigate?: (newIndex: number) => void;
2151
-
};
2152
-
export function Lightbox({
2153
-
images,
2154
-
index,
2155
-
onClose,
2156
-
onNavigate,
2157
-
}: LightboxProps) {
2158
-
const image = images[index];
2159
-
2160
-
useEffect(() => {
2161
-
function handleKey(e: KeyboardEvent) {
2162
-
if (e.key === "Escape") onClose();
2163
-
if (e.key === "ArrowRight" && onNavigate)
2164
-
onNavigate((index + 1) % images.length);
2165
-
if (e.key === "ArrowLeft" && onNavigate)
2166
-
onNavigate((index - 1 + images.length) % images.length);
2167
-
}
2168
-
window.addEventListener("keydown", handleKey);
2169
-
return () => window.removeEventListener("keydown", handleKey);
2170
-
}, [index, images.length, onClose, onNavigate]);
2171
-
2172
-
return createPortal(
2173
-
<div
2174
-
className="fixed inset-0 z-50 flex items-center justify-center bg-black/80"
2175
-
onClick={(e) => {
2176
-
e.stopPropagation();
2177
-
onClose();
2178
-
}}
2179
-
>
2180
-
<img
2181
-
src={image.src}
2182
-
alt={image.alt}
2183
-
className="max-h-[90vh] max-w-[90vw] object-contain rounded-lg shadow-lg"
2184
-
onClick={(e) => e.stopPropagation()}
2185
-
/>
2186
-
2187
-
{images.length > 1 && (
2188
-
<>
2189
-
<button
2190
-
onClick={(e) => {
2191
-
e.stopPropagation();
2192
-
onNavigate?.((index - 1 + images.length) % images.length);
2193
-
}}
2194
-
className="absolute left-4 top-1/2 -translate-y-1/2 text-white text-4xl h-8 w-8 rounded-full bg-gray-900 flex items-center justify-center"
2195
-
>
2196
-
<svg
2197
-
xmlns="http://www.w3.org/2000/svg"
2198
-
width={28}
2199
-
height={28}
2200
-
viewBox="0 0 24 24"
2201
-
>
2202
-
<g fill="none" fillRule="evenodd">
2203
-
<path d="M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"></path>
2204
-
<path
2205
-
fill="currentColor"
2206
-
d="M8.293 12.707a1 1 0 0 1 0-1.414l5.657-5.657a1 1 0 1 1 1.414 1.414L10.414 12l4.95 4.95a1 1 0 0 1-1.414 1.414z"
2207
-
></path>
2208
-
</g>
2209
-
</svg>
2210
-
</button>
2211
-
<button
2212
-
onClick={(e) => {
2213
-
e.stopPropagation();
2214
-
onNavigate?.((index + 1) % images.length);
2215
-
}}
2216
-
className="absolute right-4 top-1/2 -translate-y-1/2 text-white text-4xl h-8 w-8 rounded-full bg-gray-900 flex items-center justify-center"
2217
-
>
2218
-
<svg
2219
-
xmlns="http://www.w3.org/2000/svg"
2220
-
width={28}
2221
-
height={28}
2222
-
viewBox="0 0 24 24"
2223
-
>
2224
-
<g fill="none" fillRule="evenodd">
2225
-
<path d="M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"></path>
2226
-
<path
2227
-
fill="currentColor"
2228
-
d="M15.707 11.293a1 1 0 0 1 0 1.414l-5.657 5.657a1 1 0 1 1-1.414-1.414l4.95-4.95l-4.95-4.95a1 1 0 0 1 1.414-1.414z"
2229
-
></path>
2230
-
</g>
2231
-
</svg>
2232
-
</button>
2233
-
</>
2234
-
)}
2235
-
</div>,
2236
-
document.body
2237
-
);
2238
-
}
2239
-
2240
function getDomain(url: string) {
2241
try {
2242
const { hostname } = new URL(url);
···
2267
for (let i = 0; i < bytes.length; i++) {
2268
map[byteIndex++] = charIndex;
2269
}
2270
-
charIndex++;
2271
}
2272
2273
return map;
···
2301
return { start, end, feature: f.features[0] };
2302
});
2303
}
2304
-
function renderTextWithFacets({
2305
text,
2306
facets,
2307
navigate,
2308
}: {
2309
text: string;
2310
facets: Facet[];
2311
-
navigate: ({}: any) => void;
2312
}) {
2313
const ranges = extractFacetRanges(text, facets).sort(
2314
(a: any, b: any) => a.start - b.start
···
2323
}
2324
2325
const fragment = text.slice(start, end);
2326
-
// @ts-ignore
2327
if (feature.$type === "app.bsky.richtext.facet#link" && feature.uri) {
2328
result.push(
2329
<a
2330
-
// @ts-ignore
2331
href={feature.uri}
2332
key={start}
2333
className="link"
···
2347
);
2348
} else if (
2349
feature.$type === "app.bsky.richtext.facet#mention" &&
2350
-
// @ts-ignore
2351
feature.did
2352
) {
2353
result.push(
···
2359
e.stopPropagation();
2360
navigate({
2361
to: "/profile/$did",
2362
-
// @ts-ignore
2363
-
params: { did: feature.did},
2364
});
2365
}}
2366
>
···
2456
rel="noopener noreferrer"
2457
onClick={(e) => {
2458
e.stopPropagation();
2459
-
onOpen;
2460
}}
2461
-
/* @ts-ignore */
2462
style={linkStyle}
2463
className="text-gray-500 dark:text-gray-400"
2464
>
2465
-
{/* @ts-ignore ehiaeih */}
2466
<div
2467
style={containerStyle as React.CSSProperties}
2468
-
className="border border-gray-200 dark:border-gray-700"
2469
>
2470
{thumb && (
2471
<div
···
2479
marginBottom: 8,
2480
//borderBottom: `1px solid ${theme.border}`,
2481
}}
2482
-
className="border-b border-gray-200 dark:border-gray-700"
2483
>
2484
<img
2485
src={thumb}
···
2503
paddingTop: thumb ? 0 : 12,
2504
}}
2505
>
2506
-
{/* @ts-ignore */}
2507
<div style={titleStyle} className="text-gray-900 dark:text-gray-100">
2508
{title}
2509
</div>
2510
-
{/* @ts-ignore */}
2511
<div
2512
style={descriptionStyle as React.CSSProperties}
2513
className="text-gray-500 dark:text-gray-400"
···
2606
borderRadius: 12,
2607
//border: `1px solid ${theme.border}`,
2608
}}
2609
-
className="border border-gray-200 dark:border-gray-700"
2610
onClick={async (e) => {
2611
e.stopPropagation();
2612
setPlaying(true);
···
2647
100 / (aspect ? aspect.width / aspect.height : 16 / 9)
2648
}%`, // 16:9 = 56.25%, 4:3 = 75%
2649
}}
2650
-
className="border border-gray-200 dark:border-gray-700"
2651
>
2652
<ReactPlayer
2653
src={url}
···
1
+
import { useNavigate } from "@tanstack/react-router";
2
+
import DOMPurify from "dompurify";
3
+
import { useAtom } from "jotai";
4
+
import { DropdownMenu } from "radix-ui";
5
+
import { HoverCard } from "radix-ui";
6
import * as React from "react";
7
import { type SVGProps } from "react";
8
+
9
+
import {
10
+
composerAtom,
11
+
constellationURLAtom,
12
+
imgCDNAtom,
13
+
likedPostsAtom,
14
+
} from "~/utils/atoms";
15
import { useHydratedEmbed } from "~/utils/useHydrated";
16
import {
17
+
useQueryConstellation,
18
+
useQueryIdentity,
19
useQueryPost,
20
useQueryProfile,
21
+
yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks,
22
} from "~/utils/useQuery";
23
24
function asTyped<T extends { $type: string }>(obj: T): $Typed<T> {
···
36
topReplyLine?: boolean;
37
bottomBorder?: boolean;
38
feedviewpost?: boolean;
39
+
repostedby?: string;
40
+
style?: React.CSSProperties;
41
+
ref?: React.Ref<HTMLDivElement>;
42
+
dataIndexPropPass?: number;
43
+
nopics?: boolean;
44
+
lightboxCallback?: (d: LightboxProps) => void;
45
+
maxReplies?: number;
46
+
isQuote?: boolean;
47
}
48
49
// export async function cachedGetRecord({
···
147
topReplyLine,
148
bottomBorder = true,
149
feedviewpost = false,
150
+
repostedby,
151
+
style,
152
+
ref,
153
+
dataIndexPropPass,
154
+
nopics,
155
+
lightboxCallback,
156
+
maxReplies,
157
+
isQuote,
158
}: UniversalPostRendererATURILoaderProps) {
159
+
// todo remove this once tree rendering is implemented, use a prop like isTree
160
+
const TEMPLINEAR = true;
161
+
// /*mass comment*/ console.log("atUri", atUri);
162
//const { get, set } = usePersistentStore();
163
//const [record, setRecord] = React.useState<any>(null);
164
//const [links, setLinks] = React.useState<any>(null);
···
171
// >(null);
172
//const router = useRouter();
173
174
+
//const parsed = React.useMemo(() => parseAtUri(atUri), [atUri]);
175
+
const parsed = new AtUri(atUri);
176
+
const did = parsed?.host;
177
const rkey = parsed?.rkey;
178
+
// /*mass comment*/ console.log("did", did);
179
+
// /*mass comment*/ console.log("rkey", rkey);
180
181
// React.useEffect(() => {
182
// const checkCache = async () => {
···
184
// const cacheKey = `record:${postUri}`;
185
// const cached = await get(cacheKey);
186
// const now = Date.now();
187
+
// // /*mass comment*/ console.log(
188
// "UniversalPostRenderer checking cache for",
189
// cacheKey,
190
// "cached:",
···
197
// now - cached.time < CACHE_TIMEOUT
198
// ) {
199
// try {
200
+
// // /*mass comment*/ console.log("UniversalPostRenderer found cached data for", cacheKey);
201
// setRecord(JSON.parse(cached.value));
202
// } catch {
203
// setRecord(null);
···
383
const [replies, setReplies] = React.useState<number | null>(null);
384
385
React.useEffect(() => {
386
+
// /*mass comment*/ console.log(JSON.stringify(links, null, 2));
387
setLikes(
388
links
389
? links?.links?.["app.bsky.feed.like"]?.[".subject.uri"]?.records || 0
···
402
);
403
}, [links]);
404
405
+
// const { data: repliesData } = useQueryConstellation({
406
+
// method: "/links",
407
+
// target: atUri,
408
+
// collection: "app.bsky.feed.post",
409
+
// path: ".reply.parent.uri",
410
+
// });
411
+
412
+
const [constellationurl] = useAtom(constellationURLAtom);
413
+
414
+
const infinitequeryresults = useInfiniteQuery({
415
+
...yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks(
416
+
{
417
+
constellation: constellationurl,
418
+
method: "/links",
419
+
target: atUri,
420
+
collection: "app.bsky.feed.post",
421
+
path: ".reply.parent.uri",
422
+
}
423
+
),
424
+
enabled: !!atUri && !!maxReplies && !isQuote,
425
+
});
426
+
427
+
const {
428
+
data: repliesData,
429
+
// fetchNextPage,
430
+
// hasNextPage,
431
+
// isFetchingNextPage,
432
+
} = infinitequeryresults;
433
+
434
+
// auto-fetch all pages
435
+
useEffect(() => {
436
+
if (!maxReplies || isQuote || TEMPLINEAR) return;
437
+
if (
438
+
infinitequeryresults.hasNextPage &&
439
+
!infinitequeryresults.isFetchingNextPage
440
+
) {
441
+
console.log("Fetching the next page...");
442
+
infinitequeryresults.fetchNextPage();
443
+
}
444
+
}, [TEMPLINEAR, infinitequeryresults, isQuote, maxReplies]);
445
+
446
+
const replyAturis = repliesData
447
+
? repliesData.pages.flatMap((page) =>
448
+
page
449
+
? page.linking_records.map((record) => {
450
+
const aturi = `at://${record.did}/${record.collection}/${record.rkey}`;
451
+
return aturi;
452
+
})
453
+
: []
454
+
)
455
+
: [];
456
+
457
+
//const [oldestOpsReply, setOldestOpsReply] = useState<string | undefined>(undefined);
458
+
459
+
const { oldestOpsReply, oldestOpsReplyElseNewestNonOpsReply } = (() => {
460
+
if (isQuote || !replyAturis || replyAturis.length === 0 || !maxReplies)
461
+
return {
462
+
oldestOpsReply: undefined,
463
+
oldestOpsReplyElseNewestNonOpsReply: undefined,
464
+
};
465
+
466
+
const opdid = new AtUri(
467
+
//postQuery?.value.reply?.root.uri ?? postQuery?.uri ?? atUri
468
+
atUri
469
+
).host;
470
+
471
+
const opReplies = replyAturis.filter(
472
+
(aturi) => new AtUri(aturi).host === opdid
473
+
);
474
+
475
+
if (opReplies.length > 0) {
476
+
const opreply = opReplies[opReplies.length - 1];
477
+
//setOldestOpsReply(opreply);
478
+
return {
479
+
oldestOpsReply: opreply,
480
+
oldestOpsReplyElseNewestNonOpsReply: opreply,
481
+
};
482
+
} else {
483
+
return {
484
+
oldestOpsReply: undefined,
485
+
oldestOpsReplyElseNewestNonOpsReply: replyAturis[0],
486
+
};
487
+
}
488
+
})();
489
+
490
// const navigateToProfile = (e: React.MouseEvent) => {
491
// e.stopPropagation();
492
// if (resolved?.did) {
···
496
// });
497
// }
498
// };
499
+
if (!postQuery?.value) {
500
+
// deleted post more often than a non-resolvable post
501
+
return <></>;
502
+
}
503
504
return (
505
+
<>
506
+
{/* <span>uprrs {maxReplies} {!!maxReplies&&!!oldestOpsReplyElseNewestNonOpsReply ? "true" : "false"}</span> */}
507
+
<UniversalPostRendererRawRecordShim
508
+
detailed={detailed}
509
+
postRecord={postQuery}
510
+
profileRecord={opProfile}
511
+
aturi={atUri}
512
+
resolved={resolved}
513
+
likesCount={likes}
514
+
repostsCount={reposts}
515
+
repliesCount={replies}
516
+
bottomReplyLine={
517
+
maxReplies && oldestOpsReplyElseNewestNonOpsReply
518
+
? true
519
+
: maxReplies && !oldestOpsReplyElseNewestNonOpsReply
520
+
? false
521
+
: (maxReplies === 0 && (!replies || (!!replies && replies === 0))) ? false : bottomReplyLine
522
+
}
523
+
topReplyLine={topReplyLine}
524
+
//bottomBorder={maxReplies&&oldestOpsReplyElseNewestNonOpsReply ? false : bottomBorder}
525
+
bottomBorder={
526
+
maxReplies && oldestOpsReplyElseNewestNonOpsReply
527
+
? false
528
+
: maxReplies === 0
529
+
? false
530
+
: bottomBorder
531
+
}
532
+
feedviewpost={feedviewpost}
533
+
repostedby={repostedby}
534
+
//style={{...style, background: oldestOpsReply === atUri ? "Red" : undefined}}
535
+
style={style}
536
+
ref={ref}
537
+
dataIndexPropPass={dataIndexPropPass}
538
+
nopics={nopics}
539
+
lightboxCallback={lightboxCallback}
540
+
maxReplies={maxReplies}
541
+
isQuote={isQuote}
542
+
/>
543
+
<>
544
+
{(maxReplies && maxReplies === 0 && replies && replies > 0) ? (
545
+
<>
546
+
{/* <div>hello</div> */}
547
+
<MoreReplies atUri={atUri} />
548
+
</>
549
+
) : (<></>)}
550
+
</>
551
+
{!isQuote && oldestOpsReplyElseNewestNonOpsReply && (
552
+
<>
553
+
{/* <span>hello {maxReplies}</span> */}
554
+
<UniversalPostRendererATURILoader
555
+
//detailed={detailed}
556
+
atUri={oldestOpsReplyElseNewestNonOpsReply}
557
+
bottomReplyLine={(maxReplies ?? 0) > 0}
558
+
topReplyLine={
559
+
(!!(maxReplies && maxReplies - 1 === 0) &&
560
+
!!(replies && replies > 0)) ||
561
+
!!((maxReplies ?? 0) > 1)
562
+
}
563
+
bottomBorder={bottomBorder}
564
+
feedviewpost={feedviewpost}
565
+
repostedby={repostedby}
566
+
style={style}
567
+
ref={ref}
568
+
dataIndexPropPass={dataIndexPropPass}
569
+
nopics={nopics}
570
+
lightboxCallback={lightboxCallback}
571
+
maxReplies={
572
+
maxReplies && maxReplies > 0 ? maxReplies - 1 : undefined
573
+
}
574
+
/>
575
+
</>
576
+
)}
577
+
</>
578
);
579
}
580
581
+
function MoreReplies({ atUri }: { atUri: string }) {
582
+
const navigate = useNavigate();
583
+
const aturio = new AtUri(atUri);
584
+
return (
585
+
<div
586
+
onClick={() =>
587
+
navigate({
588
+
to: "/profile/$did/post/$rkey",
589
+
params: { did: aturio.host, rkey: aturio.rkey },
590
+
})
591
+
}
592
+
className="border-b border-gray-300 dark:border-gray-800 flex flex-row px-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-900 transition-colors"
593
+
>
594
+
<div className="w-[42px] h-12 flex flex-col items-center justify-center">
595
+
<div
596
+
style={{
597
+
width: 2,
598
+
height: "100%",
599
+
backgroundImage:
600
+
"repeating-linear-gradient(to bottom, var(--color-gray-500) 0, var(--color-gray-500) 4px, transparent 4px, transparent 8px)",
601
+
opacity: 0.5,
602
+
}}
603
+
className="dark:bg-[repeating-linear-gradient(to_bottom,var(--color-gray-500)_0,var(--color-gray-400)_4px,transparent_4px,transparent_8px)]"
604
+
//className="border-gray-400 dark:border-gray-500"
605
+
/>
606
+
</div>
607
+
608
+
<div className="flex items-center pl-3 text-sm text-gray-500 dark:text-gray-400 select-none">
609
+
More Replies
610
+
</div>
611
+
</div>
612
+
);
613
+
}
614
+
615
+
function getAvatarUrl(opProfile: any, did: string, cdn: string) {
616
+
const link = opProfile?.value?.avatar?.ref?.["$link"];
617
+
if (!link) return null;
618
+
return `https://${cdn}/img/avatar/plain/${did}/${link}@jpeg`;
619
+
}
620
+
621
export function UniversalPostRendererRawRecordShim({
622
postRecord,
623
profileRecord,
···
631
topReplyLine = false,
632
bottomBorder = true,
633
feedviewpost = false,
634
+
repostedby,
635
+
style,
636
+
ref,
637
+
dataIndexPropPass,
638
+
nopics,
639
+
lightboxCallback,
640
+
maxReplies,
641
+
isQuote,
642
}: {
643
postRecord: any;
644
profileRecord: any;
···
652
topReplyLine?: boolean;
653
bottomBorder?: boolean;
654
feedviewpost?: boolean;
655
+
repostedby?: string;
656
+
style?: React.CSSProperties;
657
+
ref?: React.Ref<HTMLDivElement>;
658
+
dataIndexPropPass?: number;
659
+
nopics?: boolean;
660
+
lightboxCallback?: (d: LightboxProps) => void;
661
+
maxReplies?: number;
662
+
isQuote?: boolean;
663
}) {
664
+
// /*mass comment*/ console.log(`received aturi: ${aturi} of post content: ${postRecord}`);
665
const navigate = useNavigate();
666
667
//const { get, set } = usePersistentStore();
668
// const [hydratedEmbed, setHydratedEmbed] = useState<any>(undefined);
669
670
// useEffect(() => {
···
717
// result = hydrated instanceof Promise ? await hydrated : hydrated;
718
// }
719
720
+
// // /*mass comment*/ console.log(
721
// String(result) + " hydrateEmbedRecordWithMedia hey hyeh ye",
722
// );
723
// setHydratedEmbed(result);
···
736
error: embedError,
737
} = useHydratedEmbed(postRecord?.value?.embed, resolved?.did);
738
739
+
const [imgcdn] = useAtom(imgCDNAtom);
740
+
741
+
const parsedaturi = new AtUri(aturi); //parseAtUri(aturi);
742
+
743
+
const fakeprofileviewbasic = React.useMemo<AppBskyActorDefs.ProfileViewBasic>(
744
+
() => ({
745
+
did: resolved?.did || "",
746
+
handle: resolved?.handle || "",
747
+
displayName: profileRecord?.value?.displayName || "",
748
+
avatar: getAvatarUrl(profileRecord, resolved?.did, imgcdn) || "",
749
+
viewer: undefined,
750
+
labels: profileRecord?.labels || undefined,
751
+
verification: undefined,
752
+
}),
753
+
[imgcdn, profileRecord, resolved?.did, resolved?.handle]
754
+
);
755
+
756
+
const fakeprofileviewdetailed =
757
+
React.useMemo<AppBskyActorDefs.ProfileViewDetailed>(
758
+
() => ({
759
+
...fakeprofileviewbasic,
760
+
$type: "app.bsky.actor.defs#profileViewDetailed",
761
+
description: profileRecord?.value?.description || undefined,
762
+
}),
763
+
[fakeprofileviewbasic, profileRecord?.value?.description]
764
+
);
765
766
const fakepost = React.useMemo<AppBskyFeedDefs.PostView>(
767
() => ({
768
$type: "app.bsky.feed.defs#postView",
769
uri: aturi,
770
cid: postRecord?.cid || "",
771
+
author: fakeprofileviewbasic,
772
record: postRecord?.value || {},
773
embed: hydratedEmbed ?? undefined,
774
replyCount: repliesCount ?? 0,
···
782
}),
783
[
784
aturi,
785
+
postRecord?.cid,
786
+
postRecord?.value,
787
+
postRecord?.labels,
788
+
fakeprofileviewbasic,
789
hydratedEmbed,
790
repliesCount,
791
repostsCount,
792
likesCount,
793
]
794
);
795
···
829
feedviewpost ? feedviewpostreplydid : undefined
830
);
831
const feedviewpostreplyhandle = replyhookvalue?.data?.handle;
832
+
833
+
const aturirepostbydid = repostedby ? new AtUri(repostedby).host : undefined;
834
+
const repostedbyhookvalue = useQueryIdentity(
835
+
repostedby ? aturirepostbydid : undefined
836
+
);
837
+
const feedviewpostrepostedbyhandle = repostedbyhookvalue?.data?.handle;
838
return (
839
<>
840
{/* <p>
···
846
parsedaturi &&
847
navigate({
848
to: "/profile/$did/post/$rkey",
849
+
params: { did: parsedaturi.host, rkey: parsedaturi.rkey },
850
})
851
}
852
// onProfileClick={() => parsedaturi && navigate({to: "/profile/$did",
···
857
if (parsedaturi) {
858
navigate({
859
to: "/profile/$did",
860
+
params: { did: parsedaturi.host },
861
});
862
}
863
}}
864
post={fakepost}
865
+
uprrrsauthor={fakeprofileviewdetailed}
866
salt={aturi}
867
bottomReplyLine={bottomReplyLine}
868
topReplyLine={topReplyLine}
869
bottomBorder={bottomBorder}
870
//extraOptionalItemInfo={{reply: postRecord?.value?.reply as AppBskyFeedDefs.ReplyRef, post: fakepost}}
871
feedviewpostreplyhandle={feedviewpostreplyhandle}
872
+
repostedby={feedviewpostrepostedbyhandle}
873
+
style={style}
874
+
ref={ref}
875
+
dataIndexPropPass={dataIndexPropPass}
876
+
nopics={nopics}
877
+
lightboxCallback={lightboxCallback}
878
+
maxReplies={maxReplies}
879
+
isQuote={isQuote}
880
/>
881
</>
882
);
883
}
884
885
+
// export function parseAtUri(
886
+
// atUri: string
887
+
// ): { did: string; collection: string; rkey: string } | null {
888
+
// const PREFIX = "at://";
889
+
// if (!atUri.startsWith(PREFIX)) {
890
+
// return null;
891
+
// }
892
893
+
// const parts = atUri.slice(PREFIX.length).split("/");
894
895
+
// if (parts.length !== 3) {
896
+
// return null;
897
+
// }
898
899
+
// const [did, collection, rkey] = parts;
900
901
+
// if (!did || !collection || !rkey) {
902
+
// return null;
903
+
// }
904
905
+
// return { did, collection, rkey };
906
+
// }
907
908
export function MdiCommentOutline(props: SVGProps<SVGSVGElement>) {
909
return (
···
915
{...props}
916
>
917
<path
918
+
fill="var(--color-gray-400)"
919
d="M9 22a1 1 0 0 1-1-1v-3H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-6.1l-3.7 3.71c-.2.19-.45.29-.7.29zm1-6v3.08L13.08 16H20V4H4v12z"
920
></path>
921
</svg>
···
932
{...props}
933
>
934
<path
935
+
fill="var(--color-gray-400)"
936
d="M17 17H7v-3l-4 4l4 4v-3h12v-6h-2M7 7h10v3l4-4l-4-4v3H5v6h2z"
937
></path>
938
</svg>
···
983
{...props}
984
>
985
<path
986
+
fill="var(--color-gray-400)"
987
d="m12.1 18.55l-.1.1l-.11-.1C7.14 14.24 4 11.39 4 8.5C4 6.5 5.5 5 7.5 5c1.54 0 3.04 1 3.57 2.36h1.86C13.46 6 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5c0 2.89-3.14 5.74-7.9 10.05M16.5 3c-1.74 0-3.41.81-4.5 2.08C10.91 3.81 9.24 3 7.5 3C4.42 3 2 5.41 2 8.5c0 3.77 3.4 6.86 8.55 11.53L12 21.35l1.45-1.32C18.6 15.36 22 12.27 22 8.5C22 5.41 19.58 3 16.5 3"
988
></path>
989
</svg>
···
1000
{...props}
1001
>
1002
<path
1003
+
fill="var(--color-gray-400)"
1004
d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3a3 3 0 0 0-3-3a3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3a3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66c0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"
1005
></path>
1006
</svg>
···
1017
{...props}
1018
>
1019
<path
1020
+
fill="var(--color-gray-400)"
1021
d="M16 12a2 2 0 0 1 2-2a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2m-6 0a2 2 0 0 1 2-2a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2m-6 0a2 2 0 0 1 2-2a2 2 0 0 1 2 2a2 2 0 0 1-2 2a2 2 0 0 1-2-2"
1022
></path>
1023
</svg>
···
1034
{...props}
1035
>
1036
<path
1037
+
fill="var(--color-gray-400)"
1038
d="M17.9 17.39c-.26-.8-1.01-1.39-1.9-1.39h-1v-3a1 1 0 0 0-1-1H8v-2h2a1 1 0 0 0 1-1V7h2a2 2 0 0 0 2-2v-.41a7.984 7.984 0 0 1 2.9 12.8M11 19.93c-3.95-.49-7-3.85-7-7.93c0-.62.08-1.22.21-1.79L9 15v1a2 2 0 0 0 2 2m1-16A10 10 0 0 0 2 12a10 10 0 0 0 10 10a10 10 0 0 0 10-10A10 10 0 0 0 12 2"
1039
></path>
1040
</svg>
···
1068
{...props}
1069
>
1070
<path
1071
+
fill="var(--color-gray-400)"
1072
d="M10 9V5l-7 7l7 7v-4.1c5 0 8.5 1.6 11 5.1c-1-5-4-10-11-11"
1073
></path>
1074
</svg>
···
1122
{...props}
1123
>
1124
<path
1125
+
fill="var(--color-gray-400)"
1126
d="M17 17H7v-3l-4 4l4 4v-3h12v-6h-2M7 7h10v3l4-4l-4-4v3H5v6h2z"
1127
></path>
1128
</svg>
···
1139
{...props}
1140
>
1141
<path
1142
+
fill="var(--color-gray-400)"
1143
d="M6 5.75L10.25 10H7v6h6.5l2 2H7a2 2 0 0 1-2-2v-6H1.75zm12 12.5L13.75 14H17V8h-6.5l-2-2H17a2 2 0 0 1 2 2v6h3.25z"
1144
></path>
1145
</svg>
···
1164
}
1165
1166
/* what imported from testfront */
1167
//import Masonry from "@mui/lab/Masonry";
1168
import {
1169
+
type $Typed,
1170
AppBskyActorDefs,
1171
AppBskyEmbedDefs,
1172
AppBskyEmbedExternal,
1173
AppBskyEmbedImages,
···
1178
AppBskyFeedPost,
1179
AppBskyGraphDefs,
1180
AtUri,
1181
+
type Facet,
1182
//AppBskyLabelerDefs,
1183
//AtUri,
1184
//ComAtprotoRepoStrongRef,
1185
ModerationDecision,
1186
} from "@atproto/api";
1187
import type {
1188
//BlockedPost,
···
1191
PostView,
1192
//ThreadViewPost,
1193
} from "@atproto/api/dist/client/types/app/bsky/feed/defs";
1194
+
import { useInfiniteQuery } from "@tanstack/react-query";
1195
import { useEffect, useRef, useState } from "react";
1196
import ReactPlayer from "react-player";
1197
+
1198
+
import defaultpfp from "~/../public/favicon.png";
1199
+
import { useAuth } from "~/providers/UnifiedAuthProvider";
1200
+
import { FollowButton, Mutual } from "~/routes/profile.$did";
1201
+
import type { LightboxProps } from "~/routes/profile.$did/post.$rkey.image.$i";
1202
// import type { OutputSchema } from "@atproto/api/dist/client/types/app/bsky/feed/getFeed";
1203
// import type {
1204
// ViewRecord,
···
1306
1307
function UniversalPostRenderer({
1308
post,
1309
+
uprrrsauthor,
1310
//setMainItem,
1311
//isMainItem,
1312
onPostClick,
···
1322
bottomBorder = true,
1323
feedviewpostreplyhandle,
1324
depth = 0,
1325
+
repostedby,
1326
+
style,
1327
+
ref,
1328
+
dataIndexPropPass,
1329
+
nopics,
1330
+
lightboxCallback,
1331
+
maxReplies,
1332
}: {
1333
post: PostView;
1334
+
uprrrsauthor?: AppBskyActorDefs.ProfileViewDetailed;
1335
// optional for now because i havent ported every use to this yet
1336
// setMainItem?: React.Dispatch<
1337
// React.SetStateAction<AppBskyFeedDefs.FeedViewPost>
···
1348
bottomBorder?: boolean;
1349
feedviewpostreplyhandle?: string;
1350
depth?: number;
1351
+
repostedby?: string;
1352
+
style?: React.CSSProperties;
1353
+
ref?: React.Ref<HTMLDivElement>;
1354
+
dataIndexPropPass?: number;
1355
+
nopics?: boolean;
1356
+
lightboxCallback?: (d: LightboxProps) => void;
1357
+
maxReplies?: number;
1358
}) {
1359
+
const parsed = new AtUri(post.uri);
1360
const navigate = useNavigate();
1361
+
const [likedPosts, setLikedPosts] = useAtom(likedPostsAtom);
1362
+
const [hasRetweeted, setHasRetweeted] = useState<boolean>(
1363
post.viewer?.repost ? true : false
1364
);
1365
+
const [hasLiked, setHasLiked] = useState<boolean>(
1366
+
post.uri in likedPosts || post.viewer?.like ? true : false
1367
);
1368
+
const [, setComposerPost] = useAtom(composerAtom);
1369
const { agent } = useAuth();
1370
const [likeUri, setLikeUri] = useState<string | undefined>(post.viewer?.like);
1371
const [retweetUri, setRetweetUri] = useState<string | undefined>(
···
1373
);
1374
1375
const likeOrUnlikePost = async () => {
1376
+
const newLikedPosts = { ...likedPosts };
1377
if (!agent) {
1378
console.error("Agent is null or undefined");
1379
return;
1380
}
1381
if (hasLiked) {
1382
+
if (post.uri in likedPosts) {
1383
+
const likeUri = likedPosts[post.uri];
1384
+
setLikeUri(likeUri);
1385
+
}
1386
if (likeUri) {
1387
await agent.deleteLike(likeUri);
1388
setHasLiked(false);
1389
+
delete newLikedPosts[post.uri];
1390
}
1391
} else {
1392
const { uri } = await agent.like(post.uri, post.cid);
1393
setLikeUri(uri);
1394
setHasLiked(true);
1395
+
newLikedPosts[post.uri] = uri;
1396
}
1397
+
setLikedPosts(newLikedPosts);
1398
};
1399
1400
const repostOrUnrepostPost = async () => {
···
1414
}
1415
};
1416
1417
+
const isRepost = repostedby
1418
+
? repostedby
1419
+
: extraOptionalItemInfo
1420
+
? AppBskyFeedDefs.isReasonRepost(extraOptionalItemInfo.reason)
1421
+
? extraOptionalItemInfo.reason?.by.displayName
1422
+
: undefined
1423
+
: undefined;
1424
const isReply = extraOptionalItemInfo
1425
? extraOptionalItemInfo.reply
1426
: undefined;
1427
1428
const emergencySalt = randomString();
1429
+
const fedi = (post.record as { bridgyOriginalText?: string })
1430
+
.bridgyOriginalText;
1431
1432
/* fuck you */
1433
const isMainItem = false;
1434
const setMainItem = (any: any) => {};
1435
+
// eslint-disable-next-line react-hooks/refs
1436
+
console.log("Received ref in UniversalPostRenderer:", ref);
1437
return (
1438
+
<div ref={ref} style={style} data-index={dataIndexPropPass}>
1439
+
<div
1440
+
//ref={ref}
1441
+
key={salt + "-" + (post.uri || emergencySalt)}
1442
+
onClick={
1443
+
isMainItem
1444
? onPostClick
1445
+
: setMainItem
1446
+
? onPostClick
1447
+
? (e) => {
1448
+
setMainItem({ post: post });
1449
+
onPostClick(e);
1450
+
}
1451
+
: () => {
1452
+
setMainItem({ post: post });
1453
+
}
1454
+
: undefined
1455
+
}
1456
style={{
1457
+
//...style,
1458
+
//border: "1px solid #e1e8ed",
1459
+
//borderRadius: 12,
1460
+
opacity: "1 !important",
1461
+
background: "transparent",
1462
+
paddingLeft: isQuote ? 12 : 16,
1463
+
paddingRight: isQuote ? 12 : 16,
1464
+
//paddingTop: 16,
1465
+
paddingTop: isRepost ? 10 : isQuote ? 12 : topReplyLine ? 8 : 16,
1466
+
//paddingBottom: bottomReplyLine ? 0 : 16,
1467
+
paddingBottom: 0,
1468
+
fontFamily: "system-ui, sans-serif",
1469
+
//boxShadow: "0 2px 8px rgba(0,0,0,0.04)",
1470
+
position: "relative",
1471
+
// dont cursor: "pointer",
1472
+
borderBottomWidth: bottomBorder ? (isQuote ? 0 : 1) : 0,
1473
}}
1474
+
className="border-gray-300 dark:border-gray-800"
1475
>
1476
+
{isRepost && (
1477
+
<div
1478
+
style={{
1479
+
marginLeft: 36,
1480
+
display: "flex",
1481
+
borderRadius: 12,
1482
+
paddingBottom: "calc(22px - 1rem)",
1483
+
fontSize: 14,
1484
+
maxHeight: "1rem",
1485
+
justifyContent: "flex-start",
1486
+
//color: theme.textSecondary,
1487
+
gap: 4,
1488
+
alignItems: "center",
1489
+
}}
1490
+
className="text-gray-500 dark:text-gray-400"
1491
+
>
1492
+
<MdiRepost /> Reposted by @{isRepost}{" "}
1493
+
</div>
1494
+
)}
1495
+
{!isQuote && (
1496
+
<div
1497
+
style={{
1498
+
opacity:
1499
+
topReplyLine || isReply /*&& (true || expanded)*/ ? 0.5 : 0,
1500
+
position: "absolute",
1501
+
top: 0,
1502
+
left: 36, // why 36 ???
1503
+
//left: 16 + (42 / 2),
1504
+
width: 2,
1505
+
//height: "100%",
1506
+
height: isRepost
1507
+
? "calc(16px + 1rem - 6px)"
1508
+
: topReplyLine
1509
+
? 8 - 6
1510
+
: 16 - 6,
1511
+
// background: theme.textSecondary,
1512
+
//opacity: 0.5,
1513
+
// no flex here
1514
+
}}
1515
+
className="bg-gray-500 dark:bg-gray-400"
1516
+
/>
1517
+
)}
1518
+
<HoverCard.Root>
1519
+
<HoverCard.Trigger asChild>
1520
<div
1521
+
className={`absolute`}
1522
style={{
1523
+
top: isRepost
1524
+
? "calc(16px + 1rem)"
1525
+
: isQuote
1526
+
? 12
1527
+
: topReplyLine
1528
+
? 8
1529
+
: 16,
1530
+
left: isQuote ? 12 : 16,
1531
}}
1532
+
onClick={onProfileClick}
1533
+
>
1534
+
<img
1535
+
src={post.author.avatar || defaultpfp}
1536
+
alt="avatar"
1537
+
className={`rounded-full object-cover border border-gray-300 dark:border-gray-800 bg-gray-300 dark:bg-gray-600`}
1538
+
style={{
1539
+
width: isQuote ? 16 : 42,
1540
+
height: isQuote ? 16 : 42,
1541
+
}}
1542
+
/>
1543
+
</div>
1544
+
</HoverCard.Trigger>
1545
+
<HoverCard.Portal>
1546
+
<HoverCard.Content
1547
+
className="rounded-md p-4 w-72 bg-gray-50 dark:bg-gray-900 shadow-lg border border-gray-300 dark:border-gray-800 animate-slide-fade z-50"
1548
+
side={"bottom"}
1549
+
sideOffset={5}
1550
+
onClick={onProfileClick}
1551
+
>
1552
+
<div className="flex flex-col gap-2">
1553
+
<div className="flex flex-row">
1554
+
<img
1555
+
src={post.author.avatar || defaultpfp}
1556
+
alt="avatar"
1557
+
className="rounded-full w-[58px] h-[58px] object-cover border border-gray-300 dark:border-gray-800 bg-gray-300 dark:bg-gray-600"
1558
+
/>
1559
+
<div className=" flex-1 flex flex-row align-middle justify-end">
1560
+
<div className=" flex flex-col justify-start">
1561
+
<FollowButton targetdidorhandle={post.author.did} />
1562
+
</div>
1563
+
</div>
1564
+
</div>
1565
+
<div className="flex flex-col gap-3">
1566
+
<div>
1567
+
<div className="text-gray-900 dark:text-gray-100 font-medium text-md">
1568
+
{post.author.displayName || post.author.handle}{" "}
1569
+
</div>
1570
+
<div className="text-gray-500 dark:text-gray-400 text-md flex flex-row gap-1">
1571
+
<Mutual targetdidorhandle={post.author.did} />@{post.author.handle}{" "}
1572
+
</div>
1573
+
</div>
1574
+
{uprrrsauthor?.description && (
1575
+
<div className="text-gray-700 dark:text-gray-300 text-sm text-left break-words line-clamp-3">
1576
+
{uprrrsauthor.description}
1577
+
</div>
1578
+
)}
1579
+
{/* <div className="flex gap-4">
1580
+
<div className="flex gap-1">
1581
+
<div className="font-medium text-gray-900 dark:text-gray-100">
1582
+
0
1583
+
</div>
1584
+
<div className="text-gray-500 dark:text-gray-400">
1585
+
Following
1586
+
</div>
1587
+
</div>
1588
+
<div className="flex gap-1">
1589
+
<div className="font-medium text-gray-900 dark:text-gray-100">
1590
+
2,900
1591
+
</div>
1592
+
<div className="text-gray-500 dark:text-gray-400">
1593
+
Followers
1594
+
</div>
1595
+
</div>
1596
+
</div> */}
1597
+
</div>
1598
+
</div>
1599
+
1600
+
{/* <HoverCard.Arrow className="fill-gray-50 dark:fill-gray-900" /> */}
1601
+
</HoverCard.Content>
1602
+
</HoverCard.Portal>
1603
+
</HoverCard.Root>
1604
+
1605
+
<div style={{ display: "flex", alignItems: "flex-start", zIndex: 2 }}>
1606
+
<div
1607
+
style={{
1608
+
display: "flex",
1609
+
flexDirection: "column",
1610
+
alignSelf: "stretch",
1611
+
alignItems: "center",
1612
+
overflow: "hidden",
1613
+
width: expanded || isQuote ? 0 : "auto",
1614
+
marginRight: expanded || isQuote ? 0 : 12,
1615
+
}}
1616
+
>
1617
+
{/* dummy for later use */}
1618
+
<div style={{ width: 42, height: 42 + 6, minHeight: 42 + 6 }} />
1619
+
{/* reply line !!!! bottomReplyLine */}
1620
+
{bottomReplyLine && (
1621
+
<div
1622
+
style={{
1623
+
width: 2,
1624
+
height: "100%",
1625
+
//background: theme.textSecondary,
1626
+
opacity: 0.5,
1627
+
// no flex here
1628
+
//color: "Red",
1629
+
//zIndex: 99
1630
+
}}
1631
+
className="bg-gray-500 dark:bg-gray-400"
1632
+
/>
1633
+
)}
1634
+
{/* <div
1635
layout
1636
transition={{ duration: 0.2 }}
1637
animate={{ height: expanded ? 0 : '100%' }}
···
1641
// no flex here
1642
}}
1643
/> */}
1644
+
</div>
1645
+
<div style={{ flex: 1, maxWidth: "100%" }}>
1646
<div
1647
style={{
1648
display: "flex",
1649
+
flexDirection: "row",
1650
+
alignItems: "center",
1651
+
flexWrap: "nowrap",
1652
+
maxWidth: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`,
1653
+
width: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`,
1654
+
marginLeft: !expanded ? (isQuote ? 26 : 0) : 54,
1655
+
marginBottom: !expanded ? 4 : 6,
1656
}}
1657
>
1658
+
<div
1659
style={{
1660
display: "flex",
1661
+
//overflow: "hidden", // hey why is overflow hidden unapplied
1662
overflow: "hidden",
1663
textOverflow: "ellipsis",
1664
flexShrink: 1,
1665
+
flexGrow: 1,
1666
+
flexBasis: 0,
1667
+
width: 0,
1668
+
gap: expanded ? 0 : 6,
1669
+
alignItems: expanded ? "flex-start" : "center",
1670
+
flexDirection: expanded ? "column" : "row",
1671
+
height: expanded ? 42 : "1rem",
1672
}}
1673
>
1674
+
<span
1675
+
style={{
1676
+
display: "flex",
1677
+
fontWeight: 700,
1678
+
fontSize: 16,
1679
+
overflow: "hidden",
1680
+
textOverflow: "ellipsis",
1681
+
whiteSpace: "nowrap",
1682
+
flexShrink: 1,
1683
+
minWidth: 0,
1684
+
gap: 4,
1685
+
alignItems: "center",
1686
+
//color: theme.text,
1687
+
}}
1688
+
className="text-gray-900 dark:text-gray-100"
1689
+
>
1690
+
{/* verified checkmark */}
1691
+
{post.author.displayName || post.author.handle}{" "}
1692
+
{post.author.verification?.verifiedStatus == "valid" && (
1693
+
<MdiVerified />
1694
+
)}
1695
+
</span>
1696
1697
+
<span
1698
+
style={{
1699
+
//color: theme.textSecondary,
1700
+
fontSize: 16,
1701
+
overflowX: "hidden",
1702
+
textOverflow: "ellipsis",
1703
+
whiteSpace: "nowrap",
1704
+
flexShrink: 1,
1705
+
flexGrow: 0,
1706
+
minWidth: 0,
1707
+
}}
1708
+
className="text-gray-500 dark:text-gray-400"
1709
+
>
1710
+
@{post.author.handle}
1711
+
</span>
1712
+
</div>
1713
+
<div
1714
style={{
1715
+
display: "flex",
1716
+
alignItems: "center",
1717
+
height: "1rem",
1718
}}
1719
>
1720
+
<span
1721
+
style={{
1722
+
//color: theme.textSecondary,
1723
+
fontSize: 16,
1724
+
marginLeft: 8,
1725
+
whiteSpace: "nowrap",
1726
+
flexShrink: 0,
1727
+
maxWidth: "100%",
1728
+
}}
1729
+
className="text-gray-500 dark:text-gray-400"
1730
+
>
1731
+
ยท {/* time placeholder */}
1732
+
{shortTimeAgo(post.indexedAt)}
1733
+
</span>
1734
+
</div>
1735
</div>
1736
+
{/* reply indicator */}
1737
+
{!!feedviewpostreplyhandle && (
1738
+
<div
1739
style={{
1740
+
display: "flex",
1741
+
borderRadius: 12,
1742
+
paddingBottom: 2,
1743
+
fontSize: 14,
1744
+
justifyContent: "flex-start",
1745
//color: theme.textSecondary,
1746
+
gap: 4,
1747
+
alignItems: "center",
1748
+
//marginLeft: 36,
1749
+
height:
1750
+
!(expanded || isQuote) && !!feedviewpostreplyhandle
1751
+
? "1rem"
1752
+
: 0,
1753
+
opacity:
1754
+
!(expanded || isQuote) && !!feedviewpostreplyhandle ? 1 : 0,
1755
}}
1756
className="text-gray-500 dark:text-gray-400"
1757
>
1758
+
<MdiReply /> Reply to @{feedviewpostreplyhandle}
1759
+
</div>
1760
+
)}
1761
<div
1762
style={{
1763
+
fontSize: 16,
1764
+
marginBottom: !post.embed /*|| depth > 0*/ ? 0 : 8,
1765
+
whiteSpace: "pre-wrap",
1766
+
textAlign: "left",
1767
+
overflowWrap: "anywhere",
1768
+
wordBreak: "break-word",
1769
+
//color: theme.text,
1770
}}
1771
+
className="text-gray-900 dark:text-gray-100"
1772
>
1773
+
{fedi ? (
1774
+
<>
1775
+
<span
1776
+
className="dangerousFediContent"
1777
+
dangerouslySetInnerHTML={{
1778
+
__html: DOMPurify.sanitize(fedi),
1779
+
}}
1780
+
/>
1781
+
</>
1782
+
) : (
1783
+
<>
1784
+
{renderTextWithFacets({
1785
+
text: (post.record as { text?: string }).text ?? "",
1786
+
facets: (post.record.facets as Facet[]) ?? [],
1787
+
navigate: navigate,
1788
+
})}
1789
+
</>
1790
+
)}
1791
</div>
1792
+
{post.embed && depth < 1 ? (
1793
+
<PostEmbeds
1794
+
embed={post.embed}
1795
+
//moderation={moderation}
1796
+
viewContext={PostEmbedViewContext.Feed}
1797
+
salt={salt}
1798
+
navigate={navigate}
1799
+
postid={{ did: post.author.did, rkey: parsed.rkey }}
1800
+
nopics={nopics}
1801
+
lightboxCallback={lightboxCallback}
1802
+
/>
1803
+
) : null}
1804
+
{post.embed && depth > 0 && (
1805
+
/* pretty bad hack imo. its trying to sync up with how the embed shim doesnt
1806
+
hydrate embeds this deep but the connection here is implicit
1807
+
todo: idk make this a real part of the embed shim so its not implicit */
1808
+
<>
1809
+
<div className="border-gray-300 dark:border-gray-800 p-3 rounded-xl border italic text-gray-400 text-[14px]">
1810
+
(there is an embed here thats too deep to render)
1811
+
</div>
1812
+
</>
1813
+
)}
1814
+
<div style={{ paddingTop: post.embed && depth < 1 ? 4 : 0 }}>
1815
+
<>
1816
+
{expanded && (
1817
+
<div
1818
+
style={{
1819
+
overflow: "hidden",
1820
+
//color: theme.textSecondary,
1821
+
fontSize: 14,
1822
+
display: "flex",
1823
+
borderBottomStyle: "solid",
1824
+
//borderBottomColor: theme.border,
1825
+
//background: "#f00",
1826
+
// height: "1rem",
1827
+
paddingTop: 4,
1828
+
paddingBottom: 8,
1829
+
borderBottomWidth: 1,
1830
+
marginBottom: 8,
1831
+
}} // important for height animation
1832
+
className="text-gray-500 dark:text-gray-400 border-gray-200 dark:border-gray-800 was7"
1833
+
>
1834
+
{fullDateTimeFormat(post.indexedAt)}
1835
+
</div>
1836
+
)}
1837
+
</>
1838
+
{!isQuote && (
1839
<div
1840
style={{
1841
display: "flex",
1842
+
gap: 32,
1843
+
paddingTop: 8,
1844
+
//color: theme.textSecondary,
1845
+
fontSize: 15,
1846
+
justifyContent: "space-between",
1847
+
//background: "#0f0",
1848
}}
1849
+
className="text-gray-500 dark:text-gray-400"
1850
>
1851
<HitSlopButton
1852
+
onClick={() => {
1853
+
setComposerPost({ kind: "reply", parent: post.uri });
1854
}}
1855
style={{
1856
...btnstyle,
1857
}}
1858
>
1859
+
<MdiCommentOutline />
1860
+
{post.replyCount}
1861
</HitSlopButton>
1862
+
<DropdownMenu.Root modal={false}>
1863
+
<DropdownMenu.Trigger asChild>
1864
+
<div
1865
+
style={{
1866
+
...btnstyle,
1867
+
...(hasRetweeted ? { color: "#5CEFAA" } : {}),
1868
+
}}
1869
+
aria-label="Repost or quote post"
1870
+
>
1871
+
{hasRetweeted ? <MdiRepeatGreen /> : <MdiRepeat />}
1872
+
{post.repostCount ?? 0}
1873
+
</div>
1874
+
</DropdownMenu.Trigger>
1875
+
1876
+
<DropdownMenu.Portal>
1877
+
<DropdownMenu.Content
1878
+
align="start"
1879
+
sideOffset={5}
1880
+
className="bg-white dark:bg-gray-800 rounded-lg shadow-xl border border-gray-200 dark:border-gray-700 w-32 z-50 overflow-hidden"
1881
+
>
1882
+
<DropdownMenu.Item
1883
+
onSelect={repostOrUnrepostPost}
1884
+
className="px-3 py-2 text-sm flex items-center gap-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-700"
1885
+
>
1886
+
<MdiRepeat
1887
+
className={hasRetweeted ? "text-green-400" : ""}
1888
+
/>
1889
+
<span>{hasRetweeted ? "Undo Repost" : "Repost"}</span>
1890
+
</DropdownMenu.Item>
1891
+
1892
+
<DropdownMenu.Item
1893
+
onSelect={() => {
1894
+
setComposerPost({
1895
+
kind: "quote",
1896
+
subject: post.uri,
1897
+
});
1898
+
}}
1899
+
className="px-3 py-2 text-sm flex items-center gap-2 cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-700"
1900
+
>
1901
+
{/* You might want a specific quote icon here */}
1902
+
<MdiCommentOutline />
1903
+
<span>Quote</span>
1904
+
</DropdownMenu.Item>
1905
+
</DropdownMenu.Content>
1906
+
</DropdownMenu.Portal>
1907
+
</DropdownMenu.Root>
1908
+
<HitSlopButton
1909
+
onClick={() => {
1910
+
likeOrUnlikePost();
1911
+
}}
1912
+
style={{
1913
+
...btnstyle,
1914
+
...(hasLiked ? { color: "#EC4899" } : {}),
1915
+
}}
1916
+
>
1917
+
{hasLiked ? <MdiCardsHeart /> : <MdiCardsHeartOutline />}
1918
+
{(post.likeCount || 0) + (hasLiked ? 1 : 0)}
1919
+
</HitSlopButton>
1920
+
<div style={{ display: "flex", gap: 8 }}>
1921
+
<HitSlopButton
1922
+
onClick={async (e) => {
1923
+
e.stopPropagation();
1924
+
try {
1925
+
await navigator.clipboard.writeText(
1926
+
"https://bsky.app" +
1927
+
"/profile/" +
1928
+
post.author.handle +
1929
+
"/post/" +
1930
+
post.uri.split("/").pop()
1931
+
);
1932
+
} catch (_e) {
1933
+
// idk
1934
+
}
1935
+
}}
1936
+
style={{
1937
+
...btnstyle,
1938
+
}}
1939
+
>
1940
+
<MdiShareVariant />
1941
+
</HitSlopButton>
1942
+
<span style={btnstyle}>
1943
+
<MdiMoreHoriz />
1944
+
</span>
1945
+
</div>
1946
</div>
1947
+
)}
1948
+
</div>
1949
+
<div
1950
+
style={{
1951
+
//height: bottomReplyLine ? 16 : 0
1952
+
height: isQuote ? 12 : 16,
1953
+
}}
1954
+
/>
1955
</div>
1956
</div>
1957
</div>
1958
</div>
···
2044
viewContext,
2045
salt,
2046
navigate,
2047
+
postid,
2048
+
nopics,
2049
+
lightboxCallback,
2050
}: {
2051
embed?: Embed;
2052
moderation?: ModerationDecision;
···
2054
allowNestedQuotes?: boolean;
2055
viewContext?: PostEmbedViewContext;
2056
salt: string;
2057
+
navigate: (_: any) => void;
2058
+
postid?: { did: string; rkey: string };
2059
+
nopics?: boolean;
2060
+
lightboxCallback?: (d: LightboxProps) => void;
2061
}) {
2062
+
//const [lightboxIndex, setLightboxIndex] = useState<number | null>(null);
2063
+
function setLightboxIndex(number: number) {
2064
+
navigate({
2065
+
to: "/profile/$did/post/$rkey/image/$i",
2066
+
params: {
2067
+
did: postid?.did,
2068
+
rkey: postid?.rkey,
2069
+
i: number.toString(),
2070
+
},
2071
+
});
2072
+
}
2073
if (
2074
AppBskyEmbedRecordWithMedia.isView(embed) &&
2075
AppBskyEmbedRecord.isViewRecord(embed.record.record) &&
···
2103
viewContext={viewContext}
2104
salt={salt}
2105
navigate={navigate}
2106
+
postid={postid}
2107
+
nopics={nopics}
2108
+
lightboxCallback={lightboxCallback}
2109
/>
2110
{/* padding empty div of 8px height */}
2111
<div style={{ height: 12 }} />
···
2119
//boxShadow: theme.cardShadow,
2120
overflow: "hidden",
2121
}}
2122
+
className="shadow border border-gray-200 dark:border-gray-800 was7"
2123
>
2124
<UniversalPostRenderer
2125
post={post}
···
2127
salt={salt}
2128
onPostClick={(e) => {
2129
e.stopPropagation();
2130
+
const parsed = new AtUri(post.uri); //parseAtUri(post.uri);
2131
if (parsed) {
2132
navigate({
2133
to: "/profile/$did/post/$rkey",
2134
+
params: { did: parsed.host, rkey: parsed.rkey },
2135
});
2136
}
2137
}}
···
2236
//boxShadow: theme.cardShadow,
2237
overflow: "hidden",
2238
}}
2239
+
className="shadow border border-gray-200 dark:border-gray-800 was7"
2240
>
2241
<UniversalPostRenderer
2242
post={post}
···
2244
salt={salt}
2245
onPostClick={(e) => {
2246
e.stopPropagation();
2247
+
const parsed = new AtUri(post.uri); //parseAtUri(post.uri);
2248
if (parsed) {
2249
navigate({
2250
to: "/profile/$did/post/$rkey",
2251
+
params: { did: parsed.host, rkey: parsed.rkey },
2252
});
2253
}
2254
}}
···
2280
src: img.fullsize,
2281
alt: img.alt,
2282
}));
2283
+
console.log("rendering images");
2284
+
if (lightboxCallback) {
2285
+
lightboxCallback({ images: lightboxImages });
2286
+
console.log("rendering images");
2287
+
}
2288
+
2289
+
if (nopics) return;
2290
2291
if (images.length > 0) {
2292
// const items = embed.images.map(img => ({
···
2316
//border: `1px solid ${theme.border}`,
2317
overflow: "hidden",
2318
}}
2319
+
className="border border-gray-200 dark:border-gray-800 was7 bg-gray-200 dark:bg-gray-900"
2320
>
2321
+
{/* {lightboxIndex !== null && (
2322
<Lightbox
2323
images={lightboxImages}
2324
index={lightboxIndex}
2325
onClose={() => setLightboxIndex(null)}
2326
onNavigate={(newIndex) => setLightboxIndex(newIndex)}
2327
+
post={postid}
2328
/>
2329
+
)} */}
2330
<img
2331
src={image.fullsize}
2332
alt={image.alt}
···
2357
overflow: "hidden",
2358
//border: `1px solid ${theme.border}`,
2359
}}
2360
+
className="border border-gray-200 dark:border-gray-800 was7"
2361
>
2362
+
{/* {lightboxIndex !== null && (
2363
<Lightbox
2364
images={lightboxImages}
2365
index={lightboxIndex}
2366
onClose={() => setLightboxIndex(null)}
2367
onNavigate={(newIndex) => setLightboxIndex(newIndex)}
2368
+
post={postid}
2369
/>
2370
+
)} */}
2371
{images.map((img, i) => (
2372
<div
2373
key={i}
···
2407
//border: `1px solid ${theme.border}`,
2408
// height: 240, // fixed height for cropping
2409
}}
2410
+
className="border border-gray-200 dark:border-gray-800 was7"
2411
>
2412
+
{/* {lightboxIndex !== null && (
2413
<Lightbox
2414
images={lightboxImages}
2415
index={lightboxIndex}
2416
onClose={() => setLightboxIndex(null)}
2417
onNavigate={(newIndex) => setLightboxIndex(newIndex)}
2418
+
post={postid}
2419
/>
2420
+
)} */}
2421
{/* Left: 1:1 */}
2422
<div
2423
style={{ flex: 1, aspectRatio: "1 / 1", position: "relative" }}
···
2492
//border: `1px solid ${theme.border}`,
2493
//aspectRatio: "3 / 2", // overall grid aspect
2494
}}
2495
+
className="border border-gray-200 dark:border-gray-800 was7"
2496
>
2497
+
{/* {lightboxIndex !== null && (
2498
<Lightbox
2499
images={lightboxImages}
2500
index={lightboxIndex}
2501
onClose={() => setLightboxIndex(null)}
2502
onNavigate={(newIndex) => setLightboxIndex(newIndex)}
2503
+
post={postid}
2504
/>
2505
+
)} */}
2506
{images.map((img, i) => (
2507
<div
2508
key={i}
···
2593
return <div />;
2594
}
2595
2596
function getDomain(url: string) {
2597
try {
2598
const { hostname } = new URL(url);
···
2623
for (let i = 0; i < bytes.length; i++) {
2624
map[byteIndex++] = charIndex;
2625
}
2626
+
charIndex += char.length;
2627
}
2628
2629
return map;
···
2657
return { start, end, feature: f.features[0] };
2658
});
2659
}
2660
+
export function renderTextWithFacets({
2661
text,
2662
facets,
2663
navigate,
2664
}: {
2665
text: string;
2666
facets: Facet[];
2667
+
navigate: (_: any) => void;
2668
}) {
2669
const ranges = extractFacetRanges(text, facets).sort(
2670
(a: any, b: any) => a.start - b.start
···
2679
}
2680
2681
const fragment = text.slice(start, end);
2682
+
// @ts-expect-error i didnt bother with the correct types here sorry. bsky api types are cursed
2683
if (feature.$type === "app.bsky.richtext.facet#link" && feature.uri) {
2684
result.push(
2685
<a
2686
+
// @ts-expect-error i didnt bother with the correct types here sorry. bsky api types are cursed
2687
href={feature.uri}
2688
key={start}
2689
className="link"
···
2703
);
2704
} else if (
2705
feature.$type === "app.bsky.richtext.facet#mention" &&
2706
+
// @ts-expect-error i didnt bother with the correct types here sorry. bsky api types are cursed
2707
feature.did
2708
) {
2709
result.push(
···
2715
e.stopPropagation();
2716
navigate({
2717
to: "/profile/$did",
2718
+
// @ts-expect-error i didnt bother with the correct types here sorry. bsky api types are cursed
2719
+
params: { did: feature.did },
2720
});
2721
}}
2722
>
···
2812
rel="noopener noreferrer"
2813
onClick={(e) => {
2814
e.stopPropagation();
2815
+
if (onOpen) onOpen();
2816
}}
2817
+
/* @ts-expect-error css arent typed or something idk fuck you */
2818
style={linkStyle}
2819
className="text-gray-500 dark:text-gray-400"
2820
>
2821
<div
2822
style={containerStyle as React.CSSProperties}
2823
+
className="border border-gray-200 dark:border-gray-800 was7"
2824
>
2825
{thumb && (
2826
<div
···
2834
marginBottom: 8,
2835
//borderBottom: `1px solid ${theme.border}`,
2836
}}
2837
+
className="border-b border-gray-200 dark:border-gray-800 was7"
2838
>
2839
<img
2840
src={thumb}
···
2858
paddingTop: thumb ? 0 : 12,
2859
}}
2860
>
2861
+
{/* @ts-expect-error css */}
2862
<div style={titleStyle} className="text-gray-900 dark:text-gray-100">
2863
{title}
2864
</div>
2865
<div
2866
style={descriptionStyle as React.CSSProperties}
2867
className="text-gray-500 dark:text-gray-400"
···
2960
borderRadius: 12,
2961
//border: `1px solid ${theme.border}`,
2962
}}
2963
+
className="border border-gray-200 dark:border-gray-800 was7"
2964
onClick={async (e) => {
2965
e.stopPropagation();
2966
setPlaying(true);
···
3001
100 / (aspect ? aspect.width / aspect.height : 16 / 9)
3002
}%`, // 16:9 = 56.25%, 4:3 = 75%
3003
}}
3004
+
className="border border-gray-200 dark:border-gray-800 was7"
3005
>
3006
<ReactPlayer
3007
src={url}
+59
src/components/radix-m3-rd/Button.tsx
+59
src/components/radix-m3-rd/Button.tsx
···
···
1
+
import { Slot } from "@radix-ui/react-slot";
2
+
import clsx from "clsx";
3
+
import * as React from "react";
4
+
5
+
export type ButtonVariant = "filled" | "outlined" | "text" | "secondary";
6
+
export type ButtonSize = "sm" | "md" | "lg";
7
+
8
+
const variantClasses: Record<ButtonVariant, string> = {
9
+
filled:
10
+
"bg-gray-300 text-gray-900 hover:bg-gray-400 dark:bg-gray-600 dark:text-white dark:hover:bg-gray-500",
11
+
secondary:
12
+
"bg-gray-300 text-gray-900 hover:bg-gray-400 dark:bg-gray-600 dark:text-white dark:hover:bg-gray-500",
13
+
outlined:
14
+
"border border-gray-800 text-gray-800 hover:bg-gray-100 dark:border-gray-200 dark:text-gray-200 dark:hover:bg-gray-800/10",
15
+
text: "bg-transparent text-gray-800 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-800/10",
16
+
};
17
+
18
+
const sizeClasses: Record<ButtonSize, string> = {
19
+
sm: "px-3 py-1.5 text-sm",
20
+
md: "px-4 py-2 text-base",
21
+
lg: "px-6 py-3 text-lg",
22
+
};
23
+
24
+
export function Button({
25
+
variant = "filled",
26
+
size = "md",
27
+
asChild = false,
28
+
ref,
29
+
className,
30
+
children,
31
+
...props
32
+
}: {
33
+
variant?: ButtonVariant;
34
+
size?: ButtonSize;
35
+
asChild?: boolean;
36
+
className?: string;
37
+
children?: React.ReactNode;
38
+
ref?: React.Ref<HTMLButtonElement>;
39
+
} & React.ComponentPropsWithoutRef<"button">) {
40
+
const Comp = asChild ? Slot : "button";
41
+
42
+
return (
43
+
<Comp
44
+
ref={ref}
45
+
className={clsx(
46
+
//focus:outline-none focus:ring-1 focus:ring-offset-1 focus:ring-gray-500 dark:focus:ring-gray-300
47
+
"inline-flex items-center justify-center rounded-full transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
48
+
variantClasses[variant],
49
+
sizeClasses[size],
50
+
className
51
+
)}
52
+
{...props}
53
+
>
54
+
{children}
55
+
</Comp>
56
+
);
57
+
}
58
+
59
+
Button.displayName = "Button";
+77
-12
src/main.tsx
+77
-12
src/main.tsx
···
1
-
import { StrictMode } from "react";
2
import ReactDOM from "react-dom/client";
3
-
import { RouterProvider, createRouter } from "@tanstack/react-router";
4
5
// Import the generated route tree
6
import { routeTree } from "./routeTree.gen";
7
8
-
import "~/styles/app.css";
9
-
import reportWebVitals from "./reportWebVitals.ts";
10
-
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
11
12
-
const queryClient = new QueryClient();
13
// Create a new router instance
14
const router = createRouter({
15
routeTree,
···
33
const root = ReactDOM.createRoot(rootElement);
34
root.render(
35
// double queries annoys me
36
-
<StrictMode>
37
-
<QueryClientProvider client={queryClient}>
38
-
<RouterProvider router={router} />
39
-
</QueryClientProvider>
40
-
</StrictMode>
41
);
42
}
43
44
// If you want to start measuring performance in your app, pass a function
45
-
// to log results (for example: reportWebVitals(console.log))
46
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
47
reportWebVitals();
···
1
+
import "~/styles/app.css";
2
+
3
+
import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister";
4
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
5
+
import { persistQueryClient } from "@tanstack/react-query-persist-client";
6
+
import { createRouter, RouterProvider } from "@tanstack/react-router";
7
+
import { useSetAtom } from "jotai";
8
+
import { useEffect } from "react";
9
+
//import { StrictMode } from "react";
10
import ReactDOM from "react-dom/client";
11
12
+
import reportWebVitals from "./reportWebVitals.ts";
13
// Import the generated route tree
14
import { routeTree } from "./routeTree.gen";
15
+
import { isAtTopAtom } from "./utils/atoms.ts";
16
17
+
//initAtomToCssVar(hueAtom, "--tw-gray-hue")
18
+
19
+
const queryClient = new QueryClient({
20
+
defaultOptions: {
21
+
queries: {
22
+
gcTime: 1000 * 60 * 60 * 24 * 24, // 24 days
23
+
},
24
+
},
25
+
});
26
+
const localStoragePersister = createSyncStoragePersister({
27
+
storage: window.localStorage,
28
+
});
29
+
30
+
persistQueryClient({
31
+
queryClient,
32
+
persister: localStoragePersister,
33
+
});
34
35
// Create a new router instance
36
const router = createRouter({
37
routeTree,
···
55
const root = ReactDOM.createRoot(rootElement);
56
root.render(
57
// double queries annoys me
58
+
// <StrictMode>
59
+
<QueryClientProvider client={queryClient}>
60
+
<ScrollTopWatcher />
61
+
<RouterProvider router={router} />
62
+
</QueryClientProvider>
63
+
// </StrictMode>
64
);
65
}
66
67
// If you want to start measuring performance in your app, pass a function
68
+
// to log results (for example: reportWebVitals(// /*mass comment*/ console.log))
69
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
70
reportWebVitals();
71
+
72
+
export default function ScrollTopWatcher() {
73
+
const setIsAtTop = useSetAtom(isAtTopAtom);
74
+
useEffect(() => {
75
+
const meta = document.querySelector('meta[name="theme-color"]');
76
+
let lastAtTop = window.scrollY === 0;
77
+
let timeoutId: number | undefined;
78
+
79
+
const setVars = (atTop: boolean) => {
80
+
const root = document.documentElement;
81
+
root.style.setProperty("--is-top", atTop ? "1" : "0");
82
+
83
+
const bg = getComputedStyle(root).getPropertyValue("--header-bg").trim();
84
+
if (meta && bg) meta.setAttribute("content", bg);
85
+
setIsAtTop(atTop);
86
+
};
87
+
88
+
const check = () => {
89
+
const atTop = window.scrollY === 0;
90
+
if (atTop !== lastAtTop) {
91
+
lastAtTop = atTop;
92
+
setVars(atTop);
93
+
}
94
+
};
95
+
96
+
const handleScroll = () => {
97
+
if (timeoutId) clearTimeout(timeoutId);
98
+
timeoutId = window.setTimeout(check, 2);
99
+
};
100
+
101
+
// initialize
102
+
setVars(lastAtTop);
103
+
window.addEventListener("scroll", handleScroll, { passive: true });
104
+
105
+
return () => {
106
+
window.removeEventListener("scroll", handleScroll);
107
+
if (timeoutId) clearTimeout(timeoutId);
108
+
};
109
+
}, []);
110
+
111
+
return null;
112
+
}
-149
src/providers/PassAuthProvider.tsx
-149
src/providers/PassAuthProvider.tsx
···
1
-
import React, { createContext, useState, useEffect, useContext } from "react";
2
-
import { AtpAgent, type AtpSessionData } from "@atproto/api";
3
-
4
-
interface AuthContextValue {
5
-
agent: AtpAgent | null;
6
-
loginStatus: boolean;
7
-
login: (user: string, password: string, service?: string) => Promise<void>;
8
-
logout: () => Promise<void>;
9
-
loading: boolean;
10
-
authed: boolean | undefined;
11
-
}
12
-
13
-
const AuthContext = createContext<AuthContextValue>({} as AuthContextValue);
14
-
15
-
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
16
-
const [agent, setAgent] = useState<AtpAgent | null>(null);
17
-
const [loginStatus, setLoginStatus] = useState(false);
18
-
const [loading, setLoading] = useState(true);
19
-
const [increment, setIncrement] = useState(0);
20
-
const [authed, setAuthed] = useState<boolean | undefined>(undefined);
21
-
22
-
useEffect(() => {
23
-
const initialize = async () => {
24
-
try {
25
-
const service = localStorage.getItem("service");
26
-
// const user = await AsyncStorage.getItem('user');
27
-
// const password = await AsyncStorage.getItem('password');
28
-
const session = localStorage.getItem("sess");
29
-
30
-
if (service && session) {
31
-
console.log("Auto-login service is:", service);
32
-
const apiAgent = new AtpAgent({ service });
33
-
try {
34
-
if (!apiAgent) {
35
-
console.log("Agent is null or undefined");
36
-
return;
37
-
}
38
-
let sess: AtpSessionData = JSON.parse(session);
39
-
console.log("resuming session is:", sess);
40
-
const { data } = await apiAgent.resumeSession(sess);
41
-
console.log("!!!8!!! agent resume session");
42
-
setAgent(apiAgent);
43
-
setLoginStatus(true);
44
-
setLoading(false);
45
-
setAuthed(true);
46
-
} catch (e) {
47
-
console.log("Failed to resume session" + e);
48
-
setLoginStatus(true);
49
-
localStorage.removeItem("sess");
50
-
localStorage.removeItem("service");
51
-
const apiAgent = new AtpAgent({ service: "https://api.bsky.app" });
52
-
setAgent(apiAgent);
53
-
setLoginStatus(true);
54
-
setLoading(false);
55
-
setAuthed(false);
56
-
return;
57
-
}
58
-
} else {
59
-
const apiAgent = new AtpAgent({ service: "https://api.bsky.app" });
60
-
setAgent(apiAgent);
61
-
setLoginStatus(true);
62
-
setLoading(false);
63
-
setAuthed(false);
64
-
}
65
-
} catch (e) {
66
-
console.log("Failed to auto-login:", e);
67
-
} finally {
68
-
setLoading(false);
69
-
}
70
-
};
71
-
72
-
initialize();
73
-
}, [increment]);
74
-
75
-
const login = async (
76
-
user: string,
77
-
password: string,
78
-
service: string = "https://bsky.social",
79
-
) => {
80
-
try {
81
-
let sessionthing;
82
-
const apiAgent = new AtpAgent({
83
-
service: service,
84
-
persistSession: (evt, sess) => {
85
-
sessionthing = sess;
86
-
},
87
-
});
88
-
await apiAgent.login({ identifier: user, password });
89
-
console.log("!!!8!!! agent logged on");
90
-
91
-
localStorage.setItem("service", service);
92
-
// await AsyncStorage.setItem('user', user);
93
-
// await AsyncStorage.setItem('password', password);
94
-
if (sessionthing) {
95
-
localStorage.setItem("sess", JSON.stringify(sessionthing));
96
-
} else {
97
-
localStorage.setItem("sess", "{}");
98
-
}
99
-
100
-
setAgent(apiAgent);
101
-
setLoginStatus(true);
102
-
setAuthed(true);
103
-
} catch (e) {
104
-
console.error("Login failed:", e);
105
-
}
106
-
};
107
-
108
-
const logout = async () => {
109
-
if (!agent) {
110
-
console.error("Agent is null or undefined");
111
-
return;
112
-
}
113
-
setLoading(true);
114
-
try {
115
-
// check if its even in async storage before removing
116
-
if (localStorage.getItem("service") && localStorage.getItem("sess")) {
117
-
localStorage.removeItem("service");
118
-
localStorage.removeItem("sess");
119
-
}
120
-
await agent.logout();
121
-
console.log("!!!8!!! agent logout");
122
-
setLoginStatus(false);
123
-
setAuthed(undefined);
124
-
await agent.com.atproto.server.deleteSession();
125
-
console.log("!!!8!!! agent deltesession");
126
-
//setAgent(null);
127
-
setIncrement(increment + 1);
128
-
} catch (e) {
129
-
console.error("Logout failed:", e);
130
-
} finally {
131
-
setLoading(false);
132
-
}
133
-
};
134
-
135
-
// why the hell are we doing this
136
-
/*if (loading) {
137
-
return <div><span>Laoding...ae</span></div>;
138
-
}*/
139
-
140
-
return (
141
-
<AuthContext.Provider
142
-
value={{ agent, loginStatus, login, logout, loading, authed }}
143
-
>
144
-
{children}
145
-
</AuthContext.Provider>
146
-
);
147
-
};
148
-
149
-
export const useAuth = () => useContext(AuthContext);
···
-61
src/providers/PersistentStoreProvider.tsx
-61
src/providers/PersistentStoreProvider.tsx
···
1
-
import React, { createContext, useContext, useCallback } from "react";
2
-
import { get as idbGet, set as idbSet, del as idbDel } from "idb-keyval";
3
-
4
-
type PersistentValue = {
5
-
value: string;
6
-
time: number;
7
-
};
8
-
9
-
type PersistentStoreContextType = {
10
-
get: (key: string) => Promise<PersistentValue | null>;
11
-
set: (key: string, value: string) => Promise<void>;
12
-
remove: (key: string) => Promise<void>;
13
-
};
14
-
15
-
const PersistentStoreContext = createContext<PersistentStoreContextType | null>(
16
-
null,
17
-
);
18
-
19
-
export const PersistentStoreProvider: React.FC<{
20
-
children: React.ReactNode;
21
-
}> = ({ children }) => {
22
-
const get = useCallback(
23
-
async (key: string): Promise<PersistentValue | null> => {
24
-
if (typeof window === "undefined") return null;
25
-
const raw = await idbGet(key);
26
-
if (!raw) return null;
27
-
try {
28
-
return JSON.parse(raw) as PersistentValue;
29
-
} catch {
30
-
return null;
31
-
}
32
-
},
33
-
[],
34
-
);
35
-
36
-
const set = useCallback(async (key: string, value: string) => {
37
-
if (typeof window === "undefined") return;
38
-
const entry: PersistentValue = { value, time: Date.now() };
39
-
await idbSet(key, JSON.stringify(entry));
40
-
}, []);
41
-
42
-
const remove = useCallback(async (key: string) => {
43
-
if (typeof window === "undefined") return;
44
-
await idbDel(key);
45
-
}, []);
46
-
47
-
return (
48
-
<PersistentStoreContext.Provider value={{ get, set, remove }}>
49
-
{children}
50
-
</PersistentStoreContext.Provider>
51
-
);
52
-
};
53
-
54
-
export const usePersistentStore = (): PersistentStoreContextType => {
55
-
const context = useContext(PersistentStoreContext);
56
-
if (!context)
57
-
throw new Error(
58
-
"usePersistentStore must be used within a PersistentStoreProvider",
59
-
);
60
-
return context;
61
-
};
···
+209
src/providers/UnifiedAuthProvider.tsx
+209
src/providers/UnifiedAuthProvider.tsx
···
···
1
+
import { Agent, AtpAgent, type AtpSessionData } from "@atproto/api";
2
+
import {
3
+
type OAuthSession,
4
+
TokenInvalidError,
5
+
TokenRefreshError,
6
+
TokenRevokedError,
7
+
} from "@atproto/oauth-client-browser";
8
+
import { useAtom } from "jotai";
9
+
import React, {
10
+
createContext,
11
+
use,
12
+
useCallback,
13
+
useEffect,
14
+
useState,
15
+
} from "react";
16
+
17
+
import { quickAuthAtom } from "~/utils/atoms";
18
+
19
+
import { oauthClient } from "../utils/oauthClient";
20
+
21
+
type AuthStatus = "loading" | "signedIn" | "signedOut";
22
+
type AuthMethod = "password" | "oauth" | null;
23
+
24
+
interface AuthContextValue {
25
+
agent: Agent | null;
26
+
status: AuthStatus;
27
+
authMethod: AuthMethod;
28
+
loginWithPassword: (
29
+
user: string,
30
+
password: string,
31
+
service?: string,
32
+
) => Promise<void>;
33
+
loginWithOAuth: (handleOrPdsUrl: string) => Promise<void>;
34
+
logout: () => Promise<void>;
35
+
}
36
+
37
+
const AuthContext = createContext<AuthContextValue>({} as AuthContextValue);
38
+
39
+
export const UnifiedAuthProvider = ({
40
+
children,
41
+
}: {
42
+
children: React.ReactNode;
43
+
}) => {
44
+
const [agent, setAgent] = useState<Agent | null>(null);
45
+
const [status, setStatus] = useState<AuthStatus>("loading");
46
+
const [authMethod, setAuthMethod] = useState<AuthMethod>(null);
47
+
const [oauthSession, setOauthSession] = useState<OAuthSession | null>(null);
48
+
const [quickAuth, setQuickAuth] = useAtom(quickAuthAtom);
49
+
50
+
const initialize = useCallback(async () => {
51
+
try {
52
+
const oauthResult = await oauthClient.init();
53
+
if (oauthResult) {
54
+
// /*mass comment*/ console.log("OAuth session restored.");
55
+
const apiAgent = new Agent(oauthResult.session);
56
+
setAgent(apiAgent);
57
+
setOauthSession(oauthResult.session);
58
+
setAuthMethod("oauth");
59
+
setStatus("signedIn");
60
+
setQuickAuth(apiAgent?.did || null);
61
+
return;
62
+
}
63
+
} catch (e) {
64
+
console.error("OAuth init failed, checking password session.", e);
65
+
if (!quickAuth) {
66
+
// quickAuth restoration. if last used method is oauth we immediately call for oauth redo
67
+
// (and set a persistent atom somewhere to not retry again if it failed)
68
+
}
69
+
}
70
+
71
+
try {
72
+
const service = localStorage.getItem("service");
73
+
const sessionString = localStorage.getItem("sess");
74
+
75
+
if (service && sessionString) {
76
+
// /*mass comment*/ console.log("Resuming password-based session using AtpAgent...");
77
+
const apiAgent = new AtpAgent({ service });
78
+
const session: AtpSessionData = JSON.parse(sessionString);
79
+
await apiAgent.resumeSession(session);
80
+
81
+
// /*mass comment*/ console.log("Password-based session resumed successfully.");
82
+
setAgent(apiAgent);
83
+
setAuthMethod("password");
84
+
setStatus("signedIn");
85
+
setQuickAuth(apiAgent?.did || null);
86
+
return;
87
+
}
88
+
} catch (e) {
89
+
console.error("Failed to resume password-based session.", e);
90
+
localStorage.removeItem("sess");
91
+
localStorage.removeItem("service");
92
+
}
93
+
94
+
// /*mass comment*/ console.log("No active session found.");
95
+
setStatus("signedOut");
96
+
setAgent(null);
97
+
setAuthMethod(null);
98
+
// do we want to null it here?
99
+
setQuickAuth(null);
100
+
}, [quickAuth, setQuickAuth]);
101
+
102
+
useEffect(() => {
103
+
const handleOAuthSessionDeleted = (
104
+
event: CustomEvent<{ sub: string; cause: TokenRefreshError | TokenRevokedError | TokenInvalidError }>,
105
+
) => {
106
+
console.error(`OAuth Session for ${event.detail.sub} was deleted.`, event.detail.cause);
107
+
setAgent(null);
108
+
setOauthSession(null);
109
+
setAuthMethod(null);
110
+
setStatus("signedOut");
111
+
setQuickAuth(null);
112
+
};
113
+
114
+
oauthClient.addEventListener("deleted", handleOAuthSessionDeleted as EventListener);
115
+
initialize();
116
+
117
+
return () => {
118
+
oauthClient.removeEventListener("deleted", handleOAuthSessionDeleted as EventListener);
119
+
};
120
+
}, [initialize, setQuickAuth]);
121
+
122
+
const loginWithPassword = async (
123
+
user: string,
124
+
password: string,
125
+
service: string = "https://bsky.social",
126
+
) => {
127
+
if (status !== "signedOut") return;
128
+
setStatus("loading");
129
+
try {
130
+
let sessionData: AtpSessionData | undefined;
131
+
const apiAgent = new AtpAgent({
132
+
service,
133
+
persistSession: (_evt, sess) => {
134
+
sessionData = sess;
135
+
},
136
+
});
137
+
await apiAgent.login({ identifier: user, password });
138
+
139
+
if (sessionData) {
140
+
localStorage.setItem("service", service);
141
+
localStorage.setItem("sess", JSON.stringify(sessionData));
142
+
setAgent(apiAgent);
143
+
setAuthMethod("password");
144
+
setStatus("signedIn");
145
+
setQuickAuth(apiAgent?.did || null);
146
+
// /*mass comment*/ console.log("Successfully logged in with password.");
147
+
} else {
148
+
throw new Error("Session data not persisted after login.");
149
+
}
150
+
} catch (e) {
151
+
console.error("Password login failed:", e);
152
+
setStatus("signedOut");
153
+
setQuickAuth(null);
154
+
throw e;
155
+
}
156
+
};
157
+
158
+
const loginWithOAuth = useCallback(async (handleOrPdsUrl: string) => {
159
+
if (status !== "signedOut") return;
160
+
try {
161
+
sessionStorage.setItem("postLoginRedirect", window.location.pathname + window.location.search);
162
+
await oauthClient.signIn(handleOrPdsUrl);
163
+
} catch (err) {
164
+
console.error("OAuth sign-in aborted or failed:", err);
165
+
}
166
+
}, [status]);
167
+
168
+
const logout = useCallback(async () => {
169
+
if (status !== "signedIn" || !agent) return;
170
+
setStatus("loading");
171
+
172
+
try {
173
+
if (authMethod === "oauth" && oauthSession) {
174
+
await oauthClient.revoke(oauthSession.sub);
175
+
// /*mass comment*/ console.log("OAuth session revoked.");
176
+
} else if (authMethod === "password") {
177
+
localStorage.removeItem("service");
178
+
localStorage.removeItem("sess");
179
+
await (agent as AtpAgent).com.atproto.server.deleteSession();
180
+
// /*mass comment*/ console.log("Password-based session deleted.");
181
+
}
182
+
} catch (e) {
183
+
console.error("Logout failed:", e);
184
+
} finally {
185
+
setAgent(null);
186
+
setAuthMethod(null);
187
+
setOauthSession(null);
188
+
setStatus("signedOut");
189
+
setQuickAuth(null);
190
+
}
191
+
}, [status, agent, authMethod, oauthSession, setQuickAuth]);
192
+
193
+
return (
194
+
<AuthContext
195
+
value={{
196
+
agent,
197
+
status,
198
+
authMethod,
199
+
loginWithPassword,
200
+
loginWithOAuth,
201
+
logout,
202
+
}}
203
+
>
204
+
{children}
205
+
</AuthContext>
206
+
);
207
+
};
208
+
209
+
export const useAuth = () => use(AuthContext);
+57
-5
src/routeTree.gen.ts
+57
-5
src/routeTree.gen.ts
···
15
import { Route as FeedsRouteImport } from './routes/feeds'
16
import { Route as PathlessLayoutRouteImport } from './routes/_pathlessLayout'
17
import { Route as IndexRouteImport } from './routes/index'
18
import { Route as PathlessLayoutNestedLayoutRouteImport } from './routes/_pathlessLayout/_nested-layout'
19
import { Route as ProfileDidIndexRouteImport } from './routes/profile.$did/index'
20
import { Route as PathlessLayoutNestedLayoutRouteBRouteImport } from './routes/_pathlessLayout/_nested-layout/route-b'
21
import { Route as PathlessLayoutNestedLayoutRouteARouteImport } from './routes/_pathlessLayout/_nested-layout/route-a'
22
import { Route as ProfileDidPostRkeyRouteImport } from './routes/profile.$did/post.$rkey'
23
24
const SettingsRoute = SettingsRouteImport.update({
25
id: '/settings',
···
50
path: '/',
51
getParentRoute: () => rootRouteImport,
52
} as any)
53
const PathlessLayoutNestedLayoutRoute =
54
PathlessLayoutNestedLayoutRouteImport.update({
55
id: '/_nested-layout',
···
77
path: '/profile/$did/post/$rkey',
78
getParentRoute: () => rootRouteImport,
79
} as any)
80
81
export interface FileRoutesByFullPath {
82
'/': typeof IndexRoute
···
84
'/notifications': typeof NotificationsRoute
85
'/search': typeof SearchRoute
86
'/settings': typeof SettingsRoute
87
'/route-a': typeof PathlessLayoutNestedLayoutRouteARoute
88
'/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute
89
'/profile/$did': typeof ProfileDidIndexRoute
90
-
'/profile/$did/post/$rkey': typeof ProfileDidPostRkeyRoute
91
}
92
export interface FileRoutesByTo {
93
'/': typeof IndexRoute
···
95
'/notifications': typeof NotificationsRoute
96
'/search': typeof SearchRoute
97
'/settings': typeof SettingsRoute
98
'/route-a': typeof PathlessLayoutNestedLayoutRouteARoute
99
'/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute
100
'/profile/$did': typeof ProfileDidIndexRoute
101
-
'/profile/$did/post/$rkey': typeof ProfileDidPostRkeyRoute
102
}
103
export interface FileRoutesById {
104
__root__: typeof rootRouteImport
···
109
'/search': typeof SearchRoute
110
'/settings': typeof SettingsRoute
111
'/_pathlessLayout/_nested-layout': typeof PathlessLayoutNestedLayoutRouteWithChildren
112
'/_pathlessLayout/_nested-layout/route-a': typeof PathlessLayoutNestedLayoutRouteARoute
113
'/_pathlessLayout/_nested-layout/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute
114
'/profile/$did/': typeof ProfileDidIndexRoute
115
-
'/profile/$did/post/$rkey': typeof ProfileDidPostRkeyRoute
116
}
117
export interface FileRouteTypes {
118
fileRoutesByFullPath: FileRoutesByFullPath
···
122
| '/notifications'
123
| '/search'
124
| '/settings'
125
| '/route-a'
126
| '/route-b'
127
| '/profile/$did'
128
| '/profile/$did/post/$rkey'
129
fileRoutesByTo: FileRoutesByTo
130
to:
131
| '/'
···
133
| '/notifications'
134
| '/search'
135
| '/settings'
136
| '/route-a'
137
| '/route-b'
138
| '/profile/$did'
139
| '/profile/$did/post/$rkey'
140
id:
141
| '__root__'
142
| '/'
···
146
| '/search'
147
| '/settings'
148
| '/_pathlessLayout/_nested-layout'
149
| '/_pathlessLayout/_nested-layout/route-a'
150
| '/_pathlessLayout/_nested-layout/route-b'
151
| '/profile/$did/'
152
| '/profile/$did/post/$rkey'
153
fileRoutesById: FileRoutesById
154
}
155
export interface RootRouteChildren {
···
159
NotificationsRoute: typeof NotificationsRoute
160
SearchRoute: typeof SearchRoute
161
SettingsRoute: typeof SettingsRoute
162
ProfileDidIndexRoute: typeof ProfileDidIndexRoute
163
-
ProfileDidPostRkeyRoute: typeof ProfileDidPostRkeyRoute
164
}
165
166
declare module '@tanstack/react-router' {
···
207
preLoaderRoute: typeof IndexRouteImport
208
parentRoute: typeof rootRouteImport
209
}
210
'/_pathlessLayout/_nested-layout': {
211
id: '/_pathlessLayout/_nested-layout'
212
path: ''
···
242
preLoaderRoute: typeof ProfileDidPostRkeyRouteImport
243
parentRoute: typeof rootRouteImport
244
}
245
}
246
}
247
···
275
PathlessLayoutRouteChildren,
276
)
277
278
const rootRouteChildren: RootRouteChildren = {
279
IndexRoute: IndexRoute,
280
PathlessLayoutRoute: PathlessLayoutRouteWithChildren,
···
282
NotificationsRoute: NotificationsRoute,
283
SearchRoute: SearchRoute,
284
SettingsRoute: SettingsRoute,
285
ProfileDidIndexRoute: ProfileDidIndexRoute,
286
-
ProfileDidPostRkeyRoute: ProfileDidPostRkeyRoute,
287
}
288
export const routeTree = rootRouteImport
289
._addFileChildren(rootRouteChildren)
···
15
import { Route as FeedsRouteImport } from './routes/feeds'
16
import { Route as PathlessLayoutRouteImport } from './routes/_pathlessLayout'
17
import { Route as IndexRouteImport } from './routes/index'
18
+
import { Route as CallbackIndexRouteImport } from './routes/callback/index'
19
import { Route as PathlessLayoutNestedLayoutRouteImport } from './routes/_pathlessLayout/_nested-layout'
20
import { Route as ProfileDidIndexRouteImport } from './routes/profile.$did/index'
21
import { Route as PathlessLayoutNestedLayoutRouteBRouteImport } from './routes/_pathlessLayout/_nested-layout/route-b'
22
import { Route as PathlessLayoutNestedLayoutRouteARouteImport } from './routes/_pathlessLayout/_nested-layout/route-a'
23
import { Route as ProfileDidPostRkeyRouteImport } from './routes/profile.$did/post.$rkey'
24
+
import { Route as ProfileDidPostRkeyImageIRouteImport } from './routes/profile.$did/post.$rkey.image.$i'
25
26
const SettingsRoute = SettingsRouteImport.update({
27
id: '/settings',
···
52
path: '/',
53
getParentRoute: () => rootRouteImport,
54
} as any)
55
+
const CallbackIndexRoute = CallbackIndexRouteImport.update({
56
+
id: '/callback/',
57
+
path: '/callback/',
58
+
getParentRoute: () => rootRouteImport,
59
+
} as any)
60
const PathlessLayoutNestedLayoutRoute =
61
PathlessLayoutNestedLayoutRouteImport.update({
62
id: '/_nested-layout',
···
84
path: '/profile/$did/post/$rkey',
85
getParentRoute: () => rootRouteImport,
86
} as any)
87
+
const ProfileDidPostRkeyImageIRoute =
88
+
ProfileDidPostRkeyImageIRouteImport.update({
89
+
id: '/image/$i',
90
+
path: '/image/$i',
91
+
getParentRoute: () => ProfileDidPostRkeyRoute,
92
+
} as any)
93
94
export interface FileRoutesByFullPath {
95
'/': typeof IndexRoute
···
97
'/notifications': typeof NotificationsRoute
98
'/search': typeof SearchRoute
99
'/settings': typeof SettingsRoute
100
+
'/callback': typeof CallbackIndexRoute
101
'/route-a': typeof PathlessLayoutNestedLayoutRouteARoute
102
'/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute
103
'/profile/$did': typeof ProfileDidIndexRoute
104
+
'/profile/$did/post/$rkey': typeof ProfileDidPostRkeyRouteWithChildren
105
+
'/profile/$did/post/$rkey/image/$i': typeof ProfileDidPostRkeyImageIRoute
106
}
107
export interface FileRoutesByTo {
108
'/': typeof IndexRoute
···
110
'/notifications': typeof NotificationsRoute
111
'/search': typeof SearchRoute
112
'/settings': typeof SettingsRoute
113
+
'/callback': typeof CallbackIndexRoute
114
'/route-a': typeof PathlessLayoutNestedLayoutRouteARoute
115
'/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute
116
'/profile/$did': typeof ProfileDidIndexRoute
117
+
'/profile/$did/post/$rkey': typeof ProfileDidPostRkeyRouteWithChildren
118
+
'/profile/$did/post/$rkey/image/$i': typeof ProfileDidPostRkeyImageIRoute
119
}
120
export interface FileRoutesById {
121
__root__: typeof rootRouteImport
···
126
'/search': typeof SearchRoute
127
'/settings': typeof SettingsRoute
128
'/_pathlessLayout/_nested-layout': typeof PathlessLayoutNestedLayoutRouteWithChildren
129
+
'/callback/': typeof CallbackIndexRoute
130
'/_pathlessLayout/_nested-layout/route-a': typeof PathlessLayoutNestedLayoutRouteARoute
131
'/_pathlessLayout/_nested-layout/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute
132
'/profile/$did/': typeof ProfileDidIndexRoute
133
+
'/profile/$did/post/$rkey': typeof ProfileDidPostRkeyRouteWithChildren
134
+
'/profile/$did/post/$rkey/image/$i': typeof ProfileDidPostRkeyImageIRoute
135
}
136
export interface FileRouteTypes {
137
fileRoutesByFullPath: FileRoutesByFullPath
···
141
| '/notifications'
142
| '/search'
143
| '/settings'
144
+
| '/callback'
145
| '/route-a'
146
| '/route-b'
147
| '/profile/$did'
148
| '/profile/$did/post/$rkey'
149
+
| '/profile/$did/post/$rkey/image/$i'
150
fileRoutesByTo: FileRoutesByTo
151
to:
152
| '/'
···
154
| '/notifications'
155
| '/search'
156
| '/settings'
157
+
| '/callback'
158
| '/route-a'
159
| '/route-b'
160
| '/profile/$did'
161
| '/profile/$did/post/$rkey'
162
+
| '/profile/$did/post/$rkey/image/$i'
163
id:
164
| '__root__'
165
| '/'
···
169
| '/search'
170
| '/settings'
171
| '/_pathlessLayout/_nested-layout'
172
+
| '/callback/'
173
| '/_pathlessLayout/_nested-layout/route-a'
174
| '/_pathlessLayout/_nested-layout/route-b'
175
| '/profile/$did/'
176
| '/profile/$did/post/$rkey'
177
+
| '/profile/$did/post/$rkey/image/$i'
178
fileRoutesById: FileRoutesById
179
}
180
export interface RootRouteChildren {
···
184
NotificationsRoute: typeof NotificationsRoute
185
SearchRoute: typeof SearchRoute
186
SettingsRoute: typeof SettingsRoute
187
+
CallbackIndexRoute: typeof CallbackIndexRoute
188
ProfileDidIndexRoute: typeof ProfileDidIndexRoute
189
+
ProfileDidPostRkeyRoute: typeof ProfileDidPostRkeyRouteWithChildren
190
}
191
192
declare module '@tanstack/react-router' {
···
233
preLoaderRoute: typeof IndexRouteImport
234
parentRoute: typeof rootRouteImport
235
}
236
+
'/callback/': {
237
+
id: '/callback/'
238
+
path: '/callback'
239
+
fullPath: '/callback'
240
+
preLoaderRoute: typeof CallbackIndexRouteImport
241
+
parentRoute: typeof rootRouteImport
242
+
}
243
'/_pathlessLayout/_nested-layout': {
244
id: '/_pathlessLayout/_nested-layout'
245
path: ''
···
275
preLoaderRoute: typeof ProfileDidPostRkeyRouteImport
276
parentRoute: typeof rootRouteImport
277
}
278
+
'/profile/$did/post/$rkey/image/$i': {
279
+
id: '/profile/$did/post/$rkey/image/$i'
280
+
path: '/image/$i'
281
+
fullPath: '/profile/$did/post/$rkey/image/$i'
282
+
preLoaderRoute: typeof ProfileDidPostRkeyImageIRouteImport
283
+
parentRoute: typeof ProfileDidPostRkeyRoute
284
+
}
285
}
286
}
287
···
315
PathlessLayoutRouteChildren,
316
)
317
318
+
interface ProfileDidPostRkeyRouteChildren {
319
+
ProfileDidPostRkeyImageIRoute: typeof ProfileDidPostRkeyImageIRoute
320
+
}
321
+
322
+
const ProfileDidPostRkeyRouteChildren: ProfileDidPostRkeyRouteChildren = {
323
+
ProfileDidPostRkeyImageIRoute: ProfileDidPostRkeyImageIRoute,
324
+
}
325
+
326
+
const ProfileDidPostRkeyRouteWithChildren =
327
+
ProfileDidPostRkeyRoute._addFileChildren(ProfileDidPostRkeyRouteChildren)
328
+
329
const rootRouteChildren: RootRouteChildren = {
330
IndexRoute: IndexRoute,
331
PathlessLayoutRoute: PathlessLayoutRouteWithChildren,
···
333
NotificationsRoute: NotificationsRoute,
334
SearchRoute: SearchRoute,
335
SettingsRoute: SettingsRoute,
336
+
CallbackIndexRoute: CallbackIndexRoute,
337
ProfileDidIndexRoute: ProfileDidIndexRoute,
338
+
ProfileDidPostRkeyRoute: ProfileDidPostRkeyRouteWithChildren,
339
}
340
export const routeTree = rootRouteImport
341
._addFileChildren(rootRouteChildren)
+586
-473
src/routes/__root.tsx
+586
-473
src/routes/__root.tsx
···
2
3
// dont forget to run this
4
// npx @tanstack/router-cli generate
5
-
6
-
import { useState, type SVGProps } from "react";
7
import {
8
-
HeadContent,
9
-
Link,
10
-
Outlet,
11
Scripts,
12
-
createRootRoute,
13
useLocation,
14
} from "@tanstack/react-router";
15
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
16
import * as React from "react";
17
import { DefaultCatchBoundary } from "~/components/DefaultCatchBoundary";
18
import Login from "~/components/Login";
19
import { NotFound } from "~/components/NotFound";
20
-
import appCss from "~/styles/app.css?url";
21
import { seo } from "~/utils/seo";
22
-
import { AuthProvider, useAuth } from "~/providers/PassAuthProvider";
23
-
import { PersistentStoreProvider } from "~/providers/PersistentStoreProvider";
24
-
import type AtpAgent from "@atproto/api";
25
26
-
export const Route = createRootRoute({
27
head: () => ({
28
meta: [
29
{
···
39
}),
40
],
41
links: [
42
-
{ rel: "stylesheet", href: appCss },
43
{
44
rel: "apple-touch-icon",
45
sizes: "180x180",
···
61
{ rel: "icon", href: "/favicon.ico" },
62
],
63
}),
64
-
errorComponent: (props) => {
65
-
return (
66
-
<RootDocument>
67
-
<DefaultCatchBoundary {...props} />
68
-
</RootDocument>
69
-
);
70
-
},
71
notFoundComponent: () => <NotFound />,
72
component: RootComponent,
73
});
74
75
function RootComponent() {
76
return (
77
-
<AuthProvider>
78
-
<PersistentStoreProvider>
79
-
<RootDocument>
80
-
<Outlet />
81
-
</RootDocument>
82
-
</PersistentStoreProvider>
83
-
</AuthProvider>
84
);
85
}
86
87
function RootDocument({ children }: { children: React.ReactNode }) {
88
const location = useLocation();
89
-
const { agent, authed } = useAuth();
90
const isHome = location.pathname === "/";
91
const isNotifications = location.pathname.startsWith("/notifications");
92
-
const isProfile = location.pathname.startsWith("/profile/");
93
94
-
const [postOpen, setPostOpen] = useState(false);
95
-
const [postText, setPostText] = useState("");
96
-
const [posting, setPosting] = useState(false);
97
-
const [postSuccess, setPostSuccess] = useState(false);
98
-
const [postError, setPostError] = useState<string | null>(null);
99
100
-
async function handlePost() {
101
-
if (!agent) return;
102
-
setPosting(true);
103
-
setPostError(null);
104
-
try {
105
-
await agent.com.atproto.repo.createRecord({
106
-
collection: "app.bsky.feed.post",
107
-
repo: agent.assertDid,
108
-
record: {
109
-
$type: "app.bsky.feed.post",
110
-
text: postText,
111
-
createdAt: new Date().toISOString(),
112
-
},
113
-
});
114
-
setPostSuccess(true);
115
-
setPostText("");
116
-
setTimeout(() => {
117
-
setPostSuccess(false);
118
-
setPostOpen(false);
119
-
}, 1500);
120
-
} catch (e: any) {
121
-
setPostError(e?.message || "Failed to post");
122
-
} finally {
123
-
setPosting(false);
124
-
}
125
-
}
126
127
return (
128
<>
129
-
{postOpen && (
130
-
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
131
-
<div className="bg-white dark:bg-gray-900 rounded-lg shadow-lg p-6 w-full max-w-md relative">
132
-
<button
133
-
className="absolute top-2 right-2 text-gray-400 hover:text-gray-700 dark:hover:text-gray-200"
134
-
onClick={() => !posting && setPostOpen(false)}
135
-
disabled={posting}
136
-
aria-label="Close"
137
-
>
138
-
ร
139
-
</button>
140
-
<h2 className="text-lg font-bold mb-2">Create Post</h2>
141
-
{postSuccess ? (
142
-
<div className="flex flex-col items-center justify-center py-8">
143
-
<span className="text-green-500 text-4xl mb-2">โ</span>
144
-
<span className="text-green-600">Posted!</span>
145
-
</div>
146
-
) : (
147
-
<>
148
-
<textarea
149
-
className="w-full border rounded p-2 mb-2 dark:bg-gray-800 dark:border-gray-700"
150
-
rows={4}
151
-
placeholder="What's on your mind?"
152
-
value={postText}
153
-
onChange={(e) => setPostText(e.target.value)}
154
-
disabled={posting}
155
-
autoFocus
156
-
/>
157
-
{postError && (
158
-
<div className="text-red-500 text-sm mb-2">{postError}</div>
159
-
)}
160
-
<button
161
-
className="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:opacity-50"
162
-
onClick={handlePost}
163
-
disabled={posting || !postText.trim()}
164
-
>
165
-
{posting ? "Posting..." : "Post"}
166
-
</button>
167
-
</>
168
-
)}
169
-
</div>
170
-
</div>
171
-
)}
172
173
<div className="min-h-screen flex justify-center bg-gray-50 dark:bg-gray-950">
174
-
<nav className="hidden lg:flex h-screen w-[250px] flex-col gap-2 p-4 dark:border-gray-800 sticky top-0 self-start">
175
<div className="flex items-center gap-3 mb-4">
176
-
<img src="/redstar.png" alt="Red Dwarf Logo" className="w-8 h-8" />
177
<span className="font-extrabold text-2xl tracking-tight text-gray-900 dark:text-gray-100">
178
Red Dwarf{" "}
179
{/* <span className="text-gray-500 dark:text-gray-400 text-sm">
···
181
</span> */}
182
</span>
183
</div>
184
-
<Link
185
to="/"
186
className={
187
`py-2 px-4 hover:bg-gray-100 dark:hover:bg-gray-900 text-xl flex items-center gap-3 ` +
188
(isHome ? "font-bold" : "")
189
}
190
>
191
-
{isHome ? (
192
-
<TablerHomeFilled width={28} height={28} />
193
) : (
194
-
<TablerHome width={28} height={28} />
195
)}
196
<span>Home</span>
197
</Link>
···
202
(isNotifications ? "font-bold" : "")
203
}
204
>
205
-
{isNotifications ? (
206
-
<TablerBellFilled width={28} height={28} />
207
) : (
208
-
<TablerBell width={28} height={28} />
209
)}
210
<span>Notifications</span>
211
</Link>
···
216
}`}
217
>
218
{location.pathname.startsWith("/feeds") ? (
219
-
<TablerHashtagFilled width={28} height={28} />
220
) : (
221
-
<TablerHashtag width={28} height={28} />
222
)}
223
<span>Feeds</span>
224
</Link>
···
230
}`}
231
>
232
{location.pathname.startsWith("/search") ? (
233
-
<TablerSearchFilled width={28} height={28} />
234
) : (
235
-
<TablerSearch width={28} height={28} />
236
)}
237
<span>Search</span>
238
</Link>
···
242
}`}
243
onClick={() => {
244
if (authed && agent && agent.assertDid) {
245
-
window.location.href = `/profile/${agent.assertDid}`;
246
}
247
}}
248
type="button"
249
>
250
-
<TablerUserCircle width={28} height={28} />
251
<span>Profile</span>
252
</button>
253
<Link
···
256
location.pathname.startsWith("/settings") ? "font-bold" : ""
257
}`}
258
>
259
-
{location.pathname.startsWith("/settings") ? (
260
-
<IonSettingsSharp width={28} height={28} />
261
) : (
262
-
<IonSettings width={28} height={28} />
263
)}
264
<span>Settings</span>
265
-
</Link>
266
-
<button
267
className="mt-4 w-full flex items-center justify-center gap-3 py-3 px-0 mb-3 bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 text-gray-900 dark:text-gray-100 text-xl font-bold rounded-full transition-colors shadow"
268
onClick={() => setPostOpen(true)}
269
type="button"
270
>
271
-
<TablerEdit
272
width={24}
273
height={24}
274
className="text-gray-600 dark:text-gray-400"
275
/>
276
<span>Post</span>
277
-
</button>
278
<div className="flex-1"></div>
279
<a
280
href="https://tangled.sh/@whey.party/red-dwarf"
···
305
</div>
306
</nav>
307
308
-
<button
309
-
className="lg:hidden fixed bottom-20 right-6 z-50 bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 text-blue-600 dark:text-blue-400 rounded-full shadow-lg w-16 h-16 flex items-center justify-center border-4 border-white dark:border-gray-950 transition-all"
310
-
style={{ boxShadow: "0 4px 24px 0 rgba(0,0,0,0.12)" }}
311
-
onClick={() => setPostOpen(true)}
312
-
type="button"
313
-
aria-label="Create Post"
314
-
>
315
-
<TablerEdit
316
-
width={24}
317
-
height={24}
318
-
className="text-gray-600 dark:text-gray-400"
319
/>
320
-
</button>
321
322
-
<main className="w-full max-w-[600px] lg:border-x border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-950 pb-16 lg:pb-0">
323
-
<div className="lg:hidden flex items-center justify-between px-4 py-3 border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-950">
324
-
<div className="flex items-center gap-2">
325
-
<img
326
-
src="/redstar.png"
327
-
alt="Red Dwarf Logo"
328
-
className="w-6 h-6"
329
-
/>
330
-
<span className="font-bold text-lg text-gray-900 dark:text-gray-100">
331
-
Red Dwarf{" "}
332
-
{/* <span className="text-gray-500 dark:text-gray-400 text-sm">
333
-
lite
334
-
</span> */}
335
-
</span>
336
-
</div>
337
-
<div className="flex items-center gap-2">
338
-
<Login compact={true} />
339
-
</div>
340
</div>
341
342
{children}
343
</main>
344
345
<aside className="hidden lg:flex h-screen w-[250px] sticky top-0 self-start flex-col">
346
<Login />
347
348
<div className="flex-1"></div>
349
<p className="text-xs text-gray-400 dark:text-gray-500 text-justify mx-4 mb-4">
350
-
Red Dwarf is a bluesky client that uses Constellation and
351
-
direct PDS queries. Skylite would be a
352
-
self-hosted bluesky "instance". Stay tuned for the release of Skylite.
353
</p>
354
</aside>
355
</div>
356
357
-
<nav className="lg:hidden fixed bottom-0 left-0 right-0 bg-white dark:bg-gray-950 border-t border-gray-200 dark:border-gray-700 z-40">
358
-
<div className="flex justify-around items-center py-2">
359
-
<Link
360
-
to="/"
361
-
className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${
362
-
isHome
363
-
? "text-gray-900 dark:text-gray-100"
364
-
: "text-gray-600 dark:text-gray-400"
365
-
}`}
366
-
>
367
-
{isHome ? (
368
-
<TablerHomeFilled width={24} height={24} />
369
-
) : (
370
-
<TablerHome width={24} height={24} />
371
-
)}
372
-
<span className="text-xs mt-1">Home</span>
373
-
</Link>
374
-
<Link
375
-
to="/search"
376
-
className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${
377
-
location.pathname.startsWith("/search")
378
-
? "text-gray-900 dark:text-gray-100"
379
-
: "text-gray-600 dark:text-gray-400"
380
-
}`}
381
-
>
382
-
{location.pathname.startsWith("/search") ? (
383
-
<TablerSearchFilled width={24} height={24} />
384
-
) : (
385
-
<TablerSearch width={24} height={24} />
386
-
)}
387
-
<span className="text-xs mt-1">Search</span>
388
-
</Link>
389
-
<Link
390
-
to="/notifications"
391
-
className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${
392
-
isNotifications
393
-
? "text-gray-900 dark:text-gray-100"
394
-
: "text-gray-600 dark:text-gray-400"
395
-
}`}
396
-
>
397
-
{isNotifications ? (
398
-
<TablerBellFilled width={24} height={24} />
399
-
) : (
400
-
<TablerBell width={24} height={24} />
401
-
)}
402
-
<span className="text-xs mt-1">Notifications</span>
403
-
</Link>
404
-
<button
405
-
className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${
406
-
isProfile
407
-
? "text-gray-900 dark:text-gray-100"
408
-
: "text-gray-600 dark:text-gray-400"
409
-
}`}
410
-
onClick={() => {
411
-
if (authed && agent && agent.assertDid) {
412
-
window.location.href = `/profile/${agent.assertDid}`;
413
}
414
-
}}
415
-
type="button"
416
-
>
417
-
<TablerUserCircle width={24} height={24} />
418
-
<span className="text-xs mt-1">Profile</span>
419
-
</button>
420
-
<Link
421
-
to="/settings"
422
-
className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${
423
-
location.pathname.startsWith("/settings")
424
-
? "text-gray-900 dark:text-gray-100"
425
-
: "text-gray-600 dark:text-gray-400"
426
-
}`}
427
-
>
428
-
{location.pathname.startsWith("/settings") ? (
429
-
<IonSettingsSharp width={24} height={24} />
430
-
) : (
431
-
<IonSettings width={24} height={24} />
432
-
)}
433
-
<span className="text-xs mt-1">Settings</span>
434
-
</Link>
435
</div>
436
-
</nav>
437
438
-
<TanStackRouterDevtools position="bottom-right" />
439
<Scripts />
440
</>
441
);
442
}
443
-
export function TablerHashtag(props: SVGProps<SVGSVGElement>) {
444
-
return (
445
-
<svg
446
-
xmlns="http://www.w3.org/2000/svg"
447
-
width={24}
448
-
height={24}
449
-
viewBox="0 0 24 24"
450
-
{...props}
451
-
>
452
-
<path
453
-
fill="none"
454
-
stroke="currentColor"
455
-
strokeLinecap="round"
456
-
strokeLinejoin="round"
457
-
strokeWidth={2}
458
-
d="M5 9h14M5 15h14M11 4L7 20M17 4l-4 16"
459
-
></path>
460
-
</svg>
461
-
);
462
-
}
463
464
-
export function TablerHashtagFilled(props: SVGProps<SVGSVGElement>) {
465
-
return (
466
-
<svg
467
-
xmlns="http://www.w3.org/2000/svg"
468
-
width={24}
469
-
height={24}
470
-
viewBox="0 0 24 24"
471
-
{...props}
472
-
>
473
-
<path
474
-
fill="none"
475
-
stroke="currentColor"
476
-
strokeLinecap="round"
477
-
strokeLinejoin="round"
478
-
strokeWidth={3}
479
-
d="M5 9h14M5 15h14M11 4L7 20M17 4l-4 16"
480
-
></path>
481
-
</svg>
482
-
);
483
-
}
484
-
export function TablerEdit(props: SVGProps<SVGSVGElement>) {
485
-
return (
486
-
<svg
487
-
xmlns="http://www.w3.org/2000/svg"
488
-
width={24}
489
-
height={24}
490
-
viewBox="0 0 24 24"
491
-
className="text-white"
492
-
{...props}
493
-
>
494
-
<g
495
-
fill="none"
496
-
stroke="currentColor"
497
-
strokeLinecap="round"
498
-
strokeLinejoin="round"
499
-
strokeWidth={2}
500
>
501
-
<path d="M16.475 5.408a2.36 2.36 0 1 1 3.34 3.34L7.5 21H3v-4.5z"></path>
502
-
</g>
503
-
</svg>
504
-
);
505
-
}
506
-
export function TablerHome(props: SVGProps<SVGSVGElement>) {
507
-
return (
508
-
<svg
509
-
xmlns="http://www.w3.org/2000/svg"
510
-
width={24}
511
-
height={24}
512
-
viewBox="0 0 24 24"
513
-
className="text-gray-900 dark:text-gray-100 hover:text-gray-700 dark:hover:text-gray-300 transition-colors"
514
-
{...props}
515
-
>
516
-
<g
517
-
stroke="currentColor"
518
-
strokeLinecap="round"
519
-
strokeLinejoin="round"
520
-
strokeWidth={2}
521
-
fill="none"
522
-
>
523
-
<path d="M5 12H3l9-9l9 9h-2M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-7"></path>
524
-
<path d="M9 21v-6a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v6"></path>
525
-
</g>
526
-
</svg>
527
-
);
528
-
}
529
-
export function TablerHomeFilled(props: SVGProps<SVGSVGElement>) {
530
-
return (
531
-
<svg
532
-
xmlns="http://www.w3.org/2000/svg"
533
-
width={24}
534
-
height={24}
535
-
viewBox="0 0 24 24"
536
-
className="text-gray-900 dark:text-gray-100 hover:text-gray-700 dark:hover:text-gray-300 transition-colors"
537
-
{...props}
538
-
>
539
-
<path
540
-
fill="currentColor"
541
-
d="m12.707 2.293l9 9c.63.63.184 1.707-.707 1.707h-1v6a3 3 0 0 1-3 3h-1v-7a3 3 0 0 0-2.824-2.995L13 12h-2a3 3 0 0 0-3 3v7H7a3 3 0 0 1-3-3v-6H3c-.89 0-1.337-1.077-.707-1.707l9-9a1 1 0 0 1 1.414 0M13 14a1 1 0 0 1 1 1v7h-4v-7a1 1 0 0 1 .883-.993L11 14z"
542
-
></path>
543
-
</svg>
544
-
);
545
-
}
546
-
547
-
export function TablerBell(props: SVGProps<SVGSVGElement>) {
548
-
return (
549
-
<svg
550
-
xmlns="http://www.w3.org/2000/svg"
551
-
width={24}
552
-
height={24}
553
-
viewBox="0 0 24 24"
554
-
{...props}
555
-
>
556
-
<path
557
-
className="text-gray-900 dark:text-gray-100 hover:text-gray-700 dark:hover:text-gray-300 transition-colors"
558
-
stroke="currentColor"
559
-
strokeLinecap="round"
560
-
strokeLinejoin="round"
561
-
strokeWidth={2}
562
-
d="M10 5a2 2 0 1 1 4 0a7 7 0 0 1 4 6v3a4 4 0 0 0 2 3H4a4 4 0 0 0 2-3v-3a7 7 0 0 1 4-6M9 17v1a3 3 0 0 0 6 0v-1"
563
-
></path>
564
-
</svg>
565
-
);
566
-
}
567
-
export function TablerBellFilled(props: SVGProps<SVGSVGElement>) {
568
-
return (
569
-
<svg
570
-
xmlns="http://www.w3.org/2000/svg"
571
-
width={24}
572
-
height={24}
573
-
viewBox="0 0 24 24"
574
-
className="text-gray-900 dark:text-gray-100 hover:text-gray-700 dark:hover:text-gray-300 transition-colors"
575
-
{...props}
576
-
>
577
-
<path
578
-
fill="currentColor"
579
-
stroke="currentColor"
580
-
d="M14.235 19c.865 0 1.322 1.024.745 1.668A4 4 0 0 1 12 22a4 4 0 0 1-2.98-1.332c-.552-.616-.158-1.579.634-1.661l.11-.006zM12 2c1.358 0 2.506.903 2.875 2.141l.046.171l.008.043a8.01 8.01 0 0 1 4.024 6.069l.028.287L19 11v2.931l.021.136a3 3 0 0 0 1.143 1.847l.167.117l.162.099c.86.487.56 1.766-.377 1.864L20 18H4c-1.028 0-1.387-1.364-.493-1.87a3 3 0 0 0 1.472-2.063L5 13.924l.001-2.97A8 8 0 0 1 8.822 4.5l.248-.146l.01-.043a3 3 0 0 1 2.562-2.29l.182-.017z"
581
-
></path>
582
-
</svg>
583
-
);
584
-
}
585
-
586
-
export function TablerUserCircle(props: SVGProps<SVGSVGElement>) {
587
-
return (
588
-
<svg
589
-
xmlns="http://www.w3.org/2000/svg"
590
-
width={24}
591
-
height={24}
592
-
viewBox="0 0 24 24"
593
-
className="text-gray-900 dark:text-gray-100 hover:text-gray-700 dark:hover:text-gray-300 transition-colors"
594
-
{...props}
595
-
>
596
-
<g
597
-
fill="none"
598
-
stroke="currentColor"
599
-
strokeLinecap="round"
600
-
strokeLinejoin="round"
601
-
strokeWidth={2}
602
-
>
603
-
<path d="M3 12a9 9 0 1 0 18 0a9 9 0 1 0-18 0"></path>
604
-
<path d="M9 10a3 3 0 1 0 6 0a3 3 0 1 0-6 0m-2.832 8.849A4 4 0 0 1 10 16h4a4 4 0 0 1 3.834 2.855"></path>
605
-
</g>
606
-
</svg>
607
-
);
608
-
}
609
610
-
export function TablerSearch(props: SVGProps<SVGSVGElement>) {
611
return (
612
-
<svg
613
-
xmlns="http://www.w3.org/2000/svg"
614
-
width={24}
615
-
height={24}
616
-
viewBox="0 0 24 24"
617
-
//className="text-gray-400 dark:text-gray-500"
618
-
{...props}
619
-
>
620
-
<g
621
-
fill="none"
622
-
stroke="currentColor"
623
-
strokeLinecap="round"
624
-
strokeLinejoin="round"
625
-
strokeWidth={2}
626
-
>
627
-
<path d="M3 10a7 7 0 1 0 14 0a7 7 0 1 0-14 0"></path>
628
-
<path d="m21 21l-6-6"></path>
629
-
</g>
630
-
</svg>
631
-
);
632
-
}
633
-
export function TablerSearchFilled(props: SVGProps<SVGSVGElement>) {
634
-
return (
635
-
<svg
636
-
xmlns="http://www.w3.org/2000/svg"
637
-
width={24}
638
-
height={24}
639
-
viewBox="0 0 24 24"
640
-
//className="text-gray-400 dark:text-gray-500"
641
-
{...props}
642
>
643
-
<g
644
-
fill="none"
645
-
stroke="currentColor"
646
-
strokeLinecap="round"
647
-
strokeLinejoin="round"
648
-
strokeWidth={3}
649
>
650
-
<path d="M3 10a7 7 0 1 0 14 0a7 7 0 1 0-14 0"></path>
651
-
<path d="m21 21l-6-6"></path>
652
-
</g>
653
-
</svg>
654
);
655
}
656
657
-
export function IonSettings(props: SVGProps<SVGSVGElement>) {
658
-
return (
659
-
<svg
660
-
xmlns="http://www.w3.org/2000/svg"
661
-
width={24}
662
-
height={24}
663
-
viewBox="0 0 512 512"
664
-
{...props}
665
-
>
666
-
<path
667
-
fill="none"
668
-
stroke="currentColor"
669
-
strokeLinecap="round"
670
-
strokeLinejoin="round"
671
-
strokeWidth={32}
672
-
d="M262.29 192.31a64 64 0 1 0 57.4 57.4a64.13 64.13 0 0 0-57.4-57.4M416.39 256a154 154 0 0 1-1.53 20.79l45.21 35.46a10.81 10.81 0 0 1 2.45 13.75l-42.77 74a10.81 10.81 0 0 1-13.14 4.59l-44.9-18.08a16.11 16.11 0 0 0-15.17 1.75A164.5 164.5 0 0 1 325 400.8a15.94 15.94 0 0 0-8.82 12.14l-6.73 47.89a11.08 11.08 0 0 1-10.68 9.17h-85.54a11.11 11.11 0 0 1-10.69-8.87l-6.72-47.82a16.07 16.07 0 0 0-9-12.22a155 155 0 0 1-21.46-12.57a16 16 0 0 0-15.11-1.71l-44.89 18.07a10.81 10.81 0 0 1-13.14-4.58l-42.77-74a10.8 10.8 0 0 1 2.45-13.75l38.21-30a16.05 16.05 0 0 0 6-14.08c-.36-4.17-.58-8.33-.58-12.5s.21-8.27.58-12.35a16 16 0 0 0-6.07-13.94l-38.19-30A10.81 10.81 0 0 1 49.48 186l42.77-74a10.81 10.81 0 0 1 13.14-4.59l44.9 18.08a16.11 16.11 0 0 0 15.17-1.75A164.5 164.5 0 0 1 187 111.2a15.94 15.94 0 0 0 8.82-12.14l6.73-47.89A11.08 11.08 0 0 1 213.23 42h85.54a11.11 11.11 0 0 1 10.69 8.87l6.72 47.82a16.07 16.07 0 0 0 9 12.22a155 155 0 0 1 21.46 12.57a16 16 0 0 0 15.11 1.71l44.89-18.07a10.81 10.81 0 0 1 13.14 4.58l42.77 74a10.8 10.8 0 0 1-2.45 13.75l-38.21 30a16.05 16.05 0 0 0-6.05 14.08c.33 4.14.55 8.3.55 12.47"
673
-
></path>
674
-
</svg>
675
-
);
676
-
}
677
-
export function IonSettingsSharp(props: SVGProps<SVGSVGElement>) {
678
return (
679
-
<svg
680
-
xmlns="http://www.w3.org/2000/svg"
681
-
width={24}
682
-
height={24}
683
-
viewBox="0 0 512 512"
684
-
{...props}
685
>
686
-
<path
687
-
fill="currentColor"
688
-
d="M256 176a80 80 0 1 0 80 80a80.24 80.24 0 0 0-80-80m172.72 80a165.5 165.5 0 0 1-1.64 22.34l48.69 38.12a11.59 11.59 0 0 1 2.63 14.78l-46.06 79.52a11.64 11.64 0 0 1-14.14 4.93l-57.25-23a176.6 176.6 0 0 1-38.82 22.67l-8.56 60.78a11.93 11.93 0 0 1-11.51 9.86h-92.12a12 12 0 0 1-11.51-9.53l-8.56-60.78A169.3 169.3 0 0 1 151.05 393L93.8 416a11.64 11.64 0 0 1-14.14-4.92L33.6 331.57a11.59 11.59 0 0 1 2.63-14.78l48.69-38.12A175 175 0 0 1 83.28 256a165.5 165.5 0 0 1 1.64-22.34l-48.69-38.12a11.59 11.59 0 0 1-2.63-14.78l46.06-79.52a11.64 11.64 0 0 1 14.14-4.93l57.25 23a176.6 176.6 0 0 1 38.82-22.67l8.56-60.78A11.93 11.93 0 0 1 209.94 26h92.12a12 12 0 0 1 11.51 9.53l8.56 60.78A169.3 169.3 0 0 1 361 119l57.2-23a11.64 11.64 0 0 1 14.14 4.92l46.06 79.52a11.59 11.59 0 0 1-2.63 14.78l-48.69 38.12a175 175 0 0 1 1.64 22.66"
689
-
></path>
690
-
</svg>
691
);
692
}
···
2
3
// dont forget to run this
4
// npx @tanstack/router-cli generate
5
+
import type { QueryClient } from "@tanstack/react-query";
6
import {
7
+
createRootRouteWithContext,
8
+
// Link,
9
+
// Outlet,
10
Scripts,
11
useLocation,
12
+
useNavigate,
13
} from "@tanstack/react-router";
14
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
15
+
import { useAtom } from "jotai";
16
import * as React from "react";
17
+
import { KeepAliveOutlet, KeepAliveProvider } from "tanstack-router-keepalive";
18
+
19
+
import { Composer } from "~/components/Composer";
20
import { DefaultCatchBoundary } from "~/components/DefaultCatchBoundary";
21
+
import { Import } from "~/components/Import";
22
import Login from "~/components/Login";
23
import { NotFound } from "~/components/NotFound";
24
+
import { FluentEmojiHighContrastGlowingStar } from "~/components/Star";
25
+
import { UnifiedAuthProvider, useAuth } from "~/providers/UnifiedAuthProvider";
26
+
import { composerAtom, hueAtom, useAtomCssVar } from "~/utils/atoms";
27
import { seo } from "~/utils/seo";
28
29
+
export const Route = createRootRouteWithContext<{
30
+
queryClient: QueryClient;
31
+
}>()({
32
head: () => ({
33
meta: [
34
{
···
44
}),
45
],
46
links: [
47
{
48
rel: "apple-touch-icon",
49
sizes: "180x180",
···
65
{ rel: "icon", href: "/favicon.ico" },
66
],
67
}),
68
+
errorComponent: import.meta.env.DEV
69
+
? undefined
70
+
: (props) => (
71
+
<RootDocument>
72
+
<DefaultCatchBoundary {...props} />
73
+
</RootDocument>
74
+
),
75
notFoundComponent: () => <NotFound />,
76
component: RootComponent,
77
});
78
79
function RootComponent() {
80
return (
81
+
<UnifiedAuthProvider>
82
+
<RootDocument>
83
+
<KeepAliveProvider>
84
+
<KeepAliveOutlet />
85
+
</KeepAliveProvider>
86
+
</RootDocument>
87
+
</UnifiedAuthProvider>
88
);
89
}
90
91
function RootDocument({ children }: { children: React.ReactNode }) {
92
+
useAtomCssVar(hueAtom, "--tw-gray-hue");
93
const location = useLocation();
94
+
const navigate = useNavigate();
95
+
const { agent } = useAuth();
96
+
const authed = !!agent?.did;
97
const isHome = location.pathname === "/";
98
const isNotifications = location.pathname.startsWith("/notifications");
99
+
const isProfile =
100
+
agent &&
101
+
(location.pathname === `/profile/${agent?.did}` ||
102
+
location.pathname === `/profile/${encodeURIComponent(agent?.did ?? "")}`);
103
+
const isSettings = location.pathname.startsWith("/settings");
104
+
const isSearch = location.pathname.startsWith("/search");
105
+
const isFeeds = location.pathname.startsWith("/feeds");
106
107
+
const locationEnum:
108
+
| "feeds"
109
+
| "search"
110
+
| "settings"
111
+
| "notifications"
112
+
| "profile"
113
+
| "home" = isFeeds
114
+
? "feeds"
115
+
: isSearch
116
+
? "search"
117
+
: isSettings
118
+
? "settings"
119
+
: isNotifications
120
+
? "notifications"
121
+
: isProfile
122
+
? "profile"
123
+
: "home";
124
125
+
const [, setComposerPost] = useAtom(composerAtom);
126
127
return (
128
<>
129
+
<Composer />
130
131
<div className="min-h-screen flex justify-center bg-gray-50 dark:bg-gray-950">
132
+
<nav className="hidden lg:flex h-screen w-[250px] flex-col gap-0 p-4 dark:border-gray-800 sticky top-0 self-start">
133
<div className="flex items-center gap-3 mb-4">
134
+
<FluentEmojiHighContrastGlowingStar className="h-8 w-8" style={{color: "oklch(0.6616 0.2249 calc(25.88 + (var(--safe-hue) - 28))"}} />
135
<span className="font-extrabold text-2xl tracking-tight text-gray-900 dark:text-gray-100">
136
Red Dwarf{" "}
137
{/* <span className="text-gray-500 dark:text-gray-400 text-sm">
···
139
</span> */}
140
</span>
141
</div>
142
+
<MaterialNavItem
143
+
InactiveIcon={
144
+
<IconMaterialSymbolsHomeOutline className="w-6 h-6" />
145
+
}
146
+
ActiveIcon={<IconMaterialSymbolsHome className="w-6 h-6" />}
147
+
active={locationEnum === "home"}
148
+
onClickCallbback={() =>
149
+
navigate({
150
+
to: "/",
151
+
//params: { did: agent.assertDid },
152
+
})
153
+
}
154
+
text="Home"
155
+
/>
156
+
157
+
<MaterialNavItem
158
+
InactiveIcon={<IconMaterialSymbolsSearch className="w-6 h-6" />}
159
+
ActiveIcon={<IconMaterialSymbolsSearch className="w-6 h-6" />}
160
+
active={locationEnum === "search"}
161
+
onClickCallbback={() =>
162
+
navigate({
163
+
to: "/search",
164
+
//params: { did: agent.assertDid },
165
+
})
166
+
}
167
+
text="Explore"
168
+
/>
169
+
<MaterialNavItem
170
+
InactiveIcon={
171
+
<IconMaterialSymbolsNotificationsOutline className="w-6 h-6" />
172
+
}
173
+
ActiveIcon={
174
+
<IconMaterialSymbolsNotifications className="w-6 h-6" />
175
+
}
176
+
active={locationEnum === "notifications"}
177
+
onClickCallbback={() =>
178
+
navigate({
179
+
to: "/notifications",
180
+
//params: { did: agent.assertDid },
181
+
})
182
+
}
183
+
text="Notifications"
184
+
/>
185
+
<MaterialNavItem
186
+
InactiveIcon={<IconMaterialSymbolsTag className="w-6 h-6" />}
187
+
ActiveIcon={<IconMaterialSymbolsTag className="w-6 h-6" />}
188
+
active={locationEnum === "feeds"}
189
+
onClickCallbback={() =>
190
+
navigate({
191
+
to: "/feeds",
192
+
//params: { did: agent.assertDid },
193
+
})
194
+
}
195
+
text="Feeds"
196
+
/>
197
+
<MaterialNavItem
198
+
InactiveIcon={
199
+
<IconMaterialSymbolsAccountCircleOutline className="w-6 h-6" />
200
+
}
201
+
ActiveIcon={
202
+
<IconMaterialSymbolsAccountCircle className="w-6 h-6" />
203
+
}
204
+
active={locationEnum === "profile"}
205
+
onClickCallbback={() => {
206
+
if (authed && agent && agent.assertDid) {
207
+
//window.location.href = `/profile/${agent.assertDid}`;
208
+
navigate({
209
+
to: "/profile/$did",
210
+
params: { did: agent.assertDid },
211
+
});
212
+
}
213
+
}}
214
+
text="Profile"
215
+
/>
216
+
<MaterialNavItem
217
+
InactiveIcon={
218
+
<IconMaterialSymbolsSettingsOutline className="w-6 h-6" />
219
+
}
220
+
ActiveIcon={<IconMaterialSymbolsSettings className="w-6 h-6" />}
221
+
active={locationEnum === "settings"}
222
+
onClickCallbback={() =>
223
+
navigate({
224
+
to: "/settings",
225
+
//params: { did: agent.assertDid },
226
+
})
227
+
}
228
+
text="Settings"
229
+
/>
230
+
<div className="flex flex-row items-center justify-center mt-3">
231
+
<MaterialPillButton
232
+
InactiveIcon={<IconMdiPencilOutline className="w-6 h-6" />}
233
+
ActiveIcon={<IconMdiPencilOutline className="w-6 h-6" />}
234
+
//active={true}
235
+
onClickCallbback={() => setComposerPost({ kind: 'root' })}
236
+
text="Post"
237
+
/>
238
+
</div>
239
+
{/* <Link
240
to="/"
241
className={
242
`py-2 px-4 hover:bg-gray-100 dark:hover:bg-gray-900 text-xl flex items-center gap-3 ` +
243
(isHome ? "font-bold" : "")
244
}
245
>
246
+
{!isHome ? (
247
+
<IconMaterialSymbolsHomeOutline width={28} height={28} />
248
) : (
249
+
<IconMaterialSymbolsHome width={28} height={28} />
250
)}
251
<span>Home</span>
252
</Link>
···
257
(isNotifications ? "font-bold" : "")
258
}
259
>
260
+
{!isNotifications ? (
261
+
<IconMaterialSymbolsNotificationsOutline width={28} height={28} />
262
) : (
263
+
<IconMaterialSymbolsNotifications width={28} height={28} />
264
)}
265
<span>Notifications</span>
266
</Link>
···
271
}`}
272
>
273
{location.pathname.startsWith("/feeds") ? (
274
+
<IconMaterialSymbolsTag width={28} height={28} />
275
) : (
276
+
<IconMaterialSymbolsTag width={28} height={28} />
277
)}
278
<span>Feeds</span>
279
</Link>
···
285
}`}
286
>
287
{location.pathname.startsWith("/search") ? (
288
+
<IconMaterialSymbolsSearch width={28} height={28} />
289
) : (
290
+
<IconMaterialSymbolsSearch width={28} height={28} />
291
)}
292
<span>Search</span>
293
</Link>
···
297
}`}
298
onClick={() => {
299
if (authed && agent && agent.assertDid) {
300
+
//window.location.href = `/profile/${agent.assertDid}`;
301
+
navigate({
302
+
to: "/profile/$did",
303
+
params: { did: agent.assertDid },
304
+
});
305
}
306
}}
307
type="button"
308
>
309
+
{!isProfile ? (
310
+
<IconMaterialSymbolsAccountCircleOutline width={28} height={28} />
311
+
) : (
312
+
<IconMaterialSymbolsAccountCircle width={28} height={28} />
313
+
)}
314
<span>Profile</span>
315
</button>
316
<Link
···
319
location.pathname.startsWith("/settings") ? "font-bold" : ""
320
}`}
321
>
322
+
{!location.pathname.startsWith("/settings") ? (
323
+
<IconMaterialSymbolsSettingsOutline width={28} height={28} />
324
) : (
325
+
<IconMaterialSymbolsSettings width={28} height={28} />
326
)}
327
<span>Settings</span>
328
+
</Link> */}
329
+
{/* <button
330
className="mt-4 w-full flex items-center justify-center gap-3 py-3 px-0 mb-3 bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 text-gray-900 dark:text-gray-100 text-xl font-bold rounded-full transition-colors shadow"
331
onClick={() => setPostOpen(true)}
332
type="button"
333
>
334
+
<IconMdiPencilOutline
335
width={24}
336
height={24}
337
className="text-gray-600 dark:text-gray-400"
338
/>
339
<span>Post</span>
340
+
</button> */}
341
<div className="flex-1"></div>
342
<a
343
href="https://tangled.sh/@whey.party/red-dwarf"
···
368
</div>
369
</nav>
370
371
+
<nav className="hidden sm:flex items-center lg:hidden h-screen flex-col gap-2 p-4 dark:border-gray-800 sticky top-0 self-start">
372
+
<div className="flex items-center gap-3 mb-4">
373
+
<FluentEmojiHighContrastGlowingStar className="h-8 w-8" style={{color: "oklch(0.6616 0.2249 calc(25.88 + (var(--safe-hue) - 28))"}} />
374
+
</div>
375
+
<MaterialNavItem
376
+
small
377
+
InactiveIcon={
378
+
<IconMaterialSymbolsHomeOutline className="w-6 h-6" />
379
+
}
380
+
ActiveIcon={<IconMaterialSymbolsHome className="w-6 h-6" />}
381
+
active={locationEnum === "home"}
382
+
onClickCallbback={() =>
383
+
navigate({
384
+
to: "/",
385
+
//params: { did: agent.assertDid },
386
+
})
387
+
}
388
+
text="Home"
389
/>
390
391
+
<MaterialNavItem
392
+
small
393
+
InactiveIcon={<IconMaterialSymbolsSearch className="w-6 h-6" />}
394
+
ActiveIcon={<IconMaterialSymbolsSearch className="w-6 h-6" />}
395
+
active={locationEnum === "search"}
396
+
onClickCallbback={() =>
397
+
navigate({
398
+
to: "/search",
399
+
//params: { did: agent.assertDid },
400
+
})
401
+
}
402
+
text="Explore"
403
+
/>
404
+
<MaterialNavItem
405
+
small
406
+
InactiveIcon={
407
+
<IconMaterialSymbolsNotificationsOutline className="w-6 h-6" />
408
+
}
409
+
ActiveIcon={
410
+
<IconMaterialSymbolsNotifications className="w-6 h-6" />
411
+
}
412
+
active={locationEnum === "notifications"}
413
+
onClickCallbback={() =>
414
+
navigate({
415
+
to: "/notifications",
416
+
//params: { did: agent.assertDid },
417
+
})
418
+
}
419
+
text="Notifications"
420
+
/>
421
+
<MaterialNavItem
422
+
small
423
+
InactiveIcon={<IconMaterialSymbolsTag className="w-6 h-6" />}
424
+
ActiveIcon={<IconMaterialSymbolsTag className="w-6 h-6" />}
425
+
active={locationEnum === "feeds"}
426
+
onClickCallbback={() =>
427
+
navigate({
428
+
to: "/feeds",
429
+
//params: { did: agent.assertDid },
430
+
})
431
+
}
432
+
text="Feeds"
433
+
/>
434
+
<MaterialNavItem
435
+
small
436
+
InactiveIcon={
437
+
<IconMaterialSymbolsAccountCircleOutline className="w-6 h-6" />
438
+
}
439
+
ActiveIcon={
440
+
<IconMaterialSymbolsAccountCircle className="w-6 h-6" />
441
+
}
442
+
active={locationEnum === "profile"}
443
+
onClickCallbback={() => {
444
+
if (authed && agent && agent.assertDid) {
445
+
//window.location.href = `/profile/${agent.assertDid}`;
446
+
navigate({
447
+
to: "/profile/$did",
448
+
params: { did: agent.assertDid },
449
+
});
450
+
}
451
+
}}
452
+
text="Profile"
453
+
/>
454
+
<MaterialNavItem
455
+
small
456
+
InactiveIcon={
457
+
<IconMaterialSymbolsSettingsOutline className="w-6 h-6" />
458
+
}
459
+
ActiveIcon={<IconMaterialSymbolsSettings className="w-6 h-6" />}
460
+
active={locationEnum === "settings"}
461
+
onClickCallbback={() =>
462
+
navigate({
463
+
to: "/settings",
464
+
//params: { did: agent.assertDid },
465
+
})
466
+
}
467
+
text="Settings"
468
+
/>
469
+
<div className="flex flex-row items-center justify-center mt-3">
470
+
<MaterialPillButton
471
+
small
472
+
InactiveIcon={<IconMdiPencilOutline className="w-6 h-6" />}
473
+
ActiveIcon={<IconMdiPencilOutline className="w-6 h-6" />}
474
+
//active={true}
475
+
onClickCallbback={() => setComposerPost({ kind: 'root' })}
476
+
text="Post"
477
+
/>
478
</div>
479
+
</nav>
480
481
+
{agent?.did && (
482
+
<button
483
+
className="lg:hidden fixed bottom-22 right-4 z-50 bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 rounded-2xl w-14 h-14 flex items-center justify-center transition-all"
484
+
style={{ boxShadow: "0 4px 24px 0 rgba(0,0,0,0.12)" }}
485
+
onClick={() => setComposerPost({ kind: 'root' })}
486
+
type="button"
487
+
aria-label="Create Post"
488
+
>
489
+
<IconMdiPencilOutline
490
+
width={24}
491
+
height={24}
492
+
className="text-gray-600 dark:text-gray-400"
493
+
/>
494
+
</button>
495
+
)}
496
+
497
+
<main className="w-full max-w-[600px] sm:border-x border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 pb-16 lg:pb-0 overflow-x-clip">
498
{children}
499
</main>
500
501
<aside className="hidden lg:flex h-screen w-[250px] sticky top-0 self-start flex-col">
502
+
<div className="px-4 pt-4"><Import /></div>
503
<Login />
504
505
<div className="flex-1"></div>
506
<p className="text-xs text-gray-400 dark:text-gray-500 text-justify mx-4 mb-4">
507
+
Red Dwarf is a Bluesky client that does not rely on any Bluesky API App Servers. Instead, it uses Microcosm to fetch records directly from each users' PDS (via Slingshot) and connect them using backlinks (via Constellation)
508
</p>
509
</aside>
510
</div>
511
512
+
{agent?.did ? (
513
+
<nav className="sm:hidden fixed bottom-0 left-0 right-0 bg-gray-50 dark:bg-gray-900 border-0 shadow border-gray-200 dark:border-gray-700 z-40">
514
+
<div className="flex justify-around items-center p-2">
515
+
<MaterialNavItem
516
+
small
517
+
InactiveIcon={
518
+
<IconMaterialSymbolsHomeOutline className="w-6 h-6" />
519
+
}
520
+
ActiveIcon={<IconMaterialSymbolsHome className="w-6 h-6" />}
521
+
active={locationEnum === "home"}
522
+
onClickCallbback={() =>
523
+
navigate({
524
+
to: "/",
525
+
//params: { did: agent.assertDid },
526
+
})
527
+
}
528
+
text="Home"
529
+
/>
530
+
{/* <Link
531
+
to="/"
532
+
className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${
533
+
isHome
534
+
? "text-gray-900 dark:text-gray-100"
535
+
: "text-gray-600 dark:text-gray-400"
536
+
}`}
537
+
>
538
+
{!isHome ? (
539
+
<IconMaterialSymbolsHomeOutline width={24} height={24} />
540
+
) : (
541
+
<IconMaterialSymbolsHome width={24} height={24} />
542
+
)}
543
+
<span className="text-xs mt-1">Home</span>
544
+
</Link> */}
545
+
<MaterialNavItem
546
+
small
547
+
InactiveIcon={<IconMaterialSymbolsSearch className="w-6 h-6" />}
548
+
ActiveIcon={<IconMaterialSymbolsSearch className="w-6 h-6" />}
549
+
active={locationEnum === "search"}
550
+
onClickCallbback={() =>
551
+
navigate({
552
+
to: "/search",
553
+
//params: { did: agent.assertDid },
554
+
})
555
+
}
556
+
text="Explore"
557
+
/>
558
+
{/* <Link
559
+
to="/search"
560
+
className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${
561
+
location.pathname.startsWith("/search")
562
+
? "text-gray-900 dark:text-gray-100"
563
+
: "text-gray-600 dark:text-gray-400"
564
+
}`}
565
+
>
566
+
{!location.pathname.startsWith("/search") ? (
567
+
<IconMaterialSymbolsSearch width={24} height={24} />
568
+
) : (
569
+
<IconMaterialSymbolsSearch width={24} height={24} />
570
+
)}
571
+
<span className="text-xs mt-1">Search</span>
572
+
</Link> */}
573
+
<MaterialNavItem
574
+
small
575
+
InactiveIcon={
576
+
<IconMaterialSymbolsNotificationsOutline className="w-6 h-6" />
577
+
}
578
+
ActiveIcon={
579
+
<IconMaterialSymbolsNotifications className="w-6 h-6" />
580
+
}
581
+
active={locationEnum === "notifications"}
582
+
onClickCallbback={() =>
583
+
navigate({
584
+
to: "/notifications",
585
+
//params: { did: agent.assertDid },
586
+
})
587
+
}
588
+
text="Notifications"
589
+
/>
590
+
{/* <Link
591
+
to="/notifications"
592
+
className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${
593
+
isNotifications
594
+
? "text-gray-900 dark:text-gray-100"
595
+
: "text-gray-600 dark:text-gray-400"
596
+
}`}
597
+
>
598
+
{!isNotifications ? (
599
+
<IconMaterialSymbolsNotificationsOutline
600
+
width={24}
601
+
height={24}
602
+
/>
603
+
) : (
604
+
<IconMaterialSymbolsNotifications width={24} height={24} />
605
+
)}
606
+
<span className="text-xs mt-1">Notifications</span>
607
+
</Link> */}
608
+
<MaterialNavItem
609
+
small
610
+
InactiveIcon={
611
+
<IconMaterialSymbolsAccountCircleOutline className="w-6 h-6" />
612
+
}
613
+
ActiveIcon={
614
+
<IconMaterialSymbolsAccountCircle className="w-6 h-6" />
615
+
}
616
+
active={locationEnum === "profile"}
617
+
onClickCallbback={() => {
618
+
if (authed && agent && agent.assertDid) {
619
+
//window.location.href = `/profile/${agent.assertDid}`;
620
+
navigate({
621
+
to: "/profile/$did",
622
+
params: { did: agent.assertDid },
623
+
});
624
+
}
625
+
}}
626
+
text="Profile"
627
+
/>
628
+
{/* <button
629
+
className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${
630
+
isProfile
631
+
? "text-gray-900 dark:text-gray-100"
632
+
: "text-gray-600 dark:text-gray-400"
633
+
}`}
634
+
onClick={() => {
635
+
if (authed && agent && agent.assertDid) {
636
+
//window.location.href = `/profile/${agent.assertDid}`;
637
+
navigate({
638
+
to: "/profile/$did",
639
+
params: { did: agent.assertDid },
640
+
});
641
+
}
642
+
}}
643
+
type="button"
644
+
>
645
+
<IconMaterialSymbolsAccountCircleOutline width={24} height={24} />
646
+
<span className="text-xs mt-1">Profile</span>
647
+
</button> */}
648
+
<MaterialNavItem
649
+
small
650
+
InactiveIcon={
651
+
<IconMaterialSymbolsSettingsOutline className="w-6 h-6" />
652
+
}
653
+
ActiveIcon={<IconMaterialSymbolsSettings className="w-6 h-6" />}
654
+
active={locationEnum === "settings"}
655
+
onClickCallbback={() =>
656
+
navigate({
657
+
to: "/settings",
658
+
//params: { did: agent.assertDid },
659
+
})
660
}
661
+
text="Settings"
662
+
/>
663
+
{/* <Link
664
+
to="/settings"
665
+
className={`flex flex-col items-center py-2 px-3 rounded-lg transition-colors flex-1 ${
666
+
location.pathname.startsWith("/settings")
667
+
? "text-gray-900 dark:text-gray-100"
668
+
: "text-gray-600 dark:text-gray-400"
669
+
}`}
670
+
>
671
+
{!location.pathname.startsWith("/settings") ? (
672
+
<IconMaterialSymbolsSettingsOutline width={24} height={24} />
673
+
) : (
674
+
<IconMaterialSymbolsSettings width={24} height={24} />
675
+
)}
676
+
<span className="text-xs mt-1">Settings</span>
677
+
</Link> */}
678
+
</div>
679
+
</nav>
680
+
) : (
681
+
<div className="lg:hidden flex items-center fixed bottom-0 left-0 right-0 justify-between px-4 py-3 border-0 shadow border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900 z-10">
682
+
<div className="flex items-center gap-2">
683
+
<FluentEmojiHighContrastGlowingStar className="h-6 w-6" style={{color: "oklch(0.6616 0.2249 calc(25.88 + (var(--safe-hue) - 28))"}} />
684
+
<span className="font-bold text-lg text-gray-900 dark:text-gray-100">
685
+
Red Dwarf{" "}
686
+
{/* <span className="text-gray-500 dark:text-gray-400 text-sm">
687
+
lite
688
+
</span> */}
689
+
</span>
690
+
</div>
691
+
<div className="flex items-center gap-2">
692
+
<Login compact={true} popup={true} />
693
+
</div>
694
</div>
695
+
)}
696
697
+
<TanStackRouterDevtools position="bottom-left" />
698
<Scripts />
699
</>
700
);
701
}
702
703
+
function MaterialNavItem({
704
+
InactiveIcon,
705
+
ActiveIcon,
706
+
text,
707
+
active,
708
+
onClickCallbback,
709
+
small,
710
+
}: {
711
+
InactiveIcon: React.ReactElement;
712
+
ActiveIcon: React.ReactElement;
713
+
text: string;
714
+
active: boolean;
715
+
onClickCallbback: () => void;
716
+
small?: boolean | string;
717
+
}) {
718
+
if (small)
719
+
return (
720
+
<button
721
+
className={`flex flex-col items-center rounded-lg transition-colors ${small} gap-1 ${
722
+
active
723
+
? "text-gray-900 dark:text-gray-100"
724
+
: "text-gray-600 dark:text-gray-400"
725
+
}`}
726
+
onClick={() => {
727
+
onClickCallbback();
728
+
}}
729
>
730
+
<div
731
+
className={`px-4 py-1 rounded-full flex items-center justify-center ${active ? " bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 hover:dark:bg-gray-700" : "hover:bg-gray-50 hover:dark:bg-gray-900"}`}
732
+
>
733
+
{active ? ActiveIcon : InactiveIcon}
734
+
</div>
735
+
<span
736
+
className={`text-[12.8px] text-roboto ${active ? "font-medium" : ""}`}
737
+
>
738
+
{text}
739
+
</span>
740
+
</button>
741
+
);
742
743
return (
744
+
<button
745
+
className={`flex flex-row h-12 min-h-12 max-h-12 px-4 py-0.5 w-full items-center rounded-full transition-colors flex-1 gap-1 ${
746
+
active
747
+
? "text-gray-900 dark:text-gray-100 hover:bg-gray-300 dark:bg-gray-800 bg-gray-200 hover:dark:bg-gray-700"
748
+
: "text-gray-600 dark:text-gray-400 hover:bg-gray-100 hover:dark:bg-gray-900"
749
+
}`}
750
+
onClick={() => {
751
+
onClickCallbback();
752
+
}}
753
>
754
+
<div className={`mr-4 ${active ? " " : " "}`}>
755
+
{active ? ActiveIcon : InactiveIcon}
756
+
</div>
757
+
<span
758
+
className={`text-[17px] text-roboto ${active ? "font-medium" : ""}`}
759
>
760
+
{text}
761
+
</span>
762
+
</button>
763
);
764
}
765
766
+
function MaterialPillButton({
767
+
InactiveIcon,
768
+
ActiveIcon,
769
+
text,
770
+
//active,
771
+
onClickCallbback,
772
+
small,
773
+
}: {
774
+
InactiveIcon: React.ReactElement;
775
+
ActiveIcon: React.ReactElement;
776
+
text: string;
777
+
//active: boolean;
778
+
onClickCallbback: () => void;
779
+
small?: boolean | string;
780
+
}) {
781
+
const active = false;
782
return (
783
+
<button
784
+
className={`flex border border-gray-400 dark:border-gray-400 flex-row h-12 min-h-12 max-h-12 ${small ? "p-3 w-12" : "px-4 py-0.5"} items-center rounded-full transition-colors gap-1 ${
785
+
active
786
+
? "text-gray-900 dark:text-gray-100 hover:bg-gray-300 dark:bg-gray-700 bg-gray-200 hover:dark:bg-gray-600"
787
+
: "text-gray-600 dark:text-gray-400 hover:bg-gray-100 hover:dark:bg-gray-800"
788
+
}`}
789
+
onClick={() => {
790
+
onClickCallbback();
791
+
}}
792
>
793
+
<div className={`${!small && "mr-2"} ${active ? " " : " "}`}>
794
+
{active ? ActiveIcon : InactiveIcon}
795
+
</div>
796
+
{!small && (
797
+
<span
798
+
className={`text-[17px] text-roboto ${active ? "font-medium" : ""}`}
799
+
>
800
+
{text}
801
+
</span>
802
+
)}
803
+
</button>
804
);
805
}
+13
src/routes/callback/index.tsx
+13
src/routes/callback/index.tsx
···
···
1
+
import { createFileRoute, useNavigate } from '@tanstack/react-router'
2
+
3
+
export const Route = createFileRoute('/callback/')({
4
+
component: RouteComponent,
5
+
})
6
+
7
+
function RouteComponent() {
8
+
const navigate = useNavigate()
9
+
const redirectPath = sessionStorage.getItem('postLoginRedirect') || '/';
10
+
navigate({to:redirectPath})
11
+
sessionStorage.removeItem('postLoginRedirect');
12
+
return <div>Hello "/callback/"!</div>
13
+
}
+264
-96
src/routes/index.tsx
+264
-96
src/routes/index.tsx
···
1
import { createFileRoute } from "@tanstack/react-router";
2
import {
3
-
CACHE_TIMEOUT,
4
-
//cachedGetRecord,
5
-
//cachedResolveIdentity,
6
-
UniversalPostRendererATURILoader,
7
-
} from "~/components/UniversalPostRenderer";
8
-
import * as React from "react";
9
-
import { useAuth } from "~/providers/PassAuthProvider";
10
//import { usePersistentStore } from "~/providers/PersistentStoreProvider";
11
import {
12
useQueryIdentity,
13
-
useQueryPost,
14
-
useQueryFeedSkeleton,
15
useQueryPreferences,
16
-
useQueryArbitrary
17
} from "~/utils/useQuery";
18
-
import { InfiniteCustomFeed } from "~/components/InfiniteCustomFeed";
19
20
export const Route = createFileRoute("/")({
21
component: Home,
22
});
23
24
-
function Home() {
25
const {
26
agent,
27
-
loginStatus,
28
-
login,
29
logout,
30
-
loading: loadering,
31
-
authed,
32
} = useAuth();
33
//const { get, set } = usePersistentStore();
34
// const [feed, setFeed] = React.useState<any[]>([]);
35
// const [loading, setLoading] = React.useState(true);
···
48
// set,
49
// });
50
51
-
// console.log("alistoffeeds", prefs);
52
// setPrefs(prefs || {});
53
// } catch (err) {
54
// console.error("alistoffeeds Fetch error in preferences effect:", err);
···
67
// }, [prefs]);
68
69
// const savedFeeds = savedFeedsPref?.items || [];
70
-
71
-
const identityresultmaybe = useQueryIdentity(agent?.did);
72
-
const identity = identityresultmaybe?.data
73
74
-
const prefsresultmaybe = useQueryPreferences({agent: agent ?? undefined, pdsUrl: identity?.pds});
75
-
const prefs = prefsresultmaybe?.data
76
-
77
const savedFeeds = React.useMemo(() => {
78
const savedFeedsPref = prefs?.preferences?.find(
79
(p: any) => p?.$type === "app.bsky.actor.defs#savedFeedsPrefV2"
···
81
return savedFeedsPref?.items || [];
82
}, [prefs]);
83
84
85
-
86
-
const [selectedFeed, setSelectedFeed] = React.useState<string | null>(null);
87
-
88
React.useEffect(() => {
89
const fallbackFeed =
90
"at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot";
91
if (authed) {
92
if (savedFeeds.length > 0) {
93
setSelectedFeed((prev) =>
94
prev && savedFeeds.some((f: any) => f.value === prev)
95
? prev
96
-
: savedFeeds[0].value,
97
);
98
} else {
99
setSelectedFeed(fallbackFeed);
100
}
101
} else {
102
setSelectedFeed(fallbackFeed);
103
}
104
-
}, [savedFeeds, authed]);
105
106
// React.useEffect(() => {
107
// if (loadering || !selectedFeed) return;
···
123
// });
124
125
// const fetchstringcomplex = `${pdsurl.pdsUrl}/xrpc/app.bsky.feed.getFeedSkeleton?feed=${selectedFeed}`;
126
-
// console.log("fetching feed authed: " + fetchstringcomplex);
127
128
// const feeddef = await cachedGetRecord({
129
// atUri: selectedFeed,
···
146
147
// if (!ignore) setFeed(data.feed || []);
148
// } else {
149
-
// console.log("falling back");
150
// // always use fallback feed for not logged in
151
// const fallbackFeed =
152
// "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot";
···
158
159
// //const feedservicedid = "did:web:discover.bsky.app" //feeddef.did;
160
// const fetchstringsimple = `https://discover.bsky.app/xrpc/app.bsky.feed.getFeedSkeleton?feed=${fallbackFeed}`;
161
-
// console.log("fetching feed unauthed: " + fetchstringsimple);
162
163
// const res = await fetch(fetchstringsimple);
164
// if (!res.ok) throw new Error("Failed to fetch feed");
···
185
// ignore = true;
186
// };
187
// }, [authed, agent, loadering, selectedFeed, get, set]);
188
-
189
190
-
const feedGengetrecordquery = useQueryArbitrary(selectedFeed??undefined);
191
-
const feedServiceDid = (feedGengetrecordquery?.data?.value as any)?.did;
192
193
// const {
194
// data: feedData,
···
204
205
// const feed = feedData?.feed || [];
206
207
-
const isReadyForAuthedFeed = authed && agent && identity?.pds && feedServiceDid;
208
-
const isReadyForUnauthedFeed = !authed && selectedFeed;
209
210
return (
211
-
<div className="flex flex-col divide-y divide-gray-200 dark:divide-gray-800">
212
-
<div className="flex items-center gap-2 px-4 py-2 h-[52px] sticky top-0 bg-white dark:bg-gray-950 z-10 border-b border-gray-200 dark:border-gray-700 overflow-x-auto overflow-y-hidden scroll-thin">
213
-
{savedFeeds.length > 0 ? (
214
-
savedFeeds.map((item: any, idx: number) => {
215
const label = item.value.split("/").pop() || item.value;
216
const isActive = selectedFeed === item.value;
217
return (
···
219
key={item.value || idx}
220
className={`px-3 py-1 rounded-full whitespace-nowrap font-medium transition-colors ${
221
isActive
222
-
? "bg-gray-500 text-white"
223
-
: item.pinned
224
-
? "bg-gray-200 text-gray-700 dark:bg-gray-700 dark:text-gray-200"
225
-
: "bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-200"
226
}`}
227
onClick={() => setSelectedFeed(item.value)}
228
title={item.value}
229
>
230
{label}
231
{item.pinned && (
232
-
<span className="ml-1 text-xs text-gray-700 dark:text-gray-200">
233
โ
234
</span>
235
)}
236
</button>
237
);
238
-
})
239
-
) : (
240
-
<span className="text-xl font-bold ml-2">Home</span>
241
-
)}
242
-
</div>
243
{/* {isFeedLoading && <div className="p-4 text-gray-500">Loading...</div>}
244
{feedError && <div className="p-4 text-red-500">{feedError.message}</div>}
245
{!isFeedLoading && !feedError && feed.length === 0 && (
···
252
/>
253
))} */}
254
255
-
{(authed && (!identity?.pds || !feedServiceDid)) && (
256
-
<div className="p-4 text-center text-gray-500">Preparing your feed...</div>
257
)}
258
259
-
{(isReadyForAuthedFeed || isReadyForUnauthedFeed) ? (
260
-
<InfiniteCustomFeed
261
-
feedUri={selectedFeed!}
262
-
pdsUrl={identity?.pds}
263
-
feedServiceDid={feedServiceDid}
264
-
/>
265
) : (
266
-
<div className="p-4 text-center text-gray-500">Select a feed to get started.</div>
267
)}
268
</div>
269
);
270
}
271
272
-
export async function cachedResolveDIDWEBDOC({
273
-
didweb,
274
-
cacheTimeout = CACHE_TIMEOUT,
275
-
get,
276
-
set,
277
-
}: {
278
-
didweb: string;
279
-
cacheTimeout?: number;
280
-
get: (key: string) => any;
281
-
set: (key: string, value: string) => void;
282
-
}): Promise<any> {
283
-
const isDidInput = didweb.startsWith("did:web:");
284
-
const cacheKey = `didwebdoc:${didweb}`;
285
-
const now = Date.now();
286
-
const cached = get(cacheKey);
287
-
if (
288
-
cached &&
289
-
cached.value &&
290
-
cached.time &&
291
-
now - cached.time < cacheTimeout
292
-
) {
293
-
try {
294
-
return JSON.parse(cached.value);
295
-
} catch {}
296
-
}
297
-
const url = `https://free-fly-24.deno.dev/resolve-did-web?did=${encodeURIComponent(
298
-
didweb,
299
-
)}`;
300
-
const res = await fetch(url);
301
-
if (!res.ok) throw new Error("Failed to resolve didwebdoc");
302
-
const data = await res.json();
303
-
set(cacheKey, JSON.stringify(data));
304
-
if (!isDidInput && data.did) {
305
-
set(`didwebdoc:${data.did}`, JSON.stringify(data));
306
-
}
307
-
return data;
308
-
}
309
310
// export async function cachedGetPrefs({
311
// did,
···
1
import { createFileRoute } from "@tanstack/react-router";
2
+
import { useAtom } from "jotai";
3
+
import * as React from "react";
4
+
import { useLayoutEffect, useState } from "react";
5
+
6
+
import { Header } from "~/components/Header";
7
+
import { InfiniteCustomFeed } from "~/components/InfiniteCustomFeed";
8
+
import { useAuth } from "~/providers/UnifiedAuthProvider";
9
import {
10
+
feedScrollPositionsAtom,
11
+
isAtTopAtom,
12
+
quickAuthAtom,
13
+
selectedFeedUriAtom,
14
+
} from "~/utils/atoms";
15
//import { usePersistentStore } from "~/providers/PersistentStoreProvider";
16
import {
17
+
//constructArbitraryQuery,
18
+
//constructIdentityQuery,
19
+
//constructInfiniteFeedSkeletonQuery,
20
+
//constructPostQuery,
21
+
useQueryArbitrary,
22
useQueryIdentity,
23
useQueryPreferences,
24
} from "~/utils/useQuery";
25
26
export const Route = createFileRoute("/")({
27
+
// loader: async ({ context }) => {
28
+
// const { queryClient } = context;
29
+
// const atomauth = store.get(authedAtom);
30
+
// const atomagent = store.get(agentAtom);
31
+
32
+
// let identitypds: string | undefined;
33
+
// const initialselectedfeed = store.get(selectedFeedUriAtom);
34
+
// if (atomagent && atomauth && atomagent?.did) {
35
+
// const identityopts = constructIdentityQuery(atomagent.did);
36
+
// const identityresultmaybe =
37
+
// await queryClient.ensureQueryData(identityopts);
38
+
// identitypds = identityresultmaybe?.pds;
39
+
// }
40
+
41
+
// const arbitraryopts = constructArbitraryQuery(
42
+
// initialselectedfeed ??
43
+
// "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot"
44
+
// );
45
+
// const feedGengetrecordquery =
46
+
// await queryClient.ensureQueryData(arbitraryopts);
47
+
// const feedServiceDid = (feedGengetrecordquery?.value as any)?.did;
48
+
// //queryClient.ensureInfiniteQueryData()
49
+
50
+
// const { queryKey, queryFn } = constructInfiniteFeedSkeletonQuery({
51
+
// feedUri:
52
+
// initialselectedfeed ??
53
+
// "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot",
54
+
// agent: atomagent ?? undefined,
55
+
// isAuthed: atomauth ?? false,
56
+
// pdsUrl: identitypds,
57
+
// feedServiceDid: feedServiceDid,
58
+
// });
59
+
60
+
// const res = await queryClient.ensureInfiniteQueryData({
61
+
// queryKey,
62
+
// queryFn,
63
+
// initialPageParam: undefined as never,
64
+
// getNextPageParam: (lastPage: any) => lastPage.cursor as null | undefined,
65
+
// staleTime: Infinity,
66
+
// //refetchOnWindowFocus: false,
67
+
// //enabled: true,
68
+
// });
69
+
// await Promise.all(
70
+
// res.pages.map(async (page) => {
71
+
// await Promise.all(
72
+
// page.feed.map(async (feedviewpost) => {
73
+
// if (!feedviewpost.post) return;
74
+
// // /*mass comment*/ console.log("preloading: ", feedviewpost.post);
75
+
// const opts = constructPostQuery(feedviewpost.post);
76
+
// try {
77
+
// await queryClient.ensureQueryData(opts);
78
+
// } catch (e) {
79
+
// // /*mass comment*/ console.log(" failed:", e);
80
+
// }
81
+
// })
82
+
// );
83
+
// })
84
+
// );
85
+
// },
86
component: Home,
87
+
pendingComponent: PendingHome, // PendingHome,
88
+
staticData: { keepAlive: true },
89
});
90
+
function PendingHome() {
91
+
return <div>loading... (prefetching your timeline)</div>;
92
+
}
93
94
+
//function Homer() {
95
+
// return <div></div>
96
+
//}
97
+
export function Home({ hidden = false }: { hidden?: boolean }) {
98
const {
99
agent,
100
+
status,
101
+
authMethod,
102
+
loginWithPassword,
103
+
loginWithOAuth,
104
logout,
105
} = useAuth();
106
+
const authed = !!agent?.did;
107
+
108
+
// i dont remember why this is even here
109
+
// useEffect(() => {
110
+
// if (agent?.did) {
111
+
// store.set(authedAtom, true);
112
+
// } else {
113
+
// store.set(authedAtom, false);
114
+
// }
115
+
// }, [status, agent, authed]);
116
+
// useEffect(() => {
117
+
// if (agent) {
118
+
// // eslint-disable-next-line @typescript-eslint/ban-ts-comment
119
+
// // @ts-ignore is it just me or is the type really weird here it should be Agent not AtpAgent
120
+
// store.set(agentAtom, agent);
121
+
// } else {
122
+
// store.set(agentAtom, null);
123
+
// }
124
+
// }, [status, agent, authed]);
125
+
126
//const { get, set } = usePersistentStore();
127
// const [feed, setFeed] = React.useState<any[]>([]);
128
// const [loading, setLoading] = React.useState(true);
···
141
// set,
142
// });
143
144
+
// // /*mass comment*/ console.log("alistoffeeds", prefs);
145
// setPrefs(prefs || {});
146
// } catch (err) {
147
// console.error("alistoffeeds Fetch error in preferences effect:", err);
···
160
// }, [prefs]);
161
162
// const savedFeeds = savedFeedsPref?.items || [];
163
164
+
const [quickAuth, setQuickAuth] = useAtom(quickAuthAtom);
165
+
const isAuthRestoring = quickAuth ? status === "loading" : false;
166
+
167
+
const identityresultmaybe = useQueryIdentity(!isAuthRestoring ? agent?.did : undefined);
168
+
const identity = identityresultmaybe?.data;
169
+
170
+
const prefsresultmaybe = useQueryPreferences({
171
+
agent: !isAuthRestoring ? (agent ?? undefined) : undefined,
172
+
pdsUrl: !isAuthRestoring ? (identity?.pds) : undefined,
173
+
});
174
+
const prefs = prefsresultmaybe?.data;
175
+
176
const savedFeeds = React.useMemo(() => {
177
const savedFeedsPref = prefs?.preferences?.find(
178
(p: any) => p?.$type === "app.bsky.actor.defs#savedFeedsPrefV2"
···
180
return savedFeedsPref?.items || [];
181
}, [prefs]);
182
183
+
const [persistentSelectedFeed, setPersistentSelectedFeed] = useAtom(selectedFeedUriAtom);
184
+
const [unauthedSelectedFeed, setUnauthedSelectedFeed] = useState(persistentSelectedFeed);
185
+
const selectedFeed = agent?.did
186
+
? persistentSelectedFeed
187
+
: unauthedSelectedFeed;
188
+
const setSelectedFeed = agent?.did
189
+
? setPersistentSelectedFeed
190
+
: setUnauthedSelectedFeed;
191
192
+
// /*mass comment*/ console.log("my selectedFeed is: ", selectedFeed);
193
React.useEffect(() => {
194
const fallbackFeed =
195
"at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot";
196
if (authed) {
197
+
if (selectedFeed) return;
198
if (savedFeeds.length > 0) {
199
setSelectedFeed((prev) =>
200
prev && savedFeeds.some((f: any) => f.value === prev)
201
? prev
202
+
: savedFeeds[0].value
203
);
204
} else {
205
+
if (selectedFeed) return;
206
setSelectedFeed(fallbackFeed);
207
}
208
} else {
209
+
if (selectedFeed) return;
210
setSelectedFeed(fallbackFeed);
211
}
212
+
}, [savedFeeds, authed, setSelectedFeed]);
213
214
// React.useEffect(() => {
215
// if (loadering || !selectedFeed) return;
···
231
// });
232
233
// const fetchstringcomplex = `${pdsurl.pdsUrl}/xrpc/app.bsky.feed.getFeedSkeleton?feed=${selectedFeed}`;
234
+
// // /*mass comment*/ console.log("fetching feed authed: " + fetchstringcomplex);
235
236
// const feeddef = await cachedGetRecord({
237
// atUri: selectedFeed,
···
254
255
// if (!ignore) setFeed(data.feed || []);
256
// } else {
257
+
// // /*mass comment*/ console.log("falling back");
258
// // always use fallback feed for not logged in
259
// const fallbackFeed =
260
// "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot";
···
266
267
// //const feedservicedid = "did:web:discover.bsky.app" //feeddef.did;
268
// const fetchstringsimple = `https://discover.bsky.app/xrpc/app.bsky.feed.getFeedSkeleton?feed=${fallbackFeed}`;
269
+
// // /*mass comment*/ console.log("fetching feed unauthed: " + fetchstringsimple);
270
271
// const res = await fetch(fetchstringsimple);
272
// if (!res.ok) throw new Error("Failed to fetch feed");
···
293
// ignore = true;
294
// };
295
// }, [authed, agent, loadering, selectedFeed, get, set]);
296
297
+
const [scrollPositions, setScrollPositions] = useAtom(
298
+
feedScrollPositionsAtom
299
+
);
300
+
301
+
const scrollPositionsRef = React.useRef(scrollPositions);
302
+
303
+
React.useEffect(() => {
304
+
scrollPositionsRef.current = scrollPositions;
305
+
}, [scrollPositions]);
306
+
307
+
useLayoutEffect(() => {
308
+
if (isAuthRestoring) return;
309
+
const savedPosition = scrollPositions[selectedFeed ?? "null"] ?? 0;
310
+
311
+
window.scrollTo({ top: savedPosition, behavior: "instant" });
312
+
// eslint-disable-next-line react-hooks/exhaustive-deps
313
+
}, [selectedFeed, isAuthRestoring]);
314
+
315
+
useLayoutEffect(() => {
316
+
if (!selectedFeed || isAuthRestoring) return;
317
+
318
+
const handleScroll = () => {
319
+
scrollPositionsRef.current = {
320
+
...scrollPositionsRef.current,
321
+
[selectedFeed]: window.scrollY,
322
+
};
323
+
};
324
+
325
+
window.addEventListener("scroll", handleScroll, { passive: true });
326
+
return () => {
327
+
window.removeEventListener("scroll", handleScroll);
328
+
329
+
setScrollPositions(scrollPositionsRef.current);
330
+
};
331
+
}, [isAuthRestoring, selectedFeed, setScrollPositions]);
332
+
333
+
const feedGengetrecordquery = useQueryArbitrary(!isAuthRestoring ? selectedFeed ?? undefined : undefined);
334
+
const feedServiceDid = !isAuthRestoring ? (feedGengetrecordquery?.data?.value as any)?.did as string | undefined : undefined;
335
336
// const {
337
// data: feedData,
···
347
348
// const feed = feedData?.feed || [];
349
350
+
const isReadyForAuthedFeed = !isAuthRestoring && authed && agent && identity?.pds && feedServiceDid;
351
+
const isReadyForUnauthedFeed = !isAuthRestoring && !authed && selectedFeed;
352
+
353
+
354
+
const [isAtTop] = useAtom(isAtTopAtom);
355
356
return (
357
+
<div
358
+
className={`relative flex flex-col divide-y divide-gray-200 dark:divide-gray-800 ${hidden && "hidden"}`}
359
+
>
360
+
{!isAuthRestoring && savedFeeds.length > 0 ? (
361
+
<div className={`flex items-center px-4 py-2 h-[52px] sticky top-0 bg-[var(--header-bg-light)] dark:bg-[var(--header-bg-dark)] ${!isAtTop && "shadow-sm"} sm:shadow-none sm:bg-white sm:dark:bg-gray-950 z-10 border-0 sm:border-b border-gray-200 dark:border-gray-700 overflow-x-auto overflow-y-hidden scroll-thin`}>
362
+
{savedFeeds.map((item: any, idx: number) => {
363
const label = item.value.split("/").pop() || item.value;
364
const isActive = selectedFeed === item.value;
365
return (
···
367
key={item.value || idx}
368
className={`px-3 py-1 rounded-full whitespace-nowrap font-medium transition-colors ${
369
isActive
370
+
? "text-gray-900 dark:text-gray-100 hover:bg-gray-300 dark:bg-gray-700 bg-gray-200 hover:dark:bg-gray-600"
371
+
: "text-gray-600 dark:text-gray-400 hover:bg-gray-100 hover:dark:bg-gray-800"
372
+
// ? "bg-gray-500 text-white"
373
+
// : item.pinned
374
+
// ? "bg-gray-200 text-gray-700 dark:bg-gray-700 dark:text-gray-200"
375
+
// : "bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-200"
376
}`}
377
onClick={() => setSelectedFeed(item.value)}
378
title={item.value}
379
>
380
{label}
381
{item.pinned && (
382
+
<span
383
+
className={`ml-1 text-xs ${
384
+
isActive
385
+
? "text-gray-900 dark:text-gray-100"
386
+
: "text-gray-600 dark:text-gray-400"
387
+
}`}
388
+
>
389
โ
390
</span>
391
)}
392
</button>
393
);
394
+
})}
395
+
</div>
396
+
) : (
397
+
// <span className="text-xl font-bold ml-2">Home</span>
398
+
<Header title="Home" />
399
+
)}
400
{/* {isFeedLoading && <div className="p-4 text-gray-500">Loading...</div>}
401
{feedError && <div className="p-4 text-red-500">{feedError.message}</div>}
402
{!isFeedLoading && !feedError && feed.length === 0 && (
···
409
/>
410
))} */}
411
412
+
{isAuthRestoring || authed && (!identity?.pds || !feedServiceDid) && (
413
+
<div className="p-4 text-center text-gray-500">
414
+
Preparing your feed...
415
+
</div>
416
)}
417
418
+
{!isAuthRestoring && (isReadyForAuthedFeed || isReadyForUnauthedFeed) ? (
419
+
<InfiniteCustomFeed
420
+
key={selectedFeed!}
421
+
feedUri={selectedFeed!}
422
+
pdsUrl={identity?.pds}
423
+
feedServiceDid={feedServiceDid}
424
+
/>
425
) : (
426
+
<div className="p-4 text-center text-gray-500">
427
+
Loading.......
428
+
</div>
429
)}
430
+
{/* {false && restoringScrollPosition && (
431
+
<div className="fixed top-1/2 left-1/2 right-1/2">
432
+
restoringScrollPosition
433
+
</div>
434
+
)} */}
435
</div>
436
);
437
}
438
+
// not even used lmaooo
439
440
+
// export async function cachedResolveDIDWEBDOC({
441
+
// didweb,
442
+
// cacheTimeout = CACHE_TIMEOUT,
443
+
// get,
444
+
// set,
445
+
// }: {
446
+
// didweb: string;
447
+
// cacheTimeout?: number;
448
+
// get: (key: string) => any;
449
+
// set: (key: string, value: string) => void;
450
+
// }): Promise<any> {
451
+
// const isDidInput = didweb.startsWith("did:web:");
452
+
// const cacheKey = `didwebdoc:${didweb}`;
453
+
// const now = Date.now();
454
+
// const cached = get(cacheKey);
455
+
// if (
456
+
// cached &&
457
+
// cached.value &&
458
+
// cached.time &&
459
+
// now - cached.time < cacheTimeout
460
+
// ) {
461
+
// try {
462
+
// return JSON.parse(cached.value);
463
+
// } catch (_e) {/* whatever*/ }
464
+
// }
465
+
// const url = `https://free-fly-24.deno.dev/resolve-did-web?did=${encodeURIComponent(
466
+
// didweb
467
+
// )}`;
468
+
// const res = await fetch(url);
469
+
// if (!res.ok) throw new Error("Failed to resolve didwebdoc");
470
+
// const data = await res.json();
471
+
// set(cacheKey, JSON.stringify(data));
472
+
// if (!isDidInput && data.did) {
473
+
// set(`didwebdoc:${data.did}`, JSON.stringify(data));
474
+
// }
475
+
// return data;
476
+
// }
477
478
// export async function cachedGetPrefs({
479
// did,
+31
-26
src/routes/notifications.tsx
+31
-26
src/routes/notifications.tsx
···
1
import { createFileRoute } from "@tanstack/react-router";
2
-
import React, { useEffect, useState, useRef } from "react";
3
-
import { useAuth } from "~/providers/PassAuthProvider";
4
-
import { usePersistentStore } from "~/providers/PersistentStoreProvider";
5
6
const HANDLE_DID_CACHE_TIMEOUT = 60 * 60 * 1000; // 1 hour
7
···
10
});
11
12
function NotificationsComponent() {
13
-
console.log("NotificationsComponent render");
14
-
const { agent, authed, loading: authLoading } = useAuth();
15
-
const { get, set } = usePersistentStore();
16
const [did, setDid] = useState<string | null>(null);
17
const [resolving, setResolving] = useState(false);
18
const [error, setError] = useState<string | null>(null);
···
28
}, [authed, agent, authLoading]);
29
30
async function handleSubmit() {
31
-
console.log("handleSubmit called");
32
setError(null);
33
setResponses([null, null, null]);
34
const value = inputRef.current?.value?.trim() || "";
···
41
setResolving(true);
42
const cacheKey = `handleDid:${value}`;
43
const now = Date.now();
44
-
const cached = await get(cacheKey);
45
-
if (
46
-
cached &&
47
-
cached.value &&
48
-
cached.time &&
49
-
now - cached.time < HANDLE_DID_CACHE_TIMEOUT
50
-
) {
51
-
try {
52
-
const data = JSON.parse(cached.value);
53
-
setDid(data.did);
54
-
setResolving(false);
55
-
return;
56
-
} catch {}
57
-
}
58
try {
59
const url = `https://free-fly-24.deno.dev/?handle=${encodeURIComponent(value)}`;
60
const res = await fetch(url);
61
if (!res.ok) throw new Error("Failed to resolve handle");
62
const data = await res.json();
63
-
set(cacheKey, JSON.stringify(data));
64
setDid(data.did);
65
} catch (e: any) {
66
setError("Failed to resolve handle: " + (e?.message || e));
···
69
}
70
}
71
72
useEffect(() => {
73
if (!did) return;
74
setLoading(true);
75
setError(null);
76
const urls = [
77
-
`https://constellation.microcosm.blue/links?target=${encodeURIComponent(did)}&collection=app.bsky.feed.post&path=.facets[app.bsky.richtext.facet].features[app.bsky.richtext.facet%23mention].did`,
78
-
`https://constellation.microcosm.blue/links?target=${encodeURIComponent(did)}&collection=app.bsky.feed.post&path=.facets[].features[app.bsky.richtext.facet%23mention].did`,
79
-
`https://constellation.microcosm.blue/links?target=${encodeURIComponent(did)}&collection=app.bsky.graph.follow&path=.subject`,
80
];
81
let ignore = false;
82
Promise.all(
···
94
} catch (e: any) {
95
return { error: e?.message || String(e) };
96
}
97
-
}),
98
)
99
.then((results) => {
100
if (!ignore) setResponses(results);
···
1
import { createFileRoute } from "@tanstack/react-router";
2
+
import { useAtom } from "jotai";
3
+
import React, { useEffect, useRef,useState } from "react";
4
+
5
+
import { useAuth } from "~/providers/UnifiedAuthProvider";
6
+
import { constellationURLAtom } from "~/utils/atoms";
7
8
const HANDLE_DID_CACHE_TIMEOUT = 60 * 60 * 1000; // 1 hour
9
···
12
});
13
14
function NotificationsComponent() {
15
+
// /*mass comment*/ console.log("NotificationsComponent render");
16
+
const { agent, status } = useAuth();
17
+
const authed = !!agent?.did;
18
+
const authLoading = status === "loading";
19
const [did, setDid] = useState<string | null>(null);
20
const [resolving, setResolving] = useState(false);
21
const [error, setError] = useState<string | null>(null);
···
31
}, [authed, agent, authLoading]);
32
33
async function handleSubmit() {
34
+
// /*mass comment*/ console.log("handleSubmit called");
35
setError(null);
36
setResponses([null, null, null]);
37
const value = inputRef.current?.value?.trim() || "";
···
44
setResolving(true);
45
const cacheKey = `handleDid:${value}`;
46
const now = Date.now();
47
+
const cached = undefined // await get(cacheKey);
48
+
// if (
49
+
// cached &&
50
+
// cached.value &&
51
+
// cached.time &&
52
+
// now - cached.time < HANDLE_DID_CACHE_TIMEOUT
53
+
// ) {
54
+
// try {
55
+
// const data = JSON.parse(cached.value);
56
+
// setDid(data.did);
57
+
// setResolving(false);
58
+
// return;
59
+
// } catch {}
60
+
// }
61
try {
62
const url = `https://free-fly-24.deno.dev/?handle=${encodeURIComponent(value)}`;
63
const res = await fetch(url);
64
if (!res.ok) throw new Error("Failed to resolve handle");
65
const data = await res.json();
66
+
//set(cacheKey, JSON.stringify(data));
67
setDid(data.did);
68
} catch (e: any) {
69
setError("Failed to resolve handle: " + (e?.message || e));
···
72
}
73
}
74
75
+
const [constellationURL] = useAtom(constellationURLAtom)
76
+
77
useEffect(() => {
78
if (!did) return;
79
setLoading(true);
80
setError(null);
81
const urls = [
82
+
`https://${constellationURL}/links?target=${encodeURIComponent(did)}&collection=app.bsky.feed.post&path=.facets[app.bsky.richtext.facet].features[app.bsky.richtext.facet%23mention].did`,
83
+
`https://${constellationURL}/links?target=${encodeURIComponent(did)}&collection=app.bsky.feed.post&path=.facets[].features[app.bsky.richtext.facet%23mention].did`,
84
+
`https://${constellationURL}/links?target=${encodeURIComponent(did)}&collection=app.bsky.graph.follow&path=.subject`,
85
];
86
let ignore = false;
87
Promise.all(
···
99
} catch (e: any) {
100
return { error: e?.message || String(e) };
101
}
102
+
})
103
)
104
.then((results) => {
105
if (!ignore) setResponses(results);
+203
-31
src/routes/profile.$did/index.tsx
+203
-31
src/routes/profile.$did/index.tsx
···
1
-
import { createFileRoute, Link } from "@tanstack/react-router";
2
-
import React from "react";
3
-
import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer";
4
import { useQueryClient } from "@tanstack/react-query";
5
6
import {
7
useQueryIdentity,
8
useQueryProfile,
9
-
useInfiniteQueryAuthorFeed,
10
} from "~/utils/useQuery";
11
12
export const Route = createFileRoute("/profile/$did/")({
···
14
});
15
16
function ProfileComponent() {
17
const { did } = Route.useParams();
18
const queryClient = useQueryClient();
19
-
20
const {
21
data: identity,
22
isLoading: isIdentityLoading,
···
58
[postsData]
59
);
60
61
function getAvatarUrl(p: typeof profile) {
62
const link = p?.avatar?.ref?.["$link"];
63
if (!link || !resolvedDid) return null;
64
-
return `https://cdn.bsky.app/img/avatar/plain/${resolvedDid}/${link}@jpeg`;
65
}
66
function getBannerUrl(p: typeof profile) {
67
const link = p?.banner?.ref?.["$link"];
68
if (!link || !resolvedDid) return null;
69
-
return `https://cdn.bsky.app/img/banner/plain/${resolvedDid}/${link}@jpeg`;
70
}
71
72
const displayName =
···
96
97
return (
98
<>
99
-
<div className="flex gap-2 px-4 py-2 h-[52px] sticky top-0 bg-white dark:bg-gray-950 z-10 border-b border-gray-200 dark:border-gray-700">
100
<Link
101
to=".."
102
className="px-3 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-900 font-bold text-lg"
103
onClick={(e) => {
104
e.preventDefault();
105
-
window.history.length > 1
106
-
? window.history.back()
107
-
: window.location.assign("/");
108
}}
109
aria-label="Go back"
110
>
111
โ
112
</Link>
113
<span className="text-xl font-bold ml-2">Profile</span>
114
-
</div>
115
116
{/* Profile Header */}
117
-
<div className="w-full max-w-2xl mx-auto shadow-lg rounded-b-lg overflow-hidden relative bg-gray-200 dark:bg-gray-900">
118
{/* Banner */}
119
<div
120
className="w-full h-40 bg-gray-300 dark:bg-gray-700"
···
141
also delay the backfill to be on demand because it would be pretty intense
142
also save it persistently
143
*/}
144
-
{true ? (
145
-
<>
146
-
<button className="rounded-full bg-gray-600 px-3 py-2 text-[14px]">
147
-
Follow
148
-
</button>
149
-
<button className="rounded-full bg-gray-600 px-3 py-2 text-[14px]">
150
-
Unfollow
151
-
</button>
152
-
</>
153
-
) : (
154
-
<button className="rounded-full bg-gray-600 px-3 py-2 text-[14px]">
155
-
Edit Profile
156
-
</button>
157
-
)}
158
-
<button className="rounded-full bg-gray-600 px-3 py-2 text-[14px]">
159
... {/* todo: icon */}
160
-
</button>
161
</div>
162
163
{/* Info Card */}
164
<div className="mt-16 pb-2 px-4 text-gray-900 dark:text-gray-100">
165
<div className="font-bold text-2xl">{displayName}</div>
166
-
<div className="text-gray-500 dark:text-gray-400 text-base mb-3">
167
{handle}
168
</div>
169
{description && (
170
<div className="text-base leading-relaxed text-gray-800 dark:text-gray-300 mb-5 whitespace-pre-wrap break-words text-[15px]">
171
-
{description}
172
</div>
173
)}
174
</div>
···
211
</>
212
);
213
}
···
1
+
import { RichText } from "@atproto/api";
2
import { useQueryClient } from "@tanstack/react-query";
3
+
import { createFileRoute, useNavigate } from "@tanstack/react-router";
4
+
import { useAtom } from "jotai";
5
+
import React, { type ReactNode, useEffect, useState } from "react";
6
7
+
import { Header } from "~/components/Header";
8
+
import { Button } from "~/components/radix-m3-rd/Button";
9
+
import {
10
+
renderTextWithFacets,
11
+
UniversalPostRendererATURILoader,
12
+
} from "~/components/UniversalPostRenderer";
13
+
import { useAuth } from "~/providers/UnifiedAuthProvider";
14
+
import { imgCDNAtom } from "~/utils/atoms";
15
import {
16
+
toggleFollow,
17
+
useGetFollowState,
18
+
useGetOneToOneState,
19
+
} from "~/utils/followState";
20
+
import {
21
+
useInfiniteQueryAuthorFeed,
22
useQueryIdentity,
23
useQueryProfile,
24
} from "~/utils/useQuery";
25
26
export const Route = createFileRoute("/profile/$did/")({
···
28
});
29
30
function ProfileComponent() {
31
+
// booo bad this is not always the did it might be a handle, use identity.did instead
32
const { did } = Route.useParams();
33
+
const navigate = useNavigate();
34
const queryClient = useQueryClient();
35
const {
36
data: identity,
37
isLoading: isIdentityLoading,
···
73
[postsData]
74
);
75
76
+
const [imgcdn] = useAtom(imgCDNAtom);
77
+
78
function getAvatarUrl(p: typeof profile) {
79
const link = p?.avatar?.ref?.["$link"];
80
if (!link || !resolvedDid) return null;
81
+
return `https://${imgcdn}/img/avatar/plain/${resolvedDid}/${link}@jpeg`;
82
}
83
function getBannerUrl(p: typeof profile) {
84
const link = p?.banner?.ref?.["$link"];
85
if (!link || !resolvedDid) return null;
86
+
return `https://${imgcdn}/img/banner/plain/${resolvedDid}/${link}@jpeg`;
87
}
88
89
const displayName =
···
113
114
return (
115
<>
116
+
<Header
117
+
title={`Profile`}
118
+
backButtonCallback={() => {
119
+
if (window.history.length > 1) {
120
+
window.history.back();
121
+
} else {
122
+
window.location.assign("/");
123
+
}
124
+
}}
125
+
/>
126
+
{/* <div className="flex gap-2 px-4 py-2 h-[52px] sticky top-0 bg-white dark:bg-gray-950 z-10 border-b border-gray-200 dark:border-gray-700">
127
<Link
128
to=".."
129
className="px-3 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-900 font-bold text-lg"
130
onClick={(e) => {
131
e.preventDefault();
132
+
if (window.history.length > 1) {
133
+
window.history.back()
134
+
} else {
135
+
window.location.assign("/");
136
+
}
137
}}
138
aria-label="Go back"
139
>
140
โ
141
</Link>
142
<span className="text-xl font-bold ml-2">Profile</span>
143
+
</div> */}
144
145
{/* Profile Header */}
146
+
<div className="w-full max-w-2xl mx-auto overflow-hidden relative bg-gray-100 dark:bg-gray-900">
147
{/* Banner */}
148
<div
149
className="w-full h-40 bg-gray-300 dark:bg-gray-700"
···
170
also delay the backfill to be on demand because it would be pretty intense
171
also save it persistently
172
*/}
173
+
<FollowButton targetdidorhandle={did} />
174
+
<Button className="rounded-full" variant={"secondary"}>
175
... {/* todo: icon */}
176
+
</Button>
177
</div>
178
179
{/* Info Card */}
180
<div className="mt-16 pb-2 px-4 text-gray-900 dark:text-gray-100">
181
<div className="font-bold text-2xl">{displayName}</div>
182
+
<div className="text-gray-500 dark:text-gray-400 text-base mb-3 flex flex-row gap-1">
183
+
<Mutual targetdidorhandle={did} />
184
{handle}
185
</div>
186
{description && (
187
<div className="text-base leading-relaxed text-gray-800 dark:text-gray-300 mb-5 whitespace-pre-wrap break-words text-[15px]">
188
+
{/* {description} */}
189
+
<RichTextRenderer key={did} description={description} />
190
</div>
191
)}
192
</div>
···
229
</>
230
);
231
}
232
+
233
+
export function FollowButton({
234
+
targetdidorhandle,
235
+
}: {
236
+
targetdidorhandle: string;
237
+
}) {
238
+
const { agent } = useAuth();
239
+
const { data: identity } = useQueryIdentity(targetdidorhandle);
240
+
const queryClient = useQueryClient();
241
+
242
+
const followRecords = useGetFollowState({
243
+
target: identity?.did ?? targetdidorhandle,
244
+
user: agent?.did,
245
+
});
246
+
247
+
return (
248
+
<>
249
+
{identity?.did !== agent?.did ? (
250
+
<>
251
+
{!(followRecords?.length && followRecords?.length > 0) ? (
252
+
<Button
253
+
onClick={(e) => {
254
+
e.stopPropagation();
255
+
toggleFollow({
256
+
agent: agent || undefined,
257
+
targetDid: identity?.did,
258
+
followRecords: followRecords,
259
+
queryClient: queryClient,
260
+
});
261
+
}}
262
+
>
263
+
Follow
264
+
</Button>
265
+
) : (
266
+
<Button
267
+
onClick={(e) => {
268
+
e.stopPropagation();
269
+
toggleFollow({
270
+
agent: agent || undefined,
271
+
targetDid: identity?.did,
272
+
followRecords: followRecords,
273
+
queryClient: queryClient,
274
+
});
275
+
}}
276
+
>
277
+
Unfollow
278
+
</Button>
279
+
)}
280
+
</>
281
+
) : (
282
+
<Button variant={"secondary"}>Edit Profile</Button>
283
+
)}
284
+
</>
285
+
);
286
+
}
287
+
288
+
export function Mutual({ targetdidorhandle }: { targetdidorhandle: string }) {
289
+
const { agent } = useAuth();
290
+
const { data: identity } = useQueryIdentity(targetdidorhandle);
291
+
292
+
const theyFollowYouRes = useGetOneToOneState(
293
+
agent?.did
294
+
? {
295
+
target: agent?.did,
296
+
user: identity?.did ?? targetdidorhandle,
297
+
collection: "app.bsky.graph.follow",
298
+
path: ".subject",
299
+
}
300
+
: undefined
301
+
);
302
+
303
+
const youFollowThemRes = useGetFollowState({
304
+
target: identity?.did ?? targetdidorhandle,
305
+
user: agent?.did,
306
+
});
307
+
308
+
const theyFollowYou: boolean =
309
+
!!theyFollowYouRes?.length && theyFollowYouRes.length > 0;
310
+
const youFollowThem: boolean =
311
+
!!youFollowThemRes?.length && youFollowThemRes.length > 0;
312
+
313
+
return (
314
+
<>
315
+
{/* if not self */}
316
+
{identity?.did !== agent?.did ? (
317
+
<>
318
+
{theyFollowYou ? (
319
+
<>
320
+
{youFollowThem ? (
321
+
<div className=" text-sm px-1.5 py-0.5 text-gray-500 bg-gray-200 dark:text-gray-400 dark:bg-gray-800 rounded-lg flex flex-row items-center justify-center">
322
+
mutuals
323
+
</div>
324
+
) : (
325
+
<div className=" text-sm px-1.5 py-0.5 text-gray-500 bg-gray-200 dark:text-gray-400 dark:bg-gray-800 rounded-lg flex flex-row items-center justify-center">
326
+
follows you
327
+
</div>
328
+
)}
329
+
</>
330
+
) : (
331
+
<></>
332
+
)}
333
+
</>
334
+
) : (
335
+
// lmao can someone be mutuals with themselves ??
336
+
<></>
337
+
)}
338
+
</>
339
+
);
340
+
}
341
+
342
+
export function RichTextRenderer({ description }: { description: string }) {
343
+
const [richDescription, setRichDescription] = useState<string | ReactNode[]>(
344
+
description
345
+
);
346
+
const { agent } = useAuth();
347
+
const navigate = useNavigate();
348
+
349
+
useEffect(() => {
350
+
let mounted = true;
351
+
352
+
// setRichDescription(description);
353
+
354
+
async function processRichText() {
355
+
try {
356
+
if (!agent?.did) return;
357
+
const rt = new RichText({ text: description });
358
+
await rt.detectFacets(agent);
359
+
360
+
if (!mounted) return;
361
+
362
+
if (rt.facets) {
363
+
setRichDescription(
364
+
renderTextWithFacets({ text: rt.text, facets: rt.facets, navigate })
365
+
);
366
+
} else {
367
+
setRichDescription(rt.text);
368
+
}
369
+
} catch (error) {
370
+
console.error("Failed to detect facets:", error);
371
+
if (mounted) {
372
+
setRichDescription(description);
373
+
}
374
+
}
375
+
}
376
+
377
+
processRichText();
378
+
379
+
return () => {
380
+
mounted = false;
381
+
};
382
+
}, [description, agent, navigate]);
383
+
384
+
return <>{richDescription}</>;
385
+
}
+165
src/routes/profile.$did/post.$rkey.image.$i.tsx
+165
src/routes/profile.$did/post.$rkey.image.$i.tsx
···
···
1
+
import {
2
+
createFileRoute,
3
+
useNavigate,
4
+
type UseNavigateResult,
5
+
} from "@tanstack/react-router";
6
+
import { useEffect, useState } from "react";
7
+
import { createPortal } from "react-dom";
8
+
9
+
import { ProfilePostComponent } from "./post.$rkey";
10
+
11
+
export const Route = createFileRoute("/profile/$did/post/$rkey/image/$i")({
12
+
component: Lightbox,
13
+
});
14
+
15
+
export type LightboxProps = {
16
+
images: { src: string; alt?: string }[];
17
+
};
18
+
19
+
function nextprev({
20
+
index,
21
+
images,
22
+
navigate,
23
+
did,
24
+
rkey,
25
+
prev,
26
+
}: {
27
+
index?: number;
28
+
images?: LightboxProps["images"];
29
+
navigate: UseNavigateResult<string>;
30
+
did: string;
31
+
rkey: string;
32
+
prev?: boolean;
33
+
}) {
34
+
const len = images?.length ?? 0;
35
+
if (len === 0) return;
36
+
37
+
const nextIndex = ((index ?? 0) + (prev ? -1 : 1) + len) % len;
38
+
39
+
navigate({
40
+
to: "/profile/$did/post/$rkey/image/$i",
41
+
params: {
42
+
did,
43
+
rkey,
44
+
i: nextIndex.toString(),
45
+
},
46
+
replace: true,
47
+
});
48
+
}
49
+
50
+
export function Lightbox() {
51
+
console.log("hey the $i route is loaded w!!!");
52
+
const { did, rkey, i } = Route.useParams();
53
+
const [images, setImages] = useState<LightboxProps["images"] | undefined>(
54
+
undefined
55
+
);
56
+
const index = Number(i);
57
+
const navigate = useNavigate();
58
+
const post = true;
59
+
const image = images?.[index] ?? undefined;
60
+
61
+
function lightboxCallback(d: LightboxProps) {
62
+
console.log("callback actually called!");
63
+
setImages(d.images);
64
+
}
65
+
66
+
useEffect(() => {
67
+
function handleKey(e: KeyboardEvent) {
68
+
if (e.key === "Escape") window.history.back();
69
+
if (e.key === "ArrowRight")
70
+
nextprev({ index, images, navigate, did, rkey });
71
+
//onNavigate((index + 1) % images.length);
72
+
if (e.key === "ArrowLeft")
73
+
nextprev({ index, images, navigate, did, rkey, prev: true });
74
+
//onNavigate((index - 1 + images.length) % images.length);
75
+
}
76
+
window.addEventListener("keydown", handleKey);
77
+
return () => window.removeEventListener("keydown", handleKey);
78
+
}, [index, navigate, did, rkey, images]);
79
+
80
+
return createPortal(
81
+
<>
82
+
{post && (
83
+
<div
84
+
onClick={(e) => {
85
+
e.stopPropagation();
86
+
e.nativeEvent.stopImmediatePropagation();
87
+
}}
88
+
className="lightbox-sidebar hidden lg:flex overscroll-none disablegutter disablescroll border-l dark:border-gray-800 was7 border-gray-300 fixed z-50 top-0 right-0 flex-col max-w-[350px] min-w-[350px] max-h-screen overflow-y-scroll dark:bg-gray-950 bg-white"
89
+
>
90
+
<ProfilePostComponent
91
+
key={`/profile/${did}/post/${rkey}`}
92
+
did={did}
93
+
rkey={rkey}
94
+
nopics
95
+
lightboxCallback={lightboxCallback}
96
+
/>
97
+
</div>
98
+
)}
99
+
<div
100
+
className="lightbox fixed inset-0 z-50 flex items-center justify-center bg-black/80 w-screen lg:w-[calc(100vw-350px)] lg:max-w-[calc(100vw-350px)]"
101
+
onClick={(e) => {
102
+
e.stopPropagation();
103
+
window.history.back();
104
+
}}
105
+
>
106
+
<img
107
+
src={image?.src}
108
+
alt={image?.alt}
109
+
className="max-h-[90%] max-w-[90%] object-contain rounded-lg shadow-lg"
110
+
onClick={(e) => e.stopPropagation()}
111
+
/>
112
+
113
+
{(images?.length ?? 0) > 1 && (
114
+
<>
115
+
<button
116
+
onClick={(e) => {
117
+
e.stopPropagation();
118
+
nextprev({ index, images, navigate, did, rkey, prev: true });
119
+
}}
120
+
className="absolute left-4 top-1/2 -translate-y-1/2 text-white text-4xl h-8 w-8 rounded-full bg-gray-900 flex items-center justify-center"
121
+
>
122
+
<svg
123
+
xmlns="http://www.w3.org/2000/svg"
124
+
width={28}
125
+
height={28}
126
+
viewBox="0 0 24 24"
127
+
>
128
+
<g fill="none" fillRule="evenodd">
129
+
<path d="M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"></path>
130
+
<path
131
+
fill="currentColor"
132
+
d="M8.293 12.707a1 1 0 0 1 0-1.414l5.657-5.657a1 1 0 1 1 1.414 1.414L10.414 12l4.95 4.95a1 1 0 0 1-1.414 1.414z"
133
+
></path>
134
+
</g>
135
+
</svg>
136
+
</button>
137
+
<button
138
+
onClick={(e) => {
139
+
e.stopPropagation();
140
+
nextprev({ index, images, navigate, did, rkey });
141
+
}}
142
+
className="absolute right-4 top-1/2 -translate-y-1/2 text-white text-4xl h-8 w-8 rounded-full bg-gray-900 flex items-center justify-center"
143
+
>
144
+
<svg
145
+
xmlns="http://www.w3.org/2000/svg"
146
+
width={28}
147
+
height={28}
148
+
viewBox="0 0 24 24"
149
+
>
150
+
<g fill="none" fillRule="evenodd">
151
+
<path d="M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"></path>
152
+
<path
153
+
fill="currentColor"
154
+
d="M15.707 11.293a1 1 0 0 1 0 1.414l-5.657 5.657a1 1 0 1 1-1.414-1.414l4.95-4.95l-4.95-4.95a1 1 0 0 1 1.414-1.414z"
155
+
></path>
156
+
</g>
157
+
</svg>
158
+
</button>
159
+
</>
160
+
)}
161
+
</div>
162
+
</>,
163
+
document.body
164
+
);
165
+
}
+241
-70
src/routes/profile.$did/post.$rkey.tsx
+241
-70
src/routes/profile.$did/post.$rkey.tsx
···
1
-
import { useQueryClient } from "@tanstack/react-query";
2
-
import { createFileRoute, Link } from "@tanstack/react-router";
3
import React, { useLayoutEffect } from "react";
4
-
import ShrinkingBox from "~/components/shrinkpadding";
5
import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer";
6
//import { usePersistentStore } from '~/providers/PersistentStoreProvider';
7
import {
8
useQueryIdentity,
9
useQueryPost,
10
-
useQueryConstellation,
11
-
constructPostQuery,
12
-
useQueryArbitrary,
13
} from "~/utils/useQuery";
14
15
//const HANDLE_DID_CACHE_TIMEOUT = 60 * 60 * 1000; // 1 hour
16
···
33
);
34
}
35
36
-
function ProfilePostComponent({ did, rkey }: { did: string; rkey: string }) {
37
//const { get, set } = usePersistentStore();
38
const queryClient = useQueryClient();
39
// const [resolvedDid, setResolvedDid] = React.useState<string | null>(null);
···
180
() =>
181
resolvedDid
182
? `at://${decodeURIComponent(resolvedDid)}/app.bsky.feed.post/${rkey}`
183
-
: "",
184
[resolvedDid, rkey]
185
);
186
187
const { data: mainPost } = useQueryPost(atUri);
188
189
-
const { data: repliesData } = useQueryConstellation({
190
-
method: "/links",
191
target: atUri,
192
-
collection: "app.bsky.feed.post",
193
-
path: ".reply.parent.uri",
194
});
195
-
const replies = repliesData?.linking_records.slice(0, 50) ?? [];
196
197
const [parents, setParents] = React.useState<any[]>([]);
198
const [parentsLoading, setParentsLoading] = React.useState(false);
199
200
const mainPostRef = React.useRef<HTMLDivElement>(null);
201
-
const userHasScrolled = React.useRef(false);
202
203
-
const scrollAnchor = React.useRef<{ top: number } | null>(null);
204
205
206
-
React.useEffect(() => {
207
-
const onScroll = () => {
208
209
-
if (window.scrollY > 50) {
210
-
userHasScrolled.current = true;
211
212
-
window.removeEventListener("scroll", onScroll);
213
}
214
-
};
215
-
216
-
if (!userHasScrolled.current) {
217
-
window.addEventListener("scroll", onScroll, { passive: true });
218
}
219
-
return () => window.removeEventListener("scroll", onScroll);
220
-
}, []);
221
222
-
useLayoutEffect(() => {
223
-
if (parentsLoading && mainPostRef.current && !userHasScrolled.current) {
224
-
scrollAnchor.current = {
225
-
top: mainPostRef.current.getBoundingClientRect().top,
226
-
};
227
}
228
-
}, [parentsLoading]);
229
230
-
useLayoutEffect(() => {
231
-
if (
232
-
scrollAnchor.current &&
233
-
mainPostRef.current &&
234
-
!userHasScrolled.current
235
-
) {
236
-
const newTop = mainPostRef.current.getBoundingClientRect().top;
237
-
const topDiff = newTop - scrollAnchor.current.top;
238
-
if (topDiff > 0) {
239
-
window.scrollBy(0, topDiff);
240
-
}
241
-
scrollAnchor.current = null;
242
}
243
-
}, [parents]);
244
245
React.useEffect(() => {
246
if (!mainPost?.value?.reply?.parent?.uri) {
···
259
while (currentParentUri && safetyCounter < MAX_PARENTS) {
260
try {
261
const parentPost = await queryClient.fetchQuery(
262
-
constructPostQuery(currentParentUri)
263
);
264
if (!parentPost) break;
265
parentChain.push(parentPost);
···
291
292
return (
293
<>
294
-
<div className="flex items-center gap-2 px-4 py-2 h-[52px] sticky top-0 bg-white dark:bg-gray-950 z-10 border-b border-gray-200 dark:border-gray-700">
295
-
<Link
296
-
to=".."
297
-
className="px-3 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-900 font-bold text-lg"
298
-
onClick={(e) => {
299
-
e.preventDefault();
300
-
window.history.length > 1
301
-
? window.history.back()
302
-
: window.location.assign("/");
303
-
}}
304
-
aria-label="Go back"
305
-
>
306
-
โ
307
-
</Link>
308
-
<span className="text-xl font-bold ml-2">Post</span>
309
-
</div>
310
311
{parentsLoading && (
312
<div className="text-center text-gray-500 dark:text-gray-400 flex flex-row">
···
321
)}
322
323
{/* we should use the reply lines here thats provided by UPR*/}
324
-
<div style={{ maxWidth: 600, margin: "0px auto 0", padding: 0 }}>
325
{parents.map((parent, index) => (
326
<UniversalPostRendererATURILoader
327
key={parent.uri}
···
337
atUri={atUri}
338
detailed={true}
339
topReplyLine={parentsLoading || parents.length > 0}
340
/>
341
</div>
342
<div
343
style={{
344
maxWidth: 600,
345
-
margin: "0px auto 0",
346
padding: 0,
347
-
minHeight: "100dvh",
348
}}
349
>
350
<div
···
358
Replies
359
</div>
360
<div style={{ display: "flex", flexDirection: "column", gap: 0 }}>
361
-
{replies.length > 0 &&
362
-
replies.map((reply) => {
363
-
const replyAtUri = `at://${reply.did}/app.bsky.feed.post/${reply.rkey}`;
364
return (
365
<UniversalPostRendererATURILoader
366
-
key={replyAtUri}
367
-
atUri={replyAtUri}
368
/>
369
);
370
})}
371
</div>
372
</div>
373
</>
···
1
+
import { AtUri } from "@atproto/api";
2
+
import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query";
3
+
import { createFileRoute, Outlet } from "@tanstack/react-router";
4
+
import { useAtom } from "jotai";
5
import React, { useLayoutEffect } from "react";
6
+
7
+
import { Header } from "~/components/Header";
8
import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer";
9
+
import { constellationURLAtom, slingshotURLAtom } from "~/utils/atoms";
10
//import { usePersistentStore } from '~/providers/PersistentStoreProvider';
11
import {
12
+
constructPostQuery,
13
+
type linksAllResponse,
14
+
type linksRecordsResponse,
15
+
useQueryConstellation,
16
useQueryIdentity,
17
useQueryPost,
18
+
yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks,
19
} from "~/utils/useQuery";
20
+
21
+
import type { LightboxProps } from "./post.$rkey.image.$i";
22
23
//const HANDLE_DID_CACHE_TIMEOUT = 60 * 60 * 1000; // 1 hour
24
···
41
);
42
}
43
44
+
export function ProfilePostComponent({
45
+
did,
46
+
rkey,
47
+
nopics,
48
+
lightboxCallback,
49
+
}: {
50
+
did: string;
51
+
rkey: string;
52
+
nopics?: boolean;
53
+
lightboxCallback?: (d: LightboxProps) => void;
54
+
}) {
55
//const { get, set } = usePersistentStore();
56
const queryClient = useQueryClient();
57
// const [resolvedDid, setResolvedDid] = React.useState<string | null>(null);
···
198
() =>
199
resolvedDid
200
? `at://${decodeURIComponent(resolvedDid)}/app.bsky.feed.post/${rkey}`
201
+
: undefined,
202
[resolvedDid, rkey]
203
);
204
205
const { data: mainPost } = useQueryPost(atUri);
206
207
+
console.log("atUri",atUri)
208
+
209
+
const opdid = React.useMemo(
210
+
() =>
211
+
atUri
212
+
? new AtUri(atUri).host
213
+
: undefined,
214
+
[atUri]
215
+
);
216
+
217
+
// @ts-expect-error i hate overloads
218
+
const { data: links } = useQueryConstellation(atUri?{
219
+
method: "/links/all",
220
target: atUri,
221
+
} : {
222
+
method: "undefined",
223
+
target: ""
224
+
})as { data: linksAllResponse | undefined };
225
+
226
+
//const [likes, setLikes] = React.useState<number | null>(null);
227
+
//const [reposts, setReposts] = React.useState<number | null>(null);
228
+
const [replyCount, setReplyCount] = React.useState<number | null>(null);
229
+
230
+
React.useEffect(() => {
231
+
// /*mass comment*/ console.log(JSON.stringify(links, null, 2));
232
+
// setLikes(
233
+
// links
234
+
// ? links?.links?.["app.bsky.feed.like"]?.[".subject.uri"]?.records || 0
235
+
// : null
236
+
// );
237
+
// setReposts(
238
+
// links
239
+
// ? links?.links?.["app.bsky.feed.repost"]?.[".subject.uri"]?.records || 0
240
+
// : null
241
+
// );
242
+
setReplyCount(
243
+
links
244
+
? links?.links?.["app.bsky.feed.post"]?.[".reply.parent.uri"]
245
+
?.records || 0
246
+
: null
247
+
);
248
+
}, [links]);
249
+
250
+
const { data: opreplies } = useQueryConstellation(
251
+
!!opdid && replyCount && replyCount >= 25
252
+
? {
253
+
method: "/links",
254
+
target: atUri,
255
+
// @ts-expect-error overloading sucks so much
256
+
collection: "app.bsky.feed.post",
257
+
path: ".reply.parent.uri",
258
+
//cursor?: string;
259
+
dids: [opdid],
260
+
}
261
+
: {
262
+
method: "undefined",
263
+
target: "",
264
+
}
265
+
) as { data: linksRecordsResponse | undefined };
266
+
267
+
const opReplyAturis =
268
+
opreplies?.linking_records.map(
269
+
(r) => `at://${r.did}/${r.collection}/${r.rkey}`,
270
+
) ?? [];
271
+
272
+
273
+
// const { data: repliesData } = useQueryConstellation({
274
+
// method: "/links",
275
+
// target: atUri,
276
+
// collection: "app.bsky.feed.post",
277
+
// path: ".reply.parent.uri",
278
+
// });
279
+
// const replies = repliesData?.linking_records.slice(0, 50) ?? [];
280
+
const [constellationurl] = useAtom(constellationURLAtom)
281
+
282
+
const infinitequeryresults = useInfiniteQuery({
283
+
...yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks(
284
+
{
285
+
constellation: constellationurl,
286
+
method: "/links",
287
+
target: atUri,
288
+
collection: "app.bsky.feed.post",
289
+
path: ".reply.parent.uri",
290
+
}
291
+
),
292
+
enabled: !!atUri,
293
});
294
+
295
+
const {
296
+
data: infiniteRepliesData,
297
+
fetchNextPage,
298
+
hasNextPage,
299
+
isFetchingNextPage,
300
+
} = infinitequeryresults;
301
+
302
+
// // auto-fetch all pages
303
+
// useEffect(() => {
304
+
// if (
305
+
// infinitequeryresults.hasNextPage &&
306
+
// !infinitequeryresults.isFetchingNextPage
307
+
// ) {
308
+
// console.log("Fetching the next page...");
309
+
// infinitequeryresults.fetchNextPage();
310
+
// }
311
+
// }, [infinitequeryresults]);
312
+
313
+
// const replyAturis = repliesData
314
+
// ? repliesData.pages.flatMap((page) =>
315
+
// page
316
+
// ? page.linking_records.map((record) => {
317
+
// const aturi = `at://${record.did}/${record.collection}/${record.rkey}`;
318
+
// return aturi;
319
+
// })
320
+
// : []
321
+
// )
322
+
// : [];
323
+
324
+
const replyAturis = React.useMemo(() => {
325
+
// Get all replies from the standard infinite query
326
+
const allReplies =
327
+
infiniteRepliesData?.pages.flatMap(
328
+
(page) =>
329
+
page?.linking_records.map(
330
+
(r) => `at://${r.did}/${r.collection}/${r.rkey}`,
331
+
) ?? [],
332
+
) ?? [];
333
+
334
+
if (replyCount && (replyCount < 25)) {
335
+
// If count is low, just use the standard list and find the oldest OP reply to move to the top
336
+
const opdidFromUri = atUri ? new AtUri(atUri).host : undefined;
337
+
const oldestOpsIndex = allReplies.findIndex(
338
+
(aturi) => new AtUri(aturi).host === opdidFromUri,
339
+
);
340
+
if (oldestOpsIndex > 0) {
341
+
const [oldestOpsReply] = allReplies.splice(oldestOpsIndex, 1);
342
+
allReplies.unshift(oldestOpsReply);
343
+
}
344
+
return allReplies;
345
+
} else {
346
+
// If count is high, prioritize OP replies from the special query
347
+
// and filter them out from the main list to avoid duplication.
348
+
const opReplySet = new Set(opReplyAturis);
349
+
const otherReplies = allReplies.filter((uri) => !opReplySet.has(uri));
350
+
return [...opReplyAturis, ...otherReplies];
351
+
}
352
+
}, [infiniteRepliesData, opReplyAturis, replyCount, atUri]);
353
+
354
+
// Find oldest OP reply
355
+
const oldestOpsIndex = replyAturis.findIndex(
356
+
(aturi) => new AtUri(aturi).host === opdid
357
+
);
358
+
359
+
// Reorder: move oldest OP reply to the front
360
+
if (oldestOpsIndex > 0) {
361
+
const [oldestOpsReply] = replyAturis.splice(oldestOpsIndex, 1);
362
+
replyAturis.unshift(oldestOpsReply);
363
+
}
364
365
const [parents, setParents] = React.useState<any[]>([]);
366
const [parentsLoading, setParentsLoading] = React.useState(false);
367
368
const mainPostRef = React.useRef<HTMLDivElement>(null);
369
+
const hasPerformedInitialLayout = React.useRef(false);
370
371
+
const [layoutReady, setLayoutReady] = React.useState(false);
372
373
+
useLayoutEffect(() => {
374
+
if (parents.length > 0 && !layoutReady && mainPostRef.current) {
375
+
const mainPostElement = mainPostRef.current;
376
377
+
if (window.scrollY === 0 && !hasPerformedInitialLayout.current) {
378
+
const elementTop = mainPostElement.getBoundingClientRect().top;
379
+
const headerOffset = 70;
380
381
+
const targetScrollY = elementTop - headerOffset;
382
383
+
window.scrollBy(0, targetScrollY);
384
+
385
+
hasPerformedInitialLayout.current = true;
386
}
387
+
388
+
// todo idk what to do with this
389
+
// eslint-disable-next-line react-hooks/set-state-in-effect
390
+
setLayoutReady(true);
391
}
392
+
}, [parents, layoutReady]);
393
+
394
395
+
const [slingshoturl] = useAtom(slingshotURLAtom)
396
+
397
+
React.useEffect(() => {
398
+
if (parentsLoading) {
399
+
setLayoutReady(false);
400
}
401
402
+
if (!mainPost?.value?.reply?.parent?.uri && !parentsLoading) {
403
+
setLayoutReady(true);
404
+
hasPerformedInitialLayout.current = true;
405
}
406
+
}, [parentsLoading, mainPost]);
407
408
React.useEffect(() => {
409
if (!mainPost?.value?.reply?.parent?.uri) {
···
422
while (currentParentUri && safetyCounter < MAX_PARENTS) {
423
try {
424
const parentPost = await queryClient.fetchQuery(
425
+
constructPostQuery(currentParentUri, slingshoturl)
426
);
427
if (!parentPost) break;
428
parentChain.push(parentPost);
···
454
455
return (
456
<>
457
+
<Outlet />
458
+
<Header
459
+
title={`Post`}
460
+
backButtonCallback={() => {
461
+
if (window.history.length > 1) {
462
+
window.history.back();
463
+
} else {
464
+
window.location.assign("/");
465
+
}
466
+
}}
467
+
/>
468
469
{parentsLoading && (
470
<div className="text-center text-gray-500 dark:text-gray-400 flex flex-row">
···
479
)}
480
481
{/* we should use the reply lines here thats provided by UPR*/}
482
+
<div style={{ maxWidth: 600, padding: 0 }}>
483
{parents.map((parent, index) => (
484
<UniversalPostRendererATURILoader
485
key={parent.uri}
···
495
atUri={atUri}
496
detailed={true}
497
topReplyLine={parentsLoading || parents.length > 0}
498
+
nopics={!!nopics}
499
+
lightboxCallback={lightboxCallback}
500
/>
501
</div>
502
<div
503
style={{
504
maxWidth: 600,
505
+
//margin: "0px auto 0",
506
padding: 0,
507
+
minHeight: "80dvh",
508
+
paddingBottom: "20dvh",
509
}}
510
>
511
<div
···
519
Replies
520
</div>
521
<div style={{ display: "flex", flexDirection: "column", gap: 0 }}>
522
+
{replyAturis.length > 0 &&
523
+
replyAturis.map((reply) => {
524
+
//const replyAtUri = `at://${reply.did}/app.bsky.feed.post/${reply.rkey}`;
525
return (
526
<UniversalPostRendererATURILoader
527
+
key={reply}
528
+
atUri={reply}
529
+
maxReplies={4}
530
/>
531
);
532
})}
533
+
{hasNextPage && (
534
+
<button
535
+
onClick={() => fetchNextPage()}
536
+
disabled={isFetchingNextPage}
537
+
className="w-[calc(100%-2rem)] mx-4 my-4 px-4 py-2 bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 font-semibold disabled:opacity-50"
538
+
>
539
+
{isFetchingNextPage ? "Loading..." : "Load More"}
540
+
</button>
541
+
)}
542
</div>
543
</div>
544
</>
+50
-1
src/routes/search.tsx
+50
-1
src/routes/search.tsx
···
1
import { createFileRoute } from "@tanstack/react-router";
2
3
+
import { Header } from "~/components/Header";
4
+
import { Import } from "~/components/Import";
5
+
6
export const Route = createFileRoute("/search")({
7
component: Search,
8
});
9
10
export function Search() {
11
+
return (
12
+
<>
13
+
<Header
14
+
title="Explore"
15
+
backButtonCallback={() => {
16
+
if (window.history.length > 1) {
17
+
window.history.back();
18
+
} else {
19
+
window.location.assign("/");
20
+
}
21
+
}}
22
+
/>
23
+
<div className=" flex flex-col items-center mt-4 mx-4 gap-4">
24
+
<Import />
25
+
<div className="flex flex-col">
26
+
<p className="text-gray-600 dark:text-gray-400">
27
+
Sorry we dont have search. But instead, you can load some of these
28
+
types of content into Red Dwarf:
29
+
</p>
30
+
<ul className="list-disc list-inside mt-2 text-gray-600 dark:text-gray-400">
31
+
<li>
32
+
Bluesky URLs from supported clients (like{" "}
33
+
<code className="text-sm">bsky.app</code> or{" "}
34
+
<code className="text-sm">deer.social</code>).
35
+
</li>
36
+
<li>
37
+
AT-URIs (e.g.,{" "}
38
+
<code className="text-sm">at://did:example/collection/item</code>
39
+
).
40
+
</li>
41
+
<li>
42
+
Plain handles (like{" "}
43
+
<code className="text-sm">@username.bsky.social</code>).
44
+
</li>
45
+
<li>
46
+
Direct DIDs (Decentralized Identifiers, starting with{" "}
47
+
<code className="text-sm">did:</code>).
48
+
</li>
49
+
</ul>
50
+
<p className="mt-2 text-gray-600 dark:text-gray-400">
51
+
Simply paste one of these into the import field above and press
52
+
Enter to load the content.
53
+
</p>
54
+
</div>
55
+
</div>
56
+
</>
57
+
);
58
}
+181
-1
src/routes/settings.tsx
+181
-1
src/routes/settings.tsx
···
1
import { createFileRoute } from "@tanstack/react-router";
2
+
import { useAtom } from "jotai";
3
+
import { Slider } from "radix-ui";
4
+
5
+
import { Header } from "~/components/Header";
6
+
import Login from "~/components/Login";
7
+
import {
8
+
constellationURLAtom,
9
+
defaultconstellationURL,
10
+
defaulthue,
11
+
defaultImgCDN,
12
+
defaultslingshotURL,
13
+
defaultVideoCDN,
14
+
hueAtom,
15
+
imgCDNAtom,
16
+
slingshotURLAtom,
17
+
videoCDNAtom,
18
+
} from "~/utils/atoms";
19
20
export const Route = createFileRoute("/settings")({
21
component: Settings,
22
});
23
24
export function Settings() {
25
+
return (
26
+
<>
27
+
<Header
28
+
title="Settings"
29
+
backButtonCallback={() => {
30
+
if (window.history.length > 1) {
31
+
window.history.back();
32
+
} else {
33
+
window.location.assign("/");
34
+
}
35
+
}}
36
+
/>
37
+
<div className="lg:hidden">
38
+
<Login />
39
+
</div>
40
+
<div className="h-4" />
41
+
<TextInputSetting
42
+
atom={constellationURLAtom}
43
+
title={"Constellation"}
44
+
description={
45
+
"Customize the Constellation instance to be used by Red Dwarf"
46
+
}
47
+
init={defaultconstellationURL}
48
+
/>
49
+
<TextInputSetting
50
+
atom={slingshotURLAtom}
51
+
title={"Slingshot"}
52
+
description={"Customize the Slingshot instance to be used by Red Dwarf"}
53
+
init={defaultslingshotURL}
54
+
/>
55
+
<TextInputSetting
56
+
atom={imgCDNAtom}
57
+
title={"Image CDN"}
58
+
description={
59
+
"Customize the Constellation instance to be used by Red Dwarf"
60
+
}
61
+
init={defaultImgCDN}
62
+
/>
63
+
<TextInputSetting
64
+
atom={videoCDNAtom}
65
+
title={"Video CDN"}
66
+
description={"Customize the Slingshot instance to be used by Red Dwarf"}
67
+
init={defaultVideoCDN}
68
+
/>
69
+
70
+
<Hue />
71
+
<p className="text-gray-500 dark:text-gray-400 py-4 px-6 text-sm">
72
+
please restart/refresh the app if changes arent applying correctly
73
+
</p>
74
+
</>
75
+
);
76
+
}
77
+
function Hue() {
78
+
const [hue, setHue] = useAtom(hueAtom);
79
+
return (
80
+
<div className="flex flex-col px-4 mt-4 ">
81
+
<span className="z-10">Hue</span>
82
+
<div className="flex flex-row items-center gap-4">
83
+
<SliderComponent
84
+
atom={hueAtom}
85
+
max={360}
86
+
/>
87
+
<button
88
+
onClick={() => setHue(defaulthue ?? 28)}
89
+
className="px-6 py-2 h-12 rounded-full bg-gray-100 dark:bg-gray-800
90
+
text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 transition"
91
+
>
92
+
Reset
93
+
</button>
94
+
</div>
95
+
</div>
96
+
);
97
}
98
+
99
+
export function TextInputSetting({
100
+
atom,
101
+
title,
102
+
description,
103
+
init,
104
+
}: {
105
+
atom: typeof constellationURLAtom;
106
+
title?: string;
107
+
description?: string;
108
+
init?: string;
109
+
}) {
110
+
const [value, setValue] = useAtom(atom);
111
+
return (
112
+
<div className="flex flex-col gap-2 px-4 py-2">
113
+
{/* <div>
114
+
{title && (
115
+
<h3 className="text-sm font-medium text-gray-900 dark:text-gray-100">
116
+
{title}
117
+
</h3>
118
+
)}
119
+
{description && (
120
+
<p className="text-sm text-gray-500 dark:text-gray-400">
121
+
{description}
122
+
</p>
123
+
)}
124
+
</div> */}
125
+
126
+
<div className="flex flex-row gap-2 items-center">
127
+
<div className="m3input-field m3input-label m3input-border size-md flex-1">
128
+
<input
129
+
type="text"
130
+
placeholder=" "
131
+
value={value}
132
+
onChange={(e) => setValue(e.target.value)}
133
+
/>
134
+
<label>{title}</label>
135
+
</div>
136
+
{/* <input
137
+
type="text"
138
+
value={value}
139
+
onChange={(e) => setValue(e.target.value)}
140
+
className="flex-1 px-3 py-2 rounded-lg bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700
141
+
text-gray-900 dark:text-gray-100 placeholder:text-gray-500 dark:placeholder:text-gray-400
142
+
focus:outline-none focus:ring-2 focus:ring-gray-400 dark:focus:ring-gray-600"
143
+
placeholder="Enter value..."
144
+
/> */}
145
+
<button
146
+
onClick={() => setValue(init ?? "")}
147
+
className="px-6 py-2 h-12 rounded-full bg-gray-100 dark:bg-gray-800
148
+
text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 transition"
149
+
>
150
+
Reset
151
+
</button>
152
+
</div>
153
+
</div>
154
+
);
155
+
}
156
+
157
+
158
+
interface SliderProps {
159
+
atom: typeof hueAtom;
160
+
min?: number;
161
+
max?: number;
162
+
step?: number;
163
+
}
164
+
165
+
export const SliderComponent: React.FC<SliderProps> = ({
166
+
atom,
167
+
min = 0,
168
+
max = 100,
169
+
step = 1,
170
+
}) => {
171
+
172
+
const [value, setValue] = useAtom(atom)
173
+
174
+
return (
175
+
<Slider.Root
176
+
className="relative flex items-center w-full h-4"
177
+
value={[value]}
178
+
min={min}
179
+
max={max}
180
+
step={step}
181
+
onValueChange={(v: number[]) => setValue(v[0])}
182
+
>
183
+
<Slider.Track className="relative flex-grow h-4 bg-gray-300 dark:bg-gray-700 rounded-full">
184
+
<Slider.Range className="absolute h-full bg-gray-500 dark:bg-gray-400 rounded-l-full rounded-r-none" />
185
+
</Slider.Track>
186
+
<Slider.Thumb className="shadow-[0_0_0_8px_var(--color-white)] dark:shadow-[0_0_0_8px_var(--color-gray-950)] block w-[3px] h-12 bg-gray-500 dark:bg-gray-400 rounded-md focus:outline-none" />
187
+
</Slider.Root>
188
+
);
189
+
};
+184
-13
src/styles/app.css
+184
-13
src/styles/app.css
···
1
@import "tailwindcss";
2
3
/* @theme {
···
14
--color-gray-950: oklch(0.129 0.050 222.000);
15
} */
16
17
@theme {
18
-
--color-gray-50: oklch(0.984 0.012 28);
19
-
--color-gray-100: oklch(0.968 0.017 28);
20
-
--color-gray-200: oklch(0.929 0.025 28);
21
-
--color-gray-300: oklch(0.869 0.035 28);
22
-
--color-gray-400: oklch(0.704 0.05 28);
23
-
--color-gray-500: oklch(0.554 0.06 28);
24
-
--color-gray-600: oklch(0.446 0.058 28);
25
-
--color-gray-700: oklch(0.372 0.058 28);
26
-
--color-gray-800: oklch(0.279 0.055 28);
27
-
--color-gray-900: oklch(0.208 0.055 28);
28
-
--color-gray-950: oklch(0.129 0.055 28);
29
}
30
31
@layer base {
···
47
}
48
}
49
50
@media (width >= 64rem /* 1024px */) {
51
-
html,
52
-
body {
53
scrollbar-gutter: stable both-edges !important;
54
}
55
}
56
.scroll-thin {
57
scrollbar-width: thin;
58
/*scrollbar-gutter: stable both-edges !important;*/
···
61
.scroll-none {
62
scrollbar-width: none;
63
}
···
1
+
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Spectral+SC:wght@500&display=swap');
2
@import "tailwindcss";
3
4
/* @theme {
···
15
--color-gray-950: oklch(0.129 0.050 222.000);
16
} */
17
18
+
:root {
19
+
--safe-hue: var(--tw-gray-hue, 28)
20
+
}
21
+
22
@theme {
23
+
--color-gray-50: oklch(0.984 0.012 var(--safe-hue));
24
+
--color-gray-100: oklch(0.968 0.017 var(--safe-hue));
25
+
--color-gray-200: oklch(0.929 0.025 var(--safe-hue));
26
+
--color-gray-300: oklch(0.869 0.035 var(--safe-hue));
27
+
--color-gray-400: oklch(0.704 0.05 var(--safe-hue));
28
+
--color-gray-500: oklch(0.554 0.06 var(--safe-hue));
29
+
--color-gray-600: oklch(0.446 0.058 var(--safe-hue));
30
+
--color-gray-700: oklch(0.372 0.058 var(--safe-hue));
31
+
--color-gray-800: oklch(0.279 0.055 var(--safe-hue));
32
+
--color-gray-900: oklch(0.208 0.055 var(--safe-hue));
33
+
--color-gray-950: oklch(0.129 0.055 var(--safe-hue));
34
}
35
36
@layer base {
···
52
}
53
}
54
55
+
.gutter{
56
+
scrollbar-gutter: stable both-edges;
57
+
}
58
+
59
@media (width >= 64rem /* 1024px */) {
60
+
html:not(:has(.disablegutter)),
61
+
body:not(:has(.disablegutter)) {
62
scrollbar-gutter: stable both-edges !important;
63
}
64
+
html:has(.disablescroll),
65
+
body:has(.disablescroll) {
66
+
scrollbar-width: none;
67
+
overflow-y: hidden;
68
+
}
69
+
}
70
+
71
+
.lightbox:has(+.lightbox-sidebar){
72
+
opacity: 0;
73
}
74
+
75
.scroll-thin {
76
scrollbar-width: thin;
77
/*scrollbar-gutter: stable both-edges !important;*/
···
80
.scroll-none {
81
scrollbar-width: none;
82
}
83
+
84
+
.dangerousFediContent {
85
+
& a[href]{
86
+
text-decoration: none;
87
+
color: rgb(29, 122, 242);
88
+
word-break: break-all;
89
+
}
90
+
}
91
+
92
+
.font-inter {
93
+
font-family: "Inter", sans-serif;
94
+
}
95
+
.font-roboto {
96
+
font-family: "Roboto", sans-serif;
97
+
}
98
+
99
+
:root {
100
+
--header-bg-light: color-mix(in srgb, var(--color-white) calc(var(--is-top) * 100%), var(--color-gray-50));
101
+
--header-bg-dark: color-mix(in srgb, var(--color-gray-950) calc(var(--is-top) * 100%), var(--color-gray-900));
102
+
}
103
+
104
+
:root {
105
+
--header-bg: var(--header-bg-light);
106
+
}
107
+
@media (prefers-color-scheme: dark) {
108
+
:root {
109
+
--header-bg: var(--header-bg-dark);
110
+
}
111
+
}
112
+
113
+
:root {
114
+
--shadow-opacity: calc(1 - var(--is-top));
115
+
--tw-shadow-header: 0 2px 8px hsl(0 0% 0% / calc(var(--shadow-opacity) * 0.15));
116
+
}
117
+
118
+
119
+
/* m3 input */
120
+
:root {
121
+
--m3input-radius: 6px;
122
+
--m3input-border-width: .0625rem;
123
+
--m3input-font-size: 16px;
124
+
--m3input-transition: 150ms cubic-bezier(.2, .8, .2, 1);
125
+
/* light theme */
126
+
--m3input-bg: var(--color-gray-50);
127
+
--m3input-border-color: var(--color-gray-400);
128
+
--m3input-label-color: var(--color-gray-500);
129
+
--m3input-text-color: var(--color-gray-900);
130
+
--m3input-focus-color: var(--color-gray-600);
131
+
}
132
+
133
+
@media (prefers-color-scheme: dark) {
134
+
:root {
135
+
--m3input-bg: var(--color-gray-950);
136
+
--m3input-border-color: var(--color-gray-700);
137
+
--m3input-label-color: var(--color-gray-400);
138
+
--m3input-text-color: var(--color-gray-50);
139
+
--m3input-focus-color: var(--color-gray-400);
140
+
}
141
+
}
142
+
143
+
/* reset page *//*
144
+
html,
145
+
body {
146
+
background: var(--m3input-bg);
147
+
margin: 0;
148
+
padding: 1rem;
149
+
color: var(--m3input-text-color);
150
+
font-family: system-ui, sans-serif;
151
+
font-size: var(--m3input-font-size);
152
+
}*/
153
+
154
+
/* base wrapper */
155
+
.m3input-field.m3input-label.m3input-border {
156
+
position: relative;
157
+
display: inline-block;
158
+
width: 100%;
159
+
/*max-width: 400px;*/
160
+
}
161
+
162
+
/* size variants */
163
+
.m3input-field.size-sm {
164
+
--m3input-h: 40px;
165
+
}
166
+
167
+
.m3input-field.size-md {
168
+
--m3input-h: 48px;
169
+
}
170
+
171
+
.m3input-field.size-lg {
172
+
--m3input-h: 56px;
173
+
}
174
+
175
+
.m3input-field.size-xl {
176
+
--m3input-h: 64px;
177
+
}
178
+
179
+
.m3input-field.m3input-label.m3input-border:not(.size-sm):not(.size-md):not(.size-lg):not(.size-xl) {
180
+
--m3input-h: 48px;
181
+
}
182
+
183
+
/* outlined input */
184
+
.m3input-field.m3input-label.m3input-border input {
185
+
width: 100%;
186
+
height: var(--m3input-h);
187
+
border: var(--m3input-border-width) solid var(--m3input-border-color);
188
+
border-radius: var(--m3input-radius);
189
+
background: var(--m3input-bg);
190
+
color: var(--m3input-text-color);
191
+
font-size: var(--m3input-font-size);
192
+
padding: 0 12px;
193
+
box-sizing: border-box;
194
+
outline: none;
195
+
transition: border-color var(--m3input-transition), box-shadow var(--m3input-transition);
196
+
}
197
+
198
+
/* focus ring */
199
+
.m3input-field.m3input-label.m3input-border input:focus {
200
+
border-color: var(--m3input-focus-color);
201
+
/*box-shadow: 0 0 0 2px color-mix(in srgb, var(--focus-color) 20%, transparent);*/
202
+
}
203
+
204
+
/* label */
205
+
.m3input-field.m3input-label.m3input-border label {
206
+
position: absolute;
207
+
left: 12px;
208
+
top: 50%;
209
+
transform: translateY(-50%);
210
+
background: var(--m3input-bg);
211
+
padding: 0 .25em;
212
+
color: var(--m3input-label-color);
213
+
pointer-events: none;
214
+
transition: all var(--m3input-transition);
215
+
}
216
+
217
+
/* float on focus or when filled */
218
+
.m3input-field.m3input-label.m3input-border input:focus+label,
219
+
.m3input-field.m3input-label.m3input-border input:not(:placeholder-shown)+label {
220
+
top: 0;
221
+
transform: translateY(-50%) scale(.78);
222
+
left: 0;
223
+
color: var(--m3input-focus-color);
224
+
}
225
+
226
+
/* placeholder trick */
227
+
.m3input-field.m3input-label.m3input-border input::placeholder {
228
+
color: transparent;
229
+
}
230
+
231
+
/* radix i love you but like cmon man */
232
+
body[data-scroll-locked]{
233
+
margin-left: var(--removed-body-scroll-bar-size) !important;
234
+
}
+80
-3
src/utils/atoms.ts
+80
-3
src/utils/atoms.ts
···
1
+
import { atom, createStore, useAtomValue } from "jotai";
2
+
import { atomWithStorage } from "jotai/utils";
3
+
import { useEffect } from "react";
4
+
5
+
export const store = createStore();
6
+
7
+
export const quickAuthAtom = atomWithStorage<string | null>(
8
+
"quickAuth",
9
+
null
10
+
);
11
+
12
+
export const selectedFeedUriAtom = atomWithStorage<string | null>(
13
+
"selectedFeedUri",
14
+
null
15
+
);
16
+
17
+
//export const feedScrollPositionsAtom = atom<Record<string, number>>({});
18
+
19
+
export const feedScrollPositionsAtom = atomWithStorage<Record<string, number>>(
20
+
"feedscrollpositions",
21
+
{}
22
+
);
23
+
24
+
export const likedPostsAtom = atomWithStorage<Record<string, string>>(
25
+
"likedPosts",
26
+
{}
27
+
);
28
+
29
+
export const defaultconstellationURL = "constellation.microcosm.blue";
30
+
export const constellationURLAtom = atomWithStorage<string>(
31
+
"constellationURL",
32
+
defaultconstellationURL
33
+
);
34
+
export const defaultslingshotURL = "slingshot.microcosm.blue";
35
+
export const slingshotURLAtom = atomWithStorage<string>(
36
+
"slingshotURL",
37
+
defaultslingshotURL
38
+
);
39
+
export const defaultImgCDN = "cdn.bsky.app";
40
+
export const imgCDNAtom = atomWithStorage<string>("imgcdnurl", defaultImgCDN);
41
+
export const defaultVideoCDN = "video.bsky.app";
42
+
export const videoCDNAtom = atomWithStorage<string>(
43
+
"videocdnurl",
44
+
defaultVideoCDN
45
+
);
46
+
47
+
export const defaulthue = 28;
48
+
export const hueAtom = atomWithStorage<number>("hue", defaulthue);
49
+
50
+
export const isAtTopAtom = atom<boolean>(true);
51
+
52
+
type ComposerState =
53
+
| { kind: "closed" }
54
+
| { kind: "root" }
55
+
| { kind: "reply"; parent: string }
56
+
| { kind: "quote"; subject: string };
57
+
export const composerAtom = atom<ComposerState>({ kind: "closed" });
58
+
59
+
//export const agentAtom = atom<Agent | null>(null);
60
+
//export const authedAtom = atom<boolean>(false);
61
+
62
+
export function useAtomCssVar(atom: typeof hueAtom, cssVar: string) {
63
+
const value = useAtomValue(atom);
64
65
+
useEffect(() => {
66
+
document.documentElement.style.setProperty(cssVar, value.toString());
67
+
}, [value, cssVar]);
68
69
+
useEffect(() => {
70
+
document.documentElement.style.setProperty(cssVar, value.toString());
71
+
}, []);
72
+
}
73
+
74
+
hueAtom.onMount = (setAtom) => {
75
+
const stored = localStorage.getItem("hue");
76
+
if (stored != null) setAtom(Number(stored));
77
+
};
78
+
// export function initAtomToCssVar(atom: typeof hueAtom, cssVar: string) {
79
+
// const initial = store.get(atom);
80
+
// console.log("atom get ", initial);
81
+
// document.documentElement.style.setProperty(cssVar, initial.toString());
82
+
// }
+163
src/utils/followState.ts
+163
src/utils/followState.ts
···
···
1
+
import { type Agent,AtUri } from "@atproto/api";
2
+
import { TID } from "@atproto/common-web";
3
+
import type { QueryClient } from "@tanstack/react-query";
4
+
5
+
import { type linksRecordsResponse,useQueryConstellation } from "./useQuery";
6
+
7
+
export function useGetFollowState({
8
+
target,
9
+
user,
10
+
}: {
11
+
target: string;
12
+
user?: string;
13
+
}): string[] | undefined {
14
+
const { data: followData } = useQueryConstellation(
15
+
user
16
+
? {
17
+
method: "/links",
18
+
target: target,
19
+
// @ts-expect-error overloading sucks so much
20
+
collection: "app.bsky.graph.follow",
21
+
path: ".subject",
22
+
dids: [user],
23
+
}
24
+
: { method: "undefined", target: "whatever" }
25
+
// overloading sucks so much
26
+
) as { data: linksRecordsResponse | undefined };
27
+
const follows = followData?.linking_records.slice(0, 50) ?? [];
28
+
29
+
if (follows.length > 0) {
30
+
return follows.map((linksRecord) => {
31
+
return `at://${linksRecord.did}/${linksRecord.collection}/${linksRecord.rkey}`;
32
+
});
33
+
}
34
+
35
+
return undefined;
36
+
}
37
+
38
+
export function toggleFollow({
39
+
agent,
40
+
targetDid,
41
+
followRecords,
42
+
queryClient,
43
+
}: {
44
+
agent?: Agent;
45
+
targetDid?: string;
46
+
followRecords: undefined | string[];
47
+
queryClient: QueryClient;
48
+
}) {
49
+
if (!agent?.did || !targetDid) return;
50
+
51
+
const queryKey = [
52
+
"constellation",
53
+
"/links",
54
+
targetDid,
55
+
"app.bsky.graph.follow",
56
+
".subject",
57
+
undefined,
58
+
[agent.did],
59
+
] as const;
60
+
61
+
const updateCache = (
62
+
updater: (
63
+
oldData: linksRecordsResponse | undefined
64
+
) => linksRecordsResponse | undefined
65
+
) => {
66
+
queryClient.setQueryData(
67
+
queryKey,
68
+
(oldData: linksRecordsResponse | undefined) => updater(oldData)
69
+
);
70
+
};
71
+
72
+
if (typeof followRecords === "undefined") {
73
+
const newRecord = {
74
+
repo: agent.did,
75
+
collection: "app.bsky.graph.follow",
76
+
rkey: TID.next().toString(),
77
+
record: {
78
+
$type: "app.bsky.graph.follow",
79
+
subject: targetDid,
80
+
createdAt: new Date().toISOString(),
81
+
},
82
+
};
83
+
84
+
updateCache((old) => {
85
+
const newLinkingRecords = [newRecord, ...(old?.linking_records ?? [])];
86
+
return {
87
+
...old,
88
+
linking_records: newLinkingRecords,
89
+
} as linksRecordsResponse;
90
+
});
91
+
92
+
agent.com.atproto.repo.createRecord(newRecord).catch((err) => {
93
+
console.error("Follow failed, reverting cache:", err);
94
+
// rollback cache
95
+
updateCache((old) => {
96
+
return {
97
+
...old,
98
+
linking_records:
99
+
old?.linking_records.filter((r) => r.rkey !== newRecord.rkey) ?? [],
100
+
} as linksRecordsResponse;
101
+
});
102
+
});
103
+
104
+
return;
105
+
}
106
+
107
+
followRecords.forEach((followRecord) => {
108
+
const aturi = new AtUri(followRecord);
109
+
agent.com.atproto.repo
110
+
.deleteRecord({
111
+
repo: agent.did!,
112
+
collection: "app.bsky.graph.follow",
113
+
rkey: aturi.rkey,
114
+
})
115
+
.catch(console.error);
116
+
});
117
+
118
+
updateCache((old) => {
119
+
if (!old?.linking_records) return old;
120
+
return {
121
+
...old,
122
+
linking_records: old.linking_records.filter(
123
+
(rec) =>
124
+
!followRecords.includes(
125
+
`at://${rec.did}/${rec.collection}/${rec.rkey}`
126
+
)
127
+
),
128
+
};
129
+
});
130
+
}
131
+
132
+
133
+
134
+
export function useGetOneToOneState(params?: {
135
+
target: string;
136
+
user: string;
137
+
collection: string;
138
+
path: string;
139
+
}): string[] | undefined {
140
+
const { data: arbitrarydata } = useQueryConstellation(
141
+
params && params.user
142
+
? {
143
+
method: "/links",
144
+
target: params.target,
145
+
// @ts-expect-error overloading sucks so much
146
+
collection: params.collection,
147
+
path: params.path,
148
+
dids: [params.user],
149
+
}
150
+
: { method: "undefined", target: "whatever" }
151
+
// overloading sucks so much
152
+
) as { data: linksRecordsResponse | undefined };
153
+
if (!params || !params.user) return undefined;
154
+
const data = arbitrarydata?.linking_records.slice(0, 50) ?? [];
155
+
156
+
if (data.length > 0) {
157
+
return data.map((linksRecord) => {
158
+
return `at://${linksRecord.did}/${linksRecord.collection}/${linksRecord.rkey}`;
159
+
});
160
+
}
161
+
162
+
return undefined;
163
+
}
+14
src/utils/oauthClient.ts
+14
src/utils/oauthClient.ts
···
···
1
+
import { BrowserOAuthClient, type ClientMetadata } from '@atproto/oauth-client-browser';
2
+
3
+
// i tried making this https://pds-nd.whey.party but cors is annoying as fuck
4
+
const handleResolverPDS = 'https://bsky.social';
5
+
6
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
7
+
// @ts-ignore this should be fine ? the vite plugin should generate this before errors
8
+
import clientMetadata from '../../public/client-metadata.json' with { type: 'json' };
9
+
10
+
export const oauthClient = new BrowserOAuthClient({
11
+
// The type assertion is needed because the static import isn't strictly typed
12
+
clientMetadata: clientMetadata as ClientMetadata,
13
+
handleResolver: handleResolverPDS,
14
+
});
+70
-71
src/utils/useHydrated.ts
+70
-71
src/utils/useHydrated.ts
···
1
-
import { useState, useEffect, useMemo } from "react";
2
import {
3
AppBskyEmbedExternal,
4
AppBskyEmbedImages,
5
AppBskyEmbedRecord,
6
AppBskyEmbedRecordWithMedia,
7
AppBskyEmbedVideo,
8
-
AppBskyActorDefs,
9
AppBskyFeedPost,
10
AtUri,
11
-
type $Typed,
12
} from "@atproto/api";
13
-
import * as ATPAPI from "@atproto/api"
14
15
-
import { useQueryPost, useQueryProfile, useQueryIdentity } from "./useQuery";
16
17
-
type QueryResultData<T extends (...args: any) => any> = ReturnType<T> extends
18
-
| { data: infer D }
19
-
| undefined
20
-
? D
21
-
: never;
22
23
function asTyped<T extends { $type: string }>(obj: T): $Typed<T> {
24
return obj as $Typed<T>;
···
27
export function hydrateEmbedImages(
28
embed: AppBskyEmbedImages.Main,
29
did: string,
30
): $Typed<AppBskyEmbedImages.View> {
31
return asTyped({
32
$type: "app.bsky.embed.images#view" as const,
···
35
const link = img.image.ref?.["$link"];
36
if (!link) return null;
37
return {
38
-
thumb: `https://cdn.bsky.app/img/feed_thumbnail/plain/${did}/${link}@jpeg`,
39
-
fullsize: `https://cdn.bsky.app/img/feed_fullsize/plain/${did}/${link}@jpeg`,
40
alt: img.alt || "",
41
aspectRatio: img.aspectRatio,
42
};
···
48
export function hydrateEmbedExternal(
49
embed: AppBskyEmbedExternal.Main,
50
did: string,
51
): $Typed<AppBskyEmbedExternal.View> {
52
return asTyped({
53
$type: "app.bsky.embed.external#view" as const,
···
56
title: embed.external.title,
57
description: embed.external.description,
58
thumb: embed.external.thumb?.ref?.$link
59
-
? `https://cdn.bsky.app/img/feed_thumbnail/plain/${did}/${embed.external.thumb.ref.$link}@jpeg`
60
: undefined,
61
},
62
});
···
65
export function hydrateEmbedVideo(
66
embed: AppBskyEmbedVideo.Main,
67
did: string,
68
): $Typed<AppBskyEmbedVideo.View> {
69
const videoLink = embed.video.ref.$link;
70
return asTyped({
71
$type: "app.bsky.embed.video#view" as const,
72
-
playlist: `https://video.bsky.app/watch/${did}/${videoLink}/playlist.m3u8`,
73
-
thumbnail: `https://video.bsky.app/watch/${did}/${videoLink}/thumbnail.jpg`,
74
aspectRatio: embed.aspectRatio,
75
cid: videoLink,
76
});
···
81
quotedPost: QueryResultData<typeof useQueryPost>,
82
quotedProfile: QueryResultData<typeof useQueryProfile>,
83
quotedIdentity: QueryResultData<typeof useQueryIdentity>,
84
): $Typed<AppBskyEmbedRecord.View> | undefined {
85
if (!quotedPost || !quotedProfile || !quotedIdentity) {
86
return undefined;
···
92
handle: quotedIdentity.handle,
93
displayName: quotedProfile.value.displayName ?? quotedIdentity.handle,
94
avatar: quotedProfile.value.avatar?.ref?.$link
95
-
? `https://cdn.bsky.app/img/avatar/plain/${quotedIdentity.did}/${quotedProfile.value.avatar.ref.$link}@jpeg`
96
: undefined,
97
viewer: {},
98
labels: [],
···
123
quotedPost: QueryResultData<typeof useQueryPost>,
124
quotedProfile: QueryResultData<typeof useQueryProfile>,
125
quotedIdentity: QueryResultData<typeof useQueryIdentity>,
126
): $Typed<AppBskyEmbedRecordWithMedia.View> | undefined {
127
const hydratedRecord = hydrateEmbedRecord(
128
embed.record,
129
quotedPost,
130
quotedProfile,
131
quotedIdentity,
132
);
133
134
if (!hydratedRecord) return undefined;
···
149
150
export function useHydratedEmbed(
151
embed: AppBskyFeedPost.Record["embed"],
152
-
postAuthorDid: string | undefined,
153
) {
154
const recordInfo = useMemo(() => {
155
-
if (
156
-
AppBskyEmbedRecordWithMedia.isMain(embed)
157
-
) {
158
const recordUri = embed.record.record.uri;
159
const quotedAuthorDid = new AtUri(recordUri).hostname;
160
return { recordUri, quotedAuthorDid, isRecordType: true };
161
-
} else
162
-
if (
163
-
AppBskyEmbedRecord.isMain(embed)
164
-
) {
165
const recordUri = embed.record.uri;
166
const quotedAuthorDid = new AtUri(recordUri).hostname;
167
return { recordUri, quotedAuthorDid, isRecordType: true };
···
172
isRecordType: false,
173
};
174
}, [embed]);
175
-
const { isRecordType, recordUri, quotedAuthorDid } = recordInfo;
176
177
178
const usequerypostresults = useQueryPost(recordUri);
179
-
// const {
180
-
// data: quotedPost,
181
-
// isLoading: isLoadingPost,
182
-
// error: postError,
183
-
// } = usequerypostresults
184
185
-
const profileUri = quotedAuthorDid ? `at://${quotedAuthorDid}/app.bsky.actor.profile/self` : undefined;
186
187
const {
188
data: quotedProfile,
···
190
error: profileError,
191
} = useQueryProfile(profileUri);
192
193
const queryidentityresult = useQueryIdentity(quotedAuthorDid);
194
-
// const {
195
-
// data: quotedIdentity,
196
-
// isLoading: isLoadingIdentity,
197
-
// error: identityError,
198
-
// } = queryidentityresult
199
200
-
const [hydratedEmbed, setHydratedEmbed] = useState<
201
-
HydratedEmbedView | undefined
202
-
>(undefined);
203
204
-
useEffect(() => {
205
-
if (!embed || !postAuthorDid) {
206
-
setHydratedEmbed(undefined);
207
-
return;
208
-
}
209
-
210
-
if (isRecordType && (!usequerypostresults?.data || !quotedProfile || !queryidentityresult?.data)) {
211
-
setHydratedEmbed(undefined);
212
-
return;
213
}
214
215
try {
216
-
let result: HydratedEmbedView | undefined;
217
-
218
if (AppBskyEmbedImages.isMain(embed)) {
219
-
result = hydrateEmbedImages(embed, postAuthorDid);
220
} else if (AppBskyEmbedExternal.isMain(embed)) {
221
-
result = hydrateEmbedExternal(embed, postAuthorDid);
222
} else if (AppBskyEmbedVideo.isMain(embed)) {
223
-
result = hydrateEmbedVideo(embed, postAuthorDid);
224
} else if (AppBskyEmbedRecord.isMain(embed)) {
225
-
result = hydrateEmbedRecord(
226
embed,
227
usequerypostresults?.data,
228
quotedProfile,
229
queryidentityresult?.data,
230
);
231
} else if (AppBskyEmbedRecordWithMedia.isMain(embed)) {
232
let hydratedMedia:
···
236
| undefined;
237
238
if (AppBskyEmbedImages.isMain(embed.media)) {
239
-
hydratedMedia = hydrateEmbedImages(embed.media, postAuthorDid);
240
} else if (AppBskyEmbedExternal.isMain(embed.media)) {
241
-
hydratedMedia = hydrateEmbedExternal(embed.media, postAuthorDid);
242
} else if (AppBskyEmbedVideo.isMain(embed.media)) {
243
-
hydratedMedia = hydrateEmbedVideo(embed.media, postAuthorDid);
244
}
245
246
if (hydratedMedia) {
247
-
result = hydrateEmbedRecordWithMedia(
248
embed,
249
hydratedMedia,
250
usequerypostresults?.data,
251
quotedProfile,
252
queryidentityresult?.data,
253
);
254
}
255
}
256
-
setHydratedEmbed(result);
257
} catch (e) {
258
console.error("Error hydrating embed", e);
259
-
setHydratedEmbed(undefined);
260
}
261
-
}, [
262
-
embed,
263
-
postAuthorDid,
264
-
isRecordType,
265
-
usequerypostresults?.data,
266
-
quotedProfile,
267
-
queryidentityresult?.data,
268
-
]);
269
270
const isLoading = isRecordType
271
-
? usequerypostresults?.isLoading || isLoadingProfile || queryidentityresult?.isLoading
272
: false;
273
-
const error = usequerypostresults?.error || profileError || queryidentityresult?.error;
274
275
return { data: hydratedEmbed, isLoading, error };
276
-
}
···
1
import {
2
+
type $Typed,
3
+
AppBskyActorDefs,
4
AppBskyEmbedExternal,
5
AppBskyEmbedImages,
6
AppBskyEmbedRecord,
7
AppBskyEmbedRecordWithMedia,
8
AppBskyEmbedVideo,
9
AppBskyFeedPost,
10
AtUri,
11
} from "@atproto/api";
12
+
import { useAtom } from "jotai";
13
+
import { useMemo } from "react";
14
15
+
import { imgCDNAtom, videoCDNAtom } from "./atoms";
16
+
import { useQueryIdentity, useQueryPost, useQueryProfile } from "./useQuery";
17
18
+
type QueryResultData<T extends (...args: any) => any> =
19
+
ReturnType<T> extends { data: infer D } | undefined ? D : never;
20
21
function asTyped<T extends { $type: string }>(obj: T): $Typed<T> {
22
return obj as $Typed<T>;
···
25
export function hydrateEmbedImages(
26
embed: AppBskyEmbedImages.Main,
27
did: string,
28
+
cdn: string
29
): $Typed<AppBskyEmbedImages.View> {
30
return asTyped({
31
$type: "app.bsky.embed.images#view" as const,
···
34
const link = img.image.ref?.["$link"];
35
if (!link) return null;
36
return {
37
+
thumb: `https://${cdn}/img/feed_thumbnail/plain/${did}/${link}@jpeg`,
38
+
fullsize: `https://${cdn}/img/feed_fullsize/plain/${did}/${link}@jpeg`,
39
alt: img.alt || "",
40
aspectRatio: img.aspectRatio,
41
};
···
47
export function hydrateEmbedExternal(
48
embed: AppBskyEmbedExternal.Main,
49
did: string,
50
+
cdn: string
51
): $Typed<AppBskyEmbedExternal.View> {
52
return asTyped({
53
$type: "app.bsky.embed.external#view" as const,
···
56
title: embed.external.title,
57
description: embed.external.description,
58
thumb: embed.external.thumb?.ref?.$link
59
+
? `https://${cdn}/img/feed_thumbnail/plain/${did}/${embed.external.thumb.ref.$link}@jpeg`
60
: undefined,
61
},
62
});
···
65
export function hydrateEmbedVideo(
66
embed: AppBskyEmbedVideo.Main,
67
did: string,
68
+
videocdn: string
69
): $Typed<AppBskyEmbedVideo.View> {
70
const videoLink = embed.video.ref.$link;
71
return asTyped({
72
$type: "app.bsky.embed.video#view" as const,
73
+
playlist: `https://${videocdn}/watch/${did}/${videoLink}/playlist.m3u8`,
74
+
thumbnail: `https://${videocdn}/watch/${did}/${videoLink}/thumbnail.jpg`,
75
aspectRatio: embed.aspectRatio,
76
cid: videoLink,
77
});
···
82
quotedPost: QueryResultData<typeof useQueryPost>,
83
quotedProfile: QueryResultData<typeof useQueryProfile>,
84
quotedIdentity: QueryResultData<typeof useQueryIdentity>,
85
+
cdn: string
86
): $Typed<AppBskyEmbedRecord.View> | undefined {
87
if (!quotedPost || !quotedProfile || !quotedIdentity) {
88
return undefined;
···
94
handle: quotedIdentity.handle,
95
displayName: quotedProfile.value.displayName ?? quotedIdentity.handle,
96
avatar: quotedProfile.value.avatar?.ref?.$link
97
+
? `https://${cdn}/img/avatar/plain/${quotedIdentity.did}/${quotedProfile.value.avatar.ref.$link}@jpeg`
98
: undefined,
99
viewer: {},
100
labels: [],
···
125
quotedPost: QueryResultData<typeof useQueryPost>,
126
quotedProfile: QueryResultData<typeof useQueryProfile>,
127
quotedIdentity: QueryResultData<typeof useQueryIdentity>,
128
+
cdn: string
129
): $Typed<AppBskyEmbedRecordWithMedia.View> | undefined {
130
const hydratedRecord = hydrateEmbedRecord(
131
embed.record,
132
quotedPost,
133
quotedProfile,
134
quotedIdentity,
135
+
cdn
136
);
137
138
if (!hydratedRecord) return undefined;
···
153
154
export function useHydratedEmbed(
155
embed: AppBskyFeedPost.Record["embed"],
156
+
postAuthorDid: string | undefined
157
) {
158
const recordInfo = useMemo(() => {
159
+
if (AppBskyEmbedRecordWithMedia.isMain(embed)) {
160
const recordUri = embed.record.record.uri;
161
const quotedAuthorDid = new AtUri(recordUri).hostname;
162
return { recordUri, quotedAuthorDid, isRecordType: true };
163
+
} else if (AppBskyEmbedRecord.isMain(embed)) {
164
const recordUri = embed.record.uri;
165
const quotedAuthorDid = new AtUri(recordUri).hostname;
166
return { recordUri, quotedAuthorDid, isRecordType: true };
···
171
isRecordType: false,
172
};
173
}, [embed]);
174
175
+
const { isRecordType, recordUri, quotedAuthorDid } = recordInfo;
176
177
const usequerypostresults = useQueryPost(recordUri);
178
179
+
const profileUri = quotedAuthorDid
180
+
? `at://${quotedAuthorDid}/app.bsky.actor.profile/self`
181
+
: undefined;
182
183
const {
184
data: quotedProfile,
···
186
error: profileError,
187
} = useQueryProfile(profileUri);
188
189
+
const [imgcdn] = useAtom(imgCDNAtom);
190
+
const [videocdn] = useAtom(videoCDNAtom);
191
+
192
const queryidentityresult = useQueryIdentity(quotedAuthorDid);
193
194
+
const hydratedEmbed: HydratedEmbedView | undefined = (() => {
195
+
if (!embed || !postAuthorDid) return undefined;
196
197
+
if (
198
+
isRecordType &&
199
+
(!usequerypostresults?.data ||
200
+
!quotedProfile ||
201
+
!queryidentityresult?.data)
202
+
) {
203
+
return undefined;
204
}
205
206
try {
207
if (AppBskyEmbedImages.isMain(embed)) {
208
+
return hydrateEmbedImages(embed, postAuthorDid, imgcdn);
209
} else if (AppBskyEmbedExternal.isMain(embed)) {
210
+
return hydrateEmbedExternal(embed, postAuthorDid, imgcdn);
211
} else if (AppBskyEmbedVideo.isMain(embed)) {
212
+
return hydrateEmbedVideo(embed, postAuthorDid, videocdn);
213
} else if (AppBskyEmbedRecord.isMain(embed)) {
214
+
return hydrateEmbedRecord(
215
embed,
216
usequerypostresults?.data,
217
quotedProfile,
218
queryidentityresult?.data,
219
+
imgcdn
220
);
221
} else if (AppBskyEmbedRecordWithMedia.isMain(embed)) {
222
let hydratedMedia:
···
226
| undefined;
227
228
if (AppBskyEmbedImages.isMain(embed.media)) {
229
+
hydratedMedia = hydrateEmbedImages(
230
+
embed.media,
231
+
postAuthorDid,
232
+
imgcdn
233
+
);
234
} else if (AppBskyEmbedExternal.isMain(embed.media)) {
235
+
hydratedMedia = hydrateEmbedExternal(
236
+
embed.media,
237
+
postAuthorDid,
238
+
imgcdn
239
+
);
240
} else if (AppBskyEmbedVideo.isMain(embed.media)) {
241
+
hydratedMedia = hydrateEmbedVideo(
242
+
embed.media,
243
+
postAuthorDid,
244
+
videocdn
245
+
);
246
}
247
248
if (hydratedMedia) {
249
+
return hydrateEmbedRecordWithMedia(
250
embed,
251
hydratedMedia,
252
usequerypostresults?.data,
253
quotedProfile,
254
queryidentityresult?.data,
255
+
imgcdn
256
);
257
}
258
}
259
} catch (e) {
260
console.error("Error hydrating embed", e);
261
+
return undefined;
262
}
263
+
})();
264
265
const isLoading = isRecordType
266
+
? usequerypostresults?.isLoading ||
267
+
isLoadingProfile ||
268
+
queryidentityresult?.isLoading
269
: false;
270
+
271
+
const error =
272
+
usequerypostresults?.error || profileError || queryidentityresult?.error;
273
274
return { data: hydratedEmbed, isLoading, error };
275
+
}
+172
-44
src/utils/useQuery.ts
+172
-44
src/utils/useQuery.ts
···
1
import {
2
queryOptions,
3
-
useQuery,
4
useInfiniteQuery,
5
-
type QueryFunctionContext,
6
-
type UseQueryResult,
7
-
type InfiniteData
8
-
} from "@tanstack/react-query";
9
-
import * as ATPAPI from "@atproto/api";
10
11
-
export function constructIdentityQuery(didorhandle?: string) {
12
return queryOptions({
13
queryKey: ["identity", didorhandle],
14
queryFn: async () => {
15
if (!didorhandle) return undefined as undefined
16
const res = await fetch(
17
-
`https://slingshot.microcosm.blue/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${encodeURIComponent(didorhandle)}`
18
);
19
if (!res.ok) throw new Error("Failed to fetch post");
20
try {
···
28
return undefined;
29
}
30
},
31
});
32
}
33
export function useQueryIdentity(didorhandle: string): UseQueryResult<
···
54
Error
55
>
56
export function useQueryIdentity(didorhandle?: string) {
57
-
return useQuery(constructIdentityQuery(didorhandle));
58
}
59
60
-
export function constructPostQuery(uri?: string) {
61
return queryOptions({
62
queryKey: ["post", uri],
63
queryFn: async () => {
64
if (!uri) return undefined as undefined
65
const res = await fetch(
66
-
`https://slingshot.microcosm.blue/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
67
);
68
-
if (!res.ok) throw new Error("Failed to fetch post");
69
try {
70
-
return (await res.json()) as {
71
uri: string;
72
cid: string;
73
-
value: ATPAPI.AppBskyFeedPost.Record;
74
};
75
} catch (_e) {
76
return undefined;
77
}
78
},
79
});
80
}
81
export function useQueryPost(uri: string): UseQueryResult<
···
100
Error
101
>
102
export function useQueryPost(uri?: string) {
103
-
return useQuery(constructPostQuery(uri));
104
}
105
106
-
export function constructProfileQuery(uri?: string) {
107
return queryOptions({
108
queryKey: ["profile", uri],
109
queryFn: async () => {
110
if (!uri) return undefined as undefined
111
const res = await fetch(
112
-
`https://slingshot.microcosm.blue/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
113
);
114
-
if (!res.ok) throw new Error("Failed to fetch post");
115
try {
116
-
return (await res.json()) as {
117
uri: string;
118
cid: string;
119
-
value: ATPAPI.AppBskyActorProfile.Record;
120
};
121
} catch (_e) {
122
return undefined;
123
}
124
},
125
});
126
}
127
export function useQueryProfile(uri: string): UseQueryResult<
···
146
Error
147
>
148
export function useQueryProfile(uri?: string) {
149
-
return useQuery(constructProfileQuery(uri));
150
}
151
152
// export function constructConstellationQuery(
···
182
// target: string
183
// ): QueryOptions<linksAllResponse, Error>;
184
export function constructConstellationQuery(query?:{
185
method:
186
| "/links"
187
| "/links/distinct-dids"
188
| "/links/count"
189
| "/links/count/distinct-dids"
190
-
| "/links/all",
191
target: string,
192
collection?: string,
193
path?: string,
194
-
cursor?: string
195
}
196
) {
197
// : QueryOptions<
···
203
// Error
204
// >
205
return queryOptions({
206
-
queryKey: ["post", query?.method, query?.target, query?.collection, query?.path, query?.cursor] as const,
207
queryFn: async () => {
208
-
if (!query) return undefined as undefined
209
const method = query.method
210
const target = query.target
211
const collection = query?.collection
212
const path = query?.path
213
const cursor = query.cursor
214
const res = await fetch(
215
-
`https://constellation.microcosm.blue${method}?target=${encodeURIComponent(target)}${collection ? `&collection=${encodeURIComponent(collection)}` : ""}${path ? `&path=${encodeURIComponent(path)}` : ""}${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}`
216
);
217
if (!res.ok) throw new Error("Failed to fetch post");
218
try {
···
234
return undefined;
235
}
236
},
237
});
238
}
239
export function useQueryConstellation(query: {
···
242
collection: string;
243
path: string;
244
cursor?: string;
245
}): UseQueryResult<linksRecordsResponse, Error>;
246
export function useQueryConstellation(query: {
247
method: "/links/distinct-dids";
···
269
target: string;
270
}): UseQueryResult<linksAllResponse, Error>;
271
export function useQueryConstellation(): undefined;
272
export function useQueryConstellation(query?: {
273
method:
274
| "/links"
275
| "/links/distinct-dids"
276
| "/links/count"
277
| "/links/count/distinct-dids"
278
-
| "/links/all";
279
target: string;
280
collection?: string;
281
path?: string;
282
cursor?: string;
283
}):
284
| UseQueryResult<
285
| linksRecordsResponse
···
291
>
292
| undefined {
293
//if (!query) return;
294
return useQuery(
295
-
constructConstellationQuery(query)
296
);
297
}
298
···
301
collection: string;
302
rkey: string;
303
};
304
-
type linksRecordsResponse = {
305
total: string;
306
linking_records: linksRecord[];
307
cursor?: string;
···
314
type linksCountResponse = {
315
total: string;
316
};
317
-
type linksAllResponse = {
318
links: Record<
319
string,
320
Record<
···
329
330
export function constructFeedSkeletonQuery(options?: {
331
feedUri: string;
332
-
agent?: ATPAPI.AtpAgent;
333
isAuthed: boolean;
334
pdsUrl?: string;
335
feedServiceDid?: string;
···
369
370
export function useQueryFeedSkeleton(options?: {
371
feedUri: string;
372
-
agent?: ATPAPI.AtpAgent;
373
isAuthed: boolean;
374
pdsUrl?: string;
375
feedServiceDid?: string;
···
377
return useQuery(constructFeedSkeletonQuery(options));
378
}
379
380
-
export function constructPreferencesQuery(agent?: ATPAPI.AtpAgent | undefined, pdsUrl?: string | undefined) {
381
return queryOptions({
382
queryKey: ['preferences', agent?.did],
383
queryFn: async () => {
···
390
});
391
}
392
export function useQueryPreferences(options: {
393
-
agent?: ATPAPI.AtpAgent | undefined, pdsUrl?: string | undefined
394
}) {
395
return useQuery(constructPreferencesQuery(options.agent, options.pdsUrl));
396
}
397
398
399
400
-
export function constructArbitraryQuery(uri?: string) {
401
return queryOptions({
402
-
queryKey: ["post", uri],
403
queryFn: async () => {
404
if (!uri) return undefined as undefined
405
const res = await fetch(
406
-
`https://slingshot.microcosm.blue/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
407
);
408
-
if (!res.ok) throw new Error("Failed to fetch post");
409
try {
410
-
return (await res.json()) as {
411
uri: string;
412
cid: string;
413
value: any;
···
416
return undefined;
417
}
418
},
419
});
420
}
421
export function useQueryArbitrary(uri: string): UseQueryResult<
···
439
Error
440
>;
441
export function useQueryArbitrary(uri?: string) {
442
-
return useQuery(constructArbitraryQuery(uri));
443
}
444
445
export function constructFallbackNothingQuery(){
···
495
496
export function constructInfiniteFeedSkeletonQuery(options: {
497
feedUri: string;
498
-
agent?: ATPAPI.AtpAgent;
499
isAuthed: boolean;
500
pdsUrl?: string;
501
feedServiceDid?: string;
···
534
535
export function useInfiniteQueryFeedSkeleton(options: {
536
feedUri: string;
537
-
agent?: ATPAPI.AtpAgent;
538
isAuthed: boolean;
539
pdsUrl?: string;
540
feedServiceDid?: string;
541
}) {
542
const { queryKey, queryFn } = constructInfiniteFeedSkeletonQuery(options);
543
544
-
return useInfiniteQuery({
545
queryKey,
546
queryFn,
547
initialPageParam: undefined as never,
···
549
staleTime: Infinity,
550
refetchOnWindowFocus: false,
551
enabled: !!options.feedUri && (options.isAuthed ? !!options.agent && !!options.pdsUrl && !!options.feedServiceDid : true),
552
-
});
553
}
···
1
+
import * as ATPAPI from "@atproto/api";
2
import {
3
+
infiniteQueryOptions,
4
+
type QueryFunctionContext,
5
queryOptions,
6
useInfiniteQuery,
7
+
useQuery,
8
+
type UseQueryResult} from "@tanstack/react-query";
9
+
import { useAtom } from "jotai";
10
+
11
+
import { constellationURLAtom, slingshotURLAtom } from "./atoms";
12
13
+
export function constructIdentityQuery(didorhandle?: string, slingshoturl?: string) {
14
return queryOptions({
15
queryKey: ["identity", didorhandle],
16
queryFn: async () => {
17
if (!didorhandle) return undefined as undefined
18
const res = await fetch(
19
+
`https://${slingshoturl}/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${encodeURIComponent(didorhandle)}`
20
);
21
if (!res.ok) throw new Error("Failed to fetch post");
22
try {
···
30
return undefined;
31
}
32
},
33
+
staleTime: /*0,//*/ 5 * 60 * 1000, // 5 minutes
34
+
gcTime: /*0//*/5 * 60 * 1000,
35
});
36
}
37
export function useQueryIdentity(didorhandle: string): UseQueryResult<
···
58
Error
59
>
60
export function useQueryIdentity(didorhandle?: string) {
61
+
const [slingshoturl] = useAtom(slingshotURLAtom)
62
+
return useQuery(constructIdentityQuery(didorhandle, slingshoturl));
63
}
64
65
+
export function constructPostQuery(uri?: string, slingshoturl?: string) {
66
return queryOptions({
67
queryKey: ["post", uri],
68
queryFn: async () => {
69
if (!uri) return undefined as undefined
70
const res = await fetch(
71
+
`https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
72
);
73
+
let data: any;
74
try {
75
+
data = await res.json();
76
+
} catch {
77
+
return undefined;
78
+
}
79
+
if (res.status === 400) return undefined;
80
+
if (data?.error === "InvalidRequest" && data.message?.includes("Could not find repo")) {
81
+
return undefined; // cache โnot foundโ
82
+
}
83
+
try {
84
+
if (!res.ok) throw new Error("Failed to fetch post");
85
+
return (data) as {
86
uri: string;
87
cid: string;
88
+
value: any;
89
};
90
} catch (_e) {
91
return undefined;
92
}
93
},
94
+
retry: (failureCount, error) => {
95
+
// dont retry 400 errors
96
+
if ((error as any)?.message?.includes("400")) return false;
97
+
return failureCount < 2;
98
+
},
99
+
staleTime: /*0,//*/ 5 * 60 * 1000, // 5 minutes
100
+
gcTime: /*0//*/5 * 60 * 1000,
101
});
102
}
103
export function useQueryPost(uri: string): UseQueryResult<
···
122
Error
123
>
124
export function useQueryPost(uri?: string) {
125
+
const [slingshoturl] = useAtom(slingshotURLAtom)
126
+
return useQuery(constructPostQuery(uri, slingshoturl));
127
}
128
129
+
export function constructProfileQuery(uri?: string, slingshoturl?: string) {
130
return queryOptions({
131
queryKey: ["profile", uri],
132
queryFn: async () => {
133
if (!uri) return undefined as undefined
134
const res = await fetch(
135
+
`https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
136
);
137
+
let data: any;
138
+
try {
139
+
data = await res.json();
140
+
} catch {
141
+
return undefined;
142
+
}
143
+
if (res.status === 400) return undefined;
144
+
if (data?.error === "InvalidRequest" && data.message?.includes("Could not find repo")) {
145
+
return undefined; // cache โnot foundโ
146
+
}
147
try {
148
+
if (!res.ok) throw new Error("Failed to fetch post");
149
+
return (data) as {
150
uri: string;
151
cid: string;
152
+
value: any;
153
};
154
} catch (_e) {
155
return undefined;
156
}
157
},
158
+
retry: (failureCount, error) => {
159
+
// dont retry 400 errors
160
+
if ((error as any)?.message?.includes("400")) return false;
161
+
return failureCount < 2;
162
+
},
163
+
staleTime: /*0,//*/ 5 * 60 * 1000, // 5 minutes
164
+
gcTime: /*0//*/5 * 60 * 1000,
165
});
166
}
167
export function useQueryProfile(uri: string): UseQueryResult<
···
186
Error
187
>
188
export function useQueryProfile(uri?: string) {
189
+
const [slingshoturl] = useAtom(slingshotURLAtom)
190
+
return useQuery(constructProfileQuery(uri, slingshoturl));
191
}
192
193
// export function constructConstellationQuery(
···
223
// target: string
224
// ): QueryOptions<linksAllResponse, Error>;
225
export function constructConstellationQuery(query?:{
226
+
constellation: string,
227
method:
228
| "/links"
229
| "/links/distinct-dids"
230
| "/links/count"
231
| "/links/count/distinct-dids"
232
+
| "/links/all"
233
+
| "undefined",
234
target: string,
235
collection?: string,
236
path?: string,
237
+
cursor?: string,
238
+
dids?: string[]
239
}
240
) {
241
// : QueryOptions<
···
247
// Error
248
// >
249
return queryOptions({
250
+
queryKey: ["constellation", query?.method, query?.target, query?.collection, query?.path, query?.cursor, query?.dids] as const,
251
queryFn: async () => {
252
+
if (!query || query.method === "undefined") return undefined as undefined
253
const method = query.method
254
const target = query.target
255
const collection = query?.collection
256
const path = query?.path
257
const cursor = query.cursor
258
+
const dids = query?.dids
259
const res = await fetch(
260
+
`https://${query.constellation}${method}?target=${encodeURIComponent(target)}${collection ? `&collection=${encodeURIComponent(collection)}` : ""}${path ? `&path=${encodeURIComponent(path)}` : ""}${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}${dids ? dids.map((did) => `&did=${encodeURIComponent(did)}`).join("") : ""}`
261
);
262
if (!res.ok) throw new Error("Failed to fetch post");
263
try {
···
279
return undefined;
280
}
281
},
282
+
// enforce short lifespan
283
+
staleTime: /*0,//*/ 5 * 60 * 1000, // 5 minutes
284
+
gcTime: /*0//*/5 * 60 * 1000,
285
});
286
}
287
export function useQueryConstellation(query: {
···
290
collection: string;
291
path: string;
292
cursor?: string;
293
+
dids?: string[];
294
}): UseQueryResult<linksRecordsResponse, Error>;
295
export function useQueryConstellation(query: {
296
method: "/links/distinct-dids";
···
318
target: string;
319
}): UseQueryResult<linksAllResponse, Error>;
320
export function useQueryConstellation(): undefined;
321
+
export function useQueryConstellation(query: {
322
+
method: "undefined";
323
+
target: string;
324
+
}): undefined;
325
export function useQueryConstellation(query?: {
326
method:
327
| "/links"
328
| "/links/distinct-dids"
329
| "/links/count"
330
| "/links/count/distinct-dids"
331
+
| "/links/all"
332
+
| "undefined";
333
target: string;
334
collection?: string;
335
path?: string;
336
cursor?: string;
337
+
dids?: string[];
338
}):
339
| UseQueryResult<
340
| linksRecordsResponse
···
346
>
347
| undefined {
348
//if (!query) return;
349
+
const [constellationurl] = useAtom(constellationURLAtom)
350
return useQuery(
351
+
constructConstellationQuery(query && {constellation: constellationurl, ...query})
352
);
353
}
354
···
357
collection: string;
358
rkey: string;
359
};
360
+
export type linksRecordsResponse = {
361
total: string;
362
linking_records: linksRecord[];
363
cursor?: string;
···
370
type linksCountResponse = {
371
total: string;
372
};
373
+
export type linksAllResponse = {
374
links: Record<
375
string,
376
Record<
···
385
386
export function constructFeedSkeletonQuery(options?: {
387
feedUri: string;
388
+
agent?: ATPAPI.Agent;
389
isAuthed: boolean;
390
pdsUrl?: string;
391
feedServiceDid?: string;
···
425
426
export function useQueryFeedSkeleton(options?: {
427
feedUri: string;
428
+
agent?: ATPAPI.Agent;
429
isAuthed: boolean;
430
pdsUrl?: string;
431
feedServiceDid?: string;
···
433
return useQuery(constructFeedSkeletonQuery(options));
434
}
435
436
+
export function constructPreferencesQuery(agent?: ATPAPI.Agent | undefined, pdsUrl?: string | undefined) {
437
return queryOptions({
438
queryKey: ['preferences', agent?.did],
439
queryFn: async () => {
···
446
});
447
}
448
export function useQueryPreferences(options: {
449
+
agent?: ATPAPI.Agent | undefined, pdsUrl?: string | undefined
450
}) {
451
return useQuery(constructPreferencesQuery(options.agent, options.pdsUrl));
452
}
453
454
455
456
+
export function constructArbitraryQuery(uri?: string, slingshoturl?: string) {
457
return queryOptions({
458
+
queryKey: ["arbitrary", uri],
459
queryFn: async () => {
460
if (!uri) return undefined as undefined
461
const res = await fetch(
462
+
`https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
463
);
464
+
let data: any;
465
try {
466
+
data = await res.json();
467
+
} catch {
468
+
return undefined;
469
+
}
470
+
if (res.status === 400) return undefined;
471
+
if (data?.error === "InvalidRequest" && data.message?.includes("Could not find repo")) {
472
+
return undefined; // cache โnot foundโ
473
+
}
474
+
try {
475
+
if (!res.ok) throw new Error("Failed to fetch post");
476
+
return (data) as {
477
uri: string;
478
cid: string;
479
value: any;
···
482
return undefined;
483
}
484
},
485
+
retry: (failureCount, error) => {
486
+
// dont retry 400 errors
487
+
if ((error as any)?.message?.includes("400")) return false;
488
+
return failureCount < 2;
489
+
},
490
+
staleTime: /*0,//*/ 5 * 60 * 1000, // 5 minutes
491
+
gcTime: /*0//*/5 * 60 * 1000,
492
});
493
}
494
export function useQueryArbitrary(uri: string): UseQueryResult<
···
512
Error
513
>;
514
export function useQueryArbitrary(uri?: string) {
515
+
const [slingshoturl] = useAtom(slingshotURLAtom)
516
+
return useQuery(constructArbitraryQuery(uri, slingshoturl));
517
}
518
519
export function constructFallbackNothingQuery(){
···
569
570
export function constructInfiniteFeedSkeletonQuery(options: {
571
feedUri: string;
572
+
agent?: ATPAPI.Agent;
573
isAuthed: boolean;
574
pdsUrl?: string;
575
feedServiceDid?: string;
···
608
609
export function useInfiniteQueryFeedSkeleton(options: {
610
feedUri: string;
611
+
agent?: ATPAPI.Agent;
612
isAuthed: boolean;
613
pdsUrl?: string;
614
feedServiceDid?: string;
615
}) {
616
const { queryKey, queryFn } = constructInfiniteFeedSkeletonQuery(options);
617
618
+
return {...useInfiniteQuery({
619
queryKey,
620
queryFn,
621
initialPageParam: undefined as never,
···
623
staleTime: Infinity,
624
refetchOnWindowFocus: false,
625
enabled: !!options.feedUri && (options.isAuthed ? !!options.agent && !!options.pdsUrl && !!options.feedServiceDid : true),
626
+
}), queryKey: queryKey};
627
+
}
628
+
629
+
630
+
export function yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks(query?: {
631
+
constellation: string,
632
+
method: '/links'
633
+
target?: string
634
+
collection: string
635
+
path: string
636
+
}) {
637
+
console.log(
638
+
'yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks',
639
+
query,
640
+
)
641
+
642
+
return infiniteQueryOptions({
643
+
enabled: !!query?.target,
644
+
queryKey: [
645
+
'reddwarf_constellation',
646
+
query?.method,
647
+
query?.target,
648
+
query?.collection,
649
+
query?.path,
650
+
] as const,
651
+
652
+
queryFn: async ({pageParam}: {pageParam?: string}) => {
653
+
if (!query || !query?.target) return undefined
654
+
655
+
const method = query.method
656
+
const target = query.target
657
+
const collection = query.collection
658
+
const path = query.path
659
+
const cursor = pageParam
660
+
661
+
const res = await fetch(
662
+
`https://${query.constellation}${method}?target=${encodeURIComponent(target)}${
663
+
collection ? `&collection=${encodeURIComponent(collection)}` : ''
664
+
}${path ? `&path=${encodeURIComponent(path)}` : ''}${
665
+
cursor ? `&cursor=${encodeURIComponent(cursor)}` : ''
666
+
}`,
667
+
)
668
+
669
+
if (!res.ok) throw new Error('Failed to fetch')
670
+
671
+
return (await res.json()) as linksRecordsResponse
672
+
},
673
+
674
+
getNextPageParam: lastPage => {
675
+
return (lastPage as any)?.cursor ?? undefined
676
+
},
677
+
initialPageParam: undefined,
678
+
staleTime: 5 * 60 * 1000,
679
+
gcTime: 5 * 60 * 1000,
680
+
})
681
}
+1
-1
tsconfig.json
+1
-1
tsconfig.json
+49
-5
vite.config.ts
+49
-5
vite.config.ts
···
1
-
import { defineConfig } from "vite";
2
import viteReact from "@vitejs/plugin-react";
3
-
import tailwindcss from "@tailwindcss/vite";
4
5
-
import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
6
-
import { resolve } from "node:path";
7
8
// https://vitejs.dev/config/
9
export default defineConfig({
10
plugins: [
11
TanStackRouterVite({ autoCodeSplitting: true }),
12
-
viteReact(),
13
tailwindcss(),
14
],
15
// test: {
16
// globals: true,
···
21
"@": resolve(__dirname, "./src"),
22
"~": resolve(__dirname, "./src"),
23
},
24
},
25
});
···
1
+
import { resolve } from "node:path";
2
+
3
+
import tailwindcss from "@tailwindcss/vite";
4
+
import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
5
import viteReact from "@vitejs/plugin-react";
6
+
import AutoImport from 'unplugin-auto-import/vite'
7
+
import IconsResolver from 'unplugin-icons/resolver'
8
+
import Icons from 'unplugin-icons/vite'
9
+
import { defineConfig } from "vite";
10
+
11
+
import { generateMetadataPlugin } from "./oauthdev.mts";
12
+
13
+
const PROD_URL = "https://reddwarf.app"
14
+
const DEV_URL = "https://local3768forumtest.whey.party"
15
16
+
function shp(url: string): string {
17
+
return url.replace(/^https?:\/\//, '');
18
+
}
19
20
// https://vitejs.dev/config/
21
export default defineConfig({
22
plugins: [
23
+
generateMetadataPlugin({
24
+
prod: PROD_URL,
25
+
dev: DEV_URL,
26
+
}),
27
TanStackRouterVite({ autoCodeSplitting: true }),
28
+
viteReact({
29
+
babel: {
30
+
plugins: ['babel-plugin-react-compiler'],
31
+
},
32
+
}),
33
tailwindcss(),
34
+
AutoImport({
35
+
include: [
36
+
/\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
37
+
],
38
+
resolvers: [
39
+
IconsResolver({
40
+
prefix: 'Icon',
41
+
extension: 'jsx',
42
+
enabledCollections: ['mdi','material-symbols'],
43
+
}),
44
+
],
45
+
dts: 'src/auto-imports.d.ts',
46
+
}),
47
+
Icons({
48
+
//autoInstall: true,
49
+
compiler: 'jsx',
50
+
jsx: 'react'
51
+
}),
52
],
53
// test: {
54
// globals: true,
···
59
"@": resolve(__dirname, "./src"),
60
"~": resolve(__dirname, "./src"),
61
},
62
+
},
63
+
server: {
64
+
allowedHosts: [shp(PROD_URL),shp(DEV_URL)],
65
+
},
66
+
css: {
67
+
devSourcemap: true,
68
},
69
});