@alliance-droid/status-feedback-system 1.3.0 → 1.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.
Files changed (32) hide show
  1. package/CHANGELOG.md +25 -45
  2. package/LICENSE +11 -0
  3. package/README.md +7 -3
  4. package/dist/components/DevFeedback.svelte +162 -322
  5. package/dist/components/FeedbackBoard.svelte +32 -368
  6. package/dist/components/FeedbackBoard.svelte.d.ts +2 -5
  7. package/dist/components/FeedbackForm.svelte +14 -3
  8. package/dist/components/StatusBanner.svelte +48 -14
  9. package/dist/components/StatusBanner.svelte.d.ts +2 -0
  10. package/dist/components/StatusPage.svelte +43 -10
  11. package/dist/components/StatusPage.svelte.d.ts +2 -0
  12. package/dist/components/board/FeedbackDetail.svelte +7 -7
  13. package/dist/components/board/FeedbackItem.svelte +26 -12
  14. package/dist/components/board/FeedbackList.svelte +21 -1
  15. package/dist/components/board/FeedbackSidebar.svelte +3 -3
  16. package/dist/components/board/state.svelte.d.ts +6 -0
  17. package/dist/components/board/state.svelte.js +42 -2
  18. package/dist/components/dev/DevContextMenu.svelte +99 -0
  19. package/dist/components/dev/DevContextMenu.svelte.d.ts +11 -0
  20. package/dist/components/dev/DevOnboardingToast.svelte +73 -0
  21. package/dist/components/dev/DevOnboardingToast.svelte.d.ts +6 -0
  22. package/dist/components/dev/environment.d.ts +24 -0
  23. package/dist/components/dev/environment.js +93 -0
  24. package/dist/components/dev/screenshot.d.ts +6 -0
  25. package/dist/components/dev/screenshot.js +25 -0
  26. package/dist/components/shared/IncidentTimeline.svelte +3 -3
  27. package/dist/components/shared/StatusIndicator.svelte +2 -2
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +2 -0
  30. package/dist/utils.d.ts +9 -0
  31. package/dist/utils.js +18 -0
  32. package/package.json +11 -6
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Environment detection utilities for DevFeedback.
3
+ */
4
+ /**
5
+ * Read an environment variable from common SvelteKit/Vite injection patterns.
6
+ */
7
+ export function getEnvVar(key) {
8
+ try {
9
+ const env = globalThis.__sveltekit_env;
10
+ if (env?.[key])
11
+ return env[key];
12
+ }
13
+ catch { /* ignore */ }
14
+ try {
15
+ const win = window;
16
+ const env = win.__ENV;
17
+ if (env?.[key])
18
+ return env[key];
19
+ }
20
+ catch { /* ignore */ }
21
+ return undefined;
22
+ }
23
+ /**
24
+ * Detect whether DevFeedback should be enabled.
25
+ * Priority: explicit prop > env var > Vercel env > localhost.
26
+ */
27
+ export function detectEnvironment(explicitEnabled) {
28
+ if (explicitEnabled !== undefined)
29
+ return explicitEnabled;
30
+ if (typeof window === 'undefined')
31
+ return false;
32
+ const feedbackEnabled = getEnvVar('PUBLIC_FEEDBACK_ENABLED');
33
+ if (feedbackEnabled === 'true')
34
+ return true;
35
+ if (feedbackEnabled === 'false')
36
+ return false;
37
+ const vercelEnv = getEnvVar('VERCEL_ENV');
38
+ if (vercelEnv === 'production')
39
+ return false;
40
+ if (vercelEnv)
41
+ return true;
42
+ const host = window.location.hostname;
43
+ return host === 'localhost' || host === '127.0.0.1' || host.endsWith('.local');
44
+ }
45
+ /**
46
+ * Get a human-readable environment name.
47
+ */
48
+ export function getEnvironmentName() {
49
+ const vercelEnv = getEnvVar('VERCEL_ENV');
50
+ if (vercelEnv)
51
+ return vercelEnv;
52
+ if (typeof window !== 'undefined' && window.location.hostname === 'localhost')
53
+ return 'development';
54
+ return 'unknown';
55
+ }
56
+ /**
57
+ * Get a CSS selector path for a DOM element (for bug context).
58
+ */
59
+ export function getElementSelector(el) {
60
+ if (!el)
61
+ return '';
62
+ const parts = [];
63
+ let current = el;
64
+ while (current && current !== document.body) {
65
+ if (!current.tagName) {
66
+ current = current.parentElement;
67
+ continue;
68
+ }
69
+ let selector = current.tagName.toLowerCase();
70
+ if (current.id) {
71
+ selector += `#${current.id}`;
72
+ parts.unshift(selector);
73
+ break;
74
+ }
75
+ if (current.className && typeof current.className === 'string') {
76
+ const classes = current.className.trim().split(/\s+/).slice(0, 2).join('.');
77
+ if (classes)
78
+ selector += `.${classes}`;
79
+ }
80
+ parts.unshift(selector);
81
+ current = current.parentElement;
82
+ }
83
+ return parts.join(' > ');
84
+ }
85
+ /**
86
+ * Get a truncated outer HTML snippet for a DOM element (for bug context).
87
+ */
88
+ export function getElementHtml(el) {
89
+ if (!el)
90
+ return '';
91
+ const html = el.outerHTML;
92
+ return html.length > 500 ? html.slice(0, 500) + '...' : html;
93
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Screenshot capture utility for DevFeedback.
3
+ * Dynamically imports html2canvas — gracefully degrades if not installed
4
+ * (html2canvas is an optional peer dependency).
5
+ */
6
+ export declare function captureScreenshot(): Promise<string | null>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Screenshot capture utility for DevFeedback.
3
+ * Dynamically imports html2canvas — gracefully degrades if not installed
4
+ * (html2canvas is an optional peer dependency).
5
+ */
6
+ export async function captureScreenshot() {
7
+ try {
8
+ const html2canvas = (await import('html2canvas')).default;
9
+ const canvas = await html2canvas(document.body, {
10
+ logging: false,
11
+ useCORS: true,
12
+ scale: 1,
13
+ width: window.innerWidth,
14
+ height: window.innerHeight,
15
+ windowWidth: window.innerWidth,
16
+ windowHeight: window.innerHeight,
17
+ });
18
+ return canvas.toDataURL('image/png');
19
+ }
20
+ catch (err) {
21
+ console.error('[DevFeedback] Screenshot capture failed:', err);
22
+ // html2canvas not installed or capture failed (cross-origin iframe, etc.)
23
+ return null;
24
+ }
25
+ }
@@ -35,12 +35,12 @@
35
35
  }
