@walkinissue/angy 0.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,109 @@
1
+ <script lang="ts">
2
+ let {
3
+ pending = false,
4
+ onCancel,
5
+ onDiscard,
6
+ onSubmit
7
+ }: {
8
+ pending?: boolean;
9
+ onCancel: () => void;
10
+ onDiscard: () => void;
11
+ onSubmit: () => void;
12
+ } = $props();
13
+ </script>
14
+
15
+ <div class="dialog-backdrop" role="presentation">
16
+ <div
17
+ class="dialog"
18
+ role="dialog"
19
+ aria-modal="true"
20
+ aria-labelledby="pending-changes-title"
21
+ aria-describedby="pending-changes-description"
22
+ >
23
+ <h2 id="pending-changes-title">Staged changes</h2>
24
+ <p id="pending-changes-description">
25
+ You have staged translations waiting to be committed. Do you want to submit them or discard
26
+ them before closing?
27
+ </p>
28
+
29
+ <div class="actions">
30
+ <button type="button" class="secondary-btn" onclick={onCancel}>Cancel</button>
31
+ <button type="button" class="secondary-btn" disabled={pending} onclick={onDiscard}>
32
+ Discard
33
+ </button>
34
+ <button type="button" class="primary-btn" disabled={pending} onclick={onSubmit}>
35
+ {pending ? "Submitting..." : "Submit"}
36
+ </button>
37
+ </div>
38
+ </div>
39
+ </div>
40
+
41
+ <style>
42
+ .dialog-backdrop {
43
+ position: fixed;
44
+ inset: 0;
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ padding: 1rem;
49
+ background: rgba(0, 0, 0, 0.55);
50
+ z-index: 500100;
51
+ }
52
+
53
+ .dialog {
54
+ width: min(28rem, calc(100vw - 2rem));
55
+ padding: 1rem;
56
+ border-radius: 1rem;
57
+ border: 1px solid rgba(255, 255, 255, 0.12);
58
+ background: linear-gradient(180deg, rgba(25, 27, 34, 0.98) 0%, rgba(17, 19, 25, 0.99) 100%);
59
+ box-shadow:
60
+ 0 24px 60px rgba(0, 0, 0, 0.45),
61
+ 0 8px 20px rgba(0, 0, 0, 0.26);
62
+ color: rgba(248, 250, 252, 0.96);
63
+ }
64
+
65
+ h2 {
66
+ margin: 0 0 0.5rem;
67
+ font-size: 1rem;
68
+ }
69
+
70
+ p {
71
+ margin: 0;
72
+ color: rgba(255, 255, 255, 0.74);
73
+ line-height: 1.45;
74
+ }
75
+
76
+ .actions {
77
+ display: flex;
78
+ justify-content: flex-end;
79
+ gap: 0.6rem;
80
+ margin-top: 1rem;
81
+ flex-wrap: wrap;
82
+ }
83
+
84
+ .primary-btn,
85
+ .secondary-btn {
86
+ min-height: 2.5rem;
87
+ padding: 0.7rem 1rem;
88
+ border-radius: 0.8rem;
89
+ font: inherit;
90
+ cursor: pointer;
91
+ }
92
+
93
+ .primary-btn {
94
+ border: 1px solid rgba(102, 255, 178, 0.35);
95
+ background: rgba(70, 255, 170, 0.14);
96
+ color: rgba(236, 255, 243, 0.98);
97
+ }
98
+
99
+ .secondary-btn {
100
+ border: 1px solid rgba(255, 255, 255, 0.12);
101
+ background: rgba(255, 255, 255, 0.05);
102
+ color: rgba(248, 250, 252, 0.96);
103
+ }
104
+
105
+ button:disabled {
106
+ opacity: 0.5;
107
+ cursor: not-allowed;
108
+ }
109
+ </style>
@@ -0,0 +1,309 @@
1
+ <script lang="ts">
2
+ import VibeTooltip from "./VibeTooltip.svelte";
3
+ import {
4
+ getTranslationStatus,
5
+ TRANSLATION_STATUS_TOOLTIP,
6
+ translationKey,
7
+ type TranslationAlternative
8
+ } from "./toggleQA.shared";
9
+
10
+ let {
11
+ alt,
12
+ selected = false,
13
+ focused = false,
14
+ staged = false,
15
+ onFocusChange,
16
+ onKeydown,
17
+ onSelect
18
+ }: {
19
+ alt: TranslationAlternative;
20
+ selected?: boolean;
21
+ focused?: boolean;
22
+ staged?: boolean;
23
+ onFocusChange: (key: string | null) => void;
24
+ onKeydown: (event: KeyboardEvent, msgid: string, msgctxt: string | null) => void;
25
+ onSelect: (event: Event, msgid: string, msgctxt: string | null) => void;
26
+ } = $props();
27
+
28
+ function getItemKey() {
29
+ return translationKey(alt.msgid, alt.msgctxt);
30
+ }
31
+
32
+ async function copyReferenceCommand(event: MouseEvent, ref: string) {
33
+ event.preventDefault();
34
+ event.stopPropagation();
35
+
36
+ const command = `code ${ref}`;
37
+ await navigator.clipboard.writeText(command);
38
+ }
39
+ </script>
40
+
41
+ <li
42
+ data-alt-key={getItemKey()}
43
+ class:selected
44
+ class:focused
45
+ class:staged
46
+ class="alt-item"
47
+ tabindex="0"
48
+ onfocus={() => onFocusChange(getItemKey())}
49
+ onblur={() => onFocusChange(null)}
50
+ onkeydown={(event) => onKeydown(event, alt.msgid, alt.msgctxt)}
51
+ >
52
+ <div class="alt-main">
53
+ <div class="alt-row-bet">
54
+ <div class="alt-copy">
55
+ <div class="alt-header">
56
+ <span class="context-label">Key</span>
57
+ <code class="alt-id">{alt.msgid}</code>
58
+ </div>
59
+ {#if alt.hasTranslation}
60
+ <div class="alt-row">
61
+ <span class="context-label">Text</span>
62
+ <code class="alt-translation">{alt.msgstr.join("\n")}</code>
63
+ </div>
64
+ {/if}
65
+ {#each alt.references.slice(0, 3) as ref, index (`${ref}-${index}`)}
66
+ <div class="alt-row">
67
+ <button
68
+ type="button"
69
+ class="ref-btn"
70
+ aria-label={`Copy VS Code command for ${ref}`}
71
+ title="Copy VS Code command"
72
+ onclick={(event) => void copyReferenceCommand(event, ref)}
73
+ >
74
+ #:
75
+ </button>
76
+ <span class="alt-context">{ref}</span>
77
+ </div>
78
+ {/each}
79
+ </div>
80
+ <div class="alt-keycont">
81
+ <button
82
+ type="button"
83
+ class="alt-select-btn"
84
+ class:selected
85
+ aria-label="Use this key"
86
+ title="Use this key"
87
+ onclick={(event) => onSelect(event, alt.msgid, alt.msgctxt)}
88
+ >
89
+ &#8658;
90
+ </button>
91
+ <VibeTooltip delay={100} disabled={false} text={TRANSLATION_STATUS_TOOLTIP} position="top">
92
+ <div class="alt-main">
93
+ <span class="alt-status">{getTranslationStatus(alt)}</span>
94
+ <span class="alt-score">({alt.score.toFixed(3)})</span>
95
+ </div>
96
+ </VibeTooltip>
97
+ </div>
98
+ </div>
99
+ <div class="alt-meta">
100
+ {#if alt.msgctxt}
101
+ <code class="alt-context">{alt.msgctxt}</code>
102
+ {/if}
103
+ </div>
104
+ </div>
105
+ </li>
106
+
107
+ <style>
108
+ .alt-item {
109
+ display: block;
110
+ padding: 0.7rem 0.75rem;
111
+ border-radius: 0.8rem;
112
+ border: 1px solid rgba(255, 255, 255, 0.08);
113
+ background: rgba(255, 255, 255, 0.035);
114
+ outline: none;
115
+ transition:
116
+ background 0.16s ease,
117
+ border-color 0.16s ease,
118
+ box-shadow 0.16s ease,
119
+ transform 0.16s ease;
120
+ }
121
+
122
+ .alt-item:hover {
123
+ background: rgba(255, 255, 255, 0.05);
124
+ border-color: rgba(255, 255, 255, 0.12);
125
+ }
126
+
127
+ .alt-item:focus,
128
+ .alt-item.focused {
129
+ border-color: rgba(110, 168, 255, 0.5);
130
+ box-shadow: 0 0 0 4px rgba(110, 168, 255, 0.1);
131
+ background: rgba(255, 255, 255, 0.06);
132
+ }
133
+
134
+ .alt-item.selected {
135
+ border-color: rgba(102, 255, 178, 0.42);
136
+ box-shadow: 0 0 0 4px rgba(102, 255, 178, 0.08);
137
+ background: rgba(70, 255, 170, 0.05);
138
+ }
139
+
140
+ .alt-item.staged {
141
+ border-color: rgba(120, 255, 170, 0.45);
142
+ background: rgba(70, 255, 170, 0.08);
143
+ box-shadow: 0 0 0 4px rgba(70, 255, 170, 0.08);
144
+ }
145
+
146
+ .alt-main {
147
+ display: flex;
148
+ flex-direction: column;
149
+ gap: 0.45rem;
150
+ }
151
+
152
+ .alt-copy {
153
+ display: flex;
154
+ flex-direction: column;
155
+ gap: 0.45rem;
156
+ min-width: 0;
157
+ flex: 1 1 auto;
158
+ }
159
+
160
+ .alt-keycont {
161
+ display: flex;
162
+ flex-direction: column;
163
+ justify-content: flex-start;
164
+ align-items: flex-end;
165
+ gap: 0.45rem;
166
+ flex: 0 0 auto;
167
+ }
168
+
169
+ .alt-header {
170
+ display: grid;
171
+ grid-template-columns: auto 1fr auto auto;
172
+ align-items: start;
173
+ gap: 0.55rem;
174
+ }
175
+
176
+ .context-label {
177
+ font-size: 0.72rem;
178
+ font-weight: 700;
179
+ text-transform: uppercase;
180
+ letter-spacing: 0.05em;
181
+ color: rgba(255, 255, 255, 0.58);
182
+ }
183
+
184
+ .alt-id {
185
+ white-space: pre-wrap;
186
+ word-break: break-word;
187
+ }
188
+
189
+ .alt-translation {
190
+ white-space: pre-wrap;
191
+ word-break: break-word;
192
+ color: rgba(232, 243, 255, 0.94);
193
+ }
194
+
195
+ .alt-meta {
196
+ display: flex;
197
+ flex-wrap: wrap;
198
+ align-items: center;
199
+ gap: 0.5rem;
200
+ }
201
+
202
+ .alt-score {
203
+ font-size: 0.72rem;
204
+ color: rgba(255, 255, 255, 0.55);
205
+ }
206
+
207
+ .alt-context {
208
+ font-size: 0.7rem;
209
+ color: rgba(195, 225, 255, 0.82);
210
+ }
211
+
212
+ .alt-row {
213
+ display: flex;
214
+ flex-direction: row;
215
+ align-items: flex-start;
216
+ gap: 0.3rem;
217
+ padding-top: 0.15rem;
218
+ }
219
+ .alt-row-bet {
220
+ display: flex;
221
+ flex-direction: row;
222
+ justify-content: space-between;
223
+ gap: 0.75rem;
224
+ padding-top: 0.15rem;
225
+ }
226
+
227
+ .alt-status {
228
+ display: inline-flex;
229
+ align-items: center;
230
+ justify-content: center;
231
+ min-width: 1.6rem;
232
+ height: 1.6rem;
233
+ font-size: 0.95rem;
234
+ border-radius: 999px;
235
+ background: rgba(255, 255, 255, 0.05);
236
+ }
237
+
238
+ .alt-select-btn {
239
+ display: inline-flex;
240
+ align-items: center;
241
+ justify-content: center;
242
+ width: 2rem;
243
+ height: 2rem;
244
+ border: 1px solid rgba(255, 255, 255, 0.1);
245
+ border-radius: 999px;
246
+ background: rgba(255, 255, 255, 0.04);
247
+ color: rgba(255, 255, 255, 0.9);
248
+ cursor: pointer;
249
+ transition:
250
+ background 0.16s ease,
251
+ border-color 0.16s ease,
252
+ transform 0.16s ease,
253
+ box-shadow 0.16s ease;
254
+ }
255
+
256
+ .alt-select-btn:hover {
257
+ background: rgba(255, 255, 255, 0.09);
258
+ border-color: rgba(255, 255, 255, 0.18);
259
+ transform: translateX(-1px);
260
+ }
261
+
262
+ .alt-select-btn:focus-visible {
263
+ outline: none;
264
+ border-color: rgba(110, 168, 255, 0.55);
265
+ box-shadow: 0 0 0 4px rgba(110, 168, 255, 0.12);
266
+ }
267
+
268
+ .alt-select-btn.selected {
269
+ background: rgba(70, 255, 170, 0.12);
270
+ border-color: rgba(102, 255, 178, 0.42);
271
+ color: rgba(220, 255, 235, 0.98);
272
+ }
273
+
274
+ .ref-btn {
275
+ padding: 0.05rem 0.28rem;
276
+ border: 1px solid rgba(255, 255, 255, 0.14);
277
+ border-radius: 0.35rem;
278
+ background: rgba(255, 255, 255, 0.06);
279
+ color: rgba(255, 255, 255, 0.72);
280
+ font: inherit;
281
+ font-size: 0.62rem;
282
+ line-height: 1.2;
283
+ cursor: pointer;
284
+ flex: 0 0 auto;
285
+ }
286
+
287
+ .ref-btn:hover {
288
+ background: rgba(255, 255, 255, 0.1);
289
+ color: rgba(255, 255, 255, 0.92);
290
+ }
291
+
292
+ .ref-btn:focus-visible {
293
+ outline: none;
294
+ border-color: rgba(110, 168, 255, 0.55);
295
+ box-shadow: 0 0 0 3px rgba(110, 168, 255, 0.12);
296
+ }
297
+
298
+ @media (max-width: 640px) {
299
+ .alt-row-bet {
300
+ flex-direction: column;
301
+ }
302
+
303
+ .alt-keycont {
304
+ flex-direction: row;
305
+ align-items: center;
306
+ justify-content: space-between;
307
+ }
308
+ }
309
+ </style>