@newsoftglobal/feedbackkit-vue 1.0.0
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/README.md +150 -0
- package/dist/feedbackkit-vue.css +1 -0
- package/dist/feedbackkit-vue.js +5724 -0
- package/dist/feedbackkit-vue.umd.cjs +22 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# @newsoftglobal/feedbackkit-vue
|
|
2
|
+
|
|
3
|
+
> 🎯 Collect user feedback with screenshots directly from your Vue.js app.
|
|
4
|
+
|
|
5
|
+
A lightweight Vue 3 plugin that adds a feedback widget to your app. Users can select a screen region, capture a screenshot, submit feedback, and track their submissions — all without leaving your app.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 📸 **Screen Capture** — Drag to select any area, auto-capture with html2canvas
|
|
10
|
+
- 💬 **Feedback Form** — Title, description, type (bug/feature/improvement), email
|
|
11
|
+
- 📋 **My Feedbacks** — Users can view their submitted feedbacks and status
|
|
12
|
+
- 🗨️ **Comments** — Two-way conversation between users and admin
|
|
13
|
+
- 🔑 **User Identity** — `setUser` / `clearUser` pattern for delayed auth
|
|
14
|
+
- 🎨 **Dark Theme** — Premium dark UI that blends with any app
|
|
15
|
+
- ⚡ **Lightweight** — ~60KB gzipped (includes html2canvas)
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @newsoftglobal/feedbackkit-vue
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
// main.js
|
|
27
|
+
import { createApp } from 'vue'
|
|
28
|
+
import App from './App.vue'
|
|
29
|
+
import FeedbackKit from '@newsoftglobal/feedbackkit-vue'
|
|
30
|
+
import '@newsoftglobal/feedbackkit-vue/style.css'
|
|
31
|
+
|
|
32
|
+
const app = createApp(App)
|
|
33
|
+
|
|
34
|
+
app.use(FeedbackKit, {
|
|
35
|
+
apiKey: 'your-api-key',
|
|
36
|
+
serverUrl: 'https://your-backend.com'
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
app.mount('#app')
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Add the widget to your root component:
|
|
43
|
+
|
|
44
|
+
```vue
|
|
45
|
+
<template>
|
|
46
|
+
<div>
|
|
47
|
+
<!-- Your app content -->
|
|
48
|
+
<FeedbackWidget />
|
|
49
|
+
</div>
|
|
50
|
+
</template>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
That's it! A purple floating button will appear at the bottom-right corner.
|
|
54
|
+
|
|
55
|
+
## User Identity
|
|
56
|
+
|
|
57
|
+
FeedbackKit supports **init first, set user later** — perfect for apps where login happens after page load.
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
import { useFeedbackKit } from '@newsoftglobal/feedbackkit-vue'
|
|
61
|
+
|
|
62
|
+
// In your login handler:
|
|
63
|
+
const { setUser, clearUser } = useFeedbackKit()
|
|
64
|
+
|
|
65
|
+
// After user logs in
|
|
66
|
+
setUser({
|
|
67
|
+
id: 'user-123', // required
|
|
68
|
+
name: 'John Doe', // optional
|
|
69
|
+
email: 'john@email.com' // optional
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
// On logout
|
|
73
|
+
clearUser()
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Or via Options API:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
// In any component
|
|
80
|
+
this.$feedbackKit.setUser({ id: 'user-123', name: 'John' })
|
|
81
|
+
this.$feedbackKit.clearUser()
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## How It Works
|
|
85
|
+
|
|
86
|
+
1. User clicks the **floating button** → Panel opens with two tabs
|
|
87
|
+
2. **"New Feedback"** tab → Click "Select Area & Capture"
|
|
88
|
+
3. **Drag to select** a region on the screen → Click "✓ Capture"
|
|
89
|
+
4. Fill in the **feedback form** → Submit
|
|
90
|
+
5. **"My Feedbacks"** tab → View all submitted feedbacks with status
|
|
91
|
+
6. Click a feedback → See **detail & comments** (chat with admin)
|
|
92
|
+
|
|
93
|
+
## Configuration
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
app.use(FeedbackKit, {
|
|
97
|
+
apiKey: string, // Required - API key from your FeedbackKit admin
|
|
98
|
+
serverUrl: string // Required - Your FeedbackKit backend URL
|
|
99
|
+
})
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## API
|
|
103
|
+
|
|
104
|
+
### `useFeedbackKit()` (Composition API)
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
const { setUser, clearUser, user, hasUser } = useFeedbackKit()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
| Method | Description |
|
|
111
|
+
|---|---|
|
|
112
|
+
| `setUser({ id, name?, email? })` | Set current user identity |
|
|
113
|
+
| `clearUser()` | Clear user identity (on logout) |
|
|
114
|
+
| `user` | Reactive user object |
|
|
115
|
+
| `hasUser` | Boolean — whether a user is set |
|
|
116
|
+
|
|
117
|
+
### `this.$feedbackKit` (Options API)
|
|
118
|
+
|
|
119
|
+
Same methods available on `this.$feedbackKit` in any component.
|
|
120
|
+
|
|
121
|
+
## Backend
|
|
122
|
+
|
|
123
|
+
This SDK requires a FeedbackKit backend server. The SDK communicates via:
|
|
124
|
+
|
|
125
|
+
| Endpoint | Method | Auth | Description |
|
|
126
|
+
|---|---|---|---|
|
|
127
|
+
| `/api/feedbacks` | POST | API Key | Submit feedback |
|
|
128
|
+
| `/api/feedbacks/user` | GET | API Key | List user's feedbacks |
|
|
129
|
+
| `/api/feedbacks/user/:id` | GET | API Key | Get feedback detail |
|
|
130
|
+
| `/api/feedbacks/user/:id/comments` | POST | API Key | Add user comment |
|
|
131
|
+
|
|
132
|
+
All requests include `x-api-key` header automatically.
|
|
133
|
+
|
|
134
|
+
## Environment Variables (Vite)
|
|
135
|
+
|
|
136
|
+
```env
|
|
137
|
+
VITE_FEEDBACKKIT_API_KEY=your-api-key
|
|
138
|
+
VITE_FEEDBACKKIT_SERVER_URL=http://localhost:3000
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```js
|
|
142
|
+
app.use(FeedbackKit, {
|
|
143
|
+
apiKey: import.meta.env.VITE_FEEDBACKKIT_API_KEY,
|
|
144
|
+
serverUrl: import.meta.env.VITE_FEEDBACKKIT_SERVER_URL
|
|
145
|
+
})
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.fk-fab,.fk-screen-capture,.fk-form-overlay,.fk-form-modal{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;box-sizing:border-box;line-height:1.5}.fk-fab{position:fixed;bottom:24px;right:24px;width:52px;height:52px;border-radius:16px;border:none;background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 20px #6366f166,0 2px 8px #00000026;transition:all .3s cubic-bezier(.4,0,.2,1);z-index:2147483640;animation:fk-fab-entrance .4s cubic-bezier(.34,1.56,.64,1)}.fk-fab:hover{transform:scale(1.08);box-shadow:0 6px 28px #6366f18c,0 4px 12px #0003}.fk-fab:active{transform:scale(.95)}@keyframes fk-fab-entrance{0%{opacity:0;transform:scale(.5) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}.fk-screen-capture{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:2147483645;cursor:crosshair}.fk-capture-overlay{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.fk-selection-border{position:absolute;border:2px solid #6366f1;border-radius:4px;box-shadow:0 0 0 1px #ffffff4d,0 0 20px #6366f14d;pointer-events:none}.fk-capture-instructions{position:fixed;top:24px;left:50%;transform:translate(-50%);z-index:2147483646;animation:fk-slide-down .3s ease-out}.fk-capture-instructions-inner{display:flex;align-items:center;gap:10px;background:#000000d9;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);color:#fff;padding:10px 20px;border-radius:12px;font-size:14px;font-weight:500;box-shadow:0 8px 32px #0000004d}.fk-capture-cancel{margin-left:8px;padding:4px 12px;border:1px solid rgba(255,255,255,.2);border-radius:6px;background:#ffffff1a;color:#fff;cursor:pointer;font-size:12px;transition:background .2s}.fk-capture-cancel:hover{background:#fff3}@keyframes fk-slide-down{0%{opacity:0;transform:translate(-50%) translateY(-10px)}to{opacity:1;transform:translate(-50%) translateY(0)}}.fk-capture-actions{position:fixed;transform:translate(-50%);display:flex;gap:8px;z-index:2147483646;animation:fk-pop-in .2s ease-out}@keyframes fk-pop-in{0%{opacity:0;transform:translate(-50%) scale(.9)}to{opacity:1;transform:translate(-50%) scale(1)}}.fk-btn{padding:8px 18px;border-radius:8px;border:none;font-size:13px;font-weight:600;cursor:pointer;transition:all .2s ease;display:flex;align-items:center;gap:4px}.fk-btn-confirm{background:#6366f1;color:#fff;box-shadow:0 2px 8px #6366f166}.fk-btn-confirm:hover{background:#5558e6}.fk-btn-cancel,.fk-btn-secondary{background:#ffffff26;color:#fff;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.fk-btn-cancel:hover,.fk-btn-secondary:hover{background:#ffffff40}.fk-btn-primary{background:linear-gradient(135deg,#6366f1,#8b5cf6);color:#fff;box-shadow:0 2px 12px #6366f159}.fk-btn-primary:hover{box-shadow:0 4px 16px #6366f180}.fk-btn-primary:disabled{opacity:.5;cursor:not-allowed}.fk-form-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:2147483646;animation:fk-fade-in .2s ease-out}@keyframes fk-fade-in{0%{opacity:0}to{opacity:1}}.fk-form-modal{background:#1a1b2e;border-radius:16px;width:90%;max-width:480px;max-height:90vh;overflow-y:auto;box-shadow:0 24px 80px #0006,0 0 0 1px #ffffff0f;animation:fk-modal-in .3s cubic-bezier(.34,1.56,.64,1)}@keyframes fk-modal-in{0%{opacity:0;transform:scale(.95) translateY(10px)}to{opacity:1;transform:scale(1) translateY(0)}}.fk-form-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px 0}.fk-form-header h3{margin:0;font-size:18px;font-weight:700;color:#f0f0f5}.fk-form-close{width:32px;height:32px;border-radius:8px;border:none;background:#ffffff0f;color:#a0a0b0;font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s}.fk-form-close:hover{background:#ffffff1f;color:#fff}.fk-screenshot-preview{margin:16px 24px 0;position:relative;border-radius:10px;overflow:hidden;border:1px solid rgba(255,255,255,.08)}.fk-screenshot-preview img{width:100%;max-height:200px;object-fit:cover;display:block}.fk-screenshot-remove{position:absolute;top:8px;right:8px;padding:4px 10px;border-radius:6px;border:none;background:#000000b3;color:#fff;font-size:12px;cursor:pointer;transition:background .2s}.fk-screenshot-remove:hover{background:#ef4444cc}.fk-form-body{padding:20px 24px 24px}.fk-field{margin-bottom:16px}.fk-field label{display:block;font-size:13px;font-weight:600;color:#a0a0b8;margin-bottom:6px}.fk-required{color:#ef4444}.fk-field input,.fk-field textarea{width:100%;padding:10px 14px;border-radius:10px;border:1px solid rgba(255,255,255,.08);background:#ffffff0a;color:#f0f0f5;font-size:14px;font-family:inherit;transition:all .2s;outline:none;box-sizing:border-box}.fk-field input:focus,.fk-field textarea:focus{border-color:#6366f1;box-shadow:0 0 0 3px #6366f126}.fk-field input::placeholder,.fk-field textarea::placeholder{color:#555568}.fk-field textarea{resize:vertical;min-height:60px}.fk-type-selector{display:flex;gap:8px;flex-wrap:wrap}.fk-type-btn{padding:6px 14px;border-radius:20px;border:1px solid rgba(255,255,255,.08);background:#ffffff0a;color:#a0a0b8;font-size:13px;cursor:pointer;transition:all .2s;display:flex;align-items:center;gap:5px}.fk-type-btn:hover{border-color:#ffffff26;background:#ffffff14}.fk-type-btn.active{border-color:#6366f1;background:#6366f126;color:#a5b4fc}.fk-type-icon{font-size:14px}.fk-form-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}.fk-form-actions .fk-btn-secondary{color:#a0a0b8;background:#ffffff0f}.fk-form-actions .fk-btn-secondary:hover{background:#ffffff1a;color:#fff}.fk-error{margin-top:12px;padding:8px 12px;border-radius:8px;background:#ef44441f;color:#fca5a5;font-size:13px}.fk-success{margin-top:12px;padding:8px 12px;border-radius:8px;background:#22c55e1f;color:#86efac;font-size:13px}.fk-panel{position:fixed;bottom:86px;right:24px;width:340px;background:#1a1b2e;border-radius:16px;border:1px solid rgba(255,255,255,.06);box-shadow:0 16px 64px #0006,0 0 0 1px #ffffff0a;z-index:2147483640;overflow:hidden;animation:fk-panel-in .25s cubic-bezier(.34,1.56,.64,1);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;color:#f0f0f5}@keyframes fk-panel-in{0%{opacity:0;transform:translateY(8px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.fk-panel-tabs{display:flex;border-bottom:1px solid rgba(255,255,255,.06)}.fk-tab{flex:1;padding:12px 8px;border:none;background:transparent;color:#666680;font-size:13px;font-weight:600;cursor:pointer;transition:all .2s;font-family:inherit;border-bottom:2px solid transparent}.fk-tab:hover{color:#a0a0b8;background:#ffffff05}.fk-tab.active{color:#a5b4fc;border-bottom-color:#6366f1}.fk-panel-body{padding:20px}.fk-panel-hint{font-size:13px;color:#8888a0;margin-bottom:16px;line-height:1.4}.fk-btn-full{width:100%;justify-content:center;padding:12px 18px;font-size:14px}.fk-feedback-list{max-height:380px;overflow-y:auto}.fk-list-header{display:flex;align-items:center;justify-content:space-between;padding:14px 18px 8px}.fk-list-header h4{margin:0;font-size:14px;font-weight:700;color:#a0a0b8}.fk-list-count{background:#6366f126;color:#a5b4fc;font-size:11px;font-weight:700;padding:2px 8px;border-radius:10px}.fk-list-loading{padding:30px 20px;text-align:center;color:#666680;font-size:13px}.fk-list-empty{padding:32px 20px;text-align:center}.fk-list-empty-icon{font-size:28px;display:block;margin-bottom:8px}.fk-list-empty p{color:#555568;font-size:13px;margin:0}.fk-list-items{padding:4px 8px 8px}.fk-list-item{padding:10px 12px;border-radius:10px;margin-bottom:2px;transition:background .15s;cursor:pointer}.fk-list-item:hover{background:#ffffff08}.fk-list-item-top{display:flex;align-items:center;gap:8px}.fk-list-type{font-size:14px;flex-shrink:0}.fk-list-title{font-size:13px;font-weight:600;color:#e0e0ee;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.fk-list-item-bottom{display:flex;align-items:center;justify-content:space-between;margin-top:4px;padding-left:22px}.fk-list-status{font-size:11px;font-weight:600}.fk-list-status.new{color:#fde047}.fk-list-status.in-progress{color:#93c5fd}.fk-list-status.resolved{color:#86efac}.fk-list-status.closed{color:#666680}.fk-list-date{font-size:11px;color:#555568}.fk-detail-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#0009;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;z-index:2147483647;animation:fk-fade-in .2s ease-out}.fk-detail-modal{background:#1a1b2e;border-radius:16px;width:90%;max-width:440px;max-height:85vh;display:flex;flex-direction:column;box-shadow:0 24px 80px #00000080,0 0 0 1px #ffffff0f;animation:fk-modal-in .3s cubic-bezier(.34,1.56,.64,1);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;color:#f0f0f5}.fk-detail-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid rgba(255,255,255,.06)}.fk-detail-type{font-size:12px;font-weight:600;padding:3px 10px;border-radius:12px;text-transform:capitalize;margin-right:8px}.fk-detail-type.bug{background:#ef44441f;color:#fca5a5}.fk-detail-type.feature{background:#6366f11f;color:#a5b4fc}.fk-detail-type.improvement{background:#eab3081f;color:#fde047}.fk-detail-type.other{background:#3b82f61f;color:#93c5fd}.fk-detail-status{font-size:11px;font-weight:600}.fk-detail-status.new{color:#fde047}.fk-detail-status.in-progress{color:#93c5fd}.fk-detail-status.resolved{color:#86efac}.fk-detail-status.closed{color:#666680}.fk-detail-loading{padding:40px 20px;text-align:center;color:#666680}.fk-detail-body{padding:16px 20px;border-bottom:1px solid rgba(255,255,255,.06)}.fk-detail-title{font-size:16px;font-weight:700;margin:0 0 6px}.fk-detail-desc{font-size:14px;color:#a0a0b8;line-height:1.5;margin:0 0 8px}.fk-detail-date{font-size:11px;color:#555568}.fk-comments{flex:1;display:flex;flex-direction:column;min-height:0}.fk-comments-label{font-size:12px;font-weight:600;color:#555568;text-transform:uppercase;letter-spacing:.5px;padding:12px 20px 6px}.fk-comments-empty{padding:24px 20px;text-align:center;font-size:13px;color:#555568}.fk-comments-list{flex:1;overflow-y:auto;padding:8px 20px;max-height:280px;display:flex;flex-direction:column;gap:10px}.fk-comment{padding:10px 14px;border-radius:12px;max-width:85%}.fk-comment.user{background:#6366f11a;align-self:flex-end;border-bottom-right-radius:4px}.fk-comment.admin{background:#ffffff0d;align-self:flex-start;border-bottom-left-radius:4px}.fk-comment-meta{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px;gap:8px}.fk-comment-author{font-size:11px;font-weight:700;color:#8888a0}.fk-comment-time{font-size:10px;color:#444458}.fk-comment-text{font-size:13px;line-height:1.5;color:#d0d0e0}.fk-comment-input{display:flex;gap:8px;padding:12px 16px;border-top:1px solid rgba(255,255,255,.06)}.fk-comment-input input{flex:1;padding:8px 14px;border-radius:20px;border:1px solid rgba(255,255,255,.08);background:#ffffff0a;color:#f0f0f5;font-size:13px;font-family:inherit;outline:none;transition:border-color .2s}.fk-comment-input input:focus{border-color:#6366f1}.fk-comment-input input::placeholder{color:#555568}.fk-comment-input .fk-btn{width:36px;height:36px;padding:0;border-radius:50%;justify-content:center;font-size:16px;flex-shrink:0}
|