@tscircuit/fake-snippets 0.0.111 → 0.0.113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/bun-tests/fake-snippets-api/routes/orgs/get.test.ts +2 -1
  2. package/bun-tests/fake-snippets-api/routes/orgs/list_members.test.ts +1 -1
  3. package/bun-tests/fake-snippets-api/routes/packages/list_latest.test.ts +4 -4
  4. package/bun.lock +9 -9
  5. package/dist/bundle.js +22 -6
  6. package/dist/index.js +3 -0
  7. package/dist/schema.d.ts +3 -0
  8. package/dist/schema.js +1 -0
  9. package/fake-snippets-api/lib/db/schema.ts +1 -0
  10. package/fake-snippets-api/lib/db/seed.ts +2 -0
  11. package/fake-snippets-api/lib/public-mapping/public-map-org.ts +1 -0
  12. package/fake-snippets-api/routes/api/orgs/list_members.ts +15 -5
  13. package/package.json +4 -4
  14. package/src/components/CmdKMenu.tsx +1 -1
  15. package/src/components/GithubAvatarWithFallback.tsx +35 -0
  16. package/src/components/HeaderLogin.tsx +1 -1
  17. package/src/components/PackageCard.tsx +2 -5
  18. package/src/components/PackagesList.tsx +2 -2
  19. package/src/components/ProfileRouter.tsx +4 -6
  20. package/src/components/TrendingPackagesCarousel.tsx +2 -2
  21. package/src/components/UserCard.tsx +1 -1
  22. package/src/components/ViewPackagePage/components/build-status.tsx +2 -2
  23. package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +2 -2
  24. package/src/components/organization/OrganizationCard.tsx +11 -15
  25. package/src/components/organization/OrganizationHeader.tsx +15 -32
  26. package/src/components/organization/OrganizationMembers.tsx +8 -9
  27. package/src/components/preview/ConnectedPackagesList.tsx +1 -1
  28. package/src/components/preview/PackageReleasesDashboard.tsx +3 -3
  29. package/src/hooks/use-list-org-members.ts +5 -1
  30. package/src/hooks/use-org-by-github-handle.ts +0 -2
  31. package/src/pages/editor.tsx +1 -3
  32. package/src/pages/release-detail.tsx +25 -23
  33. package/src/pages/user-profile.tsx +2 -2
