@aphrody/m3-showcase 3.3.4

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 (674) hide show
  1. package/README.md +47 -0
  2. package/dist/Album-20-x0fyhqxj.png +0 -0
  3. package/dist/Album-txdjxr6p.png +0 -0
  4. package/dist/Album_Light-bnvn9x43.png +0 -0
  5. package/dist/Alias-20-jpvzp7sd.png +0 -0
  6. package/dist/Alias-fbqj79wp.png +0 -0
  7. package/dist/Alias_Light-hv5b8k7t.png +0 -0
  8. package/dist/AmazonS3-x58haer2.png +0 -0
  9. package/dist/AndroidPhotos-cj9z6mnt.png +0 -0
  10. package/dist/AppleFiles-g4g8431e.png +0 -0
  11. package/dist/ApplePhotos-f2nesvx1.png +0 -0
  12. package/dist/Application-ft1as292.png +0 -0
  13. package/dist/Application_Light-h2p2z3de.png +0 -0
  14. package/dist/Archive-20-y262mxsm.png +0 -0
  15. package/dist/Archive-vmmq3f0p.png +0 -0
  16. package/dist/Archive_Light-fqxdt82g.png +0 -0
  17. package/dist/Audio-20-345hqxr8.png +0 -0
  18. package/dist/Audio-3w697yx9.png +0 -0
  19. package/dist/Audio_Light-4pb6z10h.png +0 -0
  20. package/dist/BackBlaze-6m4qpkyc.png +0 -0
  21. package/dist/Ball-d0bcgqha.png +0 -0
  22. package/dist/Book-20-etd4fzhm.png +0 -0
  23. package/dist/Book-ekfqxh7a.png +0 -0
  24. package/dist/BookBlue-17k9z7dy.png +0 -0
  25. package/dist/Book_Light-0n5wsr76.png +0 -0
  26. package/dist/Box-rd26c0g6.png +0 -0
  27. package/dist/CloudSync-wxh5ez5h.png +0 -0
  28. package/dist/CloudSync_Light-nb09rvv4.png +0 -0
  29. package/dist/Code-20-ybgq5j59.png +0 -0
  30. package/dist/Collection-20-7g9nzzcf.png +0 -0
  31. package/dist/Collection-52f2j9wx.png +0 -0
  32. package/dist/CollectionSparkle-nj38wazp.png +0 -0
  33. package/dist/CollectionSparkle_Light-hp1jptvv.png +0 -0
  34. package/dist/Collection_Light-z7p3knd7.png +0 -0
  35. package/dist/Compute-ghst3emj.png +0 -0
  36. package/dist/Config-20-vqd0vqeb.png +0 -0
  37. package/dist/DAV-mr5nm7zs.png +0 -0
  38. package/dist/Database-20-0q97pw36.png +0 -0
  39. package/dist/Database-rcxjw7yv.png +0 -0
  40. package/dist/Database_Light-1dxfaj96.png +0 -0
  41. package/dist/DeleteLocation-3hw52syq.png +0 -0
  42. package/dist/Devices-t2f2k803.png +0 -0
  43. package/dist/Document-20-0f78jpbp.png +0 -0
  44. package/dist/Document-kgsdt3nq.png +0 -0
  45. package/dist/Document_Light-ht9avf71.png +0 -0
  46. package/dist/Document_doc-wqd2zqp2.png +0 -0
  47. package/dist/Document_doc_Light-4ppbm2he.png +0 -0
  48. package/dist/Document_memory-6vymqjra.png +0 -0
  49. package/dist/Document_pdf-7b1zt469.png +0 -0
  50. package/dist/Document_pdf_Light-42j6dt8z.png +0 -0
  51. package/dist/Document_srt-symqv91r.png +0 -0
  52. package/dist/Document_xls-j5tbzav2.png +0 -0
  53. package/dist/Document_xls_Light-w6kbrvem.png +0 -0
  54. package/dist/Document_xmp-7xqx4tm8.png +0 -0
  55. package/dist/Dotfile-20-w53rabv6.png +0 -0
  56. package/dist/Drive-7wb1bf5w.png +0 -0
  57. package/dist/Drive-AmazonS3_Light-z6j2s9xm.png +0 -0
  58. package/dist/Drive-BackBlaze_Light-tr4wfkey.png +0 -0
  59. package/dist/Drive-DAV_Light-kse85f46.png +0 -0
  60. package/dist/Drive-Darker-mss4n9ws.png +0 -0
  61. package/dist/Drive-Dropbox_Light-48naz6gc.png +0 -0
  62. package/dist/Drive-GoogleDrive_Light-t4d4180c.png +0 -0
  63. package/dist/Drive-Mega-z6k8n821.png +0 -0
  64. package/dist/Drive-Mega_Light-nk0qskfb.png +0 -0
  65. package/dist/Drive-OneDrive-sx649zqw.png +0 -0
  66. package/dist/Drive-OneDrive_Light-2n556kpe.png +0 -0
  67. package/dist/Drive-OpenStack-tcs5rge7.png +0 -0
  68. package/dist/Drive-OpenStack_Light-05qnc2gy.png +0 -0
  69. package/dist/Drive-PCloud_Light-d0h9kbwp.png +0 -0
  70. package/dist/Drive-box_Light-0cb17zc1.png +0 -0
  71. package/dist/Drive_Light-dcjdmxm9.png +0 -0
  72. package/dist/Dropbox-q4nkmy9v.png +0 -0
  73. package/dist/Encrypted-20-m8ax3zxz.png +0 -0
  74. package/dist/Encrypted-ddrf9wk4.png +0 -0
  75. package/dist/Encrypted_Light-n1mjh529.png +0 -0
  76. package/dist/Entity-a4438mse.png +0 -0
  77. package/dist/Entity_Light-acxm9r2c.png +0 -0
  78. package/dist/Executable-20-fp7e8r9j.png +0 -0
  79. package/dist/Executable_Light_old-6xd6fa1z.png +0 -0
  80. package/dist/Executable_old-cyj158kz.png +0 -0
  81. package/dist/Face_Light-pjctyrvt.png +0 -0
  82. package/dist/Folder-20-r5505wvj.png +0 -0
  83. package/dist/Folder-kc594khj.png +0 -0
  84. package/dist/Folder-tag-xmp-ff4bgkr4.png +0 -0
  85. package/dist/FolderGrey-2vy13evc.png +0 -0
  86. package/dist/FolderGrey_Light-7z31xy56.png +0 -0
  87. package/dist/FolderNoSpace-d65fr1rz.png +0 -0
  88. package/dist/FolderNoSpace_Light-r5fc4pfj.png +0 -0
  89. package/dist/Folder_Light-rrg0jy36.png +0 -0
  90. package/dist/Font-20-r5n0z7f9.png +0 -0
  91. package/dist/Game-ts1kdw4e.png +0 -0
  92. package/dist/Game_Light-4d6ty5nz.png +0 -0
  93. package/dist/Globe-b379ffpd.png +0 -0
  94. package/dist/GlobeAlt-2mjbsvpp.png +0 -0
  95. package/dist/Globe_Light-2r9sdhb0.png +0 -0
  96. package/dist/GoogleDrive-1swewbzf.png +0 -0
  97. package/dist/GoogleSansFlex-latin-23tdmmt1.woff2 +0 -0
  98. package/dist/HDD-e85re2j5.png +0 -0
  99. package/dist/HDD_Light-pfbhb5wg.png +0 -0
  100. package/dist/Heart-3nx0yjvz.png +0 -0
  101. package/dist/Heart_Light-msf9zhq6.png +0 -0
  102. package/dist/Home-waerfpg1.png +0 -0
  103. package/dist/Home_Light-mdswjrcg.png +0 -0
  104. package/dist/Image-20-7vvqrhrb.png +0 -0
  105. package/dist/Image-fz5c8462.png +0 -0
  106. package/dist/Image_Light-rp0w5n3r.png +0 -0
  107. package/dist/Indexed-nxd6ctrt.png +0 -0
  108. package/dist/Key-20-z5nhfv0c.png +0 -0
  109. package/dist/Key-4en80vnn.png +0 -0
  110. package/dist/Key_Light-h3pc5e2c.png +0 -0
  111. package/dist/Keys-9jknyggw.png +0 -0
  112. package/dist/Keys_Light-5w8kcsmz.png +0 -0
  113. package/dist/Laptop-9gwskqny.png +0 -0
  114. package/dist/Laptop_Light-pwtbqbkp.png +0 -0
  115. package/dist/Link-20-f7hh1tcv.png +0 -0
  116. package/dist/Link-w9y1yad0.png +0 -0
  117. package/dist/Link_Light-4dy9pa5j.png +0 -0
  118. package/dist/Location-7vx0yx6r.png +0 -0
  119. package/dist/LocationManaged-w1n71jx5.png +0 -0
  120. package/dist/LocationReplica-4c6ncswq.png +0 -0
  121. package/dist/Lock-mnveqyfm.png +0 -0
  122. package/dist/Lock_Light-xwnbzkjz.png +0 -0
  123. package/dist/Mega-h4j4t3sb.png +0 -0
  124. package/dist/Mesh-20-rkky209q.png +0 -0
  125. package/dist/Mesh-efjcay8j.png +0 -0
  126. package/dist/Mesh_Light-t9yyzb3y.png +0 -0
  127. package/dist/MiniSilverBox-g8dfw0cp.png +0 -0
  128. package/dist/Mobile-Android-wy5kr3bj.png +0 -0
  129. package/dist/Mobile-jpsv7vp8.png +0 -0
  130. package/dist/Mobile_Light-2rwnn5bx.png +0 -0
  131. package/dist/MoveLocation-kft0z94v.png +0 -0
  132. package/dist/MoveLocation_Light-c23j5x59.png +0 -0
  133. package/dist/Movie-nxat82kv.png +0 -0
  134. package/dist/Movie_Light-eh1hmsr5.png +0 -0
  135. package/dist/NewLocation-2hfv9dwq.png +0 -0
  136. package/dist/Node-wykht7k0.png +0 -0
  137. package/dist/Node_Light-maewxhk1.png +0 -0
  138. package/dist/OneDrive-e4jvssjp.png +0 -0
  139. package/dist/OpenStack-pqp01jfd.png +0 -0
  140. package/dist/PC-eyfa7ewm.png +0 -0
  141. package/dist/PCloud-p0n6g1hq.png +0 -0
  142. package/dist/Package-20-grg5wkse.png +0 -0
  143. package/dist/Package-d7ex1fnn.png +0 -0
  144. package/dist/Package_Light-yj2cvgyw.png +0 -0
  145. package/dist/SD-h17wvz4z.png +0 -0
  146. package/dist/SD_Light-y3mmqh6b.png +0 -0
  147. package/dist/Scrapbook-f92c8p1x.png +0 -0
  148. package/dist/Scrapbook_Light-50pjr0q7.png +0 -0
  149. package/dist/Screenshot-20-z4tfe78m.png +0 -0
  150. package/dist/Screenshot-9nd23fde.png +0 -0
  151. package/dist/ScreenshotAlt-en1yt2gv.png +0 -0
  152. package/dist/Screenshot_Light-hnbah84r.png +0 -0
  153. package/dist/Search-7x8c5z1s.png +0 -0
  154. package/dist/SearchAlt-dmxzk2jb.png +0 -0
  155. package/dist/Search_Light-n23xd2ws.png +0 -0
  156. package/dist/Server-hqsf8851.png +0 -0
  157. package/dist/Server_Light-3x01jqz4.png +0 -0
  158. package/dist/SilverBox-0mk6sxrh.png +0 -0
  159. package/dist/Spacedrop-1-d230z0az.png +0 -0
  160. package/dist/Spacedrop-r1t67bcq.png +0 -0
  161. package/dist/Spacedrop_Light-dj5tgtep.png +0 -0
  162. package/dist/Storage-4x2q4nx6.png +0 -0
  163. package/dist/Sync-531te7fq.png +0 -0
  164. package/dist/Sync_Light-754vfxyr.png +0 -0
  165. package/dist/Tablet-ze6ermb7.png +0 -0
  166. package/dist/Tablet_Light-32skyk12.png +0 -0
  167. package/dist/Tags-bfapk266.png +0 -0
  168. package/dist/Tags_Light-7s00envw.png +0 -0
  169. package/dist/Terminal-t1yjx33x.png +0 -0
  170. package/dist/Terminal_Light-4s5azdgr.png +0 -0
  171. package/dist/Text-20-pt0zjg62.png +0 -0
  172. package/dist/Text-6fgmf4b2.png +0 -0
  173. package/dist/TextAlt_Light-w9kbgvm8.png +0 -0
  174. package/dist/Text_Light-c2k3w31k.png +0 -0
  175. package/dist/Text_txt-xhvv80ys.png +0 -0
  176. package/dist/TexturedMesh-ysk831xz.png +0 -0
  177. package/dist/TexturedMesh_Light-4twy5k6k.png +0 -0
  178. package/dist/Trash-hzscccvk.png +0 -0
  179. package/dist/Trash_Light-78nc56tp.png +0 -0
  180. package/dist/Undefined-pkbecmq4.png +0 -0
  181. package/dist/Undefined_Light-jxesg2zv.png +0 -0
  182. package/dist/Unknown-20-07efh8ya.png +0 -0
  183. package/dist/Video-20-q7yg9p4w.png +0 -0
  184. package/dist/Video-370fzqyw.png +0 -0
  185. package/dist/Video_Light-00vhrp0m.png +0 -0
  186. package/dist/WebPageArchive-20-wn0v4x27.png +0 -0
  187. package/dist/Widget-20-9t860nnc.png +0 -0
  188. package/dist/Widget-k1p15mg9.png +0 -0
  189. package/dist/Widget_Light-5md790ar.png +0 -0
  190. package/dist/ace-ph0rt669.svg +1 -0
  191. package/dist/acemanifest-je939qnz.svg +1 -0
  192. package/dist/adoc-kfbf89h8.svg +1 -0
  193. package/dist/adonis-pn6tbmnq.svg +1 -0
  194. package/dist/adonisconfig-5wfnycbk.svg +1 -0
  195. package/dist/afdesign-5nzbppfa.svg +1 -0
  196. package/dist/afphoto-p941z6q7.svg +1 -0
  197. package/dist/afpub-3232tcp9.svg +1 -0
  198. package/dist/ai-vvwvj03w.svg +1 -0
  199. package/dist/air-e3h8cfx1.svg +1 -0
  200. package/dist/angular-fyg22v82.svg +1 -0
  201. package/dist/angular-kzcwnjdt.svg +1 -0
  202. package/dist/anim-15kqy432.svg +1 -0
  203. package/dist/astro-wdcxh4zx.svg +1 -0
  204. package/dist/astroconfig-73qsx73n.svg +1 -0
  205. package/dist/atomizer-42xe88w7.svg +1 -0
  206. package/dist/audio-xy5qb7t1.svg +1 -0
  207. package/dist/audiomp3-s01feh78.svg +1 -0
  208. package/dist/audioogg-bcake0v6.svg +1 -0
  209. package/dist/audiowav-px37pxve.svg +1 -0
  210. package/dist/audiowv-bq8tbfdv.svg +1 -0
  211. package/dist/azure-veqzyzqq.svg +1 -0
  212. package/dist/babel-vxcfp57a.svg +1 -0
  213. package/dist/ballerina-faxx9p3b.svg +1 -0
  214. package/dist/ballerinaconfig-tmd09kkg.svg +1 -0
  215. package/dist/bat-vjr63aqs.svg +1 -0
  216. package/dist/bazel-4e01p5gp.svg +1 -0
  217. package/dist/bazelignore-wzgc7h2d.svg +1 -0
  218. package/dist/bicep-dae0dh59.svg +1 -0
  219. package/dist/bicepconfig-v64442sp.svg +1 -0
  220. package/dist/bicepparam-ts4jjq60.svg +1 -0
  221. package/dist/binary-dz3thnjq.svg +1 -0
  222. package/dist/biome-gbahcmjy.svg +1 -0
  223. package/dist/blade-je22xc2d.svg +1 -0
  224. package/dist/brotli-1m7qfk77.svg +1 -0
  225. package/dist/browserslist-005php91.svg +1 -0
  226. package/dist/bruno-h4bh0s2c.svg +1 -0
  227. package/dist/bsconfig-gmwc0r2r.svg +1 -0
  228. package/dist/buck-gtasjqw1.svg +1 -0
  229. package/dist/bun-6y6y7t4s.svg +1 -0
  230. package/dist/bun-zxmcandz.svg +1 -0
  231. package/dist/bundler-qhs5a5xb.svg +1 -0
  232. package/dist/bunlock-74b62xbm.svg +1 -0
  233. package/dist/c-k2se7t6q.svg +1 -0
  234. package/dist/c-v9cxtxe1.svg +1 -0
  235. package/dist/cargo-ma5bwyg5.svg +1 -0
  236. package/dist/cargolock-ak0tnv5y.svg +1 -0
  237. package/dist/cert-z62mqtqq.svg +1 -0
  238. package/dist/cheader-mgw2nf38.svg +1 -0
  239. package/dist/chunk-08yjrfs5.js +2 -0
  240. package/dist/chunk-2pmrsdd5.js +2 -0
  241. package/dist/chunk-3995cv9k.js +1 -0
  242. package/dist/chunk-58a3eq49.js +2 -0
  243. package/dist/chunk-616szvb9.js +2 -0
  244. package/dist/chunk-6638b8v6.js +1 -0
  245. package/dist/chunk-6ej2n64j.js +1 -0
  246. package/dist/chunk-7tt0cawd.js +10 -0
  247. package/dist/chunk-9gxv4c5g.js +1 -0
  248. package/dist/chunk-9na12mjw.js +1 -0
  249. package/dist/chunk-b7mpjcry.js +1 -0
  250. package/dist/chunk-c1g6tshf.js +2 -0
  251. package/dist/chunk-d50zvrb1.css +1 -0
  252. package/dist/chunk-d6c35fm0.js +2 -0
  253. package/dist/chunk-ehpz56xv.js +2 -0
  254. package/dist/chunk-ewtr6sjm.js +9 -0
  255. package/dist/chunk-g9rnrhvz.js +2 -0
  256. package/dist/chunk-gv83r4qx.js +262 -0
  257. package/dist/chunk-j46wg1ym.js +156 -0
  258. package/dist/chunk-kapsksxf.js +1 -0
  259. package/dist/chunk-m98tyb4g.js +6 -0
  260. package/dist/chunk-nn0prq25.js +2 -0
  261. package/dist/chunk-nsgjb3bx.js +2 -0
  262. package/dist/chunk-p8r6wjkz.js +3 -0
  263. package/dist/chunk-rdnm87fw.js +1 -0
  264. package/dist/chunk-re36kkra.js +1 -0
  265. package/dist/chunk-vm9edd26.js +2 -0
  266. package/dist/chunk-x2hztqk0.css +1 -0
  267. package/dist/chunk-yyxb5zbq.js +2 -0
  268. package/dist/civet-5bbs33v3.svg +1 -0
  269. package/dist/claude-jscxahsf.svg +1 -0
  270. package/dist/cli-4f5nfe5s.svg +1 -0
  271. package/dist/clojure-0h7h9znc.svg +1 -0
  272. package/dist/cmake-q8ryfre0.svg +1 -0
  273. package/dist/cmake-qwe6x8nx.svg +1 -0
  274. package/dist/codeworkspace-326020b4.svg +1 -0
  275. package/dist/coffeescript-ec1bytnk.svg +1 -0
  276. package/dist/commitlint-93j0tfvp.svg +1 -0
  277. package/dist/compodoc-36b7gn70.svg +1 -0
  278. package/dist/composer-vv2tvxkr.svg +1 -0
  279. package/dist/composerlock-nf0232yh.svg +1 -0
  280. package/dist/conan-dggdfcr9.svg +1 -0
  281. package/dist/conf-5756g97p.svg +1 -0
  282. package/dist/copilot-1phy76q3.svg +1 -0
  283. package/dist/cpp-4yvddm6j.svg +1 -0
  284. package/dist/cpp-pbznrtpp.svg +1 -0
  285. package/dist/crystal-x20aj00e.svg +1 -0
  286. package/dist/csharp-0p3hstq8.svg +1 -0
  287. package/dist/csharp-cpmfe8y0.svg +1 -0
  288. package/dist/cshtml-xb5gtb0r.svg +1 -0
  289. package/dist/csproj-ftptw15a.svg +1 -0
  290. package/dist/css-tqps22nw.svg +1 -0
  291. package/dist/css-ycr1qc5f.svg +1 -0
  292. package/dist/cssmap-3gnm34f6.svg +1 -0
  293. package/dist/csv-gg0axfar.svg +1 -0
  294. package/dist/cucumber-m06dfkm5.svg +1 -0
  295. package/dist/cursor-jw7n7tpq.svg +1 -0
  296. package/dist/cypress-xsm2fq1p.svg +1 -0
  297. package/dist/cypressjs-hapzyfm1.svg +1 -0
  298. package/dist/cypressts-jey9ahc7.svg +1 -0
  299. package/dist/d-4x2njcan.svg +1 -0
  300. package/dist/dartlang-7dwdwv03.svg +1 -0
  301. package/dist/dartlang-mra7r0f8.svg +1 -0
  302. package/dist/delphiproject-7snmvsdx.svg +1 -0
  303. package/dist/diff-hekg2jpm.svg +1 -0
  304. package/dist/docker-8q58y2kc.svg +1 -0
  305. package/dist/dockerdebug-8zhgj7bd.svg +1 -0
  306. package/dist/dockerignore-488safx9.svg +1 -0
  307. package/dist/drawio-6qm0rhkv.svg +1 -0
  308. package/dist/drizzle-5bct2tg6.svg +1 -0
  309. package/dist/dsstore-pmhpmkdr.svg +1 -0
  310. package/dist/dune-r4xhac56.svg +1 -0
  311. package/dist/duneproject-3b99jndq.svg +1 -0
  312. package/dist/edge-0jwced3c.svg +1 -0
  313. package/dist/editorconfig-hee1zp1h.svg +1 -0
  314. package/dist/eex-q1bkj66x.svg +1 -0
  315. package/dist/elixir-48ge02m5.svg +1 -0
  316. package/dist/elm-97mh5wye.svg +1 -0
  317. package/dist/env-ysamxkcd.svg +1 -0
  318. package/dist/eraser-7mejjgrg.svg +1 -0
  319. package/dist/erb-f28j5x6b.svg +1 -0
  320. package/dist/erlang-3ebtbtfw.svg +1 -0
  321. package/dist/esbuild-wptxye5y.svg +1 -0
  322. package/dist/eslint-mrbexpc5.svg +1 -0
  323. package/dist/eslintignore-k65wpbsr.svg +1 -0
  324. package/dist/excalidraw-28avfa1h.svg +1 -0
  325. package/dist/exs-5w2cfpaf.svg +1 -0
  326. package/dist/exx-s897xhz3.svg +1 -0
  327. package/dist/farm-m80hxnfy.svg +1 -0
  328. package/dist/favicon-djc6sne4.svg +1 -0
  329. package/dist/figma-krwq889b.svg +1 -0
  330. package/dist/file-hetj1tjc.svg +1 -0
  331. package/dist/file_light-jx35pv2m.svg +1 -0
  332. package/dist/flakelock-2nsqn4gw.svg +1 -0
  333. package/dist/flutter-277q83en.svg +1 -0
  334. package/dist/flutterlock-h0nywsvt.svg +1 -0
  335. package/dist/flutterpackage-cpgnfwtt.svg +1 -0
  336. package/dist/folder-2xmsfyxp.svg +1 -0
  337. package/dist/folder_open-wk4ndx1f.svg +1 -0
  338. package/dist/fonteot-a8xmqj3j.svg +1 -0
  339. package/dist/fontotf-f01hg174.svg +1 -0
  340. package/dist/fontttf-pcr3rt21.svg +1 -0
  341. package/dist/fontwoff-v1gdka62.svg +1 -0
  342. package/dist/fontwoff2-1w1r47x8.svg +1 -0
  343. package/dist/freemarker-s9m714ah.svg +1 -0
  344. package/dist/fsharp-89mjndn4.svg +1 -0
  345. package/dist/gbl-v20qxsgx.svg +1 -0
  346. package/dist/git-wc9x7c5e.svg +1 -0
  347. package/dist/gitlab-bhcvbetz.svg +1 -0
  348. package/dist/gleam-h2ze8vtz.svg +1 -0
  349. package/dist/gleamconfig-6sq0xy19.svg +1 -0
  350. package/dist/go-15qaph9s.svg +1 -0
  351. package/dist/go-j2dk6r7k.svg +1 -0
  352. package/dist/go_package-5nc95prx.svg +1 -0
  353. package/dist/godot-v7nnsyvc.svg +1 -0
  354. package/dist/gradle-khh2bn3v.svg +1 -0
  355. package/dist/gradlebat-631878b0.svg +1 -0
  356. package/dist/gradlekotlin-f8netdbt.svg +1 -0
  357. package/dist/grain-tztem5b9.svg +1 -0
  358. package/dist/graphql-egmdpvzr.svg +1 -0
  359. package/dist/groovy-c0sstajm.svg +1 -0
  360. package/dist/grunt-56ssa3fr.svg +1 -0
  361. package/dist/gulp-j7wc27hd.svg +1 -0
  362. package/dist/h-4xbbejcs.svg +1 -0
  363. package/dist/haml-6pyt136a.svg +1 -0
  364. package/dist/handlebars-1v8g0n32.svg +1 -0
  365. package/dist/hardhat-1k6gym6f.svg +1 -0
  366. package/dist/hash-xd1ymkyp.svg +1 -0
  367. package/dist/hashicorp-vty9d6de.svg +1 -0
  368. package/dist/haskell-ncbxh3wk.svg +1 -0
  369. package/dist/haxe-j5nqdw5z.svg +1 -0
  370. package/dist/haxeml-bn7wtpx1.svg +1 -0
  371. package/dist/hpp-rpxcfk6j.svg +1 -0
  372. package/dist/htaccess-s4rrm1re.svg +1 -0
  373. package/dist/html-3vbw2fxn.svg +1 -0
  374. package/dist/html-v1z6sanr.svg +1 -0
  375. package/dist/http-9bfh1zqw.svg +1 -0
  376. package/dist/identifier-6gsrr6st.svg +1 -0
  377. package/dist/image-pstdg0vj.svg +1 -0
  378. package/dist/imagegif-any2rrn3.svg +1 -0
  379. package/dist/imageico-cng69rft.svg +1 -0
  380. package/dist/imagejpg-rtx9yy9y.svg +1 -0
  381. package/dist/imagepng-j6f306v1.svg +1 -0
  382. package/dist/imagewebp-q1mcm8np.svg +1 -0
  383. package/dist/imba-xxn1q1r2.svg +1 -0
  384. package/dist/index.html +16 -0
  385. package/dist/info-qssn7jw5.svg +1 -0
  386. package/dist/instructions-3068x11a.svg +1 -0
  387. package/dist/ipynb-qm8fb1p1.svg +1 -0
  388. package/dist/jar-src0eb7a.svg +1 -0
  389. package/dist/java-126v951r.svg +1 -0
  390. package/dist/java-hhh3k9xf.svg +1 -0
  391. package/dist/jenkins-ap6tzby2.svg +1 -0
  392. package/dist/jest-xrtp7hh0.svg +1 -0
  393. package/dist/jinja-v9kggcps.svg +1 -0
  394. package/dist/js-qsntbmzx.svg +1 -0
  395. package/dist/js-r0b86hmj.svg +1 -0
  396. package/dist/jsmap-1ns6yn3z.svg +1 -0
  397. package/dist/json-1jhmg3gf.svg +1 -0
  398. package/dist/jsp-7n103tna.svg +1 -0
  399. package/dist/julia-nba7etbq.svg +1 -0
  400. package/dist/karma-zcbeze4p.svg +1 -0
  401. package/dist/keep-tw8xf3gf.svg +1 -0
  402. package/dist/key-hd2nnhmr.svg +1 -0
  403. package/dist/knex-87w40q0j.svg +1 -0
  404. package/dist/knip-kzsz2w4s.svg +1 -0
  405. package/dist/kotlin-360tzrt1.svg +1 -0
  406. package/dist/kotlin-hbykz1k8.svg +1 -0
  407. package/dist/kotlins-4zz4rshm.svg +1 -0
  408. package/dist/krita-wx5qyrx7.svg +1 -0
  409. package/dist/latex-jwrpzd2b.svg +1 -0
  410. package/dist/launch-8wsjpmd3.svg +1 -0
  411. package/dist/lazarusproject-gma2fvya.svg +1 -0
  412. package/dist/less-p4zwh19p.svg +1 -0
  413. package/dist/license-qamq8mp3.svg +1 -0
  414. package/dist/light_editorconfig-k28g3f4k.svg +1 -0
  415. package/dist/liquid-wtexakya.svg +1 -0
  416. package/dist/llvm-cfgd7591.svg +1 -0
  417. package/dist/lock-wv5q3nef.svg +1 -0
  418. package/dist/log-ykdkwnpq.svg +1 -0
  419. package/dist/lua-aynthw24.svg +1 -0
  420. package/dist/m-va54fte8.svg +1 -0
  421. package/dist/m3-bun.manifest.json +3785 -0
  422. package/dist/makefile-kkcgz3sb.svg +1 -0
  423. package/dist/manifest-ede4t0vc.svg +1 -0
  424. package/dist/markdown-x7kezf76.svg +1 -0
  425. package/dist/markdownx-y5mf21hn.svg +1 -0
  426. package/dist/maven-djc7vb1b.svg +1 -0
  427. package/dist/mermaid-4bpjjghk.svg +1 -0
  428. package/dist/mesh-q798mf4t.svg +1 -0
  429. package/dist/mgcb-cfmfr63b.svg +1 -0
  430. package/dist/mint-b732cej4.svg +1 -0
  431. package/dist/mix-41smb4q2.svg +1 -0
  432. package/dist/mixlock-z0cvwpkq.svg +1 -0
  433. package/dist/mjml-4kzxtz0b.svg +1 -0
  434. package/dist/mkdocs-5t1davz8.svg +1 -0
  435. package/dist/mockoon-5pw3ckhf.svg +1 -0
  436. package/dist/motoko-yv95035d.svg +1 -0
  437. package/dist/mov-r3cjb3vr.svg +1 -0
  438. package/dist/mp4-31hded8m.svg +1 -0
  439. package/dist/mtl-01f1f06m.svg +1 -0
  440. package/dist/mustache-1s62ewsg.svg +1 -0
  441. package/dist/nelua-97199e3p.svg +1 -0
  442. package/dist/neon-gcp7rsp5.svg +1 -0
  443. package/dist/nestjs-sme3dmgk.svg +1 -0
  444. package/dist/nestjscontroller-2ceskrfc.svg +1 -0
  445. package/dist/nestjsdecorator-52k9dwm2.svg +1 -0
  446. package/dist/nestjsdto-xf36my7y.svg +1 -0
  447. package/dist/nestjsentity-q17fyvm1.svg +1 -0
  448. package/dist/nestjsfilter-qytmtqzj.svg +1 -0
  449. package/dist/nestjsguard-4pyb34xe.svg +1 -0
  450. package/dist/nestjsinterceptor-7s690j87.svg +1 -0
  451. package/dist/nestjsmodule-zeyz5633.svg +1 -0
  452. package/dist/nestjsrepository-kz26s1jf.svg +1 -0
  453. package/dist/nestjsresolver-8qdvexrk.svg +1 -0
  454. package/dist/nestjsservice-kp3b933m.svg +1 -0
  455. package/dist/nestscheduler-60p4j2tg.svg +1 -0
  456. package/dist/netlify-bbgdw42s.svg +1 -0
  457. package/dist/nextconfig-gr1sd69d.svg +1 -0
  458. package/dist/nextron-sf3ag316.svg +1 -0
  459. package/dist/nginx-73stz0yt.svg +1 -0
  460. package/dist/nim-gqnvnkc5.svg +1 -0
  461. package/dist/nix-t1m4qhc8.svg +1 -0
  462. package/dist/njk-dfv3nrxr.svg +1 -0
  463. package/dist/node-w3gp0xxn.svg +1 -0
  464. package/dist/nodemon-q41mkhvz.svg +1 -0
  465. package/dist/npm-rt8ga6qx.svg +1 -0
  466. package/dist/npmlock-8p4sp377.svg +1 -0
  467. package/dist/nuxt-13qdp31g.svg +1 -0
  468. package/dist/nvidia-fysz92ep.svg +1 -0
  469. package/dist/nvim-h3ynkfqg.svg +1 -0
  470. package/dist/nvm-ser6majj.svg +1 -0
  471. package/dist/nx-av0cw2sw.svg +1 -0
  472. package/dist/obj-thakg863.svg +1 -0
  473. package/dist/ocaml-maevkwa7.svg +1 -0
  474. package/dist/ocamli-w0gc5jq8.svg +1 -0
  475. package/dist/ocamll-h2wysvh1.svg +1 -0
  476. package/dist/ocamly-ppj6pfy3.svg +1 -0
  477. package/dist/odin-x7qb7b6x.svg +1 -0
  478. package/dist/opengl-h6pbxg3n.svg +1 -0
  479. package/dist/oxlint-7qwxtp86.svg +1 -0
  480. package/dist/panda-9qqa1nn4.svg +1 -0
  481. package/dist/parcel-gzckrwpy.svg +1 -0
  482. package/dist/pascal-kj6crs4h.svg +1 -0
  483. package/dist/pdf-wk39v1nv.svg +1 -0
  484. package/dist/perl-11dgrnh8.svg +1 -0
  485. package/dist/perlm-7xrwgd93.svg +1 -0
  486. package/dist/pfx-ggdb4v6p.svg +1 -0
  487. package/dist/photoshop-m3gw1xv7.svg +1 -0
  488. package/dist/php-jgyt96zk.svg +1 -0
  489. package/dist/php-jx84j7ns.svg +1 -0
  490. package/dist/plantuml-04ncqrmc.svg +1 -0
  491. package/dist/playright-dfc8tvme.svg +1 -0
  492. package/dist/plop-n71aee6w.svg +1 -0
  493. package/dist/pnpm-jvkts1qb.svg +1 -0
  494. package/dist/pnpmlock-2kqbdtn7.svg +1 -0
  495. package/dist/poetry-yjeeyvtr.svg +1 -0
  496. package/dist/poetrylock-da30xbws.svg +1 -0
  497. package/dist/postcssconfig-yyvnwr01.svg +1 -0
  498. package/dist/powershell-hf358xbb.svg +1 -0
  499. package/dist/powershelldata-nggemhrs.svg +1 -0
  500. package/dist/powershellmodule-v5wz6sed.svg +1 -0
  501. package/dist/precommit-wmfmt8tq.svg +1 -0
  502. package/dist/prettier-nyc1v0qk.svg +1 -0
  503. package/dist/prettierignore-hx4x759w.svg +1 -0
  504. package/dist/prisma-te242v0q.svg +1 -0
  505. package/dist/prolog-twb6h758.svg +1 -0
  506. package/dist/prompt-eg8c0gqa.svg +1 -0
  507. package/dist/properties-c39zkae1.svg +1 -0
  508. package/dist/proto-rsvsx4xb.svg +1 -0
  509. package/dist/pug-rqxd67km.svg +1 -0
  510. package/dist/pvk-bc4g1qms.svg +1 -0
  511. package/dist/py-0g79s39m.svg +1 -0
  512. package/dist/pyproject-5s59g4en.svg +1 -0
  513. package/dist/python-ds482k8k.svg +1 -0
  514. package/dist/qt-y3kxpf67.svg +1 -0
  515. package/dist/quarkus-xrq4b999.svg +1 -0
  516. package/dist/quasar-hvna6b7f.svg +1 -0
  517. package/dist/r-n1bnfab8.svg +1 -0
  518. package/dist/racket-vx5e6n1d.svg +1 -0
  519. package/dist/raku-4ydzc5wj.svg +1 -0
  520. package/dist/razor-cbqpr6vt.svg +1 -0
  521. package/dist/rb-mfkwkq7e.svg +1 -0
  522. package/dist/reactjs-qjyhk3rf.svg +1 -0
  523. package/dist/reactts-p0hf29yr.svg +1 -0
  524. package/dist/readme-3qcyy95y.svg +1 -0
  525. package/dist/redis-ya1xyn4v.svg +1 -0
  526. package/dist/rego-tr1y9cqm.svg +1 -0
  527. package/dist/remix-61pbjda4.svg +1 -0
  528. package/dist/rescript-9c3xnepn.svg +1 -0
  529. package/dist/rescriptinterface-6ne0a2rf.svg +1 -0
  530. package/dist/restructuredtext-7k21mjx4.svg +1 -0
  531. package/dist/rjson-3s2edhhr.svg +1 -0
  532. package/dist/robots-geh7c3pq.svg +1 -0
  533. package/dist/rollup-0dxydzr9.svg +1 -0
  534. package/dist/rome-1gxetp8g.svg +1 -0
  535. package/dist/ron-ft34rzr3.svg +1 -0
  536. package/dist/root_folder-rhwm7290.svg +1 -0
  537. package/dist/root_folder_light-ngkg5m4x.svg +1 -0
  538. package/dist/root_folder_light_open-c6nhg6sy.svg +1 -0
  539. package/dist/root_folder_open-genv0ps7.svg +1 -0
  540. package/dist/rs-60bcevwn.svg +1 -0
  541. package/dist/ruby-7j5zzh38.svg +1 -0
  542. package/dist/rust-a9528zdg.svg +1 -0
  543. package/dist/rustfmt-c8evpzd7.svg +1 -0
  544. package/dist/sails-5ecccxrg.svg +1 -0
  545. package/dist/salesforce-4d89045j.svg +1 -0
  546. package/dist/sass-g9qbr3x4.svg +1 -0
  547. package/dist/scala-8gnn0ekc.svg +1 -0
  548. package/dist/scss-g9qbr3x4.svg +1 -0
  549. package/dist/sentinel-g8py3peh.svg +1 -0
  550. package/dist/sequelize-qvzwnjhv.svg +1 -0
  551. package/dist/sh-bkp0n5vb.svg +1 -0
  552. package/dist/shaderlab-gkww43v2.svg +1 -0
  553. package/dist/shell-kc0a9zjq.svg +1 -0
  554. package/dist/silq-mczpsqmz.svg +1 -0
  555. package/dist/slim-8j9jf3zt.svg +1 -0
  556. package/dist/sln-nketqakm.svg +1 -0
  557. package/dist/smarty-w1zxys1s.svg +1 -0
  558. package/dist/sol-adyfjwzz.svg +1 -0
  559. package/dist/spc-kk30w5m6.svg +1 -0
  560. package/dist/sql-3c4gcy7a.svg +1 -0
  561. package/dist/sqlite-cppkxr0a.svg +1 -0
  562. package/dist/storybook-885ssp75.svg +1 -0
  563. package/dist/stylelint-z7s6yhc9.svg +1 -0
  564. package/dist/stylelintignore-xwnh8sx1.svg +1 -0
  565. package/dist/stylus-qz53ytkd.svg +1 -0
  566. package/dist/suo-3fvnz3bx.svg +1 -0
  567. package/dist/svelte-jp3x9gw7.svg +1 -0
  568. package/dist/svelteconfig-m0n00zjj.svg +1 -0
  569. package/dist/svg-8dyqf96t.svg +1 -0
  570. package/dist/swift-8g870v6j.svg +1 -0
  571. package/dist/symfony-q77kcepw.svg +1 -0
  572. package/dist/tailwind-3es9cgbd.svg +1 -0
  573. package/dist/tauri-xnj526kw.svg +1 -0
  574. package/dist/taze-e3ykqs0k.svg +1 -0
  575. package/dist/terrafile-gqn1tysh.svg +1 -0
  576. package/dist/terraform-jy4fbwsr.svg +1 -0
  577. package/dist/terraformvars-05qje1sw.svg +1 -0
  578. package/dist/terraformversion-gq2tkwmn.svg +1 -0
  579. package/dist/testjs-sqgjsb8h.svg +1 -0
  580. package/dist/testts-19m1sf26.svg +1 -0
  581. package/dist/tmpl-enggw2gc.svg +1 -0
  582. package/dist/todo-ccw0mpg2.svg +1 -0
  583. package/dist/toml-rmx5hba4.svg +1 -0
  584. package/dist/toolversions-s7fttfyp.svg +1 -0
  585. package/dist/tox-a4j4yvmb.svg +1 -0
  586. package/dist/travis-gr3jtpx2.svg +1 -0
  587. package/dist/tres-qt3kk1t0.svg +1 -0
  588. package/dist/ts-7amn21ms.svg +1 -0
  589. package/dist/tscn-g1jthb4m.svg +1 -0
  590. package/dist/tsconfig-r1s750bq.svg +1 -0
  591. package/dist/tsx-a3rsjrrz.svg +1 -0
  592. package/dist/turbo-dcmj75tc.svg +1 -0
  593. package/dist/twig-3xgrb919.svg +1 -0
  594. package/dist/txt-y0t8b72p.svg +1 -0
  595. package/dist/typescript-kd5g4jkg.svg +1 -0
  596. package/dist/typescriptdef-y43343m6.svg +1 -0
  597. package/dist/ui-pxvg5zj2.svg +1 -0
  598. package/dist/unocss-b0f5fthj.svg +1 -0
  599. package/dist/user-q7tk1k2d.svg +1 -0
  600. package/dist/v-c25jfygk.svg +1 -0
  601. package/dist/vanillaextract-3w6vds6m.svg +1 -0
  602. package/dist/vb-87ckj7t3.svg +1 -0
  603. package/dist/vercel-hfxjvaj9.svg +1 -0
  604. package/dist/version-zd7hfmf1.svg +1 -0
  605. package/dist/vhd-xaw7zbny.svg +1 -0
  606. package/dist/vhdl-s308rb5a.svg +1 -0
  607. package/dist/video-z6khth5y.svg +1 -0
  608. package/dist/vite-5g5xkmpk.svg +1 -0
  609. package/dist/viteenv-jbmx0tb0.svg +1 -0
  610. package/dist/vitest-5267dzt2.svg +1 -0
  611. package/dist/vmod-8jftapdc.svg +1 -0
  612. package/dist/vscode-8tvcs7ae.svg +1 -0
  613. package/dist/vue-j5sjdz4b.svg +1 -0
  614. package/dist/vue-x9h2d0d2.svg +1 -0
  615. package/dist/vueconfig-726zh8dd.svg +1 -0
  616. package/dist/wasm-vgmg9kv4.svg +1 -0
  617. package/dist/webpack-hfwce90m.svg +1 -0
  618. package/dist/wgsl-68923cz5.svg +1 -0
  619. package/dist/windi-c9m8en7k.svg +1 -0
  620. package/dist/wren-7ep5ph5r.svg +1 -0
  621. package/dist/xmake-mc60ax7m.svg +1 -0
  622. package/dist/xml-feq1fbt4.svg +1 -0
  623. package/dist/yaml-n43aw0fx.svg +1 -0
  624. package/dist/yang-mtcxs2mg.svg +1 -0
  625. package/dist/yarn-k4k6e35h.svg +1 -0
  626. package/dist/yarnerror-5jkesx9j.svg +1 -0
  627. package/dist/yarnignore-ryh8jd5p.svg +1 -0
  628. package/dist/yarnlock-9zvhbg04.svg +1 -0
  629. package/dist/yin-f931bzgj.svg +1 -0
  630. package/dist/zig-nx2e65ns.svg +1 -0
  631. package/dist/zip-7hqmj0b0.svg +1 -0
  632. package/m3.config.ts +32 -0
  633. package/package.json +60 -0
  634. package/scripts/browser-contract.ts +400 -0
  635. package/scripts/icons.ts +56 -0
  636. package/scripts/inventory.ts +86 -0
  637. package/scripts/shots.ts +154 -0
  638. package/scripts/tauri.ts +401 -0
  639. package/src/App.tsx +40 -0
  640. package/src/adaptive/dpad.ts +223 -0
  641. package/src/adaptive/window.ts +133 -0
  642. package/src/api/index.ts +332 -0
  643. package/src/components/ui.tsx +89 -0
  644. package/src/env.d.ts +5 -0
  645. package/src/favicon.svg +1 -0
  646. package/src/generated/inventory.json +426 -0
  647. package/src/index.html +16 -0
  648. package/src/inventory.ts +19 -0
  649. package/src/main.tsx +6 -0
  650. package/src/pages/Adaptive.tsx +128 -0
  651. package/src/pages/Ai.tsx +174 -0
  652. package/src/pages/Brands.tsx +156 -0
  653. package/src/pages/Components.tsx +91 -0
  654. package/src/pages/Design.tsx +163 -0
  655. package/src/pages/Explorer.tsx +125 -0
  656. package/src/pages/Forms.tsx +128 -0
  657. package/src/pages/Icons.tsx +138 -0
  658. package/src/pages/Motion.tsx +157 -0
  659. package/src/pages/Next.tsx +107 -0
  660. package/src/pages/Overview.tsx +105 -0
  661. package/src/pages/Primitives.tsx +138 -0
  662. package/src/pages/Reader.tsx +101 -0
  663. package/src/pages/System.tsx +283 -0
  664. package/src/pages/Theme.tsx +146 -0
  665. package/src/pages/index.ts +25 -0
  666. package/src/router.ts +22 -0
  667. package/src/shell/Shell.tsx +383 -0
  668. package/src/shell/nav.ts +198 -0
  669. package/src/styles.css +61 -0
  670. package/test/contracts.test.ts +87 -0
  671. package/test/host-contract.test.ts +183 -0
  672. package/test/runtime-api.test.ts +138 -0
  673. package/test-dom/dpad.test.ts +78 -0
  674. package/tsconfig.json +11 -0
