[READ-ONLY] a fast, modern browser for the npm registry
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add copy button to connector modal + respect pm preference (#76)

authored by

Mainasara Al-amin Tsowa and committed by
GitHub
b9edee14 983f5f67

+61 -21
+39 -2
app/components/ConnectorModal.vue
··· 6 6 7 7 const tokenInput = ref('') 8 8 const portInput = ref('31415') 9 + const copied = ref(false) 9 10 10 11 async function handleConnect() { 11 12 const port = Number.parseInt(portInput.value, 10) || 31415 ··· 19 20 function handleDisconnect() { 20 21 disconnect() 21 22 } 23 + 24 + function copyCommand() { 25 + let command = executeNpmxConnectorCommand.value 26 + if (portInput.value !== '31415') { 27 + command += ` --port ${portInput.value}` 28 + } 29 + navigator.clipboard.writeText(command) 30 + copied.value = true 31 + setTimeout(() => { 32 + copied.value = false 33 + }, 2000) 34 + } 35 + 36 + const selectedPM = useSelectedPackageManager() 37 + 38 + const executeNpmxConnectorCommand = computed(() => { 39 + return getExecuteCommand({ 40 + packageName: 'npmx-connector', 41 + packageManager: selectedPM.value, 42 + }) 43 + }) 22 44 23 45 // Reset form when modal opens 24 46 watch(open, isOpen => { ··· 103 125 Run the connector on your machine to enable admin features: 104 126 </p> 105 127 106 - <div class="p-3 bg-[#0d0d0d] border border-border rounded-lg font-mono text-sm"> 128 + <div 129 + class="flex items-center p-3 bg-[#0d0d0d] border border-border rounded-lg font-mono text-sm" 130 + > 107 131 <span class="text-fg-subtle">$</span> 108 - <span class="text-fg ml-2">npx&nbsp;npmx-connector</span> 132 + <span class="text-fg ml-2">{{ executeNpmxConnectorCommand }}</span> 133 + <button 134 + type="button" 135 + :aria-label="copied ? 'Copied' : 'Copy command'" 136 + class="ml-auto text-fg-subtle hover:text-fg transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 rounded" 137 + @click="copyCommand" 138 + > 139 + <span v-if="!copied" class="i-carbon-copy block w-5 h-5" aria-hidden="true" /> 140 + <span 141 + v-else 142 + class="i-carbon-checkmark block w-5 h-5 text-green-500" 143 + aria-hidden="true" 144 + /> 145 + </button> 109 146 </div> 110 147 111 148 <p class="text-sm text-fg-muted">Then paste the token shown in your terminal:</p>
+5
app/composables/useSelectedPackageManager.ts
··· 1 + import { useLocalStorage } from '@vueuse/core' 2 + 3 + export function useSelectedPackageManager() { 4 + return useLocalStorage<PackageManagerId>('npmx-pm', 'npm') 5 + }
+1 -13
app/pages/[...package].vue
··· 190 190 return !!dist.attestations 191 191 } 192 192 193 - // Persist package manager preference in localStorage 194 - const selectedPM = ref<PackageManagerId>('npm') 195 - 196 - onMounted(() => { 197 - const stored = localStorage.getItem('npmx-pm') 198 - if (stored && packageManagers.some(pm => pm.id === stored)) { 199 - selectedPM.value = stored as PackageManagerId 200 - } 201 - }) 202 - 203 - watch(selectedPM, value => { 204 - localStorage.setItem('npmx-pm', value) 205 - }) 193 + const selectedPM = useSelectedPackageManager() 206 194 207 195 const installCommandParts = computed(() => { 208 196 if (!pkg.value) return []
+16 -6
app/utils/install-command.ts
··· 1 1 import type { JsrPackageInfo } from '#shared/types/jsr' 2 2 3 3 export const packageManagers = [ 4 - { id: 'npm', label: 'npm', action: 'install' }, 5 - { id: 'pnpm', label: 'pnpm', action: 'add' }, 6 - { id: 'yarn', label: 'yarn', action: 'add' }, 7 - { id: 'bun', label: 'bun', action: 'add' }, 8 - { id: 'deno', label: 'deno', action: 'add' }, 9 - { id: 'vlt', label: 'vlt', action: 'install' }, 4 + { id: 'npm', label: 'npm', action: 'install', execute: 'npx' }, 5 + { id: 'pnpm', label: 'pnpm', action: 'add', execute: 'pnpm dlx' }, 6 + { id: 'yarn', label: 'yarn', action: 'add', execute: 'yarn dlx' }, 7 + { id: 'bun', label: 'bun', action: 'add', execute: 'bunx' }, 8 + { id: 'deno', label: 'deno', action: 'add', execute: 'deno run' }, 9 + { id: 'vlt', label: 'vlt', action: 'install', execute: 'vlt x' }, 10 10 ] as const 11 11 12 12 export type PackageManagerId = (typeof packageManagers)[number]['id'] ··· 59 59 60 60 return [pm.label, pm.action, `${spec}${version}`] 61 61 } 62 + 63 + export function getExecuteCommand(options: InstallCommandOptions): string { 64 + return getExecuteCommandParts(options).join(' ') 65 + } 66 + 67 + export function getExecuteCommandParts(options: InstallCommandOptions): string[] { 68 + const pm = packageManagers.find(p => p.id === options.packageManager) 69 + if (!pm) return [] 70 + return [pm.execute, getPackageSpecifier(options)] 71 + }