@grove-dev/astro 0.2.18 → 0.2.20
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.
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -1
- package/dist/index.js.map +1 -1
- package/dist/theme.test.d.ts +2 -0
- package/dist/theme.test.d.ts.map +1 -0
- package/dist/theme.test.js +55 -0
- package/dist/theme.test.js.map +1 -0
- package/package.json +1 -1
- package/src/components/CategoryGrid.astro +2 -11
- package/src/components/ContributorsGrid.astro +2 -11
- package/src/components/CurationGrid.astro +1 -1
- package/src/components/DecisionRow.astro +1 -1
- package/src/components/ExploreByCategory.astro +3 -3
- package/src/components/ExploreByStack.astro +3 -3
- package/src/components/FilterGroupMenu.astro +5 -5
- package/src/components/Hero.astro +11 -11
- package/src/components/Icon.astro +6 -33
- package/src/components/IndexRow.astro +5 -5
- package/src/components/ItemCard.astro +5 -16
- package/src/components/MinimalAbout.astro +2 -2
- package/src/components/OriginalCollection.astro +4 -4
- package/src/components/Pagination.astro +2 -2
- package/src/components/RecordSection.astro +1 -1
- package/src/components/RefinePanel.astro +1 -1
- package/src/components/SmartLensTabs.astro +3 -3
- package/src/components/StackGrid.astro +6 -15
- package/src/components/WhyThisExists.astro +3 -3
- package/src/index.ts +52 -1
- package/src/layouts/BaseLayout.astro +1 -1
- package/src/layouts/Container.astro +4 -4
- package/src/layouts/Footer.astro +3 -3
- package/src/layouts/Header.astro +5 -5
- package/src/layouts/ThemeToggle.astro +1 -1
- package/src/styles.css +217 -408
- package/src/theme.test.ts +67 -0
- package/templates/default/package.json +1 -1
- package/templates/default/public/icons/stacks/rag.svg +7 -0
- package/templates/default/public/llms-full.txt +1 -1
- package/templates/default/public/sitemap.xml +10 -10
- package/templates/default/src/pages/404.astro +5 -5
- package/templates/default/src/pages/[slug]/[recordSlug].astro +27 -31
- package/templates/default/src/pages/[slug]/index.astro +8 -37
- package/templates/default/src/pages/about.astro +9 -9
- package/templates/default/src/pages/contributors.astro +8 -17
- package/templates/default/src/pages/submit.astro +23 -31
- package/templates/default/src/styles/global.css +14 -39
- package/templates/default/tailwind.config.mjs +0 -130
|
@@ -104,7 +104,7 @@ const groups: RenderedFilterGroup[] = baseGroups
|
|
|
104
104
|
{!hide.includes("sort") && (
|
|
105
105
|
<label class="relative">
|
|
106
106
|
<span class="sr-only">Sort items</span>
|
|
107
|
-
<select name="sort" class="h-9 cursor-pointer appearance-none
|
|
107
|
+
<select name="sort" class="h-9 cursor-pointer appearance-none border py-1.5 pl-3 pr-8 text-[0.8125rem] font-medium">
|
|
108
108
|
{SORT_OPTIONS.map((option) => <option value={option.value} selected={(initial.sort ?? "recently-updated") === option.value}>{option.label}</option>)}
|
|
109
109
|
</select>
|
|
110
110
|
<svg viewBox="0 0 16 16" width="11" height="11" aria-hidden="true" class="pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 text-ink-400" fill="currentColor">
|
|
@@ -55,10 +55,10 @@ const lenses =
|
|
|
55
55
|
<a
|
|
56
56
|
href={hrefForLens(lens.id, currentParams, pathPrefix)}
|
|
57
57
|
class:list={[
|
|
58
|
-
"
|
|
58
|
+
"inline-flex h-8 cursor-pointer items-center justify-center gap-1.5 rounded-[var(--radius)] border border-transparent px-3 text-2xs font-medium leading-none no-underline outline-none transition-colors focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35",
|
|
59
59
|
active
|
|
60
|
-
? "
|
|
61
|
-
: "
|
|
60
|
+
? "bg-primary text-primary-foreground hover:bg-primary/90"
|
|
61
|
+
: "border-border bg-secondary text-foreground hover:bg-accent",
|
|
62
62
|
]}
|
|
63
63
|
aria-current={active ? "page" : undefined}
|
|
64
64
|
data-event="lens_tab_click"
|
|
@@ -64,10 +64,10 @@ function statusLabel(s: StackEntry["status"]): string | null {
|
|
|
64
64
|
|
|
65
65
|
<section
|
|
66
66
|
id="stacks"
|
|
67
|
-
class:list={["
|
|
67
|
+
class:list={["py-12 sm:py-16 scroll-mt-20 border-b border-ink-200 dark:border-ink-800", className]}
|
|
68
68
|
aria-labelledby={bare ? undefined : "grove-stackgrid-heading"}
|
|
69
69
|
>
|
|
70
|
-
<div class="
|
|
70
|
+
<div class="mx-auto w-full max-w-container px-5 sm:px-7">
|
|
71
71
|
{!bare && (
|
|
72
72
|
<header class="mb-6">
|
|
73
73
|
<span class="text-2xs font-medium uppercase tracking-wider text-ink-500 dark:text-ink-400">
|
|
@@ -89,7 +89,7 @@ function statusLabel(s: StackEntry["status"]): string | null {
|
|
|
89
89
|
{stacks.map((s) => (
|
|
90
90
|
<a
|
|
91
91
|
href={buildHref(s.slug)}
|
|
92
|
-
class="
|
|
92
|
+
class="rounded-[calc(var(--radius)+0.25rem)] border-0 bg-muted shadow-none transition-colors hover:bg-secondary group flex h-full items-center gap-3 p-3.5 no-underline"
|
|
93
93
|
data-event="stack_grid_click"
|
|
94
94
|
data-event-source="stack_grid"
|
|
95
95
|
>
|
|
@@ -115,10 +115,10 @@ function statusLabel(s: StackEntry["status"]): string | null {
|
|
|
115
115
|
class:list={[
|
|
116
116
|
"shrink-0 inline-flex items-center rounded-md border px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wider",
|
|
117
117
|
s.status === "live"
|
|
118
|
-
? "
|
|
118
|
+
? "!bg-emerald-50 !text-emerald-700 dark:!bg-emerald-950/80 dark:!text-emerald-300"
|
|
119
119
|
: s.status === "expanding"
|
|
120
|
-
? "
|
|
121
|
-
: "
|
|
120
|
+
? "!bg-blue-50 !text-blue-700 dark:!bg-blue-950/80 dark:!text-blue-300"
|
|
121
|
+
: "!bg-amber-50 !text-amber-800 dark:!bg-amber-950/80 dark:!text-amber-300",
|
|
122
122
|
]}
|
|
123
123
|
>
|
|
124
124
|
{statusLabel(s.status)}
|
|
@@ -129,12 +129,3 @@ function statusLabel(s: StackEntry["status"]): string | null {
|
|
|
129
129
|
</div>
|
|
130
130
|
</div>
|
|
131
131
|
</section>
|
|
132
|
-
|
|
133
|
-
<style>
|
|
134
|
-
.line-clamp-2 {
|
|
135
|
-
display: -webkit-box;
|
|
136
|
-
-webkit-line-clamp: 2;
|
|
137
|
-
-webkit-box-orient: vertical;
|
|
138
|
-
overflow: hidden;
|
|
139
|
-
}
|
|
140
|
-
</style>
|
|
@@ -56,10 +56,10 @@ const items = points && points.length > 0 ? points : defaultPoints;
|
|
|
56
56
|
|
|
57
57
|
<section
|
|
58
58
|
id="about"
|
|
59
|
-
class:list={["
|
|
59
|
+
class:list={["py-12 sm:py-16 scroll-mt-20 border-b border-ink-200 dark:border-ink-800", className]}
|
|
60
60
|
aria-labelledby="grove-why-heading"
|
|
61
61
|
>
|
|
62
|
-
<div class="
|
|
62
|
+
<div class="mx-auto w-full max-w-container px-5 sm:px-7">
|
|
63
63
|
<header class="flex flex-col gap-2">
|
|
64
64
|
<span class="text-2xs font-medium uppercase tracking-wider text-ink-500 dark:text-ink-400">
|
|
65
65
|
{eyebrow}
|
|
@@ -82,7 +82,7 @@ const items = points && points.length > 0 ? points : defaultPoints;
|
|
|
82
82
|
aria-label="Why this directory"
|
|
83
83
|
>
|
|
84
84
|
{items.map((p) => (
|
|
85
|
-
<li class="
|
|
85
|
+
<li class="rounded-[calc(var(--radius)+0.25rem)] border-0 bg-muted shadow-none transition-colors p-4">
|
|
86
86
|
<div
|
|
87
87
|
aria-hidden="true"
|
|
88
88
|
class="mb-3 flex h-8 w-8 items-center justify-center rounded-md border border-ink-200 bg-white text-ink-700 dark:border-ink-800 dark:bg-ink-950 dark:text-ink-300"
|
package/src/index.ts
CHANGED
|
@@ -16,7 +16,15 @@
|
|
|
16
16
|
* - Re-exports the generic `lib/` helpers (search, lenses, scores,
|
|
17
17
|
* repo, format, display, taxonomy-counts) under a single import
|
|
18
18
|
* path so consumers can `import { ... } from "@grove-dev/astro"`.
|
|
19
|
+
*
|
|
20
|
+
* Also auto-loads the consumer's `src/styles/global.css` when it
|
|
21
|
+
* exists. Without this hook the scaffold's global.css (which the
|
|
22
|
+
* CLI generates for theme overrides) sits on disk unused, and any
|
|
23
|
+
* custom theme tokens silently degrade to the package defaults —
|
|
24
|
+
* which is the classic "I changed the brand color in global.css
|
|
25
|
+
* and nothing happened" surprise.
|
|
19
26
|
*/
|
|
27
|
+
import { existsSync } from "node:fs";
|
|
20
28
|
import { fileURLToPath } from "node:url";
|
|
21
29
|
import { dirname, resolve } from "node:path";
|
|
22
30
|
import type { AstroIntegration } from "astro";
|
|
@@ -38,16 +46,27 @@ const srcRoot = resolve(here, "..", "src");
|
|
|
38
46
|
const componentsDir = resolve(srcRoot, "components");
|
|
39
47
|
const layoutsDir = resolve(srcRoot, "layouts");
|
|
40
48
|
|
|
49
|
+
// Virtual module id used to inject the consumer's `src/styles/global.css`.
|
|
50
|
+
// Resolved by the inline Vite plugin below to the absolute file path
|
|
51
|
+
// when the file exists, or to an empty module when it doesn't.
|
|
52
|
+
const CONSUMER_GLOBAL_CSS_VIRTUAL_ID = "virtual:grove-consumer-global-css";
|
|
53
|
+
const CONSUMER_GLOBAL_CSS_EMPTY_ID =
|
|
54
|
+
"\0virtual:grove-consumer-global-css:empty";
|
|
55
|
+
|
|
41
56
|
export default function groveAstro(): AstroIntegration {
|
|
42
57
|
return {
|
|
43
58
|
name: "@grove-dev/astro",
|
|
44
59
|
hooks: {
|
|
45
|
-
"astro:config:setup": ({ updateConfig }) => {
|
|
60
|
+
"astro:config:setup": ({ config, updateConfig, injectScript }) => {
|
|
46
61
|
// Alias the components/layouts source directories so
|
|
47
62
|
// consumer builds can import from
|
|
48
63
|
// @grove-dev/astro/components/ItemCard.astro
|
|
49
64
|
// without us shipping a glob-shaped `exports` map that
|
|
50
65
|
// Vite/Rollup does not expand reliably.
|
|
66
|
+
const consumerRoot = fileURLToPath(config.root);
|
|
67
|
+
const globalCssPath = resolve(consumerRoot, "src/styles/global.css");
|
|
68
|
+
const globalCssExists = existsSync(globalCssPath);
|
|
69
|
+
|
|
51
70
|
updateConfig({
|
|
52
71
|
vite: {
|
|
53
72
|
resolve: {
|
|
@@ -56,9 +75,41 @@ export default function groveAstro(): AstroIntegration {
|
|
|
56
75
|
"@grove-dev/astro/layouts": layoutsDir,
|
|
57
76
|
},
|
|
58
77
|
},
|
|
78
|
+
plugins: [
|
|
79
|
+
{
|
|
80
|
+
name: "grove:consumer-global-css-resolver",
|
|
81
|
+
resolveId(id) {
|
|
82
|
+
if (id === CONSUMER_GLOBAL_CSS_VIRTUAL_ID) {
|
|
83
|
+
return globalCssExists
|
|
84
|
+
? globalCssPath
|
|
85
|
+
: CONSUMER_GLOBAL_CSS_EMPTY_ID;
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
},
|
|
89
|
+
load(id) {
|
|
90
|
+
if (id === CONSUMER_GLOBAL_CSS_EMPTY_ID) {
|
|
91
|
+
return "";
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
],
|
|
59
97
|
},
|
|
60
98
|
});
|
|
99
|
+
|
|
100
|
+
// Always inject the virtual module so the build is symmetric
|
|
101
|
+
// regardless of whether the consumer has a global.css yet.
|
|
102
|
+
// Vite's CSS pipeline (with @tailwindcss/vite) handles the
|
|
103
|
+
// resulting import as a stylesheet — no JS bundle weight.
|
|
104
|
+
injectScript(
|
|
105
|
+
"page-ssr",
|
|
106
|
+
`import "${CONSUMER_GLOBAL_CSS_VIRTUAL_ID}";`,
|
|
107
|
+
);
|
|
61
108
|
},
|
|
62
109
|
},
|
|
63
110
|
};
|
|
64
111
|
}
|
|
112
|
+
|
|
113
|
+
// Re-export the virtual module id so consumers (and tests) can
|
|
114
|
+
// reason about it without copy-pasting the literal string.
|
|
115
|
+
export const CONSUMER_GLOBAL_CSS_ID = CONSUMER_GLOBAL_CSS_VIRTUAL_ID;
|
|
@@ -186,7 +186,7 @@ const favicon =
|
|
|
186
186
|
})();
|
|
187
187
|
</script>
|
|
188
188
|
</head>
|
|
189
|
-
<body class="min-h-screen bg-
|
|
189
|
+
<body class="min-h-screen bg-background text-foreground">
|
|
190
190
|
<slot name="header">
|
|
191
191
|
<Header
|
|
192
192
|
site={site}
|
|
@@ -7,12 +7,12 @@ interface Props {
|
|
|
7
7
|
const { size = "default", class: className = "" } = Astro.props;
|
|
8
8
|
const sizeClass =
|
|
9
9
|
size === "wide"
|
|
10
|
-
? "
|
|
10
|
+
? "mx-auto w-full max-w-wide"
|
|
11
11
|
: size === "narrow"
|
|
12
|
-
? "
|
|
13
|
-
: "
|
|
12
|
+
? "mx-auto w-full max-w-narrow"
|
|
13
|
+
: "mx-auto w-full max-w-container";
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
<div class={`${sizeClass}
|
|
16
|
+
<div class={`${sizeClass} px-5 sm:px-7 ${className}`}>
|
|
17
17
|
<slot />
|
|
18
18
|
</div>
|
package/src/layouts/Footer.astro
CHANGED
|
@@ -104,12 +104,12 @@ const projectItems = project.items.length ? project.items : defaultProject;
|
|
|
104
104
|
|
|
105
105
|
<footer
|
|
106
106
|
class:list={[
|
|
107
|
-
"
|
|
107
|
+
"border-border bg-background mt-16 border-t text-ink-500 dark:text-ink-400",
|
|
108
108
|
className,
|
|
109
109
|
]}
|
|
110
110
|
>
|
|
111
111
|
<div
|
|
112
|
-
class="
|
|
112
|
+
class="mx-auto grid w-full max-w-wide grid-cols-2 gap-8 px-5 py-12 md:grid-cols-4 sm:px-7"
|
|
113
113
|
>
|
|
114
114
|
<div class="col-span-2 md:col-span-1">
|
|
115
115
|
<div
|
|
@@ -225,7 +225,7 @@ const projectItems = project.items.length ? project.items : defaultProject;
|
|
|
225
225
|
|
|
226
226
|
<div class="border-t border-ink-200 dark:border-ink-800">
|
|
227
227
|
<div
|
|
228
|
-
class="
|
|
228
|
+
class="mx-auto flex w-full max-w-wide flex-wrap items-center gap-3 px-5 py-4 text-2xs text-ink-500 sm:px-7 dark:text-ink-400"
|
|
229
229
|
>
|
|
230
230
|
<span>© {year} {holder}{licenseLine ? `. ${licenseLine}` : "."}</span>
|
|
231
231
|
{gh && (
|
package/src/layouts/Header.astro
CHANGED
|
@@ -73,12 +73,12 @@ const starsLabel =
|
|
|
73
73
|
|
|
74
74
|
<header
|
|
75
75
|
class:list={[
|
|
76
|
-
"sticky top-0 z-50 border-b
|
|
76
|
+
"border-border bg-background/85 sticky top-0 z-50 border-b backdrop-blur",
|
|
77
77
|
className,
|
|
78
78
|
]}
|
|
79
79
|
>
|
|
80
80
|
<div
|
|
81
|
-
class="
|
|
81
|
+
class="mx-auto flex w-full max-w-wide items-center gap-6 px-5 py-3 sm:px-7"
|
|
82
82
|
>
|
|
83
83
|
<a
|
|
84
84
|
href="/"
|
|
@@ -110,7 +110,7 @@ const starsLabel =
|
|
|
110
110
|
{submitHref && (
|
|
111
111
|
<a
|
|
112
112
|
href={submitHref}
|
|
113
|
-
class="
|
|
113
|
+
class="inline-flex h-8 cursor-pointer items-center justify-center gap-1.5 rounded-[var(--radius)] border border-transparent px-3 text-sm font-medium leading-none no-underline outline-none transition-colors focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35 border-border bg-secondary text-foreground hover:bg-accent hidden sm:inline-flex"
|
|
114
114
|
>
|
|
115
115
|
<svg
|
|
116
116
|
viewBox="0 0 16 16"
|
|
@@ -132,7 +132,7 @@ const starsLabel =
|
|
|
132
132
|
rel="noopener noreferrer"
|
|
133
133
|
aria-label={`${repoLabel} on GitHub — ${stars} stars`}
|
|
134
134
|
title={`${repoLabel} on GitHub`}
|
|
135
|
-
class="inline-flex h-
|
|
135
|
+
class="inline-flex h-8 cursor-pointer items-center justify-center gap-1.5 overflow-hidden rounded-[var(--radius)] border border-border bg-secondary p-0 text-sm font-medium leading-none text-foreground no-underline outline-none transition-colors hover:bg-accent focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35"
|
|
136
136
|
>
|
|
137
137
|
<span class="flex items-center gap-1.5 px-2.5 py-1.5 text-ink-900 dark:text-ink-100">
|
|
138
138
|
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" fill="currentColor">
|
|
@@ -140,7 +140,7 @@ const starsLabel =
|
|
|
140
140
|
</svg>
|
|
141
141
|
<span>{repoLabel}</span>
|
|
142
142
|
</span>
|
|
143
|
-
<span class="flex items-center gap-1
|
|
143
|
+
<span class="flex items-center gap-1 border-s border-border bg-secondary px-2 py-1.5 text-secondary-foreground">
|
|
144
144
|
<svg viewBox="0 0 16 16" width="11" height="11" aria-hidden="true" fill="currentColor" class="text-amber-500">
|
|
145
145
|
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z"></path>
|
|
146
146
|
</svg>
|
|
@@ -24,7 +24,7 @@ const { class: className = "" } = Astro.props;
|
|
|
24
24
|
data-theme-toggle
|
|
25
25
|
aria-label="Toggle theme"
|
|
26
26
|
title="Toggle theme"
|
|
27
|
-
class={`
|
|
27
|
+
class={`inline-flex h-8 cursor-pointer items-center justify-center gap-1.5 rounded-[var(--radius)] border border-transparent px-3 text-sm font-medium leading-none no-underline outline-none transition-colors focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/35 border-border bg-secondary text-foreground hover:bg-accent relative h-8 w-8 p-0 ${className}`}
|
|
28
28
|
>
|
|
29
29
|
{/* Sun — shown in dark mode (click to go light) */}
|
|
30
30
|
<svg
|