@tonytangdev/pin-point 0.1.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 +119 -0
- package/dist/index.d.mts +32 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +941 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +914 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles/pin-point.css +523 -0
- package/dist/styles/pin-point.css.map +1 -0
- package/dist/styles/pin-point.d.mts +2 -0
- package/dist/styles/pin-point.d.ts +2 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# pin-point
|
|
2
|
+
|
|
3
|
+
Visual feedback overlay for React. Drop pins on any page, leave comments.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install pin-point
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { FeedbackOverlay } from 'pin-point';
|
|
15
|
+
import 'pin-point/styles.css';
|
|
16
|
+
|
|
17
|
+
function App() {
|
|
18
|
+
return (
|
|
19
|
+
<FeedbackOverlay
|
|
20
|
+
onCommentCreate={async (comment, authHeaders) => {
|
|
21
|
+
// Send to your backend with auth headers
|
|
22
|
+
}}
|
|
23
|
+
onCommentsFetch={async (authHeaders) => {
|
|
24
|
+
// Fetch from your backend
|
|
25
|
+
return [];
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
<YourApp />
|
|
29
|
+
</FeedbackOverlay>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The toolbar is always visible when `FeedbackOverlay` is mounted. Anonymous users can view existing comments but cannot create new ones. To leave feedback, a user needs either:
|
|
35
|
+
|
|
36
|
+
- A **feedback link** — a URL containing `?pin-token=<id>`, generated by an admin and shared with reviewers.
|
|
37
|
+
- The **admin key** — paste the admin secret via the toolbar's key icon. It's stored in `localStorage`.
|
|
38
|
+
|
|
39
|
+
Admins generate shareable feedback links from the toolbar's Share button.
|
|
40
|
+
|
|
41
|
+
### With pin-point-server
|
|
42
|
+
|
|
43
|
+
If you don't want to build your own backend, use [pin-point-server](https://www.npmjs.com/package/pin-point-server):
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx pin-point-server
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
const API = 'http://localhost:3000';
|
|
51
|
+
|
|
52
|
+
<FeedbackOverlay
|
|
53
|
+
onCommentCreate={async (comment, authHeaders) => {
|
|
54
|
+
await fetch(`${API}/comments`, {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
headers: { 'Content-Type': 'application/json', ...authHeaders },
|
|
57
|
+
body: JSON.stringify(comment),
|
|
58
|
+
});
|
|
59
|
+
}}
|
|
60
|
+
onCommentsFetch={async (authHeaders) => {
|
|
61
|
+
const res = await fetch(
|
|
62
|
+
`${API}/comments?url=${location.pathname}`,
|
|
63
|
+
{ headers: authHeaders },
|
|
64
|
+
);
|
|
65
|
+
return res.json();
|
|
66
|
+
}}
|
|
67
|
+
onAdminValidate={async (secret) => {
|
|
68
|
+
const res = await fetch(`${API}/admin/tokens`, {
|
|
69
|
+
headers: { 'X-Pin-Admin': secret },
|
|
70
|
+
});
|
|
71
|
+
return res.ok;
|
|
72
|
+
}}
|
|
73
|
+
onShareLinkCreate={async (label, expiresInHours, authHeaders) => {
|
|
74
|
+
const res = await fetch(`${API}/admin/tokens`, {
|
|
75
|
+
method: 'POST',
|
|
76
|
+
headers: { 'Content-Type': 'application/json', ...authHeaders },
|
|
77
|
+
body: JSON.stringify({ label, expiresInHours }),
|
|
78
|
+
});
|
|
79
|
+
const token = await res.json();
|
|
80
|
+
return { tokenId: token.id };
|
|
81
|
+
}}
|
|
82
|
+
>
|
|
83
|
+
<YourApp />
|
|
84
|
+
</FeedbackOverlay>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Props
|
|
88
|
+
|
|
89
|
+
All callbacks receive an `authHeaders` object containing the relevant auth header (`X-Pin-Token` or `X-Pin-Admin`) based on the current user's auth state. Spread it into your `fetch` headers.
|
|
90
|
+
|
|
91
|
+
| Prop | Type | Required | Description |
|
|
92
|
+
|------|------|----------|-------------|
|
|
93
|
+
| `onCommentCreate` | `(comment: PinComment, authHeaders: Record<string, string>) => Promise<void>` | Yes | Called when user submits a comment |
|
|
94
|
+
| `onCommentsFetch` | `(authHeaders: Record<string, string>) => Promise<PinComment[]>` | Yes | Called on mount to load existing comments |
|
|
95
|
+
| `onCommentDelete` | `(id: string, authHeaders: Record<string, string>) => Promise<void>` | No | Called when an admin deletes a comment |
|
|
96
|
+
| `onCommentUpdate` | `(id: string, content: string, authHeaders: Record<string, string>) => Promise<PinComment>` | No | Called when an admin edits a comment |
|
|
97
|
+
| `onAdminValidate` | `(secret: string) => Promise<boolean>` | No | Validates an admin key entered via the toolbar |
|
|
98
|
+
| `onShareLinkCreate` | `(label: string, expiresInHours: number \| null, authHeaders: Record<string, string>) => Promise<{ tokenId: string }>` | No | Mints a feedback-link token (admin-only) |
|
|
99
|
+
|
|
100
|
+
## PinComment
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
type PinComment = {
|
|
104
|
+
id: string;
|
|
105
|
+
url: string;
|
|
106
|
+
content: string;
|
|
107
|
+
anchor: {
|
|
108
|
+
selector: string;
|
|
109
|
+
xPercent: number;
|
|
110
|
+
yPercent: number;
|
|
111
|
+
};
|
|
112
|
+
viewport: { width: number };
|
|
113
|
+
createdAt: string;
|
|
114
|
+
};
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
type PinComment = {
|
|
4
|
+
id: string;
|
|
5
|
+
url: string;
|
|
6
|
+
content: string;
|
|
7
|
+
anchor: {
|
|
8
|
+
selector: string;
|
|
9
|
+
xPercent: number;
|
|
10
|
+
yPercent: number;
|
|
11
|
+
};
|
|
12
|
+
viewport: {
|
|
13
|
+
width: number;
|
|
14
|
+
};
|
|
15
|
+
createdAt: string;
|
|
16
|
+
};
|
|
17
|
+
type AuthHeaders = Record<string, string>;
|
|
18
|
+
type FeedbackOverlayProps = {
|
|
19
|
+
onCommentCreate: (comment: PinComment, authHeaders: AuthHeaders) => Promise<void>;
|
|
20
|
+
onCommentsFetch: (authHeaders: AuthHeaders) => Promise<PinComment[]>;
|
|
21
|
+
onCommentDelete?: (id: string, authHeaders: AuthHeaders) => Promise<void>;
|
|
22
|
+
onCommentUpdate?: (id: string, content: string, authHeaders: AuthHeaders) => Promise<PinComment>;
|
|
23
|
+
onAdminValidate?: (secret: string) => Promise<boolean>;
|
|
24
|
+
onShareLinkCreate?: (label: string | undefined, expiresInHours: number | undefined, authHeaders: AuthHeaders) => Promise<{
|
|
25
|
+
tokenId: string;
|
|
26
|
+
}>;
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
declare function FeedbackOverlay({ onCommentCreate, onCommentsFetch, onCommentDelete, onCommentUpdate, onAdminValidate, onShareLinkCreate, children, }: FeedbackOverlayProps): react_jsx_runtime.JSX.Element;
|
|
31
|
+
|
|
32
|
+
export { FeedbackOverlay, type FeedbackOverlayProps, type PinComment };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
type PinComment = {
|
|
4
|
+
id: string;
|
|
5
|
+
url: string;
|
|
6
|
+
content: string;
|
|
7
|
+
anchor: {
|
|
8
|
+
selector: string;
|
|
9
|
+
xPercent: number;
|
|
10
|
+
yPercent: number;
|
|
11
|
+
};
|
|
12
|
+
viewport: {
|
|
13
|
+
width: number;
|
|
14
|
+
};
|
|
15
|
+
createdAt: string;
|
|
16
|
+
};
|
|
17
|
+
type AuthHeaders = Record<string, string>;
|
|
18
|
+
type FeedbackOverlayProps = {
|
|
19
|
+
onCommentCreate: (comment: PinComment, authHeaders: AuthHeaders) => Promise<void>;
|
|
20
|
+
onCommentsFetch: (authHeaders: AuthHeaders) => Promise<PinComment[]>;
|
|
21
|
+
onCommentDelete?: (id: string, authHeaders: AuthHeaders) => Promise<void>;
|
|
22
|
+
onCommentUpdate?: (id: string, content: string, authHeaders: AuthHeaders) => Promise<PinComment>;
|
|
23
|
+
onAdminValidate?: (secret: string) => Promise<boolean>;
|
|
24
|
+
onShareLinkCreate?: (label: string | undefined, expiresInHours: number | undefined, authHeaders: AuthHeaders) => Promise<{
|
|
25
|
+
tokenId: string;
|
|
26
|
+
}>;
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
declare function FeedbackOverlay({ onCommentCreate, onCommentsFetch, onCommentDelete, onCommentUpdate, onAdminValidate, onShareLinkCreate, children, }: FeedbackOverlayProps): react_jsx_runtime.JSX.Element;
|
|
31
|
+
|
|
32
|
+
export { FeedbackOverlay, type FeedbackOverlayProps, type PinComment };
|