@tscircuit/fake-snippets 0.0.49 → 0.0.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lock +183 -16
- package/dist/bundle.js +49 -14
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1 -0
- package/dist/schema.d.ts +8 -0
- package/dist/schema.js +1 -0
- package/fake-snippets-api/lib/db/schema.ts +1 -0
- package/fake-snippets-api/routes/api/order_quotes/create.ts +13 -1
- package/fake-snippets-api/routes/api/packages/add_star.ts +4 -2
- package/fake-snippets-api/routes/api/packages/list.ts +11 -0
- package/fake-snippets-api/routes/api/snippets/list.ts +39 -17
- package/package.json +6 -3
- package/src/ContextProviders.tsx +56 -1
- package/src/components/Analytics.tsx +0 -7
- package/src/components/CodeEditor.tsx +46 -29
- package/src/components/SearchComponent.tsx +7 -0
- package/src/components/ViewPackagePage/components/important-files-view.tsx +4 -6
- package/src/components/ViewPackagePage/components/markdown-viewer.tsx +37 -0
- package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +1 -1
- package/src/components/ViewPackagePage/components/package-header.tsx +13 -21
- package/src/components/ViewPackagePage/components/repo-page-content.tsx +1 -15
- package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +1 -16
- package/src/components/package-port/CodeEditor.tsx +20 -6
- package/src/hooks/use-shiki-highlighter.ts +26 -0
- package/src/index.css +6 -0
- package/src/lib/posthog.ts +10 -0
- package/src/lib/types.ts +16 -0
- package/src/pages/user-profile.tsx +11 -1
- package/tailwind.config.js +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ declare const snippetSchema: z.ZodObject<{
|
|
|
16
16
|
manual_edits_json_content: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
17
17
|
created_at: z.ZodString;
|
|
18
18
|
updated_at: z.ZodString;
|
|
19
|
+
starred_at: z.ZodOptional<z.ZodString>;
|
|
19
20
|
snippet_type: z.ZodEnum<["board", "package", "model", "footprint"]>;
|
|
20
21
|
description: z.ZodOptional<z.ZodString>;
|
|
21
22
|
version: z.ZodDefault<z.ZodString>;
|
|
@@ -44,6 +45,7 @@ declare const snippetSchema: z.ZodObject<{
|
|
|
44
45
|
compiled_js?: string | null | undefined;
|
|
45
46
|
circuit_json?: Record<string, any>[] | null | undefined;
|
|
46
47
|
manual_edits_json_content?: string | null | undefined;
|
|
48
|
+
starred_at?: string | undefined;
|
|
47
49
|
description?: string | undefined;
|
|
48
50
|
tags?: string[] | undefined;
|
|
49
51
|
}, {
|
|
@@ -61,6 +63,7 @@ declare const snippetSchema: z.ZodObject<{
|
|
|
61
63
|
compiled_js?: string | null | undefined;
|
|
62
64
|
circuit_json?: Record<string, any>[] | null | undefined;
|
|
63
65
|
manual_edits_json_content?: string | null | undefined;
|
|
66
|
+
starred_at?: string | undefined;
|
|
64
67
|
description?: string | undefined;
|
|
65
68
|
version?: string | undefined;
|
|
66
69
|
star_count?: number | undefined;
|
|
@@ -676,6 +679,7 @@ declare const createDatabase: ({ seed }?: {
|
|
|
676
679
|
compiled_js?: string | null | undefined;
|
|
677
680
|
circuit_json?: Record<string, any>[] | null | undefined;
|
|
678
681
|
manual_edits_json_content?: string | null | undefined;
|
|
682
|
+
starred_at?: string | undefined;
|
|
679
683
|
description?: string | undefined;
|
|
680
684
|
tags?: string[] | undefined;
|
|
681
685
|
}[];
|
|
@@ -960,6 +964,7 @@ declare const createDatabase: ({ seed }?: {
|
|
|
960
964
|
compiled_js?: string | null | undefined;
|
|
961
965
|
circuit_json?: Record<string, any>[] | null | undefined;
|
|
962
966
|
manual_edits_json_content?: string | null | undefined;
|
|
967
|
+
starred_at?: string | undefined;
|
|
963
968
|
description?: string | undefined;
|
|
964
969
|
tags?: string[] | undefined;
|
|
965
970
|
}[];
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ var snippetSchema = z.object({
|
|
|
26
26
|
manual_edits_json_content: z.string().optional().nullable(),
|
|
27
27
|
created_at: z.string(),
|
|
28
28
|
updated_at: z.string(),
|
|
29
|
+
starred_at: z.string().optional(),
|
|
29
30
|
snippet_type: z.enum(["board", "package", "model", "footprint"]),
|
|
30
31
|
description: z.string().optional(),
|
|
31
32
|
version: z.string().default("0.0.1"),
|
package/dist/schema.d.ts
CHANGED
|
@@ -50,6 +50,7 @@ declare const snippetSchema: z.ZodObject<{
|
|
|
50
50
|
manual_edits_json_content: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
51
51
|
created_at: z.ZodString;
|
|
52
52
|
updated_at: z.ZodString;
|
|
53
|
+
starred_at: z.ZodOptional<z.ZodString>;
|
|
53
54
|
snippet_type: z.ZodEnum<["board", "package", "model", "footprint"]>;
|
|
54
55
|
description: z.ZodOptional<z.ZodString>;
|
|
55
56
|
version: z.ZodDefault<z.ZodString>;
|
|
@@ -78,6 +79,7 @@ declare const snippetSchema: z.ZodObject<{
|
|
|
78
79
|
compiled_js?: string | null | undefined;
|
|
79
80
|
circuit_json?: Record<string, any>[] | null | undefined;
|
|
80
81
|
manual_edits_json_content?: string | null | undefined;
|
|
82
|
+
starred_at?: string | undefined;
|
|
81
83
|
description?: string | undefined;
|
|
82
84
|
tags?: string[] | undefined;
|
|
83
85
|
}, {
|
|
@@ -95,6 +97,7 @@ declare const snippetSchema: z.ZodObject<{
|
|
|
95
97
|
compiled_js?: string | null | undefined;
|
|
96
98
|
circuit_json?: Record<string, any>[] | null | undefined;
|
|
97
99
|
manual_edits_json_content?: string | null | undefined;
|
|
100
|
+
starred_at?: string | undefined;
|
|
98
101
|
description?: string | undefined;
|
|
99
102
|
version?: string | undefined;
|
|
100
103
|
star_count?: number | undefined;
|
|
@@ -792,6 +795,7 @@ declare const databaseSchema: z.ZodObject<{
|
|
|
792
795
|
manual_edits_json_content: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
793
796
|
created_at: z.ZodString;
|
|
794
797
|
updated_at: z.ZodString;
|
|
798
|
+
starred_at: z.ZodOptional<z.ZodString>;
|
|
795
799
|
snippet_type: z.ZodEnum<["board", "package", "model", "footprint"]>;
|
|
796
800
|
description: z.ZodOptional<z.ZodString>;
|
|
797
801
|
version: z.ZodDefault<z.ZodString>;
|
|
@@ -820,6 +824,7 @@ declare const databaseSchema: z.ZodObject<{
|
|
|
820
824
|
compiled_js?: string | null | undefined;
|
|
821
825
|
circuit_json?: Record<string, any>[] | null | undefined;
|
|
822
826
|
manual_edits_json_content?: string | null | undefined;
|
|
827
|
+
starred_at?: string | undefined;
|
|
823
828
|
description?: string | undefined;
|
|
824
829
|
tags?: string[] | undefined;
|
|
825
830
|
}, {
|
|
@@ -837,6 +842,7 @@ declare const databaseSchema: z.ZodObject<{
|
|
|
837
842
|
compiled_js?: string | null | undefined;
|
|
838
843
|
circuit_json?: Record<string, any>[] | null | undefined;
|
|
839
844
|
manual_edits_json_content?: string | null | undefined;
|
|
845
|
+
starred_at?: string | undefined;
|
|
840
846
|
description?: string | undefined;
|
|
841
847
|
version?: string | undefined;
|
|
842
848
|
star_count?: number | undefined;
|
|
@@ -1455,6 +1461,7 @@ declare const databaseSchema: z.ZodObject<{
|
|
|
1455
1461
|
compiled_js?: string | null | undefined;
|
|
1456
1462
|
circuit_json?: Record<string, any>[] | null | undefined;
|
|
1457
1463
|
manual_edits_json_content?: string | null | undefined;
|
|
1464
|
+
starred_at?: string | undefined;
|
|
1458
1465
|
description?: string | undefined;
|
|
1459
1466
|
tags?: string[] | undefined;
|
|
1460
1467
|
}[];
|
|
@@ -1661,6 +1668,7 @@ declare const databaseSchema: z.ZodObject<{
|
|
|
1661
1668
|
compiled_js?: string | null | undefined;
|
|
1662
1669
|
circuit_json?: Record<string, any>[] | null | undefined;
|
|
1663
1670
|
manual_edits_json_content?: string | null | undefined;
|
|
1671
|
+
starred_at?: string | undefined;
|
|
1664
1672
|
description?: string | undefined;
|
|
1665
1673
|
version?: string | undefined;
|
|
1666
1674
|
star_count?: number | undefined;
|
package/dist/schema.js
CHANGED
|
@@ -21,6 +21,7 @@ var snippetSchema = z.object({
|
|
|
21
21
|
manual_edits_json_content: z.string().optional().nullable(),
|
|
22
22
|
created_at: z.string(),
|
|
23
23
|
updated_at: z.string(),
|
|
24
|
+
starred_at: z.string().optional(),
|
|
24
25
|
snippet_type: z.enum(["board", "package", "model", "footprint"]),
|
|
25
26
|
description: z.string().optional(),
|
|
26
27
|
version: z.string().default("0.0.1"),
|
|
@@ -25,6 +25,7 @@ export const snippetSchema = z.object({
|
|
|
25
25
|
manual_edits_json_content: z.string().optional().nullable(),
|
|
26
26
|
created_at: z.string(),
|
|
27
27
|
updated_at: z.string(),
|
|
28
|
+
starred_at: z.string().optional(),
|
|
28
29
|
snippet_type: z.enum(["board", "package", "model", "footprint"]),
|
|
29
30
|
description: z.string().optional(),
|
|
30
31
|
version: z.string().default("0.0.1"),
|
|
@@ -9,11 +9,23 @@ export default withRouteSpec({
|
|
|
9
9
|
vendor_name: z.string(),
|
|
10
10
|
}),
|
|
11
11
|
jsonResponse: z.object({
|
|
12
|
-
order_quote_id: z.string(),
|
|
12
|
+
order_quote_id: z.string().optional(),
|
|
13
|
+
error: z.string().optional(),
|
|
13
14
|
}),
|
|
14
15
|
})(async (req, ctx) => {
|
|
15
16
|
const { package_release_id, vendor_name } = req.jsonBody
|
|
16
17
|
|
|
18
|
+
// check package release exists
|
|
19
|
+
const packageRelease = ctx.db.getPackageReleaseById(package_release_id)
|
|
20
|
+
if (!packageRelease) {
|
|
21
|
+
return ctx.json(
|
|
22
|
+
{
|
|
23
|
+
error: "Package release not found",
|
|
24
|
+
},
|
|
25
|
+
{ status: 404 },
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
|
|
17
29
|
const orderQuoteId = ctx.db.addOrderQuote({
|
|
18
30
|
account_id: ctx.auth.account_id,
|
|
19
31
|
package_release_id,
|
|
@@ -66,12 +66,14 @@ export default withRouteSpec({
|
|
|
66
66
|
existing.updated_at = new Date().toISOString()
|
|
67
67
|
} else {
|
|
68
68
|
// Add star by creating a new account_package record
|
|
69
|
+
const newTimestamp = new Date().toISOString()
|
|
69
70
|
const newAccountPackage = {
|
|
71
|
+
account_package_id: `ap_${Date.now()}`,
|
|
70
72
|
account_id: ctx.auth.account_id,
|
|
71
73
|
package_id: packageId,
|
|
72
74
|
is_starred: true,
|
|
73
|
-
created_at:
|
|
74
|
-
updated_at:
|
|
75
|
+
created_at: newTimestamp,
|
|
76
|
+
updated_at: newTimestamp,
|
|
75
77
|
}
|
|
76
78
|
ctx.db.addAccountPackage(newAccountPackage)
|
|
77
79
|
}
|
|
@@ -49,11 +49,22 @@ export default withRouteSpec({
|
|
|
49
49
|
packages = packages.filter((p) => p.owner_org_id === auth.personal_org_id)
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
// Get star timestamps for authenticated user
|
|
53
|
+
const starTimestamps = new Map<string, string>()
|
|
54
|
+
if (auth) {
|
|
55
|
+
ctx.db.accountPackages
|
|
56
|
+
.filter((ap) => ap.account_id === auth.account_id && ap.is_starred)
|
|
57
|
+
.forEach((ap) => {
|
|
58
|
+
starTimestamps.set(ap.package_id, ap.updated_at)
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
52
62
|
return ctx.json({
|
|
53
63
|
ok: true,
|
|
54
64
|
packages: packages.map((p) => ({
|
|
55
65
|
...p,
|
|
56
66
|
latest_package_release_id: p.latest_package_release_id || null,
|
|
67
|
+
starred_at: starTimestamps.get(p.package_id) || null,
|
|
57
68
|
})),
|
|
58
69
|
})
|
|
59
70
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { withRouteSpec } from "fake-snippets-api/lib/middleware/with-winter-spec"
|
|
2
2
|
import { z } from "zod"
|
|
3
|
-
import { snippetSchema } from "fake-snippets-api/lib/db/schema"
|
|
3
|
+
import { snippetSchema, type Account } from "fake-snippets-api/lib/db/schema"
|
|
4
4
|
|
|
5
5
|
export default withRouteSpec({
|
|
6
6
|
methods: ["GET", "POST"],
|
|
@@ -17,7 +17,7 @@ export default withRouteSpec({
|
|
|
17
17
|
}),
|
|
18
18
|
})(async (req, ctx) => {
|
|
19
19
|
const { owner_name, unscoped_name, starred_by } = req.commonParams
|
|
20
|
-
|
|
20
|
+
let starredByAccount: Account | null = null
|
|
21
21
|
// Get all packages that are snippets
|
|
22
22
|
let packages = ctx.db.packages.filter((pkg) => pkg.is_snippet === true)
|
|
23
23
|
|
|
@@ -38,25 +38,44 @@ export default withRouteSpec({
|
|
|
38
38
|
|
|
39
39
|
// Filter by starred_by if provided
|
|
40
40
|
if (starred_by) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
starredByAccount =
|
|
42
|
+
ctx.db.accounts.find(
|
|
43
|
+
(acc) => acc.github_username.toLowerCase() === starred_by.toLowerCase(),
|
|
44
|
+
) || null
|
|
45
|
+
|
|
45
46
|
if (starredByAccount) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
ctx.db.hasStarred(starredByAccount.account_id, pkg.package_id),
|
|
47
|
+
const accountPackages = ctx.db.accountPackages.filter(
|
|
48
|
+
(ap) => ap.account_id === starredByAccount?.account_id && ap.is_starred,
|
|
49
49
|
)
|
|
50
|
+
|
|
51
|
+
const starTimestamps = new Map(
|
|
52
|
+
accountPackages.map((ap) => [ap.package_id, ap.updated_at]),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
// Filter packages to only include starred ones
|
|
56
|
+
packages = packages.filter((pkg) => starTimestamps.has(pkg.package_id))
|
|
50
57
|
} else {
|
|
51
|
-
// If we can't find the account, return no snippets
|
|
52
58
|
packages = []
|
|
53
59
|
}
|
|
54
60
|
}
|
|
55
61
|
|
|
62
|
+
// Convert packages to snippets
|
|
56
63
|
const snippets = packages.map((pkg) => {
|
|
57
64
|
const packageRelease = ctx.db.getPackageReleaseById(
|
|
58
65
|
pkg.latest_package_release_id || "",
|
|
59
66
|
)
|
|
67
|
+
|
|
68
|
+
let starTimestamp
|
|
69
|
+
if (starred_by && starredByAccount) {
|
|
70
|
+
const accountPackage = ctx.db.accountPackages.find(
|
|
71
|
+
(ap) =>
|
|
72
|
+
ap.account_id === starredByAccount.account_id &&
|
|
73
|
+
ap.package_id === pkg.package_id &&
|
|
74
|
+
ap.is_starred,
|
|
75
|
+
)
|
|
76
|
+
starTimestamp = accountPackage?.updated_at
|
|
77
|
+
}
|
|
78
|
+
|
|
60
79
|
if (!packageRelease) {
|
|
61
80
|
return {
|
|
62
81
|
snippet_id: pkg.package_id,
|
|
@@ -71,6 +90,7 @@ export default withRouteSpec({
|
|
|
71
90
|
compiled_js: "",
|
|
72
91
|
created_at: pkg.created_at,
|
|
73
92
|
updated_at: pkg.updated_at,
|
|
93
|
+
starred_at: starTimestamp, // Add star timestamp
|
|
74
94
|
star_count: ctx.db.getStarCount(pkg.package_id),
|
|
75
95
|
is_starred: ctx.auth
|
|
76
96
|
? ctx.db.hasStarred(ctx.auth.account_id, pkg.package_id)
|
|
@@ -81,6 +101,7 @@ export default withRouteSpec({
|
|
|
81
101
|
is_unlisted: pkg.is_unlisted || false,
|
|
82
102
|
}
|
|
83
103
|
}
|
|
104
|
+
|
|
84
105
|
const packageFiles = ctx.db.getPackageFilesByReleaseId(
|
|
85
106
|
packageRelease.package_release_id,
|
|
86
107
|
)
|
|
@@ -88,12 +109,8 @@ export default withRouteSpec({
|
|
|
88
109
|
(file: { file_path: string }) =>
|
|
89
110
|
file.file_path === "index.ts" || file.file_path === "index.tsx",
|
|
90
111
|
)
|
|
91
|
-
const starCount = ctx.db.getStarCount(pkg.package_id)
|
|
92
|
-
const isStarred = ctx.auth
|
|
93
|
-
? ctx.db.hasStarred(ctx.auth.account_id, pkg.package_id)
|
|
94
|
-
: false
|
|
95
112
|
|
|
96
|
-
|
|
113
|
+
const snippet = {
|
|
97
114
|
snippet_id: pkg.package_id,
|
|
98
115
|
package_release_id: pkg.latest_package_release_id || "",
|
|
99
116
|
unscoped_name: pkg.unscoped_name,
|
|
@@ -113,13 +130,18 @@ export default withRouteSpec({
|
|
|
113
130
|
)?.content_text || "",
|
|
114
131
|
created_at: pkg.created_at,
|
|
115
132
|
updated_at: pkg.updated_at,
|
|
116
|
-
|
|
117
|
-
|
|
133
|
+
starred_at: starTimestamp, // Add star timestamp
|
|
134
|
+
star_count: ctx.db.getStarCount(pkg.package_id),
|
|
135
|
+
is_starred: ctx.auth
|
|
136
|
+
? ctx.db.hasStarred(ctx.auth.account_id, pkg.package_id)
|
|
137
|
+
: false,
|
|
118
138
|
version: pkg.latest_version || "0.0.1",
|
|
119
139
|
is_private: pkg.is_private || false,
|
|
120
140
|
is_public: pkg.is_public || true,
|
|
121
141
|
is_unlisted: pkg.is_unlisted || false,
|
|
122
142
|
}
|
|
143
|
+
|
|
144
|
+
return snippet
|
|
123
145
|
})
|
|
124
146
|
|
|
125
147
|
return ctx.json({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/fake-snippets",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.51",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"playwright": "bunx playwright test",
|
|
19
19
|
"playwright:update": "bunx playwright test --update-snapshots",
|
|
20
20
|
"start:playwright-server": "bun run build:fake-api && vite --port 5177",
|
|
21
|
-
"dev": "bun run build:fake-api &&
|
|
21
|
+
"dev": "bun run build:fake-api && AUTOLOAD_PACKAGES=true vite",
|
|
22
22
|
"dev:registry": "SNIPPETS_API_URL=http://localhost:3100 vite",
|
|
23
23
|
"build": "bun run generate-images && bun run generate-sitemap && bun run build:fake-api && tsc -b && vite build",
|
|
24
24
|
"preview": "vite preview",
|
|
@@ -120,9 +120,11 @@
|
|
|
120
120
|
"react-hook-form": "^7.53.0",
|
|
121
121
|
"react-hot-toast": "^2.5.2",
|
|
122
122
|
"react-intersection-observer": "^9.14.1",
|
|
123
|
+
"react-markdown": "^10.1.0",
|
|
123
124
|
"react-query": "^3.39.3",
|
|
124
125
|
"react-resizable-panels": "^2.1.3",
|
|
125
126
|
"recharts": "^2.12.7",
|
|
127
|
+
"remark-gfm": "^4.0.1",
|
|
126
128
|
"rollup-plugin-visualizer": "^5.12.0",
|
|
127
129
|
"sitemap": "^8.0.0",
|
|
128
130
|
"sonner": "^1.5.0",
|
|
@@ -140,9 +142,10 @@
|
|
|
140
142
|
"@babel/standalone": "^7.26.2",
|
|
141
143
|
"@biomejs/biome": "^1.9.2",
|
|
142
144
|
"@playwright/test": "^1.48.0",
|
|
145
|
+
"@tailwindcss/typography": "^0.5.16",
|
|
143
146
|
"@tscircuit/core": "^0.0.370",
|
|
144
147
|
"@tscircuit/prompt-benchmarks": "^0.0.28",
|
|
145
|
-
"@tscircuit/runframe": "^0.0.
|
|
148
|
+
"@tscircuit/runframe": "^0.0.370",
|
|
146
149
|
"@types/babel__standalone": "^7.1.7",
|
|
147
150
|
"@types/bun": "^1.1.10",
|
|
148
151
|
"@types/country-list": "^2.1.4",
|
package/src/ContextProviders.tsx
CHANGED
|
@@ -1,12 +1,67 @@
|
|
|
1
1
|
import { QueryClient, QueryClientProvider } from "react-query"
|
|
2
2
|
import { HelmetProvider } from "react-helmet-async"
|
|
3
|
+
import { useEffect } from "react"
|
|
4
|
+
import { useGlobalStore } from "./hooks/use-global-store"
|
|
5
|
+
import { posthog } from "./lib/posthog"
|
|
6
|
+
|
|
7
|
+
const staffGithubUsernames = [
|
|
8
|
+
"imrishabh18",
|
|
9
|
+
"seveibar",
|
|
10
|
+
"testuser",
|
|
11
|
+
...(import.meta.env.VITE_STAFF_GITHUB_USERNAMES?.split(",") || []),
|
|
12
|
+
]
|
|
3
13
|
|
|
4
14
|
const queryClient = new QueryClient()
|
|
5
15
|
|
|
16
|
+
const isInternalGithubUser = (githubUsername?: string | null) => {
|
|
17
|
+
if (!githubUsername) return false
|
|
18
|
+
return staffGithubUsernames.some(
|
|
19
|
+
(internalGithubUsername: string) =>
|
|
20
|
+
internalGithubUsername.toLowerCase() === githubUsername.toLowerCase(),
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function PostHogIdentifier() {
|
|
25
|
+
const session = useGlobalStore((s) => s.session)
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!posthog.__loaded) {
|
|
29
|
+
const checkInterval = setInterval(() => {
|
|
30
|
+
if (posthog.__loaded) {
|
|
31
|
+
clearInterval(checkInterval)
|
|
32
|
+
identifyUser()
|
|
33
|
+
}
|
|
34
|
+
}, 100)
|
|
35
|
+
return () => clearInterval(checkInterval)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const identifyUser = async () => {
|
|
39
|
+
try {
|
|
40
|
+
const githubUsername = session?.github_username
|
|
41
|
+
|
|
42
|
+
if (isInternalGithubUser(githubUsername)) {
|
|
43
|
+
posthog.identify(session?.github_username, {
|
|
44
|
+
is_tscircuit_staff: true,
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
// Error handling silently fails
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
identifyUser()
|
|
53
|
+
}, [session])
|
|
54
|
+
|
|
55
|
+
return null
|
|
56
|
+
}
|
|
57
|
+
|
|
6
58
|
export const ContextProviders = ({ children }: any) => {
|
|
7
59
|
return (
|
|
8
60
|
<QueryClientProvider client={queryClient}>
|
|
9
|
-
<HelmetProvider>
|
|
61
|
+
<HelmetProvider>
|
|
62
|
+
<PostHogIdentifier />
|
|
63
|
+
{children}
|
|
64
|
+
</HelmetProvider>
|
|
10
65
|
</QueryClientProvider>
|
|
11
66
|
)
|
|
12
67
|
}
|
|
@@ -1,11 +1,4 @@
|
|
|
1
1
|
import { Analytics as VercelAnalytics } from "@vercel/analytics/react"
|
|
2
|
-
import posthog from "posthog-js"
|
|
3
|
-
import CookieConsent from "react-cookie-consent"
|
|
4
|
-
|
|
5
|
-
posthog.init("phc_htd8AQjSfVEsFCLQMAiUooG4Q0DKBCjqYuQglc9V3Wo", {
|
|
6
|
-
api_host: "https://postpig.tscircuit.com",
|
|
7
|
-
person_profiles: "always",
|
|
8
|
-
})
|
|
9
2
|
|
|
10
3
|
export const Analytics = () => {
|
|
11
4
|
return (
|
|
@@ -33,6 +33,9 @@ import React from "@types/react/jsx-runtime"
|
|
|
33
33
|
import { Circuit, createUseComponent } from "@tscircuit/core"
|
|
34
34
|
import type { CommonLayoutProps } from "@tscircuit/props"
|
|
35
35
|
`
|
|
36
|
+
import { getSingletonHighlighter, Highlighter } from "shiki"
|
|
37
|
+
import { useShikiHighlighter } from "@/hooks/use-shiki-highlighter"
|
|
38
|
+
|
|
36
39
|
export const CodeEditor = ({
|
|
37
40
|
onCodeChange,
|
|
38
41
|
onDtsChange,
|
|
@@ -58,6 +61,8 @@ export const CodeEditor = ({
|
|
|
58
61
|
const apiUrl = useSnippetsBaseApiUrl()
|
|
59
62
|
const codeCompletionApi = useCodeCompletionApi()
|
|
60
63
|
|
|
64
|
+
const { highlighter, isLoading } = useShikiHighlighter()
|
|
65
|
+
|
|
61
66
|
const [cursorPosition, setCursorPosition] = useState<number | null>(null)
|
|
62
67
|
const [code, setCode] = useState(initialCode)
|
|
63
68
|
|
|
@@ -256,32 +261,33 @@ export const CodeEditor = ({
|
|
|
256
261
|
tsSync(),
|
|
257
262
|
tsLinter(),
|
|
258
263
|
autocompletion({ override: [tsAutocomplete()] }),
|
|
259
|
-
tsHover(),
|
|
260
264
|
hoverTooltip((view, pos) => {
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
265
|
+
const facet = view.state.facet(tsFacet)
|
|
266
|
+
if (!facet) return null
|
|
267
|
+
|
|
268
|
+
const { env, path } = facet
|
|
269
|
+
const info = env.languageService.getQuickInfoAtPosition(path, pos)
|
|
270
|
+
if (!info) return null
|
|
271
|
+
|
|
272
|
+
const start = info.textSpan.start
|
|
273
|
+
const end = start + info.textSpan.length
|
|
274
|
+
const content = ts.displayPartsToString(info.displayParts || [])
|
|
275
|
+
|
|
276
|
+
const dom = document.createElement("div")
|
|
277
|
+
if (highlighter) {
|
|
278
|
+
dom.innerHTML = highlighter.codeToHtml(content, {
|
|
279
|
+
lang: "typescript",
|
|
280
|
+
themes: {
|
|
281
|
+
light: "github-light",
|
|
282
|
+
dark: "github-dark",
|
|
283
|
+
},
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
return {
|
|
287
|
+
pos: start,
|
|
288
|
+
end,
|
|
289
|
+
above: true,
|
|
290
|
+
create: () => ({ dom }),
|
|
285
291
|
}
|
|
286
292
|
}
|
|
287
293
|
return null
|
|
@@ -321,10 +327,21 @@ export const CodeEditor = ({
|
|
|
321
327
|
},
|
|
322
328
|
}),
|
|
323
329
|
EditorView.theme({
|
|
324
|
-
".
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
330
|
+
".shiki": {
|
|
331
|
+
maxWidth: "600px",
|
|
332
|
+
padding: "12px",
|
|
333
|
+
maxHeight: "400px",
|
|
334
|
+
borderRadius: "0.5rem",
|
|
335
|
+
backgroundColor: "#fff",
|
|
336
|
+
color: "#0f172a",
|
|
337
|
+
border: "1px solid #e2e8f0",
|
|
338
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.08)",
|
|
339
|
+
fontSize: "14px",
|
|
340
|
+
fontFamily: "monospace",
|
|
341
|
+
whiteSpace: "pre-wrap",
|
|
342
|
+
lineHeight: "1.6",
|
|
343
|
+
overflow: "auto",
|
|
344
|
+
zIndex: "9999",
|
|
328
345
|
},
|
|
329
346
|
}),
|
|
330
347
|
EditorView.decorations.of((view) => {
|
|
@@ -48,6 +48,7 @@ const SearchComponent: React.FC<SearchComponentProps> = ({
|
|
|
48
48
|
const [showResults, setShowResults] = useState(false)
|
|
49
49
|
const axios = useAxios()
|
|
50
50
|
const resultsRef = useRef<HTMLDivElement>(null)
|
|
51
|
+
const inputRef = useRef<HTMLInputElement>(null)
|
|
51
52
|
const [location] = useLocation()
|
|
52
53
|
const { snippetsBaseApiUrl } = useSnippetsBaseApiUrl()
|
|
53
54
|
|
|
@@ -71,6 +72,11 @@ const SearchComponent: React.FC<SearchComponentProps> = ({
|
|
|
71
72
|
setShowResults(!!searchQuery)
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
// Focus input on mount
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
inputRef.current?.focus()
|
|
78
|
+
}, [])
|
|
79
|
+
|
|
74
80
|
useEffect(() => {
|
|
75
81
|
const handleClickOutside = (event: MouseEvent) => {
|
|
76
82
|
if (
|
|
@@ -93,6 +99,7 @@ const SearchComponent: React.FC<SearchComponentProps> = ({
|
|
|
93
99
|
return (
|
|
94
100
|
<form onSubmit={handleSearch} className="relative">
|
|
95
101
|
<Input
|
|
102
|
+
ref={inputRef}
|
|
96
103
|
type="search"
|
|
97
104
|
placeholder="Search"
|
|
98
105
|
className="pl-4 focus:border-blue-500 placeholder-gray-400 text-sm"
|
|
@@ -6,6 +6,7 @@ import { Skeleton } from "@/components/ui/skeleton"
|
|
|
6
6
|
import { usePackageFile, usePackageFileByPath } from "@/hooks/use-package-files"
|
|
7
7
|
import { ShikiCodeViewer } from "./ShikiCodeViewer"
|
|
8
8
|
import { SparklesIcon } from "lucide-react"
|
|
9
|
+
import MarkdownViewer from "./markdown-viewer"
|
|
9
10
|
|
|
10
11
|
interface PackageFile {
|
|
11
12
|
package_file_id: string
|
|
@@ -86,13 +87,13 @@ export default function ImportantFilesView({
|
|
|
86
87
|
{aiDescription && (
|
|
87
88
|
<div className="mb-6">
|
|
88
89
|
<h3 className="font-semibold text-lg mb-2">Description</h3>
|
|
89
|
-
<
|
|
90
|
+
<MarkdownViewer markdownContent={aiDescription} />
|
|
90
91
|
</div>
|
|
91
92
|
)}
|
|
92
93
|
{aiUsageInstructions && (
|
|
93
94
|
<div>
|
|
94
95
|
<h3 className="font-semibold text-lg mb-2">Instructions</h3>
|
|
95
|
-
<
|
|
96
|
+
<MarkdownViewer markdownContent={aiUsageInstructions} />
|
|
96
97
|
</div>
|
|
97
98
|
)}
|
|
98
99
|
</div>
|
|
@@ -213,10 +214,7 @@ export default function ImportantFilesView({
|
|
|
213
214
|
{activeTab === "ai" ? (
|
|
214
215
|
renderAiContent()
|
|
215
216
|
) : activeFilePath && activeFilePath.endsWith(".md") ? (
|
|
216
|
-
<
|
|
217
|
-
{/* In a real app, you'd use a markdown renderer here */}
|
|
218
|
-
<pre className="whitespace-pre-wrap">{activeFileContent}</pre>
|
|
219
|
-
</div>
|
|
217
|
+
<MarkdownViewer markdownContent={activeFileContent} />
|
|
220
218
|
) : activeFilePath &&
|
|
221
219
|
(activeFilePath.endsWith(".js") ||
|
|
222
220
|
activeFilePath.endsWith(".jsx") ||
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Markdown from "react-markdown"
|
|
2
|
+
import remarkGfm from "remark-gfm"
|
|
3
|
+
|
|
4
|
+
export default function MarkdownViewer({
|
|
5
|
+
markdownContent,
|
|
6
|
+
}: {
|
|
7
|
+
markdownContent: string
|
|
8
|
+
}) {
|
|
9
|
+
return (
|
|
10
|
+
<div className="prose dark:prose-invert prose-pre:bg-gray-100 dark:prose-pre:bg-gray-800 prose-code:font-mono markdown-content">
|
|
11
|
+
<Markdown
|
|
12
|
+
remarkPlugins={[remarkGfm]}
|
|
13
|
+
components={{
|
|
14
|
+
code({ node, className, children, ...props }) {
|
|
15
|
+
const isCodeBlock =
|
|
16
|
+
className?.includes("language-") || /\n/.test(String(children))
|
|
17
|
+
|
|
18
|
+
// Don't use code tags cause of it's backticks not being removed
|
|
19
|
+
return isCodeBlock ? (
|
|
20
|
+
<div className="bg-gray-100 dark:bg-gray-800 rounded overflow-auto w-full">
|
|
21
|
+
<span className="text-gray-800 dark:text-gray-200 font-mono whitespace-pre">
|
|
22
|
+
{children}
|
|
23
|
+
</span>
|
|
24
|
+
</div>
|
|
25
|
+
) : (
|
|
26
|
+
<span className="bg-gray-100 dark:bg-gray-800 text-gray-800 font-semibold font-mono dark:text-gray-200 px-1 py-0.5 rounded">
|
|
27
|
+
{children}
|
|
28
|
+
</span>
|
|
29
|
+
)
|
|
30
|
+
},
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
{markdownContent}
|
|
34
|
+
</Markdown>
|
|
35
|
+
</div>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
@@ -8,9 +8,9 @@ import { Button } from "@/components/ui/button"
|
|
|
8
8
|
import { useEditPackageDetailsDialog } from "@/components/dialogs/edit-package-details-dialog"
|
|
9
9
|
import { useState, useEffect, useMemo } from "react"
|
|
10
10
|
import { useCurrentPackageInfo } from "@/hooks/use-current-package-info"
|
|
11
|
-
import { PackageInfo } from "./sidebar-about-section"
|
|
12
11
|
import { usePackageFile } from "@/hooks/use-package-files"
|
|
13
12
|
import { getLicenseFromLicenseContent } from "@/lib/getLicenseFromLicenseContent"
|
|
13
|
+
import { PackageInfo } from "@/lib/types"
|
|
14
14
|
|
|
15
15
|
interface MobileSidebarProps {
|
|
16
16
|
isLoading?: boolean
|