@@ -0,0 +1,87 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { afterAll, describe, expect, test } from "bun:test";
3
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { adaptiveFor, parseOverride } from "../src/adaptive/window.ts";
7
+ import { pickNext } from "../src/adaptive/dpad.ts";
8
+ import { parseRoute } from "../src/router.ts";
9
+ import { collect } from "../scripts/inventory.ts";
10
+ import { plan } from "../scripts/shots.ts";
11
+
12
+ const root = mkdtempSync(join(tmpdir(), "m3-showcase-contract-"));
13
+ afterAll(() => rmSync(root, { recursive: true, force: true }));
14
+ describe("adaptive showcase contracts", () => {
15
+ test("viewport and explicit TV preferences are independent", () => {
16
+ const mobile = adaptiveFor({
17
+ width: 390,
18
+ height: 844,
19
+ userAgent: "",
20
+ override: null,
21
+ touch: true,
22
+ });
23
+ expect(mobile.mode).toBe("mobile");
24
+ expect(mobile.width).toBe("compact");
25
+ const tv = adaptiveFor({
26
+ width: 390,
27
+ height: 844,
28
+ userAgent: "",
29
+ override: "tv",
30
+ touch: false,
31
+ });
32
+ expect(tv.mode).toBe("tv");
33
+ const desktop = adaptiveFor({
34
+ width: 1280,
35
+ height: 800,
36
+ userAgent: "SMART-TV",
37
+ override: "desktop",
38
+ touch: false,
39
+ });
40
+ expect(desktop.tv).toBe(false);
41
+ expect(desktop.source).toBe("override");
42
+ expect(parseOverride("?layout=mobile", "tv")).toBe("mobile");
43
+ expect(parseOverride("?tv", null)).toBe("tv");
44
+ expect(parseOverride("?layout=invalid", null)).toBeNull();
45
+ });
46
+ test("D-pad selects an aligned target and never moves backwards", () => {
47
+ const from = { left: 0, top: 0, right: 100, bottom: 100 };
48
+ expect(
49
+ pickNext(
50
+ from,
51
+ [
52
+ { item: "aligned", box: { left: 0, top: 150, right: 100, bottom: 250 } },
53
+ { item: "side", box: { left: 200, top: 110, right: 300, bottom: 210 } },
54
+ { item: "behind", box: { left: 0, top: -150, right: 100, bottom: -50 } },
55
+ ],
56
+ "down",
57
+ ),
58
+ ).toBe("aligned");
59
+ expect(pickNext(from, [], "left")).toBeUndefined();
60
+ });
61
+ test("hash destinations preserve direct links", () => {
62
+ expect(parseRoute("#/theme")).toBe("theme");
63
+ expect(parseRoute("#/reader/?page=2")).toBe("reader");
64
+ expect(parseRoute("")).toBe("overview");
65
+ });
66
+ test("inventory uses the selected workspace's exclusions", () => {
67
+ mkdirSync(join(root, "packages/private"), { recursive: true });
68
+ mkdirSync(join(root, "packages/public"), { recursive: true });
69
+ writeFileSync(
70
+ join(root, "package.json"),
71
+ JSON.stringify({ workspaces: { packages: ["packages/*", "!packages/private"] } }),
72
+ );
73
+ for (const name of ["private", "public"])
74
+ writeFileSync(
75
+ join(root, "packages", name, "package.json"),
76
+ JSON.stringify({ name: `@fixture/${name}`, version: "1.0.0" }),
77
+ );
78
+ const entries = collect(root);
79
+ expect(entries.find((entry) => entry.name === "@fixture/private")!.workspace).toBe(false);
80
+ expect(entries.find((entry) => entry.name === "@fixture/public")!.workspace).toBe(true);
81
+ });
82
+ test("capture planning rejects output traversal and invalid layout input", () => {
83
+ expect(() => plan(["../../outside"])).toThrow("Unknown showcase route");
84
+ expect(() => plan(["overview"], ["bad" as "tv"])).toThrow("Unknown layout");
85
+ expect(plan(["overview", "adaptive"], ["mobile", "tv"], ["light", "dark"])).toHaveLength(8);
86
+ });
87
+ });
@@ -0,0 +1,183 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { afterEach, describe, expect, spyOn, test } from "bun:test";
3
+ import { mkdtemp, rm, writeFile } from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import { join, resolve } from "node:path";
6
+ import {
7
+ generateIcons,
8
+ ICON_SOURCE,
9
+ iconCommand,
10
+ TAURI_ROOT,
11
+ SHOWCASE_ROOT,
12
+ } from "../scripts/icons";
13
+ import {
14
+ assertFactoryHost,
15
+ CARGO_RUNNER,
16
+ prepareShowcaseHost,
17
+ serializedTauriCommand,
18
+ runTauri,
19
+ showcaseShellFiles,
20
+ sidecarCommand,
21
+ tauriHostPlan,
22
+ } from "../scripts/tauri";
23
+
24
+ const installed = (name: string) =>
25
+ ["tauri", "cargo", "rustc", "java"].includes(name) ? "/installed/" + name : null;
26
+
27
+ let temporary: string | undefined;
28
+ afterEach(async () => {
29
+ if (temporary) await rm(temporary, { recursive: true, force: true });
30
+ temporary = undefined;
31
+ });
32
+
33
+ describe("showcase host delivery contract", () => {
34
+ test("uses canonical artwork and the installed owner without downloading replacements", async () => {
35
+ expect(await Bun.file(ICON_SOURCE).exists()).toBe(true);
36
+ expect(iconCommand("/consumer", "/installed/tauri")).toEqual([
37
+ "/installed/tauri",
38
+ "icon",
39
+ ICON_SOURCE,
40
+ "--output",
41
+ "/consumer/icons",
42
+ "--ios-color",
43
+ "#6750a4",
44
+ ]);
45
+ expect(() => iconCommand("/consumer", null)).toThrow("installed Tauri CLI");
46
+ });
47
+ test("the icon plan defaults to the canonical Rust owner's packaging directory", async () => {
48
+ const which = spyOn(Bun, "which").mockReturnValue("/installed/tauri");
49
+ const output = spyOn(console, "log").mockImplementation(() => {});
50
+ try {
51
+ await generateIcons(["--plan"]);
52
+ expect(output).toHaveBeenCalledTimes(1);
53
+ const plan = JSON.parse(String(output.mock.calls[0]?.[0]));
54
+ expect(plan.source).toBe(ICON_SOURCE);
55
+ expect(plan.output).toBe(resolve(TAURI_ROOT, "icons"));
56
+ expect(plan.command).toEqual(iconCommand(TAURI_ROOT, "/installed/tauri"));
57
+ const config = await Bun.file(resolve(TAURI_ROOT, "tauri.conf.json")).json();
58
+ for (const icon of config.bundle.icon)
59
+ expect(resolve(TAURI_ROOT, icon).startsWith(plan.output + "/")).toBe(true);
60
+ } finally {
61
+ output.mockRestore();
62
+ which.mockRestore();
63
+ }
64
+ });
65
+ test("the host has a real mobile entry and no ambient privileged namespace", () => {
66
+ const files = showcaseShellFiles();
67
+ const config = JSON.parse(String(files["tauri.conf.json"]));
68
+ expect(config.build.frontendDist).toBe("../../../m3/apps/showcase/dist");
69
+ expect(config.app.windows).toEqual([]);
70
+ expect(config.bundle.externalBin).toEqual(["binaries/m3-showcase"]);
71
+ const wrap = JSON.parse(String(files["wrap.json"]));
72
+ expect(wrap.mode).toBe("sidecar");
73
+ expect(wrap.sidecar).toEqual({
74
+ program: "m3-showcase",
75
+ args: [],
76
+ port: 0,
77
+ readyPath: "/healthz",
78
+ readyTimeoutSecs: 30,
79
+ env: {},
80
+ });
81
+ expect(files["Cargo.toml"]).toContain("aphrody-tauri-wrap.workspace = true");
82
+ expect(files["Cargo.toml"]).toContain("tauri-runtime-wry.workspace = true");
83
+ expect(files["Cargo.toml"]).not.toContain("[workspace]");
84
+ expect(files["src/lib.rs"]).toContain('aphrody_tauri_wrap::init(include_str!("../wrap.json"))');
85
+ expect(config.build.beforeBuildCommand).toContain("scripts/tauri.ts sidecar");
86
+ expect(config.app.withGlobalTauri).toBeUndefined();
87
+ expect(config.app.security.csp).toContain("object-src 'none'");
88
+ expect(config.app.security.csp).toContain("script-src 'self'");
89
+ expect(files["src/lib.rs"]).toContain("tauri::mobile_entry_point");
90
+ expect(JSON.parse(String(files["capabilities/default.json"])).permissions).toEqual([]);
91
+ expect(files[".gitignore"]).toContain("/icons/");
92
+ });
93
+ test("the concrete native owner inherits workspace identities and resolves the canonical frontend", async () => {
94
+ const manifest = Bun.TOML.parse(await Bun.file(resolve(TAURI_ROOT, "Cargo.toml")).text()) as {
95
+ dependencies: Record<string, { workspace?: boolean }>;
96
+ "build-dependencies": Record<string, { workspace?: boolean }>;
97
+ };
98
+ for (const name of ["tauri", "tauri-runtime-wry", "aphrody-tauri-wrap"])
99
+ expect(manifest.dependencies[name]?.workspace).toBe(true);
100
+ expect(manifest["build-dependencies"]["tauri-build"]?.workspace).toBe(true);
101
+ const config = await Bun.file(resolve(TAURI_ROOT, "tauri.conf.json")).json();
102
+ expect(resolve(TAURI_ROOT, config.build.frontendDist)).toBe(resolve(SHOWCASE_ROOT, "dist"));
103
+ const plan = tauriHostPlan(["build"], {}, "linux", installed);
104
+ expect(plan.hostOwner).toBe(TAURI_ROOT);
105
+ expect(plan.apiOwner).toBe(SHOWCASE_ROOT);
106
+ expect(() =>
107
+ serializedTauriCommand(["build", "--", "--manifest-path", "/other/Cargo.toml"], "/tauri"),
108
+ ).toThrow("manifest");
109
+ });
110
+ test("Android and iOS diagnostics require their actual platform toolchains", () => {
111
+ expect(
112
+ tauriHostPlan(["android", "build"], {}, "linux", installed).missing.join("; "),
113
+ ).toContain("Android SDK");
114
+ expect(
115
+ tauriHostPlan(["android", "build"], {}, "linux", installed).missing.join("; "),
116
+ ).toContain("Android NDK");
117
+ expect(tauriHostPlan(["ios", "build"], {}, "linux", installed).missing.join("; ")).toContain(
118
+ "macOS/Xcode",
119
+ );
120
+ expect(tauriHostPlan(["build"], {}, "linux", () => null).missing).toHaveLength(3);
121
+ });
122
+ test("desktop compilation keeps factory admission and the canonical Cargo lock", () => {
123
+ const local = {
124
+ configured: true,
125
+ enabled: true,
126
+ target: "vps",
127
+ host: null,
128
+ localCargo: true,
129
+ route: "local" as const,
130
+ reason: "diagnostic",
131
+ };
132
+ expect(() => assertFactoryHost(local)).toThrow("Workspace build factory");
133
+ expect(() => assertFactoryHost({ ...local, configured: false, host: "vps" })).toThrow(
134
+ "Workspace build factory",
135
+ );
136
+ expect(() => assertFactoryHost({ ...local, host: "vps", route: "factory" })).toThrow(
137
+ "Workspace build factory",
138
+ );
139
+ expect(() => assertFactoryHost({ ...local, host: "vps", localCargo: false })).not.toThrow();
140
+ expect(serializedTauriCommand(["build", "--", "--release"], "/installed/tauri")).toEqual([
141
+ "/installed/tauri",
142
+ "build",
143
+ "--runner",
144
+ CARGO_RUNNER,
145
+ "--",
146
+ "--release",
147
+ "--manifest-path",
148
+ resolve(TAURI_ROOT, "Cargo.toml"),
149
+ "--package",
150
+ "aphrody-m3-showcase",
151
+ ]);
152
+ expect(() => serializedTauriCommand(["build", "--runner=unlocked-cargo"], "/tauri")).toThrow(
153
+ "Cargo runner",
154
+ );
155
+ expect(tauriHostPlan(["build"], {}, "linux", () => "/installed").execution).toBe(
156
+ "workspace-build-factory",
157
+ );
158
+ expect(() => serializedTauriCommand(["android", "build"], "/tauri")).toThrow(
159
+ "API host adapter",
160
+ );
161
+ });
162
+ test("global options cannot turn a local inspection into an unguarded heavy command", async () => {
163
+ await expect(runTauri(["-v", "build"])).rejects.toThrow("global options cannot bypass");
164
+ expect(() => serializedTauriCommand(["build", "-rcargo"], "/tauri")).toThrow("Cargo runner");
165
+ });
166
+ test("sidecar target names match Tauri packaging and unsupported mobile hosts fail clearly", () => {
167
+ const linux = sidecarCommand("x86_64-unknown-linux-gnu", "/consumer");
168
+ expect(linux).toContain("linux-x64");
169
+ expect(linux.at(-1)).toBe("/consumer/binaries/m3-showcase-x86_64-unknown-linux-gnu");
170
+ const windows = sidecarCommand("x86_64-pc-windows-msvc", "/consumer");
171
+ expect(windows).toContain("windows-x64");
172
+ expect(windows.at(-1)).toEndWith("m3-showcase-x86_64-pc-windows-msvc.exe");
173
+ expect(() => sidecarCommand("aarch64-linux-android")).toThrow("canonical API host adapter");
174
+ });
175
+ test("preparation fills missing shell files and preserves existing host configuration", async () => {
176
+ temporary = await mkdtemp(join(tmpdir(), "m3-showcase-host-"));
177
+ const path = join(temporary, "tauri.conf.json");
178
+ await writeFile(path, '{"owner":"preserved"}');
179
+ await prepareShowcaseHost(temporary);
180
+ expect(await Bun.file(path).text()).toBe('{"owner":"preserved"}');
181
+ expect(await Bun.file(join(temporary, "src/lib.rs")).exists()).toBe(true);
182
+ });
183
+ });
@@ -0,0 +1,138 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { describe, expect, test } from "bun:test";
3
+ import { routesToFetch } from "@aphrody/m3-bun/api";
4
+ import routes from "../src/api/index.ts";
5
+
6
+ const handler = routesToFetch(routes);
7
+ async function request(path: string, init?: RequestInit): Promise<Response> {
8
+ const response = await handler(new Request("http://m3.test" + path, init));
9
+ if (!response) throw new Error("Missing showcase endpoint: " + path);
10
+ return response;
11
+ }
12
+ function post(path: string, body: unknown): Promise<Response> {
13
+ return request(path, {
14
+ method: "POST",
15
+ headers: { "Content-Type": "application/json" },
16
+ body: JSON.stringify(body),
17
+ });
18
+ }
19
+
20
+ describe("showcase package computations", () => {
21
+ test("design compiles a brief and migration applies the actual transform", async () => {
22
+ const design = await post("/api/design", {
23
+ brief: "A minimal dashboard for developers with a list-detail layout.",
24
+ seed: "#123456",
25
+ });
26
+ expect(design.status).toBe(200);
27
+ const output = await design.json();
28
+ expect(output.files.some((file: { path: string }) => file.path === "src/theme.css")).toBe(true);
29
+ expect(output.theme.palettes.primary.tones[40]).toMatch(/^#[a-f\d]{6}$/i);
30
+ const migrated = await post("/api/migrate", {
31
+ source:
32
+ 'import { Button } from "@mui/material"; export default () => <Button variant="contained">Save</Button>;',
33
+ });
34
+ expect(migrated.status).toBe(200);
35
+ const migration = await migrated.json();
36
+ expect(migration.source).toContain("@aphrody/m3-react");
37
+ expect(migration.source).toContain("<MdFilledButton>Save</MdFilledButton>");
38
+ expect(migration.diagnostics).toEqual([]);
39
+ });
40
+
41
+ test("system discovers the real MCP server, lint rules and generated files", async () => {
42
+ const response = await request("/api/system?target=cosmic&seed=%236750a4");
43
+ expect(response.status).toBe(200);
44
+ const data = await response.json();
45
+ expect(data.mcpTools.map((tool: { name: string }) => tool.name)).toContain("m3_symbol_search");
46
+ expect(data.lintRules.length).toBeGreaterThan(0);
47
+ expect(data.themeFiles.length).toBeGreaterThan(0);
48
+ expect(data.themeFiles.every((file: { target: string }) => file.target === "cosmic")).toBe(
49
+ true,
50
+ );
51
+ expect(data.scaffold["m3.config.ts"]).toContain("@aphrody/m3/config");
52
+ const file = data.themeFiles.find((entry: { binary: boolean }) => !entry.binary);
53
+ const theme = await request(
54
+ "/api/os-theme?target=cosmic&path=" + encodeURIComponent(file.path),
55
+ );
56
+ expect(theme.status).toBe(200);
57
+ expect((await theme.json()).content.length).toBeGreaterThan(0);
58
+ });
59
+
60
+ test("Next outputs use the requested origin and canonical theme roles", async () => {
61
+ const response = await request("/api/next?seed=%236750a4");
62
+ expect(response.status).toBe(200);
63
+ const data = await response.json();
64
+ expect(data.schemeCss).toContain("--md-sys-color-primary");
65
+ expect(data.robots).toContain("http://m3.test/sitemap.xml");
66
+ expect(data.sitemap).toContain("http://m3.test/components");
67
+ expect(data.jsonLd).toContain("Aphrody M3 Showcase");
68
+ });
69
+ });
70
+
71
+ describe("showcase request boundaries", () => {
72
+ test("rejects malformed, missing, oversized and non-object JSON", async () => {
73
+ for (const body of ["{", "null", "[]", JSON.stringify({ prompt: "x".repeat(70_000) })]) {
74
+ // eslint-disable-next-line no-await-in-loop -- Exercise each independent malformed body against the bounded request reader.
75
+ expect((await request("/api/ai/stream", { method: "POST", body })).status).toBe(400);
76
+ }
77
+ expect((await request("/api/ai/stream", { method: "POST" })).status).toBe(400);
78
+ });
79
+
80
+ test("rejects invalid themes, migration syntax and files outside generated output", async () => {
81
+ expect((await post("/api/design", { brief: "Dashboard", seed: "oops" })).status).toBe(400);
82
+ expect((await request("/api/next?seed=invalid")).status).toBe(400);
83
+ expect((await request("/api/system?target=unknown")).status).toBe(400);
84
+ expect((await request("/api/os-theme?path=../../secrets")).status).toBe(404);
85
+ expect((await post("/api/migrate", { source: "export default <" })).status).toBe(400);
86
+ expect((await post("/api/migrate", { source: "const x = 1;", kind: "unknown" })).status).toBe(
87
+ 400,
88
+ );
89
+ });
90
+
91
+ test("fonts are allowlisted, immutable per ETag, and HEAD has no body", async () => {
92
+ const path = "/api/m3/fonts/GoogleSansCode-latin.woff2";
93
+ const response = await request(path);
94
+ expect(response.status).toBe(200);
95
+ expect(response.headers.get("content-type")).toBe("font/woff2");
96
+ expect(response.headers.get("cache-control")).toContain("max-age");
97
+ const bytes = new Uint8Array(await response.arrayBuffer());
98
+ expect(new TextDecoder().decode(bytes.slice(0, 4))).toBe("wOF2");
99
+ const tag = response.headers.get("etag")!;
100
+ expect((await request(path, { headers: { "If-None-Match": tag } })).status).toBe(304);
101
+ const head = await request(path, { method: "HEAD" });
102
+ expect(head.status).toBe(200);
103
+ expect(head.headers.get("etag")).toBe(tag);
104
+ expect(await head.text()).toBe("");
105
+ const mono = await request("/api/m3/fonts/RobotoMono-latin.woff2");
106
+ expect(mono.status).toBe(200);
107
+ await mono.body?.cancel();
108
+ expect((await request("/api/m3/fonts/unknown.woff2")).status).toBe(404);
109
+ expect((await request("/api/m3/fonts/%2e%2e%2fRobotoMono-latin.woff2")).status).toBe(404);
110
+ });
111
+
112
+ test("AG-UI fixture completes and abort closes its producer", async () => {
113
+ const response = await post("/api/ai/stream", { prompt: "Inspect the package inventory." });
114
+ expect(response.headers.get("x-m3-fixture")).toBe("true");
115
+ const events = (await response.text())
116
+ .split("\n\n")
117
+ .filter(Boolean)
118
+ .map((frame) => JSON.parse(frame.replace(/^data:\s*/, "")));
119
+ expect(events[0].type).toBe("RUN_STARTED");
120
+ expect(events.at(-1).type).toBe("RUN_FINISHED");
121
+ expect(events.find((event) => event.type === "TOOL_CALL_RESULT").content).toContain(
122
+ "build inventory",
123
+ );
124
+ const controller = new AbortController();
125
+ const interrupted = await request("/api/ai/stream", {
126
+ method: "POST",
127
+ body: JSON.stringify({ prompt: "Interrupt this fixture." }),
128
+ signal: controller.signal,
129
+ });
130
+ const reader = interrupted.body!.getReader();
131
+ expect((await reader.read()).done).toBe(false);
132
+ controller.abort(new Error("fixture stopped"));
133
+ await expect(reader.read()).rejects.toThrow("fixture stopped");
134
+ reader.releaseLock();
135
+ const cancelled = await post("/api/ai/stream", { prompt: "Cancel without abort." });
136
+ await cancelled.body!.cancel();
137
+ });
138
+ });
@@ -0,0 +1,78 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { afterEach, expect, test } from "bun:test";
3
+ import { activeModal, attachDpad, focusables } from "../src/adaptive/dpad.ts";
4
+ afterEach(() => {
5
+ document.body.innerHTML = "";
6
+ });
7
+ function button(parent: HTMLElement, label: string): HTMLButtonElement {
8
+ const node = document.createElement("button");
9
+ node.textContent = label;
10
+ node.getBoundingClientRect = () => ({
11
+ x: 0,
12
+ y: 0,
13
+ left: 0,
14
+ top: 0,
15
+ right: 20,
16
+ bottom: 20,
17
+ width: 20,
18
+ height: 20,
19
+ toJSON() {},
20
+ });
21
+ parent.append(node);
22
+ return node;
23
+ }
24
+ test("D-pad ignores controls hidden or disabled by ancestors", () => {
25
+ const visible = button(document.body, "Visible");
26
+ const hidden = document.createElement("div");
27
+ hidden.setAttribute("aria-hidden", "true");
28
+ document.body.append(hidden);
29
+ button(hidden, "Hidden");
30
+ const inert = document.createElement("div");
31
+ inert.setAttribute("inert", "");
32
+ document.body.append(inert);
33
+ button(inert, "Inert");
34
+ const disabled = document.createElement("fieldset");
35
+ disabled.disabled = true;
36
+ document.body.append(disabled);
37
+ button(disabled, "Disabled fieldset");
38
+ expect(focusables(document).map((element) => element.textContent)).toEqual([visible.textContent]);
39
+ });
40
+ test("hidden modal containers do not steal the D-pad focus scope", () => {
41
+ const live = document.createElement("section");
42
+ live.setAttribute("aria-modal", "true");
43
+ document.body.append(live);
44
+ const stale = document.createElement("section");
45
+ stale.setAttribute("aria-modal", "true");
46
+ stale.hidden = true;
47
+ document.body.append(stale);
48
+ expect(activeModal(document) === live).toBe(true);
49
+ });
50
+ test("Back calls a custom dialog's close method and disposal removes the handler", () => {
51
+ const dialog = document.createElement("md-dialog") as HTMLElement & { close(): void };
52
+ dialog.setAttribute("open", "");
53
+ let closes = 0;
54
+ dialog.close = () => {
55
+ closes++;
56
+ dialog.removeAttribute("open");
57
+ };
58
+ document.body.append(dialog);
59
+ let backs = 0;
60
+ const dispose = attachDpad({
61
+ onBack: () => {
62
+ backs++;
63
+ },
64
+ });
65
+ document.dispatchEvent(
66
+ new KeyboardEvent("keydown", { key: "Escape", bubbles: true, cancelable: true }),
67
+ );
68
+ expect(closes).toBe(1);
69
+ document.dispatchEvent(
70
+ new KeyboardEvent("keydown", { key: "Escape", bubbles: true, cancelable: true }),
71
+ );
72
+ expect(backs).toBe(1);
73
+ dispose();
74
+ document.dispatchEvent(
75
+ new KeyboardEvent("keydown", { key: "Escape", bubbles: true, cancelable: true }),
76
+ );
77
+ expect(backs).toBe(1);
78
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "@aphrody/m3-config/tsconfig.json",
3
+ "compilerOptions": {
4
+ "target": "ES2023",
5
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
6
+ "types": ["bun", "node"],
7
+ "noUnusedLocals": true,
8
+ "noUnusedParameters": true
9
+ },
10
+ "include": ["src/**/*", "scripts/**/*", "test/**/*", "m3.config.ts"]
11
+ }