@grove-dev/astro 0.2.10 → 0.2.14

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 (237) hide show
  1. package/README.md +26 -18
  2. package/dist/lib/display.d.ts +11 -17
  3. package/dist/lib/display.d.ts.map +1 -1
  4. package/dist/lib/display.js +43 -43
  5. package/dist/lib/display.js.map +1 -1
  6. package/dist/lib/format.d.ts +6 -7
  7. package/dist/lib/format.d.ts.map +1 -1
  8. package/dist/lib/format.js +11 -12
  9. package/dist/lib/format.js.map +1 -1
  10. package/dist/lib/lenses.d.ts +35 -73
  11. package/dist/lib/lenses.d.ts.map +1 -1
  12. package/dist/lib/lenses.js +144 -126
  13. package/dist/lib/lenses.js.map +1 -1
  14. package/dist/lib/repo.d.ts +12 -22
  15. package/dist/lib/repo.d.ts.map +1 -1
  16. package/dist/lib/repo.js +13 -25
  17. package/dist/lib/repo.js.map +1 -1
  18. package/dist/lib/scores.d.ts +15 -16
  19. package/dist/lib/scores.d.ts.map +1 -1
  20. package/dist/lib/scores.js +4 -11
  21. package/dist/lib/scores.js.map +1 -1
  22. package/dist/lib/search.d.ts +44 -129
  23. package/dist/lib/search.d.ts.map +1 -1
  24. package/dist/lib/search.js +192 -180
  25. package/dist/lib/search.js.map +1 -1
  26. package/dist/lib/taxonomy-counts.d.ts +7 -21
  27. package/dist/lib/taxonomy-counts.d.ts.map +1 -1
  28. package/dist/lib/taxonomy-counts.js +12 -31
  29. package/dist/lib/taxonomy-counts.js.map +1 -1
  30. package/package.json +4 -4
  31. package/src/components/CategoryGrid.astro +43 -31
  32. package/src/components/ContributorsGrid.astro +3 -3
  33. package/src/components/CurationGrid.astro +41 -0
  34. package/src/components/ExploreByStack.astro +6 -0
  35. package/src/components/FilterGroupMenu.astro +49 -0
  36. package/src/components/FilterOptions.astro +44 -0
  37. package/src/components/Hero.astro +198 -147
  38. package/src/components/Icon.astro +10 -3
  39. package/src/components/IndexRow.astro +75 -0
  40. package/src/components/ItemCard.astro +266 -248
  41. package/src/components/Pagination.astro +63 -0
  42. package/src/components/RecordSection.astro +70 -34
  43. package/src/components/RefinePanel.astro +115 -141
  44. package/src/components/StackGrid.astro +32 -24
  45. package/src/components/WhyThisExists.astro +32 -32
  46. package/src/layouts/BaseLayout.astro +104 -49
  47. package/src/layouts/Container.astro +5 -44
  48. package/src/layouts/Footer.astro +31 -20
  49. package/src/layouts/Header.astro +40 -19
  50. package/src/layouts/SectionHeader.astro +27 -43
  51. package/src/layouts/Seo.astro +38 -56
  52. package/src/layouts/ThemeToggle.astro +35 -48
  53. package/src/lib/display.ts +46 -53
  54. package/src/lib/format.ts +11 -12
  55. package/src/lib/lenses.ts +151 -172
  56. package/src/lib/repo.ts +17 -28
  57. package/src/lib/scores.ts +15 -19
  58. package/src/lib/search.ts +218 -291
  59. package/src/lib/taxonomy-counts.ts +12 -46
  60. package/src/styles.css +209 -1
  61. package/templates/default/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
  62. package/templates/default/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  63. package/templates/default/.github/ISSUE_TEMPLATE/record_submission.md +48 -0
  64. package/templates/default/.github/pull_request_template.md +27 -0
  65. package/templates/default/.github/workflows/build.yml +55 -0
  66. package/templates/default/.github/workflows/cleanup-stale-records.yml +48 -0
  67. package/templates/default/.github/workflows/daily-refresh.yml +53 -0
  68. package/templates/default/.github/workflows/sync-contributors.yml +53 -0
  69. package/templates/default/.github/workflows/sync-github-metadata.yml +58 -0
  70. package/templates/default/.github/workflows/validate-data.yml +35 -0
  71. package/templates/default/data/records/coolify.yml +46 -0
  72. package/templates/default/data/records/gitea.yml +46 -0
  73. package/templates/default/data/records/hoppscotch.yml +47 -0
  74. package/templates/default/data/records/inventree.yml +47 -0
  75. package/templates/default/data/records/label-studio.yml +46 -0
  76. package/templates/default/data/records/logseq.yml +48 -0
  77. package/templates/default/data/records/private-gpt.yml +47 -0
  78. package/templates/default/data/records/wakapi.yml +44 -0
  79. package/templates/default/data/taxonomy/categories.yml +47 -0
  80. package/templates/default/data/taxonomy/distribution-channels.yml +43 -0
  81. package/templates/default/data/taxonomy/platforms.yml +27 -0
  82. package/templates/default/data/taxonomy/stacks.yml +41 -0
  83. package/templates/default/grove.config.ts +1 -1
  84. package/templates/default/package.json +5 -4
  85. package/templates/default/public/icons/stacks/bun.svg +1 -0
  86. package/templates/default/public/icons/stacks/clojure.svg +1 -0
  87. package/templates/default/public/icons/stacks/clojurescript.svg +1 -0
  88. package/templates/default/public/icons/stacks/deno.svg +1 -0
  89. package/templates/default/public/icons/stacks/django.svg +1 -0
  90. package/templates/default/public/icons/stacks/docker.svg +1 -0
  91. package/templates/default/public/icons/stacks/go.svg +1 -0
  92. package/templates/default/public/icons/stacks/llm.svg +1 -0
  93. package/templates/default/public/icons/stacks/node.js.svg +1 -0
  94. package/templates/default/public/icons/stacks/sveltekit.svg +1 -0
  95. package/templates/default/public/icons/stacks/vue.svg +1 -0
  96. package/templates/default/public/llms-full.txt +197 -5
  97. package/templates/default/public/llms.txt +107 -6
  98. package/templates/default/public/sitemap.xml +63 -0
  99. package/templates/default/scripts/build-llms.mjs +123 -0
  100. package/templates/default/scripts/build-records-json.mjs +27 -0
  101. package/templates/default/scripts/build-sitemap.mjs +20 -0
  102. package/templates/default/scripts/cleanup-stale-records.mjs +20 -0
  103. package/templates/default/scripts/enrich-github-metadata.mjs +99 -0
  104. package/templates/default/scripts/fetch-icons.mjs +137 -0
  105. package/templates/default/scripts/migrate-legacy-to-schema-v1.mjs +86 -0
  106. package/templates/default/scripts/parse-legacy-readme.mjs +59 -0
  107. package/templates/default/scripts/refresh-records-activity.mjs +24 -0
  108. package/templates/default/scripts/repair-license-format.mjs +72 -0
  109. package/templates/default/scripts/report-cleanup-candidates.mjs +21 -0
  110. package/templates/default/scripts/seed-from-github.mjs +62 -0
  111. package/templates/default/scripts/sync-contributors.mjs +145 -0
  112. package/templates/default/scripts/sync-github-metadata.mjs +28 -0
  113. package/templates/default/scripts/validate-records.mjs +27 -0
  114. package/templates/default/src/data/records.ts +138 -51
  115. package/templates/default/src/pages/404.astro +64 -0
  116. package/templates/default/src/pages/{projects/[slug].astro → [slug]/[recordSlug].astro} +236 -66
  117. package/templates/default/src/pages/[slug]/index.astro +477 -0
  118. package/templates/default/src/pages/about.astro +165 -82
  119. package/templates/default/src/pages/apps/[recordSlug].astro +33 -0
  120. package/templates/default/src/pages/contributors.astro +184 -0
  121. package/templates/default/src/pages/index.astro +119 -162
  122. package/templates/default/src/pages/submit.astro +276 -114
  123. package/templates/default/wrangler.jsonc +28 -0
  124. package/LICENSE +0 -21
  125. package/src/components/AppsIndexRow.astro +0 -204
  126. package/src/components/AppsPagination.astro +0 -126
  127. package/templates/default/.astro/content.d.ts +0 -155
  128. package/templates/default/.astro/settings.json +0 -5
  129. package/templates/default/.astro/types.d.ts +0 -1
  130. package/templates/default/data/generated/apps.json +0 -1
  131. package/templates/default/data/generated/records.full.json +0 -8
  132. package/templates/default/data/generated/records.index.json +0 -7
  133. package/templates/default/data/generated/records.json +0 -8
  134. package/templates/default/data/generated/repo-stats.json +0 -1
  135. package/templates/default/data/generated/site-config.json +0 -31
  136. package/templates/default/dist/_astro/BaseLayout.Dz_HR-68.css +0 -1
  137. package/templates/default/dist/about/index.html +0 -165
  138. package/templates/default/dist/icons/platforms/android.svg +0 -1
  139. package/templates/default/dist/icons/platforms/apple-dark.svg +0 -1
  140. package/templates/default/dist/icons/platforms/apple-light.svg +0 -1
  141. package/templates/default/dist/icons/platforms/chrome.svg +0 -1
  142. package/templates/default/dist/icons/platforms/chromeos.svg +0 -5
  143. package/templates/default/dist/icons/platforms/desktop.svg +0 -4
  144. package/templates/default/dist/icons/platforms/embedded.svg +0 -5
  145. package/templates/default/dist/icons/platforms/ios.svg +0 -1
  146. package/templates/default/dist/icons/platforms/linux.svg +0 -1
  147. package/templates/default/dist/icons/platforms/macos.svg +0 -1
  148. package/templates/default/dist/icons/platforms/ubuntu.svg +0 -1
  149. package/templates/default/dist/icons/platforms/web.svg +0 -5
  150. package/templates/default/dist/icons/platforms/windows.svg +0 -6
  151. package/templates/default/dist/icons/stacks/android.svg +0 -1
  152. package/templates/default/dist/icons/stacks/apple-dark.svg +0 -1
  153. package/templates/default/dist/icons/stacks/apple-light.svg +0 -1
  154. package/templates/default/dist/icons/stacks/capacitor.svg +0 -14
  155. package/templates/default/dist/icons/stacks/dart.svg +0 -1
  156. package/templates/default/dist/icons/stacks/firebase.svg +0 -1
  157. package/templates/default/dist/icons/stacks/flutter.svg +0 -1
  158. package/templates/default/dist/icons/stacks/graphql.svg +0 -1
  159. package/templates/default/dist/icons/stacks/ionic.svg +0 -4
  160. package/templates/default/dist/icons/stacks/java.svg +0 -1
  161. package/templates/default/dist/icons/stacks/javascript.svg +0 -1
  162. package/templates/default/dist/icons/stacks/kotlin.svg +0 -1
  163. package/templates/default/dist/icons/stacks/mongodb.svg +0 -1
  164. package/templates/default/dist/icons/stacks/nodejs.svg +0 -1
  165. package/templates/default/dist/icons/stacks/python.svg +0 -1
  166. package/templates/default/dist/icons/stacks/react-native.svg +0 -1
  167. package/templates/default/dist/icons/stacks/react.svg +0 -1
  168. package/templates/default/dist/icons/stacks/rust.svg +0 -1
  169. package/templates/default/dist/icons/stacks/solidity.svg +0 -1
  170. package/templates/default/dist/icons/stacks/swift.svg +0 -1
  171. package/templates/default/dist/icons/stacks/tensorflow.svg +0 -1
  172. package/templates/default/dist/icons/stacks/typescript.svg +0 -1
  173. package/templates/default/dist/index.html +0 -55
  174. package/templates/default/dist/llms-full.txt +0 -14
  175. package/templates/default/dist/llms.txt +0 -11
  176. package/templates/default/dist/og-image.svg +0 -48
  177. package/templates/default/dist/projects/index.html +0 -61
  178. package/templates/default/dist/robots.txt +0 -53
  179. package/templates/default/dist/sitemap.xml +0 -21
  180. package/templates/default/dist/submit/index.html +0 -69
  181. package/templates/default/node_modules/.bin/astro +0 -21
  182. package/templates/default/node_modules/.bin/astro-check +0 -21
  183. package/templates/default/node_modules/.bin/grove +0 -21
  184. package/templates/default/node_modules/.bin/jiti +0 -21
  185. package/templates/default/node_modules/.bin/prettier +0 -21
  186. package/templates/default/node_modules/.bin/rollup +0 -21
  187. package/templates/default/node_modules/.bin/tsc +0 -21
  188. package/templates/default/node_modules/.bin/tsserver +0 -21
  189. package/templates/default/node_modules/.bin/tsx +0 -21
  190. package/templates/default/node_modules/.bin/vite +0 -21
  191. package/templates/default/node_modules/.bin/yaml +0 -21
  192. package/templates/default/node_modules/.vite/deps/_metadata.json +0 -79
  193. package/templates/default/node_modules/.vite/deps/astro-KRVZHBC5.js +0 -433
  194. package/templates/default/node_modules/.vite/deps/astro-KRVZHBC5.js.map +0 -7
  195. package/templates/default/node_modules/.vite/deps/astro___aria-query.js +0 -5
  196. package/templates/default/node_modules/.vite/deps/astro___aria-query.js.map +0 -7
  197. package/templates/default/node_modules/.vite/deps/astro___axobject-query.js +0 -5
  198. package/templates/default/node_modules/.vite/deps/astro___axobject-query.js.map +0 -7
  199. package/templates/default/node_modules/.vite/deps/astro___html-escaper.js +0 -9
  200. package/templates/default/node_modules/.vite/deps/astro___html-escaper.js.map +0 -7
  201. package/templates/default/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +0 -241
  202. package/templates/default/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +0 -7
  203. package/templates/default/node_modules/.vite/deps/audit-GYHQ3ITH.js +0 -1592
  204. package/templates/default/node_modules/.vite/deps/audit-GYHQ3ITH.js.map +0 -7
  205. package/templates/default/node_modules/.vite/deps/chunk-5WRI5ZAA.js +0 -30
  206. package/templates/default/node_modules/.vite/deps/chunk-5WRI5ZAA.js.map +0 -7
  207. package/templates/default/node_modules/.vite/deps/chunk-7P4KIK53.js +0 -186
  208. package/templates/default/node_modules/.vite/deps/chunk-7P4KIK53.js.map +0 -7
  209. package/templates/default/node_modules/.vite/deps/chunk-BQGHFQJH.js +0 -48
  210. package/templates/default/node_modules/.vite/deps/chunk-BQGHFQJH.js.map +0 -7
  211. package/templates/default/node_modules/.vite/deps/chunk-CJCDKWP2.js +0 -6779
  212. package/templates/default/node_modules/.vite/deps/chunk-CJCDKWP2.js.map +0 -7
  213. package/templates/default/node_modules/.vite/deps/chunk-FHJ3XBDE.js +0 -33
  214. package/templates/default/node_modules/.vite/deps/chunk-FHJ3XBDE.js.map +0 -7
  215. package/templates/default/node_modules/.vite/deps/chunk-FQEMNIUQ.js +0 -88
  216. package/templates/default/node_modules/.vite/deps/chunk-FQEMNIUQ.js.map +0 -7
  217. package/templates/default/node_modules/.vite/deps/chunk-HBSVDAQD.js +0 -72
  218. package/templates/default/node_modules/.vite/deps/chunk-HBSVDAQD.js.map +0 -7
  219. package/templates/default/node_modules/.vite/deps/chunk-HDOQ2U3U.js +0 -3757
  220. package/templates/default/node_modules/.vite/deps/chunk-HDOQ2U3U.js.map +0 -7
  221. package/templates/default/node_modules/.vite/deps/chunk-XEBKRCNE.js +0 -54
  222. package/templates/default/node_modules/.vite/deps/chunk-XEBKRCNE.js.map +0 -7
  223. package/templates/default/node_modules/.vite/deps/package.json +0 -3
  224. package/templates/default/node_modules/.vite/deps/settings-C5H4VHXU.js +0 -213
  225. package/templates/default/node_modules/.vite/deps/settings-C5H4VHXU.js.map +0 -7
  226. package/templates/default/node_modules/.vite/deps/toolbar-H5DB6HVP.js +0 -525
  227. package/templates/default/node_modules/.vite/deps/toolbar-H5DB6HVP.js.map +0 -7
  228. package/templates/default/node_modules/.vite/deps/ui-library-JGHU6JE2.js +0 -1020
  229. package/templates/default/node_modules/.vite/deps/ui-library-JGHU6JE2.js.map +0 -7
  230. package/templates/default/node_modules/.vite/deps/xray-EFCQOW4E.js +0 -147
  231. package/templates/default/node_modules/.vite/deps/xray-EFCQOW4E.js.map +0 -7
  232. package/templates/default/src/components/layout/BaseLayout.astro +0 -47
  233. package/templates/default/src/components/layout/Container.astro +0 -18
  234. package/templates/default/src/components/layout/Footer.astro +0 -27
  235. package/templates/default/src/components/layout/Header.astro +0 -43
  236. package/templates/default/src/lib/markdown.ts +0 -171
  237. package/templates/default/src/pages/projects/index.astro +0 -193
