@loupekit/shared 0.1.0 → 0.2.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 ADDED
@@ -0,0 +1,66 @@
1
+ # @loupekit/shared
2
+
3
+ **Canonical TypeScript types and pure helpers shared across [Loupe](https://github.com/mohamed-ashraf-elsaed/loupe)** —
4
+ the SDK, backend API, dashboard, and MCP server all import from here so a comment means the
5
+ same thing everywhere in the loop.
6
+
7
+ This package has no runtime dependencies. It's the contract layer, not a feature.
8
+
9
+ ---
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm i @loupekit/shared
15
+ ```
16
+
17
+ > Also mirrored to **GitHub Packages** as `@mohamed-ashraf-elsaed/shared`. To install from
18
+ > there, add `@mohamed-ashraf-elsaed:registry=https://npm.pkg.github.com` to your `.npmrc`.
19
+
20
+ ## Types
21
+
22
+ - **`Comment`** — a piece of visual feedback: body, author, status, the element `anchor`,
23
+ the captured `context` (HTML + styles), screenshot URL, and — for free-region comments —
24
+ `kind: "region"` plus a `region` rectangle.
25
+ - **`Anchor`** — the multi-signal element fingerprint (tag, CSS path, XPath, testid, text,
26
+ attributes, nth-of-type, bounding rect, viewport) used to re-locate an element after a
27
+ redeploy.
28
+ - **`ElementContext`** — the target's `outerHTML` and a curated slice of computed styles.
29
+ - **`RegionRect`** — a free-region rectangle in document coordinates, with optional
30
+ element-relative fractions (`rel`) so regions track responsive reflow.
31
+ - **`LoupeUser`**, **`CommentStatus`**, **`CommentKind`** — identity and workflow enums.
32
+
33
+ ## Helper: `normalizeUrl(input)`
34
+
35
+ Normalizes a page URL so comments don't fragment across tracking/volatile query params.
36
+
37
+ ```ts
38
+ import { normalizeUrl } from "@loupekit/shared";
39
+
40
+ normalizeUrl("/checkout?utm_source=x&gclid=123&step=2");
41
+ // → "/checkout?step=2"
42
+ ```
43
+
44
+ It:
45
+
46
+ - strips `utm_*`, click ids (`gclid`, `fbclid`, `msclkid`, …), and Loupe's own dev params
47
+ (`api`, `key`),
48
+ - sorts the remaining params for stability,
49
+ - drops trailing slashes.
50
+
51
+ So a comment on `/checkout?utm_source=x` and one on `/checkout` land on the **same** page and
52
+ don't split into two buckets.
53
+
54
+ ## Usage notes
55
+
56
+ - ESM-only, ships compiled JS + `.d.ts` (`main`/`types` → `dist`).
57
+ - Node packages in the monorepo import the compiled JS; browser packages import the types.
58
+
59
+ ## Related packages
60
+
61
+ - [`@loupekit/sdk`](https://www.npmjs.com/package/@loupekit/sdk) — the embeddable widget.
62
+ - [`@loupekit/mcp`](https://www.npmjs.com/package/@loupekit/mcp) — the MCP server for Claude Code.
63
+
64
+ ## License
65
+
66
+ MIT © [Mohamed Ashraf Elsaed](https://github.com/mohamed-ashraf-elsaed)
package/dist/index.d.ts CHANGED
@@ -27,6 +27,31 @@ export interface ElementContext {
27
27
  html: string;
28
28
  styles: Record<string, string>;
29
29
  }
30
+ /** A rectangle in **document** coordinates (page px, scroll included). */
31
+ export interface RegionRect {
32
+ x: number;
33
+ y: number;
34
+ w: number;
35
+ h: number;
36
+ /**
37
+ * The same rectangle expressed as fractions of the region's anchor element
38
+ * (the element under the region's center). Present when an anchor element was
39
+ * found. Used to re-place the region across responsive reflow / different
40
+ * viewports — absolute x/y/w/h are only a fallback when the anchor is gone.
41
+ */
42
+ rel?: {
43
+ fx: number;
44
+ fy: number;
45
+ fw: number;
46
+ fh: number;
47
+ };
48
+ }
49
+ /**
50
+ * How a comment is pinned to the page:
51
+ * - "element" (default) → anchored to a DOM element via its fingerprint.
52
+ * - "region" → a free-form rectangle the user dragged out; carries `region`.
53
+ */
54
+ export type CommentKind = "element" | "region";
30
55
  export interface Comment {
31
56
  id: string;
32
57
  projectKey: string;
@@ -34,12 +59,16 @@ export interface Comment {
34
59
  author: LoupeUser;
35
60
  body: string;
36
61
  status: CommentStatus;
62
+ /** Defaults to "element" when absent (back-compat with pre-region comments). */
63
+ kind?: CommentKind;
37
64
  anchor: Anchor;
38
65
  context: ElementContext;
39
66
  offset: {
40
67
  x: number;
41
68
  y: number;
42
69
  };
70
+ /** Present for region comments: the dragged rectangle in document coords. */
71
+ region?: RegionRect;
43
72
  /** A URL (object storage) in server mode, or an inline data URL in offline mode. */
44
73
  screenshot?: string;
45
74
  createdAt: string;
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@loupekit/shared",
3
- "version": "0.1.0",
4
- "description": "Loupe shared types + helpers (normalizeUrl).",
3
+ "version": "0.2.0",
4
+ "description": "Canonical TypeScript types + helpers (normalizeUrl) shared across the Loupe visual-feedback platform.",
5
+ "keywords": ["loupe", "types", "shared", "visual-feedback", "annotation", "normalize-url", "typescript"],
5
6
  "license": "MIT",
6
7
  "repository": { "type": "git", "url": "https://github.com/mohamed-ashraf-elsaed/loupe.git", "directory": "packages/shared" },
7
8
  "homepage": "https://mohamed-ashraf-elsaed.github.io/loupe/",