Skip to content

Commit 613ca24

Browse files
Merge branch 'main' into fix/preserve-current-page-context
2 parents 6ed842a + 0b55ca4 commit 613ca24

53 files changed

Lines changed: 1867 additions & 489 deletions

Some content is hidden

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

.github/workflows/semantic-pull-requests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ jobs:
2626
a11y
2727
deps
2828
docs
29+
cli
2930
i18n
3031
ui
3132
subjectPattern: ^(?![A-Z]).+$

app/components/AppHeader.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ onKeyStroke(
109109
to="/"
110110
:aria-label="$t('header.home')"
111111
dir="ltr"
112-
class="inline-flex items-center gap-2 header-logo font-mono text-lg font-medium text-fg hover:text-fg transition-colors duration-200 rounded"
112+
class="inline-flex items-center gap-1 header-logo font-mono text-lg font-medium text-fg hover:text-fg/90 transition-colors duration-200 rounded"
113113
>
114114
<AppLogo class="w-8 h-8 rounded-lg" />
115115
<span>npmx</span>

app/components/AppLogo.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ defineProps<{
1515
>
1616
<title>{{ $t('alt_logo') }}</title>
1717
<rect fill="var(--bg)" width="512" height="512" rx="64" />
18-
<rect fill="var(--fg)" x="110" y="310" width="60" height="60" />
18+
<rect fill="currentColor" x="110" y="310" width="60" height="60" />
1919
<text
2020
fill="var(--accent)"
2121
x="320"

app/components/CollapsibleSection.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,10 @@ useHead({
125125

126126
<div
127127
:id="contentId"
128-
class="grid ms-6 transition-[grid-template-rows] duration-200 ease-in-out collapsible-content overflow-hidden"
128+
class="grid ms-6 grid-rows-[1fr] transition-[grid-template-rows] duration-200 ease-in-out collapsible-content overflow-hidden"
129129
:inert="!isOpen"
130130
>
131-
<div class="min-h-0 min-w-0 p-1">
131+
<div class="min-h-0 min-w-0">
132132
<slot />
133133
</div>
134134
</div>

app/components/Compare/FacetCard.vue

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,13 @@ function getShortName(header: string): string {
7575
<!-- Facet header -->
7676
<div class="flex items-center gap-1.5 px-3 py-2 bg-bg-subtle border-b border-border">
7777
<span class="text-xs text-fg-muted uppercase tracking-wider font-medium">{{ label }}</span>
78-
<span
79-
v-if="description"
80-
class="i-carbon:information w-3 h-3 text-fg-subtle"
81-
:title="description"
82-
aria-hidden="true"
83-
/>
78+
<TooltipApp v-if="description" :text="description" position="top">
79+
<span
80+
class="i-carbon:information w-3 h-3 text-fg-subtle"
81+
:title="description"
82+
aria-hidden="true"
83+
/>
84+
</TooltipApp>
8485
</div>
8586

8687
<!-- Package values -->

app/components/Compare/PackageSelector.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ function handleBlur() {
7575
:aria-label="$t('compare.selector.remove_package', { package: pkg })"
7676
@click="removePackage(pkg)"
7777
>
78-
<span class="i-carbon:close w-3.5 h-3.5" aria-hidden="true" />
78+
<span class="i-carbon:close flex items-center w-3.5 h-3.5" aria-hidden="true" />
7979
</button>
8080
</div>
8181
</div>

app/components/Header/AccountMenu.client.vue

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,17 @@ function openAuthModal() {
8787
</span>
8888

8989
<!-- Atmosphere avatar (second/front, overlapping) -->
90+
<img
91+
v-if="atprotoUser?.avatar"
92+
:src="atprotoUser.avatar"
93+
:alt="atprotoUser.handle"
94+
width="24"
95+
height="24"
96+
class="w-6 h-6 rounded-full ring-2 ring-bg"
97+
:class="hasBothConnections ? 'relative z-10' : ''"
98+
/>
9099
<span
91-
v-if="atprotoUser"
100+
v-else-if="atprotoUser"
92101
class="w-6 h-6 rounded-full bg-bg-muted ring-2 ring-bg flex items-center justify-center"
93102
:class="hasBothConnections ? 'relative z-10' : ''"
94103
>
@@ -135,7 +144,7 @@ function openAuthModal() {
135144
v-if="isNpmConnected && npmUser"
136145
type="button"
137146
role="menuitem"
138-
class="w-full px-3 py-2.5 flex items-center gap-3 hover:bg-bg-subtle transition-colors text-start"
147+
class="w-full px-3 py-2.5 flex items-center gap-3 hover:bg-bg-subtle transition-colors text-start rounded-md"
139148
@click="openConnectorModal"
140149
>
141150
<img
@@ -178,10 +187,21 @@ function openAuthModal() {
178187
v-if="atprotoUser"
179188
type="button"
180189
role="menuitem"
181-
class="w-full px-3 py-2.5 flex items-center gap-3 hover:bg-bg-subtle transition-colors text-start"
190+
class="w-full px-3 py-2.5 flex items-center gap-3 hover:bg-bg-subtle transition-colors text-start rounded-md"
182191
@click="openAuthModal"
183192
>
184-
<span class="w-8 h-8 rounded-full bg-bg-muted flex items-center justify-center">
193+
<img
194+
v-if="atprotoUser.avatar"
195+
:src="atprotoUser.avatar"
196+
:alt="atprotoUser.handle"
197+
width="32"
198+
height="32"
199+
class="w-8 h-8 rounded-full"
200+
/>
201+
<span
202+
v-else
203+
class="w-8 h-8 rounded-full bg-bg-muted flex items-center justify-center"
204+
>
185205
<span class="i-carbon-cloud w-4 h-4 text-fg-muted" aria-hidden="true" />
186206
</span>
187207
<div class="flex-1 min-w-0">

app/components/Header/SearchBox.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ defineExpose({ focus })
109109
<div class="relative group" :class="{ 'is-focused': isSearchFocused }">
110110
<div class="search-box relative flex items-center">
111111
<span
112-
class="absolute inset-is-3 text-fg-subtle font-mono text-sm pointer-events-none transition-colors duration-200 motion-reduce:transition-none group-focus-within:text-accent z-1"
112+
class="absolute inset-is-3 text-fg-subtle font-mono text-sm pointer-events-none transition-colors duration-200 motion-reduce:transition-none [.group:hover:not(:focus-within)_&]:text-fg/80 group-focus-within:text-accent z-1"
113113
>
114114
/
115115
</span>
@@ -122,7 +122,7 @@ defineExpose({ focus })
122122
name="q"
123123
:placeholder="$t('search.placeholder')"
124124
v-bind="noCorrect"
125-
class="w-full min-w-25 bg-bg-subtle border border-border rounded-md ps-7 pe-3 py-1.5 font-mono text-sm text-fg placeholder:text-fg-subtle transition-border-color duration-300 motion-reduce:transition-none focus:border-accent focus-visible:(outline-2 outline-accent/70)"
125+
class="w-full min-w-25 bg-bg-subtle border border-border rounded-md ps-7 pe-3 py-1.5 font-mono text-sm text-fg placeholder:text-fg-subtle transition-[border-color,outline-color] duration-300 hover:border-fg-subtle outline-2 outline-transparent focus:border-accent focus-visible:(outline-2 outline-accent/70)"
126126
@focus="handleSearchFocus"
127127
@blur="handleSearchBlur"
128128
/>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
declare const _default: any
2+
3+
export default _default

app/components/OgImage/Package.vue

Lines changed: 130 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,73 @@
11
<script setup lang="ts">
2-
import { computed, toRefs } from 'vue'
2+
import { joinURL } from 'ufo'
33
44
const props = withDefaults(
55
defineProps<{
66
name: string
77
version: string
8-
stars: number
9-
downloads?: string
10-
license?: string
118
primaryColor?: string
129
}>(),
1310
{
14-
downloads: '',
15-
license: '',
1611
primaryColor: '#60a5fa',
1712
},
1813
)
1914
20-
const { name, version, stars, downloads, license, primaryColor } = toRefs(props)
15+
const { name, version, primaryColor } = toRefs(props)
16+
17+
const {
18+
data: resolvedVersion,
19+
status: versionStatus,
20+
error: versionError,
21+
} = await useResolvedVersion(name, version)
22+
23+
if (
24+
versionStatus.value === 'error' &&
25+
versionError.value?.statusCode &&
26+
versionError.value.statusCode >= 400 &&
27+
versionError.value.statusCode < 500
28+
) {
29+
throw createError({
30+
statusCode: 404,
31+
})
32+
}
33+
34+
const { data: downloads, refresh: refreshDownloads } = usePackageDownloads(name, 'last-week')
35+
const { data: pkg, refresh: refreshPkg } = usePackage(name, resolvedVersion.value ?? version.value)
36+
const displayVersion = computed(() => pkg.value?.requestedVersion ?? null)
37+
38+
const repositoryUrl = computed(() => {
39+
const repo = displayVersion.value?.repository
40+
if (!repo?.url) return null
41+
let url = normalizeGitUrl(repo.url)
42+
// append `repository.directory` for monorepo packages
43+
if (repo.directory) {
44+
url = joinURL(`${url}/tree/HEAD`, repo.directory)
45+
}
46+
return url
47+
})
48+
49+
const { data: likes, refresh: refreshLikes } = useFetch(() => `/api/social/likes/${name.value}`, {
50+
default: () => ({ totalLikes: 0, userHasLiked: false }),
51+
})
52+
53+
const { stars, refresh: refreshRepoMeta } = useRepoMeta(repositoryUrl)
2154
2255
const formattedStars = computed(() =>
2356
Intl.NumberFormat('en', {
2457
notation: 'compact',
2558
maximumFractionDigits: 1,
2659
}).format(stars.value),
2760
)
61+
62+
try {
63+
await refreshPkg()
64+
await Promise.all([refreshRepoMeta(), refreshDownloads(), refreshLikes()])
65+
} catch (err) {
66+
console.warn('[og-image-package] Failed to load data server-side:', err)
67+
throw createError({
68+
statusCode: 404,
69+
})
70+
}
2871
</script>
2972

3073
<template>
@@ -34,7 +77,7 @@ const formattedStars = computed(() =>
3477
<div class="relative z-10 flex flex-col gap-6">
3578
<div class="flex items-start gap-4">
3679
<div
37-
class="flex items-start justify-center w-16 h-16 rounded-xl shadow-lg bg-gradient-to-tr from-[#3b82f6]"
80+
class="flex items-center justify-center w-16 h-16 p-4 rounded-xl shadow-lg bg-gradient-to-tr from-[#3b82f6]"
3881
:style="{ backgroundColor: primaryColor }"
3982
>
4083
<svg
@@ -60,58 +103,111 @@ const formattedStars = computed(() =>
60103
class="text-8xl font-bold tracking-tighter"
61104
style="font-family: 'Geist Sans', sans-serif"
62105
>
63-
<span :style="{ color: primaryColor }" class="opacity-80">./</span>{{ name }}
106+
<span :style="{ color: primaryColor }" class="opacity-80">./</span>{{ pkg?.name }}
64107
</h1>
65108
</div>
66109

67110
<div
68-
class="flex items-center gap-3 text-4xl font-light text-[#a3a3a3]"
111+
class="flex items-center gap-5 text-4xl font-light text-[#a3a3a3]"
69112
style="font-family: 'Geist Sans', sans-serif"
70113
>
71114
<span
72-
class="px-3 py-1 rounded-lg border"
115+
class="px-3 py-1 mr-2 rounded-lg border font-bold opacity-90"
73116
:style="{
74117
color: primaryColor,
75118
backgroundColor: primaryColor + '10',
76119
borderColor: primaryColor + '30',
77120
boxShadow: `0 0 20px ${primaryColor}25`,
78121
}"
79122
>
80-
{{ version }}
123+
{{ resolvedVersion }}
81124
</span>
82-
<span v-if="downloads">
83-
<span>• {{ downloads }} </span>
84-
<span class="flex items-center gap-0">
85-
<svg
86-
width="30"
87-
height="30"
88-
viewBox="0 0 24 24"
89-
fill="none"
90-
stroke="currentColor"
91-
stroke-width="2"
92-
stroke-linecap="round"
93-
stroke-linejoin="round"
94-
class="text-white/70"
95-
>
96-
<circle cx="12" cy="12" r="10" class="opacity-40" />
97-
<path d="M12 8v8m-3-3l3 3 3-3" />
98-
</svg>
99-
<span>/wk</span>
125+
<span v-if="downloads" class="flex items-center gap-2">
126+
<svg
127+
width="30"
128+
height="30"
129+
viewBox="0 0 24 24"
130+
fill="none"
131+
:stroke="primaryColor"
132+
stroke-width="2"
133+
stroke-linecap="round"
134+
stroke-linejoin="round"
135+
class="opacity-90"
136+
>
137+
<circle cx="12" cy="12" r="10" class="opacity-60" />
138+
<path d="M12 8v8m-3-3l3 3 3-3" />
139+
</svg>
140+
<span>{{ $n(downloads.downloads) }}/wk</span>
141+
</span>
142+
<span v-if="pkg?.license" class="flex items-center gap-2">
143+
<svg
144+
viewBox="0 0 32 32"
145+
:fill="primaryColor"
146+
xmlns="http://www.w3.org/2000/svg"
147+
height="32"
148+
width="32"
149+
class="opacity-90"
150+
>
151+
<path
152+
d="M21.7166 12.57C20.5503 10.631 18.4257 9.33301 15.9997 9.33301C12.3197 9.33301 9.33301 12.3197 9.33301 15.9997C9.33301 19.6797 12.3197 22.6663 15.9997 22.6663C18.4257 22.6663 20.5503 21.3683 21.7166 19.4294L19.4302 18.0586C18.7307 19.2218 17.4566 19.9997 15.9997 19.9997C13.7897 19.9997 11.9997 18.2097 11.9997 15.9997C11.9997 13.7897 13.7897 11.9997 15.9997 11.9997C17.457 11.9997 18.7318 12.7782 19.431 13.9421L21.7166 12.57Z"
153+
/>
154+
<path
155+
fill-rule="evenodd"
156+
clip-rule="evenodd"
157+
d="M15.5247 2.66602C22.8847 2.66602 28.8581 8.63932 28.8581 15.9993C28.8581 23.3593 22.8847 29.3327 15.5247 29.3327C8.16471 29.3327 2.19141 23.3593 2.19141 15.9993C2.19141 8.63932 8.16471 2.66602 15.5247 2.66602ZM4.85807 15.9993C4.85807 10.106 9.63135 5.33268 15.5247 5.33268C21.4181 5.33268 26.1914 10.106 26.1914 15.9993C26.1914 21.8927 21.4181 26.666 15.5247 26.666C9.63135 26.666 4.85807 21.8927 4.85807 15.9993Z"
158+
class="opacity-60"
159+
/>
160+
</svg>
161+
<span>
162+
{{ pkg.license }}
100163
</span>
101164
</span>
102-
<span v-if="license"> • {{ license }}</span>
103165
<span class="flex items-center gap-2">
104-
<span>•</span>
105-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32px" height="32px">
166+
<svg
167+
xmlns="http://www.w3.org/2000/svg"
168+
viewBox="0 0 32 32"
169+
width="32px"
170+
height="32px"
171+
class="opacity-60"
172+
>
106173
<path
107-
fill="currentColor"
174+
:fill="primaryColor"
108175
d="m16 6.52l2.76 5.58l.46 1l1 .15l6.16.89l-4.38 4.3l-.75.73l.18 1l1.05 6.13l-5.51-2.89L16 23l-.93.49l-5.51 2.85l1-6.13l.18-1l-.74-.77l-4.42-4.35l6.16-.89l1-.15l.46-1zM16 2l-4.55 9.22l-10.17 1.47l7.36 7.18L6.9 30l9.1-4.78L25.1 30l-1.74-10.13l7.36-7.17l-10.17-1.48Z"
109176
/>
110177
</svg>
111178
<span>
112179
{{ formattedStars }}
113180
</span>
114181
</span>
182+
<span class="flex items-center gap-2">
183+
<svg
184+
width="32"
185+
height="32"
186+
viewBox="0 0 32 32"
187+
fill="none"
188+
xmlns="http://www.w3.org/2000/svg"
189+
class="opacity-90"
190+
>
191+
<path
192+
d="M19.3057 25.8317L18.011 27.0837C17.7626 27.3691 17.4562 27.5983 17.1124 27.7561C16.7685 27.914 16.3951 27.9969 16.0167 27.9993C15.6384 28.0017 15.2639 27.9235 14.918 27.77C14.5722 27.6165 14.263 27.3912 14.011 27.1091L6.66699 19.9997C4.66699 17.9997 2.66699 15.7331 2.66699 12.6664C2.66702 11.1827 3.11712 9.73384 3.95784 8.51128C4.79856 7.28872 5.99035 6.34994 7.3758 5.81893C8.76126 5.28792 10.2752 5.18965 11.7177 5.53712C13.1602 5.88459 14.4633 6.66143 15.455 7.76506C15.5248 7.83975 15.6093 7.89929 15.7031 7.93999C15.7969 7.9807 15.8981 8.00171 16.0003 8.00171C16.1026 8.00171 16.2038 7.9807 16.2976 7.93999C16.3914 7.89929 16.4758 7.83975 16.5457 7.76506C17.5342 6.65426 18.8377 5.87088 20.2825 5.5192C21.7273 5.16751 23.245 5.26419 24.6335 5.79637C26.022 6.32856 27.2155 7.271 28.0551 8.49826C28.8948 9.72553 29.3407 11.1794 29.3337 12.6664C29.3332 13.3393 29.2349 14.0085 29.0417 14.6531"
193+
:stroke="primaryColor"
194+
stroke-width="2.66667"
195+
stroke-linecap="round"
196+
stroke-linejoin="round"
197+
class="opacity-60"
198+
/>
199+
<path
200+
d="M20 20H24M28 20H24M24 16L24 20M24 24L24 20"
201+
:stroke="primaryColor"
202+
stroke-width="2.66667"
203+
stroke-linecap="round"
204+
stroke-linejoin="round"
205+
/>
206+
</svg>
207+
<span>
208+
{{ likes.totalLikes }}
209+
</span>
210+
</span>
115211
</div>
116212
</div>
117213

0 commit comments

Comments
 (0)