@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,383 @@
1
+ // The adaptive shell. One component tree, three layouts chosen from the window size class and the layout mode:
2
+ // mobile (compact) top app bar, content, bottom navigation bar, "More" sheet for the other destinations
3
+ // desktop (medium and up) navigation rail (medium, expanded) or standard drawer (large, extra large) beside the content
4
+ // tv 10-foot drawer, large type, focus ring, D-pad (arrow keys + Enter + Back) navigation
5
+ import { useM3Theme } from "@aphrody/m3-theme/react";
6
+ import { Component, Suspense, useEffect, useRef, useState, type ReactNode } from "react";
7
+ import closeIcon from "m3:icons/close";
8
+ import contrastIcon from "m3:icons/contrast";
9
+ import darkIcon from "m3:icons/dark_mode";
10
+ import lightIcon from "m3:icons/light_mode";
11
+ import { attachDpad } from "../adaptive/dpad.ts";
12
+ import { useAdaptive, type AdaptiveState } from "../adaptive/window.ts";
13
+ import { Svg } from "../components/ui.tsx";
14
+ import { PAGES } from "../pages/index.ts";
15
+ import { useRoute } from "../router.ts";
16
+ import {
17
+ DESTINATIONS,
18
+ MORE_ICON,
19
+ MORE_ICON_FILLED,
20
+ PRIMARY_IDS,
21
+ findDestination,
22
+ type Destination,
23
+ } from "./nav.ts";
24
+
25
+ const MODE_LABEL = { light: "Light", dark: "Dark", system: "System" } as const;
26
+
27
+ function ThemeModeButton() {
28
+ const { themeMode, setThemeMode } = useM3Theme();
29
+ const next = themeMode === "system" ? "light" : themeMode === "light" ? "dark" : "system";
30
+ const icon = themeMode === "light" ? lightIcon : themeMode === "dark" ? darkIcon : contrastIcon;
31
+ return (
32
+ <button
33
+ type="button"
34
+ className="state-layer inline-flex size-12 items-center justify-center rounded-full text-on-surface-variant"
35
+ aria-label={`Colour scheme: ${MODE_LABEL[themeMode]}. Switch to ${MODE_LABEL[next]}`}
36
+ title={`Colour scheme: ${MODE_LABEL[themeMode]}`}
37
+ onClick={() => setThemeMode(next)}
38
+ >
39
+ <Svg html={icon} />
40
+ </button>
41
+ );
42
+ }
43
+
44
+ function TopBar({ a, current }: { a: AdaptiveState; current: Destination }) {
45
+ return (
46
+ <header
47
+ className="flex h-16 shrink-0 items-center gap-2 bg-surface px-(--m3-gutter) text-on-surface"
48
+ role="banner"
49
+ >
50
+ <div
51
+ className={`${a.mode === "tv" ? "text-headline-medium" : "text-title-large"} flex-1 truncate`}
52
+ data-testid="top-title"
53
+ >
54
+ {a.mode === "mobile" ? current.label : `Aphrody M3 / ${current.label}`}
55
+ </div>
56
+ <span
57
+ className="hidden rounded-full bg-secondary-container px-3 py-1 text-label-medium text-on-secondary-container expanded:inline"
58
+ data-testid="window-class"
59
+ title="Window size class, M3 breakpoints"
60
+ >
61
+ {a.width} · {a.mode}
62
+ </span>
63
+ <ThemeModeButton />
64
+ </header>
65
+ );
66
+ }
67
+
68
+ function NavItem({
69
+ item,
70
+ selected,
71
+ variant,
72
+ onSelect,
73
+ }: {
74
+ item: Destination;
75
+ selected: boolean;
76
+ variant: "bar" | "rail" | "drawer";
77
+ onSelect: (id: string) => void;
78
+ }) {
79
+ const icon = <Svg html={selected ? item.iconFilled : item.icon} />;
80
+ if (variant === "drawer") {
81
+ return (
82
+ <a
83
+ href={`#/${item.id}`}
84
+ data-dpad
85
+ data-testid={`nav-${item.id}`}
86
+ aria-current={selected ? "page" : undefined}
87
+ className={`state-layer flex h-14 w-full items-center gap-3 rounded-full px-4 text-label-large ${selected ? "bg-secondary-container text-on-secondary-container" : "text-on-surface-variant"}`}
88
+ onClick={(event) => {
89
+ if (
90
+ event.button === 0 &&
91
+ !event.metaKey &&
92
+ !event.ctrlKey &&
93
+ !event.shiftKey &&
94
+ !event.altKey
95
+ ) {
96
+ event.preventDefault();
97
+ onSelect(item.id);
98
+ }
99
+ }}
100
+ >
101
+ {icon}
102
+ <span className="truncate">{item.label}</span>
103
+ </a>
104
+ );
105
+ }
106
+ return (
107
+ <a
108
+ href={`#/${item.id}`}
109
+ data-dpad
110
+ data-testid={`nav-${item.id}`}
111
+ aria-current={selected ? "page" : undefined}
112
+ className={`state-layer group flex ${variant === "bar" ? "flex-1 py-3" : "w-full py-1.5"} flex-col items-center gap-1 text-label-medium ${selected ? "text-on-surface" : "text-on-surface-variant"}`}
113
+ onClick={() => onSelect(item.id)}
114
+ >
115
+ <span
116
+ className={`flex h-8 w-16 items-center justify-center rounded-full ${selected ? "bg-secondary-container text-on-secondary-container" : ""}`}
117
+ >
118
+ {icon}
119
+ </span>
120
+ <span className="max-w-full truncate px-1">{item.label}</span>
121
+ </a>
122
+ );
123
+ }
124
+
125
+ function SideNav({
126
+ a,
127
+ route,
128
+ navigate,
129
+ }: {
130
+ a: AdaptiveState;
131
+ route: string;
132
+ navigate: (id: string) => void;
133
+ }) {
134
+ const drawer = a.mode === "tv" || a.navigation === "rail-expanded";
135
+ return (
136
+ <nav
137
+ aria-label="Destinations"
138
+ className={`m3-scroll flex shrink-0 flex-col gap-1 overflow-y-auto bg-surface p-3 ${drawer ? (a.mode === "tv" ? "w-[19rem]" : "w-[22.5rem]") : "w-24"}`}
139
+ data-testid={drawer ? "drawer" : "rail"}
140
+ >
141
+ {DESTINATIONS.map((item) => (
142
+ <NavItem
143
+ key={item.id}
144
+ item={item}
145
+ selected={route === item.id}
146
+ variant={drawer ? "drawer" : "rail"}
147
+ onSelect={navigate}
148
+ />
149
+ ))}
150
+ </nav>
151
+ );
152
+ }
153
+
154
+ function BottomBar({
155
+ route,
156
+ navigate,
157
+ onMore,
158
+ }: {
159
+ route: string;
160
+ navigate: (id: string) => void;
161
+ onMore: () => void;
162
+ }) {
163
+ const primary = PRIMARY_IDS.map(findDestination);
164
+ const moreSelected = !PRIMARY_IDS.includes(route as (typeof PRIMARY_IDS)[number]);
165
+ return (
166
+ <nav
167
+ aria-label="Destinations"
168
+ className="flex h-20 shrink-0 items-stretch bg-surface-container px-2 pb-[env(safe-area-inset-bottom)]"
169
+ data-testid="bottom-bar"
170
+ >
171
+ {primary.map((item) => (
172
+ <NavItem
173
+ key={item.id}
174
+ item={item}
175
+ selected={route === item.id}
176
+ variant="bar"
177
+ onSelect={navigate}
178
+ />
179
+ ))}
180
+ <button
181
+ type="button"
182
+ data-testid="nav-more"
183
+ aria-haspopup="dialog"
184
+ className={`state-layer flex flex-1 flex-col items-center gap-1 py-3 text-label-medium ${moreSelected ? "text-on-surface" : "text-on-surface-variant"}`}
185
+ onClick={onMore}
186
+ >
187
+ <span
188
+ className={`flex h-8 w-16 items-center justify-center rounded-full ${moreSelected ? "bg-secondary-container text-on-secondary-container" : ""}`}
189
+ >
190
+ <Svg html={moreSelected ? MORE_ICON_FILLED : MORE_ICON} />
191
+ </span>
192
+ <span>More</span>
193
+ </button>
194
+ </nav>
195
+ );
196
+ }
197
+
198
+ /** The destinations behind "More", as a modal bottom sheet on a native <dialog> (focus trap and Escape for free). */
199
+ function MoreSheet({
200
+ open,
201
+ route,
202
+ navigate,
203
+ onClose,
204
+ }: {
205
+ open: boolean;
206
+ route: string;
207
+ navigate: (id: string) => void;
208
+ onClose: () => void;
209
+ }) {
210
+ const ref = useRef<HTMLDialogElement>(null);
211
+ useEffect(() => {
212
+ const dialog = ref.current;
213
+ if (!dialog) return;
214
+ if (open && !dialog.open) dialog.showModal();
215
+ if (!open && dialog.open) dialog.close();
216
+ }, [open]);
217
+ return (
218
+ <dialog
219
+ ref={ref}
220
+ onClose={onClose}
221
+ onClick={(event) => event.target === ref.current && onClose()}
222
+ className="m-0 mt-auto w-full max-w-none rounded-t-extra-large bg-surface-container-low p-4 text-on-surface backdrop:bg-scrim/32"
223
+ data-testid="more-sheet"
224
+ aria-label="All destinations"
225
+ >
226
+ <div className="mb-2 flex items-center justify-between">
227
+ <h2 className="text-title-large">All destinations</h2>
228
+ <button
229
+ type="button"
230
+ className="state-layer inline-flex size-12 items-center justify-center rounded-full"
231
+ aria-label="Close"
232
+ onClick={onClose}
233
+ >
234
+ <Svg html={closeIcon} />
235
+ </button>
236
+ </div>
237
+ <div className="grid grid-cols-3 gap-2">
238
+ {DESTINATIONS.map((item) => (
239
+ <a
240
+ key={item.id}
241
+ href={`#/${item.id}`}
242
+ data-testid={`more-${item.id}`}
243
+ aria-current={route === item.id ? "page" : undefined}
244
+ className={`state-layer flex flex-col items-center gap-1 rounded-large p-3 text-label-medium ${route === item.id ? "bg-secondary-container text-on-secondary-container" : "text-on-surface-variant"}`}
245
+ onClick={(event) => {
246
+ if (
247
+ event.button === 0 &&
248
+ !event.metaKey &&
249
+ !event.ctrlKey &&
250
+ !event.shiftKey &&
251
+ !event.altKey
252
+ ) {
253
+ event.preventDefault();
254
+ navigate(item.id);
255
+ onClose();
256
+ }
257
+ }}
258
+ >
259
+ <Svg html={route === item.id ? item.iconFilled : item.icon} />
260
+ <span className="truncate">{item.label}</span>
261
+ </a>
262
+ ))}
263
+ </div>
264
+ </dialog>
265
+ );
266
+ }
267
+
268
+ function PageSlot({
269
+ a,
270
+ route,
271
+ children,
272
+ }: {
273
+ a: AdaptiveState;
274
+ route: string;
275
+ children: ReactNode;
276
+ }) {
277
+ const heading = useRef<HTMLDivElement>(null);
278
+ useEffect(() => {
279
+ // After a route change the page, not the nav, takes focus: screen readers announce the new title. TV keeps the nav focused.
280
+ if (a.mode !== "tv") heading.current?.focus({ preventScroll: true });
281
+ }, [route, a.mode]);
282
+ return (
283
+ <main
284
+ id="main"
285
+ ref={heading}
286
+ tabIndex={-1}
287
+ className="m3-scroll min-w-0 flex-1 overflow-y-auto rounded-tl-extra-large bg-surface-container-lowest outline-none"
288
+ data-testid="main"
289
+ data-route={route}
290
+ aria-labelledby="page-title"
291
+ >
292
+ {children}
293
+ </main>
294
+ );
295
+ }
296
+
297
+ class PageBoundary extends Component<{ children: ReactNode }, { failed: boolean }> {
298
+ override state = { failed: false };
299
+ static getDerivedStateFromError() {
300
+ return { failed: true };
301
+ }
302
+ override render() {
303
+ if (this.state.failed)
304
+ return (
305
+ <div className="p-6" role="alert">
306
+ <h1 id="page-title" className="text-headline-medium">
307
+ Unable to load this page
308
+ </h1>
309
+ <p>Reload to try again.</p>
310
+ <button
311
+ type="button"
312
+ className="state-layer rounded-full bg-primary px-6 py-3 text-on-primary"
313
+ onClick={() => location.reload()}
314
+ >
315
+ Reload
316
+ </button>
317
+ </div>
318
+ );
319
+ return this.props.children;
320
+ }
321
+ }
322
+
323
+ export function Shell() {
324
+ const a = useAdaptive();
325
+ const { route, navigate } = useRoute();
326
+ const [more, setMore] = useState(false);
327
+ const current = findDestination(route);
328
+ const Page = PAGES[current.id];
329
+
330
+ useEffect(
331
+ () =>
332
+ a.mode === "tv" || document.documentElement.dataset["dpad"] === "on"
333
+ ? attachDpad({ onBack: () => history.back() })
334
+ : undefined,
335
+ [a.mode],
336
+ );
337
+ useEffect(() => {
338
+ document.title = `${current.label} · Aphrody M3 Showcase`;
339
+ }, [current.label]);
340
+
341
+ return (
342
+ <div className="flex h-full flex-col bg-surface" data-testid="shell" data-layout={a.mode}>
343
+ <a
344
+ href="#main"
345
+ onClick={(event) => {
346
+ event.preventDefault();
347
+ document.getElementById("main")?.focus();
348
+ }}
349
+ className="sr-only focus:not-sr-only focus:absolute focus:left-2 focus:top-2 focus:z-50 focus:rounded-full focus:bg-primary focus:px-4 focus:py-2 focus:text-on-primary"
350
+ >
351
+ Skip to content
352
+ </a>
353
+ <TopBar a={a} current={current} />
354
+ <div className="flex min-h-0 flex-1">
355
+ {a.mode !== "mobile" ? <SideNav a={a} route={current.id} navigate={navigate} /> : null}
356
+ <PageSlot a={a} route={current.id}>
357
+ <PageBoundary key={current.id}>
358
+ <Suspense
359
+ fallback={
360
+ <div className="p-6 text-body-medium text-on-surface-variant" role="status">
361
+ Loading {current.label}…
362
+ </div>
363
+ }
364
+ >
365
+ <Page adaptive={a} />
366
+ </Suspense>
367
+ </PageBoundary>
368
+ </PageSlot>
369
+ </div>
370
+ {a.mode === "mobile" ? (
371
+ <BottomBar route={current.id} navigate={navigate} onMore={() => setMore(true)} />
372
+ ) : null}
373
+ {a.mode === "mobile" ? (
374
+ <MoreSheet
375
+ open={more}
376
+ route={current.id}
377
+ navigate={navigate}
378
+ onClose={() => setMore(false)}
379
+ />
380
+ ) : null}
381
+ </div>
382
+ );
383
+ }
@@ -0,0 +1,198 @@
1
+ // Destinations of the showcase: one per group of packages, each with the packages it demonstrates.
2
+ import appsIcon from "m3:icons/apps";
3
+ import appsFilled from "m3:icons/apps?fill=1";
4
+ import badgeIcon from "m3:icons/badge";
5
+ import badgeFilled from "m3:icons/badge?fill=1";
6
+ import designIcon from "m3:icons/design_services";
7
+ import designFilled from "m3:icons/design_services?fill=1";
8
+ import devicesIcon from "m3:icons/devices";
9
+ import devicesFilled from "m3:icons/devices?fill=1";
10
+ import editIcon from "m3:icons/edit_note";
11
+ import editFilled from "m3:icons/edit_note?fill=1";
12
+ import folderIcon from "m3:icons/folder";
13
+ import folderFilled from "m3:icons/folder?fill=1";
14
+ import homeIcon from "m3:icons/home";
15
+ import homeFilled from "m3:icons/home?fill=1";
16
+ import motionIcon from "m3:icons/animation";
17
+ import motionFilled from "m3:icons/animation?fill=1";
18
+ import paletteIcon from "m3:icons/palette";
19
+ import paletteFilled from "m3:icons/palette?fill=1";
20
+ import readerIcon from "m3:icons/menu_book";
21
+ import readerFilled from "m3:icons/menu_book?fill=1";
22
+ import smartIcon from "m3:icons/smart_toy";
23
+ import smartFilled from "m3:icons/smart_toy?fill=1";
24
+ import symbolsIcon from "m3:icons/interests";
25
+ import symbolsFilled from "m3:icons/interests?fill=1";
26
+ import terminalIcon from "m3:icons/terminal";
27
+ import terminalFilled from "m3:icons/terminal?fill=1";
28
+ import webIcon from "m3:icons/web";
29
+ import webFilled from "m3:icons/web?fill=1";
30
+ import widgetsIcon from "m3:icons/widgets";
31
+ import widgetsFilled from "m3:icons/widgets?fill=1";
32
+ import extensionIcon from "m3:icons/extension";
33
+ import extensionFilled from "m3:icons/extension?fill=1";
34
+
35
+ import type { PageId } from "../pages/index.ts";
36
+
37
+ export interface Destination {
38
+ id: PageId;
39
+ label: string;
40
+ /** Outlined and filled (selected) Material Symbols SVG markup. */
41
+ icon: string;
42
+ iconFilled: string;
43
+ /** What the page shows, one sentence. */
44
+ summary: string;
45
+ /** The workspace packages the page imports and exercises. */
46
+ packages: readonly string[];
47
+ }
48
+
49
+ export const DESTINATIONS: readonly Destination[] = [
50
+ {
51
+ id: "overview",
52
+ label: "Overview",
53
+ icon: homeIcon,
54
+ iconFilled: homeFilled,
55
+ summary: "Every package of the monorepo, served by this app's own API.",
56
+ packages: ["@aphrody/m3", "@aphrody/m3-bun", "@aphrody/m3-config"],
57
+ },
58
+ {
59
+ id: "theme",
60
+ label: "Theme",
61
+ icon: paletteIcon,
62
+ iconFilled: paletteFilled,
63
+ summary: "Material You roles from a seed: tokens, Tailwind preset, fonts, a scoped <m3-theme>.",
64
+ packages: [
65
+ "@aphrody/m3-theme",
66
+ "@aphrody/m3-tokens",
67
+ "@aphrody/m3-front",
68
+ "@aphrody/m3-tailwind",
69
+ "@aphrody/m3-fonts",
70
+ ],
71
+ },
72
+ {
73
+ id: "components",
74
+ label: "Components",
75
+ icon: widgetsIcon,
76
+ iconFilled: widgetsFilled,
77
+ summary: "The Material Web components through their React wrappers.",
78
+ packages: ["@aphrody/m3-react"],
79
+ },
80
+ {
81
+ id: "primitives",
82
+ label: "Primitives",
83
+ icon: extensionIcon,
84
+ iconFilled: extensionFilled,
85
+ summary: "Accessible parts on Base UI, styled with M3 tokens.",
86
+ packages: ["@aphrody/m3-primitives", "@aphrody/m3-baseui"],
87
+ },
88
+ {
89
+ id: "forms",
90
+ label: "Forms",
91
+ icon: editIcon,
92
+ iconFilled: editFilled,
93
+ summary: "react-hook-form fields with M3 inputs, validation and descriptions.",
94
+ packages: ["@aphrody/m3-forms"],
95
+ },
96
+ {
97
+ id: "explorer",
98
+ label: "Explorer",
99
+ icon: folderIcon,
100
+ iconFilled: folderFilled,
101
+ summary: "A file explorer: list and grid views, thumbnails, tags, rename.",
102
+ packages: ["@aphrody/m3-explorer"],
103
+ },
104
+ {
105
+ id: "motion",
106
+ label: "Motion",
107
+ icon: motionIcon,
108
+ iconFilled: motionFilled,
109
+ summary: "Springs, easings, shared axis, container transform, list stagger.",
110
+ packages: ["@aphrody/m3-motion", "@aphrody/m3-react"],
111
+ },
112
+ {
113
+ id: "icons",
114
+ label: "Icons & fonts",
115
+ icon: symbolsIcon,
116
+ iconFilled: symbolsFilled,
117
+ summary: "Material Symbols from the forked catalogue, inlined at build time.",
118
+ packages: ["@aphrody/m3-icons", "@aphrody/material-design-icons", "@aphrody/m3-fonts"],
119
+ },
120
+ {
121
+ id: "ai",
122
+ label: "AI",
123
+ icon: smartIcon,
124
+ iconFilled: smartFilled,
125
+ summary: "A chat transcript, tool calls, markdown and an AG-UI stream from the API.",
126
+ packages: ["@aphrody/m3-ai", "@aphrody/ag-ui"],
127
+ },
128
+ {
129
+ id: "reader",
130
+ label: "Reader",
131
+ icon: readerIcon,
132
+ iconFilled: readerFilled,
133
+ summary: "Manga and databook readers with paging, vertical scroll and RTL.",
134
+ packages: ["@aphrody/m3-reader"],
135
+ },
136
+ {
137
+ id: "design",
138
+ label: "Design",
139
+ icon: designIcon,
140
+ iconFilled: designFilled,
141
+ summary: "A design brief parsed and turned into an M3 theme by the design engine.",
142
+ packages: ["@aphrody/m3-design"],
143
+ },
144
+ {
145
+ id: "next",
146
+ label: "Next",
147
+ icon: webIcon,
148
+ iconFilled: webFilled,
149
+ summary: "Metadata, scheme CSS, robots, sitemap and JSON-LD from the Next integration.",
150
+ packages: ["@aphrody/m3-next", "@aphrody/m3-next-migrate"],
151
+ },
152
+ {
153
+ id: "system",
154
+ label: "System",
155
+ icon: terminalIcon,
156
+ iconFilled: terminalFilled,
157
+ summary: "OS themes, scaffolds, MCP tools, codemods and lint rules, computed by the API.",
158
+ packages: [
159
+ "@aphrody/m3-os-themes",
160
+ "@aphrody/scaffold",
161
+ "@aphrody/m3-mcp",
162
+ "@aphrody/m3-codemods",
163
+ "@aphrody/eslint-plugin-m3",
164
+ ],
165
+ },
166
+ {
167
+ id: "brands",
168
+ label: "Brands",
169
+ icon: badgeIcon,
170
+ iconFilled: badgeFilled,
171
+ summary: "Host-bound UI kits where they resolve, the identity set, canvas and assets.",
172
+ packages: [
173
+ "@rosegriffon/ui",
174
+ "@shenron/ui",
175
+ "@aphrody/nie-ui",
176
+ "@aphrody/identity",
177
+ "@aphrody/canvas",
178
+ "@aphrody/assets",
179
+ ],
180
+ },
181
+ {
182
+ id: "adaptive",
183
+ label: "Adaptive",
184
+ icon: devicesIcon,
185
+ iconFilled: devicesFilled,
186
+ summary: "Window size classes, layout modes and the TV D-pad lab.",
187
+ packages: ["@aphrody/m3-tokens", "@aphrody/m3-front"],
188
+ },
189
+ ];
190
+
191
+ /** The destinations the mobile bottom bar shows; the rest sit behind "More". */
192
+ export const PRIMARY_IDS = ["overview", "theme", "components", "adaptive"] as const;
193
+
194
+ export const MORE_ICON = appsIcon;
195
+ export const MORE_ICON_FILLED = appsFilled;
196
+
197
+ export const findDestination = (id: string): Destination =>
198
+ DESTINATIONS.find((d) => d.id === id) ?? DESTINATIONS[0]!;
package/src/styles.css ADDED
@@ -0,0 +1,61 @@
1
+ @import "tailwindcss";
2
+ @import "@aphrody/m3-tokens/m3-tokens.css";
3
+ @import "@aphrody/m3-tokens/expressive.css";
4
+ @import "@aphrody/m3-tailwind/preset.css";
5
+
6
+ /*
7
+ * Google Sans Flex (latin subset) from @aphrody/m3-fonts. The package's own fonts.css also declares Google Sans Code and
8
+ * Roboto Mono: Bun inlines CSS url() assets under ~128 KB as base64 (neither a loader nor a plugin changes that), which
9
+ * would put ~290 KB of data URLs into the render-blocking stylesheet. The Icons & fonts page loads the other families itself.
10
+ */
11
+ @font-face {
12
+ font-family: "Google Sans Flex";
13
+ src: url("../../../packages/m3-fonts/fonts/web/GoogleSansFlex-latin.woff2") format("woff2");
14
+ font-weight: 1 1000;
15
+ font-stretch: 25% 151%;
16
+ font-style: oblique -10deg 0deg;
17
+ font-display: swap;
18
+ }
19
+
20
+ /* The showcase sets colour roles at runtime (M3ThemeProvider); everything else comes from the token sheets. */
21
+ :root {
22
+ --m3-nav-width: 0px;
23
+ --m3-gutter: 16px;
24
+ color-scheme: light dark;
25
+ }
26
+ html[data-m3-width="medium"], html[data-m3-width="expanded"], html[data-m3-width="large"], html[data-m3-width="extra-large"] { --m3-gutter: 24px; }
27
+
28
+ html, body, #root { height: 100%; }
29
+ body {
30
+ margin: 0;
31
+ background: var(--md-sys-color-background);
32
+ color: var(--md-sys-color-on-background);
33
+ font-family: var(--md-ref-typeface-plain);
34
+ font-size: var(--md-sys-typescale-body-large-size);
35
+ line-height: var(--md-sys-typescale-body-large-line-height);
36
+ -webkit-font-smoothing: antialiased;
37
+ overscroll-behavior: none;
38
+ }
39
+ * { box-sizing: border-box; }
40
+ a { color: inherit; }
41
+
42
+ /* TV: 10-foot type scale, safe area, obvious focus. */
43
+ html[data-layout="tv"] { font-size: 150%; }
44
+ html[data-layout="tv"] body { padding: 2.5vh 2.5vw; }
45
+ html[data-layout="tv"] :focus-visible,
46
+ html[data-layout="tv"] [data-dpad-focus] {
47
+ outline: 4px solid var(--md-sys-color-primary);
48
+ outline-offset: 4px;
49
+ border-radius: var(--md-sys-shape-corner-medium);
50
+ }
51
+ :focus-visible { outline: 2px solid var(--md-sys-color-primary); outline-offset: 2px; }
52
+
53
+ .m3-scroll { scrollbar-width: thin; scrollbar-color: var(--md-sys-color-outline-variant) transparent; }
54
+ .m3-card { background: var(--md-sys-color-surface-container); border-radius: var(--md-sys-shape-corner-large); padding: 16px; }
55
+ .m3-code { font-family: var(--md-ref-typeface-code, ui-monospace, monospace); font-size: 0.8125rem; background: var(--md-sys-color-surface-container-highest); border-radius: var(--md-sys-shape-corner-small); padding: 12px; overflow: auto; white-space: pre; }
56
+ .m3-icon svg { width: 1.5rem; height: 1.5rem; fill: currentColor; display: block; }
57
+ .m3-icon-sm svg { width: 1.125rem; height: 1.125rem; fill: currentColor; display: block; }
58
+
59
+ @media (prefers-reduced-motion: reduce) {
60
+ * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
61
+ }