@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,89 @@
1
+ import React from "react"
2
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
3
+ import { Button } from "@/components/ui/button"
4
+ import { Share, PlayIcon, Download, EllipsisIcon } from "lucide-react"
5
+ import { Skeleton } from "@/components/ui/skeleton"
6
+
7
+ const SkeletonContent = () => (
8
+ <div className="h-full p-4 space-y-4">
9
+ <Skeleton className="h-10 w-full" />
10
+ <Skeleton className="h-10 w-full" />
11
+ <div className="space-y-2">
12
+ <Skeleton className="h-4 w-full" />
13
+ <Skeleton className="h-4 w-3/4" />
14
+ <Skeleton className="h-4 w-1/2" />
15
+ </div>
16
+ <div className="space-y-2 mt-4">
17
+ <Skeleton className="h-4 w-full" />
18
+ <Skeleton className="h-4 w-3/4" />
19
+ <Skeleton className="h-4 w-1/2" />
20
+ </div>
21
+ </div>
22
+ )
23
+
24
+ export default function StaticPreviewLoading() {
25
+ return (
26
+ <div className="flex flex-col relative h-full">
27
+ <div className="md:sticky md:top-2">
28
+ <Tabs defaultValue="code" className="flex-grow flex flex-col">
29
+ <div className="p-4 border-b border-gray-200 flex items-center gap-2">
30
+ <Button
31
+ variant="outline"
32
+ size="sm"
33
+ className="h-6 px-2 text-xs loading-placeholder"
34
+ disabled
35
+ aria-label="Loading placeholder"
36
+ >
37
+ <Share className="mr-1 h-3 w-3" />
38
+ Copy URL
39
+ </Button>
40
+ <Button
41
+ variant="ghost"
42
+ size="sm"
43
+ className="px-2 text-xs loading-placeholder"
44
+ disabled
45
+ aria-label="Loading placeholder"
46
+ >
47
+ <Download className="mr-1 h-3 w-3" />
48
+ Download
49
+ </Button>
50
+ <div className="flex-grow" />
51
+ <Button
52
+ disabled
53
+ className="bg-blue-600 hover:bg-blue-500 cursor-not-allowed loading-placeholder"
54
+ aria-label="Loading placeholder"
55
+ >
56
+ Run
57
+ <PlayIcon className="w-3 h-3 ml-2" />
58
+ </Button>
59
+ <TabsList>
60
+ <TabsTrigger value="code">Code</TabsTrigger>
61
+ <TabsTrigger value="pcb" className="whitespace-nowrap">
62
+ PCB
63
+ </TabsTrigger>
64
+ <TabsTrigger value="schematic" className="whitespace-nowrap">
65
+ Schematic
66
+ </TabsTrigger>
67
+ <TabsTrigger value="cad">3D</TabsTrigger>
68
+ <div className="whitespace-nowrap p-2 mr-1 cursor-pointer relative">
69
+ <EllipsisIcon className="w-4 h-4" />
70
+ </div>
71
+ </TabsList>
72
+ </div>
73
+ <TabsContent value="code" className="flex-grow overflow-hidden">
74
+ <SkeletonContent />
75
+ </TabsContent>
76
+ <TabsContent value="pcb" className="h-[500px]">
77
+ <SkeletonContent />
78
+ </TabsContent>
79
+ <TabsContent value="schematic" className="h-[500px]">
80
+ <SkeletonContent />
81
+ </TabsContent>
82
+ <TabsContent value="cad" className="h-[500px]">
83
+ <SkeletonContent />
84
+ </TabsContent>
85
+ </Tabs>
86
+ </div>
87
+ </div>
88
+ )
89
+ }
@@ -0,0 +1,70 @@
1
+ import React from "react"
2
+ import { TypeBadge } from "@/components/TypeBadge"
3
+ import { Button } from "@/components/ui/button"
4
+ import { ChevronLeft, Eye, GitFork, Star } from "lucide-react"
5
+ import { Link } from "wouter"
6
+
7
+ export default function StaticViewSnippetHeader({
8
+ author,
9
+ snippetName,
10
+ }: {
11
+ author: string
12
+ snippetName: string
13
+ }) {
14
+ const snippet_data = {
15
+ owner_name: author,
16
+ unscoped_name: snippetName,
17
+ //sample values
18
+ snippet_type: "board",
19
+ is_starred: false,
20
+ star_count: 0,
21
+ }
22
+
23
+ return (
24
+ <header className="bg-white border-b border-gray-200 py-4 px-6">
25
+ <div className="flex items-center justify-between">
26
+ <div className="flex items-center">
27
+ <h1 className="text-xl font-bold mr-2">
28
+ <Link
29
+ href={`/${snippet_data.owner_name}`}
30
+ className="text-blue-600"
31
+ >
32
+ {snippet_data.owner_name}
33
+ </Link>
34
+ <span className="px-1 text-gray-500">/</span>
35
+ <Link
36
+ className="text-blue-600"
37
+ href={`/${snippet_data.owner_name}/${snippet_data.unscoped_name}`}
38
+ >
39
+ {snippet_data.unscoped_name}
40
+ </Link>
41
+ </h1>
42
+ {snippet_data.snippet_type && (
43
+ <TypeBadge type={snippet_data.snippet_type} />
44
+ )}
45
+ </div>
46
+ <div className="flex items-center space-x-2">
47
+ <Button
48
+ size="sm"
49
+ disabled
50
+ aria-label="Loading placeholder"
51
+ className="loading-placeholder"
52
+ >
53
+ <Star className="w-4 h-4 mr-2" />
54
+ Star
55
+ </Button>
56
+
57
+ <Button
58
+ size="sm"
59
+ disabled
60
+ aria-label="Loading placeholder"
61
+ className="loading-placeholder"
62
+ >
63
+ <GitFork className="w-4 h-4 mr-2" />
64
+ Fork
65
+ </Button>
66
+ </div>
67
+ </div>
68
+ </header>
69
+ )
70
+ }
@@ -0,0 +1,100 @@
1
+ import React from "react"
2
+ import { cn } from "@/lib/utils"
3
+ import { Code, Bot, GitFork, AtSign, Package, Clock, File } from "lucide-react"
4
+ import { Skeleton } from "./ui/skeleton"
5
+
6
+ export default function StaticViewSnippetSidebar({
7
+ className,
8
+ }: {
9
+ className?: string
10
+ }) {
11
+ const sidebarItems = [
12
+ {
13
+ icon: <Code className="w-5 h-5" />,
14
+ label: "Edit Code",
15
+ href: "#",
16
+ },
17
+ {
18
+ icon: <Bot className="w-5 h-5" />,
19
+ label: "Edit with AI",
20
+ badge: "AI",
21
+ href: "#",
22
+ },
23
+ {
24
+ icon: <GitFork className="w-5 h-5" />,
25
+ label: "Forks",
26
+ notImplemented: true,
27
+ },
28
+ {
29
+ icon: <AtSign className="w-5 h-5" />,
30
+ label: "References",
31
+ notImplemented: true,
32
+ },
33
+ {
34
+ icon: <Package className="w-5 h-5" />,
35
+ label: "Dependencies",
36
+ notImplemented: true,
37
+ },
38
+ {
39
+ icon: <Clock className="w-5 h-5" />,
40
+ label: "Versions",
41
+ notImplemented: true,
42
+ },
43
+ {
44
+ icon: <File className="w-5 h-5" />,
45
+ label: "Files",
46
+ href: "#",
47
+ },
48
+ ]
49
+
50
+ return (
51
+ <div
52
+ className={cn(
53
+ "w-64 h-full bg-gray-100 text-gray-700 flex flex-col flex-shrink-0",
54
+ "hidden sm:block h-screen sticky top-0",
55
+ className,
56
+ )}
57
+ >
58
+ <nav className="flex-grow overflow-y-auto">
59
+ <ul className="p-2 space-y-2">
60
+ {sidebarItems.map((item, index) => (
61
+ <li key={index}>
62
+ <a
63
+ href={item.href ?? "#"}
64
+ className="flex items-center gap-3 px-2 py-1.5 hover:bg-gray-200 rounded-md disabled opacity-50 cursor-not-allowed"
65
+ >
66
+ {item.icon}
67
+ <span className="text-sm">{item.label}</span>
68
+ {item.badge && (
69
+ <span className="ml-auto bg-blue-500 text-white text-xs px-1.5 py-0.5 rounded">
70
+ {item.badge}
71
+ </span>
72
+ )}
73
+ </a>
74
+ </li>
75
+ ))}
76
+ </ul>
77
+ </nav>
78
+ <div className="p-4 border-t border-gray-200 space-y-4">
79
+ <div className="space-y-1">
80
+ <div className="text-xs font-medium">Copy embed code</div>
81
+ <div className="text-[0.5em] p-2 rounded-sm bg-blue-50 border border-blue-200 cursor-pointer font-mono whitespace-nowrap overflow-hidden text-ellipsis">
82
+ <Skeleton className="h-4 w-full rounded-sm" />
83
+ </div>
84
+ </div>
85
+ <div className="space-y-1">
86
+ <div className="text-xs font-medium">Copy import code</div>
87
+ <div className="text-[0.5em] p-2 rounded-sm bg-blue-50 border border-blue-200 cursor-pointer font-mono whitespace-nowrap overflow-hidden text-ellipsis">
88
+ <Skeleton className="h-4 w-full rounded-sm" />
89
+ </div>
90
+ </div>
91
+ <div className="space-y-1">
92
+ <div className="text-xs font-medium">Copy install command</div>
93
+ <div className="text-[0.5em] p-2 rounded-sm bg-blue-50 border border-blue-200 cursor-pointer font-mono whitespace-nowrap overflow-hidden text-ellipsis">
94
+ <Skeleton className="h-4 w-full rounded-sm" />
95
+ </div>
96
+ </div>
97
+ </div>
98
+ </div>
99
+ )
100
+ }
@@ -0,0 +1,316 @@
1
+ // CircuitJsonTableViewer.tsx
2
+ import React, { useReducer, useState } from "react"
3
+ import { ClickableText } from "./ClickableText"
4
+ import { HeaderCell } from "./HeaderCell"
5
+ import Modal from "./Modal"
6
+
7
+ type Filters = {
8
+ component_type_filter?:
9
+ | "any"
10
+ | "source"
11
+ | "source/pcb"
12
+ | "source/schematic"
13
+ | string
14
+ id_search?: string
15
+ name_search?: string
16
+ selector_search?: string
17
+ focused_id?: string
18
+ }
19
+
20
+ type CommonProps = { name?: string; type: string }
21
+
22
+ type ModalState =
23
+ | { open: false; element?: never }
24
+ | { open: true; element: Element; title: string }
25
+
26
+ interface Element {
27
+ [key: string]: any
28
+ type: string
29
+ name?: string
30
+ }
31
+
32
+ interface ProcessedElement extends CommonProps {
33
+ primary_id: string
34
+ other_ids: { [key: string]: string }
35
+ selector_path?: string
36
+ _og_elm: Element
37
+ }
38
+
39
+ interface Column {
40
+ key: string
41
+ name: string
42
+ renderCell?: (row: ProcessedElement) => React.ReactNode
43
+ renderHeaderCell?: (col: Column) => React.ReactNode
44
+ }
45
+
46
+ export const CircuitJsonTableViewer: React.FC<{ elements: Element[] }> = ({
47
+ elements,
48
+ }) => {
49
+ const [modal, setModal] = useState<ModalState>({ open: false })
50
+ const [filters, setFilter] = useReducer(
51
+ (s: Filters, a: Filters) => ({
52
+ ...s,
53
+ ...a,
54
+ }),
55
+ {},
56
+ )
57
+
58
+ const element_types = [...new Set(elements.map((e) => e.type))]
59
+
60
+ // Process elements to separate primary and non-primary ids
61
+ const elements2: ProcessedElement[] = elements.map((e) => {
62
+ const primary_id = e[`${e.type}_id`]
63
+
64
+ const other_ids = Object.fromEntries(
65
+ Object.entries(e).filter(([k]) => {
66
+ if (k === `${e.type}_id`) return false
67
+ if (!k.endsWith("_id")) return false
68
+ return true
69
+ }),
70
+ ) as { [key: string]: string }
71
+
72
+ const other_props: CommonProps = Object.fromEntries(
73
+ Object.entries(e).filter(([k]) => !k.endsWith("_id")),
74
+ ) as CommonProps
75
+
76
+ return {
77
+ primary_id,
78
+ other_ids,
79
+ ...other_props,
80
+ _og_elm: e,
81
+ }
82
+ })
83
+
84
+ const elements3 = elements2.map((e) => {
85
+ let selector_path = ""
86
+
87
+ const getSelectorPath = (e2: ProcessedElement): string => {
88
+ const parent_key = Object.keys(e2.other_ids).find((k) =>
89
+ k.startsWith("source_"),
90
+ )
91
+ if (!parent_key) return `.${e2.name}`
92
+ const parent_type = parent_key.slice(0, -3) // trim "_id"
93
+
94
+ const parent = elements2.find(
95
+ (p) =>
96
+ p.type === parent_type && p.primary_id === e2.other_ids[parent_key],
97
+ )
98
+
99
+ if (!parent) return `??? > .${e2.name}`
100
+
101
+ if (!("name" in parent)) return `#${parent.primary_id} > .${e2.name}`
102
+
103
+ return `${getSelectorPath(parent)} > .${e2.name}`
104
+ }
105
+
106
+ if ("name" in e) {
107
+ selector_path = getSelectorPath(e)
108
+ }
109
+
110
+ return {
111
+ ...e,
112
+ selector_path,
113
+ }
114
+ })
115
+
116
+ const columns: Column[] = [
117
+ {
118
+ key: "primary_id",
119
+ name: "primary_id",
120
+ renderCell: (row: ProcessedElement) => (
121
+ <div className="flex items-center">
122
+ <ClickableText
123
+ text={row.primary_id}
124
+ onClick={() =>
125
+ setFilter({
126
+ focused_id: row.primary_id,
127
+ id_search: undefined,
128
+ selector_search: undefined,
129
+ })
130
+ }
131
+ />
132
+ <span className="flex-grow" />
133
+ <ClickableText
134
+ text="(JSON)"
135
+ onClick={() =>
136
+ setModal({
137
+ open: true,
138
+ element: row._og_elm,
139
+ title: row.primary_id,
140
+ })
141
+ }
142
+ />
143
+ </div>
144
+ ),
145
+ renderHeaderCell: (col: Column) => (
146
+ <HeaderCell
147
+ column={col}
148
+ onTextChange={(v) => setFilter({ id_search: v })}
149
+ field={
150
+ !filters.focused_id
151
+ ? undefined
152
+ : () => (
153
+ <div>
154
+ Focus:{" "}
155
+ <span className="underline">{filters.focused_id}</span>
156
+ <ClickableText
157
+ text="(unfocus)"
158
+ onClick={() => setFilter({ focused_id: undefined })}
159
+ />
160
+ </div>
161
+ )
162
+ }
163
+ />
164
+ ),
165
+ },
166
+ {
167
+ key: "type",
168
+ name: "type",
169
+ renderHeaderCell: (col: Column) => (
170
+ <HeaderCell
171
+ column={col}
172
+ field={() => (
173
+ <select
174
+ onChange={(e) =>
175
+ setFilter({ component_type_filter: e.target.value })
176
+ }
177
+ className="border rounded p-1 w-full"
178
+ >
179
+ <option key="any" value="any">
180
+ any
181
+ </option>
182
+ <option key="source" value="source">
183
+ source
184
+ </option>
185
+ <option key="source/pcb" value="source/pcb">
186
+ source/pcb
187
+ </option>
188
+ <option key="source/schematic" value="source/schematic">
189
+ source/schematic
190
+ </option>
191
+ {element_types.map((type) => (
192
+ <option key={type} value={type}>
193
+ {type}
194
+ </option>
195
+ ))}
196
+ </select>
197
+ )}
198
+ />
199
+ ),
200
+ },
201
+ {
202
+ key: "name",
203
+ name: "name",
204
+ renderHeaderCell: (col: Column) => (
205
+ <HeaderCell
206
+ column={col}
207
+ onTextChange={(t) => setFilter({ name_search: t })}
208
+ />
209
+ ),
210
+ },
211
+ {
212
+ key: "selector_path",
213
+ name: "selector_path",
214
+ renderHeaderCell: (col: Column) => (
215
+ <HeaderCell
216
+ column={col}
217
+ onTextChange={(t) => setFilter({ selector_search: t })}
218
+ />
219
+ ),
220
+ },
221
+ {
222
+ key: "other_ids",
223
+ name: "other_ids",
224
+ renderCell: (row: ProcessedElement) => (
225
+ <div className="space-x-2">
226
+ {Object.entries(row.other_ids).map(([other_id, v]) => (
227
+ <ClickableText
228
+ key={v}
229
+ text={v}
230
+ onClick={() => setFilter({ focused_id: v })}
231
+ />
232
+ ))}
233
+ </div>
234
+ ),
235
+ },
236
+ ]
237
+
238
+ const elements4 = elements3
239
+ .filter((e) => {
240
+ if (!filters.name_search) return true
241
+ return e.name?.toLowerCase()?.includes(filters.name_search.toLowerCase())
242
+ })
243
+ .filter((e) => {
244
+ if (!filters.component_type_filter) return true
245
+ if (filters.component_type_filter === "any") return true
246
+ if (filters.component_type_filter === "source") {
247
+ return e.type.startsWith("source_")
248
+ }
249
+ if (filters.component_type_filter === "source/pcb") {
250
+ return e.type.startsWith("source_") || e.type.startsWith("pcb_")
251
+ }
252
+ if (filters.component_type_filter === "source/schematic") {
253
+ return e.type.startsWith("source_") || e.type.startsWith("schematic_")
254
+ }
255
+ return e.type?.includes(filters.component_type_filter)
256
+ })
257
+ .filter((e) => {
258
+ if (!filters.selector_search) return true
259
+ const parts = filters.selector_search
260
+ .split(" ")
261
+ .filter((p) => p.length > 0)
262
+ return parts.every((part) => e.selector_path?.includes(part))
263
+ })
264
+ .filter((e) => {
265
+ if (!filters.id_search) return true
266
+ return e.primary_id?.includes(filters.id_search)
267
+ })
268
+ .filter((e) => {
269
+ if (!filters.focused_id) return true
270
+ if (e.primary_id === filters.focused_id) return true
271
+ if (Object.values(e.other_ids).includes(filters.focused_id)) return true
272
+ return false
273
+ })
274
+
275
+ return (
276
+ <div className="font-mono text-xs">
277
+ <div className="overflow-x-auto">
278
+ <table className="table-auto w-full text-left">
279
+ <thead>
280
+ <tr>
281
+ {columns.map((col) => (
282
+ <th key={col.key} className="px-4 py-2 border-b">
283
+ {col.renderHeaderCell ? col.renderHeaderCell(col) : col.name}
284
+ </th>
285
+ ))}
286
+ </tr>
287
+ </thead>
288
+ <tbody>
289
+ {elements4.map((row, rowIndex) => (
290
+ <tr key={rowIndex} className="hover:bg-gray-100">
291
+ {columns.map((col) => (
292
+ <td key={col.key} className="px-4 py-2 border-b">
293
+ {col.renderCell
294
+ ? col.renderCell(row)
295
+ : (row as any)[col.key]}
296
+ </td>
297
+ ))}
298
+ </tr>
299
+ ))}
300
+ </tbody>
301
+ </table>
302
+ </div>
303
+ <Modal
304
+ open={modal.open}
305
+ onClose={() => setModal({ open: false })}
306
+ title={modal.open ? modal.title : ""}
307
+ >
308
+ <div className="bg-gray-800 p-3 text-white rounded">
309
+ <pre className="whitespace-pre-wrap">
310
+ {modal.open ? JSON.stringify(modal.element, null, 2) : ""}
311
+ </pre>
312
+ </div>
313
+ </Modal>
314
+ </div>
315
+ )
316
+ }
@@ -0,0 +1,21 @@
1
+ // ClickableText.tsx
2
+ import React from "react"
3
+
4
+ interface ClickableTextProps {
5
+ text: string
6
+ onClick: () => void
7
+ }
8
+
9
+ export const ClickableText: React.FC<ClickableTextProps> = ({
10
+ text,
11
+ onClick,
12
+ }) => {
13
+ return (
14
+ <span
15
+ className="cursor-pointer underline text-blue-300 mx-2"
16
+ onClick={onClick}
17
+ >
18
+ {text}
19
+ </span>
20
+ )
21
+ }
@@ -0,0 +1,27 @@
1
+ // HeaderCell.tsx
2
+ import React from "react"
3
+
4
+ interface HeaderCellProps {
5
+ column: { name: string }
6
+ field?: () => React.ReactNode
7
+ onTextChange?: (value: string) => void
8
+ }
9
+
10
+ export const HeaderCell: React.FC<HeaderCellProps> = (p) => {
11
+ return (
12
+ <div className="leading-5">
13
+ <div className="py-2 font-bold">{p.column.name}</div>
14
+ <div>
15
+ {p.field?.() ?? (
16
+ <input
17
+ type="text"
18
+ className="border rounded p-1 w-full"
19
+ onChange={(e) => {
20
+ p.onTextChange?.(e.target.value)
21
+ }}
22
+ />
23
+ )}
24
+ </div>
25
+ </div>
26
+ )
27
+ }
@@ -0,0 +1,39 @@
1
+ // Modal.tsx
2
+ import React from "react"
3
+
4
+ interface ModalProps {
5
+ open: boolean
6
+ children: React.ReactNode
7
+ title: string
8
+ onClose: () => void
9
+ }
10
+
11
+ const Modal: React.FC<ModalProps> = ({ open, children, title, onClose }) => {
12
+ if (!open) return null
13
+
14
+ return (
15
+ <div
16
+ className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50"
17
+ onClick={onClose}
18
+ >
19
+ <div
20
+ className="bg-white p-5 rounded-lg relative w-11/12 max-w-2xl"
21
+ onClick={(e) => {
22
+ e.preventDefault()
23
+ e.stopPropagation()
24
+ }}
25
+ >
26
+ <h2 className="mt-0 text-xl">{title}</h2>
27
+ <button
28
+ className="absolute top-4 right-4 text-2xl font-bold"
29
+ onClick={onClose}
30
+ >
31
+ &times;
32
+ </button>
33
+ {children}
34
+ </div>
35
+ </div>
36
+ )
37
+ }
38
+
39
+ export default Modal