@tscircuit/fake-snippets 0.0.108 → 0.0.110

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 (203) hide show
  1. package/.github/workflows/bun-formatcheck.yml +2 -2
  2. package/.github/workflows/bun-pver-release.yml +3 -3
  3. package/.github/workflows/bun-test.yml +1 -1
  4. package/.github/workflows/bun-typecheck.yml +2 -2
  5. package/.github/workflows/update-snapshots.yml +1 -1
  6. package/README.md +4 -0
  7. package/api/generated-index.js +37 -3
  8. package/biome.json +2 -1
  9. package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +31 -3
  10. package/bun-tests/fake-snippets-api/fixtures/preload.ts +18 -0
  11. package/bun-tests/fake-snippets-api/routes/orgs/add_member.test.ts +26 -0
  12. package/bun-tests/fake-snippets-api/routes/orgs/create.test.ts +37 -0
  13. package/bun-tests/fake-snippets-api/routes/orgs/get.test.ts +52 -0
  14. package/bun-tests/fake-snippets-api/routes/orgs/list.test.ts +17 -0
  15. package/bun-tests/fake-snippets-api/routes/orgs/list_members.test.ts +23 -0
  16. package/bun-tests/fake-snippets-api/routes/orgs/remove_member.test.ts +81 -0
  17. package/bun-tests/fake-snippets-api/routes/orgs/update.test.ts +99 -0
  18. package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +1 -1
  19. package/bun-tests/fake-snippets-api/routes/package_files/create.test.ts +15 -13
  20. package/bun-tests/fake-snippets-api/routes/package_files/create_or_update.test.ts +26 -24
  21. package/bun-tests/fake-snippets-api/routes/package_files/delete.test.ts +9 -9
  22. package/bun-tests/fake-snippets-api/routes/package_files/download.test.ts +4 -4
  23. package/bun-tests/fake-snippets-api/routes/package_files/get.test.ts +38 -28
  24. package/bun-tests/fake-snippets-api/routes/package_files/list.test.ts +23 -15
  25. package/bun-tests/fake-snippets-api/routes/package_releases/create.test.ts +33 -0
  26. package/bun-tests/fake-snippets-api/routes/package_releases/get.test.ts +4 -4
  27. package/bun-tests/fake-snippets-api/routes/package_releases/get_image_generation_fields.test.ts +38 -0
  28. package/bun-tests/fake-snippets-api/routes/packages/create.test.ts +19 -0
  29. package/bun-tests/fake-snippets-api/routes/packages/fork.test.ts +3 -4
  30. package/bun-tests/fake-snippets-api/routes/packages/get.test.ts +30 -0
  31. package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +4 -2
  32. package/bun-tests/fake-snippets-api/routes/packages/list-1.test.ts +34 -0
  33. package/bun.lock +389 -450
  34. package/bunfig.toml +2 -1
  35. package/dist/bundle.js +1255 -625
  36. package/dist/index.d.ts +296 -4
  37. package/dist/index.js +325 -24
  38. package/dist/schema.d.ts +282 -1
  39. package/dist/schema.js +54 -2
  40. package/fake-snippets-api/lib/db/autoload-dev-packages.ts +31 -20
  41. package/fake-snippets-api/lib/db/db-client.ts +214 -3
  42. package/fake-snippets-api/lib/db/schema.ts +62 -0
  43. package/fake-snippets-api/lib/db/seed.ts +100 -0
  44. package/fake-snippets-api/lib/middleware/with-session-auth.ts +1 -1
  45. package/fake-snippets-api/lib/package_file/get-package-file-id-from-file-descriptor.ts +2 -2
  46. package/fake-snippets-api/lib/public-mapping/public-map-org.ts +32 -0
  47. package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +10 -0
  48. package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +17 -0
  49. package/fake-snippets-api/routes/api/orgs/add_member.ts +52 -0
  50. package/fake-snippets-api/routes/api/orgs/create.ts +46 -0
  51. package/fake-snippets-api/routes/api/orgs/get.ts +39 -0
  52. package/fake-snippets-api/routes/api/orgs/list.ts +31 -0
  53. package/fake-snippets-api/routes/api/orgs/list_members.ts +67 -0
  54. package/fake-snippets-api/routes/api/orgs/remove_member.ts +46 -0
  55. package/fake-snippets-api/routes/api/orgs/update.ts +93 -0
  56. package/fake-snippets-api/routes/api/package_files/get.ts +3 -6
  57. package/fake-snippets-api/routes/api/package_files/list.ts +7 -4
  58. package/fake-snippets-api/routes/api/packages/create.ts +54 -10
  59. package/fake-snippets-api/routes/api/packages/get.ts +23 -0
  60. package/fake-snippets-api/routes/api/packages/images/[owner_github_username]/[unscoped_name]/[view_format].ts +13 -11
  61. package/fake-snippets-api/routes/api/packages/list.ts +29 -2
  62. package/fake-snippets-api/routes/api/packages/update_ai_description.ts +37 -0
  63. package/package.json +27 -24
  64. package/renovate.json +1 -1
  65. package/scripts/generate-sitemap.ts +1 -1
  66. package/src/App.tsx +29 -10
  67. package/src/ContextProviders.tsx +25 -2
  68. package/src/components/CircuitJsonImportDialog.tsx +1 -1
  69. package/src/components/CmdKMenu.tsx +281 -247
  70. package/src/components/DownloadButtonAndMenu.tsx +133 -36
  71. package/src/components/FileSidebar.tsx +41 -50
  72. package/src/components/Footer.tsx +8 -10
  73. package/src/components/Header.tsx +19 -32
  74. package/src/components/Header2.tsx +16 -32
  75. package/src/components/HeaderDropdown.tsx +13 -8
  76. package/src/components/HeaderLogin.tsx +44 -16
  77. package/src/components/HiddenFilesDropdown.tsx +0 -2
  78. package/src/components/NotFound.tsx +5 -5
  79. package/src/components/PackageBreadcrumb.tsx +6 -12
  80. package/src/components/PackageCard.tsx +0 -1
  81. package/src/components/PackageSearchResults.tsx +1 -1
  82. package/src/components/PrefetchPageLink.tsx +7 -1
  83. package/src/components/ProfileRouter.tsx +32 -0
  84. package/src/components/SearchComponent.tsx +12 -8
  85. package/src/components/UserCard.tsx +80 -0
  86. package/src/components/ViewPackagePage/components/ShikiCodeViewer.tsx +20 -11
  87. package/src/components/ViewPackagePage/components/build-status.tsx +1 -1
  88. package/src/components/ViewPackagePage/components/important-files-view.tsx +174 -87
  89. package/src/components/ViewPackagePage/components/main-content-header.tsx +8 -4
  90. package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +1 -2
  91. package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +54 -20
  92. package/src/components/ViewPackagePage/components/package-header.tsx +26 -37
  93. package/src/components/ViewPackagePage/components/preview-image-squares.tsx +11 -19
  94. package/src/components/ViewPackagePage/components/repo-page-content.tsx +33 -25
  95. package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +16 -10
  96. package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +11 -11
  97. package/src/components/ViewPackagePage/components/sidebar.tsx +0 -2
  98. package/src/components/ViewPackagePage/components/tab-views/files-view.tsx +18 -17
  99. package/src/components/ViewPackagePage/components/tab-views/pcb-view.tsx +1 -2
  100. package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +2 -1
  101. package/src/components/ViewPackagePage/components/theme-toggle.tsx +0 -2
  102. package/src/components/ViewPackagePage/hooks/use-toast.tsx +0 -1
  103. package/src/components/dialogs/GitHubRepositorySelector.tsx +56 -49
  104. package/src/components/dialogs/edit-package-details-dialog.tsx +5 -6
  105. package/src/components/dialogs/import-component-dialog.tsx +16 -9
  106. package/src/components/dialogs/import-package-dialog.tsx +3 -2
  107. package/src/components/dialogs/new-package-save-prompt-dialog.tsx +190 -0
  108. package/src/components/organization/OrganizationCard.tsx +204 -0
  109. package/src/components/organization/OrganizationCardSkeleton.tsx +55 -0
  110. package/src/components/organization/OrganizationHeader.tsx +154 -0
  111. package/src/components/organization/OrganizationMembers.tsx +146 -0
  112. package/src/components/package-port/CodeAndPreview.tsx +32 -46
  113. package/src/components/package-port/CodeEditor.tsx +28 -31
  114. package/src/components/package-port/CodeEditorHeader.tsx +128 -63
  115. package/src/components/package-port/EditorNav.tsx +32 -49
  116. package/src/components/preview/ConnectedPackagesList.tsx +8 -8
  117. package/src/components/preview/ConnectedRepoOverview.tsx +102 -2
  118. package/src/components/preview/PackageReleasesDashboard.tsx +53 -36
  119. package/src/components/ui/tree-view.tsx +6 -3
  120. package/src/hooks/use-add-org-member-mutation.ts +51 -0
  121. package/src/hooks/use-create-org-mutation.ts +38 -0
  122. package/src/hooks/use-create-package-mutation.ts +3 -0
  123. package/src/hooks/use-current-package-id.ts +5 -30
  124. package/src/hooks/use-current-package-info.ts +29 -5
  125. package/src/hooks/use-current-package-release.ts +4 -3
  126. package/src/hooks/use-download-zip.ts +2 -2
  127. package/src/hooks/use-global-store.ts +6 -4
  128. package/src/hooks/use-jlcpcb-component-import.tsx +164 -0
  129. package/src/hooks/use-list-org-members.ts +27 -0
  130. package/src/hooks/use-list-user-orgs.ts +25 -0
  131. package/src/hooks/use-org-by-github-handle.ts +26 -0
  132. package/src/hooks/use-org.ts +24 -0
  133. package/src/hooks/use-organization.ts +42 -0
  134. package/src/hooks/use-package-as-snippet.ts +4 -2
  135. package/src/hooks/use-package-builds.ts +6 -2
  136. package/src/hooks/use-package-files.ts +5 -3
  137. package/src/hooks/use-package-release-by-id-or-version.ts +29 -20
  138. package/src/hooks/use-package-release-images.ts +105 -0
  139. package/src/hooks/use-package-release.ts +2 -2
  140. package/src/hooks/use-package-stars.ts +80 -4
  141. package/src/hooks/use-preview-images.ts +6 -3
  142. package/src/hooks/use-remove-org-member-mutation.ts +32 -0
  143. package/src/hooks/use-update-ai-description-mutation.ts +42 -0
  144. package/src/hooks/use-update-org-mutation.ts +41 -0
  145. package/src/hooks/use-warn-user-on-page-change.ts +71 -4
  146. package/src/hooks/useFileManagement.ts +183 -35
  147. package/src/hooks/useOptimizedPackageFilesLoader.ts +136 -0
  148. package/src/hooks/usePackageFilesLoader.ts +2 -2
  149. package/src/hooks/useUpdatePackageFilesMutation.ts +15 -1
  150. package/src/lib/download-fns/download-circuit-png.ts +11 -3
  151. package/src/lib/download-fns/download-gltf-from-circuit-json.ts +44 -0
  152. package/src/lib/download-fns/download-kicad-files.ts +12 -11
  153. package/src/lib/normalize-svg-for-tile.ts +50 -0
  154. package/src/lib/posthog.ts +11 -9
  155. package/src/lib/react-query-api-failure-tracking.ts +148 -0
  156. package/src/lib/sentry.ts +14 -0
  157. package/src/lib/templates/blank-circuit-board-template.ts +0 -4
  158. package/src/lib/ts-lib-cache.ts +122 -7
  159. package/src/lib/utils/checkIfManualEditsImported.ts +4 -4
  160. package/src/lib/utils/findTargetFile.ts +45 -10
  161. package/src/lib/utils/isComponentExported.ts +10 -0
  162. package/src/main.tsx +2 -1
  163. package/src/pages/authorize.tsx +0 -2
  164. package/src/pages/create-organization.tsx +168 -0
  165. package/src/pages/dashboard.tsx +38 -6
  166. package/src/pages/datasheet.tsx +1 -1
  167. package/src/pages/datasheets.tsx +3 -3
  168. package/src/pages/editor.tsx +4 -6
  169. package/src/pages/landing.tsx +6 -7
  170. package/src/pages/latest.tsx +3 -0
  171. package/src/pages/organization-profile.tsx +199 -0
  172. package/src/pages/organization-settings.tsx +566 -0
  173. package/src/pages/package-editor.tsx +21 -21
  174. package/src/pages/preview-release.tsx +76 -136
  175. package/src/pages/quickstart.tsx +159 -123
  176. package/src/pages/release-detail.tsx +119 -31
  177. package/src/pages/search.tsx +192 -57
  178. package/src/pages/settings-redirect.tsx +44 -0
  179. package/src/pages/trending.tsx +29 -20
  180. package/src/pages/user-profile.tsx +58 -7
  181. package/src/pages/view-package.tsx +21 -26
  182. package/vite.config.ts +9 -0
  183. package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +0 -133
  184. package/src/components/Footer2.tsx +0 -100
  185. package/src/components/JLCPCBImportDialog.tsx +0 -280
  186. package/src/components/PackageBuildsPage/LogContent.tsx +0 -72
  187. package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +0 -115
  188. package/src/components/PackageBuildsPage/build-preview-content.tsx +0 -27
  189. package/src/components/PackageBuildsPage/collapsible-section.tsx +0 -63
  190. package/src/components/PackageBuildsPage/package-build-details-panel.tsx +0 -166
  191. package/src/components/PackageBuildsPage/package-build-header.tsx +0 -79
  192. package/src/components/PageSearchComponent.tsx +0 -148
  193. package/src/components/ShippingInformationForm.tsx +0 -423
  194. package/src/components/StaticViewSnippetHeader.tsx +0 -70
  195. package/src/components/ViewPackagePage/components/file-explorer.tsx +0 -67
  196. package/src/components/ViewPackagePage/components/readme-view.tsx +0 -58
  197. package/src/components/ViewPackagePage/components/repo-header-button.tsx +0 -36
  198. package/src/components/ViewPackagePage/components/repo-header.tsx +0 -4
  199. package/src/components/ViewPackagePage/components/sidebar-contributors-section.tsx +0 -31
  200. package/src/components/ViewSnippetHeader.tsx +0 -181
  201. package/src/components/ui/input-otp.tsx +0 -69
  202. package/src/pages/package-builds.tsx +0 -33
  203. package/src/pages/settings.tsx +0 -25
