page-annotation 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +50 -0
- package/dist/annotator.d.ts +3 -0
- package/dist/annotator.d.ts.map +1 -0
- package/dist/capture/color-sanitizer.d.ts +3 -0
- package/dist/capture/color-sanitizer.d.ts.map +1 -0
- package/dist/capture/dom-capture.d.ts +3 -0
- package/dist/capture/dom-capture.d.ts.map +1 -0
- package/dist/clipboard.d.ts +4 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/defaults.d.ts +6 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/download.d.ts +3 -0
- package/dist/download.d.ts.map +1 -0
- package/dist/export/compose.d.ts +3 -0
- package/dist/export/compose.d.ts.map +1 -0
- package/dist/geometry.d.ts +9 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/icons.d.ts +4 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/id.d.ts +2 -0
- package/dist/id.d.ts.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/page-annotation.css +1 -0
- package/dist/page-annotation.es.js +5574 -0
- package/dist/page-annotation.es.js.map +1 -0
- package/dist/page-annotation.iife.js +6 -0
- package/dist/page-annotation.iife.js.map +1 -0
- package/dist/render.d.ts +5 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/store.d.ts +23 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/types.d.ts +137 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Taimoor Qureshi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Page Annotation
|
|
2
|
+
|
|
3
|
+
Framework-neutral browser page annotation tools for collecting screenshot-backed feedback.
|
|
4
|
+
|
|
5
|
+
This package is currently in early development. The first integration target is an ASP.NET Core MVC admin workflow, but the package itself is plain TypeScript and does not depend on any server framework.
|
|
6
|
+
|
|
7
|
+
Documentation will live at [page-annotation.com](https://page-annotation.com).
|
|
8
|
+
|
|
9
|
+
## Goals
|
|
10
|
+
|
|
11
|
+
- Add an annotation overlay to any web application.
|
|
12
|
+
- Support simple tools: pen, eraser, text notes, rectangles, and arrows.
|
|
13
|
+
- Export, copy, or download a PNG screenshot with annotations in the browser.
|
|
14
|
+
- Tolerate modern app CSS colors during capture, including Tailwind's `oklab`/`oklch` output.
|
|
15
|
+
- Ship framework-neutral CSS with namespaced variables instead of depending on Tailwind, Bootstrap, or app styles.
|
|
16
|
+
- Let host applications decide whether and where exported screenshots are uploaded.
|
|
17
|
+
- Avoid telemetry and network calls by default.
|
|
18
|
+
|
|
19
|
+
## Local Development
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install
|
|
23
|
+
npm run build
|
|
24
|
+
npm test
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install page-annotation
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { createAnnotator } from "page-annotation";
|
|
35
|
+
import "page-annotation/styles.css";
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Host-Owned Trigger
|
|
39
|
+
|
|
40
|
+
Apps can skip the package-owned launcher and open annotation mode from their own UI:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
const annotator = createAnnotator({ launcher: false });
|
|
44
|
+
|
|
45
|
+
document.querySelector("#feedback")?.addEventListener("click", () => {
|
|
46
|
+
annotator.open();
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Screenshots can contain sensitive application data. The package never uploads screenshots automatically; host applications own authorization, consent, storage, retention, and auditing.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"annotator.d.ts","sourceRoot":"","sources":["../src/annotator.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAKV,aAAa,EAGb,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAcjB,wBAAgB,eAAe,CAAC,OAAO,GAAE,oBAAyB,GAAG,aAAa,CAEjF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color-sanitizer.d.ts","sourceRoot":"","sources":["../../src/capture/color-sanitizer.ts"],"names":[],"mappings":"AA0BA,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEvE;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAUjE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-capture.d.ts","sourceRoot":"","sources":["../../src/capture/dom-capture.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7D,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CA+BhH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../src/clipboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,wBAAgB,wBAAwB,IAAI,OAAO,CAMlD;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AnnotationTool, PageAnnotatorLabels } from "./types";
|
|
2
|
+
export declare const defaultTools: AnnotationTool[];
|
|
3
|
+
export declare const defaultLabels: PageAnnotatorLabels;
|
|
4
|
+
export declare const defaultColor = "#ef4444";
|
|
5
|
+
export declare const defaultStrokeWidth = 4;
|
|
6
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnE,eAAO,MAAM,YAAY,EAAE,cAAc,EAAoD,CAAC;AAE9F,eAAO,MAAM,aAAa,EAAE,mBAoB3B,CAAC;AAEF,eAAO,MAAM,YAAY,YAAY,CAAC;AAEtC,eAAO,MAAM,kBAAkB,IAAI,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../src/download.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,wBAAgB,cAAc,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAS7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/export/compose.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD,wBAAsB,UAAU,CAAC,UAAU,EAAE,iBAAiB,EAAE,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB9G"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AnnotationItem, AnnotationPoint } from "./types";
|
|
2
|
+
export declare function normalizeRectangle(x: number, y: number, width: number, height: number): {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
};
|
|
8
|
+
export declare function hitTest(annotation: AnnotationItem, point: AnnotationPoint, tolerance?: number): boolean;
|
|
9
|
+
//# sourceMappingURL=geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../src/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/D,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;;;;EASrF;AAED,wBAAgB,OAAO,CAAC,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,SAAS,SAAK,GAAG,OAAO,CA4BnG"}
|
package/dist/icons.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type ToolbarIconName = "arrow" | "close" | "copy" | "download" | "eraser" | "move" | "pen" | "rectangle" | "redo" | "send" | "text" | "trash" | "undo";
|
|
2
|
+
export declare function iconSvg(name: ToolbarIconName): string;
|
|
3
|
+
export declare function createIcon(name: ToolbarIconName): HTMLSpanElement;
|
|
4
|
+
//# sourceMappingURL=icons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../src/icons.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,OAAO,GACP,OAAO,GACP,MAAM,GACN,UAAU,GACV,QAAQ,GACR,MAAM,GACN,KAAK,GACL,WAAW,GACX,MAAM,GACN,MAAM,GACN,MAAM,GACN,OAAO,GACP,MAAM,CAAC;AAkEX,wBAAgB,OAAO,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAErD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,CAKjE"}
|
package/dist/id.d.ts
ADDED
package/dist/id.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../src/id.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,MAAM,SAAe,GAAG,MAAM,CAG1D"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "./styles.css";
|
|
2
|
+
export { createAnnotator } from "./annotator";
|
|
3
|
+
export { canCopyExportToClipboard, copyExportToClipboard } from "./clipboard";
|
|
4
|
+
export { downloadExport } from "./download";
|
|
5
|
+
export { iconSvg } from "./icons";
|
|
6
|
+
export { AnnotationStore } from "./store";
|
|
7
|
+
export type { AnnotationDocument, AnnotationExport, AnnotationItem, AnnotationPoint, AnnotationTool, CaptureOptions, CaptureProvider, PageAnnotator, PageAnnotatorLabels, PageAnnotatorLauncherOffset, PageAnnotatorLauncherOptions, PageAnnotatorLauncherPosition, PageAnnotatorOptions } from "./types";
|
|
8
|
+
export type { ToolbarIconName } from "./icons";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAEtB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,aAAa,EACb,mBAAmB,EACnB,2BAA2B,EAC3B,4BAA4B,EAC5B,6BAA6B,EAC7B,oBAAoB,EACrB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--pa-color-primary: #2563eb;--pa-color-primary-strong: #1d4ed8;--pa-color-danger: #dc2626;--pa-color-text: #0f172a;--pa-color-muted: #64748b;--pa-color-border: #cbd5e1;--pa-color-surface: #ffffff;--pa-color-surface-muted: #f8fafc;--pa-color-primary-soft: #dbeafe;--pa-color-primary-border: #93c5fd;--pa-color-panel: rgba(255, 255, 255, .96);--pa-shadow: 0 18px 42px rgb(15 23 42 / .18);--pa-radius: 8px;--pa-z-index: 2147483000}.pa-launcher{position:fixed;right:auto;bottom:auto;--pa-launcher-offset-x: 18px;--pa-launcher-offset-y: 18px;z-index:calc(var(--pa-z-index) - 1);display:inline-flex;align-items:center;justify-content:center;min-height:42px;border:1px solid var(--pa-color-border);border-radius:var(--pa-radius);background:var(--pa-color-surface);color:var(--pa-color-text);box-shadow:var(--pa-shadow);cursor:pointer;font:600 14px/1 ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;padding:0 14px}.pa-launcher[data-position=bottom-right]{right:var(--pa-launcher-offset-x);bottom:var(--pa-launcher-offset-y)}.pa-launcher[data-position=bottom-left]{left:var(--pa-launcher-offset-x);bottom:var(--pa-launcher-offset-y)}.pa-launcher[data-position=top-right]{top:var(--pa-launcher-offset-y);right:var(--pa-launcher-offset-x)}.pa-launcher[data-position=top-left]{top:var(--pa-launcher-offset-y);left:var(--pa-launcher-offset-x)}.pa-launcher:hover{background:var(--pa-color-surface-muted)}.pa-overlay{position:fixed;inset:0;z-index:var(--pa-z-index);display:none;cursor:crosshair;touch-action:none}.pa-overlay[data-open=true]{display:block}.pa-canvas{position:absolute;inset:0;width:100vw;height:100vh}.pa-toolbar{position:absolute;top:16px;left:50%;display:flex;max-width:calc(100vw - 24px);align-items:center;gap:6px;overflow-x:auto;border:1px solid var(--pa-color-border);border-radius:var(--pa-radius);background:var(--pa-color-panel);box-shadow:var(--pa-shadow);cursor:default;padding:8px;transform:translate(-50%)}.pa-button,.pa-toolbar-handle,.pa-color,.pa-range{flex:0 0 auto}.pa-icon-wrap{display:inline-flex;width:18px;height:18px;align-items:center;justify-content:center;pointer-events:none}.pa-icon{width:18px;height:18px;fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:2}.pa-toolbar-handle{display:inline-flex;width:38px;height:36px;align-items:center;justify-content:center;border:1px dashed var(--pa-color-border);border-radius:6px;background:var(--pa-color-surface-muted);color:var(--pa-color-muted);cursor:grab;padding:0;user-select:none}.pa-toolbar-handle:active{cursor:grabbing}.pa-button{display:inline-flex;min-width:40px;height:36px;align-items:center;justify-content:center;gap:7px;border:1px solid transparent;border-radius:6px;background:transparent;color:var(--pa-color-text);cursor:pointer;font:600 13px/1 ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;padding:0 10px}.pa-button[data-icon-only=true]{width:40px;padding:0}.pa-button[data-show-label=true]{min-width:auto}.pa-button-text{white-space:nowrap}.pa-button:hover{background:var(--pa-color-surface-muted)}.pa-button[aria-pressed=true]{border-color:var(--pa-color-primary-border);background:var(--pa-color-primary-soft);color:var(--pa-color-primary-strong)}.pa-button:disabled{cursor:not-allowed;opacity:.45}.pa-button[data-kind=danger]{color:var(--pa-color-danger)}.pa-color{width:36px;height:36px;border:1px solid var(--pa-color-border);border-radius:6px;background:var(--pa-color-surface);cursor:pointer;padding:4px}.pa-range{width:86px;accent-color:var(--pa-color-primary)}.pa-text-popover{position:fixed;z-index:calc(var(--pa-z-index) + 1);border:2px solid var(--pa-color-primary);border-radius:var(--pa-radius);background:var(--pa-color-surface);box-shadow:var(--pa-shadow);cursor:default;padding:8px}.pa-text-editor{display:block;width:min(240px,calc(100vw - 40px));min-height:72px;border:1px solid var(--pa-color-border);border-radius:6px;background:var(--pa-color-surface);color:var(--pa-color-text);font:600 18px/1.35 ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;padding:8px 10px;resize:none}.pa-text-actions{display:flex;justify-content:flex-end;gap:6px;margin-top:8px}.pa-text-action{display:inline-flex;height:32px;align-items:center;justify-content:center;border:1px solid var(--pa-color-border);border-radius:6px;background:var(--pa-color-surface);color:var(--pa-color-text);cursor:pointer;font:600 12px/1 ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;padding:0 10px}.pa-text-action-primary{border-color:var(--pa-color-primary);background:var(--pa-color-primary);color:#fff}
|