Skip to content

Commit 194474c

Browse files
authored
Merge branch 'main' into fix/server-error-multiple-sp
2 parents 4533bdb + 7071ba5 commit 194474c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+1227
-798
lines changed

app/assets/main.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,32 @@
7575
--badge-cyan: oklch(0.571 0.181 210);
7676
}
7777

78+
@media (prefers-contrast: more) {
79+
:root[data-theme='dark'] {
80+
/* text colors */
81+
--fg: oklch(1 0 0);
82+
--fg-muted: oklch(0.769 0 0);
83+
--fg-subtle: oklch(0.693 0 0);
84+
85+
/* border, separator colors */
86+
--border: oklch(0.769 0 0);
87+
--border-subtle: oklch(0.739 0 0);
88+
--border-hover: oklch(0.771 0 0);
89+
}
90+
91+
:root[data-theme='light'] {
92+
/* text colors */
93+
--fg: oklch(0 0 0);
94+
--fg-muted: oklch(0.329 0 0);
95+
--fg-subtle: oklch(0.4 0 0);
96+
97+
/* border, separator colors */
98+
--border: oklch(0.3514 0 0);
99+
--border-subtle: oklch(0.422 0 0);
100+
--border-hover: oklch(0.315 0 0);
101+
}
102+
}
103+
78104
html {
79105
-webkit-font-smoothing: antialiased;
80106
-moz-osx-font-smoothing: grayscale;

app/components/CallToAction.vue

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<script setup lang="ts">
2+
const socialLinks = {
3+
github: 'https://repo.npmx.dev',
4+
discord: 'https://chat.npmx.dev',
5+
bluesky: 'https://social.npmx.dev',
6+
}
7+
</script>
8+
9+
<template>
10+
<div>
11+
<h2 class="text-lg text-fg-subtle uppercase tracking-wider mb-6">
12+
{{ $t('about.get_involved.title') }}
13+
</h2>
14+
15+
<div class="grid gap-4 sm:grid-cols-3">
16+
<a
17+
:href="socialLinks.github"
18+
target="_blank"
19+
rel="noopener noreferrer"
20+
class="group flex flex-col gap-3 p-4 rounded-lg bg-bg-subtle hover:bg-bg-elevated border border-border hover:border-border-hover transition-all duration-200"
21+
>
22+
<div class="flex gap-2">
23+
<span class="i-carbon:logo-github shrink-0 mt-1 w-5 h-5 text-fg" aria-hidden="true" />
24+
<span class="font-medium text-fg">
25+
{{ $t('about.get_involved.contribute.title') }}
26+
</span>
27+
</div>
28+
<p class="text-sm text-fg-muted leading-relaxed">
29+
{{ $t('about.get_involved.contribute.description') }}
30+
</p>
31+
<span
32+
class="text-sm text-fg-muted group-hover:text-fg inline-flex items-center gap-1 mt-auto"
33+
>
34+
{{ $t('about.get_involved.contribute.cta') }}
35+
<span class="i-carbon:arrow-right rtl-flip w-3 h-3" aria-hidden="true" />
36+
</span>
37+
</a>
38+
39+
<a
40+
:href="socialLinks.discord"
41+
target="_blank"
42+
rel="noopener noreferrer"
43+
class="group flex flex-col gap-3 p-4 rounded-lg bg-bg-subtle hover:bg-bg-elevated border border-border hover:border-border-hover transition-all duration-200"
44+
>
45+
<div class="flex gap-2">
46+
<span class="i-carbon:chat shrink-0 mt-1 w-5 h-5 text-fg" aria-hidden="true" />
47+
<span class="font-medium text-fg">
48+
{{ $t('about.get_involved.community.title') }}
49+
</span>
50+
</div>
51+
<p class="text-sm text-fg-muted leading-relaxed">
52+
{{ $t('about.get_involved.community.description') }}
53+
</p>
54+
<span
55+
class="text-sm text-fg-muted group-hover:text-fg inline-flex items-center gap-1 mt-auto"
56+
>
57+
{{ $t('about.get_involved.community.cta') }}
58+
<span class="i-carbon:arrow-right rtl-flip w-3 h-3" aria-hidden="true" />
59+
</span>
60+
</a>
61+
62+
<a
63+
:href="socialLinks.bluesky"
64+
target="_blank"
65+
rel="noopener noreferrer"
66+
class="group flex flex-col gap-3 p-4 rounded-lg bg-bg-subtle hover:bg-bg-elevated border border-border hover:border-border-hover transition-all duration-200"
67+
>
68+
<div class="flex gap-2">
69+
<span class="i-simple-icons:bluesky shrink-0 mt-1 w-5 h-5 text-fg" aria-hidden="true" />
70+
<span class="font-medium text-fg">
71+
{{ $t('about.get_involved.follow.title') }}
72+
</span>
73+
</div>
74+
<p class="text-sm text-fg-muted leading-relaxed">
75+
{{ $t('about.get_involved.follow.description') }}
76+
</p>
77+
<span
78+
class="text-sm text-fg-muted group-hover:text-fg inline-flex items-center gap-1 mt-auto"
79+
>
80+
{{ $t('about.get_involved.follow.cta') }}
81+
<span class="i-carbon:arrow-right rtl-flip w-3 h-3" aria-hidden="true" />
82+
</span>
83+
</a>
84+
</div>
85+
</div>
86+
</template>

app/components/Package/Card.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const pkgDescription = useMarkdown(() => ({
3232
<article
3333
class="group card-interactive scroll-mt-48 scroll-mb-6 relative focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-bg focus-within:ring-offset-2 focus-within:ring-fg/50 focus-within:bg-bg-muted focus-within:border-border-hover"
3434
:class="{
35-
'border-accent/30 bg-accent/5': isExactMatch,
35+
'border-accent/30 contrast-more:border-accent/90 bg-accent/5': isExactMatch,
3636
}"
3737
>
3838
<!-- Glow effect for exact matches -->

app/components/Package/Versions.vue

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import type { PackageVersionInfo, PackumentVersion } from '#shared/types'
2+
import type { PackageVersionInfo, SlimVersion } from '#shared/types'
33
import { compare } from 'semver'
44
import type { RouteLocationRaw } from 'vue-router'
55
import { fetchAllPackageVersions } from '~/composables/useNpmRegistry'
@@ -14,7 +14,7 @@ import {
1414
1515
const props = defineProps<{
1616
packageName: string
17-
versions: Record<string, PackumentVersion>
17+
versions: Record<string, SlimVersion>
1818
distTags: Record<string, string>
1919
time: Record<string, string>
2020
}>()
@@ -31,13 +31,6 @@ interface VersionDisplay {
3131
deprecated?: string
3232
}
3333
34-
// Check if a version has provenance/attestations
35-
function hasProvenance(version: PackumentVersion | undefined): boolean {
36-
if (!version?.dist) return false
37-
const dist = version.dist as { attestations?: unknown }
38-
return !!dist.attestations
39-
}
40-
4134
// Build route object for package version link
4235
function versionRoute(version: string): RouteLocationRaw {
4336
return {
@@ -53,10 +46,7 @@ const versionToTags = computed(() => buildVersionToTagsMap(props.distTags))
5346
// Deduplicates so each version appears only once, with all its tags
5447
const allTagRows = computed(() => {
5548
// Group tags by version with their metadata
56-
const versionMap = new Map<
57-
string,
58-
{ tags: string[]; versionData: PackumentVersion | undefined }
59-
>()
49+
const versionMap = new Map<string, { tags: string[]; versionData: SlimVersion | undefined }>()
6050
for (const [tag, version] of Object.entries(props.distTags)) {
6151
const existing = versionMap.get(version)
6252
if (existing) {
@@ -88,7 +78,7 @@ const allTagRows = computed(() => {
8878
version,
8979
time: props.time[version],
9080
tags,
91-
hasProvenance: hasProvenance(versionData),
81+
hasProvenance: versionData?.hasProvenance,
9282
deprecated: versionData?.deprecated,
9383
} as VersionDisplay,
9484
}))

app/components/Package/WeeklyDownloadStats.vue

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { OKLCH_NEUTRAL_FALLBACK, lightenOklch } from '~/utils/colors'
55
66
const props = defineProps<{
77
packageName: string
8+
createdIso: string | null
89
}>()
910
1011
const chartModal = useModal('chart-modal')
@@ -16,9 +17,6 @@ function openChartModal() {
1617
nextTick(() => chartModal.open())
1718
}
1819
19-
const { data: packument } = usePackage(() => props.packageName)
20-
const createdIso = computed(() => packument.value?.time?.created ?? null)
21-
2220
const { fetchPackageDownloadEvolution } = useCharts()
2321
2422
const { accentColors, selectedAccentColor } = useAccentColor()
@@ -92,7 +90,7 @@ async function loadWeeklyDownloads() {
9290
try {
9391
const result = await fetchPackageDownloadEvolution(
9492
() => props.packageName,
95-
() => createdIso.value,
93+
() => props.createdIso,
9694
() => ({ granularity: 'week' as const, weeks: 52 }),
9795
)
9896
weeklyDownloads.value = (result as WeeklyDownloadPoint[]) ?? []

app/components/Readme.vue

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,43 @@
22
defineProps<{
33
html: string
44
}>()
5+
6+
const { copy } = useClipboard()
7+
8+
const handleCopy = async (e: MouseEvent) => {
9+
const target = (e.target as HTMLElement).closest('[data-copy]')
10+
if (!target) return
11+
12+
const wrapper = target.closest('.readme-code-block')
13+
if (!wrapper) return
14+
15+
const pre = wrapper.querySelector('pre')
16+
if (!pre?.textContent) return
17+
18+
await copy(pre.textContent)
19+
20+
const icon = target.querySelector('span')
21+
if (!icon) return
22+
23+
const originalIcon = 'i-carbon:copy'
24+
const successIcon = 'i-carbon:checkmark'
25+
26+
icon.classList.remove(originalIcon)
27+
icon.classList.add(successIcon)
28+
29+
setTimeout(() => {
30+
icon.classList.remove(successIcon)
31+
icon.classList.add(originalIcon)
32+
}, 2000)
33+
}
534
</script>
635

736
<template>
8-
<article class="readme prose prose-invert max-w-[70ch] lg:max-w-none" v-html="html" />
37+
<article
38+
class="readme prose prose-invert max-w-[70ch] lg:max-w-none"
39+
v-html="html"
40+
@click="handleCopy"
41+
/>
942
</template>
1043

1144
<style scoped>
@@ -99,6 +132,90 @@ defineProps<{
99132
box-sizing: border-box;
100133
}
101134
135+
.readme :deep(.readme-code-block) {
136+
display: block;
137+
width: 100%;
138+
position: relative;
139+
}
140+
141+
.readme :deep(.readme-copy-button) {
142+
position: absolute;
143+
top: 0.4rem;
144+
inset-inline-end: 0.4rem;
145+
display: inline-flex;
146+
align-items: center;
147+
justify-content: center;
148+
padding: 0.25rem;
149+
border-radius: 6px;
150+
background: color-mix(in srgb, var(--bg-subtle) 80%, transparent);
151+
border: 1px solid var(--border);
152+
color: var(--fg-subtle);
153+
opacity: 0;
154+
transition:
155+
opacity 0.2s ease,
156+
color 0.2s ease,
157+
border-color 0.2s ease;
158+
}
159+
160+
.readme :deep(.readme-code-block:hover .readme-copy-button),
161+
.readme :deep(.readme-copy-button:focus-visible) {
162+
opacity: 1;
163+
}
164+
165+
.readme :deep(.readme-copy-button:hover) {
166+
color: var(--fg);
167+
border-color: var(--border-hover);
168+
}
169+
170+
.readme :deep(.readme-copy-button > span) {
171+
width: 1rem;
172+
height: 1rem;
173+
display: inline-block;
174+
pointer-events: none;
175+
}
176+
177+
.readme :deep(.readme-code-block) {
178+
display: block;
179+
width: 100%;
180+
position: relative;
181+
}
182+
183+
.readme :deep(.readme-copy-button) {
184+
position: absolute;
185+
top: 0.4rem;
186+
inset-inline-end: 0.4rem;
187+
display: inline-flex;
188+
align-items: center;
189+
justify-content: center;
190+
padding: 0.25rem;
191+
border-radius: 6px;
192+
background: color-mix(in srgb, var(--bg-subtle) 80%, transparent);
193+
border: 1px solid var(--border);
194+
color: var(--fg-subtle);
195+
opacity: 0;
196+
transition:
197+
opacity 0.2s ease,
198+
color 0.2s ease,
199+
border-color 0.2s ease;
200+
}
201+
202+
.readme :deep(.readme-code-block:hover .readme-copy-button),
203+
.readme :deep(.readme-copy-button:focus-visible) {
204+
opacity: 1;
205+
}
206+
207+
.readme :deep(.readme-copy-button:hover) {
208+
color: var(--fg);
209+
border-color: var(--border-hover);
210+
}
211+
212+
.readme :deep(.readme-copy-button > span) {
213+
width: 1.05rem;
214+
height: 1.05rem;
215+
display: inline-block;
216+
pointer-events: none;
217+
}
218+
102219
.readme :deep(pre code),
103220
.readme :deep(.shiki code) {
104221
background: transparent !important;
@@ -308,4 +425,17 @@ defineProps<{
308425
margin: 0 0.25rem 0.25rem 0;
309426
border-radius: 4px;
310427
}
428+
429+
/* Screen reader only text */
430+
.readme :deep(.sr-only) {
431+
position: absolute;
432+
width: 1px;
433+
height: 1px;
434+
padding: 0;
435+
margin: -1px;
436+
overflow: hidden;
437+
clip: rect(0, 0, 0, 0);
438+
white-space: nowrap;
439+
border-width: 0;
440+
}
311441
</style>

app/components/SearchSuggestionCard.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ defineProps<{
1515
<article
1616
class="group card-interactive relative focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-bg focus-within:ring-offset-2 focus-within:ring-fg/50 focus-within:bg-bg-muted focus-within:border-border-hover"
1717
:class="{
18-
'border-accent/30 bg-accent/5': isExactMatch,
18+
'border-accent/30 contrast-more:border-accent/90 bg-accent/5': isExactMatch,
1919
}"
2020
>
2121
<!-- Glow effect for exact matches -->

app/components/Settings/Toggle.client.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ const checked = defineModel<boolean>({
2121
{{ label }}
2222
</span>
2323
<span
24-
class="relative inline-flex h-6 w-11 shrink-0 items-center rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out motion-reduce:transition-none shadow-sm cursor-pointer"
25-
:class="checked ? 'bg-accent' : 'bg-bg border border-border'"
24+
class="relative inline-flex h-6 w-11 shrink-0 items-center rounded-full border-2 transition-colors duration-200 ease-in-out motion-reduce:transition-none cursor-pointer"
25+
:class="checked ? 'bg-accent border-transparent shadow-sm' : 'bg-bg border border-border'"
2626
aria-hidden="true"
2727
>
2828
<span

0 commit comments

Comments
 (0)