@pixelmatters/markup 1.14.0 → 1.16.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 +18 -27
- package/dist/widget.d.ts +15 -6
- package/dist/widget.js +2403 -1432
- package/dist/widget.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -35,34 +35,32 @@ CDN drop-in (no build step) — paste this just before `</body>`:
|
|
|
35
35
|
```html
|
|
36
36
|
<script type="module">
|
|
37
37
|
// Pin the exact version — esm.sh resolves it from npm
|
|
38
|
-
import { init } from 'https://esm.sh/@pixelmatters/markup@1.
|
|
38
|
+
import { init } from 'https://esm.sh/@pixelmatters/markup@1.16.0'
|
|
39
39
|
// or
|
|
40
|
-
// import { init } from 'https://esm.run/@pixelmatters/markup@1.
|
|
40
|
+
// import { init } from 'https://esm.run/@pixelmatters/markup@1.16.0'
|
|
41
41
|
|
|
42
42
|
init({
|
|
43
43
|
apiUrl: 'https://your-deployment.convex.site',
|
|
44
44
|
apiKey: 'markup_...',
|
|
45
45
|
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left' | 'bottom-center'
|
|
46
46
|
theme: 'auto', // optional: 'auto' | 'light' | 'dark'
|
|
47
|
-
fab: 'default', // optional: 'default' | 'icon-only'
|
|
48
47
|
})
|
|
49
48
|
</script>
|
|
50
49
|
```
|
|
51
50
|
|
|
52
|
-
> **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.
|
|
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.16.0`).
|
|
53
52
|
|
|
54
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:
|
|
55
54
|
|
|
56
55
|
```html
|
|
57
56
|
<script
|
|
58
57
|
type="module"
|
|
59
|
-
src="https://esm.sh/@pixelmatters/markup@1.
|
|
58
|
+
src="https://esm.sh/@pixelmatters/markup@1.16.0"
|
|
60
59
|
data-markup-widget="true"
|
|
61
60
|
data-api-url="https://your-deployment.convex.site"
|
|
62
61
|
data-api-key="markup_..."
|
|
63
62
|
data-position="bottom-right"
|
|
64
63
|
data-theme="auto"
|
|
65
|
-
data-fab="default"
|
|
66
64
|
></script>
|
|
67
65
|
```
|
|
68
66
|
|
|
@@ -80,7 +78,6 @@ const stop = init({
|
|
|
80
78
|
apiKey: 'markup_...',
|
|
81
79
|
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left' | 'bottom-center'
|
|
82
80
|
theme: 'light', // optional: 'auto' | 'light' | 'dark'
|
|
83
|
-
fab: 'default', // optional: 'default' | 'icon-only'
|
|
84
81
|
})
|
|
85
82
|
|
|
86
83
|
// Tear down on logout / route change / page unload:
|
|
@@ -100,7 +97,6 @@ export default function App() {
|
|
|
100
97
|
apiKey: import.meta.env.VITE_MARKUP_API_KEY,
|
|
101
98
|
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left' | 'bottom-center'
|
|
102
99
|
theme: 'auto', // optional: 'auto' | 'light' | 'dark'
|
|
103
|
-
fab: 'default', // optional: 'default' | 'icon-only'
|
|
104
100
|
})
|
|
105
101
|
}, [])
|
|
106
102
|
|
|
@@ -122,7 +118,6 @@ onMounted(() => {
|
|
|
122
118
|
apiKey: import.meta.env.VITE_MARKUP_API_KEY,
|
|
123
119
|
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left' | 'bottom-center'
|
|
124
120
|
theme: 'auto', // optional: 'auto' | 'light' | 'dark'
|
|
125
|
-
fab: 'default', // optional: 'default' | 'icon-only'
|
|
126
121
|
})
|
|
127
122
|
})
|
|
128
123
|
onBeforeUnmount(() => stop?.())
|
|
@@ -142,7 +137,6 @@ export default function App() {
|
|
|
142
137
|
apiKey: import.meta.env.VITE_MARKUP_API_KEY,
|
|
143
138
|
position: 'bottom-right', // optional: 'bottom-right' | 'bottom-left' | 'bottom-center'
|
|
144
139
|
theme: 'auto', // optional: 'auto' | 'light' | 'dark'
|
|
145
|
-
fab: 'default', // optional: 'default' | 'icon-only'
|
|
146
140
|
})
|
|
147
141
|
onCleanup(stop)
|
|
148
142
|
})
|
|
@@ -157,13 +151,12 @@ export default function App() {
|
|
|
157
151
|
|
|
158
152
|
Mounts the widget. Always tears down any existing instance before mounting, so calling `init` again (with the same or a different config) is safe. Returns the `destroy` function.
|
|
159
153
|
|
|
160
|
-
| Option | Type | Default | Description
|
|
161
|
-
| ---------- | ---------------------------------------------------- | ---------------- |
|
|
162
|
-
| `apiUrl` | `string` | required | Convex deployment site URL (`https://*.convex.site`)
|
|
163
|
-
| `apiKey` | `string` | required | Project API key — mint one in the dashboard
|
|
164
|
-
| `position` | `'bottom-right' \| 'bottom-left' \| 'bottom-center'` | `'bottom-right'` | Initial placement for the
|
|
165
|
-
| `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` |
|
|
166
|
-
| `fab` | `'default' \| 'icon-only'` | `'default'` | Floating button variant — `'icon-only'` drops the "Markup" label for a circular icon button |
|
|
154
|
+
| Option | Type | Default | Description |
|
|
155
|
+
| ---------- | ---------------------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
156
|
+
| `apiUrl` | `string` | required | Convex deployment site URL (`https://*.convex.site`) |
|
|
157
|
+
| `apiKey` | `string` | required | Project API key — mint one in the dashboard |
|
|
158
|
+
| `position` | `'bottom-right' \| 'bottom-left' \| 'bottom-center'` | `'bottom-right'` | Initial placement for the toolbar — users can move it with the Position picker in the toolbar's overflow menu |
|
|
159
|
+
| `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | Initial theme — `'light'` or `'dark'`, or `'auto'` (default) to follow the host's `prefers-color-scheme`. Users can change this from the overflow menu; their choice persists and wins over this option from then on |
|
|
167
160
|
|
|
168
161
|
### `destroy()`
|
|
169
162
|
|
|
@@ -173,9 +166,10 @@ Unmounts the widget and removes the host element. Safe to call when nothing is m
|
|
|
173
166
|
|
|
174
167
|
| Shortcut | Action |
|
|
175
168
|
| --------------------- | ---------------------------------------------------------------------- |
|
|
169
|
+
| `c` | Start placing a markup (ignored while typing) |
|
|
170
|
+
| `esc` | Cancel placement, or close the open popover |
|
|
176
171
|
| `cmd/ctrl + .` | Toggle HUD visibility |
|
|
177
|
-
| `cmd/ctrl + click` | Click the
|
|
178
|
-
| Drag the FAB | Snap it to whichever bottom corner the pointer ends in |
|
|
172
|
+
| `cmd/ctrl + click` | Click the toolbar's comment button to hide the HUD with a hint toast |
|
|
179
173
|
| Drag a popover header | Move the open thread / new-thread popover; resets to the pin on reopen |
|
|
180
174
|
|
|
181
175
|
## Screenshots & privacy
|
|
@@ -210,7 +204,7 @@ When a screenshot is attached in the composer, a chip shows how many fields were
|
|
|
210
204
|
|
|
211
205
|
- The widget mounts `<div id="markup-widget">` on `document.body` and attaches an open shadow root.
|
|
212
206
|
- All UI lives in that shadow root, with `:host { all: initial }` blocking style inheritance.
|
|
213
|
-
- The host element is `position: fixed; inset: 0; pointer-events: none`, so the widget paints over the entire viewport without blocking the host's clicks; only the
|
|
207
|
+
- The host element is `position: fixed; inset: 0; pointer-events: none`, so the widget paints over the entire viewport without blocking the host's clicks; only the toolbar and active popovers opt back in to pointer events.
|
|
214
208
|
- Pins are anchored as `(x, y)` fractions of the document plus a best-effort CSS selector (via [`@medv/finder`](https://github.com/antonmedv/finder)). The selector wins when it still resolves; the fraction is the fallback so pins survive layout changes.
|
|
215
209
|
- Identity lives in **host-page** `localStorage` under `markup.identity`, keyed to the top-level site. On first load the widget mints a server-signed anonymous JWT via `POST /widget/anon-identity` so the backend can verify the `authorClientId` on every anon write — tampering with the cached `clientId` invalidates the signature. Verified identities upgrade to a `Bearer` JWT via the popup flow described below.
|
|
216
210
|
|
|
@@ -218,7 +212,7 @@ When a screenshot is attached in the composer, a chip shows how many fields were
|
|
|
218
212
|
|
|
219
213
|
Anonymous by default, with two opt-in upgrade paths:
|
|
220
214
|
|
|
221
|
-
- **Sign in with Markup** — the widget POSTs to `/widget/popup-exchange` with the apiKey + Origin gate, gets back a single-use 60-second code, then opens `${apiUrl}/widget/auth?code=…` in a popup. Because the popup is first-party to the deployment origin, the better-auth session cookie is sent normally (sidestepping third-party cookie blocks). The popup `postMessage`s a verified identity plus a
|
|
215
|
+
- **Sign in with Markup** — the widget POSTs to `/widget/popup-exchange` with the apiKey + Origin gate, gets back a single-use 60-second code, then opens `${apiUrl}/widget/auth?code=…` in a popup. Because the popup is first-party to the deployment origin, the better-auth session cookie is sent normally (sidestepping third-party cookie blocks). The popup `postMessage`s a verified identity plus a short-lived server-signed `Bearer` JWT back to the host page, which attaches it as `Authorization: Bearer` on subsequent writes. Where partitioned (CHIPS) cookies are available the tokens are held in `HttpOnly` cookies and the session refreshes for up to 7 days; where they aren't, the widget falls back to `markup.identity` in the host page's `localStorage` and the session is capped at 24 hours, since a token stored there is readable by any script on the page. The apiKey never appears in the popup URL.
|
|
222
216
|
- **Continue as a guest** — name (and optional email), stored alongside the server-issued anonymous `clientId` + JWT minted on first load.
|
|
223
217
|
|
|
224
218
|
The popup origin is validated against the project's `allowedDomains` before any identity is returned, so only embeds on approved domains can resolve dashboard sessions. Verified JWTs can be invalidated before their TTL via the dashboard's "Sign out everywhere" action.
|
|
@@ -247,7 +241,7 @@ You are helping me install the **`@pixelmatters/markup`** feedback widget into m
|
|
|
247
241
|
|
|
248
242
|
## What it is
|
|
249
243
|
|
|
250
|
-
A drop-in feedback widget published on npm as `@pixelmatters/markup`. It mounts a
|
|
244
|
+
A drop-in feedback widget published on npm as `@pixelmatters/markup`. It mounts a compact toolbar that lets users pin threaded comments (and optional annotated screenshots) anywhere on the page. It runs inside a shadow DOM so it doesn't affect host CSS.
|
|
251
245
|
|
|
252
246
|
## My credentials
|
|
253
247
|
|
|
@@ -265,7 +259,6 @@ init({
|
|
|
265
259
|
apiKey: string, // required
|
|
266
260
|
position?: 'bottom-right' | 'bottom-left' | 'bottom-center', // default 'bottom-right'
|
|
267
261
|
theme?: 'light' | 'dark' | 'auto', // default 'auto'
|
|
268
|
-
fab?: 'default' | 'icon-only', // default 'default'
|
|
269
262
|
}) // returns a destroy() function — call it on unmount / logout / route teardown
|
|
270
263
|
```
|
|
271
264
|
|
|
@@ -278,14 +271,13 @@ For a `<script>` tag drop-in (no bundler), use the inline ESM form and **pin the
|
|
|
278
271
|
|
|
279
272
|
```html
|
|
280
273
|
<script type="module">
|
|
281
|
-
import { init } from 'https://esm.sh/@pixelmatters/markup@1.
|
|
274
|
+
import { init } from 'https://esm.sh/@pixelmatters/markup@1.16.0'
|
|
282
275
|
|
|
283
276
|
init({
|
|
284
277
|
apiUrl: '...',
|
|
285
278
|
apiKey: '...',
|
|
286
279
|
position: 'bottom-right',
|
|
287
280
|
theme: 'auto',
|
|
288
|
-
fab: 'default',
|
|
289
281
|
})
|
|
290
282
|
</script>
|
|
291
283
|
```
|
|
@@ -295,12 +287,11 @@ If inline JS is disallowed (some CMS / page-builder editors), use the auto-init
|
|
|
295
287
|
```html
|
|
296
288
|
<script
|
|
297
289
|
type="module"
|
|
298
|
-
src="https://esm.sh/@pixelmatters/markup@1.
|
|
290
|
+
src="https://esm.sh/@pixelmatters/markup@1.16.0"
|
|
299
291
|
data-markup-widget="true"
|
|
300
292
|
data-api-url="..."
|
|
301
293
|
data-api-key="..."
|
|
302
294
|
data-position="bottom-right"
|
|
303
|
-
data-fab="default"
|
|
304
295
|
></script>
|
|
305
296
|
```
|
|
306
297
|
|
package/dist/widget.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
export type WidgetTheme = 'light' | 'dark' | 'auto';
|
|
2
|
+
/**
|
|
3
|
+
* @deprecated The floating action button was replaced by the toolbar
|
|
4
|
+
* pill, which has no variants. Kept so existing type imports keep
|
|
5
|
+
* compiling; it is no longer referenced by anything the widget renders
|
|
6
|
+
* and will be removed in the next major.
|
|
7
|
+
*/
|
|
2
8
|
export type WidgetFab = 'default' | 'icon-only';
|
|
3
9
|
export interface ScreenshotsConfig {
|
|
4
10
|
/** Disable screenshot capture entirely. Default: enabled. */
|
|
@@ -13,7 +19,10 @@ export interface WidgetConfig {
|
|
|
13
19
|
apiUrl: string;
|
|
14
20
|
/** Raw API key minted from a project's settings page */
|
|
15
21
|
apiKey: string;
|
|
16
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Initial corner for the toolbar. Defaults to bottom-right. Users can
|
|
24
|
+
* move it afterwards from the toolbar's overflow menu.
|
|
25
|
+
*/
|
|
17
26
|
position?: 'bottom-right' | 'bottom-left' | 'bottom-center';
|
|
18
27
|
/**
|
|
19
28
|
* Visual theme.
|
|
@@ -23,11 +32,11 @@ export interface WidgetConfig {
|
|
|
23
32
|
*/
|
|
24
33
|
theme?: WidgetTheme;
|
|
25
34
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
35
|
+
* @deprecated Ignored. The floating action button was replaced by the
|
|
36
|
+
* toolbar pill, which has no variants, so neither `'default'` nor
|
|
37
|
+
* `'icon-only'` describes anything the widget can render. Accepted
|
|
38
|
+
* (and dropped) so upgrading doesn't break callers that still pass it;
|
|
39
|
+
* remove it from your config. Will be deleted in the next major.
|
|
31
40
|
*/
|
|
32
41
|
fab?: WidgetFab;
|
|
33
42
|
/** Screenshot capture and PII-scrub options. */
|