@pixelmatters/markup 1.2.0 → 1.3.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 +99 -26
- package/package.json +3 -21
- package/dist/react.d.ts +0 -21
- package/dist/react.js +0 -4896
package/README.md
CHANGED
|
@@ -17,25 +17,45 @@ Pin-anchored feedback for live web apps. Drop in a script tag (or one React comp
|
|
|
17
17
|
- **Respects the platform** — honours `prefers-reduced-motion` and `prefers-color-scheme`; full keyboard navigation with focus traps in popovers.
|
|
18
18
|
- **Tiny surface, tiny config** — `init({ apiUrl, apiKey })` is enough to start. No global CSS to import, no provider to wrap.
|
|
19
19
|
|
|
20
|
-
Built with [Preact](https://preactjs.com). Ships as ESM with a
|
|
20
|
+
Built with [Preact](https://preactjs.com). Ships as a single ESM bundle — wire it into any framework with a one-liner in your root component (snippets below).
|
|
21
21
|
|
|
22
22
|
## Install
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
25
|
# pnpm
|
|
26
|
-
pnpm
|
|
26
|
+
pnpm add @pixelmatters/markup
|
|
27
27
|
# or yarn
|
|
28
28
|
yarn add @pixelmatters/markup
|
|
29
29
|
# or npm
|
|
30
30
|
npm install @pixelmatters/markup
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
CDN drop-in (
|
|
33
|
+
CDN drop-in (no build step) — paste this just before `</body>`:
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<script type="module">
|
|
37
|
+
// Pin the exact version — esm.sh resolves it from npm
|
|
38
|
+
import { init } from 'https://esm.sh/@pixelmatters/markup@1.3.0'
|
|
39
|
+
// or
|
|
40
|
+
// import { init } from 'https://esm.run/@pixelmatters/markup@1.3.0'
|
|
41
|
+
|
|
42
|
+
init({
|
|
43
|
+
apiUrl: 'https://your-deployment.convex.site',
|
|
44
|
+
apiKey: 'markup_...',
|
|
45
|
+
position: 'bottom-right', // optional
|
|
46
|
+
theme: 'auto', // optional
|
|
47
|
+
})
|
|
48
|
+
</script>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
> **Why pin the version?** CDN URLs without a version (`@pixelmatters/markup`) resolve to whatever's `latest` on npm — a future major release will break your page silently. Always pin (`@pixelmatters/markup@1.3.0`).
|
|
52
|
+
|
|
53
|
+
If your platform doesn't allow inline JS (some CMS / page-builder editors), use the auto-init form instead — point a `<script src=…>` at the bundle and pass config via `data-*` attributes:
|
|
34
54
|
|
|
35
55
|
```html
|
|
36
56
|
<script
|
|
37
57
|
type="module"
|
|
38
|
-
src="https://
|
|
58
|
+
src="https://esm.sh/@pixelmatters/markup@1.3.0"
|
|
39
59
|
data-markup-widget="true"
|
|
40
60
|
data-api-url="https://your-deployment.convex.site"
|
|
41
61
|
data-api-key="markup_..."
|
|
@@ -43,7 +63,7 @@ CDN drop-in (auto-init on `DOMContentLoaded`):
|
|
|
43
63
|
></script>
|
|
44
64
|
```
|
|
45
65
|
|
|
46
|
-
|
|
66
|
+
`data-markup-widget="true"` is required — it's how the bootstrap finds its own `<script>` tag (since `document.currentScript` is `null` for `type="module"`).
|
|
47
67
|
|
|
48
68
|
## Quickstart
|
|
49
69
|
|
|
@@ -63,23 +83,60 @@ const stop = init({
|
|
|
63
83
|
stop() // equivalent to destroy()
|
|
64
84
|
```
|
|
65
85
|
|
|
66
|
-
### React
|
|
86
|
+
### React
|
|
67
87
|
|
|
68
88
|
```tsx
|
|
69
|
-
import {
|
|
89
|
+
import { useEffect } from 'react'
|
|
90
|
+
import { init } from '@pixelmatters/markup'
|
|
70
91
|
|
|
71
92
|
export default function App() {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
return init({
|
|
95
|
+
apiUrl: import.meta.env.VITE_MARKUP_API_URL,
|
|
96
|
+
apiKey: import.meta.env.VITE_MARKUP_API_KEY,
|
|
97
|
+
position: 'bottom-right', // optional
|
|
98
|
+
theme: 'auto', // optional
|
|
99
|
+
})
|
|
100
|
+
}, [])
|
|
101
|
+
|
|
102
|
+
return <>{/* your app */}</>
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Vue 3
|
|
107
|
+
|
|
108
|
+
```vue
|
|
109
|
+
<script setup lang="ts">
|
|
110
|
+
import { onMounted, onBeforeUnmount } from 'vue'
|
|
111
|
+
import { init } from '@pixelmatters/markup'
|
|
112
|
+
|
|
113
|
+
let stop: (() => void) | undefined
|
|
114
|
+
onMounted(() => {
|
|
115
|
+
stop = init({
|
|
116
|
+
apiUrl: import.meta.env.VITE_MARKUP_API_URL,
|
|
117
|
+
apiKey: import.meta.env.VITE_MARKUP_API_KEY,
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
onBeforeUnmount(() => stop?.())
|
|
121
|
+
</script>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### SolidJS
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
import { onMount, onCleanup } from 'solid-js'
|
|
128
|
+
import { init } from '@pixelmatters/markup'
|
|
129
|
+
|
|
130
|
+
export default function App() {
|
|
131
|
+
onMount(() => {
|
|
132
|
+
const stop = init({
|
|
133
|
+
apiUrl: import.meta.env.VITE_MARKUP_API_URL,
|
|
134
|
+
apiKey: import.meta.env.VITE_MARKUP_API_KEY,
|
|
135
|
+
})
|
|
136
|
+
onCleanup(stop)
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
return <>{/* your app */}</>
|
|
83
140
|
}
|
|
84
141
|
```
|
|
85
142
|
|
|
@@ -156,8 +213,6 @@ A drop-in feedback widget published on npm as `@pixelmatters/markup`. It mounts
|
|
|
156
213
|
|
|
157
214
|
```ts
|
|
158
215
|
import { init, destroy } from '@pixelmatters/markup'
|
|
159
|
-
// or:
|
|
160
|
-
import { MarkupWidget } from '@pixelmatters/markup/react'
|
|
161
216
|
|
|
162
217
|
init({
|
|
163
218
|
apiUrl: string, // required
|
|
@@ -167,12 +222,32 @@ init({
|
|
|
167
222
|
}) // returns a destroy() function — call it on unmount / logout / route teardown
|
|
168
223
|
```
|
|
169
224
|
|
|
170
|
-
For
|
|
225
|
+
For React/Vue/Solid hosts, call `init()` from a mount lifecycle hook
|
|
226
|
+
(`useEffect`, `onMounted`, `onMount`) and call the returned `destroy` on
|
|
227
|
+
cleanup. There's no framework-specific entrypoint — `init` is the entire
|
|
228
|
+
public surface.
|
|
229
|
+
|
|
230
|
+
For a `<script>` tag drop-in (no bundler), use the inline ESM form and **pin the version**:
|
|
231
|
+
|
|
232
|
+
```html
|
|
233
|
+
<script type="module">
|
|
234
|
+
import { init } from 'https://esm.sh/@pixelmatters/markup@1.3.0'
|
|
235
|
+
|
|
236
|
+
init({
|
|
237
|
+
apiUrl: '...',
|
|
238
|
+
apiKey: '...',
|
|
239
|
+
position: 'bottom-right',
|
|
240
|
+
theme: 'auto',
|
|
241
|
+
})
|
|
242
|
+
</script>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
If inline JS is disallowed (some CMS / page-builder editors), use the auto-init `<script src=…>` form with `data-*` attributes (`data-markup-widget="true"` is required):
|
|
171
246
|
|
|
172
247
|
```html
|
|
173
248
|
<script
|
|
174
249
|
type="module"
|
|
175
|
-
src="https://
|
|
250
|
+
src="https://esm.sh/@pixelmatters/markup@1.3.0"
|
|
176
251
|
data-markup-widget="true"
|
|
177
252
|
data-api-url="..."
|
|
178
253
|
data-api-key="..."
|
|
@@ -180,8 +255,6 @@ For a `<script>` tag drop-in (no bundler), use:
|
|
|
180
255
|
></script>
|
|
181
256
|
```
|
|
182
257
|
|
|
183
|
-
The `data-markup-widget="true"` attribute is required.
|
|
184
|
-
|
|
185
258
|
## Your task
|
|
186
259
|
|
|
187
260
|
1. Detect my framework (React, Vue, Svelte, Next.js, plain HTML, etc.) by inspecting the project.
|
|
@@ -195,7 +268,7 @@ Constraints:
|
|
|
195
268
|
|
|
196
269
|
- Do **not** add CSS imports or provider components — the widget needs neither.
|
|
197
270
|
- Do **not** hardcode the key.
|
|
198
|
-
- If the project has a CSP, add `https://
|
|
271
|
+
- If the project has a CSP, add `https://esm.sh` to `script-src` only if I'm using the `<script>` tag path.
|
|
199
272
|
````
|
|
200
273
|
|
|
201
274
|
## Browser support
|
|
@@ -206,7 +279,7 @@ Modern evergreen browsers (Chrome, Edge, Firefox, Safari) and their mobile equiv
|
|
|
206
279
|
|
|
207
280
|
```bash
|
|
208
281
|
pnpm dev # vite dev server with the playground page
|
|
209
|
-
pnpm build # production build → dist/
|
|
282
|
+
pnpm build # production build → dist/widget.{js,d.ts}
|
|
210
283
|
pnpm typecheck # tsc --noEmit
|
|
211
284
|
```
|
|
212
285
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixelmatters/markup",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Embeddable feedback widget for collecting visual bug reports, screenshots, and comments on live web apps.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"annotation",
|
|
@@ -26,8 +26,6 @@
|
|
|
26
26
|
"files": [
|
|
27
27
|
"dist/widget.js",
|
|
28
28
|
"dist/widget.d.ts",
|
|
29
|
-
"dist/react.js",
|
|
30
|
-
"dist/react.d.ts",
|
|
31
29
|
"README.md",
|
|
32
30
|
"LICENSE"
|
|
33
31
|
],
|
|
@@ -38,10 +36,7 @@
|
|
|
38
36
|
"types": "./dist/widget.d.ts",
|
|
39
37
|
"import": "./dist/widget.js"
|
|
40
38
|
},
|
|
41
|
-
"./
|
|
42
|
-
"types": "./dist/react.d.ts",
|
|
43
|
-
"import": "./dist/react.js"
|
|
44
|
-
}
|
|
39
|
+
"./package.json": "./package.json"
|
|
45
40
|
},
|
|
46
41
|
"publishConfig": {
|
|
47
42
|
"access": "public",
|
|
@@ -50,7 +45,6 @@
|
|
|
50
45
|
"devDependencies": {
|
|
51
46
|
"@medv/finder": "^4.0.2",
|
|
52
47
|
"@preact/preset-vite": "^2.10.5",
|
|
53
|
-
"@types/react": "^19.2.14",
|
|
54
48
|
"convex": "^1.37.0",
|
|
55
49
|
"html-to-image": "^1.11.13",
|
|
56
50
|
"preact": "^10.25.0",
|
|
@@ -58,23 +52,11 @@
|
|
|
58
52
|
"vite": "^8.0.11",
|
|
59
53
|
"vite-plugin-dts": "^5.0.0"
|
|
60
54
|
},
|
|
61
|
-
"peerDependencies": {
|
|
62
|
-
"react": "^18.0.0 || ^19.0.0",
|
|
63
|
-
"react-dom": "^18.0.0 || ^19.0.0"
|
|
64
|
-
},
|
|
65
|
-
"peerDependenciesMeta": {
|
|
66
|
-
"react": {
|
|
67
|
-
"optional": true
|
|
68
|
-
},
|
|
69
|
-
"react-dom": {
|
|
70
|
-
"optional": true
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
55
|
"engines": {
|
|
74
56
|
"node": ">=18"
|
|
75
57
|
},
|
|
76
58
|
"scripts": {
|
|
77
|
-
"build": "vite build
|
|
59
|
+
"build": "vite build && rm -rf dist/runtime",
|
|
78
60
|
"dev": "vite",
|
|
79
61
|
"typecheck": "tsc --noEmit"
|
|
80
62
|
}
|
package/dist/react.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { WidgetTheme } from './widget';
|
|
2
|
-
export interface MarkupWidgetProps {
|
|
3
|
-
/** Convex deployment site URL, e.g. `https://your-deployment.convex.site` */
|
|
4
|
-
apiUrl: string;
|
|
5
|
-
/** Raw API key minted from a project's settings page */
|
|
6
|
-
apiKey: string;
|
|
7
|
-
/** Where the floating button sits. Defaults to bottom-right. */
|
|
8
|
-
position?: 'bottom-right' | 'bottom-left';
|
|
9
|
-
/** 'light' | 'dark' | 'auto' (default 'auto' — follow prefers-color-scheme) */
|
|
10
|
-
theme?: WidgetTheme;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* React-host entrypoint. Renders nothing — the actual UI mounts itself into
|
|
14
|
-
* a sibling shadow DOM at `document.body` so it never tangles with the host
|
|
15
|
-
* tree's CSS.
|
|
16
|
-
*
|
|
17
|
-
* `useEffect` is imported from `react`, which the consumer's bundler
|
|
18
|
-
* resolves: real React in a React app, or `preact/hooks` re-exported via
|
|
19
|
-
* `preact/compat` in a Preact app that has aliased `react` → `preact/compat`.
|
|
20
|
-
*/
|
|
21
|
-
export declare function MarkupWidget(props: MarkupWidgetProps): null;
|