|
1 | 1 | <script lang="ts"> |
2 | | - import { onDestroy, getContext } from 'svelte'; |
| 2 | + import { onDestroy, getContext, createEventDispatcher } from 'svelte'; |
3 | 3 | import type { ListeningPort } from '$lib/apis/terminal'; |
4 | 4 | import { getListeningPorts, getPortProxyUrl } from '$lib/apis/terminal'; |
5 | 5 | import Tooltip from '$lib/components/common/Tooltip.svelte'; |
6 | 6 |
|
7 | 7 | const i18n = getContext('i18n'); |
| 8 | + const dispatch = createEventDispatcher<{ previewPort: number }>(); |
8 | 9 |
|
9 | 10 | export let baseUrl: string; |
10 | 11 | export let apiKey: string; |
|
33 | 34 | } |
34 | 35 | }; |
35 | 36 |
|
36 | | - const openPort = (port: number) => { |
| 37 | + const previewPort = (port: number) => { |
| 38 | + dispatch('previewPort', port); |
| 39 | + }; |
| 40 | +
|
| 41 | + const openPortExternal = (port: number) => { |
37 | 42 | const url = getPortProxyUrl(baseUrl, port); |
38 | 43 | window.open(url, '_blank', 'noopener,noreferrer'); |
39 | 44 | }; |
|
107 | 112 | {#each ports as port} |
108 | 113 | <button |
109 | 114 | class="flex items-center w-full gap-2 px-1.5 py-1 text-xs rounded hover:bg-gray-100 dark:hover:bg-gray-800 transition group" |
110 | | - on:click={() => openPort(port.port)} |
| 115 | + on:click={() => previewPort(port.port)} |
111 | 116 | > |
112 | 117 | <span class="font-mono text-blue-500 dark:text-blue-400 shrink-0"> |
113 | 118 | :{port.port} |
114 | 119 | </span> |
115 | 120 | <span class="text-gray-500 dark:text-gray-400 truncate flex-1 text-left"> |
116 | 121 | {port.process ?? ''} |
117 | 122 | </span> |
118 | | - <span |
119 | | - class="text-gray-400 dark:text-gray-500 opacity-0 group-hover:opacity-100 transition shrink-0" |
120 | | - > |
121 | | - <svg |
122 | | - xmlns="http://www.w3.org/2000/svg" |
123 | | - viewBox="0 0 20 20" |
124 | | - fill="currentColor" |
125 | | - class="size-3" |
| 123 | + <Tooltip content={$i18n.t('Open in new tab')}> |
| 124 | + <!-- svelte-ignore a11y-click-events-have-key-events --> |
| 125 | + <span |
| 126 | + role="button" |
| 127 | + tabindex="-1" |
| 128 | + class="text-gray-400 dark:text-gray-500 opacity-0 group-hover:opacity-100 transition shrink-0 p-0.5 rounded hover:bg-gray-200 dark:hover:bg-gray-700" |
| 129 | + on:click|stopPropagation={() => openPortExternal(port.port)} |
126 | 130 | > |
127 | | - <path |
128 | | - fill-rule="evenodd" |
129 | | - d="M4.25 5.5a.75.75 0 0 0-.75.75v8.5c0 .414.336.75.75.75h8.5a.75.75 0 0 0 .75-.75v-4a.75.75 0 0 1 1.5 0v4A2.25 2.25 0 0 1 12.75 17h-8.5A2.25 2.25 0 0 1 2 14.75v-8.5A2.25 2.25 0 0 1 4.25 4h5a.75.75 0 0 1 0 1.5h-5Zm7.5-3.5a.75.75 0 0 0 0 1.5h2.69l-4.72 4.72a.75.75 0 0 0 1.06 1.06l4.72-4.72v2.69a.75.75 0 0 0 1.5 0v-5.25a.75.75 0 0 0-.75-.75h-5.25Z" |
130 | | - clip-rule="evenodd" |
131 | | - /> |
132 | | - </svg> |
133 | | - </span> |
| 131 | + <svg |
| 132 | + xmlns="http://www.w3.org/2000/svg" |
| 133 | + viewBox="0 0 20 20" |
| 134 | + fill="currentColor" |
| 135 | + class="size-3" |
| 136 | + > |
| 137 | + <path |
| 138 | + fill-rule="evenodd" |
| 139 | + d="M4.25 5.5a.75.75 0 0 0-.75.75v8.5c0 .414.336.75.75.75h8.5a.75.75 0 0 0 .75-.75v-4a.75.75 0 0 1 1.5 0v4A2.25 2.25 0 0 1 12.75 17h-8.5A2.25 2.25 0 0 1 2 14.75v-8.5A2.25 2.25 0 0 1 4.25 4h5a.75.75 0 0 1 0 1.5h-5Zm7.5-3.5a.75.75 0 0 0 0 1.5h2.69l-4.72 4.72a.75.75 0 0 0 1.06 1.06l4.72-4.72v2.69a.75.75 0 0 0 1.5 0v-5.25a.75.75 0 0 0-.75-.75h-5.25Z" |
| 140 | + clip-rule="evenodd" |
| 141 | + /> |
| 142 | + </svg> |
| 143 | + </span> |
| 144 | + </Tooltip> |
134 | 145 | </button> |
135 | 146 | {/each} |
136 | 147 | {/if} |
|
0 commit comments