@tonytangdev/pin-point 0.2.2 → 0.2.3
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/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -122,6 +122,21 @@ var import_jsx_runtime3 = (
|
|
|
122
122
|
);
|
|
123
123
|
var POPOVER_OFFSET = 14;
|
|
124
124
|
var VIEWPORT_MARGIN = 8;
|
|
125
|
+
var KEYBOARD_HEIGHT_THRESHOLD = 150;
|
|
126
|
+
function useScrollIntoViewOnKeyboard(ref) {
|
|
127
|
+
(0, import_react3.useEffect)(() => {
|
|
128
|
+
const viewport = window.visualViewport;
|
|
129
|
+
if (!viewport) return;
|
|
130
|
+
const baselineHeight = viewport.height;
|
|
131
|
+
const handleResize = () => {
|
|
132
|
+
if (baselineHeight - viewport.height > KEYBOARD_HEIGHT_THRESHOLD && ref.current) {
|
|
133
|
+
ref.current.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
viewport.addEventListener("resize", handleResize);
|
|
137
|
+
return () => viewport.removeEventListener("resize", handleResize);
|
|
138
|
+
}, [ref]);
|
|
139
|
+
}
|
|
125
140
|
function CommentPopover(props) {
|
|
126
141
|
const { mode, top, left } = props;
|
|
127
142
|
const popoverRef = (0, import_react3.useRef)(null);
|
|
@@ -150,6 +165,7 @@ function CommentPopover(props) {
|
|
|
150
165
|
});
|
|
151
166
|
setSize({ width: w, height: h });
|
|
152
167
|
}, [top, left]);
|
|
168
|
+
useScrollIntoViewOnKeyboard(popoverRef);
|
|
153
169
|
const style = size ? {
|
|
154
170
|
top: `${placement.y === "bottom" ? top + POPOVER_OFFSET : top - POPOVER_OFFSET - size.height}px`,
|
|
155
171
|
left: `${placement.x === "right" ? left - POPOVER_OFFSET : left + POPOVER_OFFSET - size.width}px`
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/FeedbackOverlay.tsx","../src/components/AdminKeyModal.tsx","../src/components/ClickInterceptLayer.tsx","../src/components/CommentPopover.tsx","../src/components/FeedbackToolbar.tsx","../src/components/PinMarker.tsx","../src/components/ShareLinkButton.tsx","../src/hooks/useAuth.ts","../src/utils/resolveAnchor.ts","../src/utils/restorePosition.ts"],"sourcesContent":["export { FeedbackOverlay } from \"./FeedbackOverlay\";\nexport type { FeedbackOverlayProps, PinComment } from \"./types\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { AdminKeyModal } from \"./components/AdminKeyModal\";\nimport { ClickInterceptLayer } from \"./components/ClickInterceptLayer\";\nimport { CommentPopover } from \"./components/CommentPopover\";\nimport { FeedbackToolbar } from \"./components/FeedbackToolbar\";\nimport { PinMarker } from \"./components/PinMarker\";\nimport { ShareLinkButton } from \"./components/ShareLinkButton\";\nimport { useAuth } from \"./hooks/useAuth\";\nimport type { FeedbackOverlayProps, PendingPin, PinComment } from \"./types\";\nimport { resolveAnchor } from \"./utils/resolveAnchor\";\nimport { restorePosition } from \"./utils/restorePosition\";\n\nexport function FeedbackOverlay({\n\tonCommentCreate,\n\tonCommentsFetch,\n\tonCommentDelete,\n\tonCommentUpdate,\n\tonAdminValidate,\n\tonShareLinkCreate,\n\tchildren,\n}: FeedbackOverlayProps) {\n\tconst { auth, authHeaders, setAdminKey } = useAuth();\n\tconst [comments, setComments] = useState<PinComment[]>([]);\n\tconst [pendingPin, setPendingPin] = useState<PendingPin | null>(null);\n\tconst [expandedPinId, setExpandedPinId] = useState<string | null>(null);\n\tconst [fetchError, setFetchError] = useState<string | null>(null);\n\tconst [pinMode, setPinMode] = useState(false);\n\tconst [adminModalOpen, setAdminModalOpen] = useState(false);\n\tconst hasFetched = useRef(false);\n\n\tuseEffect(() => {\n\t\tif (hasFetched.current) return;\n\t\thasFetched.current = true;\n\n\t\tonCommentsFetch(authHeaders)\n\t\t\t.then((data) => setComments([...data]))\n\t\t\t.catch(() => setFetchError(\"Couldn't load comments.\"));\n\t}, [onCommentsFetch, authHeaders]);\n\n\tconst handleClick = useCallback((clientX: number, clientY: number) => {\n\t\tsetExpandedPinId(null);\n\n\t\tconst interceptLayer = document.querySelector(\n\t\t\t\".pp-intercept\",\n\t\t) as HTMLElement;\n\t\tif (interceptLayer) interceptLayer.style.pointerEvents = \"none\";\n\t\tconst elementBelow = document.elementFromPoint(clientX, clientY);\n\t\tif (interceptLayer) interceptLayer.style.pointerEvents = \"\";\n\n\t\tif (!elementBelow) return;\n\n\t\tconst anchor = resolveAnchor(elementBelow, clientX, clientY);\n\t\tsetPendingPin({\n\t\t\tx: clientX + window.scrollX,\n\t\t\ty: clientY + window.scrollY,\n\t\t\tanchor,\n\t\t});\n\t}, []);\n\n\tconst handleSubmit = useCallback(\n\t\tasync (content: string) => {\n\t\t\tif (!pendingPin) return;\n\n\t\t\tconst comment: PinComment = {\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\turl: window.location.pathname,\n\t\t\t\tcontent,\n\t\t\t\tanchor: pendingPin.anchor,\n\t\t\t\tviewport: { width: window.innerWidth },\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t};\n\n\t\t\tawait onCommentCreate(comment, authHeaders);\n\t\t\tsetComments((prev) => [...prev, comment]);\n\t\t\tsetPendingPin(null);\n\t\t\tsetPinMode(false);\n\t\t},\n\t\t[pendingPin, onCommentCreate, authHeaders],\n\t);\n\n\tconst handleCancel = useCallback(() => {\n\t\tsetPendingPin(null);\n\t}, []);\n\n\tconst handleDelete = useCallback(\n\t\tasync (id: string) => {\n\t\t\tif (!onCommentDelete) return;\n\t\t\tawait onCommentDelete(id, authHeaders);\n\t\t\tsetComments((prev) => prev.filter((c) => c.id !== id));\n\t\t\tsetExpandedPinId(null);\n\t\t},\n\t\t[onCommentDelete, authHeaders],\n\t);\n\n\tconst handleUpdate = useCallback(\n\t\tasync (id: string, content: string) => {\n\t\t\tif (!onCommentUpdate) return;\n\t\t\tconst updated = await onCommentUpdate(id, content, authHeaders);\n\t\t\tsetComments((prev) => prev.map((c) => (c.id === id ? updated : c)));\n\t\t},\n\t\t[onCommentUpdate, authHeaders],\n\t);\n\n\tconst handlePinModeToggle = useCallback(() => {\n\t\tsetPinMode((prev) => {\n\t\t\tconst next = !prev;\n\t\t\tif (!next) setPendingPin(null);\n\t\t\treturn next;\n\t\t});\n\t}, []);\n\n\tconst handleAdminValidate = useCallback(\n\t\tasync (secret: string) => {\n\t\t\tif (!onAdminValidate) return false;\n\t\t\treturn onAdminValidate(secret);\n\t\t},\n\t\t[onAdminValidate],\n\t);\n\n\tconst handleAdminSuccess = useCallback(\n\t\t(secret: string) => {\n\t\t\tsetAdminKey(secret);\n\t\t\tsetAdminModalOpen(false);\n\t\t},\n\t\t[setAdminKey],\n\t);\n\n\tconst handleShareCreate = useCallback(\n\t\tasync (label?: string, ttl?: number) => {\n\t\t\tif (!onShareLinkCreate) throw new Error(\"onShareLinkCreate not provided\");\n\t\t\treturn onShareLinkCreate(label, ttl, authHeaders);\n\t\t},\n\t\t[onShareLinkCreate, authHeaders],\n\t);\n\n\treturn (\n\t\t<div data-pin-point=\"\">\n\t\t\t{children}\n\t\t\t{pinMode && <ClickInterceptLayer onClick={handleClick} />}\n\n\t\t\t{comments.map((comment, index) => {\n\t\t\t\tconst pos = restorePosition(comment.anchor);\n\t\t\t\tif (!pos) return null;\n\n\t\t\t\treturn (\n\t\t\t\t\t<PinMarker\n\t\t\t\t\t\tkey={comment.id}\n\t\t\t\t\t\tnumber={index + 1}\n\t\t\t\t\t\ttop={pos.top}\n\t\t\t\t\t\tleft={pos.left}\n\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\tsetExpandedPinId(expandedPinId === comment.id ? null : comment.id)\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t})}\n\n\t\t\t{expandedPinId &&\n\t\t\t\t(() => {\n\t\t\t\t\tconst comment = comments.find((c) => c.id === expandedPinId);\n\t\t\t\t\tif (!comment) return null;\n\t\t\t\t\tconst pos = restorePosition(comment.anchor);\n\t\t\t\t\tif (!pos) return null;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<CommentPopover\n\t\t\t\t\t\t\tmode=\"read\"\n\t\t\t\t\t\t\tcontent={comment.content}\n\t\t\t\t\t\t\tcreatedAt={comment.createdAt}\n\t\t\t\t\t\t\tviewportWidth={comment.viewport.width}\n\t\t\t\t\t\t\ttop={pos.top}\n\t\t\t\t\t\t\tleft={pos.left}\n\t\t\t\t\t\t\tonDelete={\n\t\t\t\t\t\t\t\tonCommentDelete\n\t\t\t\t\t\t\t\t\t? async () => handleDelete(comment.id)\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonUpdate={\n\t\t\t\t\t\t\t\tonCommentUpdate\n\t\t\t\t\t\t\t\t\t? async (content: string) => {\n\t\t\t\t\t\t\t\t\t\t\tawait handleUpdate(comment.id, content);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})()}\n\n\t\t\t{pendingPin && (\n\t\t\t\t<>\n\t\t\t\t\t<PinMarker\n\t\t\t\t\t\tnumber={comments.length + 1}\n\t\t\t\t\t\ttop={pendingPin.y}\n\t\t\t\t\t\tleft={pendingPin.x}\n\t\t\t\t\t\tonClick={() => {}}\n\t\t\t\t\t/>\n\t\t\t\t\t<CommentPopover\n\t\t\t\t\t\tmode=\"create\"\n\t\t\t\t\t\ttop={pendingPin.y}\n\t\t\t\t\t\tleft={pendingPin.x}\n\t\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\t\tonCancel={handleCancel}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t)}\n\n\t\t\t<FeedbackToolbar\n\t\t\t\tauth={auth}\n\t\t\t\tcommentCount={comments.length}\n\t\t\t\tpinModeActive={pinMode}\n\t\t\t\tonPinModeToggle={handlePinModeToggle}\n\t\t\t\tonAdminKeyOpen={() => setAdminModalOpen(true)}\n\t\t\t\tshareButton={\n\t\t\t\t\tauth.role === \"admin\" && onShareLinkCreate ? (\n\t\t\t\t\t\t<ShareLinkButton onCreate={handleShareCreate} />\n\t\t\t\t\t) : undefined\n\t\t\t\t}\n\t\t\t\terror={fetchError ?? undefined}\n\t\t\t/>\n\n\t\t\t{adminModalOpen && (\n\t\t\t\t<AdminKeyModal\n\t\t\t\t\tonValidate={handleAdminValidate}\n\t\t\t\t\tonSuccess={handleAdminSuccess}\n\t\t\t\t\tonClose={() => setAdminModalOpen(false)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { useState } from \"react\";\n\ntype Props = {\n\tonValidate: (secret: string) => Promise<boolean>;\n\tonSuccess: (secret: string) => void;\n\tonClose: () => void;\n};\n\nexport function AdminKeyModal({ onValidate, onSuccess, onClose }: Props) {\n\tconst [value, setValue] = useState(\"\");\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [busy, setBusy] = useState(false);\n\n\tconst handleSubmit = async () => {\n\t\tsetBusy(true);\n\t\tsetError(null);\n\t\ttry {\n\t\t\tconst ok = await onValidate(value);\n\t\t\tif (ok) {\n\t\t\t\tonSuccess(value);\n\t\t\t} else {\n\t\t\t\tsetError(\"Invalid admin key\");\n\t\t\t}\n\t\t} catch {\n\t\t\tsetError(\"Could not reach server\");\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: backdrop click dismissal, Cancel button and Escape are primary dismissal paths\n\t\t// biome-ignore lint/a11y/noStaticElementInteractions: backdrop is a visual scrim, inner dialog has role\n\t\t<div className=\"pp-modal-backdrop\" onClick={onClose}>\n\t\t\t{/* biome-ignore lint/a11y/useKeyWithClickEvents: stopPropagation only, not an interactive element */}\n\t\t\t<div\n\t\t\t\tclassName=\"pp-modal\"\n\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\trole=\"dialog\"\n\t\t\t\taria-modal=\"true\"\n\t\t\t>\n\t\t\t\t<h3>Enter admin key</h3>\n\t\t\t\t<input\n\t\t\t\t\ttype=\"password\"\n\t\t\t\t\tplaceholder=\"Admin key\"\n\t\t\t\t\tvalue={value}\n\t\t\t\t\tonChange={(e) => setValue(e.target.value)}\n\t\t\t\t\tdisabled={busy}\n\t\t\t\t/>\n\t\t\t\t{error && <div className=\"pp-modal-error\">{error}</div>}\n\t\t\t\t<div className=\"pp-modal-actions\">\n\t\t\t\t\t<button type=\"button\" onClick={onClose} disabled={busy}>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleSubmit}\n\t\t\t\t\t\tdisabled={busy || !value}\n\t\t\t\t\t>\n\t\t\t\t\t\tSave\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { useCallback, useRef } from \"react\";\n\ntype ClickInterceptLayerProps = {\n\tonClick: (clientX: number, clientY: number) => void;\n};\n\nexport function ClickInterceptLayer({ onClick }: ClickInterceptLayerProps) {\n\tconst lastClickTime = useRef(0);\n\n\tconst handleClick = useCallback(\n\t\t(e: React.MouseEvent) => {\n\t\t\tconst now = Date.now();\n\t\t\tif (now - lastClickTime.current < 300) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlastClickTime.current = now;\n\t\t\tonClick(e.clientX, e.clientY);\n\t\t},\n\t\t[onClick],\n\t);\n\n\treturn (\n\t\t// biome-ignore lint/a11y/noStaticElementInteractions: click-only overlay for pin placement\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: click-only overlay for pin placement\n\t\t<div className=\"pp-intercept\" onClick={handleClick} />\n\t);\n}\n","import type React from \"react\";\nimport { useEffect, useLayoutEffect, useRef, useState } from \"react\";\n\ntype ReadProps = {\n\tmode: \"read\";\n\tcontent: string;\n\tcreatedAt: string;\n\tviewportWidth: number;\n\ttop: number;\n\tleft: number;\n\tonDelete?: () => Promise<void>;\n\tonUpdate?: (content: string) => Promise<void>;\n\tonSubmit?: never;\n\tonCancel?: never;\n};\n\ntype CreateProps = {\n\tmode: \"create\";\n\ttop: number;\n\tleft: number;\n\tonSubmit: (content: string) => Promise<void>;\n\tonCancel: () => void;\n\tcontent?: never;\n\tcreatedAt?: never;\n\tviewportWidth?: never;\n};\n\ntype CommentPopoverProps = ReadProps | CreateProps;\n\ntype Placement = { x: \"right\" | \"left\"; y: \"bottom\" | \"top\" };\n\nconst POPOVER_OFFSET = 14;\nconst VIEWPORT_MARGIN = 8;\n\nexport function CommentPopover(props: CommentPopoverProps) {\n\tconst { mode, top, left } = props;\n\tconst popoverRef = useRef<HTMLDivElement>(null);\n\tconst [placement, setPlacement] = useState<Placement>({\n\t\tx: \"right\",\n\t\ty: \"bottom\",\n\t});\n\tconst [size, setSize] = useState<{ width: number; height: number } | null>(\n\t\tnull,\n\t);\n\n\tuseLayoutEffect(() => {\n\t\tconst el = popoverRef.current;\n\t\tif (!el) return;\n\t\tconst rect = el.getBoundingClientRect();\n\t\tconst w = rect.width;\n\t\tconst h = rect.height;\n\n\t\tconst pinViewX = left - window.scrollX;\n\t\tconst pinViewY = top - window.scrollY;\n\n\t\tconst fitsRight =\n\t\t\tpinViewX - POPOVER_OFFSET + w + VIEWPORT_MARGIN <= window.innerWidth;\n\t\tconst fitsLeft = pinViewX + POPOVER_OFFSET - w - VIEWPORT_MARGIN >= 0;\n\t\tconst fitsBottom =\n\t\t\tpinViewY + POPOVER_OFFSET + h + VIEWPORT_MARGIN <= window.innerHeight;\n\t\tconst fitsTop = pinViewY - POPOVER_OFFSET - h - VIEWPORT_MARGIN >= 0;\n\n\t\tsetPlacement({\n\t\t\tx: fitsRight ? \"right\" : fitsLeft ? \"left\" : \"right\",\n\t\t\ty: fitsBottom ? \"bottom\" : fitsTop ? \"top\" : \"bottom\",\n\t\t});\n\t\tsetSize({ width: w, height: h });\n\t}, [top, left]);\n\n\tconst style: React.CSSProperties = size\n\t\t? {\n\t\t\t\ttop: `${\n\t\t\t\t\tplacement.y === \"bottom\"\n\t\t\t\t\t\t? top + POPOVER_OFFSET\n\t\t\t\t\t\t: top - POPOVER_OFFSET - size.height\n\t\t\t\t}px`,\n\t\t\t\tleft: `${\n\t\t\t\t\tplacement.x === \"right\"\n\t\t\t\t\t\t? left - POPOVER_OFFSET\n\t\t\t\t\t\t: left + POPOVER_OFFSET - size.width\n\t\t\t\t}px`,\n\t\t\t}\n\t\t: {\n\t\t\t\ttop: `${top + POPOVER_OFFSET}px`,\n\t\t\t\tleft: `${left - POPOVER_OFFSET}px`,\n\t\t\t\tvisibility: \"hidden\",\n\t\t\t};\n\n\treturn (\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: stopPropagation only, not interactive\n\t\t<div\n\t\t\tref={popoverRef}\n\t\t\tclassName=\"pp-popover\"\n\t\t\tdata-placement-x={placement.x}\n\t\t\tdata-placement-y={placement.y}\n\t\t\tstyle={style}\n\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\trole=\"dialog\"\n\t\t>\n\t\t\t<div className=\"pp-popover-arrow\" />\n\t\t\t{mode === \"read\" ? (\n\t\t\t\t<ReadContent\n\t\t\t\t\tcontent={props.content}\n\t\t\t\t\tcreatedAt={props.createdAt}\n\t\t\t\t\tviewportWidth={props.viewportWidth}\n\t\t\t\t\tonDelete={props.onDelete}\n\t\t\t\t\tonUpdate={props.onUpdate}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<CreateContent onSubmit={props.onSubmit} onCancel={props.onCancel} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction ReadContent({\n\tcontent,\n\tcreatedAt,\n\tviewportWidth,\n\tonDelete,\n\tonUpdate,\n}: {\n\tcontent: string;\n\tcreatedAt: string;\n\tviewportWidth: number;\n\tonDelete?: () => Promise<void>;\n\tonUpdate?: (content: string) => Promise<void>;\n}) {\n\tconst [isConfirmingDelete, setIsConfirmingDelete] = useState(false);\n\tconst [isEditing, setIsEditing] = useState(false);\n\tconst [editContent, setEditContent] = useState(content);\n\tconst [saving, setSaving] = useState(false);\n\tconst [deleting, setDeleting] = useState(false);\n\tconst [deleteError, setDeleteError] = useState(false);\n\tconst [editError, setEditError] = useState(false);\n\n\tuseEffect(() => setEditContent(content), [content]);\n\n\tconst date = new Date(createdAt).toLocaleDateString(undefined, {\n\t\tmonth: \"short\",\n\t\tday: \"numeric\",\n\t\tyear: \"numeric\",\n\t});\n\n\tif (isEditing) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<textarea\n\t\t\t\t\tclassName=\"pp-popover-textarea\"\n\t\t\t\t\tvalue={editContent}\n\t\t\t\t\tonChange={(e) => setEditContent(e.target.value)}\n\t\t\t\t/>\n\t\t\t\t<div className=\"pp-popover-actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetIsEditing(false);\n\t\t\t\t\t\t\tsetEditContent(content);\n\t\t\t\t\t\t\tsetEditError(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--submit\"\n\t\t\t\t\t\tdisabled={editContent.trim().length === 0 || saving}\n\t\t\t\t\t\tonClick={async () => {\n\t\t\t\t\t\t\tsetSaving(true);\n\t\t\t\t\t\t\tsetEditError(false);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait onUpdate?.(editContent);\n\t\t\t\t\t\t\t\tsetIsEditing(false);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tsetEditError(true);\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tsetSaving(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tSave\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t{editError && (\n\t\t\t\t\t<div className=\"pp-popover-error\">Couldn't save. Try again.</div>\n\t\t\t\t)}\n\t\t\t</>\n\t\t);\n\t}\n\n\tif (isConfirmingDelete) {\n\t\treturn (\n\t\t\t<div className=\"pp-delete-confirm\">\n\t\t\t\t<div className=\"pp-delete-confirm-icon\">\n\t\t\t\t\t<svg\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\twidth=\"20\"\n\t\t\t\t\t\theight=\"20\"\n\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t\t\t\t<line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n\t\t\t\t\t\t<line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n\t\t\t\t\t</svg>\n\t\t\t\t</div>\n\t\t\t\t<p className=\"pp-delete-confirm-text\">Delete this comment?</p>\n\t\t\t\t{deleteError && (\n\t\t\t\t\t<div className=\"pp-popover-error\">Couldn't delete. Try again.</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"pp-delete-confirm-actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\t\tdisabled={deleting}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetIsConfirmingDelete(false);\n\t\t\t\t\t\t\tsetDeleteError(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--danger\"\n\t\t\t\t\t\tdisabled={deleting}\n\t\t\t\t\t\tonClick={async () => {\n\t\t\t\t\t\t\tsetDeleting(true);\n\t\t\t\t\t\t\tsetDeleteError(false);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait onDelete?.();\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tsetDeleteError(true);\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tsetDeleting(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{deleting ? \"Deleting...\" : \"Delete\"}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"pp-popover-content\">{content}</div>\n\t\t\t<div className=\"pp-popover-footer\">\n\t\t\t\t<div className=\"pp-popover-meta\">\n\t\t\t\t\t{date} · {viewportWidth}px viewport\n\t\t\t\t</div>\n\t\t\t\t{(onDelete || onUpdate) && (\n\t\t\t\t\t<div className=\"pp-popover-actions-row\">\n\t\t\t\t\t\t{onUpdate && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"pp-action-btn\"\n\t\t\t\t\t\t\t\taria-label=\"Edit\"\n\t\t\t\t\t\t\t\tonClick={() => setIsEditing(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\twidth=\"13\"\n\t\t\t\t\t\t\t\t\theight=\"13\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path d=\"M17 3a2.83 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z\" />\n\t\t\t\t\t\t\t\t\t<path d=\"m15 5 4 4\" />\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onDelete && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"pp-action-btn pp-action-btn--danger\"\n\t\t\t\t\t\t\t\taria-label=\"Delete\"\n\t\t\t\t\t\t\t\tonClick={() => setIsConfirmingDelete(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\twidth=\"13\"\n\t\t\t\t\t\t\t\t\theight=\"13\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path d=\"M3 6h18\" />\n\t\t\t\t\t\t\t\t\t<path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\" />\n\t\t\t\t\t\t\t\t\t<path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\" />\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</>\n\t);\n}\n\nfunction CreateContent({\n\tonSubmit,\n\tonCancel,\n}: {\n\tonSubmit: (content: string) => Promise<void>;\n\tonCancel: () => void;\n}) {\n\tconst [text, setText] = useState(\"\");\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [submitting, setSubmitting] = useState(false);\n\n\tconst handleSubmit = async () => {\n\t\tsetError(null);\n\t\tsetSubmitting(true);\n\t\ttry {\n\t\t\tawait onSubmit(text);\n\t\t} catch {\n\t\t\tsetError(\"Couldn't save. Try again.\");\n\t\t} finally {\n\t\t\tsetSubmitting(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<textarea\n\t\t\t\tclassName=\"pp-popover-textarea\"\n\t\t\t\tplaceholder=\"Leave your feedback...\"\n\t\t\t\tvalue={text}\n\t\t\t\tonChange={(e) => setText(e.target.value)}\n\t\t\t/>\n\t\t\t<div className=\"pp-popover-actions\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\tonClick={onCancel}\n\t\t\t\t>\n\t\t\t\t\tCancel\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-btn pp-btn--submit\"\n\t\t\t\t\tonClick={handleSubmit}\n\t\t\t\t\tdisabled={text.trim().length === 0 || submitting}\n\t\t\t\t>\n\t\t\t\t\tSubmit\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{error && <div className=\"pp-popover-error\">{error}</div>}\n\t\t</>\n\t);\n}\n","import type React from \"react\";\nimport type { PinAuth } from \"../types\";\n\ntype FeedbackToolbarProps = {\n\tauth: PinAuth;\n\tcommentCount: number;\n\tpinModeActive: boolean;\n\tonPinModeToggle: () => void;\n\tonAdminKeyOpen: () => void;\n\tshareButton?: React.ReactNode;\n\terror?: string;\n};\n\nconst CommentIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"16\"\n\t\theight=\"16\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n\t</svg>\n);\n\nconst KeyIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"16\"\n\t\theight=\"16\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"m21 2-9.6 9.6\" />\n\t\t<circle cx=\"7.5\" cy=\"15.5\" r=\"5.5\" />\n\t\t<path d=\"m15.5 7.5 3 3\" />\n\t</svg>\n);\n\nexport function FeedbackToolbar({\n\tauth,\n\tcommentCount,\n\tpinModeActive,\n\tonPinModeToggle,\n\tonAdminKeyOpen,\n\tshareButton,\n\terror,\n}: FeedbackToolbarProps) {\n\tconst commentDisabled = auth.role === \"anonymous\";\n\tconst commentTitle = commentDisabled\n\t\t? \"Sign in with a share link to leave feedback\"\n\t\t: pinModeActive\n\t\t\t? \"Exit pin mode\"\n\t\t\t: \"Leave feedback\";\n\tconst showAdminKey = auth.role !== \"tokenHolder\";\n\n\treturn (\n\t\t<div className=\"pp-toolbar\">\n\t\t\t<div className=\"pp-toolbar-dot\" />\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"pp-toolbar-btn\"\n\t\t\t\tonClick={onPinModeToggle}\n\t\t\t\tdisabled={commentDisabled}\n\t\t\t\taria-pressed={pinModeActive}\n\t\t\t\taria-label=\"Leave feedback\"\n\t\t\t\ttitle={commentTitle}\n\t\t\t>\n\t\t\t\t<CommentIcon />\n\t\t\t</button>\n\t\t\t{showAdminKey && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-toolbar-btn\"\n\t\t\t\t\tonClick={onAdminKeyOpen}\n\t\t\t\t\taria-label=\"Enter admin key\"\n\t\t\t\t\ttitle=\"Enter admin key\"\n\t\t\t\t>\n\t\t\t\t\t<KeyIcon />\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{shareButton}\n\t\t\t{error ? (\n\t\t\t\t<span className=\"pp-toolbar-error\">{error}</span>\n\t\t\t) : (\n\t\t\t\t<span className=\"pp-toolbar-badge\">\n\t\t\t\t\t{commentCount} {commentCount === 1 ? \"comment\" : \"comments\"}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","type PinMarkerProps = {\n\tnumber: number;\n\ttop: number;\n\tleft: number;\n\tonClick: () => void;\n};\n\nexport function PinMarker({ number, top, left, onClick }: PinMarkerProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName=\"pp-pin\"\n\t\t\tstyle={{ top: `${top}px`, left: `${left}px` }}\n\t\t\tonClick={(e) => {\n\t\t\t\te.stopPropagation();\n\t\t\t\tonClick();\n\t\t\t}}\n\t\t>\n\t\t\t{number}\n\t\t</button>\n\t);\n}\n","import { useState } from \"react\";\n\ntype Props = {\n\tonCreate: (\n\t\tlabel?: string,\n\t\texpiresInHours?: number,\n\t) => Promise<{ tokenId: string }>;\n};\n\nconst ShareIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2.2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8\" />\n\t\t<polyline points=\"16 6 12 2 8 6\" />\n\t\t<line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"15\" />\n\t</svg>\n);\n\nconst CheckIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2.5\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t</svg>\n);\n\nexport function ShareLinkButton({ onCreate }: Props) {\n\tconst [busy, setBusy] = useState(false);\n\tconst [copied, setCopied] = useState(false);\n\n\tconst handleClick = async () => {\n\t\tsetBusy(true);\n\t\ttry {\n\t\t\tconst { tokenId } = await onCreate();\n\t\t\tconst url = new URL(window.location.href);\n\t\t\turl.searchParams.set(\"pin-token\", tokenId);\n\t\t\tawait navigator.clipboard.writeText(url.toString());\n\t\t\tsetCopied(true);\n\t\t\tsetTimeout(() => setCopied(false), 2000);\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className=\"pp-share-wrapper\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"pp-share-btn\"\n\t\t\t\tonClick={handleClick}\n\t\t\t\tdisabled={busy}\n\t\t\t\tdata-state={copied ? \"copied\" : busy ? \"busy\" : \"idle\"}\n\t\t\t>\n\t\t\t\t{copied ? <CheckIcon /> : <ShareIcon />}\n\t\t\t\t<span>{copied ? \"Link copied\" : \"Share for feedback\"}</span>\n\t\t\t</button>\n\t\t</div>\n\t);\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport type { AuthHeaders, PinAuth } from \"../types\";\n\nconst ADMIN_KEY_STORAGE = \"pin-admin-key\";\nconst TOKEN_QUERY_PARAM = \"pin-token\";\n\nconst resolveAuth = (): PinAuth => {\n\tif (typeof window === \"undefined\") return { role: \"anonymous\" };\n\n\tconst params = new URLSearchParams(window.location.search);\n\tconst token = params.get(TOKEN_QUERY_PARAM);\n\tif (token) return { role: \"tokenHolder\", token };\n\n\tconst adminKey = localStorage.getItem(ADMIN_KEY_STORAGE);\n\tif (adminKey) return { role: \"admin\", secret: adminKey };\n\n\treturn { role: \"anonymous\" };\n};\n\nconst computeHeaders = (auth: PinAuth): AuthHeaders => {\n\tswitch (auth.role) {\n\t\tcase \"tokenHolder\":\n\t\t\treturn { \"X-Pin-Token\": auth.token };\n\t\tcase \"admin\":\n\t\t\treturn { \"X-Pin-Admin\": auth.secret };\n\t\tcase \"anonymous\":\n\t\t\treturn {};\n\t}\n};\n\nexport const useAuth = () => {\n\tconst [auth, setAuth] = useState<PinAuth>(resolveAuth);\n\n\tuseEffect(() => {\n\t\tconst onPopState = () => setAuth(resolveAuth());\n\t\twindow.addEventListener(\"popstate\", onPopState);\n\t\treturn () => window.removeEventListener(\"popstate\", onPopState);\n\t}, []);\n\n\tconst setAdminKey = useCallback((secret: string) => {\n\t\tlocalStorage.setItem(ADMIN_KEY_STORAGE, secret);\n\t\tsetAuth(resolveAuth());\n\t}, []);\n\n\tconst clearAdminKey = useCallback(() => {\n\t\tlocalStorage.removeItem(ADMIN_KEY_STORAGE);\n\t\tsetAuth(resolveAuth());\n\t}, []);\n\n\treturn {\n\t\tauth,\n\t\tauthHeaders: computeHeaders(auth),\n\t\tsetAdminKey,\n\t\tclearAdminKey,\n\t};\n};\n","import type { AnchorData } from \"../types\";\n\nconst DATA_ATTR_PRIORITY = [\"data-testid\", \"data-cy\"];\n\nfunction findAnchorElement(element: Element): {\n\tel: Element;\n\tselector: string;\n} {\n\t// 1. Check clicked element for id\n\tif (element.id) {\n\t\treturn { el: element, selector: `#${CSS.escape(element.id)}` };\n\t}\n\n\t// 2. Walk up to nearest ancestor with id\n\tlet current = element.parentElement;\n\twhile (current && current !== document.body) {\n\t\tif (current.id) {\n\t\t\treturn { el: current, selector: `#${CSS.escape(current.id)}` };\n\t\t}\n\t\tcurrent = current.parentElement;\n\t}\n\n\t// 3. Check element and ancestors for data attributes\n\tcurrent = element as HTMLElement;\n\twhile (current && current !== document.body) {\n\t\tfor (const attr of DATA_ATTR_PRIORITY) {\n\t\t\tconst value = current.getAttribute(attr);\n\t\t\tif (value) {\n\t\t\t\treturn { el: current, selector: `[${attr}=\"${CSS.escape(value)}\"]` };\n\t\t\t}\n\t\t}\n\t\t// Check any other data-* attribute\n\t\tfor (const attr of current.getAttributeNames()) {\n\t\t\tif (attr.startsWith(\"data-\") && !DATA_ATTR_PRIORITY.includes(attr)) {\n\t\t\t\tconst value = current.getAttribute(attr);\n\t\t\t\treturn {\n\t\t\t\t\tel: current,\n\t\t\t\t\tselector: `[${attr}=\"${CSS.escape(value ?? \"\")}\"]`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentElement as HTMLElement;\n\t}\n\n\t// 4. Fallback: structural path (max 3 levels)\n\treturn { el: element, selector: buildStructuralSelector(element) };\n}\n\nfunction buildStructuralSelector(element: Element): string {\n\tconst parts: string[] = [];\n\tlet current: Element | null = element;\n\tlet depth = 0;\n\n\twhile (current && current !== document.body && depth < 3) {\n\t\tconst tag = current.tagName.toLowerCase();\n\t\tconst parent: Element | null = current.parentElement;\n\n\t\tif (parent) {\n\t\t\tconst siblings = Array.from(parent.children).filter(\n\t\t\t\t(c: Element) => c.tagName === current?.tagName,\n\t\t\t);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst index = siblings.indexOf(current) + 1;\n\t\t\t\tparts.unshift(`${tag}:nth-of-type(${index})`);\n\t\t\t} else {\n\t\t\t\tparts.unshift(tag);\n\t\t\t}\n\t\t} else {\n\t\t\tparts.unshift(tag);\n\t\t}\n\n\t\tcurrent = parent;\n\t\tdepth++;\n\t}\n\n\treturn parts.join(\" > \");\n}\n\nfunction computePercentages(\n\tanchorEl: Element,\n\tclickX: number,\n\tclickY: number,\n): { xPercent: number; yPercent: number } {\n\tconst rect = anchorEl.getBoundingClientRect();\n\tconst width = rect.width || 1;\n\tconst height = rect.height || 1;\n\n\tconst xPercent = ((clickX - rect.left) / width) * 100;\n\tconst yPercent = ((clickY - rect.top) / height) * 100;\n\n\treturn { xPercent, yPercent };\n}\n\nexport function resolveAnchor(\n\telement: Element,\n\tclickX: number,\n\tclickY: number,\n): AnchorData {\n\tconst { el, selector } = findAnchorElement(element);\n\tconst { xPercent, yPercent } = computePercentages(el, clickX, clickY);\n\n\treturn { selector, xPercent, yPercent };\n}\n","import type { AnchorData } from \"../types\";\n\nexport function restorePosition(\n\tanchor: AnchorData,\n): { top: number; left: number } | null {\n\tif (!anchor.selector) {\n\t\treturn null;\n\t}\n\n\tlet el: Element | null;\n\ttry {\n\t\tel = document.querySelector(anchor.selector);\n\t} catch {\n\t\treturn null;\n\t}\n\n\tif (!el) {\n\t\treturn null;\n\t}\n\n\tconst rect = el.getBoundingClientRect();\n\tconst scrollX = window.scrollX;\n\tconst scrollY = window.scrollY;\n\n\tconst left = rect.left + scrollX + (rect.width * anchor.xPercent) / 100;\n\tconst top = rect.top + scrollY + (rect.height * anchor.yPercent) / 100;\n\n\treturn { top, left };\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/FeedbackOverlay.tsx","../src/components/AdminKeyModal.tsx","../src/components/ClickInterceptLayer.tsx","../src/components/CommentPopover.tsx","../src/components/FeedbackToolbar.tsx","../src/components/PinMarker.tsx","../src/components/ShareLinkButton.tsx","../src/hooks/useAuth.ts","../src/utils/resolveAnchor.ts","../src/utils/restorePosition.ts"],"sourcesContent":["export { FeedbackOverlay } from \"./FeedbackOverlay\";\nexport type { FeedbackOverlayProps, PinComment } from \"./types\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { AdminKeyModal } from \"./components/AdminKeyModal\";\nimport { ClickInterceptLayer } from \"./components/ClickInterceptLayer\";\nimport { CommentPopover } from \"./components/CommentPopover\";\nimport { FeedbackToolbar } from \"./components/FeedbackToolbar\";\nimport { PinMarker } from \"./components/PinMarker\";\nimport { ShareLinkButton } from \"./components/ShareLinkButton\";\nimport { useAuth } from \"./hooks/useAuth\";\nimport type { FeedbackOverlayProps, PendingPin, PinComment } from \"./types\";\nimport { resolveAnchor } from \"./utils/resolveAnchor\";\nimport { restorePosition } from \"./utils/restorePosition\";\n\nexport function FeedbackOverlay({\n\tonCommentCreate,\n\tonCommentsFetch,\n\tonCommentDelete,\n\tonCommentUpdate,\n\tonAdminValidate,\n\tonShareLinkCreate,\n\tchildren,\n}: FeedbackOverlayProps) {\n\tconst { auth, authHeaders, setAdminKey } = useAuth();\n\tconst [comments, setComments] = useState<PinComment[]>([]);\n\tconst [pendingPin, setPendingPin] = useState<PendingPin | null>(null);\n\tconst [expandedPinId, setExpandedPinId] = useState<string | null>(null);\n\tconst [fetchError, setFetchError] = useState<string | null>(null);\n\tconst [pinMode, setPinMode] = useState(false);\n\tconst [adminModalOpen, setAdminModalOpen] = useState(false);\n\tconst hasFetched = useRef(false);\n\n\tuseEffect(() => {\n\t\tif (hasFetched.current) return;\n\t\thasFetched.current = true;\n\n\t\tonCommentsFetch(authHeaders)\n\t\t\t.then((data) => setComments([...data]))\n\t\t\t.catch(() => setFetchError(\"Couldn't load comments.\"));\n\t}, [onCommentsFetch, authHeaders]);\n\n\tconst handleClick = useCallback((clientX: number, clientY: number) => {\n\t\tsetExpandedPinId(null);\n\n\t\tconst interceptLayer = document.querySelector(\n\t\t\t\".pp-intercept\",\n\t\t) as HTMLElement;\n\t\tif (interceptLayer) interceptLayer.style.pointerEvents = \"none\";\n\t\tconst elementBelow = document.elementFromPoint(clientX, clientY);\n\t\tif (interceptLayer) interceptLayer.style.pointerEvents = \"\";\n\n\t\tif (!elementBelow) return;\n\n\t\tconst anchor = resolveAnchor(elementBelow, clientX, clientY);\n\t\tsetPendingPin({\n\t\t\tx: clientX + window.scrollX,\n\t\t\ty: clientY + window.scrollY,\n\t\t\tanchor,\n\t\t});\n\t}, []);\n\n\tconst handleSubmit = useCallback(\n\t\tasync (content: string) => {\n\t\t\tif (!pendingPin) return;\n\n\t\t\tconst comment: PinComment = {\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\turl: window.location.pathname,\n\t\t\t\tcontent,\n\t\t\t\tanchor: pendingPin.anchor,\n\t\t\t\tviewport: { width: window.innerWidth },\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t};\n\n\t\t\tawait onCommentCreate(comment, authHeaders);\n\t\t\tsetComments((prev) => [...prev, comment]);\n\t\t\tsetPendingPin(null);\n\t\t\tsetPinMode(false);\n\t\t},\n\t\t[pendingPin, onCommentCreate, authHeaders],\n\t);\n\n\tconst handleCancel = useCallback(() => {\n\t\tsetPendingPin(null);\n\t}, []);\n\n\tconst handleDelete = useCallback(\n\t\tasync (id: string) => {\n\t\t\tif (!onCommentDelete) return;\n\t\t\tawait onCommentDelete(id, authHeaders);\n\t\t\tsetComments((prev) => prev.filter((c) => c.id !== id));\n\t\t\tsetExpandedPinId(null);\n\t\t},\n\t\t[onCommentDelete, authHeaders],\n\t);\n\n\tconst handleUpdate = useCallback(\n\t\tasync (id: string, content: string) => {\n\t\t\tif (!onCommentUpdate) return;\n\t\t\tconst updated = await onCommentUpdate(id, content, authHeaders);\n\t\t\tsetComments((prev) => prev.map((c) => (c.id === id ? updated : c)));\n\t\t},\n\t\t[onCommentUpdate, authHeaders],\n\t);\n\n\tconst handlePinModeToggle = useCallback(() => {\n\t\tsetPinMode((prev) => {\n\t\t\tconst next = !prev;\n\t\t\tif (!next) setPendingPin(null);\n\t\t\treturn next;\n\t\t});\n\t}, []);\n\n\tconst handleAdminValidate = useCallback(\n\t\tasync (secret: string) => {\n\t\t\tif (!onAdminValidate) return false;\n\t\t\treturn onAdminValidate(secret);\n\t\t},\n\t\t[onAdminValidate],\n\t);\n\n\tconst handleAdminSuccess = useCallback(\n\t\t(secret: string) => {\n\t\t\tsetAdminKey(secret);\n\t\t\tsetAdminModalOpen(false);\n\t\t},\n\t\t[setAdminKey],\n\t);\n\n\tconst handleShareCreate = useCallback(\n\t\tasync (label?: string, ttl?: number) => {\n\t\t\tif (!onShareLinkCreate) throw new Error(\"onShareLinkCreate not provided\");\n\t\t\treturn onShareLinkCreate(label, ttl, authHeaders);\n\t\t},\n\t\t[onShareLinkCreate, authHeaders],\n\t);\n\n\treturn (\n\t\t<div data-pin-point=\"\">\n\t\t\t{children}\n\t\t\t{pinMode && <ClickInterceptLayer onClick={handleClick} />}\n\n\t\t\t{comments.map((comment, index) => {\n\t\t\t\tconst pos = restorePosition(comment.anchor);\n\t\t\t\tif (!pos) return null;\n\n\t\t\t\treturn (\n\t\t\t\t\t<PinMarker\n\t\t\t\t\t\tkey={comment.id}\n\t\t\t\t\t\tnumber={index + 1}\n\t\t\t\t\t\ttop={pos.top}\n\t\t\t\t\t\tleft={pos.left}\n\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\tsetExpandedPinId(expandedPinId === comment.id ? null : comment.id)\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t})}\n\n\t\t\t{expandedPinId &&\n\t\t\t\t(() => {\n\t\t\t\t\tconst comment = comments.find((c) => c.id === expandedPinId);\n\t\t\t\t\tif (!comment) return null;\n\t\t\t\t\tconst pos = restorePosition(comment.anchor);\n\t\t\t\t\tif (!pos) return null;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<CommentPopover\n\t\t\t\t\t\t\tmode=\"read\"\n\t\t\t\t\t\t\tcontent={comment.content}\n\t\t\t\t\t\t\tcreatedAt={comment.createdAt}\n\t\t\t\t\t\t\tviewportWidth={comment.viewport.width}\n\t\t\t\t\t\t\ttop={pos.top}\n\t\t\t\t\t\t\tleft={pos.left}\n\t\t\t\t\t\t\tonDelete={\n\t\t\t\t\t\t\t\tonCommentDelete\n\t\t\t\t\t\t\t\t\t? async () => handleDelete(comment.id)\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonUpdate={\n\t\t\t\t\t\t\t\tonCommentUpdate\n\t\t\t\t\t\t\t\t\t? async (content: string) => {\n\t\t\t\t\t\t\t\t\t\t\tawait handleUpdate(comment.id, content);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})()}\n\n\t\t\t{pendingPin && (\n\t\t\t\t<>\n\t\t\t\t\t<PinMarker\n\t\t\t\t\t\tnumber={comments.length + 1}\n\t\t\t\t\t\ttop={pendingPin.y}\n\t\t\t\t\t\tleft={pendingPin.x}\n\t\t\t\t\t\tonClick={() => {}}\n\t\t\t\t\t/>\n\t\t\t\t\t<CommentPopover\n\t\t\t\t\t\tmode=\"create\"\n\t\t\t\t\t\ttop={pendingPin.y}\n\t\t\t\t\t\tleft={pendingPin.x}\n\t\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\t\tonCancel={handleCancel}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t)}\n\n\t\t\t<FeedbackToolbar\n\t\t\t\tauth={auth}\n\t\t\t\tcommentCount={comments.length}\n\t\t\t\tpinModeActive={pinMode}\n\t\t\t\tonPinModeToggle={handlePinModeToggle}\n\t\t\t\tonAdminKeyOpen={() => setAdminModalOpen(true)}\n\t\t\t\tshareButton={\n\t\t\t\t\tauth.role === \"admin\" && onShareLinkCreate ? (\n\t\t\t\t\t\t<ShareLinkButton onCreate={handleShareCreate} />\n\t\t\t\t\t) : undefined\n\t\t\t\t}\n\t\t\t\terror={fetchError ?? undefined}\n\t\t\t/>\n\n\t\t\t{adminModalOpen && (\n\t\t\t\t<AdminKeyModal\n\t\t\t\t\tonValidate={handleAdminValidate}\n\t\t\t\t\tonSuccess={handleAdminSuccess}\n\t\t\t\t\tonClose={() => setAdminModalOpen(false)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { useState } from \"react\";\n\ntype Props = {\n\tonValidate: (secret: string) => Promise<boolean>;\n\tonSuccess: (secret: string) => void;\n\tonClose: () => void;\n};\n\nexport function AdminKeyModal({ onValidate, onSuccess, onClose }: Props) {\n\tconst [value, setValue] = useState(\"\");\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [busy, setBusy] = useState(false);\n\n\tconst handleSubmit = async () => {\n\t\tsetBusy(true);\n\t\tsetError(null);\n\t\ttry {\n\t\t\tconst ok = await onValidate(value);\n\t\t\tif (ok) {\n\t\t\t\tonSuccess(value);\n\t\t\t} else {\n\t\t\t\tsetError(\"Invalid admin key\");\n\t\t\t}\n\t\t} catch {\n\t\t\tsetError(\"Could not reach server\");\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: backdrop click dismissal, Cancel button and Escape are primary dismissal paths\n\t\t// biome-ignore lint/a11y/noStaticElementInteractions: backdrop is a visual scrim, inner dialog has role\n\t\t<div className=\"pp-modal-backdrop\" onClick={onClose}>\n\t\t\t{/* biome-ignore lint/a11y/useKeyWithClickEvents: stopPropagation only, not an interactive element */}\n\t\t\t<div\n\t\t\t\tclassName=\"pp-modal\"\n\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\trole=\"dialog\"\n\t\t\t\taria-modal=\"true\"\n\t\t\t>\n\t\t\t\t<h3>Enter admin key</h3>\n\t\t\t\t<input\n\t\t\t\t\ttype=\"password\"\n\t\t\t\t\tplaceholder=\"Admin key\"\n\t\t\t\t\tvalue={value}\n\t\t\t\t\tonChange={(e) => setValue(e.target.value)}\n\t\t\t\t\tdisabled={busy}\n\t\t\t\t/>\n\t\t\t\t{error && <div className=\"pp-modal-error\">{error}</div>}\n\t\t\t\t<div className=\"pp-modal-actions\">\n\t\t\t\t\t<button type=\"button\" onClick={onClose} disabled={busy}>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleSubmit}\n\t\t\t\t\t\tdisabled={busy || !value}\n\t\t\t\t\t>\n\t\t\t\t\t\tSave\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { useCallback, useRef } from \"react\";\n\ntype ClickInterceptLayerProps = {\n\tonClick: (clientX: number, clientY: number) => void;\n};\n\nexport function ClickInterceptLayer({ onClick }: ClickInterceptLayerProps) {\n\tconst lastClickTime = useRef(0);\n\n\tconst handleClick = useCallback(\n\t\t(e: React.MouseEvent) => {\n\t\t\tconst now = Date.now();\n\t\t\tif (now - lastClickTime.current < 300) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlastClickTime.current = now;\n\t\t\tonClick(e.clientX, e.clientY);\n\t\t},\n\t\t[onClick],\n\t);\n\n\treturn (\n\t\t// biome-ignore lint/a11y/noStaticElementInteractions: click-only overlay for pin placement\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: click-only overlay for pin placement\n\t\t<div className=\"pp-intercept\" onClick={handleClick} />\n\t);\n}\n","import type React from \"react\";\nimport { useEffect, useLayoutEffect, useRef, useState } from \"react\";\n\ntype ReadProps = {\n\tmode: \"read\";\n\tcontent: string;\n\tcreatedAt: string;\n\tviewportWidth: number;\n\ttop: number;\n\tleft: number;\n\tonDelete?: () => Promise<void>;\n\tonUpdate?: (content: string) => Promise<void>;\n\tonSubmit?: never;\n\tonCancel?: never;\n};\n\ntype CreateProps = {\n\tmode: \"create\";\n\ttop: number;\n\tleft: number;\n\tonSubmit: (content: string) => Promise<void>;\n\tonCancel: () => void;\n\tcontent?: never;\n\tcreatedAt?: never;\n\tviewportWidth?: never;\n};\n\ntype CommentPopoverProps = ReadProps | CreateProps;\n\ntype Placement = { x: \"right\" | \"left\"; y: \"bottom\" | \"top\" };\n\nconst POPOVER_OFFSET = 14;\nconst VIEWPORT_MARGIN = 8;\nconst KEYBOARD_HEIGHT_THRESHOLD = 150;\n\nfunction useScrollIntoViewOnKeyboard(\n\tref: React.RefObject<HTMLDivElement | null>,\n) {\n\tuseEffect(() => {\n\t\tconst viewport = window.visualViewport;\n\t\tif (!viewport) return;\n\n\t\tconst baselineHeight = viewport.height;\n\n\t\tconst handleResize = () => {\n\t\t\tif (\n\t\t\t\tbaselineHeight - viewport.height > KEYBOARD_HEIGHT_THRESHOLD &&\n\t\t\t\tref.current\n\t\t\t) {\n\t\t\t\tref.current.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n\t\t\t}\n\t\t};\n\n\t\tviewport.addEventListener(\"resize\", handleResize);\n\t\treturn () => viewport.removeEventListener(\"resize\", handleResize);\n\t}, [ref]);\n}\n\nexport function CommentPopover(props: CommentPopoverProps) {\n\tconst { mode, top, left } = props;\n\tconst popoverRef = useRef<HTMLDivElement>(null);\n\tconst [placement, setPlacement] = useState<Placement>({\n\t\tx: \"right\",\n\t\ty: \"bottom\",\n\t});\n\tconst [size, setSize] = useState<{ width: number; height: number } | null>(\n\t\tnull,\n\t);\n\n\tuseLayoutEffect(() => {\n\t\tconst el = popoverRef.current;\n\t\tif (!el) return;\n\t\tconst rect = el.getBoundingClientRect();\n\t\tconst w = rect.width;\n\t\tconst h = rect.height;\n\n\t\tconst pinViewX = left - window.scrollX;\n\t\tconst pinViewY = top - window.scrollY;\n\n\t\tconst fitsRight =\n\t\t\tpinViewX - POPOVER_OFFSET + w + VIEWPORT_MARGIN <= window.innerWidth;\n\t\tconst fitsLeft = pinViewX + POPOVER_OFFSET - w - VIEWPORT_MARGIN >= 0;\n\t\tconst fitsBottom =\n\t\t\tpinViewY + POPOVER_OFFSET + h + VIEWPORT_MARGIN <= window.innerHeight;\n\t\tconst fitsTop = pinViewY - POPOVER_OFFSET - h - VIEWPORT_MARGIN >= 0;\n\n\t\tsetPlacement({\n\t\t\tx: fitsRight ? \"right\" : fitsLeft ? \"left\" : \"right\",\n\t\t\ty: fitsBottom ? \"bottom\" : fitsTop ? \"top\" : \"bottom\",\n\t\t});\n\t\tsetSize({ width: w, height: h });\n\t}, [top, left]);\n\n\tuseScrollIntoViewOnKeyboard(popoverRef);\n\n\tconst style: React.CSSProperties = size\n\t\t? {\n\t\t\t\ttop: `${\n\t\t\t\t\tplacement.y === \"bottom\"\n\t\t\t\t\t\t? top + POPOVER_OFFSET\n\t\t\t\t\t\t: top - POPOVER_OFFSET - size.height\n\t\t\t\t}px`,\n\t\t\t\tleft: `${\n\t\t\t\t\tplacement.x === \"right\"\n\t\t\t\t\t\t? left - POPOVER_OFFSET\n\t\t\t\t\t\t: left + POPOVER_OFFSET - size.width\n\t\t\t\t}px`,\n\t\t\t}\n\t\t: {\n\t\t\t\ttop: `${top + POPOVER_OFFSET}px`,\n\t\t\t\tleft: `${left - POPOVER_OFFSET}px`,\n\t\t\t\tvisibility: \"hidden\",\n\t\t\t};\n\n\treturn (\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: stopPropagation only, not interactive\n\t\t<div\n\t\t\tref={popoverRef}\n\t\t\tclassName=\"pp-popover\"\n\t\t\tdata-placement-x={placement.x}\n\t\t\tdata-placement-y={placement.y}\n\t\t\tstyle={style}\n\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\trole=\"dialog\"\n\t\t>\n\t\t\t<div className=\"pp-popover-arrow\" />\n\t\t\t{mode === \"read\" ? (\n\t\t\t\t<ReadContent\n\t\t\t\t\tcontent={props.content}\n\t\t\t\t\tcreatedAt={props.createdAt}\n\t\t\t\t\tviewportWidth={props.viewportWidth}\n\t\t\t\t\tonDelete={props.onDelete}\n\t\t\t\t\tonUpdate={props.onUpdate}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<CreateContent onSubmit={props.onSubmit} onCancel={props.onCancel} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction ReadContent({\n\tcontent,\n\tcreatedAt,\n\tviewportWidth,\n\tonDelete,\n\tonUpdate,\n}: {\n\tcontent: string;\n\tcreatedAt: string;\n\tviewportWidth: number;\n\tonDelete?: () => Promise<void>;\n\tonUpdate?: (content: string) => Promise<void>;\n}) {\n\tconst [isConfirmingDelete, setIsConfirmingDelete] = useState(false);\n\tconst [isEditing, setIsEditing] = useState(false);\n\tconst [editContent, setEditContent] = useState(content);\n\tconst [saving, setSaving] = useState(false);\n\tconst [deleting, setDeleting] = useState(false);\n\tconst [deleteError, setDeleteError] = useState(false);\n\tconst [editError, setEditError] = useState(false);\n\n\tuseEffect(() => setEditContent(content), [content]);\n\n\tconst date = new Date(createdAt).toLocaleDateString(undefined, {\n\t\tmonth: \"short\",\n\t\tday: \"numeric\",\n\t\tyear: \"numeric\",\n\t});\n\n\tif (isEditing) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<textarea\n\t\t\t\t\tclassName=\"pp-popover-textarea\"\n\t\t\t\t\tvalue={editContent}\n\t\t\t\t\tonChange={(e) => setEditContent(e.target.value)}\n\t\t\t\t/>\n\t\t\t\t<div className=\"pp-popover-actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetIsEditing(false);\n\t\t\t\t\t\t\tsetEditContent(content);\n\t\t\t\t\t\t\tsetEditError(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--submit\"\n\t\t\t\t\t\tdisabled={editContent.trim().length === 0 || saving}\n\t\t\t\t\t\tonClick={async () => {\n\t\t\t\t\t\t\tsetSaving(true);\n\t\t\t\t\t\t\tsetEditError(false);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait onUpdate?.(editContent);\n\t\t\t\t\t\t\t\tsetIsEditing(false);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tsetEditError(true);\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tsetSaving(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tSave\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t{editError && (\n\t\t\t\t\t<div className=\"pp-popover-error\">Couldn't save. Try again.</div>\n\t\t\t\t)}\n\t\t\t</>\n\t\t);\n\t}\n\n\tif (isConfirmingDelete) {\n\t\treturn (\n\t\t\t<div className=\"pp-delete-confirm\">\n\t\t\t\t<div className=\"pp-delete-confirm-icon\">\n\t\t\t\t\t<svg\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\twidth=\"20\"\n\t\t\t\t\t\theight=\"20\"\n\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t\t\t\t<line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n\t\t\t\t\t\t<line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n\t\t\t\t\t</svg>\n\t\t\t\t</div>\n\t\t\t\t<p className=\"pp-delete-confirm-text\">Delete this comment?</p>\n\t\t\t\t{deleteError && (\n\t\t\t\t\t<div className=\"pp-popover-error\">Couldn't delete. Try again.</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"pp-delete-confirm-actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\t\tdisabled={deleting}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetIsConfirmingDelete(false);\n\t\t\t\t\t\t\tsetDeleteError(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--danger\"\n\t\t\t\t\t\tdisabled={deleting}\n\t\t\t\t\t\tonClick={async () => {\n\t\t\t\t\t\t\tsetDeleting(true);\n\t\t\t\t\t\t\tsetDeleteError(false);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait onDelete?.();\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tsetDeleteError(true);\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tsetDeleting(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{deleting ? \"Deleting...\" : \"Delete\"}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"pp-popover-content\">{content}</div>\n\t\t\t<div className=\"pp-popover-footer\">\n\t\t\t\t<div className=\"pp-popover-meta\">\n\t\t\t\t\t{date} · {viewportWidth}px viewport\n\t\t\t\t</div>\n\t\t\t\t{(onDelete || onUpdate) && (\n\t\t\t\t\t<div className=\"pp-popover-actions-row\">\n\t\t\t\t\t\t{onUpdate && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"pp-action-btn\"\n\t\t\t\t\t\t\t\taria-label=\"Edit\"\n\t\t\t\t\t\t\t\tonClick={() => setIsEditing(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\twidth=\"13\"\n\t\t\t\t\t\t\t\t\theight=\"13\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path d=\"M17 3a2.83 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z\" />\n\t\t\t\t\t\t\t\t\t<path d=\"m15 5 4 4\" />\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onDelete && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"pp-action-btn pp-action-btn--danger\"\n\t\t\t\t\t\t\t\taria-label=\"Delete\"\n\t\t\t\t\t\t\t\tonClick={() => setIsConfirmingDelete(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\twidth=\"13\"\n\t\t\t\t\t\t\t\t\theight=\"13\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path d=\"M3 6h18\" />\n\t\t\t\t\t\t\t\t\t<path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\" />\n\t\t\t\t\t\t\t\t\t<path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\" />\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</>\n\t);\n}\n\nfunction CreateContent({\n\tonSubmit,\n\tonCancel,\n}: {\n\tonSubmit: (content: string) => Promise<void>;\n\tonCancel: () => void;\n}) {\n\tconst [text, setText] = useState(\"\");\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [submitting, setSubmitting] = useState(false);\n\n\tconst handleSubmit = async () => {\n\t\tsetError(null);\n\t\tsetSubmitting(true);\n\t\ttry {\n\t\t\tawait onSubmit(text);\n\t\t} catch {\n\t\t\tsetError(\"Couldn't save. Try again.\");\n\t\t} finally {\n\t\t\tsetSubmitting(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<textarea\n\t\t\t\tclassName=\"pp-popover-textarea\"\n\t\t\t\tplaceholder=\"Leave your feedback...\"\n\t\t\t\tvalue={text}\n\t\t\t\tonChange={(e) => setText(e.target.value)}\n\t\t\t/>\n\t\t\t<div className=\"pp-popover-actions\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\tonClick={onCancel}\n\t\t\t\t>\n\t\t\t\t\tCancel\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-btn pp-btn--submit\"\n\t\t\t\t\tonClick={handleSubmit}\n\t\t\t\t\tdisabled={text.trim().length === 0 || submitting}\n\t\t\t\t>\n\t\t\t\t\tSubmit\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{error && <div className=\"pp-popover-error\">{error}</div>}\n\t\t</>\n\t);\n}\n","import type React from \"react\";\nimport type { PinAuth } from \"../types\";\n\ntype FeedbackToolbarProps = {\n\tauth: PinAuth;\n\tcommentCount: number;\n\tpinModeActive: boolean;\n\tonPinModeToggle: () => void;\n\tonAdminKeyOpen: () => void;\n\tshareButton?: React.ReactNode;\n\terror?: string;\n};\n\nconst CommentIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"16\"\n\t\theight=\"16\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n\t</svg>\n);\n\nconst KeyIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"16\"\n\t\theight=\"16\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"m21 2-9.6 9.6\" />\n\t\t<circle cx=\"7.5\" cy=\"15.5\" r=\"5.5\" />\n\t\t<path d=\"m15.5 7.5 3 3\" />\n\t</svg>\n);\n\nexport function FeedbackToolbar({\n\tauth,\n\tcommentCount,\n\tpinModeActive,\n\tonPinModeToggle,\n\tonAdminKeyOpen,\n\tshareButton,\n\terror,\n}: FeedbackToolbarProps) {\n\tconst commentDisabled = auth.role === \"anonymous\";\n\tconst commentTitle = commentDisabled\n\t\t? \"Sign in with a share link to leave feedback\"\n\t\t: pinModeActive\n\t\t\t? \"Exit pin mode\"\n\t\t\t: \"Leave feedback\";\n\tconst showAdminKey = auth.role !== \"tokenHolder\";\n\n\treturn (\n\t\t<div className=\"pp-toolbar\">\n\t\t\t<div className=\"pp-toolbar-dot\" />\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"pp-toolbar-btn\"\n\t\t\t\tonClick={onPinModeToggle}\n\t\t\t\tdisabled={commentDisabled}\n\t\t\t\taria-pressed={pinModeActive}\n\t\t\t\taria-label=\"Leave feedback\"\n\t\t\t\ttitle={commentTitle}\n\t\t\t>\n\t\t\t\t<CommentIcon />\n\t\t\t</button>\n\t\t\t{showAdminKey && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-toolbar-btn\"\n\t\t\t\t\tonClick={onAdminKeyOpen}\n\t\t\t\t\taria-label=\"Enter admin key\"\n\t\t\t\t\ttitle=\"Enter admin key\"\n\t\t\t\t>\n\t\t\t\t\t<KeyIcon />\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{shareButton}\n\t\t\t{error ? (\n\t\t\t\t<span className=\"pp-toolbar-error\">{error}</span>\n\t\t\t) : (\n\t\t\t\t<span className=\"pp-toolbar-badge\">\n\t\t\t\t\t{commentCount} {commentCount === 1 ? \"comment\" : \"comments\"}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","type PinMarkerProps = {\n\tnumber: number;\n\ttop: number;\n\tleft: number;\n\tonClick: () => void;\n};\n\nexport function PinMarker({ number, top, left, onClick }: PinMarkerProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName=\"pp-pin\"\n\t\t\tstyle={{ top: `${top}px`, left: `${left}px` }}\n\t\t\tonClick={(e) => {\n\t\t\t\te.stopPropagation();\n\t\t\t\tonClick();\n\t\t\t}}\n\t\t>\n\t\t\t{number}\n\t\t</button>\n\t);\n}\n","import { useState } from \"react\";\n\ntype Props = {\n\tonCreate: (\n\t\tlabel?: string,\n\t\texpiresInHours?: number,\n\t) => Promise<{ tokenId: string }>;\n};\n\nconst ShareIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2.2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8\" />\n\t\t<polyline points=\"16 6 12 2 8 6\" />\n\t\t<line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"15\" />\n\t</svg>\n);\n\nconst CheckIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2.5\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t</svg>\n);\n\nexport function ShareLinkButton({ onCreate }: Props) {\n\tconst [busy, setBusy] = useState(false);\n\tconst [copied, setCopied] = useState(false);\n\n\tconst handleClick = async () => {\n\t\tsetBusy(true);\n\t\ttry {\n\t\t\tconst { tokenId } = await onCreate();\n\t\t\tconst url = new URL(window.location.href);\n\t\t\turl.searchParams.set(\"pin-token\", tokenId);\n\t\t\tawait navigator.clipboard.writeText(url.toString());\n\t\t\tsetCopied(true);\n\t\t\tsetTimeout(() => setCopied(false), 2000);\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className=\"pp-share-wrapper\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"pp-share-btn\"\n\t\t\t\tonClick={handleClick}\n\t\t\t\tdisabled={busy}\n\t\t\t\tdata-state={copied ? \"copied\" : busy ? \"busy\" : \"idle\"}\n\t\t\t>\n\t\t\t\t{copied ? <CheckIcon /> : <ShareIcon />}\n\t\t\t\t<span>{copied ? \"Link copied\" : \"Share for feedback\"}</span>\n\t\t\t</button>\n\t\t</div>\n\t);\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport type { AuthHeaders, PinAuth } from \"../types\";\n\nconst ADMIN_KEY_STORAGE = \"pin-admin-key\";\nconst TOKEN_QUERY_PARAM = \"pin-token\";\n\nconst resolveAuth = (): PinAuth => {\n\tif (typeof window === \"undefined\") return { role: \"anonymous\" };\n\n\tconst params = new URLSearchParams(window.location.search);\n\tconst token = params.get(TOKEN_QUERY_PARAM);\n\tif (token) return { role: \"tokenHolder\", token };\n\n\tconst adminKey = localStorage.getItem(ADMIN_KEY_STORAGE);\n\tif (adminKey) return { role: \"admin\", secret: adminKey };\n\n\treturn { role: \"anonymous\" };\n};\n\nconst computeHeaders = (auth: PinAuth): AuthHeaders => {\n\tswitch (auth.role) {\n\t\tcase \"tokenHolder\":\n\t\t\treturn { \"X-Pin-Token\": auth.token };\n\t\tcase \"admin\":\n\t\t\treturn { \"X-Pin-Admin\": auth.secret };\n\t\tcase \"anonymous\":\n\t\t\treturn {};\n\t}\n};\n\nexport const useAuth = () => {\n\tconst [auth, setAuth] = useState<PinAuth>(resolveAuth);\n\n\tuseEffect(() => {\n\t\tconst onPopState = () => setAuth(resolveAuth());\n\t\twindow.addEventListener(\"popstate\", onPopState);\n\t\treturn () => window.removeEventListener(\"popstate\", onPopState);\n\t}, []);\n\n\tconst setAdminKey = useCallback((secret: string) => {\n\t\tlocalStorage.setItem(ADMIN_KEY_STORAGE, secret);\n\t\tsetAuth(resolveAuth());\n\t}, []);\n\n\tconst clearAdminKey = useCallback(() => {\n\t\tlocalStorage.removeItem(ADMIN_KEY_STORAGE);\n\t\tsetAuth(resolveAuth());\n\t}, []);\n\n\treturn {\n\t\tauth,\n\t\tauthHeaders: computeHeaders(auth),\n\t\tsetAdminKey,\n\t\tclearAdminKey,\n\t};\n};\n","import type { AnchorData } from \"../types\";\n\nconst DATA_ATTR_PRIORITY = [\"data-testid\", \"data-cy\"];\n\nfunction findAnchorElement(element: Element): {\n\tel: Element;\n\tselector: string;\n} {\n\t// 1. Check clicked element for id\n\tif (element.id) {\n\t\treturn { el: element, selector: `#${CSS.escape(element.id)}` };\n\t}\n\n\t// 2. Walk up to nearest ancestor with id\n\tlet current = element.parentElement;\n\twhile (current && current !== document.body) {\n\t\tif (current.id) {\n\t\t\treturn { el: current, selector: `#${CSS.escape(current.id)}` };\n\t\t}\n\t\tcurrent = current.parentElement;\n\t}\n\n\t// 3. Check element and ancestors for data attributes\n\tcurrent = element as HTMLElement;\n\twhile (current && current !== document.body) {\n\t\tfor (const attr of DATA_ATTR_PRIORITY) {\n\t\t\tconst value = current.getAttribute(attr);\n\t\t\tif (value) {\n\t\t\t\treturn { el: current, selector: `[${attr}=\"${CSS.escape(value)}\"]` };\n\t\t\t}\n\t\t}\n\t\t// Check any other data-* attribute\n\t\tfor (const attr of current.getAttributeNames()) {\n\t\t\tif (attr.startsWith(\"data-\") && !DATA_ATTR_PRIORITY.includes(attr)) {\n\t\t\t\tconst value = current.getAttribute(attr);\n\t\t\t\treturn {\n\t\t\t\t\tel: current,\n\t\t\t\t\tselector: `[${attr}=\"${CSS.escape(value ?? \"\")}\"]`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentElement as HTMLElement;\n\t}\n\n\t// 4. Fallback: structural path (max 3 levels)\n\treturn { el: element, selector: buildStructuralSelector(element) };\n}\n\nfunction buildStructuralSelector(element: Element): string {\n\tconst parts: string[] = [];\n\tlet current: Element | null = element;\n\tlet depth = 0;\n\n\twhile (current && current !== document.body && depth < 3) {\n\t\tconst tag = current.tagName.toLowerCase();\n\t\tconst parent: Element | null = current.parentElement;\n\n\t\tif (parent) {\n\t\t\tconst siblings = Array.from(parent.children).filter(\n\t\t\t\t(c: Element) => c.tagName === current?.tagName,\n\t\t\t);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst index = siblings.indexOf(current) + 1;\n\t\t\t\tparts.unshift(`${tag}:nth-of-type(${index})`);\n\t\t\t} else {\n\t\t\t\tparts.unshift(tag);\n\t\t\t}\n\t\t} else {\n\t\t\tparts.unshift(tag);\n\t\t}\n\n\t\tcurrent = parent;\n\t\tdepth++;\n\t}\n\n\treturn parts.join(\" > \");\n}\n\nfunction computePercentages(\n\tanchorEl: Element,\n\tclickX: number,\n\tclickY: number,\n): { xPercent: number; yPercent: number } {\n\tconst rect = anchorEl.getBoundingClientRect();\n\tconst width = rect.width || 1;\n\tconst height = rect.height || 1;\n\n\tconst xPercent = ((clickX - rect.left) / width) * 100;\n\tconst yPercent = ((clickY - rect.top) / height) * 100;\n\n\treturn { xPercent, yPercent };\n}\n\nexport function resolveAnchor(\n\telement: Element,\n\tclickX: number,\n\tclickY: number,\n): AnchorData {\n\tconst { el, selector } = findAnchorElement(element);\n\tconst { xPercent, yPercent } = computePercentages(el, clickX, clickY);\n\n\treturn { selector, xPercent, yPercent };\n}\n","import type { AnchorData } from \"../types\";\n\nexport function restorePosition(\n\tanchor: AnchorData,\n): { top: number; left: number } | null {\n\tif (!anchor.selector) {\n\t\treturn null;\n\t}\n\n\tlet el: Element | null;\n\ttry {\n\t\tel = document.querySelector(anchor.selector);\n\t} catch {\n\t\treturn null;\n\t}\n\n\tif (!el) {\n\t\treturn null;\n\t}\n\n\tconst rect = el.getBoundingClientRect();\n\tconst scrollX = window.scrollX;\n\tconst scrollY = window.scrollY;\n\n\tconst left = rect.left + scrollX + (rect.width * anchor.xPercent) / 100;\n\tconst top = rect.top + scrollY + (rect.height * anchor.yPercent) / 100;\n\n\treturn { top, left };\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime"]}
|
package/dist/index.mjs
CHANGED
|
@@ -93,6 +93,21 @@ import { useEffect, useLayoutEffect, useRef as useRef2, useState as useState2 }
|
|
|
93
93
|
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
94
94
|
var POPOVER_OFFSET = 14;
|
|
95
95
|
var VIEWPORT_MARGIN = 8;
|
|
96
|
+
var KEYBOARD_HEIGHT_THRESHOLD = 150;
|
|
97
|
+
function useScrollIntoViewOnKeyboard(ref) {
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
const viewport = window.visualViewport;
|
|
100
|
+
if (!viewport) return;
|
|
101
|
+
const baselineHeight = viewport.height;
|
|
102
|
+
const handleResize = () => {
|
|
103
|
+
if (baselineHeight - viewport.height > KEYBOARD_HEIGHT_THRESHOLD && ref.current) {
|
|
104
|
+
ref.current.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
viewport.addEventListener("resize", handleResize);
|
|
108
|
+
return () => viewport.removeEventListener("resize", handleResize);
|
|
109
|
+
}, [ref]);
|
|
110
|
+
}
|
|
96
111
|
function CommentPopover(props) {
|
|
97
112
|
const { mode, top, left } = props;
|
|
98
113
|
const popoverRef = useRef2(null);
|
|
@@ -121,6 +136,7 @@ function CommentPopover(props) {
|
|
|
121
136
|
});
|
|
122
137
|
setSize({ width: w, height: h });
|
|
123
138
|
}, [top, left]);
|
|
139
|
+
useScrollIntoViewOnKeyboard(popoverRef);
|
|
124
140
|
const style = size ? {
|
|
125
141
|
top: `${placement.y === "bottom" ? top + POPOVER_OFFSET : top - POPOVER_OFFSET - size.height}px`,
|
|
126
142
|
left: `${placement.x === "right" ? left - POPOVER_OFFSET : left + POPOVER_OFFSET - size.width}px`
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/FeedbackOverlay.tsx","../src/components/AdminKeyModal.tsx","../src/components/ClickInterceptLayer.tsx","../src/components/CommentPopover.tsx","../src/components/FeedbackToolbar.tsx","../src/components/PinMarker.tsx","../src/components/ShareLinkButton.tsx","../src/hooks/useAuth.ts","../src/utils/resolveAnchor.ts","../src/utils/restorePosition.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { AdminKeyModal } from \"./components/AdminKeyModal\";\nimport { ClickInterceptLayer } from \"./components/ClickInterceptLayer\";\nimport { CommentPopover } from \"./components/CommentPopover\";\nimport { FeedbackToolbar } from \"./components/FeedbackToolbar\";\nimport { PinMarker } from \"./components/PinMarker\";\nimport { ShareLinkButton } from \"./components/ShareLinkButton\";\nimport { useAuth } from \"./hooks/useAuth\";\nimport type { FeedbackOverlayProps, PendingPin, PinComment } from \"./types\";\nimport { resolveAnchor } from \"./utils/resolveAnchor\";\nimport { restorePosition } from \"./utils/restorePosition\";\n\nexport function FeedbackOverlay({\n\tonCommentCreate,\n\tonCommentsFetch,\n\tonCommentDelete,\n\tonCommentUpdate,\n\tonAdminValidate,\n\tonShareLinkCreate,\n\tchildren,\n}: FeedbackOverlayProps) {\n\tconst { auth, authHeaders, setAdminKey } = useAuth();\n\tconst [comments, setComments] = useState<PinComment[]>([]);\n\tconst [pendingPin, setPendingPin] = useState<PendingPin | null>(null);\n\tconst [expandedPinId, setExpandedPinId] = useState<string | null>(null);\n\tconst [fetchError, setFetchError] = useState<string | null>(null);\n\tconst [pinMode, setPinMode] = useState(false);\n\tconst [adminModalOpen, setAdminModalOpen] = useState(false);\n\tconst hasFetched = useRef(false);\n\n\tuseEffect(() => {\n\t\tif (hasFetched.current) return;\n\t\thasFetched.current = true;\n\n\t\tonCommentsFetch(authHeaders)\n\t\t\t.then((data) => setComments([...data]))\n\t\t\t.catch(() => setFetchError(\"Couldn't load comments.\"));\n\t}, [onCommentsFetch, authHeaders]);\n\n\tconst handleClick = useCallback((clientX: number, clientY: number) => {\n\t\tsetExpandedPinId(null);\n\n\t\tconst interceptLayer = document.querySelector(\n\t\t\t\".pp-intercept\",\n\t\t) as HTMLElement;\n\t\tif (interceptLayer) interceptLayer.style.pointerEvents = \"none\";\n\t\tconst elementBelow = document.elementFromPoint(clientX, clientY);\n\t\tif (interceptLayer) interceptLayer.style.pointerEvents = \"\";\n\n\t\tif (!elementBelow) return;\n\n\t\tconst anchor = resolveAnchor(elementBelow, clientX, clientY);\n\t\tsetPendingPin({\n\t\t\tx: clientX + window.scrollX,\n\t\t\ty: clientY + window.scrollY,\n\t\t\tanchor,\n\t\t});\n\t}, []);\n\n\tconst handleSubmit = useCallback(\n\t\tasync (content: string) => {\n\t\t\tif (!pendingPin) return;\n\n\t\t\tconst comment: PinComment = {\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\turl: window.location.pathname,\n\t\t\t\tcontent,\n\t\t\t\tanchor: pendingPin.anchor,\n\t\t\t\tviewport: { width: window.innerWidth },\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t};\n\n\t\t\tawait onCommentCreate(comment, authHeaders);\n\t\t\tsetComments((prev) => [...prev, comment]);\n\t\t\tsetPendingPin(null);\n\t\t\tsetPinMode(false);\n\t\t},\n\t\t[pendingPin, onCommentCreate, authHeaders],\n\t);\n\n\tconst handleCancel = useCallback(() => {\n\t\tsetPendingPin(null);\n\t}, []);\n\n\tconst handleDelete = useCallback(\n\t\tasync (id: string) => {\n\t\t\tif (!onCommentDelete) return;\n\t\t\tawait onCommentDelete(id, authHeaders);\n\t\t\tsetComments((prev) => prev.filter((c) => c.id !== id));\n\t\t\tsetExpandedPinId(null);\n\t\t},\n\t\t[onCommentDelete, authHeaders],\n\t);\n\n\tconst handleUpdate = useCallback(\n\t\tasync (id: string, content: string) => {\n\t\t\tif (!onCommentUpdate) return;\n\t\t\tconst updated = await onCommentUpdate(id, content, authHeaders);\n\t\t\tsetComments((prev) => prev.map((c) => (c.id === id ? updated : c)));\n\t\t},\n\t\t[onCommentUpdate, authHeaders],\n\t);\n\n\tconst handlePinModeToggle = useCallback(() => {\n\t\tsetPinMode((prev) => {\n\t\t\tconst next = !prev;\n\t\t\tif (!next) setPendingPin(null);\n\t\t\treturn next;\n\t\t});\n\t}, []);\n\n\tconst handleAdminValidate = useCallback(\n\t\tasync (secret: string) => {\n\t\t\tif (!onAdminValidate) return false;\n\t\t\treturn onAdminValidate(secret);\n\t\t},\n\t\t[onAdminValidate],\n\t);\n\n\tconst handleAdminSuccess = useCallback(\n\t\t(secret: string) => {\n\t\t\tsetAdminKey(secret);\n\t\t\tsetAdminModalOpen(false);\n\t\t},\n\t\t[setAdminKey],\n\t);\n\n\tconst handleShareCreate = useCallback(\n\t\tasync (label?: string, ttl?: number) => {\n\t\t\tif (!onShareLinkCreate) throw new Error(\"onShareLinkCreate not provided\");\n\t\t\treturn onShareLinkCreate(label, ttl, authHeaders);\n\t\t},\n\t\t[onShareLinkCreate, authHeaders],\n\t);\n\n\treturn (\n\t\t<div data-pin-point=\"\">\n\t\t\t{children}\n\t\t\t{pinMode && <ClickInterceptLayer onClick={handleClick} />}\n\n\t\t\t{comments.map((comment, index) => {\n\t\t\t\tconst pos = restorePosition(comment.anchor);\n\t\t\t\tif (!pos) return null;\n\n\t\t\t\treturn (\n\t\t\t\t\t<PinMarker\n\t\t\t\t\t\tkey={comment.id}\n\t\t\t\t\t\tnumber={index + 1}\n\t\t\t\t\t\ttop={pos.top}\n\t\t\t\t\t\tleft={pos.left}\n\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\tsetExpandedPinId(expandedPinId === comment.id ? null : comment.id)\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t})}\n\n\t\t\t{expandedPinId &&\n\t\t\t\t(() => {\n\t\t\t\t\tconst comment = comments.find((c) => c.id === expandedPinId);\n\t\t\t\t\tif (!comment) return null;\n\t\t\t\t\tconst pos = restorePosition(comment.anchor);\n\t\t\t\t\tif (!pos) return null;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<CommentPopover\n\t\t\t\t\t\t\tmode=\"read\"\n\t\t\t\t\t\t\tcontent={comment.content}\n\t\t\t\t\t\t\tcreatedAt={comment.createdAt}\n\t\t\t\t\t\t\tviewportWidth={comment.viewport.width}\n\t\t\t\t\t\t\ttop={pos.top}\n\t\t\t\t\t\t\tleft={pos.left}\n\t\t\t\t\t\t\tonDelete={\n\t\t\t\t\t\t\t\tonCommentDelete\n\t\t\t\t\t\t\t\t\t? async () => handleDelete(comment.id)\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonUpdate={\n\t\t\t\t\t\t\t\tonCommentUpdate\n\t\t\t\t\t\t\t\t\t? async (content: string) => {\n\t\t\t\t\t\t\t\t\t\t\tawait handleUpdate(comment.id, content);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})()}\n\n\t\t\t{pendingPin && (\n\t\t\t\t<>\n\t\t\t\t\t<PinMarker\n\t\t\t\t\t\tnumber={comments.length + 1}\n\t\t\t\t\t\ttop={pendingPin.y}\n\t\t\t\t\t\tleft={pendingPin.x}\n\t\t\t\t\t\tonClick={() => {}}\n\t\t\t\t\t/>\n\t\t\t\t\t<CommentPopover\n\t\t\t\t\t\tmode=\"create\"\n\t\t\t\t\t\ttop={pendingPin.y}\n\t\t\t\t\t\tleft={pendingPin.x}\n\t\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\t\tonCancel={handleCancel}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t)}\n\n\t\t\t<FeedbackToolbar\n\t\t\t\tauth={auth}\n\t\t\t\tcommentCount={comments.length}\n\t\t\t\tpinModeActive={pinMode}\n\t\t\t\tonPinModeToggle={handlePinModeToggle}\n\t\t\t\tonAdminKeyOpen={() => setAdminModalOpen(true)}\n\t\t\t\tshareButton={\n\t\t\t\t\tauth.role === \"admin\" && onShareLinkCreate ? (\n\t\t\t\t\t\t<ShareLinkButton onCreate={handleShareCreate} />\n\t\t\t\t\t) : undefined\n\t\t\t\t}\n\t\t\t\terror={fetchError ?? undefined}\n\t\t\t/>\n\n\t\t\t{adminModalOpen && (\n\t\t\t\t<AdminKeyModal\n\t\t\t\t\tonValidate={handleAdminValidate}\n\t\t\t\t\tonSuccess={handleAdminSuccess}\n\t\t\t\t\tonClose={() => setAdminModalOpen(false)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { useState } from \"react\";\n\ntype Props = {\n\tonValidate: (secret: string) => Promise<boolean>;\n\tonSuccess: (secret: string) => void;\n\tonClose: () => void;\n};\n\nexport function AdminKeyModal({ onValidate, onSuccess, onClose }: Props) {\n\tconst [value, setValue] = useState(\"\");\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [busy, setBusy] = useState(false);\n\n\tconst handleSubmit = async () => {\n\t\tsetBusy(true);\n\t\tsetError(null);\n\t\ttry {\n\t\t\tconst ok = await onValidate(value);\n\t\t\tif (ok) {\n\t\t\t\tonSuccess(value);\n\t\t\t} else {\n\t\t\t\tsetError(\"Invalid admin key\");\n\t\t\t}\n\t\t} catch {\n\t\t\tsetError(\"Could not reach server\");\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: backdrop click dismissal, Cancel button and Escape are primary dismissal paths\n\t\t// biome-ignore lint/a11y/noStaticElementInteractions: backdrop is a visual scrim, inner dialog has role\n\t\t<div className=\"pp-modal-backdrop\" onClick={onClose}>\n\t\t\t{/* biome-ignore lint/a11y/useKeyWithClickEvents: stopPropagation only, not an interactive element */}\n\t\t\t<div\n\t\t\t\tclassName=\"pp-modal\"\n\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\trole=\"dialog\"\n\t\t\t\taria-modal=\"true\"\n\t\t\t>\n\t\t\t\t<h3>Enter admin key</h3>\n\t\t\t\t<input\n\t\t\t\t\ttype=\"password\"\n\t\t\t\t\tplaceholder=\"Admin key\"\n\t\t\t\t\tvalue={value}\n\t\t\t\t\tonChange={(e) => setValue(e.target.value)}\n\t\t\t\t\tdisabled={busy}\n\t\t\t\t/>\n\t\t\t\t{error && <div className=\"pp-modal-error\">{error}</div>}\n\t\t\t\t<div className=\"pp-modal-actions\">\n\t\t\t\t\t<button type=\"button\" onClick={onClose} disabled={busy}>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleSubmit}\n\t\t\t\t\t\tdisabled={busy || !value}\n\t\t\t\t\t>\n\t\t\t\t\t\tSave\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { useCallback, useRef } from \"react\";\n\ntype ClickInterceptLayerProps = {\n\tonClick: (clientX: number, clientY: number) => void;\n};\n\nexport function ClickInterceptLayer({ onClick }: ClickInterceptLayerProps) {\n\tconst lastClickTime = useRef(0);\n\n\tconst handleClick = useCallback(\n\t\t(e: React.MouseEvent) => {\n\t\t\tconst now = Date.now();\n\t\t\tif (now - lastClickTime.current < 300) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlastClickTime.current = now;\n\t\t\tonClick(e.clientX, e.clientY);\n\t\t},\n\t\t[onClick],\n\t);\n\n\treturn (\n\t\t// biome-ignore lint/a11y/noStaticElementInteractions: click-only overlay for pin placement\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: click-only overlay for pin placement\n\t\t<div className=\"pp-intercept\" onClick={handleClick} />\n\t);\n}\n","import type React from \"react\";\nimport { useEffect, useLayoutEffect, useRef, useState } from \"react\";\n\ntype ReadProps = {\n\tmode: \"read\";\n\tcontent: string;\n\tcreatedAt: string;\n\tviewportWidth: number;\n\ttop: number;\n\tleft: number;\n\tonDelete?: () => Promise<void>;\n\tonUpdate?: (content: string) => Promise<void>;\n\tonSubmit?: never;\n\tonCancel?: never;\n};\n\ntype CreateProps = {\n\tmode: \"create\";\n\ttop: number;\n\tleft: number;\n\tonSubmit: (content: string) => Promise<void>;\n\tonCancel: () => void;\n\tcontent?: never;\n\tcreatedAt?: never;\n\tviewportWidth?: never;\n};\n\ntype CommentPopoverProps = ReadProps | CreateProps;\n\ntype Placement = { x: \"right\" | \"left\"; y: \"bottom\" | \"top\" };\n\nconst POPOVER_OFFSET = 14;\nconst VIEWPORT_MARGIN = 8;\n\nexport function CommentPopover(props: CommentPopoverProps) {\n\tconst { mode, top, left } = props;\n\tconst popoverRef = useRef<HTMLDivElement>(null);\n\tconst [placement, setPlacement] = useState<Placement>({\n\t\tx: \"right\",\n\t\ty: \"bottom\",\n\t});\n\tconst [size, setSize] = useState<{ width: number; height: number } | null>(\n\t\tnull,\n\t);\n\n\tuseLayoutEffect(() => {\n\t\tconst el = popoverRef.current;\n\t\tif (!el) return;\n\t\tconst rect = el.getBoundingClientRect();\n\t\tconst w = rect.width;\n\t\tconst h = rect.height;\n\n\t\tconst pinViewX = left - window.scrollX;\n\t\tconst pinViewY = top - window.scrollY;\n\n\t\tconst fitsRight =\n\t\t\tpinViewX - POPOVER_OFFSET + w + VIEWPORT_MARGIN <= window.innerWidth;\n\t\tconst fitsLeft = pinViewX + POPOVER_OFFSET - w - VIEWPORT_MARGIN >= 0;\n\t\tconst fitsBottom =\n\t\t\tpinViewY + POPOVER_OFFSET + h + VIEWPORT_MARGIN <= window.innerHeight;\n\t\tconst fitsTop = pinViewY - POPOVER_OFFSET - h - VIEWPORT_MARGIN >= 0;\n\n\t\tsetPlacement({\n\t\t\tx: fitsRight ? \"right\" : fitsLeft ? \"left\" : \"right\",\n\t\t\ty: fitsBottom ? \"bottom\" : fitsTop ? \"top\" : \"bottom\",\n\t\t});\n\t\tsetSize({ width: w, height: h });\n\t}, [top, left]);\n\n\tconst style: React.CSSProperties = size\n\t\t? {\n\t\t\t\ttop: `${\n\t\t\t\t\tplacement.y === \"bottom\"\n\t\t\t\t\t\t? top + POPOVER_OFFSET\n\t\t\t\t\t\t: top - POPOVER_OFFSET - size.height\n\t\t\t\t}px`,\n\t\t\t\tleft: `${\n\t\t\t\t\tplacement.x === \"right\"\n\t\t\t\t\t\t? left - POPOVER_OFFSET\n\t\t\t\t\t\t: left + POPOVER_OFFSET - size.width\n\t\t\t\t}px`,\n\t\t\t}\n\t\t: {\n\t\t\t\ttop: `${top + POPOVER_OFFSET}px`,\n\t\t\t\tleft: `${left - POPOVER_OFFSET}px`,\n\t\t\t\tvisibility: \"hidden\",\n\t\t\t};\n\n\treturn (\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: stopPropagation only, not interactive\n\t\t<div\n\t\t\tref={popoverRef}\n\t\t\tclassName=\"pp-popover\"\n\t\t\tdata-placement-x={placement.x}\n\t\t\tdata-placement-y={placement.y}\n\t\t\tstyle={style}\n\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\trole=\"dialog\"\n\t\t>\n\t\t\t<div className=\"pp-popover-arrow\" />\n\t\t\t{mode === \"read\" ? (\n\t\t\t\t<ReadContent\n\t\t\t\t\tcontent={props.content}\n\t\t\t\t\tcreatedAt={props.createdAt}\n\t\t\t\t\tviewportWidth={props.viewportWidth}\n\t\t\t\t\tonDelete={props.onDelete}\n\t\t\t\t\tonUpdate={props.onUpdate}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<CreateContent onSubmit={props.onSubmit} onCancel={props.onCancel} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction ReadContent({\n\tcontent,\n\tcreatedAt,\n\tviewportWidth,\n\tonDelete,\n\tonUpdate,\n}: {\n\tcontent: string;\n\tcreatedAt: string;\n\tviewportWidth: number;\n\tonDelete?: () => Promise<void>;\n\tonUpdate?: (content: string) => Promise<void>;\n}) {\n\tconst [isConfirmingDelete, setIsConfirmingDelete] = useState(false);\n\tconst [isEditing, setIsEditing] = useState(false);\n\tconst [editContent, setEditContent] = useState(content);\n\tconst [saving, setSaving] = useState(false);\n\tconst [deleting, setDeleting] = useState(false);\n\tconst [deleteError, setDeleteError] = useState(false);\n\tconst [editError, setEditError] = useState(false);\n\n\tuseEffect(() => setEditContent(content), [content]);\n\n\tconst date = new Date(createdAt).toLocaleDateString(undefined, {\n\t\tmonth: \"short\",\n\t\tday: \"numeric\",\n\t\tyear: \"numeric\",\n\t});\n\n\tif (isEditing) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<textarea\n\t\t\t\t\tclassName=\"pp-popover-textarea\"\n\t\t\t\t\tvalue={editContent}\n\t\t\t\t\tonChange={(e) => setEditContent(e.target.value)}\n\t\t\t\t/>\n\t\t\t\t<div className=\"pp-popover-actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetIsEditing(false);\n\t\t\t\t\t\t\tsetEditContent(content);\n\t\t\t\t\t\t\tsetEditError(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--submit\"\n\t\t\t\t\t\tdisabled={editContent.trim().length === 0 || saving}\n\t\t\t\t\t\tonClick={async () => {\n\t\t\t\t\t\t\tsetSaving(true);\n\t\t\t\t\t\t\tsetEditError(false);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait onUpdate?.(editContent);\n\t\t\t\t\t\t\t\tsetIsEditing(false);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tsetEditError(true);\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tsetSaving(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tSave\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t{editError && (\n\t\t\t\t\t<div className=\"pp-popover-error\">Couldn't save. Try again.</div>\n\t\t\t\t)}\n\t\t\t</>\n\t\t);\n\t}\n\n\tif (isConfirmingDelete) {\n\t\treturn (\n\t\t\t<div className=\"pp-delete-confirm\">\n\t\t\t\t<div className=\"pp-delete-confirm-icon\">\n\t\t\t\t\t<svg\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\twidth=\"20\"\n\t\t\t\t\t\theight=\"20\"\n\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t\t\t\t<line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n\t\t\t\t\t\t<line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n\t\t\t\t\t</svg>\n\t\t\t\t</div>\n\t\t\t\t<p className=\"pp-delete-confirm-text\">Delete this comment?</p>\n\t\t\t\t{deleteError && (\n\t\t\t\t\t<div className=\"pp-popover-error\">Couldn't delete. Try again.</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"pp-delete-confirm-actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\t\tdisabled={deleting}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetIsConfirmingDelete(false);\n\t\t\t\t\t\t\tsetDeleteError(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--danger\"\n\t\t\t\t\t\tdisabled={deleting}\n\t\t\t\t\t\tonClick={async () => {\n\t\t\t\t\t\t\tsetDeleting(true);\n\t\t\t\t\t\t\tsetDeleteError(false);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait onDelete?.();\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tsetDeleteError(true);\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tsetDeleting(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{deleting ? \"Deleting...\" : \"Delete\"}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"pp-popover-content\">{content}</div>\n\t\t\t<div className=\"pp-popover-footer\">\n\t\t\t\t<div className=\"pp-popover-meta\">\n\t\t\t\t\t{date} · {viewportWidth}px viewport\n\t\t\t\t</div>\n\t\t\t\t{(onDelete || onUpdate) && (\n\t\t\t\t\t<div className=\"pp-popover-actions-row\">\n\t\t\t\t\t\t{onUpdate && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"pp-action-btn\"\n\t\t\t\t\t\t\t\taria-label=\"Edit\"\n\t\t\t\t\t\t\t\tonClick={() => setIsEditing(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\twidth=\"13\"\n\t\t\t\t\t\t\t\t\theight=\"13\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path d=\"M17 3a2.83 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z\" />\n\t\t\t\t\t\t\t\t\t<path d=\"m15 5 4 4\" />\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onDelete && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"pp-action-btn pp-action-btn--danger\"\n\t\t\t\t\t\t\t\taria-label=\"Delete\"\n\t\t\t\t\t\t\t\tonClick={() => setIsConfirmingDelete(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\twidth=\"13\"\n\t\t\t\t\t\t\t\t\theight=\"13\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path d=\"M3 6h18\" />\n\t\t\t\t\t\t\t\t\t<path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\" />\n\t\t\t\t\t\t\t\t\t<path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\" />\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</>\n\t);\n}\n\nfunction CreateContent({\n\tonSubmit,\n\tonCancel,\n}: {\n\tonSubmit: (content: string) => Promise<void>;\n\tonCancel: () => void;\n}) {\n\tconst [text, setText] = useState(\"\");\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [submitting, setSubmitting] = useState(false);\n\n\tconst handleSubmit = async () => {\n\t\tsetError(null);\n\t\tsetSubmitting(true);\n\t\ttry {\n\t\t\tawait onSubmit(text);\n\t\t} catch {\n\t\t\tsetError(\"Couldn't save. Try again.\");\n\t\t} finally {\n\t\t\tsetSubmitting(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<textarea\n\t\t\t\tclassName=\"pp-popover-textarea\"\n\t\t\t\tplaceholder=\"Leave your feedback...\"\n\t\t\t\tvalue={text}\n\t\t\t\tonChange={(e) => setText(e.target.value)}\n\t\t\t/>\n\t\t\t<div className=\"pp-popover-actions\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\tonClick={onCancel}\n\t\t\t\t>\n\t\t\t\t\tCancel\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-btn pp-btn--submit\"\n\t\t\t\t\tonClick={handleSubmit}\n\t\t\t\t\tdisabled={text.trim().length === 0 || submitting}\n\t\t\t\t>\n\t\t\t\t\tSubmit\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{error && <div className=\"pp-popover-error\">{error}</div>}\n\t\t</>\n\t);\n}\n","import type React from \"react\";\nimport type { PinAuth } from \"../types\";\n\ntype FeedbackToolbarProps = {\n\tauth: PinAuth;\n\tcommentCount: number;\n\tpinModeActive: boolean;\n\tonPinModeToggle: () => void;\n\tonAdminKeyOpen: () => void;\n\tshareButton?: React.ReactNode;\n\terror?: string;\n};\n\nconst CommentIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"16\"\n\t\theight=\"16\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n\t</svg>\n);\n\nconst KeyIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"16\"\n\t\theight=\"16\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"m21 2-9.6 9.6\" />\n\t\t<circle cx=\"7.5\" cy=\"15.5\" r=\"5.5\" />\n\t\t<path d=\"m15.5 7.5 3 3\" />\n\t</svg>\n);\n\nexport function FeedbackToolbar({\n\tauth,\n\tcommentCount,\n\tpinModeActive,\n\tonPinModeToggle,\n\tonAdminKeyOpen,\n\tshareButton,\n\terror,\n}: FeedbackToolbarProps) {\n\tconst commentDisabled = auth.role === \"anonymous\";\n\tconst commentTitle = commentDisabled\n\t\t? \"Sign in with a share link to leave feedback\"\n\t\t: pinModeActive\n\t\t\t? \"Exit pin mode\"\n\t\t\t: \"Leave feedback\";\n\tconst showAdminKey = auth.role !== \"tokenHolder\";\n\n\treturn (\n\t\t<div className=\"pp-toolbar\">\n\t\t\t<div className=\"pp-toolbar-dot\" />\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"pp-toolbar-btn\"\n\t\t\t\tonClick={onPinModeToggle}\n\t\t\t\tdisabled={commentDisabled}\n\t\t\t\taria-pressed={pinModeActive}\n\t\t\t\taria-label=\"Leave feedback\"\n\t\t\t\ttitle={commentTitle}\n\t\t\t>\n\t\t\t\t<CommentIcon />\n\t\t\t</button>\n\t\t\t{showAdminKey && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-toolbar-btn\"\n\t\t\t\t\tonClick={onAdminKeyOpen}\n\t\t\t\t\taria-label=\"Enter admin key\"\n\t\t\t\t\ttitle=\"Enter admin key\"\n\t\t\t\t>\n\t\t\t\t\t<KeyIcon />\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{shareButton}\n\t\t\t{error ? (\n\t\t\t\t<span className=\"pp-toolbar-error\">{error}</span>\n\t\t\t) : (\n\t\t\t\t<span className=\"pp-toolbar-badge\">\n\t\t\t\t\t{commentCount} {commentCount === 1 ? \"comment\" : \"comments\"}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","type PinMarkerProps = {\n\tnumber: number;\n\ttop: number;\n\tleft: number;\n\tonClick: () => void;\n};\n\nexport function PinMarker({ number, top, left, onClick }: PinMarkerProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName=\"pp-pin\"\n\t\t\tstyle={{ top: `${top}px`, left: `${left}px` }}\n\t\t\tonClick={(e) => {\n\t\t\t\te.stopPropagation();\n\t\t\t\tonClick();\n\t\t\t}}\n\t\t>\n\t\t\t{number}\n\t\t</button>\n\t);\n}\n","import { useState } from \"react\";\n\ntype Props = {\n\tonCreate: (\n\t\tlabel?: string,\n\t\texpiresInHours?: number,\n\t) => Promise<{ tokenId: string }>;\n};\n\nconst ShareIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2.2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8\" />\n\t\t<polyline points=\"16 6 12 2 8 6\" />\n\t\t<line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"15\" />\n\t</svg>\n);\n\nconst CheckIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2.5\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t</svg>\n);\n\nexport function ShareLinkButton({ onCreate }: Props) {\n\tconst [busy, setBusy] = useState(false);\n\tconst [copied, setCopied] = useState(false);\n\n\tconst handleClick = async () => {\n\t\tsetBusy(true);\n\t\ttry {\n\t\t\tconst { tokenId } = await onCreate();\n\t\t\tconst url = new URL(window.location.href);\n\t\t\turl.searchParams.set(\"pin-token\", tokenId);\n\t\t\tawait navigator.clipboard.writeText(url.toString());\n\t\t\tsetCopied(true);\n\t\t\tsetTimeout(() => setCopied(false), 2000);\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className=\"pp-share-wrapper\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"pp-share-btn\"\n\t\t\t\tonClick={handleClick}\n\t\t\t\tdisabled={busy}\n\t\t\t\tdata-state={copied ? \"copied\" : busy ? \"busy\" : \"idle\"}\n\t\t\t>\n\t\t\t\t{copied ? <CheckIcon /> : <ShareIcon />}\n\t\t\t\t<span>{copied ? \"Link copied\" : \"Share for feedback\"}</span>\n\t\t\t</button>\n\t\t</div>\n\t);\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport type { AuthHeaders, PinAuth } from \"../types\";\n\nconst ADMIN_KEY_STORAGE = \"pin-admin-key\";\nconst TOKEN_QUERY_PARAM = \"pin-token\";\n\nconst resolveAuth = (): PinAuth => {\n\tif (typeof window === \"undefined\") return { role: \"anonymous\" };\n\n\tconst params = new URLSearchParams(window.location.search);\n\tconst token = params.get(TOKEN_QUERY_PARAM);\n\tif (token) return { role: \"tokenHolder\", token };\n\n\tconst adminKey = localStorage.getItem(ADMIN_KEY_STORAGE);\n\tif (adminKey) return { role: \"admin\", secret: adminKey };\n\n\treturn { role: \"anonymous\" };\n};\n\nconst computeHeaders = (auth: PinAuth): AuthHeaders => {\n\tswitch (auth.role) {\n\t\tcase \"tokenHolder\":\n\t\t\treturn { \"X-Pin-Token\": auth.token };\n\t\tcase \"admin\":\n\t\t\treturn { \"X-Pin-Admin\": auth.secret };\n\t\tcase \"anonymous\":\n\t\t\treturn {};\n\t}\n};\n\nexport const useAuth = () => {\n\tconst [auth, setAuth] = useState<PinAuth>(resolveAuth);\n\n\tuseEffect(() => {\n\t\tconst onPopState = () => setAuth(resolveAuth());\n\t\twindow.addEventListener(\"popstate\", onPopState);\n\t\treturn () => window.removeEventListener(\"popstate\", onPopState);\n\t}, []);\n\n\tconst setAdminKey = useCallback((secret: string) => {\n\t\tlocalStorage.setItem(ADMIN_KEY_STORAGE, secret);\n\t\tsetAuth(resolveAuth());\n\t}, []);\n\n\tconst clearAdminKey = useCallback(() => {\n\t\tlocalStorage.removeItem(ADMIN_KEY_STORAGE);\n\t\tsetAuth(resolveAuth());\n\t}, []);\n\n\treturn {\n\t\tauth,\n\t\tauthHeaders: computeHeaders(auth),\n\t\tsetAdminKey,\n\t\tclearAdminKey,\n\t};\n};\n","import type { AnchorData } from \"../types\";\n\nconst DATA_ATTR_PRIORITY = [\"data-testid\", \"data-cy\"];\n\nfunction findAnchorElement(element: Element): {\n\tel: Element;\n\tselector: string;\n} {\n\t// 1. Check clicked element for id\n\tif (element.id) {\n\t\treturn { el: element, selector: `#${CSS.escape(element.id)}` };\n\t}\n\n\t// 2. Walk up to nearest ancestor with id\n\tlet current = element.parentElement;\n\twhile (current && current !== document.body) {\n\t\tif (current.id) {\n\t\t\treturn { el: current, selector: `#${CSS.escape(current.id)}` };\n\t\t}\n\t\tcurrent = current.parentElement;\n\t}\n\n\t// 3. Check element and ancestors for data attributes\n\tcurrent = element as HTMLElement;\n\twhile (current && current !== document.body) {\n\t\tfor (const attr of DATA_ATTR_PRIORITY) {\n\t\t\tconst value = current.getAttribute(attr);\n\t\t\tif (value) {\n\t\t\t\treturn { el: current, selector: `[${attr}=\"${CSS.escape(value)}\"]` };\n\t\t\t}\n\t\t}\n\t\t// Check any other data-* attribute\n\t\tfor (const attr of current.getAttributeNames()) {\n\t\t\tif (attr.startsWith(\"data-\") && !DATA_ATTR_PRIORITY.includes(attr)) {\n\t\t\t\tconst value = current.getAttribute(attr);\n\t\t\t\treturn {\n\t\t\t\t\tel: current,\n\t\t\t\t\tselector: `[${attr}=\"${CSS.escape(value ?? \"\")}\"]`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentElement as HTMLElement;\n\t}\n\n\t// 4. Fallback: structural path (max 3 levels)\n\treturn { el: element, selector: buildStructuralSelector(element) };\n}\n\nfunction buildStructuralSelector(element: Element): string {\n\tconst parts: string[] = [];\n\tlet current: Element | null = element;\n\tlet depth = 0;\n\n\twhile (current && current !== document.body && depth < 3) {\n\t\tconst tag = current.tagName.toLowerCase();\n\t\tconst parent: Element | null = current.parentElement;\n\n\t\tif (parent) {\n\t\t\tconst siblings = Array.from(parent.children).filter(\n\t\t\t\t(c: Element) => c.tagName === current?.tagName,\n\t\t\t);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst index = siblings.indexOf(current) + 1;\n\t\t\t\tparts.unshift(`${tag}:nth-of-type(${index})`);\n\t\t\t} else {\n\t\t\t\tparts.unshift(tag);\n\t\t\t}\n\t\t} else {\n\t\t\tparts.unshift(tag);\n\t\t}\n\n\t\tcurrent = parent;\n\t\tdepth++;\n\t}\n\n\treturn parts.join(\" > \");\n}\n\nfunction computePercentages(\n\tanchorEl: Element,\n\tclickX: number,\n\tclickY: number,\n): { xPercent: number; yPercent: number } {\n\tconst rect = anchorEl.getBoundingClientRect();\n\tconst width = rect.width || 1;\n\tconst height = rect.height || 1;\n\n\tconst xPercent = ((clickX - rect.left) / width) * 100;\n\tconst yPercent = ((clickY - rect.top) / height) * 100;\n\n\treturn { xPercent, yPercent };\n}\n\nexport function resolveAnchor(\n\telement: Element,\n\tclickX: number,\n\tclickY: number,\n): AnchorData {\n\tconst { el, selector } = findAnchorElement(element);\n\tconst { xPercent, yPercent } = computePercentages(el, clickX, clickY);\n\n\treturn { selector, xPercent, yPercent };\n}\n","import type { AnchorData } from \"../types\";\n\nexport function restorePosition(\n\tanchor: AnchorData,\n): { top: number; left: number } | null {\n\tif (!anchor.selector) {\n\t\treturn null;\n\t}\n\n\tlet el: Element | null;\n\ttry {\n\t\tel = document.querySelector(anchor.selector);\n\t} catch {\n\t\treturn null;\n\t}\n\n\tif (!el) {\n\t\treturn null;\n\t}\n\n\tconst rect = el.getBoundingClientRect();\n\tconst scrollX = window.scrollX;\n\tconst scrollY = window.scrollY;\n\n\tconst left = rect.left + scrollX + (rect.width * anchor.xPercent) / 100;\n\tconst top = rect.top + scrollY + (rect.height * anchor.yPercent) / 100;\n\n\treturn { top, left };\n}\n"],"mappings":"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","names":["useCallback","useEffect","useRef","useState","jsx","useRef","useState","jsx","jsxs","jsx","jsxs","jsx","useState","jsx","jsxs","useCallback","useEffect","useState","Fragment","jsx","jsxs","useState","useRef","useEffect","useCallback"]}
|
|
1
|
+
{"version":3,"sources":["../src/FeedbackOverlay.tsx","../src/components/AdminKeyModal.tsx","../src/components/ClickInterceptLayer.tsx","../src/components/CommentPopover.tsx","../src/components/FeedbackToolbar.tsx","../src/components/PinMarker.tsx","../src/components/ShareLinkButton.tsx","../src/hooks/useAuth.ts","../src/utils/resolveAnchor.ts","../src/utils/restorePosition.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { AdminKeyModal } from \"./components/AdminKeyModal\";\nimport { ClickInterceptLayer } from \"./components/ClickInterceptLayer\";\nimport { CommentPopover } from \"./components/CommentPopover\";\nimport { FeedbackToolbar } from \"./components/FeedbackToolbar\";\nimport { PinMarker } from \"./components/PinMarker\";\nimport { ShareLinkButton } from \"./components/ShareLinkButton\";\nimport { useAuth } from \"./hooks/useAuth\";\nimport type { FeedbackOverlayProps, PendingPin, PinComment } from \"./types\";\nimport { resolveAnchor } from \"./utils/resolveAnchor\";\nimport { restorePosition } from \"./utils/restorePosition\";\n\nexport function FeedbackOverlay({\n\tonCommentCreate,\n\tonCommentsFetch,\n\tonCommentDelete,\n\tonCommentUpdate,\n\tonAdminValidate,\n\tonShareLinkCreate,\n\tchildren,\n}: FeedbackOverlayProps) {\n\tconst { auth, authHeaders, setAdminKey } = useAuth();\n\tconst [comments, setComments] = useState<PinComment[]>([]);\n\tconst [pendingPin, setPendingPin] = useState<PendingPin | null>(null);\n\tconst [expandedPinId, setExpandedPinId] = useState<string | null>(null);\n\tconst [fetchError, setFetchError] = useState<string | null>(null);\n\tconst [pinMode, setPinMode] = useState(false);\n\tconst [adminModalOpen, setAdminModalOpen] = useState(false);\n\tconst hasFetched = useRef(false);\n\n\tuseEffect(() => {\n\t\tif (hasFetched.current) return;\n\t\thasFetched.current = true;\n\n\t\tonCommentsFetch(authHeaders)\n\t\t\t.then((data) => setComments([...data]))\n\t\t\t.catch(() => setFetchError(\"Couldn't load comments.\"));\n\t}, [onCommentsFetch, authHeaders]);\n\n\tconst handleClick = useCallback((clientX: number, clientY: number) => {\n\t\tsetExpandedPinId(null);\n\n\t\tconst interceptLayer = document.querySelector(\n\t\t\t\".pp-intercept\",\n\t\t) as HTMLElement;\n\t\tif (interceptLayer) interceptLayer.style.pointerEvents = \"none\";\n\t\tconst elementBelow = document.elementFromPoint(clientX, clientY);\n\t\tif (interceptLayer) interceptLayer.style.pointerEvents = \"\";\n\n\t\tif (!elementBelow) return;\n\n\t\tconst anchor = resolveAnchor(elementBelow, clientX, clientY);\n\t\tsetPendingPin({\n\t\t\tx: clientX + window.scrollX,\n\t\t\ty: clientY + window.scrollY,\n\t\t\tanchor,\n\t\t});\n\t}, []);\n\n\tconst handleSubmit = useCallback(\n\t\tasync (content: string) => {\n\t\t\tif (!pendingPin) return;\n\n\t\t\tconst comment: PinComment = {\n\t\t\t\tid: crypto.randomUUID(),\n\t\t\t\turl: window.location.pathname,\n\t\t\t\tcontent,\n\t\t\t\tanchor: pendingPin.anchor,\n\t\t\t\tviewport: { width: window.innerWidth },\n\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t};\n\n\t\t\tawait onCommentCreate(comment, authHeaders);\n\t\t\tsetComments((prev) => [...prev, comment]);\n\t\t\tsetPendingPin(null);\n\t\t\tsetPinMode(false);\n\t\t},\n\t\t[pendingPin, onCommentCreate, authHeaders],\n\t);\n\n\tconst handleCancel = useCallback(() => {\n\t\tsetPendingPin(null);\n\t}, []);\n\n\tconst handleDelete = useCallback(\n\t\tasync (id: string) => {\n\t\t\tif (!onCommentDelete) return;\n\t\t\tawait onCommentDelete(id, authHeaders);\n\t\t\tsetComments((prev) => prev.filter((c) => c.id !== id));\n\t\t\tsetExpandedPinId(null);\n\t\t},\n\t\t[onCommentDelete, authHeaders],\n\t);\n\n\tconst handleUpdate = useCallback(\n\t\tasync (id: string, content: string) => {\n\t\t\tif (!onCommentUpdate) return;\n\t\t\tconst updated = await onCommentUpdate(id, content, authHeaders);\n\t\t\tsetComments((prev) => prev.map((c) => (c.id === id ? updated : c)));\n\t\t},\n\t\t[onCommentUpdate, authHeaders],\n\t);\n\n\tconst handlePinModeToggle = useCallback(() => {\n\t\tsetPinMode((prev) => {\n\t\t\tconst next = !prev;\n\t\t\tif (!next) setPendingPin(null);\n\t\t\treturn next;\n\t\t});\n\t}, []);\n\n\tconst handleAdminValidate = useCallback(\n\t\tasync (secret: string) => {\n\t\t\tif (!onAdminValidate) return false;\n\t\t\treturn onAdminValidate(secret);\n\t\t},\n\t\t[onAdminValidate],\n\t);\n\n\tconst handleAdminSuccess = useCallback(\n\t\t(secret: string) => {\n\t\t\tsetAdminKey(secret);\n\t\t\tsetAdminModalOpen(false);\n\t\t},\n\t\t[setAdminKey],\n\t);\n\n\tconst handleShareCreate = useCallback(\n\t\tasync (label?: string, ttl?: number) => {\n\t\t\tif (!onShareLinkCreate) throw new Error(\"onShareLinkCreate not provided\");\n\t\t\treturn onShareLinkCreate(label, ttl, authHeaders);\n\t\t},\n\t\t[onShareLinkCreate, authHeaders],\n\t);\n\n\treturn (\n\t\t<div data-pin-point=\"\">\n\t\t\t{children}\n\t\t\t{pinMode && <ClickInterceptLayer onClick={handleClick} />}\n\n\t\t\t{comments.map((comment, index) => {\n\t\t\t\tconst pos = restorePosition(comment.anchor);\n\t\t\t\tif (!pos) return null;\n\n\t\t\t\treturn (\n\t\t\t\t\t<PinMarker\n\t\t\t\t\t\tkey={comment.id}\n\t\t\t\t\t\tnumber={index + 1}\n\t\t\t\t\t\ttop={pos.top}\n\t\t\t\t\t\tleft={pos.left}\n\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\tsetExpandedPinId(expandedPinId === comment.id ? null : comment.id)\n\t\t\t\t\t\t}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t})}\n\n\t\t\t{expandedPinId &&\n\t\t\t\t(() => {\n\t\t\t\t\tconst comment = comments.find((c) => c.id === expandedPinId);\n\t\t\t\t\tif (!comment) return null;\n\t\t\t\t\tconst pos = restorePosition(comment.anchor);\n\t\t\t\t\tif (!pos) return null;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<CommentPopover\n\t\t\t\t\t\t\tmode=\"read\"\n\t\t\t\t\t\t\tcontent={comment.content}\n\t\t\t\t\t\t\tcreatedAt={comment.createdAt}\n\t\t\t\t\t\t\tviewportWidth={comment.viewport.width}\n\t\t\t\t\t\t\ttop={pos.top}\n\t\t\t\t\t\t\tleft={pos.left}\n\t\t\t\t\t\t\tonDelete={\n\t\t\t\t\t\t\t\tonCommentDelete\n\t\t\t\t\t\t\t\t\t? async () => handleDelete(comment.id)\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonUpdate={\n\t\t\t\t\t\t\t\tonCommentUpdate\n\t\t\t\t\t\t\t\t\t? async (content: string) => {\n\t\t\t\t\t\t\t\t\t\t\tawait handleUpdate(comment.id, content);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})()}\n\n\t\t\t{pendingPin && (\n\t\t\t\t<>\n\t\t\t\t\t<PinMarker\n\t\t\t\t\t\tnumber={comments.length + 1}\n\t\t\t\t\t\ttop={pendingPin.y}\n\t\t\t\t\t\tleft={pendingPin.x}\n\t\t\t\t\t\tonClick={() => {}}\n\t\t\t\t\t/>\n\t\t\t\t\t<CommentPopover\n\t\t\t\t\t\tmode=\"create\"\n\t\t\t\t\t\ttop={pendingPin.y}\n\t\t\t\t\t\tleft={pendingPin.x}\n\t\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\t\tonCancel={handleCancel}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t)}\n\n\t\t\t<FeedbackToolbar\n\t\t\t\tauth={auth}\n\t\t\t\tcommentCount={comments.length}\n\t\t\t\tpinModeActive={pinMode}\n\t\t\t\tonPinModeToggle={handlePinModeToggle}\n\t\t\t\tonAdminKeyOpen={() => setAdminModalOpen(true)}\n\t\t\t\tshareButton={\n\t\t\t\t\tauth.role === \"admin\" && onShareLinkCreate ? (\n\t\t\t\t\t\t<ShareLinkButton onCreate={handleShareCreate} />\n\t\t\t\t\t) : undefined\n\t\t\t\t}\n\t\t\t\terror={fetchError ?? undefined}\n\t\t\t/>\n\n\t\t\t{adminModalOpen && (\n\t\t\t\t<AdminKeyModal\n\t\t\t\t\tonValidate={handleAdminValidate}\n\t\t\t\t\tonSuccess={handleAdminSuccess}\n\t\t\t\t\tonClose={() => setAdminModalOpen(false)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import { useState } from \"react\";\n\ntype Props = {\n\tonValidate: (secret: string) => Promise<boolean>;\n\tonSuccess: (secret: string) => void;\n\tonClose: () => void;\n};\n\nexport function AdminKeyModal({ onValidate, onSuccess, onClose }: Props) {\n\tconst [value, setValue] = useState(\"\");\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [busy, setBusy] = useState(false);\n\n\tconst handleSubmit = async () => {\n\t\tsetBusy(true);\n\t\tsetError(null);\n\t\ttry {\n\t\t\tconst ok = await onValidate(value);\n\t\t\tif (ok) {\n\t\t\t\tonSuccess(value);\n\t\t\t} else {\n\t\t\t\tsetError(\"Invalid admin key\");\n\t\t\t}\n\t\t} catch {\n\t\t\tsetError(\"Could not reach server\");\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: backdrop click dismissal, Cancel button and Escape are primary dismissal paths\n\t\t// biome-ignore lint/a11y/noStaticElementInteractions: backdrop is a visual scrim, inner dialog has role\n\t\t<div className=\"pp-modal-backdrop\" onClick={onClose}>\n\t\t\t{/* biome-ignore lint/a11y/useKeyWithClickEvents: stopPropagation only, not an interactive element */}\n\t\t\t<div\n\t\t\t\tclassName=\"pp-modal\"\n\t\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\t\trole=\"dialog\"\n\t\t\t\taria-modal=\"true\"\n\t\t\t>\n\t\t\t\t<h3>Enter admin key</h3>\n\t\t\t\t<input\n\t\t\t\t\ttype=\"password\"\n\t\t\t\t\tplaceholder=\"Admin key\"\n\t\t\t\t\tvalue={value}\n\t\t\t\t\tonChange={(e) => setValue(e.target.value)}\n\t\t\t\t\tdisabled={busy}\n\t\t\t\t/>\n\t\t\t\t{error && <div className=\"pp-modal-error\">{error}</div>}\n\t\t\t\t<div className=\"pp-modal-actions\">\n\t\t\t\t\t<button type=\"button\" onClick={onClose} disabled={busy}>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleSubmit}\n\t\t\t\t\t\tdisabled={busy || !value}\n\t\t\t\t\t>\n\t\t\t\t\t\tSave\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { useCallback, useRef } from \"react\";\n\ntype ClickInterceptLayerProps = {\n\tonClick: (clientX: number, clientY: number) => void;\n};\n\nexport function ClickInterceptLayer({ onClick }: ClickInterceptLayerProps) {\n\tconst lastClickTime = useRef(0);\n\n\tconst handleClick = useCallback(\n\t\t(e: React.MouseEvent) => {\n\t\t\tconst now = Date.now();\n\t\t\tif (now - lastClickTime.current < 300) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlastClickTime.current = now;\n\t\t\tonClick(e.clientX, e.clientY);\n\t\t},\n\t\t[onClick],\n\t);\n\n\treturn (\n\t\t// biome-ignore lint/a11y/noStaticElementInteractions: click-only overlay for pin placement\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: click-only overlay for pin placement\n\t\t<div className=\"pp-intercept\" onClick={handleClick} />\n\t);\n}\n","import type React from \"react\";\nimport { useEffect, useLayoutEffect, useRef, useState } from \"react\";\n\ntype ReadProps = {\n\tmode: \"read\";\n\tcontent: string;\n\tcreatedAt: string;\n\tviewportWidth: number;\n\ttop: number;\n\tleft: number;\n\tonDelete?: () => Promise<void>;\n\tonUpdate?: (content: string) => Promise<void>;\n\tonSubmit?: never;\n\tonCancel?: never;\n};\n\ntype CreateProps = {\n\tmode: \"create\";\n\ttop: number;\n\tleft: number;\n\tonSubmit: (content: string) => Promise<void>;\n\tonCancel: () => void;\n\tcontent?: never;\n\tcreatedAt?: never;\n\tviewportWidth?: never;\n};\n\ntype CommentPopoverProps = ReadProps | CreateProps;\n\ntype Placement = { x: \"right\" | \"left\"; y: \"bottom\" | \"top\" };\n\nconst POPOVER_OFFSET = 14;\nconst VIEWPORT_MARGIN = 8;\nconst KEYBOARD_HEIGHT_THRESHOLD = 150;\n\nfunction useScrollIntoViewOnKeyboard(\n\tref: React.RefObject<HTMLDivElement | null>,\n) {\n\tuseEffect(() => {\n\t\tconst viewport = window.visualViewport;\n\t\tif (!viewport) return;\n\n\t\tconst baselineHeight = viewport.height;\n\n\t\tconst handleResize = () => {\n\t\t\tif (\n\t\t\t\tbaselineHeight - viewport.height > KEYBOARD_HEIGHT_THRESHOLD &&\n\t\t\t\tref.current\n\t\t\t) {\n\t\t\t\tref.current.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n\t\t\t}\n\t\t};\n\n\t\tviewport.addEventListener(\"resize\", handleResize);\n\t\treturn () => viewport.removeEventListener(\"resize\", handleResize);\n\t}, [ref]);\n}\n\nexport function CommentPopover(props: CommentPopoverProps) {\n\tconst { mode, top, left } = props;\n\tconst popoverRef = useRef<HTMLDivElement>(null);\n\tconst [placement, setPlacement] = useState<Placement>({\n\t\tx: \"right\",\n\t\ty: \"bottom\",\n\t});\n\tconst [size, setSize] = useState<{ width: number; height: number } | null>(\n\t\tnull,\n\t);\n\n\tuseLayoutEffect(() => {\n\t\tconst el = popoverRef.current;\n\t\tif (!el) return;\n\t\tconst rect = el.getBoundingClientRect();\n\t\tconst w = rect.width;\n\t\tconst h = rect.height;\n\n\t\tconst pinViewX = left - window.scrollX;\n\t\tconst pinViewY = top - window.scrollY;\n\n\t\tconst fitsRight =\n\t\t\tpinViewX - POPOVER_OFFSET + w + VIEWPORT_MARGIN <= window.innerWidth;\n\t\tconst fitsLeft = pinViewX + POPOVER_OFFSET - w - VIEWPORT_MARGIN >= 0;\n\t\tconst fitsBottom =\n\t\t\tpinViewY + POPOVER_OFFSET + h + VIEWPORT_MARGIN <= window.innerHeight;\n\t\tconst fitsTop = pinViewY - POPOVER_OFFSET - h - VIEWPORT_MARGIN >= 0;\n\n\t\tsetPlacement({\n\t\t\tx: fitsRight ? \"right\" : fitsLeft ? \"left\" : \"right\",\n\t\t\ty: fitsBottom ? \"bottom\" : fitsTop ? \"top\" : \"bottom\",\n\t\t});\n\t\tsetSize({ width: w, height: h });\n\t}, [top, left]);\n\n\tuseScrollIntoViewOnKeyboard(popoverRef);\n\n\tconst style: React.CSSProperties = size\n\t\t? {\n\t\t\t\ttop: `${\n\t\t\t\t\tplacement.y === \"bottom\"\n\t\t\t\t\t\t? top + POPOVER_OFFSET\n\t\t\t\t\t\t: top - POPOVER_OFFSET - size.height\n\t\t\t\t}px`,\n\t\t\t\tleft: `${\n\t\t\t\t\tplacement.x === \"right\"\n\t\t\t\t\t\t? left - POPOVER_OFFSET\n\t\t\t\t\t\t: left + POPOVER_OFFSET - size.width\n\t\t\t\t}px`,\n\t\t\t}\n\t\t: {\n\t\t\t\ttop: `${top + POPOVER_OFFSET}px`,\n\t\t\t\tleft: `${left - POPOVER_OFFSET}px`,\n\t\t\t\tvisibility: \"hidden\",\n\t\t\t};\n\n\treturn (\n\t\t// biome-ignore lint/a11y/useKeyWithClickEvents: stopPropagation only, not interactive\n\t\t<div\n\t\t\tref={popoverRef}\n\t\t\tclassName=\"pp-popover\"\n\t\t\tdata-placement-x={placement.x}\n\t\t\tdata-placement-y={placement.y}\n\t\t\tstyle={style}\n\t\t\tonClick={(e) => e.stopPropagation()}\n\t\t\trole=\"dialog\"\n\t\t>\n\t\t\t<div className=\"pp-popover-arrow\" />\n\t\t\t{mode === \"read\" ? (\n\t\t\t\t<ReadContent\n\t\t\t\t\tcontent={props.content}\n\t\t\t\t\tcreatedAt={props.createdAt}\n\t\t\t\t\tviewportWidth={props.viewportWidth}\n\t\t\t\t\tonDelete={props.onDelete}\n\t\t\t\t\tonUpdate={props.onUpdate}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<CreateContent onSubmit={props.onSubmit} onCancel={props.onCancel} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction ReadContent({\n\tcontent,\n\tcreatedAt,\n\tviewportWidth,\n\tonDelete,\n\tonUpdate,\n}: {\n\tcontent: string;\n\tcreatedAt: string;\n\tviewportWidth: number;\n\tonDelete?: () => Promise<void>;\n\tonUpdate?: (content: string) => Promise<void>;\n}) {\n\tconst [isConfirmingDelete, setIsConfirmingDelete] = useState(false);\n\tconst [isEditing, setIsEditing] = useState(false);\n\tconst [editContent, setEditContent] = useState(content);\n\tconst [saving, setSaving] = useState(false);\n\tconst [deleting, setDeleting] = useState(false);\n\tconst [deleteError, setDeleteError] = useState(false);\n\tconst [editError, setEditError] = useState(false);\n\n\tuseEffect(() => setEditContent(content), [content]);\n\n\tconst date = new Date(createdAt).toLocaleDateString(undefined, {\n\t\tmonth: \"short\",\n\t\tday: \"numeric\",\n\t\tyear: \"numeric\",\n\t});\n\n\tif (isEditing) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<textarea\n\t\t\t\t\tclassName=\"pp-popover-textarea\"\n\t\t\t\t\tvalue={editContent}\n\t\t\t\t\tonChange={(e) => setEditContent(e.target.value)}\n\t\t\t\t/>\n\t\t\t\t<div className=\"pp-popover-actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetIsEditing(false);\n\t\t\t\t\t\t\tsetEditContent(content);\n\t\t\t\t\t\t\tsetEditError(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--submit\"\n\t\t\t\t\t\tdisabled={editContent.trim().length === 0 || saving}\n\t\t\t\t\t\tonClick={async () => {\n\t\t\t\t\t\t\tsetSaving(true);\n\t\t\t\t\t\t\tsetEditError(false);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait onUpdate?.(editContent);\n\t\t\t\t\t\t\t\tsetIsEditing(false);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tsetEditError(true);\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tsetSaving(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tSave\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t\t{editError && (\n\t\t\t\t\t<div className=\"pp-popover-error\">Couldn't save. Try again.</div>\n\t\t\t\t)}\n\t\t\t</>\n\t\t);\n\t}\n\n\tif (isConfirmingDelete) {\n\t\treturn (\n\t\t\t<div className=\"pp-delete-confirm\">\n\t\t\t\t<div className=\"pp-delete-confirm-icon\">\n\t\t\t\t\t<svg\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\twidth=\"20\"\n\t\t\t\t\t\theight=\"20\"\n\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\" />\n\t\t\t\t\t\t<line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n\t\t\t\t\t\t<line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n\t\t\t\t\t</svg>\n\t\t\t\t</div>\n\t\t\t\t<p className=\"pp-delete-confirm-text\">Delete this comment?</p>\n\t\t\t\t{deleteError && (\n\t\t\t\t\t<div className=\"pp-popover-error\">Couldn't delete. Try again.</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"pp-delete-confirm-actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\t\tdisabled={deleting}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\tsetIsConfirmingDelete(false);\n\t\t\t\t\t\t\tsetDeleteError(false);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\tCancel\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"pp-btn pp-btn--danger\"\n\t\t\t\t\t\tdisabled={deleting}\n\t\t\t\t\t\tonClick={async () => {\n\t\t\t\t\t\t\tsetDeleting(true);\n\t\t\t\t\t\t\tsetDeleteError(false);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait onDelete?.();\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tsetDeleteError(true);\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tsetDeleting(false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{deleting ? \"Deleting...\" : \"Delete\"}\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\"pp-popover-content\">{content}</div>\n\t\t\t<div className=\"pp-popover-footer\">\n\t\t\t\t<div className=\"pp-popover-meta\">\n\t\t\t\t\t{date} · {viewportWidth}px viewport\n\t\t\t\t</div>\n\t\t\t\t{(onDelete || onUpdate) && (\n\t\t\t\t\t<div className=\"pp-popover-actions-row\">\n\t\t\t\t\t\t{onUpdate && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"pp-action-btn\"\n\t\t\t\t\t\t\t\taria-label=\"Edit\"\n\t\t\t\t\t\t\t\tonClick={() => setIsEditing(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\twidth=\"13\"\n\t\t\t\t\t\t\t\t\theight=\"13\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path d=\"M17 3a2.83 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z\" />\n\t\t\t\t\t\t\t\t\t<path d=\"m15 5 4 4\" />\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{onDelete && (\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tclassName=\"pp-action-btn pp-action-btn--danger\"\n\t\t\t\t\t\t\t\taria-label=\"Delete\"\n\t\t\t\t\t\t\t\tonClick={() => setIsConfirmingDelete(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\t\t\twidth=\"13\"\n\t\t\t\t\t\t\t\t\theight=\"13\"\n\t\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<path d=\"M3 6h18\" />\n\t\t\t\t\t\t\t\t\t<path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\" />\n\t\t\t\t\t\t\t\t\t<path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\" />\n\t\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</>\n\t);\n}\n\nfunction CreateContent({\n\tonSubmit,\n\tonCancel,\n}: {\n\tonSubmit: (content: string) => Promise<void>;\n\tonCancel: () => void;\n}) {\n\tconst [text, setText] = useState(\"\");\n\tconst [error, setError] = useState<string | null>(null);\n\tconst [submitting, setSubmitting] = useState(false);\n\n\tconst handleSubmit = async () => {\n\t\tsetError(null);\n\t\tsetSubmitting(true);\n\t\ttry {\n\t\t\tawait onSubmit(text);\n\t\t} catch {\n\t\t\tsetError(\"Couldn't save. Try again.\");\n\t\t} finally {\n\t\t\tsetSubmitting(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<textarea\n\t\t\t\tclassName=\"pp-popover-textarea\"\n\t\t\t\tplaceholder=\"Leave your feedback...\"\n\t\t\t\tvalue={text}\n\t\t\t\tonChange={(e) => setText(e.target.value)}\n\t\t\t/>\n\t\t\t<div className=\"pp-popover-actions\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-btn pp-btn--cancel\"\n\t\t\t\t\tonClick={onCancel}\n\t\t\t\t>\n\t\t\t\t\tCancel\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-btn pp-btn--submit\"\n\t\t\t\t\tonClick={handleSubmit}\n\t\t\t\t\tdisabled={text.trim().length === 0 || submitting}\n\t\t\t\t>\n\t\t\t\t\tSubmit\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t{error && <div className=\"pp-popover-error\">{error}</div>}\n\t\t</>\n\t);\n}\n","import type React from \"react\";\nimport type { PinAuth } from \"../types\";\n\ntype FeedbackToolbarProps = {\n\tauth: PinAuth;\n\tcommentCount: number;\n\tpinModeActive: boolean;\n\tonPinModeToggle: () => void;\n\tonAdminKeyOpen: () => void;\n\tshareButton?: React.ReactNode;\n\terror?: string;\n};\n\nconst CommentIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"16\"\n\t\theight=\"16\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n\t</svg>\n);\n\nconst KeyIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"16\"\n\t\theight=\"16\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"m21 2-9.6 9.6\" />\n\t\t<circle cx=\"7.5\" cy=\"15.5\" r=\"5.5\" />\n\t\t<path d=\"m15.5 7.5 3 3\" />\n\t</svg>\n);\n\nexport function FeedbackToolbar({\n\tauth,\n\tcommentCount,\n\tpinModeActive,\n\tonPinModeToggle,\n\tonAdminKeyOpen,\n\tshareButton,\n\terror,\n}: FeedbackToolbarProps) {\n\tconst commentDisabled = auth.role === \"anonymous\";\n\tconst commentTitle = commentDisabled\n\t\t? \"Sign in with a share link to leave feedback\"\n\t\t: pinModeActive\n\t\t\t? \"Exit pin mode\"\n\t\t\t: \"Leave feedback\";\n\tconst showAdminKey = auth.role !== \"tokenHolder\";\n\n\treturn (\n\t\t<div className=\"pp-toolbar\">\n\t\t\t<div className=\"pp-toolbar-dot\" />\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"pp-toolbar-btn\"\n\t\t\t\tonClick={onPinModeToggle}\n\t\t\t\tdisabled={commentDisabled}\n\t\t\t\taria-pressed={pinModeActive}\n\t\t\t\taria-label=\"Leave feedback\"\n\t\t\t\ttitle={commentTitle}\n\t\t\t>\n\t\t\t\t<CommentIcon />\n\t\t\t</button>\n\t\t\t{showAdminKey && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclassName=\"pp-toolbar-btn\"\n\t\t\t\t\tonClick={onAdminKeyOpen}\n\t\t\t\t\taria-label=\"Enter admin key\"\n\t\t\t\t\ttitle=\"Enter admin key\"\n\t\t\t\t>\n\t\t\t\t\t<KeyIcon />\n\t\t\t\t</button>\n\t\t\t)}\n\t\t\t{shareButton}\n\t\t\t{error ? (\n\t\t\t\t<span className=\"pp-toolbar-error\">{error}</span>\n\t\t\t) : (\n\t\t\t\t<span className=\"pp-toolbar-badge\">\n\t\t\t\t\t{commentCount} {commentCount === 1 ? \"comment\" : \"comments\"}\n\t\t\t\t</span>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","type PinMarkerProps = {\n\tnumber: number;\n\ttop: number;\n\tleft: number;\n\tonClick: () => void;\n};\n\nexport function PinMarker({ number, top, left, onClick }: PinMarkerProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclassName=\"pp-pin\"\n\t\t\tstyle={{ top: `${top}px`, left: `${left}px` }}\n\t\t\tonClick={(e) => {\n\t\t\t\te.stopPropagation();\n\t\t\t\tonClick();\n\t\t\t}}\n\t\t>\n\t\t\t{number}\n\t\t</button>\n\t);\n}\n","import { useState } from \"react\";\n\ntype Props = {\n\tonCreate: (\n\t\tlabel?: string,\n\t\texpiresInHours?: number,\n\t) => Promise<{ tokenId: string }>;\n};\n\nconst ShareIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2.2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<path d=\"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8\" />\n\t\t<polyline points=\"16 6 12 2 8 6\" />\n\t\t<line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"15\" />\n\t</svg>\n);\n\nconst CheckIcon = () => (\n\t<svg\n\t\taria-hidden=\"true\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tviewBox=\"0 0 24 24\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2.5\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t>\n\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t</svg>\n);\n\nexport function ShareLinkButton({ onCreate }: Props) {\n\tconst [busy, setBusy] = useState(false);\n\tconst [copied, setCopied] = useState(false);\n\n\tconst handleClick = async () => {\n\t\tsetBusy(true);\n\t\ttry {\n\t\t\tconst { tokenId } = await onCreate();\n\t\t\tconst url = new URL(window.location.href);\n\t\t\turl.searchParams.set(\"pin-token\", tokenId);\n\t\t\tawait navigator.clipboard.writeText(url.toString());\n\t\t\tsetCopied(true);\n\t\t\tsetTimeout(() => setCopied(false), 2000);\n\t\t} finally {\n\t\t\tsetBusy(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className=\"pp-share-wrapper\">\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName=\"pp-share-btn\"\n\t\t\t\tonClick={handleClick}\n\t\t\t\tdisabled={busy}\n\t\t\t\tdata-state={copied ? \"copied\" : busy ? \"busy\" : \"idle\"}\n\t\t\t>\n\t\t\t\t{copied ? <CheckIcon /> : <ShareIcon />}\n\t\t\t\t<span>{copied ? \"Link copied\" : \"Share for feedback\"}</span>\n\t\t\t</button>\n\t\t</div>\n\t);\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport type { AuthHeaders, PinAuth } from \"../types\";\n\nconst ADMIN_KEY_STORAGE = \"pin-admin-key\";\nconst TOKEN_QUERY_PARAM = \"pin-token\";\n\nconst resolveAuth = (): PinAuth => {\n\tif (typeof window === \"undefined\") return { role: \"anonymous\" };\n\n\tconst params = new URLSearchParams(window.location.search);\n\tconst token = params.get(TOKEN_QUERY_PARAM);\n\tif (token) return { role: \"tokenHolder\", token };\n\n\tconst adminKey = localStorage.getItem(ADMIN_KEY_STORAGE);\n\tif (adminKey) return { role: \"admin\", secret: adminKey };\n\n\treturn { role: \"anonymous\" };\n};\n\nconst computeHeaders = (auth: PinAuth): AuthHeaders => {\n\tswitch (auth.role) {\n\t\tcase \"tokenHolder\":\n\t\t\treturn { \"X-Pin-Token\": auth.token };\n\t\tcase \"admin\":\n\t\t\treturn { \"X-Pin-Admin\": auth.secret };\n\t\tcase \"anonymous\":\n\t\t\treturn {};\n\t}\n};\n\nexport const useAuth = () => {\n\tconst [auth, setAuth] = useState<PinAuth>(resolveAuth);\n\n\tuseEffect(() => {\n\t\tconst onPopState = () => setAuth(resolveAuth());\n\t\twindow.addEventListener(\"popstate\", onPopState);\n\t\treturn () => window.removeEventListener(\"popstate\", onPopState);\n\t}, []);\n\n\tconst setAdminKey = useCallback((secret: string) => {\n\t\tlocalStorage.setItem(ADMIN_KEY_STORAGE, secret);\n\t\tsetAuth(resolveAuth());\n\t}, []);\n\n\tconst clearAdminKey = useCallback(() => {\n\t\tlocalStorage.removeItem(ADMIN_KEY_STORAGE);\n\t\tsetAuth(resolveAuth());\n\t}, []);\n\n\treturn {\n\t\tauth,\n\t\tauthHeaders: computeHeaders(auth),\n\t\tsetAdminKey,\n\t\tclearAdminKey,\n\t};\n};\n","import type { AnchorData } from \"../types\";\n\nconst DATA_ATTR_PRIORITY = [\"data-testid\", \"data-cy\"];\n\nfunction findAnchorElement(element: Element): {\n\tel: Element;\n\tselector: string;\n} {\n\t// 1. Check clicked element for id\n\tif (element.id) {\n\t\treturn { el: element, selector: `#${CSS.escape(element.id)}` };\n\t}\n\n\t// 2. Walk up to nearest ancestor with id\n\tlet current = element.parentElement;\n\twhile (current && current !== document.body) {\n\t\tif (current.id) {\n\t\t\treturn { el: current, selector: `#${CSS.escape(current.id)}` };\n\t\t}\n\t\tcurrent = current.parentElement;\n\t}\n\n\t// 3. Check element and ancestors for data attributes\n\tcurrent = element as HTMLElement;\n\twhile (current && current !== document.body) {\n\t\tfor (const attr of DATA_ATTR_PRIORITY) {\n\t\t\tconst value = current.getAttribute(attr);\n\t\t\tif (value) {\n\t\t\t\treturn { el: current, selector: `[${attr}=\"${CSS.escape(value)}\"]` };\n\t\t\t}\n\t\t}\n\t\t// Check any other data-* attribute\n\t\tfor (const attr of current.getAttributeNames()) {\n\t\t\tif (attr.startsWith(\"data-\") && !DATA_ATTR_PRIORITY.includes(attr)) {\n\t\t\t\tconst value = current.getAttribute(attr);\n\t\t\t\treturn {\n\t\t\t\t\tel: current,\n\t\t\t\t\tselector: `[${attr}=\"${CSS.escape(value ?? \"\")}\"]`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tcurrent = current.parentElement as HTMLElement;\n\t}\n\n\t// 4. Fallback: structural path (max 3 levels)\n\treturn { el: element, selector: buildStructuralSelector(element) };\n}\n\nfunction buildStructuralSelector(element: Element): string {\n\tconst parts: string[] = [];\n\tlet current: Element | null = element;\n\tlet depth = 0;\n\n\twhile (current && current !== document.body && depth < 3) {\n\t\tconst tag = current.tagName.toLowerCase();\n\t\tconst parent: Element | null = current.parentElement;\n\n\t\tif (parent) {\n\t\t\tconst siblings = Array.from(parent.children).filter(\n\t\t\t\t(c: Element) => c.tagName === current?.tagName,\n\t\t\t);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst index = siblings.indexOf(current) + 1;\n\t\t\t\tparts.unshift(`${tag}:nth-of-type(${index})`);\n\t\t\t} else {\n\t\t\t\tparts.unshift(tag);\n\t\t\t}\n\t\t} else {\n\t\t\tparts.unshift(tag);\n\t\t}\n\n\t\tcurrent = parent;\n\t\tdepth++;\n\t}\n\n\treturn parts.join(\" > \");\n}\n\nfunction computePercentages(\n\tanchorEl: Element,\n\tclickX: number,\n\tclickY: number,\n): { xPercent: number; yPercent: number } {\n\tconst rect = anchorEl.getBoundingClientRect();\n\tconst width = rect.width || 1;\n\tconst height = rect.height || 1;\n\n\tconst xPercent = ((clickX - rect.left) / width) * 100;\n\tconst yPercent = ((clickY - rect.top) / height) * 100;\n\n\treturn { xPercent, yPercent };\n}\n\nexport function resolveAnchor(\n\telement: Element,\n\tclickX: number,\n\tclickY: number,\n): AnchorData {\n\tconst { el, selector } = findAnchorElement(element);\n\tconst { xPercent, yPercent } = computePercentages(el, clickX, clickY);\n\n\treturn { selector, xPercent, yPercent };\n}\n","import type { AnchorData } from \"../types\";\n\nexport function restorePosition(\n\tanchor: AnchorData,\n): { top: number; left: number } | null {\n\tif (!anchor.selector) {\n\t\treturn null;\n\t}\n\n\tlet el: Element | null;\n\ttry {\n\t\tel = document.querySelector(anchor.selector);\n\t} catch {\n\t\treturn null;\n\t}\n\n\tif (!el) {\n\t\treturn null;\n\t}\n\n\tconst rect = el.getBoundingClientRect();\n\tconst scrollX = window.scrollX;\n\tconst scrollY = window.scrollY;\n\n\tconst left = rect.left + scrollX + (rect.width * anchor.xPercent) / 100;\n\tconst top = rect.top + scrollY + (rect.height * anchor.yPercent) / 100;\n\n\treturn { top, left };\n}\n"],"mappings":"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","names":["useCallback","useEffect","useRef","useState","jsx","useRef","useState","jsx","jsxs","jsx","jsxs","jsx","useState","jsx","jsxs","useCallback","useEffect","useState","Fragment","jsx","jsxs","useState","useRef","useEffect","useCallback"]}
|
package/package.json
CHANGED