@tscircuit/fake-snippets 0.0.1

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 (396) hide show
  1. package/.github/CODEOWNERS +1 -0
  2. package/.github/workflows/bun-formatcheck.yml +26 -0
  3. package/.github/workflows/bun-test.yml +28 -0
  4. package/.github/workflows/bun-typecheck.yml +26 -0
  5. package/.github/workflows/bundle-size-analysis.yml +79 -0
  6. package/.github/workflows/playwright-test.yml +37 -0
  7. package/.github/workflows/stale.yml +40 -0
  8. package/.github/workflows/update-snapshots.yml +49 -0
  9. package/CONTRIBUTING.md +59 -0
  10. package/LICENSE +21 -0
  11. package/README.md +113 -0
  12. package/biome.json +60 -0
  13. package/bun-tests/fake-snippets-api/fixtures/get-circuit-json.ts +148 -0
  14. package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +96 -0
  15. package/bun-tests/fake-snippets-api/fixtures/start-server.ts +44 -0
  16. package/bun-tests/fake-snippets-api/routes/accounts/get_account_balance.test.ts +18 -0
  17. package/bun-tests/fake-snippets-api/routes/health.test.ts +9 -0
  18. package/bun-tests/fake-snippets-api/routes/order_files/get.test.ts +48 -0
  19. package/bun-tests/fake-snippets-api/routes/order_files/upload.test.ts +77 -0
  20. package/bun-tests/fake-snippets-api/routes/orders/create.test.ts +19 -0
  21. package/bun-tests/fake-snippets-api/routes/orders/get.test.ts +38 -0
  22. package/bun-tests/fake-snippets-api/routes/orders/list.test.ts +30 -0
  23. package/bun-tests/fake-snippets-api/routes/orders/update.test.ts +46 -0
  24. package/bun-tests/fake-snippets-api/routes/snippets/add_star.test.ts +114 -0
  25. package/bun-tests/fake-snippets-api/routes/snippets/create.test.ts +28 -0
  26. package/bun-tests/fake-snippets-api/routes/snippets/delete.test.ts +106 -0
  27. package/bun-tests/fake-snippets-api/routes/snippets/download.test.ts +90 -0
  28. package/bun-tests/fake-snippets-api/routes/snippets/generate_from_jlcpcb.test.ts +25 -0
  29. package/bun-tests/fake-snippets-api/routes/snippets/get_image.test.ts +113 -0
  30. package/bun-tests/fake-snippets-api/routes/snippets/images.test.ts +112 -0
  31. package/bun-tests/fake-snippets-api/routes/snippets/list.test.ts +62 -0
  32. package/bun-tests/fake-snippets-api/routes/snippets/list_newest.test.ts +48 -0
  33. package/bun-tests/fake-snippets-api/routes/snippets/list_trending.test.ts +69 -0
  34. package/bun-tests/fake-snippets-api/routes/snippets/remove_star.test.ts +110 -0
  35. package/bun-tests/fake-snippets-api/routes/snippets/search.test.ts +75 -0
  36. package/bun-tests/fake-snippets-api/routes/snippets/star-count.test.ts +44 -0
  37. package/bun-tests/fake-snippets-api/routes/snippets/update.test.ts +116 -0
  38. package/bun-tests/parts-engine.test.ts +18 -0
  39. package/bun.lockb +0 -0
  40. package/bunfig.toml +2 -0
  41. package/components.json +20 -0
  42. package/dist/assets/editor_example_1-1000w.webp +0 -0
  43. package/dist/assets/editor_example_1-1200w.webp +0 -0
  44. package/dist/assets/editor_example_1-1600w.webp +0 -0
  45. package/dist/assets/editor_example_1-2000w.webp +0 -0
  46. package/dist/assets/editor_example_1-400w.webp +0 -0
  47. package/dist/assets/editor_example_1-600w.webp +0 -0
  48. package/dist/assets/editor_example_1-800w.webp +0 -0
  49. package/dist/assets/editor_example_1_more_square-1000w.webp +0 -0
  50. package/dist/assets/editor_example_1_more_square-1200w.webp +0 -0
  51. package/dist/assets/editor_example_1_more_square-1600w.webp +0 -0
  52. package/dist/assets/editor_example_1_more_square-2000w.webp +0 -0
  53. package/dist/assets/editor_example_1_more_square-400w.webp +0 -0
  54. package/dist/assets/editor_example_1_more_square-600w.webp +0 -0
  55. package/dist/assets/editor_example_1_more_square-800w.webp +0 -0
  56. package/dist/assets/editor_example_2-1000w.webp +0 -0
  57. package/dist/assets/editor_example_2-1200w.webp +0 -0
  58. package/dist/assets/editor_example_2-1600w.webp +0 -0
  59. package/dist/assets/editor_example_2-2000w.webp +0 -0
  60. package/dist/assets/editor_example_2-400w.webp +0 -0
  61. package/dist/assets/editor_example_2-600w.webp +0 -0
  62. package/dist/assets/editor_example_2-800w.webp +0 -0
  63. package/dist/assets/example_schematic-1000w.webp +0 -0
  64. package/dist/assets/example_schematic-1200w.webp +0 -0
  65. package/dist/assets/example_schematic-1600w.webp +0 -0
  66. package/dist/assets/example_schematic-2000w.webp +0 -0
  67. package/dist/assets/example_schematic-400w.webp +0 -0
  68. package/dist/assets/example_schematic-600w.webp +0 -0
  69. package/dist/assets/example_schematic-800w.webp +0 -0
  70. package/dist/bundle.js +3270 -0
  71. package/dist/robots.txt +9 -0
  72. package/dist/sitemap.xml +118 -0
  73. package/docs/CIRCUIT_JSON_SOURCE_COMPONENT_OVERVIEW.md +151 -0
  74. package/fake-snippets-api/README.md +6 -0
  75. package/fake-snippets-api/biome.json +47 -0
  76. package/fake-snippets-api/bun.lockb +0 -0
  77. package/fake-snippets-api/lib/db/autoload-dev-snippets.ts +84 -0
  78. package/fake-snippets-api/lib/db/autoload-snippets.json +24 -0
  79. package/fake-snippets-api/lib/db/db-client.ts +343 -0
  80. package/fake-snippets-api/lib/db/schema.ts +112 -0
  81. package/fake-snippets-api/lib/db/seed.ts +1608 -0
  82. package/fake-snippets-api/lib/middleware/with-ctx-error.ts +26 -0
  83. package/fake-snippets-api/lib/middleware/with-db.ts +15 -0
  84. package/fake-snippets-api/lib/middleware/with-error-handling.ts +24 -0
  85. package/fake-snippets-api/lib/middleware/with-optional-session-auth.ts +34 -0
  86. package/fake-snippets-api/lib/middleware/with-request-logging.ts +54 -0
  87. package/fake-snippets-api/lib/middleware/with-session-auth.ts +39 -0
  88. package/fake-snippets-api/lib/middleware/with-winter-spec.ts +24 -0
  89. package/fake-snippets-api/next-env.d.ts +5 -0
  90. package/fake-snippets-api/routes/api/accounts/get.ts +21 -0
  91. package/fake-snippets-api/routes/api/accounts/get_account_balance.ts +22 -0
  92. package/fake-snippets-api/routes/api/accounts/update.ts +32 -0
  93. package/fake-snippets-api/routes/api/ai/[...anyroute].ts +31 -0
  94. package/fake-snippets-api/routes/api/ai.ts +2 -0
  95. package/fake-snippets-api/routes/api/aistream/[...anyroute].ts +65 -0
  96. package/fake-snippets-api/routes/api/health.ts +9 -0
  97. package/fake-snippets-api/routes/api/internal/sessions/create_without_auth.ts +63 -0
  98. package/fake-snippets-api/routes/api/order_files/get.ts +28 -0
  99. package/fake-snippets-api/routes/api/order_files/upload.ts +43 -0
  100. package/fake-snippets-api/routes/api/orders/create.ts +41 -0
  101. package/fake-snippets-api/routes/api/orders/get.ts +28 -0
  102. package/fake-snippets-api/routes/api/orders/list.ts +15 -0
  103. package/fake-snippets-api/routes/api/orders/update.ts +50 -0
  104. package/fake-snippets-api/routes/api/snippets/add_star.ts +42 -0
  105. package/fake-snippets-api/routes/api/snippets/create.ts +55 -0
  106. package/fake-snippets-api/routes/api/snippets/delete.ts +41 -0
  107. package/fake-snippets-api/routes/api/snippets/download.ts +148 -0
  108. package/fake-snippets-api/routes/api/snippets/generate_from_jlcpcb.ts +55 -0
  109. package/fake-snippets-api/routes/api/snippets/get.ts +50 -0
  110. package/fake-snippets-api/routes/api/snippets/get_image.ts +65 -0
  111. package/fake-snippets-api/routes/api/snippets/images/[author]/[snippet_name]/[typeFormat].ts +74 -0
  112. package/fake-snippets-api/routes/api/snippets/list.ts +28 -0
  113. package/fake-snippets-api/routes/api/snippets/list_newest.ts +13 -0
  114. package/fake-snippets-api/routes/api/snippets/list_trending.ts +21 -0
  115. package/fake-snippets-api/routes/api/snippets/remove_star.ts +42 -0
  116. package/fake-snippets-api/routes/api/snippets/search.ts +18 -0
  117. package/fake-snippets-api/routes/api/snippets/update.ts +86 -0
  118. package/favicon.ico +0 -0
  119. package/index.html +23 -0
  120. package/landing.html +23 -0
  121. package/package.json +164 -0
  122. package/playwright-tests/ai-page.spec.ts +19 -0
  123. package/playwright-tests/cmd-click.spec.ts +43 -0
  124. package/playwright-tests/dashboard-page.spec.ts +10 -0
  125. package/playwright-tests/editor-page.spec.ts +15 -0
  126. package/playwright-tests/files-dialog.spec.ts +19 -0
  127. package/playwright-tests/footprint-dialog/footprint-dialog.spec.ts +27 -0
  128. package/playwright-tests/footprint-dialog/footprint-insertion.spec.ts +38 -0
  129. package/playwright-tests/footprint-dialog/footprint-preview.spec.ts +34 -0
  130. package/playwright-tests/footprint-dialog/footprint-selection.spec.ts +29 -0
  131. package/playwright-tests/handle-manual-edits.spec.ts +55 -0
  132. package/playwright-tests/home-page.spec.ts +10 -0
  133. package/playwright-tests/images.spec.ts +17 -0
  134. package/playwright-tests/manual-edits.spec.ts +89 -0
  135. package/playwright-tests/preview-page.spec.ts +14 -0
  136. package/playwright-tests/quickstart-page.spec.ts +10 -0
  137. package/playwright-tests/search-links.spec.ts +21 -0
  138. package/playwright-tests/search.spec.ts +27 -0
  139. package/playwright-tests/snapshots/ai-page.spec.ts-AI-Page-lg.png +0 -0
  140. package/playwright-tests/snapshots/ai-page.spec.ts-AI-Page-md.png +0 -0
  141. package/playwright-tests/snapshots/ai-page.spec.ts-AI-Page-xs.png +0 -0
  142. package/playwright-tests/snapshots/cmd-click.spec.ts-underlined-imports.png +0 -0
  143. package/playwright-tests/snapshots/dashboard-page.spec.ts-Dashboard-page-lg.png +0 -0
  144. package/playwright-tests/snapshots/dashboard-page.spec.ts-Dashboard-page-md.png +0 -0
  145. package/playwright-tests/snapshots/dashboard-page.spec.ts-Dashboard-page-xs.png +0 -0
  146. package/playwright-tests/snapshots/editor-page.spec.ts-editor-with-snippet.png +0 -0
  147. package/playwright-tests/snapshots/error-fallback.spec.ts-error-fallback-lg.png +0 -0
  148. package/playwright-tests/snapshots/error-fallback.spec.ts-error-fallback-md.png +0 -0
  149. package/playwright-tests/snapshots/error-fallback.spec.ts-error-fallback-xs.png +0 -0
  150. package/playwright-tests/snapshots/files-dialog.spec.ts-view-snippet-files.png +0 -0
  151. package/playwright-tests/snapshots/footprint-dialog/footprint-dialog.spec.ts-footprint-preview-lg.png +0 -0
  152. package/playwright-tests/snapshots/footprint-dialog/footprint-dialog.spec.ts-footprint-preview-md.png +0 -0
  153. package/playwright-tests/snapshots/footprint-dialog/footprint-dialog.spec.ts-footprint-preview-xs.png +0 -0
  154. package/playwright-tests/snapshots/footprint-dialog/footprint-insertion.spec.ts-footprint-insertion-lg.png +0 -0
  155. package/playwright-tests/snapshots/footprint-dialog/footprint-insertion.spec.ts-footprint-insertion-md.png +0 -0
  156. package/playwright-tests/snapshots/footprint-dialog/footprint-insertion.spec.ts-footprint-insertion-xs.png +0 -0
  157. package/playwright-tests/snapshots/footprint-dialog/footprint-preview.spec.ts-footprint-preview-lg.png +0 -0
  158. package/playwright-tests/snapshots/footprint-dialog/footprint-preview.spec.ts-footprint-preview-md.png +0 -0
  159. package/playwright-tests/snapshots/footprint-dialog/footprint-preview.spec.ts-footprint-preview-xs.png +0 -0
  160. package/playwright-tests/snapshots/footprint-dialog/footprint-selection.spec.ts-footprint-preview-lg.png +0 -0
  161. package/playwright-tests/snapshots/footprint-dialog/footprint-selection.spec.ts-footprint-preview-md.png +0 -0
  162. package/playwright-tests/snapshots/footprint-dialog/footprint-selection.spec.ts-footprint-preview-xs.png +0 -0
  163. package/playwright-tests/snapshots/handle-manual-edits.spec.ts-handle-manual-edits.png +0 -0
  164. package/playwright-tests/snapshots/home-page.spec.ts-Home-page-lg.png +0 -0
  165. package/playwright-tests/snapshots/home-page.spec.ts-Home-page-md.png +0 -0
  166. package/playwright-tests/snapshots/home-page.spec.ts-Home-page-xs.png +0 -0
  167. package/playwright-tests/snapshots/images.spec.ts-pcb-image.png +0 -0
  168. package/playwright-tests/snapshots/images.spec.ts-schematic-image.png +0 -0
  169. package/playwright-tests/snapshots/manual-edits.spec.ts-editor-manual-edits.png +0 -0
  170. package/playwright-tests/snapshots/manual-edits.spec.ts-manual-edits-view.png +0 -0
  171. package/playwright-tests/snapshots/preview-page.spec.ts-preview-snippet-pcb.png +0 -0
  172. package/playwright-tests/snapshots/preview-page.spec.ts-preview-snippet-schematic.png +0 -0
  173. package/playwright-tests/snapshots/quickstart-page.spec.ts-Quickstart-Pagelg.png +0 -0
  174. package/playwright-tests/snapshots/quickstart-page.spec.ts-Quickstart-Pagemd.png +0 -0
  175. package/playwright-tests/snapshots/quickstart-page.spec.ts-Quickstart-Pagexs.png +0 -0
  176. package/playwright-tests/snapshots/search-links.spec.ts-search-links.png +0 -0
  177. package/playwright-tests/snapshots/search.spec.ts-search-lg.png +0 -0
  178. package/playwright-tests/snapshots/search.spec.ts-search-md.png +0 -0
  179. package/playwright-tests/snapshots/search.spec.ts-search-xs.png +0 -0
  180. package/playwright-tests/snapshots/star.spec.ts-remove-star-button.png +0 -0
  181. package/playwright-tests/snapshots/star.spec.ts-star-button.png +0 -0
  182. package/playwright-tests/snapshots/update-description.spec.ts-update-description.png +0 -0
  183. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-after-lg.png +0 -0
  184. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-after-md.png +0 -0
  185. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-after-xs.png +0 -0
  186. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-before-lg.png +0 -0
  187. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-before-md.png +0 -0
  188. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-before-xs.png +0 -0
  189. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-files.png +0 -0
  190. package/playwright-tests/star.spec.ts +40 -0
  191. package/playwright-tests/update-description.spec.ts +18 -0
  192. package/playwright-tests/view-snippet.spec.ts +35 -0
  193. package/playwright-tests/viewports.ts +5 -0
  194. package/playwright.config.ts +27 -0
  195. package/postcss.config.js +6 -0
  196. package/public/robots.txt +9 -0
  197. package/renovate.json +24 -0
  198. package/scripts/generate-image-sizes.ts +58 -0
  199. package/scripts/generate-sitemap.ts +103 -0
  200. package/scripts/generate_bundle_stats.js +192 -0
  201. package/scripts/snapshot.ts +35 -0
  202. package/src/App.tsx +113 -0
  203. package/src/ContextProviders.tsx +9 -0
  204. package/src/assets/originals/editor_example_1.webp +0 -0
  205. package/src/assets/originals/editor_example_1_more_square.webp +0 -0
  206. package/src/assets/originals/editor_example_2.webp +0 -0
  207. package/src/assets/originals/example_schematic.webp +0 -0
  208. package/src/components/AiChatInterface.tsx +221 -0
  209. package/src/components/AiChatMessage.tsx +86 -0
  210. package/src/components/Analytics.tsx +30 -0
  211. package/src/components/BomTable.tsx +69 -0
  212. package/src/components/ChatInput.tsx +53 -0
  213. package/src/components/CircuitToSvgWithMouseControl.tsx +78 -0
  214. package/src/components/CmdKMenu.tsx +301 -0
  215. package/src/components/CodeAndPreview.tsx +258 -0
  216. package/src/components/CodeEditor.tsx +460 -0
  217. package/src/components/CodeEditorHeader.tsx +160 -0
  218. package/src/components/CreateNewSnippetWithAiHero.tsx +77 -0
  219. package/src/components/DownloadButtonAndMenu.tsx +212 -0
  220. package/src/components/EditorNav.tsx +428 -0
  221. package/src/components/ErrorFallback.tsx +25 -0
  222. package/src/components/ErrorTabContent.tsx +122 -0
  223. package/src/components/FAQ.tsx +113 -0
  224. package/src/components/Footer.tsx +134 -0
  225. package/src/components/Footer2.tsx +100 -0
  226. package/src/components/FootprintDialog.tsx +342 -0
  227. package/src/components/Header.tsx +187 -0
  228. package/src/components/Header2.tsx +135 -0
  229. package/src/components/HeaderDropdown.tsx +83 -0
  230. package/src/components/HeaderLogin.tsx +94 -0
  231. package/src/components/JLCPCBImportDialog.tsx +155 -0
  232. package/src/components/LandingHero.tsx +175 -0
  233. package/src/components/LatestSnippets.tsx +39 -0
  234. package/src/components/OptimizedImage.tsx +96 -0
  235. package/src/components/OrderPreviewContent.tsx +61 -0
  236. package/src/components/ParametersEditor.tsx +140 -0
  237. package/src/components/PcbViewerWithContainerHeight.tsx +47 -0
  238. package/src/components/PrefetchPageLink.tsx +45 -0
  239. package/src/components/PreviewContent.tsx +375 -0
  240. package/src/components/PreviewEmptyState.tsx +16 -0
  241. package/src/components/RunButton.tsx +27 -0
  242. package/src/components/SearchComponent.tsx +163 -0
  243. package/src/components/ShippingInformationForm.tsx +423 -0
  244. package/src/components/SnippetLink.tsx +37 -0
  245. package/src/components/StaticPreviewContent.tsx +89 -0
  246. package/src/components/StaticViewSnippetHeader.tsx +70 -0
  247. package/src/components/StaticViewSnippetSidebar.tsx +100 -0
  248. package/src/components/TableViewer/CircuitJsonTableViewer.tsx +316 -0
  249. package/src/components/TableViewer/ClickableText.tsx +21 -0
  250. package/src/components/TableViewer/HeaderCell.tsx +27 -0
  251. package/src/components/TableViewer/Modal.tsx +39 -0
  252. package/src/components/TrendingSnippetCarousel.tsx +77 -0
  253. package/src/components/TypeBadge.tsx +31 -0
  254. package/src/components/ViewSnippetHeader.tsx +144 -0
  255. package/src/components/ViewSnippetSidebar.tsx +162 -0
  256. package/src/components/dialogs/confirm-delete-snippet-dialog.tsx +80 -0
  257. package/src/components/dialogs/create-order-dialog.tsx +146 -0
  258. package/src/components/dialogs/create-use-dialog.tsx +34 -0
  259. package/src/components/dialogs/edit-description-dialog.tsx +96 -0
  260. package/src/components/dialogs/files-dialog.tsx +70 -0
  261. package/src/components/dialogs/import-snippet-dialog.tsx +84 -0
  262. package/src/components/dialogs/rename-snippet-dialog.tsx +81 -0
  263. package/src/components/dialogs/view-ts-files-dialog.tsx +89 -0
  264. package/src/components/ui/accordion.tsx +55 -0
  265. package/src/components/ui/alert-dialog.tsx +139 -0
  266. package/src/components/ui/alert.tsx +59 -0
  267. package/src/components/ui/aspect-ratio.tsx +5 -0
  268. package/src/components/ui/avatar.tsx +48 -0
  269. package/src/components/ui/badge.tsx +36 -0
  270. package/src/components/ui/breadcrumb.tsx +118 -0
  271. package/src/components/ui/button.tsx +58 -0
  272. package/src/components/ui/calendar.tsx +73 -0
  273. package/src/components/ui/card.tsx +76 -0
  274. package/src/components/ui/carousel.tsx +260 -0
  275. package/src/components/ui/chart.tsx +363 -0
  276. package/src/components/ui/checkbox.tsx +28 -0
  277. package/src/components/ui/collapsible.tsx +9 -0
  278. package/src/components/ui/combobox.tsx +178 -0
  279. package/src/components/ui/command.tsx +151 -0
  280. package/src/components/ui/context-menu.tsx +202 -0
  281. package/src/components/ui/dialog.tsx +120 -0
  282. package/src/components/ui/drawer.tsx +116 -0
  283. package/src/components/ui/dropdown-menu.tsx +203 -0
  284. package/src/components/ui/form.tsx +182 -0
  285. package/src/components/ui/hover-card.tsx +27 -0
  286. package/src/components/ui/input-otp.tsx +69 -0
  287. package/src/components/ui/input.tsx +25 -0
  288. package/src/components/ui/label.tsx +24 -0
  289. package/src/components/ui/menubar.tsx +238 -0
  290. package/src/components/ui/navigation-menu.tsx +129 -0
  291. package/src/components/ui/pagination.tsx +121 -0
  292. package/src/components/ui/popover.tsx +31 -0
  293. package/src/components/ui/progress.tsx +26 -0
  294. package/src/components/ui/radio-group.tsx +42 -0
  295. package/src/components/ui/resizable.tsx +43 -0
  296. package/src/components/ui/scroll-area.tsx +46 -0
  297. package/src/components/ui/searchable-select.tsx +94 -0
  298. package/src/components/ui/select.tsx +162 -0
  299. package/src/components/ui/separator.tsx +29 -0
  300. package/src/components/ui/sheet.tsx +141 -0
  301. package/src/components/ui/skeleton.tsx +18 -0
  302. package/src/components/ui/slider.tsx +26 -0
  303. package/src/components/ui/sonner.tsx +30 -0
  304. package/src/components/ui/switch.tsx +27 -0
  305. package/src/components/ui/table.tsx +120 -0
  306. package/src/components/ui/tabs.tsx +53 -0
  307. package/src/components/ui/textarea.tsx +24 -0
  308. package/src/components/ui/toast.tsx +128 -0
  309. package/src/components/ui/toaster.tsx +33 -0
  310. package/src/components/ui/toggle-group.tsx +59 -0
  311. package/src/components/ui/toggle.tsx +43 -0
  312. package/src/components/ui/tooltip.tsx +28 -0
  313. package/src/entry-server.tsx +12 -0
  314. package/src/hooks/use-account-balance.ts +24 -0
  315. package/src/hooks/use-ai-api.ts +35 -0
  316. package/src/hooks/use-axios.ts +20 -0
  317. package/src/hooks/use-code-completion-ai-api.ts +11 -0
  318. package/src/hooks/use-compiled-tsx.ts +37 -0
  319. package/src/hooks/use-copy-to-clipboard.ts +26 -0
  320. package/src/hooks/use-create-snippet-mutation.ts +62 -0
  321. package/src/hooks/use-current-snippet-id.ts +75 -0
  322. package/src/hooks/use-current-snippet.ts +24 -0
  323. package/src/hooks/use-global-store.ts +33 -0
  324. package/src/hooks/use-is-using-fake-api.ts +3 -0
  325. package/src/hooks/use-run-tsx/construct-circuit.tsx +64 -0
  326. package/src/hooks/use-run-tsx/eval-compiled-js.ts +9 -0
  327. package/src/hooks/use-run-tsx/index.tsx +251 -0
  328. package/src/hooks/use-save-snippet.ts +66 -0
  329. package/src/hooks/use-sign-in.ts +22 -0
  330. package/src/hooks/use-snippet-by-name.ts +25 -0
  331. package/src/hooks/use-snippet.ts +23 -0
  332. package/src/hooks/use-snippets-base-api-url.ts +3 -0
  333. package/src/hooks/use-toast.tsx +208 -0
  334. package/src/hooks/use-typecheck.ts +54 -0
  335. package/src/hooks/use-url-params.ts +31 -0
  336. package/src/hooks/use-warn-user-on-page-change.ts +23 -0
  337. package/src/hooks/useForkSnippetMutation.ts +52 -0
  338. package/src/index.css +21 -0
  339. package/src/lib/__tests__/constants.test.ts +66 -0
  340. package/src/lib/base64ToBytes.ts +5 -0
  341. package/src/lib/bytesToBase64.ts +4 -0
  342. package/src/lib/codemirror/basic-setup.ts +51 -0
  343. package/src/lib/constants.ts +12 -0
  344. package/src/lib/decodeUrlHashToText.ts +15 -0
  345. package/src/lib/defaultCodeForBlankCode.tsx +7 -0
  346. package/src/lib/download-fns/createBlobURL.ts +4 -0
  347. package/src/lib/download-fns/download-assembly-svg.ts +12 -0
  348. package/src/lib/download-fns/download-circuit-json-fn.ts +12 -0
  349. package/src/lib/download-fns/download-dsn-file-fn.ts +12 -0
  350. package/src/lib/download-fns/download-fabrication-files.ts +233 -0
  351. package/src/lib/download-fns/download-gltf.ts +49 -0
  352. package/src/lib/download-fns/download-kicad-files.ts +27 -0
  353. package/src/lib/download-fns/download-readable-netlist.ts +12 -0
  354. package/src/lib/download-fns/download-schematic-svg.ts +12 -0
  355. package/src/lib/download-fns/download-simple-route-json.ts +17 -0
  356. package/src/lib/encodeTextToUrlHash.ts +17 -0
  357. package/src/lib/get-snippet-template.ts +26 -0
  358. package/src/lib/handleManualEditsImport.tsx +65 -0
  359. package/src/lib/jlc-parts-engine.ts +69 -0
  360. package/src/lib/templates/blank-3d-model-template.ts +12 -0
  361. package/src/lib/templates/blank-circuit-board-template.ts +24 -0
  362. package/src/lib/templates/blank-footprint-template.ts +29 -0
  363. package/src/lib/templates/blank-package-template.ts +22 -0
  364. package/src/lib/templates/blinking-led-board-template.ts +63 -0
  365. package/src/lib/templates/manual-edits-template.ts +5 -0
  366. package/src/lib/templates/usb-c-led-flashlight-template.ts +22 -0
  367. package/src/lib/utils/checkIfManualEditsImported.ts +6 -0
  368. package/src/lib/utils/getSyntaxError.ts +13 -0
  369. package/src/lib/utils/index.ts +6 -0
  370. package/src/lib/utils/load-prettier.ts +18 -0
  371. package/src/lib/utils/parseFootprintParams.ts +52 -0
  372. package/src/lib/utils/parseJsonOrNull.ts +8 -0
  373. package/src/lib/utils/pcbManualEditEventHandler.ts +156 -0
  374. package/src/main.tsx +10 -0
  375. package/src/pages/ai.tsx +92 -0
  376. package/src/pages/authorize.tsx +54 -0
  377. package/src/pages/dashboard.tsx +165 -0
  378. package/src/pages/dev-login.tsx +68 -0
  379. package/src/pages/editor.tsx +28 -0
  380. package/src/pages/landing.tsx +236 -0
  381. package/src/pages/my-orders.tsx +54 -0
  382. package/src/pages/newest.tsx +16 -0
  383. package/src/pages/preview.tsx +70 -0
  384. package/src/pages/quickstart.tsx +198 -0
  385. package/src/pages/search.tsx +26 -0
  386. package/src/pages/settings.tsx +25 -0
  387. package/src/pages/user-profile.tsx +97 -0
  388. package/src/pages/view-order.tsx +123 -0
  389. package/src/pages/view-snippet.tsx +149 -0
  390. package/src/prettier.ts +9 -0
  391. package/src/vite-env.d.ts +1 -0
  392. package/tailwind.config.js +47 -0
  393. package/tsconfig.json +30 -0
  394. package/vercel.json +50 -0
  395. package/vite.config.ts +146 -0
  396. package/winterspec.config.ts +6 -0