package/dist/index.js CHANGED
@@ -361,6 +361,7 @@ var publicOrgSchema = z.object({
361
361
  is_personal_org: z.boolean(),
362
362
  display_name: z.string().optional(),
363
363
  package_count: z.number(),
364
+ github_handle: z.string().optional(),
364
365
  created_at: z.string(),
365
366
  user_permissions: z.object({
366
367
  can_manage_org: z.boolean().optional(),
@@ -2278,6 +2279,7 @@ export const SquareWaveModule = () => (
2278
2279
  });
2279
2280
  const testOrg = db.addOrganization({
2280
2281
  name: "test-organization",
2282
+ github_handle: "tscircuit",
2281
2283
  owner_account_id: account_id
2282
2284
  });
2283
2285
  db.addOrganizationAccount({
@@ -2365,6 +2367,7 @@ exports.TestComponent = TestComponent;
2365
2367
  db.addOrganization({
2366
2368
  name: "testuser",
2367
2369
  owner_account_id: account_id,
2370
+ github_handle: "tscircuit",
2368
2371
  is_personal_org: true
2369
2372
  });
2370
2373
  };
package/dist/schema.d.ts CHANGED
@@ -1173,6 +1173,7 @@ declare const publicOrgSchema: z.ZodObject<{
1173
1173
  is_personal_org: z.ZodBoolean;
1174
1174
  display_name: z.ZodOptional<z.ZodString>;
1175
1175
  package_count: z.ZodNumber;
1176
+ github_handle: z.ZodOptional<z.ZodString>;
1176
1177
  created_at: z.ZodString;
1177
1178
  user_permissions: z.ZodOptional<z.ZodObject<{
1178
1179
  can_manage_org: z.ZodOptional<z.ZodBoolean>;
@@ -1192,6 +1193,7 @@ declare const publicOrgSchema: z.ZodObject<{
1192
1193
  is_personal_org: boolean;
1193
1194
  member_count: number;
1194
1195
  package_count: number;
1196
+ github_handle?: string | undefined;
1195
1197
  display_name?: string | undefined;
1196
1198
  user_permissions?: {
1197
1199
  can_manage_org?: boolean | undefined;
@@ -1205,6 +1207,7 @@ declare const publicOrgSchema: z.ZodObject<{
1205
1207
  is_personal_org: boolean;
1206
1208
  member_count: number;
1207
1209
  package_count: number;
1210
+ github_handle?: string | undefined;
1208
1211
  display_name?: string | undefined;
1209
1212
  user_permissions?: {
1210
1213
  can_manage_org?: boolean | undefined;
package/dist/schema.js CHANGED
@@ -356,6 +356,7 @@ var publicOrgSchema = z.object({
356
356
  is_personal_org: z.boolean(),
357
357
  display_name: z.string().optional(),
358
358
  package_count: z.number(),
359
+ github_handle: z.string().optional(),
359
360
  created_at: z.string(),
360
361
  user_permissions: z.object({
361
362
  can_manage_org: z.boolean().optional(),
@@ -427,6 +427,7 @@ export const publicOrgSchema = z.object({
427
427
  is_personal_org: z.boolean(),
428
428
  display_name: z.string().optional(),
429
429
  package_count: z.number(),
430
+ github_handle: z.string().optional(),
430
431
  created_at: z.string(),
431
432
  user_permissions: z
432
433
  .object({
@@ -1736,6 +1736,7 @@ export const SquareWaveModule = () => (
1736
1736
 
1737
1737
  const testOrg = db.addOrganization({
1738
1738
  name: "test-organization",
1739
+ github_handle: "tscircuit",
1739
1740
  owner_account_id: account_id,
1740
1741
  })
1741
1742
 
@@ -1831,6 +1832,7 @@ exports.TestComponent = TestComponent;
1831
1832
  db.addOrganization({
1832
1833
  name: "testuser",
1833
1834
  owner_account_id: account_id,
1835
+ github_handle: "tscircuit",
1834
1836
  is_personal_org: true,
1835
1837
  })
1836
1838
  }
@@ -28,6 +28,7 @@ export const publicMapOrg = (
28
28
  package_count: Number(package_count) || 0,
29
29
  is_personal_org: Boolean(is_personal_org),
30
30
  created_at: String(created_at),
31
+ ...(github_handle ? { github_handle } : {}),
31
32
  ...(can_manage_org ? { user_permissions: { can_manage_org: true } } : {}),
32
33
  }
33
34
  }
@@ -15,7 +15,7 @@ export default withRouteSpec({
15
15
  ),
16
16
  auth: "optional_session",
17
17
  jsonResponse: z.object({
18
- members: z.array(accountSchema),
18
+ members: z.array(accountSchema.extend({ joined_at: z.string() })),
19
19
  }),
20
20
  })(async (req, ctx) => {
21
21
  const params = req.commonParams as { org_id?: string; name?: string }
@@ -37,13 +37,17 @@ export default withRouteSpec({
37
37
 
38
38
  const members = ctx.db.orgAccounts
39
39
  .map((m) => {
40
- if (m.org_id == org.org_id) return ctx.db.getAccount(m.account_id)
41
- return undefined
40
+ if (m.org_id !== org.org_id) return undefined
41
+ const account = ctx.db.getAccount(m.account_id)
42
+ if (!account) return undefined
43
+ return {
44
+ ...account,
45
+ joined_at: m.created_at,
46
+ }
42
47
  })
43
48
  .filter(
44
49
  (member): member is NonNullable<typeof member> => member !== undefined,
45
50
  )
46
-
47
51
  const hasOwner = members.some((m) => m?.account_id === org.owner_account_id)
48
52
  let fullMembers = members
49
53
 
@@ -52,7 +56,13 @@ export default withRouteSpec({
52
56
  (acc) => acc.account_id === org.owner_account_id,
53
57
  )
54
58
  if (owner) {
55
- fullMembers = [...members, owner]
59
+ fullMembers = [
60
+ ...members,
61
+ {
62
+ ...owner,
63
+ joined_at: org.created_at,
64
+ },
65
+ ]
56
66
  }
57
67
  }
58
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/fake-snippets",
3
- "version": "0.0.111",
3
+ "version": "0.0.113",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -78,7 +78,7 @@
78
78
  "@resvg/resvg-wasm": "^2.6.2",
79
79
  "@sentry/react": "^10.10.0",
80
80
  "@tailwindcss/typography": "^0.5.16",
81
- "@tscircuit/3d-viewer": "^0.0.402",
81
+ "@tscircuit/3d-viewer": "^0.0.407",
82
82
  "@tscircuit/assembly-viewer": "^0.0.5",
83
83
  "@tscircuit/create-snippet-url": "^0.0.8",
84
84
  "@tscircuit/eval": "^0.0.325",
@@ -110,7 +110,7 @@
110
110
  "circuit-json-to-bom-csv": "^0.0.7",
111
111
  "circuit-json-to-gerber": "^0.0.29",
112
112
  "circuit-json-to-gltf": "^0.0.14",
113
- "circuit-json-to-kicad": "^0.0.9",
113
+ "circuit-json-to-kicad": "^0.0.22",
114
114
  "circuit-json-to-pnp-csv": "^0.0.7",
115
115
  "circuit-json-to-readable-netlist": "^0.0.13",
116
116
  "circuit-json-to-simple-3d": "^0.0.7",
@@ -141,7 +141,7 @@
141
141
  "jscad-electronics": "^0.0.25",
142
142
  "jszip": "^3.10.1",
143
143
  "kicad-converter": "^0.0.17",
144
- "kicadts": "^0.0.9",
144
+ "kicadts": "^0.0.10",
145
145
  "ky": "^1.7.5",
146
146
  "lucide-react": "^0.488.0",
147
147
  "lz-string": "^1.5.0",
@@ -372,7 +372,7 @@ const CmdKMenu = () => {
372
372
  switch (type) {
373
373
  case "package":
374
374
  case "recent":
375
- window.location.href = `/${item.owner_github_username}/${item.unscoped_name}`
375
+ window.location.href = `/${item.name}`
376
376
  setOpen(false)
377
377
  break
378
378
  case "account":
@@ -0,0 +1,35 @@
1
+ import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
2
+
3
+ export const GithubAvatarWithFallback = ({
4
+ username,
5
+ fallback,
6
+ className,
7
+ fallbackClassName,
8
+ size,
9
+ }: {
10
+ username?: string | null
11
+ fallback?: string | null
12
+ className?: string
13
+ fallbackClassName?: string
14
+ size?: number
15
+ }) => {
16
+ return (
17
+ <Avatar className={`border-4 border-gray-100 ${className}`}>
18
+ <AvatarImage
19
+ src={`https://github.com/${username}.png${size ? `?size=${size}` : ""}`}
20
+ alt={`${username || fallback} avatar`}
21
+ className="object-cover"
22
+ />
23
+ <AvatarFallback
24
+ className={`bg-blue-100 text-blue-600 ${fallbackClassName}`}
25
+ >
26
+ {(username || fallback || "")
27
+ .split(" ")
28
+ .map((word) => word[0])
29
+ .join("")
30
+ .toUpperCase()
31
+ .slice(0, 2)}
32
+ </AvatarFallback>
33
+ </Avatar>
34
+ )
35
+ }
@@ -35,7 +35,7 @@ export const HeaderLogin = () => {
35
35
  <DropdownMenuTrigger asChild>
36
36
  <Avatar className="w-8 h-8 login-avatar">
37
37
  <AvatarImage
38
- src={`https://github.com/${session?.github_username}.png`}
38
+ src={`https://github.com/${session?.github_username}.png?size=40`}
39
39
  alt={`${session?.github_username}'s profile picture`}
40
40
  />
41
41
  <AvatarFallback aria-label="User avatar fallback">
@@ -67,7 +67,7 @@ export const PackageCard: React.FC<PackageCardProps> = ({
67
67
 
68
68
  const handleShareClick = (e: React.MouseEvent) => {
69
69
  e.preventDefault()
70
- const shareUrl = `${window.location.origin}/${pkg.owner_github_username}/${pkg.unscoped_name}`
70
+ const shareUrl = `${window.location.origin}/${pkg.name}`
71
71
  copyToClipboard(shareUrl)
72
72
  }
73
73
 
@@ -178,10 +178,7 @@ export const PackageCard: React.FC<PackageCardProps> = ({
178
178
 
179
179
  if (withLink) {
180
180
  return (
181
- <Link
182
- key={pkg.package_id}
183
- href={`/${pkg.owner_github_username}/${pkg.unscoped_name}`}
184
- >
181
+ <Link key={pkg.package_id} href={`/${pkg.name}`}>
185
182
  {cardContent}
186
183
  </Link>
187
184
  )
@@ -50,10 +50,10 @@ export const PackagesList = ({
50
50
  <li key={pkg.package_id}>
51
51
  <div className="flex items-center">
52
52
  <Link
53
- href={`/${pkg.owner_github_username}/${pkg.unscoped_name}`}
53
+ href={`/${pkg.name}`}
54
54
  className="text-blue-600 hover:underline text-sm"
55
55
  >
56
- {pkg.owner_github_username}/{pkg.unscoped_name}
56
+ {pkg.name}
57
57
  </Link>
58
58
  {pkg.star_count > 0 && (
59
59
  <span className="ml-2 text-gray-500 text-xs flex items-center">
@@ -1,18 +1,16 @@
1
1
  import React from "react"
2
2
  import { useParams } from "wouter"
3
- import { useOrgByGithubHandle } from "@/hooks/use-org-by-github-handle"
4
3
  import { OrganizationProfilePageContent } from "@/pages/organization-profile"
5
4
  import { UserProfilePage } from "@/pages/user-profile"
6
5
  import NotFoundPage from "@/pages/404"
7
6
  import { FullPageLoader } from "@/App"
7
+ import { useOrganization } from "@/hooks/use-organization"
8
8
 
9
9
  const ProfileRouter: React.FC = () => {
10
10
  const { username } = useParams()
11
- const {
12
- data: organization,
13
- isLoading,
14
- error,
15
- } = useOrgByGithubHandle(username || null)
11
+ const { organization, isLoading, error } = useOrganization({
12
+ orgName: username,
13
+ })
16
14
 
17
15
  if (!username) {
18
16
  return <NotFoundPage heading="Username Not Provided" />
@@ -11,10 +11,10 @@ const CarouselItem = ({
11
11
  apiBaseUrl,
12
12
  }: { pkg: Package; apiBaseUrl: string }) => {
13
13
  return (
14
- <Link href={`/${pkg.owner_github_username}/${pkg.unscoped_name}`}>
14
+ <Link href={`/${pkg.name}`}>
15
15
  <div className="flex-shrink-0 w-[200px] bg-white p-3 py-2 rounded-lg shadow-sm border border-gray-200 hover:border-gray-300 transition-colors">
16
16
  <div className="font-medium text-blue-600 mb-1 truncate text-sm">
17
- {pkg.owner_github_username}/{pkg.unscoped_name}
17
+ {pkg.name}
18
18
  </div>
19
19
  <div className="mb-2 h-24 w-full bg-black rounded overflow-hidden">
20
20
  <img
@@ -36,7 +36,7 @@ export const UserCard: React.FC<UserCardProps> = ({
36
36
  <div className="flex items-start gap-4">
37
37
  <div className="w-16 h-16 flex-shrink-0 rounded-md overflow-hidden bg-gray-50 border flex items-center justify-center">
38
38
  <img
39
- src={`https://github.com/${account.github_username}.png`}
39
+ src={`https://github.com/${account.github_username}.png?size=69`}
40
40
  alt={`${account.github_username} avatar`}
41
41
  className="object-cover h-full w-full transition-transform duration-300 hover:scale-110"
42
42
  onError={(e) => {
@@ -1,4 +1,4 @@
1
- import { CheckCircle, XCircle, Clock, Loader2 } from "lucide-react"
1
+ import { CheckCircle, XCircle, Clock, Loader2, Hourglass } from "lucide-react"
2
2
  import { Link, useParams } from "wouter"
3
3
 
4
4
  export interface BuildStep {
@@ -28,7 +28,7 @@ export const BuildStatus = ({ step, packageReleaseId }: BuildStatusProps) => {
28
28
  <Loader2 className="h-4 w-4 text-blue-600 animate-spin dark:text-[#8b949e]" />
29
29
  )}
30
30
  {step.status === "pending" && (
31
- <Clock className="h-4 w-4 text-yellow-600 dark:text-[#8b949e]" />
31
+ <Hourglass className="h-4 w-4 text-gray-500 dark:text-[#8b949e]" />
32
32
  )}
33
33
  <span className="text-sm text-gray-500 dark:text-[#8b949e]">
34
34
  {step.name}
@@ -81,7 +81,7 @@ export default function SidebarReleasesSection() {
81
81
  <div className="mb-6">
82
82
  <h2 className="text-lg font-semibold mb-2">
83
83
  <Link
84
- href={`/${packageInfo?.owner_github_username}/${packageInfo?.unscoped_name}/releases`}
84
+ href={`/${packageInfo?.name}/releases`}
85
85
  className="hover:underline"
86
86
  >
87
87
  Releases
@@ -89,7 +89,7 @@ export default function SidebarReleasesSection() {
89
89
  </h2>
90
90
  <div className="flex flex-col space-y-2">
91
91
  <Link
92
- href={`/${packageInfo?.owner_github_username}/${packageInfo?.unscoped_name}/releases`}
92
+ href={`/${packageInfo?.name}/releases`}
93
93
  className="flex items-center hover:underline"
94
94
  >
95
95
  <Tag className="h-4 w-4 mr-2 text-gray-500 dark:text-[#8b949e]" />
@@ -21,6 +21,7 @@ import { timeAgo } from "@/lib/utils/timeAgo"
21
21
  import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"
22
22
  import { PublicOrgSchema } from "fake-snippets-api/lib/db/schema"
23
23
  import { useGlobalStore } from "@/hooks/use-global-store"
24
+ import { GithubAvatarWithFallback } from "../GithubAvatarWithFallback"
24
25
 
25
26
  export interface OrganizationCardProps {
26
27
  /** The organization data to display */
@@ -85,21 +86,16 @@ export const OrganizationCard: React.FC<OrganizationCardProps> = ({
85
86
  <div className="flex items-start gap-4">
86
87
  {/* Organization Avatar */}
87
88
  <div className="flex-shrink-0">
88
- <Avatar className="h-16 w-16 border-2 border-gray-100">
89
- <AvatarImage
90
- src={`https://github.com/${organization.name}.png`}
91
- alt={`${organization.name} avatar`}
92
- className="object-cover"
93
- />
94
- <AvatarFallback className="bg-blue-100 text-blue-600 font-semibold text-lg">
95
- {organization.name
96
- ?.split(" ")
97
- .map((word) => word[0])
98
- .join("")
99
- .toUpperCase()
100
- .slice(0, 2)}
101
- </AvatarFallback>
102
- </Avatar>
89
+ <GithubAvatarWithFallback
90
+ username={
91
+ organization.is_personal_org
92
+ ? organization.github_handle || organization.name
93
+ : organization.github_handle
94
+ }
95
+ fallback={organization.name}
96
+ fallbackClassName=" font-semibold text-lg"
97
+ size={40}
98
+ />
103
99
  </div>
104
100
 
105
101
  {/* Organization Info */}
@@ -1,5 +1,4 @@
1
- import React, { useState } from "react"
2
- import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
1
+ import React from "react"
3
2
  import { Button } from "@/components/ui/button"
4
3
  import { Building2, Users, Package, Lock, Globe2, Settings } from "lucide-react"
5
4
  import { cn } from "@/lib/utils"
@@ -7,6 +6,7 @@ import { PublicOrgSchema } from "fake-snippets-api/lib/db/schema"
7
6
  import { useGlobalStore } from "@/hooks/use-global-store"
8
7
  import { useLocation } from "wouter"
9
8
  import { useOrganization } from "@/hooks/use-organization"
9
+ import { GithubAvatarWithFallback } from "../GithubAvatarWithFallback"
10
10
 
11
11
  interface OrganizationHeaderProps {
12
12
  organization: PublicOrgSchema
@@ -40,21 +40,13 @@ export const OrganizationHeader: React.FC<OrganizationHeaderProps> = ({
40
40
  {/* Mobile Layout */}
41
41
  <div className="block sm:hidden">
42
42
  <div className="flex flex-col items-center text-center space-y-4">
43
- <Avatar className="border-4 border-gray-100 shadow-sm size-16 md:size-20 lg:size-24">
44
- <AvatarImage
45
- src={`https://github.com/${organization.name}.png`}
46
- alt={`${organization.name} avatar`}
47
- className="object-cover"
48
- />
49
- <AvatarFallback className="bg-blue-100 text-blue-600 font-bold text-xl md:text-2xl lg:text-3xl">
50
- {(organization.name || "")
51
- .split(" ")
52
- .map((word) => word[0])
53
- .join("")
54
- .toUpperCase()
55
- .slice(0, 2)}
56
- </AvatarFallback>
57
- </Avatar>
43
+ <GithubAvatarWithFallback
44
+ username={organization.github_handle}
45
+ fallback={organization.name}
46
+ className="shadow-sm size-16 md:size-20 lg:size-24"
47
+ fallbackClassName="font-bold text-xl md:text-2xl lg:text-3xl"
48
+ size={300}
49
+ />
58
50
 
59
51
  <div>
60
52
  <div className="flex flex-col items-center gap-3 mb-3">
@@ -96,21 +88,12 @@ export const OrganizationHeader: React.FC<OrganizationHeaderProps> = ({
96
88
  {/* Desktop Layout */}
97
89
  <div className="hidden sm:block">
98
90
  <div className="flex items-center gap-6">
99
- <Avatar className="border-4 border-gray-100 shadow-sm size-16 md:size-20 lg:size-24 flex-shrink-0">
100
- <AvatarImage
101
- src={`https://github.com/${organization.name}.png`}
102
- alt={`${organization.name} avatar`}
103
- className="object-cover"
104
- />
105
- <AvatarFallback className="bg-blue-100 text-blue-600 font-bold text-xl md:text-2xl lg:text-3xl">
106
- {(organization.name || "")
107
- .split(" ")
108
- .map((word) => word[0])
109
- .join("")
110
- .toUpperCase()
111
- .slice(0, 2)}
112
- </AvatarFallback>
113
- </Avatar>
91
+ <GithubAvatarWithFallback
92
+ username={organization.github_handle}
93
+ fallback={organization.name}
94
+ className="flex-shrink-0 shadow-sm size-16 md:size-20 lg:size-24"
95
+ fallbackClassName="font-bold text-xl md:text-2xl lg:text-3xl"
96
+ />
114
97
 
115
98
  <div className="flex-1 min-w-0">
116
99
  <div className="flex items-center justify-between mb-3">
@@ -2,11 +2,9 @@ import React from "react"
2
2
  import { Link } from "wouter"
3
3
  import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
4
4
  import { Badge } from "@/components/ui/badge"
5
- import { Button } from "@/components/ui/button"
6
5
  import { Users, Crown, Shield, User, Loader2 } from "lucide-react"
7
6
  import { timeAgo } from "@/lib/utils/timeAgo"
8
7
  import { cn } from "@/lib/utils"
9
- import { Account } from "fake-snippets-api/lib/db/schema"
10
8
  import { useListOrgMembers } from "@/hooks/use-list-org-members"
11
9
 
12
10
  interface OrganizationMembersProps {
@@ -69,7 +67,7 @@ export const OrganizationMembers: React.FC<OrganizationMembersProps> = ({
69
67
  return (
70
68
  <div
71
69
  className={cn(
72
- "bg-white rounded-lg border border-gray-200 p-4 py-20 sm:p-6",
70
+ "bg-white rounded-lg border border-gray-200 p-4 sm:p-6",
73
71
  className,
74
72
  )}
75
73
  >
@@ -124,12 +122,13 @@ export const OrganizationMembers: React.FC<OrganizationMembersProps> = ({
124
122
  </p>
125
123
  </div>
126
124
  </div>
127
-
128
- <div className="text-right flex-shrink-0 hidden sm:block">
129
- <p className="text-xs text-gray-500">
130
- Joined {timeAgo(new Date())}
131
- </p>
132
- </div>
125
+ {member.joined_at && (
126
+ <div className="text-right flex-shrink-0 hidden sm:block">
127
+ <p className="text-xs text-gray-500">
128
+ Joined {timeAgo(new Date(member.joined_at))}
129
+ </p>
130
+ </div>
131
+ )}
133
132
  </div>
134
133
  </Link>
135
134
  ))}
@@ -117,7 +117,7 @@ export const ConnectedPackageCard = ({
117
117
  <div className="flex items-start justify-between mb-4">
118
118
  <div className="flex items-center gap-3">
119
119
  <Link
120
- href={`/${pkg.owner_github_username}/${pkg.unscoped_name}`}
120
+ href={`/${pkg.name}`}
121
121
  className="text-lg font-semibold text-gray-900 hover:text-blue-600 transition-colors"
122
122
  >
123
123
  {pkg.unscoped_name}
@@ -62,8 +62,8 @@ export const PackageReleasesDashboard = ({
62
62
  {/* Project Header */}
63
63
  <div className="bg-gray-50 border-b md:py-10">
64
64
  <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
65
- <div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-6">
66
- <div className="flex flex-col sm:flex-row sm:items-center gap-4">
65
+ <div className="flex flex-col md:justify-between md:flex-row lg:items-center lg:justify-between gap-6">
66
+ <div className="flex flex-col md:flex-row md:items-center gap-4">
67
67
  <div className="w-12 hidden md:block h-12 rounded-lg overflow-hidden flex-shrink-0">
68
68
  <img
69
69
  src="https://github.com/tscircuit.png"
@@ -180,7 +180,7 @@ export const PackageReleasesDashboard = ({
180
180
  <MoreHorizontal className="w-4 h-4" />
181
181
  </Button>
182
182
  </DropdownMenuTrigger>
183
- <DropdownMenuContent align="end">
183
+ <DropdownMenuContent align="end" className="ml-2">
184
184
  {pkg.github_repo_full_name && (
185
185
  <DropdownMenuItem asChild>
186
186
  <a
@@ -2,12 +2,16 @@ import { useQuery } from "react-query"
2
2
  import { useAxios } from "@/hooks/use-axios"
3
3
  import type { Account } from "fake-snippets-api/lib/db/schema"
4
4
 
5
+ interface MemberAccount extends Account {
6
+ joined_at?: string
7
+ }
8
+
5
9
  export const useListOrgMembers = ({
6
10
  orgId,
7
11
  orgName,
8
12
  }: { orgId?: string; orgName?: string }) => {
9
13
  const axios = useAxios()
10
- return useQuery<Account[], Error & { status: number }>(
14
+ return useQuery<MemberAccount[], Error & { status: number }>(
11
15
  ["orgs", "members", orgId || orgName],
12
16
  async () => {
13
17
  if (!orgId && !orgName) {
@@ -1,11 +1,9 @@
1
1
  import { useQuery } from "react-query"
2
2
  import { useAxios } from "@/hooks/use-axios"
3
3
  import type { PublicOrgSchema } from "fake-snippets-api/lib/db/schema"
4
- import { useGlobalStore } from "./use-global-store"
5
4
 
6
5
  export const useOrgByGithubHandle = (githubHandle: string | null) => {
7
6
  const axios = useAxios()
8
- const session = useGlobalStore((s) => s.session)
9
7
  return useQuery<PublicOrgSchema, Error & { status: number }>(
10
8
  ["orgs", "by-github-handle", githubHandle],
11
9
  async () => {
@@ -7,9 +7,7 @@ import { useCurrentPackageInfo } from "@/hooks/use-current-package-info"
7
7
  export const EditorPage = () => {
8
8
  const { packageInfo: pkg, error } = useCurrentPackageInfo()
9
9
 
10
- const projectUrl = pkg
11
- ? `https://tscircuit.com/${pkg.owner_github_username}/${pkg.unscoped_name}`
12
- : undefined
10
+ const projectUrl = pkg ? `https://tscircuit.com/${pkg.name}` : undefined
13
11
 
14
12
  return (
15
13
  <div className="overflow-x-hidden">
@@ -170,30 +170,32 @@ export default function ReleaseDetailPage() {
170
170
  </div>
171
171
 
172
172
  {/* Images Section - Always show with skeletons while loading */}
173
- <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
174
- <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
175
- {availableViews.length > 0
176
- ? availableViews.map((view) => (
177
- <div
178
- key={view.id}
179
- className="flex items-center justify-center border rounded-lg bg-gray-50 overflow-hidden h-48"
180
- >
181
- {view.isLoading ? (
182
- <Skeleton className="w-full h-full" />
183
- ) : (
184
- <img
185
- src={view.imageUrl}
186
- alt={`${view.label} preview`}
187
- className={`w-full h-full object-contain ${view.label.toLowerCase() == "pcb" ? "bg-black" : view.label.toLowerCase() == "schematic" ? "bg-[#F5F1ED]" : "bg-gray-100"}`}
188
- />
189
- )}
190
- </div>
191
- ))
192
- : [1, 2, 3].map((i) => (
193
- <Skeleton key={i} className="h-48 rounded-lg" />
194
- ))}
173
+ {Boolean(latestBuild) && (
174
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
175
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
176
+ {availableViews.length > 0
177
+ ? availableViews.map((view) => (
178
+ <div
179
+ key={view.id}
180
+ className="flex items-center justify-center border rounded-lg bg-gray-50 overflow-hidden h-48"
181
+ >
182
+ {view.isLoading ? (
183
+ <Skeleton className="w-full h-full" />
184
+ ) : (
185
+ <img
186
+ src={view.imageUrl}
187
+ alt={`${view.label} preview`}
188
+ className={`w-full h-full object-contain ${view.label.toLowerCase() == "pcb" ? "bg-black" : view.label.toLowerCase() == "schematic" ? "bg-[#F5F1ED]" : "bg-gray-100"}`}
189
+ />
190
+ )}
191
+ </div>
192
+ ))
193
+ : [1, 2, 3].map((i) => (
194
+ <Skeleton key={i} className="h-48 rounded-lg" />
195
+ ))}
196
+ </div>
195
197
  </div>
196
- </div>
198
+ )}
197
199
 
198
200
  {/* Main Content */}
199
201
  <ConnectedRepoOverview