@alliance-droid/status-feedback-system 2.3.0 → 2.3.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.3.2
4
+
5
+ ### Changed
6
+
7
+ - `<DevFeedback>` *Report Bug* form: when the consumer app's render-token endpoint is unreachable or returns an error, the form now shows paste-screenshot instructions ("Paste a screenshot to attach one — capture with ⌘⇧4 / Win+Shift+S, then ⌘V / Ctrl+V into the description") instead of the dead-end "Screenshot setup failed / Retry" panel. The previous panel offered a Retry button that could never succeed when the endpoint was simply not configured.
8
+
9
+ ## 2.3.1
10
+
11
+ ### Fixed
12
+
13
+ - `<FeedbackSubmitForm>` paste-to-attach was missing from 2.3.0 (commit didn't land on main before merge). Now included.
14
+
3
15
  ## 2.3.0
4
16
 
5
17
  ### Added
@@ -89,6 +89,10 @@
89
89
  // --- Environment gate ---
90
90
  let isEnabled = $state(false);
91
91
  let hasUserEmail = $derived(!!userEmail);
92
+ const isMac = $derived(
93
+ typeof navigator !== 'undefined' &&
94
+ /Mac|iPhone|iPad|iPod/i.test(navigator.platform || navigator.userAgent || '')
95
+ );
92
96
 
93
97
  // --- State ---
94
98
  let menuOpen = $state(false);
@@ -508,16 +512,14 @@
508
512
  {:else if renderTokenFailed && !pastedScreenshot}
509
513
  <div class="rounded-md border border-border bg-surface p-3">
510
514
  <div class="flex items-center gap-2 text-sm text-foreground-secondary mb-1">
511
- <i class="fa-solid fa-image-slash" aria-hidden="true"></i>
512
- <span>Screenshot setup failed</span>
515
+ <i class="fa-solid fa-paste" aria-hidden="true"></i>
516
+ <span>Paste a screenshot to attach one</span>
513
517
  </div>
514
- <p class="text-xs text-foreground-tertiary mb-2">Your feedback will be submitted without a screenshot.</p>
515
- <button
516
- class="text-xs text-primary hover:underline bg-transparent border-none cursor-pointer p-0"
517
- onclick={fetchRenderToken}
518
- >
519
- Retry
520
- </button>
518
+ <p class="text-xs text-foreground-tertiary">
519
+ Capture a screenshot (<kbd class="px-1 py-0.5 rounded bg-surface-secondary border border-border text-[10px] font-mono">{isMac ? '⌘⇧4' : 'Win+Shift+S'}</kbd>),
520
+ then paste it into the description above with
521
+ <kbd class="px-1 py-0.5 rounded bg-surface-secondary border border-border text-[10px] font-mono">{isMac ? '⌘V' : 'Ctrl+V'}</kbd>.
522
+ </p>
521
523
  </div>
522
524
  {:else if renderContext && !pastedScreenshot}
523
525
  <div class="rounded-md border border-border bg-surface-secondary p-2 flex items-center gap-2 text-sm text-foreground-secondary">
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { Card, Button, Input, Textarea, Select } from '@alliance-droid/svelte-component-library';
3
3
  import type { FeedbackBoardState } from './state.svelte.js';
4
+ import PasteImageInput from '../shared/PasteImageInput.svelte';
4
5
 
5
6
  interface Props {
6
7
  board: FeedbackBoardState;
@@ -16,6 +17,16 @@
16
17
  let submitting = $state(false);
17
18
  let success = $state(false);
18
19
  let error = $state('');
20
+ let pastedImage = $state<string | null>(null);
21
+ let pastedFilename = $state('');
22
+ let textareaWrapperEl: HTMLDivElement | undefined = $state();
23
+ let textareaEl: HTMLTextAreaElement | undefined = $state();
24
+
25
+ $effect(() => {
26
+ if (textareaWrapperEl) {
27
+ textareaEl = textareaWrapperEl.querySelector('textarea') ?? undefined;
28
+ }
29
+ });
19
30
 
20
31
  let isAuthenticated = $derived(!!board.userEmail);
21
32
 
@@ -32,11 +43,14 @@
32
43
  title: title.trim() || undefined,
33
44
  message: message.trim(),
34
45
  category: category || undefined,
46
+ pastedImage,
35
47
  });
36
48
  success = true;
37
49
  title = '';
38
50
  message = '';
39
51
  category = '';
52
+ pastedImage = null;
53
+ pastedFilename = '';
40
54
  setTimeout(() => { success = false; }, 2000);
41
55
  } catch (err) {
42
56
  error = err instanceof Error ? err.message : 'Failed to submit';
@@ -66,11 +80,18 @@
66
80
  bind:value={title}
67
81
  placeholder="Title (optional)"
68
82
  />
69
- <Textarea
70
- value={message}
71
- oninput={(e) => (message = (e.currentTarget as HTMLTextAreaElement).value)}
72
- placeholder="Describe your feedback..."
73
- rows={3}
83
+ <div bind:this={textareaWrapperEl}>
84
+ <Textarea
85
+ value={message}
86
+ oninput={(e) => (message = (e.currentTarget as HTMLTextAreaElement).value)}
87
+ placeholder="Describe your feedback (paste an image to attach it)\u2026"
88
+ rows={3}
89
+ />
90
+ </div>
91
+ <PasteImageInput
92
+ {textareaEl}
93
+ bind:image={pastedImage}
94
+ bind:filename={pastedFilename}
74
95
  />
75
96
  {#if error}
76
97
  <p class="text-sm text-red-400">
@@ -46,6 +46,7 @@ export interface FeedbackBoardState {
46
46
  title?: string;
47
47
  message: string;
48
48
  category?: string;
49
+ pastedImage?: string | null;
49
50
  }): Promise<void>;
50
51
  submitResponse(itemId: string, message: string, pastedImage?: string | null): Promise<void>;
51
52
  getCategoryIcon(name: string): string;
@@ -128,10 +128,16 @@ export function createFeedbackBoard(options) {
128
128
  async function submitFeedback(data) {
129
129
  if (!resolvedEmail)
130
130
  throw new Error('Authentication required to submit feedback');
131
+ const metadata = {};
132
+ if (data.pastedImage)
133
+ metadata.pastedScreenshot = data.pastedImage;
131
134
  await client.submitFeedback({
132
- ...data,
135
+ title: data.title,
136
+ message: data.message,
137
+ category: data.category,
133
138
  email: resolvedEmail,
134
139
  pageUrl: typeof window !== 'undefined' ? window.location.href : undefined,
140
+ metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
135
141
  });
136
142
  await load();
137
143
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alliance-droid/status-feedback-system",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "type": "module",
5
5
  "description": "Drop-in system status pages and user feedback forms for SvelteKit apps",
6
6
  "svelte": "./dist/index.js",