@@ -0,0 +1,18 @@
1
+ import { withRouteSpec } from "fake-snippets-api/lib/middleware/with-winter-spec"
2
+ import { z } from "zod"
3
+ import { snippetSchema } from "fake-snippets-api/lib/db/schema"
4
+
5
+ export default withRouteSpec({
6
+ methods: ["GET"],
7
+ auth: "none",
8
+ queryParams: z.object({
9
+ q: z.string(),
10
+ }),
11
+ jsonResponse: z.object({
12
+ snippets: z.array(snippetSchema),
13
+ }),
14
+ })(async (req, ctx) => {
15
+ const { q } = req.query
16
+ const snippets = ctx.db.searchSnippets(q)
17
+ return ctx.json({ snippets })
18
+ })
@@ -0,0 +1,86 @@
1
+ import { z } from "zod"
2
+ import { snippetSchema } from "../../../lib/db/schema"
3
+ import { withRouteSpec } from "../../../lib/middleware/with-winter-spec"
4
+
5
+ export default withRouteSpec({
6
+ methods: ["POST"],
7
+ auth: "session",
8
+ jsonBody: z.object({
9
+ snippet_id: z.string(),
10
+ code: z.string().optional(),
11
+ description: z.string().optional(),
12
+ unscoped_name: z.string().optional(),
13
+ dts: z.string().optional(),
14
+ compiled_js: z.string().optional().nullable(),
15
+ circuit_json: z.array(z.record(z.any())).optional().nullable(),
16
+ manual_edits_json_content: z.string().optional().nullable(),
17
+ snippet_type: z.enum(["board", "package", "model", "footprint"]).optional(),
18
+ }),
19
+ jsonResponse: z.object({
20
+ ok: z.boolean(),
21
+ snippet: snippetSchema,
22
+ }),
23
+ })(async (req, ctx) => {
24
+ const {
25
+ snippet_id,
26
+ code,
27
+ description,
28
+ unscoped_name,
29
+ dts,
30
+ compiled_js,
31
+ circuit_json,
32
+ snippet_type,
33
+ manual_edits_json_content,
34
+ } = req.jsonBody
35
+
36
+ const snippetIndex = ctx.db.snippets.findIndex(
37
+ (s) => s.snippet_id === snippet_id,
38
+ )
39
+
40
+ if (snippetIndex === -1) {
41
+ return ctx.error(404, {
42
+ error_code: "snippet_not_found",
43
+ message: "Snippet not found",
44
+ })
45
+ }
46
+
47
+ const snippet = ctx.db.snippets[snippetIndex]
48
+
49
+ if (snippet.owner_name !== ctx.auth.github_username) {
50
+ return ctx.error(403, {
51
+ error_code: "forbidden",
52
+ message: "You don't have permission to update this snippet",
53
+ })
54
+ }
55
+
56
+ const updatedSnippet = ctx.db.updateSnippet(snippet_id, {
57
+ code: code ?? snippet.code,
58
+ description: description ?? snippet.description,
59
+ unscoped_name: unscoped_name ?? snippet.unscoped_name,
60
+ name: unscoped_name
61
+ ? `${ctx.auth.github_username}/${unscoped_name}`
62
+ : snippet.name,
63
+ dts: dts ?? snippet.dts,
64
+ compiled_js: compiled_js !== undefined ? compiled_js : snippet.compiled_js,
65
+ manual_edits_json_content:
66
+ manual_edits_json_content !== undefined
67
+ ? manual_edits_json_content
68
+ : snippet.manual_edits_json_content,
69
+ circuit_json:
70
+ circuit_json !== undefined ? circuit_json : snippet.circuit_json,
71
+ snippet_type: snippet_type ?? snippet.snippet_type,
72
+ updated_at: new Date().toISOString(),
73
+ })
74
+
75
+ if (!updatedSnippet) {
76
+ return ctx.error(500, {
77
+ error_code: "update_failed",
78
+ message: "Failed to update snippet",
79
+ })
80
+ }
81
+
82
+ return ctx.json({
83
+ ok: true,
84
+ snippet: updatedSnippet,
85
+ })
86
+ })
package/favicon.ico ADDED
Binary file
package/index.html ADDED
@@ -0,0 +1,23 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="robots" content="index, follow, NOODP" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <link rel="icon" href="/favicon.ico" type="image/x-icon" sizes="16x16">
8
+ <title>tscircuit - Code Electronics with React</title>
9
+ <meta name="description" content="tscircuit is an open-source electronics design tool that lets you create circuits using React components. Design schematics, generate PCB layouts, export and manufacture PCBs online!" />
10
+ <meta name="keywords" content="electronic design, PCB design, schematic capture, React components, circuit design, electronics CAD, open source EDA" />
11
+ <meta property="og:title" content="tscircuit - Design Electronics with React Components" />
12
+ <meta property="og:description" content="Create electronic circuits using React components. Design schematics, generate PCB layouts, and manufacture custom PCBs with this free open-source tool." />
13
+ <meta property="og:type" content="website" />
14
+ <meta name="twitter:card" content="summary_large_image" />
15
+ <meta name="twitter:title" content="tscircuit - Design Electronics with React Components" />
16
+ <meta name="twitter:description" content="Create electronic circuits using React components. Free open-source electronics design tool." />
17
+ <link rel="canonical" href="https://tscircuit.com" />
18
+ </head>
19
+ <body>
20
+ <div id="root"></div>
21
+ <script type="module" src="/src/main.tsx"></script>
22
+ </body>
23
+ </html>
package/landing.html ADDED
@@ -0,0 +1,23 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="robots" content="index, follow, NOODP" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <link rel="icon" href="/favicon.ico" type="image/x-icon" sizes="16x16">
8
+ <title>tscircuit - Code Electronics with React</title>
9
+ <meta name="description" content="tscircuit is an open-source electronics design tool that lets you create circuits using React components. Design schematics, generate PCB layouts, export and manufacture PCBs online!" />
10
+ <meta name="keywords" content="electronic design, PCB design, schematic capture, React components, circuit design, electronics CAD, open source EDA" />
11
+ <meta property="og:title" content="tscircuit - Design Electronics with React Components" />
12
+ <meta property="og:description" content="Create electronic circuits using React components. Design schematics, generate PCB layouts, and manufacture custom PCBs with this free open-source tool." />
13
+ <meta property="og:type" content="website" />
14
+ <meta name="twitter:card" content="summary_large_image" />
15
+ <meta name="twitter:title" content="tscircuit - Design Electronics with React Components" />
16
+ <meta name="twitter:description" content="Create electronic circuits using React components. Free open-source electronics design tool." />
17
+ <link rel="canonical" href="https://tscircuit.com" />
18
+ </head>
19
+ <body>
20
+ <div id="root"></div>
21
+ <script type="module" src="/src/pages/landing.tsx"></script>
22
+ </body>
23
+ </html>
package/package.json ADDED
@@ -0,0 +1,164 @@
1
+ {
2
+ "name": "@tscircuit/fake-snippets",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/tscircuit/snippets"
8
+ },
9
+ "main": "dist/bundle.js",
10
+ "scripts": {
11
+ "start": "bun run dev",
12
+ "snapshot": "bun scripts/snapshot.ts",
13
+ "playwright": "bunx playwright test",
14
+ "playwright:update": "bunx playwright test --update-snapshots",
15
+ "start:playwright-server": "bun run build:fake-api && vite --port 5177",
16
+ "dev": "bun run build:fake-api && AUTOLOAD_SNIPPETS=true vite",
17
+ "dev:registry": "SNIPPETS_API_URL=http://localhost:3100 vite",
18
+ "build": "bun run generate-images && bun run generate-sitemap && bun run build:fake-api && tsc -b && vite build",
19
+ "preview": "vite preview",
20
+ "format": "biome format --write .",
21
+ "lint": "biome format .",
22
+ "build:fake-api": "winterspec bundle -o dist/bundle.js",
23
+ "generate-images": "bun run scripts/generate-image-sizes.ts",
24
+ "generate-sitemap": "bun run scripts/generate-sitemap.ts"
25
+ },
26
+ "dependencies": {
27
+ "@babel/preset-react": "^7.25.9",
28
+ "@babel/preset-typescript": "^7.26.0",
29
+ "@codemirror/autocomplete": "^6.18.1",
30
+ "@codemirror/lang-javascript": "^6.2.2",
31
+ "@codemirror/lang-json": "^6.0.1",
32
+ "@codemirror/lint": "^6.8.2",
33
+ "@codemirror/state": "^6.4.1",
34
+ "@codemirror/view": "^6.34.1",
35
+ "@hookform/resolvers": "^3.9.0",
36
+ "@radix-ui/react-accordion": "^1.2.0",
37
+ "@radix-ui/react-alert-dialog": "^1.1.1",
38
+ "@radix-ui/react-aspect-ratio": "^1.1.0",
39
+ "@radix-ui/react-avatar": "^1.1.0",
40
+ "@radix-ui/react-checkbox": "^1.1.1",
41
+ "@radix-ui/react-collapsible": "^1.1.0",
42
+ "@radix-ui/react-context-menu": "^2.2.1",
43
+ "@radix-ui/react-dialog": "^1.1.1",
44
+ "@radix-ui/react-dropdown-menu": "^2.1.1",
45
+ "@radix-ui/react-hover-card": "^1.1.1",
46
+ "@radix-ui/react-icons": "^1.3.0",
47
+ "@radix-ui/react-label": "^2.1.0",
48
+ "@radix-ui/react-menubar": "^1.1.1",
49
+ "@radix-ui/react-navigation-menu": "^1.2.0",
50
+ "@radix-ui/react-popover": "^1.1.1",
51
+ "@radix-ui/react-progress": "^1.1.0",
52
+ "@radix-ui/react-radio-group": "^1.2.0",
53
+ "@radix-ui/react-scroll-area": "^1.1.0",
54
+ "@radix-ui/react-select": "^2.1.1",
55
+ "@radix-ui/react-separator": "^1.1.0",
56
+ "@radix-ui/react-slider": "^1.2.0",
57
+ "@radix-ui/react-slot": "^1.1.0",
58
+ "@radix-ui/react-switch": "^1.1.0",
59
+ "@radix-ui/react-tabs": "^1.1.0",
60
+ "@radix-ui/react-toast": "^1.2.1",
61
+ "@radix-ui/react-toggle": "^1.1.0",
62
+ "@radix-ui/react-toggle-group": "^1.1.0",
63
+ "@radix-ui/react-tooltip": "^1.1.2",
64
+ "@tscircuit/3d-viewer": "^0.0.94",
65
+ "@tscircuit/footprinter": "^0.0.99",
66
+ "@tscircuit/layout": "^0.0.29",
67
+ "@tscircuit/math-utils": "^0.0.10",
68
+ "@tscircuit/mm": "^0.0.8",
69
+ "@tscircuit/pcb-viewer": "^1.11.12",
70
+ "@tscircuit/props": "^0.0.129",
71
+ "@tscircuit/schematic-viewer": "^1.4.3",
72
+ "@types/file-saver": "^2.0.7",
73
+ "@types/ms": "^0.7.34",
74
+ "@typescript/ata": "^0.9.7",
75
+ "@valtown/codemirror-codeium": "^1.1.1",
76
+ "@valtown/codemirror-ts": "^2.2.0",
77
+ "@vercel/analytics": "^1.4.1",
78
+ "change-case": "^5.4.4",
79
+ "circuit-json": "^0.0.130",
80
+ "circuit-json-to-bom-csv": "^0.0.6",
81
+ "circuit-json-to-gerber": "^0.0.16",
82
+ "circuit-json-to-pnp-csv": "^0.0.6",
83
+ "circuit-json-to-readable-netlist": "^0.0.5",
84
+ "class-variance-authority": "^0.7.0",
85
+ "clsx": "^2.1.1",
86
+ "cmdk": "^1.0.4",
87
+ "codemirror": "^6.0.1",
88
+ "country-list": "^2.3.0",
89
+ "date-fns": "^4.1.0",
90
+ "dsn-converter": "^0.0.54",
91
+ "easyeda": "^0.0.62",
92
+ "embla-carousel-react": "^8.3.0",
93
+ "extract-codefence": "^0.0.4",
94
+ "fflate": "^0.8.2",
95
+ "file-saver": "^2.0.5",
96
+ "immer": "^10.1.1",
97
+ "input-otp": "^1.2.4",
98
+ "jose": "^5.9.3",
99
+ "jscad-electronics": "^0.0.24",
100
+ "jszip": "^3.10.1",
101
+ "kicad-converter": "^0.0.16",
102
+ "lucide-react": "^0.445.0",
103
+ "ms": "^2.1.3",
104
+ "next-themes": "^0.3.0",
105
+ "posthog-js": "^1.203.2",
106
+ "react-cookie-consent": "^9.0.0",
107
+ "react-day-picker": "8.10.1",
108
+ "react-dom": "^18.3.1",
109
+ "react-helmet": "^6.1.0",
110
+ "react-hook-form": "^7.53.0",
111
+ "react-intersection-observer": "^9.14.1",
112
+ "react-query": "^3.39.3",
113
+ "react-resizable-panels": "^2.1.3",
114
+ "recharts": "^2.12.7",
115
+ "rollup-plugin-visualizer": "^5.12.0",
116
+ "sitemap": "^8.0.0",
117
+ "sonner": "^1.5.0",
118
+ "states-us": "^1.1.1",
119
+ "tailwind-merge": "^2.5.2",
120
+ "tailwindcss-animate": "^1.0.7",
121
+ "use-async-memo": "^1.2.5",
122
+ "use-mouse-matrix-transform": "^1.3.0",
123
+ "vaul": "^0.9.9",
124
+ "vite-plugin-vercel": "^9.0.4",
125
+ "wouter": "^3.3.5"
126
+ },
127
+ "devDependencies": {
128
+ "@anthropic-ai/sdk": "^0.27.3",
129
+ "@babel/standalone": "^7.26.2",
130
+ "@biomejs/biome": "^1.9.2",
131
+ "@playwright/test": "^1.48.0",
132
+ "@tscircuit/core": "^0.0.267",
133
+ "@tscircuit/prompt-benchmarks": "^0.0.20",
134
+ "@types/babel__standalone": "^7.1.7",
135
+ "@types/bun": "^1.1.10",
136
+ "@types/country-list": "^2.1.4",
137
+ "@types/prismjs": "^1.26.4",
138
+ "@types/react": "^18.3.9",
139
+ "@types/react-dom": "^18.3.0",
140
+ "@types/react-helmet": "^6.1.11",
141
+ "@types/sharp": "^0.32.0",
142
+ "@typescript/vfs": "^1.6.0",
143
+ "@vitejs/plugin-react": "^4.3.1",
144
+ "autoprefixer": "^10.4.20",
145
+ "circuit-to-svg": "^0.0.100",
146
+ "globals": "^15.9.0",
147
+ "postcss": "^8.4.47",
148
+ "prismjs": "^1.29.0",
149
+ "prompts": "^2.4.2",
150
+ "react": "^18.3.1",
151
+ "redaxios": "^0.5.1",
152
+ "sharp": "^0.33.5",
153
+ "tailwindcss": "^3.4.13",
154
+ "terser": "^5.27.0",
155
+ "tsup": "^8.3.5",
156
+ "typescript": "^5.6.3",
157
+ "vite": "^5.4.8",
158
+ "vite-plugin-image-optimizer": "^1.1.8",
159
+ "winterspec": "^0.0.94",
160
+ "zod": "^3.23.8",
161
+ "zustand": "^4.5.5",
162
+ "zustand-hoist": "^2.0.1"
163
+ }
164
+ }
@@ -0,0 +1,19 @@
1
+ import { test, expect } from "@playwright/test"
2
+ import { viewports } from "./viewports"
3
+
4
+ for (const [size, viewport] of Object.entries(viewports)) {
5
+ test(`AI Page on ${size} screen`, async ({ page }) => {
6
+ await page.setViewportSize(viewport)
7
+ await page.goto("http://127.0.0.1:5177/ai")
8
+
9
+ // it is only working for desktop beacuse fake testuser login is not appearing for mobile
10
+
11
+ // await page.goto("http://127.0.0.1:5177");
12
+ // await page.click("text='Fake testuser Login'");
13
+ // await page.waitForSelector(".login-avatar");
14
+ // await page.click(".header-button[href='/ai']");
15
+ // await page.waitForSelector("text='Submit a prompt to get started!'");
16
+
17
+ await expect(page).toHaveScreenshot(`AI-Page-${size}.png`)
18
+ })
19
+ }
@@ -0,0 +1,43 @@
1
+ import { test, expect } from "@playwright/test"
2
+
3
+ test("Editor handles imports with underlining and cmd+click", async ({
4
+ page,
5
+ }) => {
6
+ await page.goto("http://127.0.0.1:5177/editor?snippet_id=snippet_5")
7
+
8
+ await page.waitForLoadState("networkidle")
9
+
10
+ // Wait for and verify the underlined import
11
+ const underlinedText = await page.locator(".cm-underline")
12
+ await expect(underlinedText).toBeVisible()
13
+
14
+ // Verify the styling matches our expectations
15
+ const styles = await underlinedText.evaluate((el) => {
16
+ const computed = window.getComputedStyle(el)
17
+ return {
18
+ textDecoration: computed.textDecoration,
19
+ cursor: computed.cursor,
20
+ }
21
+ })
22
+
23
+ expect(styles.textDecoration).toContain("underline")
24
+ expect(styles.cursor).toBe("pointer")
25
+
26
+ // Test cmd+click behavior
27
+ const popupPromise = page.waitForEvent("popup")
28
+ await underlinedText.click({
29
+ modifiers: process.platform === "darwin" ? ["Meta"] : ["Control"],
30
+ })
31
+
32
+ // Verify new tab opens with correct URL
33
+ const popup = await popupPromise
34
+ const popupUrl = popup.url()
35
+
36
+ // URL validation
37
+ expect(popupUrl).toMatch(
38
+ /^http:\/\/127\.0\.0\.1:5177\/[a-zA-Z0-9-]+\/[a-zA-Z0-9-]+$/,
39
+ )
40
+
41
+ // Take a snapshot of the editor showing underlined imports
42
+ await expect(page).toHaveScreenshot("underlined-imports.png")
43
+ })
@@ -0,0 +1,10 @@
1
+ import { test, expect } from "@playwright/test"
2
+ import { viewports } from "./viewports"
3
+
4
+ for (const [size, viewport] of Object.entries(viewports)) {
5
+ test(`Dashboard Page on ${size} screen`, async ({ page }) => {
6
+ await page.setViewportSize(viewport)
7
+ await page.goto("http://127.0.0.1:5177/dashboard")
8
+ await expect(page).toHaveScreenshot(`Dashboard-page-${size}.png`)
9
+ })
10
+ }
@@ -0,0 +1,15 @@
1
+ import { test, expect } from "@playwright/test"
2
+ import { viewports } from "./viewports"
3
+
4
+ test("Editor loads snippet correctly", async ({ page }) => {
5
+ await page.goto("http://127.0.0.1:5177/editor?snippet_id=snippet_5")
6
+
7
+ // Wait for network requests to complete
8
+ await page.waitForLoadState("networkidle")
9
+
10
+ // Check for specific text that should be present
11
+ await expect(page.getByText("SquareWaveModule")).toBeVisible()
12
+
13
+ // Take a snapshot
14
+ await expect(page).toHaveScreenshot("editor-with-snippet.png")
15
+ })
@@ -0,0 +1,19 @@
1
+ // files-dialog.spec.js
2
+ import { test, expect } from "@playwright/test"
3
+
4
+ test("files dialog", async ({ page }) => {
5
+ // Wait for network requests during navigation
6
+ await Promise.all([page.goto("http://127.0.0.1:5177/testuser/my-test-board")])
7
+
8
+ // Wait for run button and files tab to be visible
9
+ await page.waitForSelector(".run-button", { state: "visible" })
10
+ const filesTab = await page.waitForSelector('span:has-text("Files")', {
11
+ state: "visible",
12
+ })
13
+
14
+ // Click and wait for any animations or state changes
15
+ await filesTab.click()
16
+ await page.getByLabel("Files").click()
17
+
18
+ await expect(page).toHaveScreenshot(`view-snippet-files.png`)
19
+ })
@@ -0,0 +1,27 @@
1
+ import { test, expect } from "@playwright/test"
2
+ import { viewports } from "../viewports"
3
+
4
+ for (const [size, viewport] of Object.entries(viewports)) {
5
+ test.describe(`FootprintDialog tests - ${size} viewport`, () => {
6
+ let isMobileOrTablet: boolean
7
+
8
+ test.beforeEach(async ({ page }) => {
9
+ await page.setViewportSize(viewport)
10
+ await page.goto("http://127.0.0.1:5177/editor")
11
+ await page.waitForSelector("button.run-button")
12
+ isMobileOrTablet = page.viewportSize()?.width! <= 768
13
+ })
14
+
15
+ test("opens footprint dialog and shows preview", async ({ page }) => {
16
+ if (isMobileOrTablet) {
17
+ await page.click('button:has-text("Show Code")')
18
+ await page.waitForSelector('button:has-text("Show Preview")')
19
+ }
20
+ await page.click('button:has-text("Insert")')
21
+ await page.click("text=Chip")
22
+ await expect(page.getByRole("dialog")).toBeVisible()
23
+ await expect(page.getByRole("heading", { name: "Insert" })).toBeVisible()
24
+ await expect(page).toHaveScreenshot(`footprint-preview-${size}.png`)
25
+ })
26
+ })
27
+ }
@@ -0,0 +1,38 @@
1
+ import { test, expect } from "@playwright/test"
2
+ import { viewports } from "../viewports"
3
+
4
+ for (const [size, viewport] of Object.entries(viewports)) {
5
+ test.describe(`Footprint Insertion tests - ${size} viewport`, () => {
6
+ let isMobileOrTablet: boolean
7
+
8
+ test.beforeEach(async ({ page }) => {
9
+ await page.setViewportSize(viewport)
10
+ await page.goto("http://127.0.0.1:5177/editor")
11
+ // await page.waitForLoadState("networkidle")
12
+ await page.waitForSelector("button.run-button")
13
+ isMobileOrTablet = page.viewportSize()?.width! <= 768
14
+ })
15
+
16
+ test("inserts footprint into code", async ({ page }) => {
17
+ if (isMobileOrTablet) {
18
+ await page.click('button:has-text("Show Code")')
19
+ }
20
+ await page.click('button:has-text("Insert")')
21
+ await page.click("text=Chip")
22
+ await page.fill(
23
+ 'input[placeholder="Enter chip name (e.g., U1)..."]',
24
+ "U1",
25
+ )
26
+ await page.getByRole("combobox").click()
27
+ await page.getByRole("option", { name: "ms012" }).click()
28
+ await page.click('button:has-text("Insert Footprint")')
29
+ await page.waitForSelector('[role="dialog"]', {
30
+ state: "hidden",
31
+ timeout: 5000,
32
+ })
33
+ await expect(page.locator(".cm-content")).toContainText("<chip")
34
+ await expect(page.locator(".cm-content")).toContainText('name="U1"')
35
+ await expect(page).toHaveScreenshot(`footprint-insertion-${size}.png`)
36
+ })
37
+ })
38
+ }
@@ -0,0 +1,34 @@
1
+ import { test, expect } from "@playwright/test"
2
+ import { viewports } from "../viewports"
3
+
4
+ for (const [size, viewport] of Object.entries(viewports)) {
5
+ test.describe(`Footprint Preview tests - ${size} viewport`, () => {
6
+ let isMobileOrTablet: boolean
7
+
8
+ test.beforeEach(async ({ page }) => {
9
+ await page.setViewportSize(viewport)
10
+ await page.goto("http://127.0.0.1:5177/editor")
11
+ await page.waitForSelector("button.run-button")
12
+ isMobileOrTablet = page.viewportSize()?.width! <= 768
13
+ })
14
+
15
+ test("parameter controls update preview", async ({ page }) => {
16
+ if (isMobileOrTablet) {
17
+ await page.click('button:has-text("Show Code")')
18
+ }
19
+ await page.click('button:has-text("Insert")')
20
+ await page.click("text=Chip")
21
+ await expect(page.getByRole("dialog")).toBeVisible()
22
+ await page.getByRole("combobox").click()
23
+ await page.getByRole("option", { name: "dip" }).click()
24
+ await page.fill('label:has-text("Number of Pins") + input', "16")
25
+ const previewContainer = page.locator(".rounded-xl.overflow-hidden svg")
26
+ const initialPreview = await previewContainer.innerHTML()
27
+ await page.fill('label:has-text("Number of Pins") + input', "22")
28
+ await page.waitForTimeout(500)
29
+ const updatedPreview = await previewContainer.innerHTML()
30
+ expect(initialPreview).not.toEqual(updatedPreview)
31
+ await expect(page).toHaveScreenshot(`footprint-preview-${size}.png`)
32
+ })
33
+ })
34
+ }
@@ -0,0 +1,29 @@
1
+ import { test, expect } from "@playwright/test"
2
+ import { viewports } from "../viewports"
3
+
4
+ for (const [size, viewport] of Object.entries(viewports)) {
5
+ test.describe(`Footprint Selection tests - ${size} viewport`, () => {
6
+ let isMobileOrTablet: boolean
7
+
8
+ test.beforeEach(async ({ page }) => {
9
+ await page.setViewportSize(viewport)
10
+ await page.goto("http://127.0.0.1:5177/editor")
11
+ await page.waitForSelector("button.run-button")
12
+ isMobileOrTablet = page.viewportSize()?.width! <= 768
13
+ })
14
+
15
+ test("footprint selection and preview updates", async ({ page }) => {
16
+ if (isMobileOrTablet) {
17
+ await page.click('button:has-text("Show Code")')
18
+ }
19
+ await page.click('button:has-text("Insert")')
20
+ await page.click("text=Chip")
21
+ await page.getByRole("combobox").click()
22
+ await page.getByRole("option", { name: "ms012" }).click()
23
+ await expect(
24
+ page.locator(".rounded-xl.overflow-hidden svg"),
25
+ ).toBeVisible()
26
+ await expect(page).toHaveScreenshot(`footprint-preview-${size}.png`)
27
+ })
28
+ })
29
+ }
@@ -0,0 +1,55 @@
1
+ import { test, expect } from "@playwright/test"
2
+
3
+ test("Handle manual edits test", async ({ page }) => {
4
+ await page.goto("http://127.0.0.1:5177/editor?snippet_id=snippet_3")
5
+
6
+ await page.getByRole("button", { name: "Log in" }).click()
7
+
8
+ const combobox = page.getByRole("combobox")
9
+ await combobox.waitFor({ state: "visible" })
10
+ await combobox.click()
11
+
12
+ const manualEditsFile = page.getByText("manual-edits.json", { exact: true })
13
+ await manualEditsFile.waitFor({ state: "visible" })
14
+ await manualEditsFile.click()
15
+
16
+ await page.locator("div").filter({ hasText: /^91›$/ }).first().click()
17
+
18
+ const pcbPlacementsData = `{
19
+ "pcb_placements": [
20
+ {
21
+ "selector": "U1",
22
+ "center": {
23
+ "x": -26.03275345576554,
24
+ "y": 23.735745797903878
25
+ },
26
+ "relative_to": "group_center",
27
+ "_edit_event_id": "0.5072961258141278"
28
+ }
29
+ ],
30
+ "edit_events": [],
31
+ "manual_trace_hints": []
32
+ }`
33
+
34
+ await page.keyboard.type(pcbPlacementsData)
35
+
36
+ await combobox.click()
37
+
38
+ const indexFile = page.getByText("index.tsx", { exact: true })
39
+ await indexFile.waitFor({ state: "visible" })
40
+ await indexFile.click()
41
+
42
+ await page.getByRole("button", { name: "Error" }).click()
43
+ await page
44
+ .getByRole("menuitem", { name: "Manual edits exist but have" })
45
+ .click()
46
+ await page.waitForTimeout(500)
47
+
48
+ const runButton = page.getByRole("button", { name: "Run", exact: true })
49
+ await runButton.waitFor({ state: "visible" })
50
+ await runButton.click()
51
+
52
+ await page.waitForTimeout(2000)
53
+
54
+ await expect(page).toHaveScreenshot("handle-manual-edits.png")
55
+ })
@@ -0,0 +1,10 @@
1
+ import { test, expect } from "@playwright/test"
2
+ import { viewports } from "./viewports"
3
+
4
+ for (const [size, viewport] of Object.entries(viewports)) {
5
+ test(`Home Page on ${size} screen`, async ({ page }) => {
6
+ await page.setViewportSize(viewport)
7
+ await page.goto("http://127.0.0.1:5177")
8
+ await expect(page).toHaveScreenshot(`Home-page-${size}.png`)
9
+ })
10
+ }
@@ -0,0 +1,17 @@
1
+ import { test, expect } from "@playwright/test"
2
+
3
+ test(`Pcb Image`, async ({ page }) => {
4
+ await page.goto(
5
+ "http://127.0.0.1:5177/api/snippets/images/testuser/my-test-board/pcb.svg",
6
+ )
7
+ await page.waitForLoadState("networkidle")
8
+ await expect(page).toHaveScreenshot(`pcb-image.png`)
9
+ })
10
+
11
+ test(`Schematic Image`, async ({ page }) => {
12
+ await page.goto(
13
+ "http://127.0.0.1:5177/api/snippets/images/testuser/my-test-board/schematic.svg",
14
+ )
15
+ await page.waitForLoadState("networkidle")
16
+ await expect(page).toHaveScreenshot(`schematic-image.png`)
17
+ })