Skip to content

Commit 342adca

Browse files
authored
Merge branch 'main' into feat/changelog-1
2 parents cab3cc6 + 7a30866 commit 342adca

32 files changed

Lines changed: 580 additions & 280 deletions
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: "\U0001F41E Bug report"
2+
description: Create a report to help us improve npmx
3+
body:
4+
- type: markdown
5+
attributes:
6+
value: |
7+
Please carefully read the contribution docs before creating a bug report
8+
👉 https://github.com/npmx-dev/npmx.dev/blob/main/CONTRIBUTING.md
9+
- type: textarea
10+
id: bug-description
11+
attributes:
12+
label: Describe the bug
13+
description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks!
14+
placeholder: Bug description
15+
validations:
16+
required: true
17+
- type: textarea
18+
id: additional
19+
attributes:
20+
label: Additional context
21+
description: If applicable, add any other context about the problem here
22+
- type: textarea
23+
id: logs
24+
attributes:
25+
label: Logs
26+
description: |
27+
Optional if you have reproduction steps. Please try not to insert an image but copy paste the log text.
28+
render: shell-script

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
blank_issues_enabled: true
2+
contact_links:
3+
- name: 📚 npmx documentation
4+
url: https://docs.npmx.dev/
5+
about: Check the documentation for usage of npmx
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: '🚀 Feature request'
2+
description: Suggest a feature that will improve npmx
3+
labels: ['pending triage']
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
Thank you for taking the time to fill out this feature request!
9+
10+
Please carefully read the contribution docs before suggesting a new feature
11+
👉 https://github.com/npmx-dev/npmx.dev/blob/main/CONTRIBUTING.md
12+
- type: textarea
13+
id: feature-description
14+
attributes:
15+
label: Describe the feature
16+
description: A clear and concise description of what you think would be a helpful addition to npmx, including the possible use cases and alternatives you have considered. If you have a working prototype or module that implements it, please include a link.
17+
placeholder: Feature description
18+
validations:
19+
required: true
20+
- type: checkboxes
21+
id: additional-info
22+
attributes:
23+
label: Additional information
24+
description: Additional information that helps us decide how to proceed.
25+
options:
26+
- label: Would you be willing to help implement this feature?
27+
- type: checkboxes
28+
id: required-info
29+
attributes:
30+
label: Final checks
31+
description: Before submitting, please make sure you do the following
32+
options:
33+
- label: Read the [contribution guide](https://github.com/npmx-dev/npmx.dev/blob/main/CONTRIBUTING.md).
34+
required: true
35+
- label: Check existing [issues](https://github.com/npmx-dev/npmx.dev/issues).
36+
required: true

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
### 🔗 Linked issue
2+
3+
<!-- Please ensure there is an open issue and mention its number. For example, "resolves #123" -->
4+
5+
### 🧭 Context
6+
7+
<!-- Brief background and why this change is needed -->
8+
9+
<!-- High-level summary of what changed -->
10+
11+
### 📚 Description
12+
13+
<!-- Describe your changes in detail. Why is this change required? What problem does it solve? -->
14+
15+
<!-- If you used AI tools to help with this contribution, please ensure the PR description and code reflect your own understanding.
16+
Write in your own voice rather than copying AI-generated text. -->
17+
18+
<!----------------------------------------------------------------------
19+
Before creating the pull request, please make sure you do the following:
20+
21+
- Check that there isn't already a PR that solves the problem the same way. If you find a duplicate, please help us reviewing it.
22+
- Ensure that PR title follows conventional commits (https://www.conventionalcommits.org)
23+
- Update the corresponding documentation if needed.
24+
- Include relevant tests that fail without this PR but pass with it.
25+
- Add any additional context, tradeoffs, follow-ups, or things reviewers should be aware of.
26+
27+
Thank you for contributing to npmx!
28+
----------------------------------------------------------------------->

app/components/Button/Base.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<script setup lang="ts">
2+
import type { IconClass } from '~/types'
3+
24
const props = withDefaults(
35
defineProps<{
46
disabled?: boolean
@@ -8,7 +10,7 @@ const props = withDefaults(
810
ariaKeyshortcuts?: string
911
block?: boolean
1012
11-
classicon?: string
13+
classicon?: IconClass
1214
}>(),
1315
{
1416
type: 'button',

app/components/Link/Base.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
22
import type { NuxtLinkProps } from '#app'
3+
import type { IconClass } from '~/types'
34
45
const props = withDefaults(
56
defineProps<
@@ -26,7 +27,7 @@ const props = withDefaults(
2627
*/
2728
rel?: never
2829
29-
classicon?: string
30+
classicon?: IconClass
3031
3132
to?: NuxtLinkProps['to']
3233

app/components/Package/Playgrounds.vue

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<script setup lang="ts">
22
import type { PlaygroundLink } from '#shared/types'
3-
import { decodeHtmlEntities } from '~/utils/formatters'
43
54
const props = defineProps<{
65
links: PlaygroundLink[]
@@ -130,7 +129,7 @@ function focusMenuItem(index: number) {
130129
:class="[getIcon(firstLink.provider), getColor(firstLink.provider), 'w-4 h-4 shrink-0']"
131130
aria-hidden="true"
132131
/>
133-
<span class="truncate text-fg-muted">{{ decodeHtmlEntities(firstLink.label) }}</span>
132+
<span class="truncate text-fg-muted">{{ firstLink.label }}</span>
134133
</a>
135134
</TooltipApp>
136135

@@ -186,7 +185,7 @@ function focusMenuItem(index: number) {
186185
:class="[getIcon(link.provider), getColor(link.provider), 'w-4 h-4 shrink-0']"
187186
aria-hidden="true"
188187
/>
189-
<span class="truncate">{{ decodeHtmlEntities(link.label) }}</span>
188+
<span class="truncate">{{ link.label }}</span>
190189
</a>
191190
</TooltipApp>
192191
</div>

app/components/Package/TrendsChart.vue

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { VueUiXyDatasetItem } from 'vue-data-ui'
33
import { VueUiXy } from 'vue-data-ui/vue-ui-xy'
44
import { useDebounceFn, useElementSize } from '@vueuse/core'
55
import { useCssVariables } from '~/composables/useColors'
6-
import { OKLCH_NEUTRAL_FALLBACK, transparentizeOklch } from '~/utils/colors'
6+
import { OKLCH_NEUTRAL_FALLBACK, transparentizeOklch, lightenOklch } from '~/utils/colors'
77
import { getFrameworkColor, isListedFramework } from '~/utils/frameworks'
88
import { drawNpmxLogoAndTaglineWatermark } from '~/composables/useChartWatermark'
99
import type { RepoRef } from '#shared/utils/git-providers'
@@ -201,59 +201,41 @@ function formatXyDataset(
201201
dataset: EvolutionData,
202202
seriesName: string,
203203
): { dataset: VueUiXyDatasetItem[] | null; dates: number[] } {
204+
const lightColor = isDarkMode.value ? lightenOklch(accent.value, 0.618) : undefined
205+
206+
// Subtle path gradient applied in dark mode only
207+
const temperatureColors = lightColor ? [lightColor, accent.value] : undefined
208+
209+
const datasetItem: VueUiXyDatasetItem = {
210+
name: seriesName,
211+
type: 'line',
212+
series: dataset.map(d => d.value),
213+
color: accent.value,
214+
temperatureColors,
215+
useArea: true,
216+
}
217+
204218
if (selectedGranularity === 'weekly' && isWeeklyDataset(dataset)) {
205219
return {
206-
dataset: [
207-
{
208-
name: seriesName,
209-
type: 'line',
210-
series: dataset.map(d => d.value),
211-
color: accent.value,
212-
useArea: true,
213-
},
214-
],
220+
dataset: [datasetItem],
215221
dates: dataset.map(d => d.timestampEnd),
216222
}
217223
}
218224
if (selectedGranularity === 'daily' && isDailyDataset(dataset)) {
219225
return {
220-
dataset: [
221-
{
222-
name: seriesName,
223-
type: 'line',
224-
series: dataset.map(d => d.value),
225-
color: accent.value,
226-
useArea: true,
227-
},
228-
],
226+
dataset: [datasetItem],
229227
dates: dataset.map(d => d.timestamp),
230228
}
231229
}
232230
if (selectedGranularity === 'monthly' && isMonthlyDataset(dataset)) {
233231
return {
234-
dataset: [
235-
{
236-
name: seriesName,
237-
type: 'line',
238-
series: dataset.map(d => d.value),
239-
color: accent.value,
240-
useArea: true,
241-
},
242-
],
232+
dataset: [datasetItem],
243233
dates: dataset.map(d => d.timestamp),
244234
}
245235
}
246236
if (selectedGranularity === 'yearly' && isYearlyDataset(dataset)) {
247237
return {
248-
dataset: [
249-
{
250-
name: seriesName,
251-
type: 'line',
252-
series: dataset.map(d => d.value),
253-
color: accent.value,
254-
useArea: true,
255-
},
256-
],
238+
dataset: [datasetItem],
257239
dates: dataset.map(d => d.timestamp),
258240
}
259241
}
@@ -1529,7 +1511,7 @@ const chartConfig = computed(() => {
15291511
backdropFilter: false,
15301512
backgroundColor: 'transparent',
15311513
customFormat: ({ datapoint }: { datapoint: Record<string, any> | any[] }) => {
1532-
if (!datapoint) return ''
1514+
if (!datapoint || pending.value) return ''
15331515
15341516
const items = Array.isArray(datapoint) ? datapoint : [datapoint[0]]
15351517
const hasMultipleItems = items.length > 1
@@ -1575,6 +1557,7 @@ const chartConfig = computed(() => {
15751557
zoom: {
15761558
maxWidth: isMobile.value ? 350 : 500,
15771559
highlightColor: colors.value.bgElevated,
1560+
useResetSlot: true,
15781561
minimap: {
15791562
show: true,
15801563
lineColor: '#FAFAFA',
@@ -1805,6 +1788,19 @@ watch(selectedMetric, value => {
18051788
</div>
18061789
</template>
18071790

1791+
<!-- Custom minimap reset button -->
1792+
<template #reset-action="{ reset: resetMinimap }">
1793+
<button
1794+
type="button"
1795+
aria-label="reset minimap"
1796+
class="absolute inset-is-1/2 -translate-x-1/2 -bottom-18 sm:inset-is-unset sm:translate-x-0 sm:bottom-auto sm:-inset-ie-20 sm:-top-3 flex items-center justify-center px-2.5 py-1.75 border border-transparent rounded-md text-fg-subtle hover:text-fg transition-colors hover:border-border focus-visible:outline-accent/70 sm:mb-0"
1797+
style="pointer-events: all !important"
1798+
@click="resetMinimap"
1799+
>
1800+
<span class="i-lucide:undo-2 w-5 h-5" aria-hidden="true" />
1801+
</button>
1802+
</template>
1803+
18081804
<template #menuIcon="{ isOpen }">
18091805
<span v-if="isOpen" class="i-lucide:x w-6 h-6" aria-hidden="true" />
18101806
<span v-else class="i-lucide:ellipsis-vertical w-6 h-6" aria-hidden="true" />

app/components/Package/VersionDistribution.vue

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type {
88
} from 'vue-data-ui'
99
import { useElementSize } from '@vueuse/core'
1010
import { useCssVariables } from '~/composables/useColors'
11-
import { OKLCH_NEUTRAL_FALLBACK, transparentizeOklch } from '~/utils/colors'
11+
import { OKLCH_NEUTRAL_FALLBACK, transparentizeOklch, lightenHex } from '~/utils/colors'
1212
import {
1313
drawSvgPrintLegend,
1414
drawNpmxLogoAndTaglineWatermark,
@@ -212,7 +212,7 @@ const chartConfig = computed(() => {
212212
backgroundColor: 'transparent',
213213
customFormat: (params: TooltipParams) => {
214214
const { datapoint, absoluteIndex, bars } = params
215-
if (!datapoint) return ''
215+
if (!datapoint || pending.value) return ''
216216
217217
// Use absoluteIndex to get the correct version from chartDataset
218218
const index = Number(absoluteIndex)
@@ -243,6 +243,7 @@ const chartConfig = computed(() => {
243243
zoom: {
244244
maxWidth: isMobile.value ? 350 : 500,
245245
highlightColor: colors.value.bgElevated,
246+
useResetSlot: true,
246247
minimap: {
247248
show: true,
248249
lineColor: '#FAFAFA',
@@ -495,11 +496,12 @@ const endDate = computed(() => {
495496
/>
496497
</template>
497498

498-
<!-- Subtle gradient applied for area charts -->
499-
<template #area-gradient="{ series: chartModalSeries, id: gradientId }">
500-
<linearGradient :id="gradientId" x1="0" x2="0" y1="0" y2="1">
501-
<stop offset="0%" :stop-color="chartModalSeries.color" stop-opacity="0.2" />
502-
<stop offset="100%" :stop-color="colors.bg" stop-opacity="0" />
499+
<!-- Custom bar gradient based on the series color -->
500+
<template #bar-gradient="{ series, positiveId }">
501+
<linearGradient :id="positiveId" x1="0" x2="0" y1="0" y2="1">
502+
<!-- vue-data-ui exposes hex-normalized colors -->
503+
<stop offset="0%" :stop-color="lightenHex(series.color, 0.618)" />
504+
<stop offset="100%" :stop-color="series.color" stop-opacity="0.618" />
503505
</linearGradient>
504506
</template>
505507

@@ -521,6 +523,19 @@ const endDate = computed(() => {
521523
</div>
522524
</template>
523525

526+
<!-- Custom minimap reset button -->
527+
<template #reset-action="{ reset: resetMinimap }">
528+
<button
529+
type="button"
530+
aria-label="reset minimap"
531+
class="absolute inset-is-1/2 -translate-x-1/2 -bottom-18 sm:inset-is-unset sm:translate-x-0 sm:bottom-auto sm:-inset-ie-20 sm:-top-3 flex items-center justify-center px-2.5 py-1.75 border border-transparent rounded-md text-fg-subtle hover:text-fg transition-colors hover:border-border focus-visible:outline-accent/70 sm:mb-0"
532+
style="pointer-events: all !important"
533+
@click="resetMinimap"
534+
>
535+
<span class="i-lucide:undo-2 w-5 h-5" aria-hidden="true" />
536+
</button>
537+
</template>
538+
524539
<!-- Contextual menu icon -->
525540
<template #menuIcon="{ isOpen }">
526541
<span v-if="isOpen" class="i-lucide:x w-6 h-6" aria-hidden="true" />

app/components/Package/WeeklyDownloadStats.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ const config = computed(() => {
231231
easing: 'ease-in-out',
232232
trail: {
233233
show: true,
234-
length: 20,
234+
length: 30,
235235
opacity: 0.75,
236236
},
237237
},

0 commit comments

Comments
 (0)