@@ -1 +1 @@
1
- {"version":3,"file":"taxonomy-counts.js","sourceRoot":"","sources":["../../src/lib/taxonomy-counts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AASH,2CAA2C;AAC3C,MAAM,UAAU,eAAe,CAC7B,OAAY;IAEZ,MAAM,CAAC,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC;QAChC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,YAAY,CAC1B,OAAY;IAEZ,MAAM,CAAC,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,GAAG,CAClB,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CACnC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAC/B,CACF,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,YAAY,CAC1B,OAAY;IAEZ,MAAM,CAAC,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;YACzC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
1
+ {"version":3,"file":"taxonomy-counts.js","sourceRoot":"","sources":["../../src/lib/taxonomy-counts.ts"],"names":[],"mappings":"AAMA,2DAA2D;AAC3D,MAAM,UAAU,eAAe,CAAC,QAA0B,EAAE;IAC1D,MAAM,CAAC,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC;QAChC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,YAAY,CAAC,QAA0B,EAAE;IACvD,MAAM,CAAC,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAa,CAAC,CAAC;QACnF,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3C,KAAK,MAAM,KAAK,IAAI,MAAM;YAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grove-dev/astro",
3
- "version": "0.2.10",
3
+ "version": "0.2.14",
4
4
  "type": "module",
5
5
  "description": "Astro framework adapter for Grove. Components, layouts, design tokens, and a default template.",
6
6
  "license": "MIT",
@@ -43,9 +43,9 @@
43
43
  "./layouts/*": "./src/layouts/*.astro"
44
44
  },
45
45
  "dependencies": {
46
- "astro": "^6.4.6",
47
- "@grove-dev/core": "0.2.10",
48
- "@grove-dev/ui": "0.2.10"
46
+ "@grove-dev/core": "0.2.14",
47
+ "@grove-dev/ui": "1.0.4",
48
+ "astro": "^6.4.6"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "astro": "^6.0.0"
@@ -22,6 +22,7 @@ interface Props {
22
22
  class?: string;
23
23
  /** Hide the section header. */
24
24
  bare?: boolean;
25
+ itemLabelPlural?: string;
25
26
  }
26
27
 
27
28
  const {
@@ -29,6 +30,7 @@ const {
29
30
  pathPrefix = "/",
30
31
  class: className = "",
31
32
  bare = false,
33
+ itemLabelPlural = "items",
32
34
  } = Astro.props;
33
35
 
34
36
  function buildHref(slug: string): string {
@@ -38,50 +40,60 @@ function buildHref(slug: string): string {
38
40
  ---
39
41
 
40
42
  <section
41
- class:list={["grove-section", className]}
43
+ id="categories"
44
+ class:list={["grove-section scroll-mt-20 border-b border-ink-200 dark:border-ink-800", className]}
42
45
  aria-labelledby={bare ? undefined : "grove-categorygrid-heading"}
43
46
  >
44
- <div class="grove-container-wide mx-auto px-5 sm:px-7">
47
+ <div class="grove-container mx-auto px-5 sm:px-7">
45
48
  {!bare && (
46
- <header class="mb-6 flex flex-col gap-2">
49
+ <header class="mb-6">
50
+ <span class="text-2xs font-medium uppercase tracking-wider text-ink-500 dark:text-ink-400">
51
+ Categories
52
+ </span>
47
53
  <h2
48
54
  id="grove-categorygrid-heading"
49
- class="m-0 text-[1.5rem] sm:text-[1.625rem] font-semibold tracking-tight text-ink-900 dark:text-ink-100"
55
+ class="m-0 mt-1 text-[1.5rem] sm:text-[1.625rem] font-semibold tracking-tight text-ink-900 dark:text-ink-100"
50
56
  >
51
57
  Browse by category
52
58
  </h2>
53
59
  <p class="m-0 max-w-[60ch] text-[0.9375rem] text-ink-500 dark:text-ink-400">
54
- What kind of project are you looking for? Browse by category to find
55
- reference apps, libraries, demos, and more.
60
+ Find {itemLabelPlural} by what they do, not by which stack they use.
56
61
  </p>
57
62
  </header>
58
63
  )}
59
64
 
60
- <div class="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
61
- {categories.map((c) => (
62
- <a
63
- href={buildHref(c.slug)}
64
- class="grove-card grove-card-hover group flex flex-col gap-1.5 p-4 no-underline"
65
- data-event="category_grid_click"
66
- data-event-source="category_grid"
67
- >
68
- <div class="flex items-baseline justify-between gap-2">
69
- <h3 class="m-0 text-[0.9375rem] font-semibold tracking-tight text-ink-900 group-hover:underline dark:text-ink-100">
70
- {c.name}
71
- </h3>
72
- {typeof c.count === "number" && (
73
- <span class="font-mono text-2xs text-ink-500 dark:text-ink-400">
74
- {c.count}
75
- </span>
76
- )}
77
- </div>
78
- {c.blurb && (
79
- <p class="m-0 line-clamp-2 text-[0.8125rem] leading-snug text-ink-500 dark:text-ink-400">
80
- {c.blurb}
81
- </p>
82
- )}
83
- </a>
84
- ))}
65
+ <div class="overflow-hidden rounded-lg border border-ink-200 dark:border-ink-800">
66
+ <ul class="m-0 grid list-none grid-cols-1 divide-y divide-ink-200 p-0 sm:grid-cols-2 sm:divide-x sm:divide-y-0 lg:grid-cols-3 dark:divide-ink-800">
67
+ {categories.map((c) => (
68
+ <li class="divide-x divide-ink-200 dark:divide-ink-800">
69
+ <a
70
+ href={buildHref(c.slug)}
71
+ class="group flex h-full items-start gap-3 p-4 no-underline transition-colors hover:bg-ink-50/60 dark:hover:bg-ink-900/40"
72
+ >
73
+ <div class="flex min-w-0 flex-1 flex-col gap-0.5">
74
+ <div class="flex items-center gap-2">
75
+ <h3 class="m-0 text-[0.9375rem] font-semibold tracking-tight text-ink-900 group-hover:underline dark:text-ink-100">
76
+ {c.name}
77
+ </h3>
78
+ {typeof c.count === "number" && (
79
+ <span class="inline-flex items-center rounded-md border border-ink-200 bg-ink-50 px-1.5 py-0.5 font-mono text-[10px] font-medium text-ink-600 dark:border-ink-800 dark:bg-ink-900/60 dark:text-ink-400">
80
+ {c.count} {itemLabelPlural}
81
+ </span>
82
+ )}
83
+ </div>
84
+ {c.blurb && (
85
+ <p class="m-0 text-2xs leading-relaxed text-ink-500 dark:text-ink-400">
86
+ {c.blurb}
87
+ </p>
88
+ )}
89
+ </div>
90
+ <svg viewBox="0 0 16 16" width="12" height="12" aria-hidden="true" class="mt-1 shrink-0 text-ink-300 transition-colors group-hover:text-ink-500 dark:text-ink-700 dark:group-hover:text-ink-400" fill="currentColor">
91
+ <path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z" />
92
+ </svg>
93
+ </a>
94
+ </li>
95
+ ))}
96
+ </ul>
85
97
  </div>
86
98
  </div>
87
99
  </section>
@@ -52,14 +52,14 @@ function fmt(n: number | undefined): string | null {
52
52
 
53
53
  const visible = contributors
54
54
  .filter((c) => c.username)
55
- .slice(0, 24);
55
+ .slice(0, 100);
56
56
  ---
57
57
 
58
58
  <section
59
59
  class:list={["grove-section", className]}
60
60
  aria-labelledby="grove-contributors-heading"
61
61
  >
62
- <div class="grove-container-wide mx-auto px-5 sm:px-7">
62
+ <div class="grove-container mx-auto px-5 sm:px-7">
63
63
  <header class="mb-6 flex flex-wrap items-end justify-between gap-3">
64
64
  <div>
65
65
  <h2
@@ -95,7 +95,7 @@ const visible = contributors
95
95
  </p>
96
96
  ) : (
97
97
  <ul
98
- class="m-0 grid list-none grid-cols-3 gap-3 p-0 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-8"
98
+ class="m-0 grid list-none grid-cols-[repeat(auto-fill,minmax(72px,1fr))] gap-x-3 gap-y-5 p-0"
99
99
  aria-label="Contributors"
100
100
  >
101
101
  {visible.map((c) => {
@@ -0,0 +1,41 @@
1
+ ---
2
+ interface Props {
3
+ bestFor?: string[];
4
+ whyListed?: string[];
5
+ caveats?: string[];
6
+ class?: string;
7
+ }
8
+
9
+ const {
10
+ bestFor = [],
11
+ whyListed = [],
12
+ caveats = [],
13
+ class: className = "",
14
+ } = Astro.props;
15
+
16
+ const columns = [
17
+ { title: "Best for", items: bestFor },
18
+ { title: "Why listed", items: whyListed },
19
+ { title: "Caveats", items: caveats },
20
+ ].filter((column) => column.items.length > 0);
21
+ ---
22
+
23
+ {columns.length > 0 && (
24
+ <section
25
+ class:list={["grid grid-cols-1 gap-4 md:grid-cols-3", className]}
26
+ aria-label="Curation notes"
27
+ >
28
+ {columns.map((column) => (
29
+ <div class="grove-card p-5">
30
+ <h3 class="m-0 text-sm font-semibold uppercase tracking-wider text-ink-500 dark:text-ink-400">
31
+ {column.title}
32
+ </h3>
33
+ <ul class="mt-3 m-0 flex list-none flex-col gap-1.5 p-0">
34
+ {column.items.map((item) => (
35
+ <li class="text-sm text-ink-700 dark:text-ink-200">- {item}</li>
36
+ ))}
37
+ </ul>
38
+ </div>
39
+ ))}
40
+ </section>
41
+ )}
@@ -15,6 +15,7 @@ interface StackEntry {
15
15
  name: string;
16
16
  slug: string;
17
17
  count?: number;
18
+ status?: "live" | "expanding" | "planned";
18
19
  }
19
20
 
20
21
  interface Props {
@@ -64,6 +65,11 @@ function buildHref(slug: string): string {
64
65
  {typeof s.count === "number" && (
65
66
  <span class="font-mono text-ink-400">{s.count}</span>
66
67
  )}
68
+ {s.status && s.status !== "live" && (
69
+ <span class="text-[10px] uppercase tracking-wide text-ink-400">
70
+ {s.status}
71
+ </span>
72
+ )}
67
73
  </a>
68
74
  </li>
69
75
  ))}
@@ -0,0 +1,49 @@
1
+ ---
2
+ import FilterOptions from "./FilterOptions.astro";
3
+
4
+ interface FacetValue {
5
+ value: string;
6
+ label?: string;
7
+ count?: number;
8
+ }
9
+
10
+ interface Props {
11
+ label: string;
12
+ filterKey: string;
13
+ options: FacetValue[];
14
+ initial: string[];
15
+ single?: boolean;
16
+ active: boolean;
17
+ popoverId: string;
18
+ trigger: string;
19
+ }
20
+
21
+ const group = Astro.props;
22
+ ---
23
+
24
+ <div class="grove-filter relative" data-filter-group-key={group.filterKey} data-filter-single={group.single ? "true" : "false"}>
25
+ <button
26
+ type="button"
27
+ class:list={[
28
+ "grove-filter-trigger inline-flex h-9 items-center gap-1.5 rounded-md border px-3 text-[0.8125rem] font-medium transition-colors",
29
+ group.active
30
+ ? "border-ink-900 bg-ink-900 text-white dark:border-ink-100 dark:bg-ink-100 dark:text-ink-900"
31
+ : "border-ink-200 bg-white text-ink-700 hover:border-ink-300 hover:bg-ink-50 dark:border-ink-800 dark:bg-ink-950 dark:text-ink-300 dark:hover:border-ink-700 dark:hover:bg-ink-900/60",
32
+ ]}
33
+ aria-haspopup="listbox"
34
+ aria-expanded="false"
35
+ aria-controls={group.popoverId}
36
+ >
37
+ <span>{group.trigger}</span>
38
+ <svg viewBox="0 0 16 16" width="11" height="11" aria-hidden="true" fill="currentColor" class="opacity-70">
39
+ <path d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z"/>
40
+ </svg>
41
+ </button>
42
+ <div id={group.popoverId} class="grove-filter-popover absolute left-0 top-full z-40 mt-1 hidden w-72 max-w-[calc(100vw-2rem)] rounded-lg border border-ink-200 bg-white p-1.5 shadow-lg dark:border-ink-800 dark:bg-ink-950" role="listbox" hidden>
43
+ <FilterOptions filterKey={group.filterKey} options={group.options} initial={group.initial} single={group.single} />
44
+ <div class="mt-1 flex items-center justify-between border-t border-ink-100 px-2 pt-1.5 dark:border-ink-900">
45
+ <button type="button" class="grove-filter-clear text-2xs font-medium text-ink-500 hover:text-ink-900 dark:text-ink-400 dark:hover:text-ink-100" hidden={!group.active}>Clear {group.label.toLowerCase()}</button>
46
+ <button type="button" class="grove-filter-apply ml-auto rounded-md bg-ink-900 px-2.5 py-1 text-2xs font-medium text-white dark:bg-ink-100 dark:text-ink-900">Apply</button>
47
+ </div>
48
+ </div>
49
+ </div>
@@ -0,0 +1,44 @@
1
+ ---
2
+ interface FacetValue {
3
+ value: string;
4
+ label?: string;
5
+ count?: number;
6
+ }
7
+
8
+ interface Props {
9
+ filterKey: string;
10
+ options: FacetValue[];
11
+ initial: string[];
12
+ single?: boolean;
13
+ }
14
+
15
+ const { filterKey, options, initial, single = false } = Astro.props;
16
+
17
+ function pretty(value: string): string {
18
+ return value
19
+ .split(/[-_]/)
20
+ .map((part) => part ? part[0].toUpperCase() + part.slice(1) : part)
21
+ .join(" ");
22
+ }
23
+ ---
24
+
25
+ <ul class="m-0 flex max-h-72 list-none flex-col gap-0.5 overflow-y-auto p-0">
26
+ {options.map((option) => (
27
+ <li>
28
+ <label class="flex cursor-pointer items-center justify-between gap-3 rounded-md px-2 py-1.5 text-[0.8125rem] text-ink-700 transition-colors hover:bg-ink-50 dark:text-ink-300 dark:hover:bg-ink-900/60">
29
+ <span class="flex min-w-0 items-center gap-2">
30
+ <input
31
+ type={single ? "radio" : "checkbox"}
32
+ name={single ? filterKey : undefined}
33
+ class="grove-filter-input h-3.5 w-3.5 shrink-0 cursor-pointer accent-ink-900 dark:accent-ink-100"
34
+ data-filter-key={filterKey}
35
+ data-filter-value={option.value}
36
+ checked={initial.includes(option.value)}
37
+ />
38
+ <span class="truncate">{option.label ?? pretty(option.value)}</span>
39
+ </span>
40
+ <span class="font-mono text-2xs tabular-nums text-ink-500 dark:text-ink-400">{option.count ?? 0}</span>
41
+ </label>
42
+ </li>
43
+ ))}
44
+ </ul>