36
36
  </script>
37
37
 
38
- <div class="space-y-4">
38
+ <div class="space-y-4" role="list" aria-label="Incident timeline">
39
39
  {#each updates as update}
40
40
  {@const config = statusConfig[update.status]}
41
- <div class="flex gap-3">
41
+ <div class="flex gap-3" role="listitem">
42
42
  <div class="flex flex-col items-center">
43
- <i class="fa-solid {config.icon} {config.colorClass} text-sm"></i>
43
+ <i class="fa-solid {config.icon} {config.colorClass} text-sm" aria-hidden="true"></i>
44
44
  <div class="mt-1 h-full w-px bg-border"></div>
45
45
  </div>
46
46
  <div class="pb-4">
@@ -42,8 +42,8 @@
42
42
  let sizeClass = $derived(sizeClasses[size]);
43
43
  </script>
44
44
 
45
- <span class="inline-flex items-center gap-1.5 {sizeClass}">
46
- <i class="fa-solid {current.icon} {current.colorClass}"></i>
45
+ <span class="inline-flex items-center gap-1.5 {sizeClass}" role="status" aria-label="{current.label}">
46
+ <i class="fa-solid {current.icon} {current.colorClass}" aria-hidden="true"></i>
47
47
  {#if showLabel}
48
48
  <span class="text-foreground-secondary">{current.label}</span>
49
49
  {/if}
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  * import { StatusPage, FeedbackButton, createStatusClient } from '@alliance-droid/status-feedback-system';
9
9
  */
10
10
  export type { Project, System, Incident, IncidentUpdate, Feedback, FeedbackResponse, FeedbackVisibility, StatusHistoryEntry, SystemStatus, IncidentStatus, IncidentSeverity, FeedbackStatus, ApiResponse, } from './types.js';
11
+ export { deriveOverallStatus } from './utils.js';
11
12
  export { createStatusClient } from './api.js';
12
13
  export type { StatusClient, StatusClientConfig, StatusData, IncidentData, UptimeData, BoardData, BoardItem, BoardCategory } from './api.js';
13
14
  export { default as StatusPage } from './components/StatusPage.svelte';
package/dist/index.js CHANGED
@@ -7,6 +7,8 @@
7
7
  * Usage:
8
8
  * import { StatusPage, FeedbackButton, createStatusClient } from '@alliance-droid/status-feedback-system';
9
9
  */
10
+ // ── Utilities ──
11
+ export { deriveOverallStatus } from './utils.js';
10
12
  // ── API Client ──
11
13
  export { createStatusClient } from './api.js';
12
14
  // ── Client Components ──
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Shared utility functions for the status-feedback-system package.
3
+ */
4
+ import type { System, SystemStatus } from './types.js';
5
+ /**
6
+ * Derive the overall system status from an array of systems.
7
+ * Priority: outage > degraded > maintenance > operational.
8
+ */
9
+ export declare function deriveOverallStatus(systems: System[]): SystemStatus;
package/dist/utils.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Shared utility functions for the status-feedback-system package.
3
+ */
4
+ /**
5
+ * Derive the overall system status from an array of systems.
6
+ * Priority: outage > degraded > maintenance > operational.
7
+ */
8
+ export function deriveOverallStatus(systems) {
9
+ if (systems.length === 0)
10
+ return 'operational';
11
+ if (systems.some((s) => s.status === 'outage'))
12
+ return 'outage';
13
+ if (systems.some((s) => s.status === 'degraded'))
14
+ return 'degraded';
15
+ if (systems.some((s) => s.status === 'maintenance'))
16
+ return 'maintenance';
17
+ return 'operational';
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alliance-droid/status-feedback-system",
3
- "version": "1.3.0",
3
+ "version": "1.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",
@@ -18,6 +18,7 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "build": "svelte-package -o dist && publint",
21
+ "lint": "svelte-check --tsconfig ./tsconfig.json",
21
22
  "check": "svelte-check --tsconfig ./tsconfig.json",
22
23
  "test": "vitest run",
23
24
  "test:watch": "vitest",
@@ -25,10 +26,17 @@
25
26
  },
26
27
  "peerDependencies": {
27
28
  "@alliance-droid/svelte-component-library": ">=1.0.0",
29
+ "html2canvas": "^1.4.1",
28
30
  "svelte": "^5.0.0"
29
31
  },
32
+ "peerDependenciesMeta": {
33
+ "html2canvas": {
34
+ "optional": true
35
+ }
36
+ },
30
37
  "devDependencies": {
31
38
  "@alliance-droid/svelte-component-library": "^1.0.5",
39
+ "html2canvas": "^1.4.1",
32
40
  "@sveltejs/package": "^2.3.0",
33
41
  "@sveltejs/vite-plugin-svelte": "^6.0.0",
34
42
  "@testing-library/jest-dom": "^6.9.1",
@@ -41,9 +49,6 @@
41
49
  "vite": "^7.3.0",
42
50
  "vitest": "^4.0.0"
43
51
  },
44
- "dependencies": {
45
- "html2canvas": "^1.4.1"
46
- },
47
52
  "keywords": [
48
53
  "svelte",
49
54
  "sveltekit",
@@ -52,12 +57,12 @@
52
57
  "uptime"
53
58
  ],
54
59
  "author": "Alliance Technical Group",
55
- "license": "MIT",
60
+ "license": "UNLICENSED",
56
61
  "publishConfig": {
57
62
  "access": "restricted"
58
63
  },
59
64
  "repository": {
60
65
  "type": "git",
61
- "url": "git+https://github.com/alliance-droid/status-feedback-system.git"
66
+ "url": "git+https://alliance.ghe.com/alliance/status-feedback-system.git"
62
67
  }
63
68
  }