@@ -1,166 +0,0 @@
1
- import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
2
- import { useNow } from "@/hooks/use-now"
3
- import { timeAgo } from "@/lib/utils/timeAgo"
4
- import { PackageRelease } from "fake-snippets-api/lib/db/schema"
5
- import { Clock, GitBranch, GitCommit, Globe } from "lucide-react"
6
- import { useParams } from "wouter"
7
-
8
- const capitalCase = (str: string) => {
9
- return str.charAt(0).toUpperCase() + str.slice(1)
10
- }
11
-
12
- function getColorFromDisplayStatus(
13
- display_status: PackageRelease["display_status"],
14
- ) {
15
- switch (display_status) {
16
- case "pending":
17
- return "bg-yellow-500"
18
- case "building":
19
- return "bg-blue-500"
20
- case "complete":
21
- return "bg-green-500"
22
- case "error":
23
- return "bg-red-500"
24
- }
25
- }
26
-
27
- export function PackageBuildDetailsPanel() {
28
- const { packageRelease } = useCurrentPackageRelease({ refetchInterval: 2000 })
29
- const { author } = useParams() // TODO use packageRelease.author_account_id when it's added by backed
30
- const now = useNow(1000)
31
-
32
- if (!packageRelease) {
33
- // TODO show skeleton instead
34
- return null
35
- }
36
-
37
- const {
38
- circuit_json_build_display_status,
39
- circuit_json_build_in_progress,
40
- circuit_json_build_is_stale,
41
- circuit_json_build_logs,
42
- transpilation_display_status,
43
- transpilation_in_progress,
44
- transpilation_logs,
45
- circuit_json_build_completed_at,
46
- transpilation_is_stale,
47
- display_status,
48
- created_at,
49
- has_transpiled,
50
- circuit_json_build_started_at,
51
- circuit_json_build_error,
52
- circuit_json_build_error_last_updated_at,
53
- total_build_duration_ms,
54
- transpilation_completed_at,
55
- transpilation_error,
56
- transpilation_started_at,
57
- commit_sha,
58
- } = packageRelease
59
-
60
- const buildStartedAt = (() => {
61
- if (transpilation_started_at && circuit_json_build_started_at) {
62
- return new Date(transpilation_started_at) <
63
- new Date(circuit_json_build_started_at)
64
- ? transpilation_started_at
65
- : circuit_json_build_started_at
66
- }
67
- return transpilation_started_at || circuit_json_build_started_at || null
68
- })()
69
-
70
- const buildCompletedAt =
71
- circuit_json_build_completed_at || transpilation_completed_at || null
72
-
73
- const elapsedMs = buildStartedAt
74
- ? (buildCompletedAt ? new Date(buildCompletedAt).getTime() : now) -
75
- new Date(buildStartedAt).getTime()
76
- : null
77
-
78
- return (
79
- <div className="space-y-4 sm:space-y-6 bg-white p-3 sm:p-4 border border-gray-200 rounded-lg">
80
- {/* Created */}
81
- <div>
82
- <h3 className="text-sm font-medium text-gray-600 mb-2">Created</h3>
83
- <div className="flex items-center gap-2 min-w-0">
84
- <div className="w-6 h-6 bg-orange-500 rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0">
85
- I
86
- </div>
87
- <span className="text-sm truncate">{author}</span>
88
- <span className="text-sm text-gray-500 flex-shrink-0">
89
- {timeAgo(created_at, "")}
90
- </span>
91
- </div>
92
- </div>
93
-
94
- {/* Status */}
95
- <div>
96
- <h3 className="text-sm font-medium text-gray-600 mb-2">Status</h3>
97
- <div className="flex items-center gap-2">
98
- <div
99
- className={`w-2 h-2 ${getColorFromDisplayStatus(display_status)} rounded-full flex-shrink-0`}
100
- ></div>
101
- <span className="text-sm">{capitalCase(display_status)}</span>
102
- {/* <Badge
103
- variant="secondary"
104
- className="bg-gray-200 text-gray-700 text-xs"
105
- >
106
- Latest
107
- </Badge> */}
108
- </div>
109
- </div>
110
-
111
- <div>
112
- <h3 className="text-sm font-medium text-gray-600 mb-2">Build Time</h3>
113
- <div className="flex items-center gap-2 min-w-0">
114
- <Clock className="w-4 h-4 text-gray-500 flex-shrink-0" />
115
- {elapsedMs !== null && (
116
- <span className="text-sm flex-shrink-0">
117
- {Math.floor(elapsedMs / 1000)}s
118
- </span>
119
- )}
120
- <span className="text-sm text-gray-500 truncate">
121
- {buildStartedAt
122
- ? `Started ${timeAgo(buildStartedAt)}`
123
- : "waiting..."}
124
- </span>
125
- </div>
126
- </div>
127
-
128
- {/* Version */}
129
- <div>
130
- <h3 className="text-sm font-medium text-gray-600 mb-2">Version</h3>
131
- <div className="flex items-center gap-2 min-w-0">
132
- <Globe className="w-4 h-4 text-gray-500 flex-shrink-0" />
133
- <span className="text-sm break-all">{packageRelease.version}</span>
134
- {/* <Badge variant="default" className="bg-blue-600 text-white text-xs">
135
- Current
136
- </Badge> */}
137
- </div>
138
- </div>
139
-
140
- {/* Outputs */}
141
- <div>
142
- <h3 className="text-sm font-medium text-gray-600 mb-2">Outputs</h3>
143
- <div>
144
- <span className="text-sm text-gray-400">None</span>
145
- </div>
146
- </div>
147
-
148
- {/* Source */}
149
- {/* <div>
150
- <h3 className="text-sm font-medium text-gray-600 mb-2">Source</h3>
151
- <div className="space-y-2">
152
- <div className="flex items-center gap-2">
153
- <GitBranch className="w-4 h-4 text-gray-500" />
154
- <span className="text-sm">main</span>
155
- </div>
156
- <div className="flex items-center gap-2">
157
- <GitCommit className="w-4 h-4 text-gray-500" />
158
- <span className="text-sm text-gray-500">
159
- edfdc67 support empty file creation (#356)
160
- </span>
161
- </div>
162
- </div>
163
- </div> */}
164
- </div>
165
- )
166
- }
@@ -1,79 +0,0 @@
1
- import { Button } from "@/components/ui/button"
2
- import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
3
- import { useRebuildPackageReleaseMutation } from "@/hooks/use-rebuild-package-release-mutation"
4
- import { Github, RefreshCw } from "lucide-react"
5
- import { useParams } from "wouter"
6
- import { DownloadButtonAndMenu } from "../DownloadButtonAndMenu"
7
- import { useGlobalStore } from "@/hooks/use-global-store"
8
- import { useCurrentPackageCircuitJson } from "../ViewPackagePage/hooks/use-current-package-circuit-json"
9
-
10
- export function PackageBuildHeader() {
11
- const { author, packageName } = useParams()
12
- const session = useGlobalStore((s) => s.session)
13
- const { packageRelease } = useCurrentPackageRelease({
14
- include_logs: true,
15
- })
16
- const { mutate: rebuildPackage, isLoading } =
17
- useRebuildPackageReleaseMutation()
18
-
19
- const { circuitJson } = useCurrentPackageCircuitJson()
20
-
21
- return (
22
- <div className="border-b border-gray-200 bg-white px-4 sm:px-6 py-4">
23
- <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 sm:gap-4 container mx-auto max-w-7xl">
24
- <div className="min-w-0 flex-1">
25
- <h1 className="text-xl sm:text-2xl font-semibold flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-2">
26
- <span className="whitespace-nowrap">Package Build</span>
27
- <a
28
- className="bg-gray-100 px-2 py-1 rounded font-mono text-blue-600 text-sm sm:text-base truncate w-fit"
29
- href={`/${author}/${packageName}`}
30
- >
31
- {author}/{packageName}
32
- </a>
33
- </h1>
34
- </div>
35
- <div className="flex items-center gap-2 sm:gap-3 flex-shrink-0">
36
- <Button
37
- variant="outline"
38
- size="sm"
39
- className="border-gray-300 bg-white hover:bg-gray-50 text-xs sm:text-sm"
40
- asChild
41
- >
42
- <a
43
- href="https://github.com/tscircuit/tscircuit.com/issues/new"
44
- target="_blank"
45
- rel="noopener noreferrer"
46
- >
47
- <Github className="w-3 h-3 sm:w-4 sm:h-4 mr-1 sm:mr-2" />
48
- <span className="hidden xs:inline">Report Issue</span>
49
- <span className="xs:hidden">Report</span>
50
- </a>
51
- </Button>
52
- {session?.github_username == author && (
53
- <Button
54
- variant="outline"
55
- size="sm"
56
- className="border-gray-300 bg-white hover:bg-gray-50 text-xs sm:text-sm"
57
- disabled={isLoading || !packageRelease}
58
- onClick={() =>
59
- packageRelease &&
60
- rebuildPackage({
61
- package_release_id: packageRelease.package_release_id,
62
- })
63
- }
64
- >
65
- <RefreshCw className="w-3 h-3 sm:w-4 sm:h-4 mr-1 sm:mr-2" />
66
- {isLoading ? "Rebuilding..." : "Rebuild"}
67
- </Button>
68
- )}
69
- <DownloadButtonAndMenu
70
- offerMultipleImageFormats
71
- circuitJson={circuitJson}
72
- unscopedName={packageName}
73
- author={author}
74
- />
75
- </div>
76
- </div>
77
- </div>
78
- )
79
- }
@@ -1,148 +0,0 @@
1
- import { Input } from "@/components/ui/input"
2
- import { useAxios } from "@/hooks/use-axios"
3
- import { useLocation } from "wouter"
4
- import React, { useState } from "react"
5
- import { useQuery } from "react-query"
6
- import { useApiBaseUrl } from "@/hooks/use-packages-base-api-url"
7
- import { Search } from "lucide-react"
8
- import { Button } from "./ui/button"
9
- import { PackageCardSkeleton } from "./PackageCardSkeleton"
10
- import { PackageCard } from "./PackageCard"
11
-
12
- interface PageSearchComponentProps {
13
- onResultsFetched?: (results: any[]) => void
14
- }
15
-
16
- const EXAMPLE_SEARCHES = ["keyboard", "esp32", "arduino"]
17
-
18
- const PageSearchComponent: React.FC<PageSearchComponentProps> = ({
19
- onResultsFetched,
20
- }) => {
21
- const [location, setLocation] = useLocation()
22
- const axios = useAxios()
23
- const snippetsBaseApiUrl = useApiBaseUrl()
24
-
25
- // Initialize search query directly from URL
26
- const [searchQuery, setSearchQuery] = useState(
27
- () => new URLSearchParams(window.location.search).get("q") ?? "",
28
- )
29
-
30
- const { data: searchResults, isLoading: isLoadingSearchResults } = useQuery(
31
- ["packageSearch", searchQuery],
32
- async () => {
33
- if (!searchQuery) return []
34
- const { data } = await axios.get("/packages/search", {
35
- params: { q: searchQuery },
36
- })
37
- if (onResultsFetched) {
38
- onResultsFetched(data.packages)
39
- }
40
- return data.packages
41
- },
42
- { enabled: Boolean(searchQuery) },
43
- )
44
-
45
- // Update URL while preserving other parameters
46
- const handleSearchChange = (newQuery: string) => {
47
- if (!newQuery.trim()) {
48
- // if empty reset
49
- setSearchQuery("")
50
- const params = new URLSearchParams(window.location.search)
51
- params.delete("q")
52
- const baseUrl = location.split("?")[0]
53
- const newUrl = params.toString()
54
- ? `${baseUrl}?${params.toString()}`
55
- : baseUrl
56
- setLocation(newUrl)
57
- return
58
- }
59
- setSearchQuery(newQuery)
60
- const params = new URLSearchParams(window.location.search)
61
- params.set("q", newQuery)
62
- const baseUrl = location.split("?")[0]
63
- const newUrl = `${baseUrl}?${params.toString()}`
64
-
65
- if (newUrl !== location) {
66
- setLocation(newUrl)
67
- }
68
- }
69
-
70
- return (
71
- <div className="min-h-[calc(100vh-20rem)]">
72
- <div className="mb-6">
73
- <div className="flex flex-col sm:flex-row gap-4 mb-4">
74
- <div className="relative flex-grow">
75
- <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 h-4 w-4" />
76
- <Input
77
- type="search"
78
- placeholder="Search packages..."
79
- className="pl-10"
80
- value={searchQuery}
81
- onChange={(e) => handleSearchChange(e.target.value)}
82
- aria-label="Search packages"
83
- role="searchbox"
84
- />
85
- </div>
86
- </div>
87
- </div>
88
-
89
- {isLoadingSearchResults ? (
90
- <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
91
- {[...Array(6)].map((_, i) => (
92
- <PackageCardSkeleton key={i} />
93
- ))}
94
- </div>
95
- ) : searchResults && searchResults.length > 0 ? (
96
- <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
97
- {searchResults.map((pkg: any) => (
98
- <PackageCard
99
- key={pkg.package_id}
100
- pkg={pkg}
101
- baseUrl={snippetsBaseApiUrl}
102
- showOwner={true}
103
- withLink={true}
104
- className="hover:bg-gray-50"
105
- />
106
- ))}
107
- </div>
108
- ) : searchQuery ? (
109
- <div className="text-center py-12 px-4">
110
- <div className="bg-slate-50 inline-flex rounded-full p-4 mb-4">
111
- <Search className="w-8 h-8 text-slate-400" />
112
- </div>
113
- <h3 className="text-xl font-medium text-slate-900 mb-2">
114
- No Results for "{searchQuery}"
115
- </h3>
116
- <p className="text-slate-500 max-w-md mx-auto mb-6">
117
- Try searching for something else or browse trending packages.
118
- </p>
119
- </div>
120
- ) : (
121
- <div className="text-center py-12 px-4">
122
- <div className="bg-slate-50 inline-flex rounded-full p-4 mb-4">
123
- <Search className="w-8 h-8 text-slate-400" />
124
- </div>
125
- <h3 className="text-xl font-medium text-slate-900 mb-2">
126
- Search for any package above
127
- </h3>
128
- <p className="text-slate-500 max-w-md mx-auto mb-6">
129
- Try searching for:
130
- </p>
131
- <div className="flex gap-2 justify-center flex-wrap">
132
- {EXAMPLE_SEARCHES.map((term) => (
133
- <Button
134
- key={term}
135
- variant="outline"
136
- onClick={() => handleSearchChange(term)}
137
- >
138
- {term}
139
- </Button>
140
- ))}
141
- </div>
142
- </div>
143
- )}
144
- </div>
145
- )
146
- }
147
-
148
- export default PageSearchComponent