@tonytangdev/pin-point 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +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"]}
@@ -0,0 +1,523 @@
1
+ /* src/styles/pin-point.css */
2
+ [data-pin-point] .pp-intercept {
3
+ position: fixed;
4
+ top: 0;
5
+ left: 0;
6
+ width: 100%;
7
+ height: 100%;
8
+ z-index: 2147483647;
9
+ cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cdefs%3E%3Cfilter id='s' x='-50%25' y='-50%25' width='200%25' height='200%25'%3E%3CfeDropShadow dx='0' dy='2' stdDeviation='1.5' flood-color='%23000' flood-opacity='0.45'/%3E%3C/filter%3E%3C/defs%3E%3Cg filter='url(%23s)'%3E%3Cpath d='M28 13c0 9.5-12 17-12 17S4 22.5 4 13a12 12 0 0 1 24 0z' fill='%236c5ce7' stroke='%23ffffff' stroke-width='2.5' stroke-linejoin='round'/%3E%3Cpath d='M16 9v8M12 13h8' stroke='%23ffffff' stroke-width='2.2' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E") 16 30, crosshair;
10
+ }
11
+ [data-pin-point] .pp-pin {
12
+ position: absolute;
13
+ width: 30px;
14
+ height: 30px;
15
+ background:
16
+ linear-gradient(
17
+ 180deg,
18
+ #8e7ef8 0%,
19
+ #6c5ce7 55%,
20
+ #5a4cd6 100%);
21
+ border-radius: 50%;
22
+ color: #fff;
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ font-weight: 700;
27
+ font-size: 13px;
28
+ font-family:
29
+ system-ui,
30
+ -apple-system,
31
+ sans-serif;
32
+ font-variant-numeric: tabular-nums;
33
+ letter-spacing: -0.01em;
34
+ box-shadow:
35
+ inset 0 1px 0 rgba(255, 255, 255, 0.35),
36
+ inset 0 -1px 0 rgba(0, 0, 0, 0.18),
37
+ 0 0 0 1px rgba(108, 92, 231, 0.35),
38
+ 0 2px 4px rgba(0, 0, 0, 0.15),
39
+ 0 6px 16px rgba(108, 92, 231, 0.5);
40
+ cursor: pointer;
41
+ border: 2px solid #fff;
42
+ padding: 0;
43
+ z-index: 2147483647;
44
+ transform: translate(-50%, -50%);
45
+ user-select: none;
46
+ line-height: 1;
47
+ transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 150ms ease;
48
+ }
49
+ [data-pin-point] .pp-pin:hover {
50
+ transform: translate(-50%, -50%) scale(1.12);
51
+ box-shadow:
52
+ inset 0 1px 0 rgba(255, 255, 255, 0.4),
53
+ inset 0 -1px 0 rgba(0, 0, 0, 0.18),
54
+ 0 0 0 1px rgba(108, 92, 231, 0.45),
55
+ 0 4px 8px rgba(0, 0, 0, 0.2),
56
+ 0 10px 24px rgba(108, 92, 231, 0.65);
57
+ }
58
+ [data-pin-point] .pp-pin:active {
59
+ transform: translate(-50%, -50%) scale(1.04);
60
+ }
61
+ [data-pin-point] .pp-pin--pending {
62
+ animation: pp-pulse 1.6s ease-in-out infinite;
63
+ }
64
+ @media (prefers-reduced-motion: reduce) {
65
+ [data-pin-point] .pp-pin {
66
+ transition: none;
67
+ }
68
+ [data-pin-point] .pp-pin:hover,
69
+ [data-pin-point] .pp-pin:active {
70
+ transform: translate(-50%, -50%);
71
+ }
72
+ [data-pin-point] .pp-pin--pending {
73
+ animation: none;
74
+ }
75
+ }
76
+ [data-pin-point] .pp-popover {
77
+ position: absolute;
78
+ width: 280px;
79
+ background: #fff;
80
+ border-radius: 12px;
81
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
82
+ padding: 16px;
83
+ font-family:
84
+ system-ui,
85
+ -apple-system,
86
+ sans-serif;
87
+ z-index: 2147483647;
88
+ box-sizing: border-box;
89
+ }
90
+ [data-pin-point] .pp-popover-arrow {
91
+ position: absolute;
92
+ width: 12px;
93
+ height: 12px;
94
+ background: #fff;
95
+ transform: rotate(45deg);
96
+ }
97
+ [data-pin-point] .pp-popover[data-placement-y=bottom] .pp-popover-arrow {
98
+ top: -6px;
99
+ }
100
+ [data-pin-point] .pp-popover[data-placement-y=top] .pp-popover-arrow {
101
+ bottom: -6px;
102
+ }
103
+ [data-pin-point] .pp-popover[data-placement-x=right] .pp-popover-arrow {
104
+ left: 16px;
105
+ }
106
+ [data-pin-point] .pp-popover[data-placement-x=left] .pp-popover-arrow {
107
+ right: 16px;
108
+ }
109
+ [data-pin-point] .pp-popover[data-placement-y=bottom][data-placement-x=right] .pp-popover-arrow {
110
+ box-shadow: -2px -2px 4px rgba(0, 0, 0, 0.05);
111
+ }
112
+ [data-pin-point] .pp-popover[data-placement-y=bottom][data-placement-x=left] .pp-popover-arrow {
113
+ box-shadow: 2px -2px 4px rgba(0, 0, 0, 0.05);
114
+ }
115
+ [data-pin-point] .pp-popover[data-placement-y=top][data-placement-x=right] .pp-popover-arrow {
116
+ box-shadow: -2px 2px 4px rgba(0, 0, 0, 0.05);
117
+ }
118
+ [data-pin-point] .pp-popover[data-placement-y=top][data-placement-x=left] .pp-popover-arrow {
119
+ box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.05);
120
+ }
121
+ [data-pin-point] .pp-popover-content {
122
+ font-size: 13px;
123
+ color: #333;
124
+ line-height: 1.5;
125
+ position: relative;
126
+ }
127
+ [data-pin-point] .pp-popover-meta {
128
+ font-size: 11px;
129
+ color: #999;
130
+ position: relative;
131
+ }
132
+ [data-pin-point] .pp-popover-textarea {
133
+ width: 100%;
134
+ height: 70px;
135
+ border: 1.5px solid #e0e0e0;
136
+ border-radius: 8px;
137
+ padding: 10px;
138
+ font-size: 13px;
139
+ font-family:
140
+ system-ui,
141
+ -apple-system,
142
+ sans-serif;
143
+ resize: none;
144
+ outline: none;
145
+ box-sizing: border-box;
146
+ position: relative;
147
+ }
148
+ [data-pin-point] .pp-popover-textarea:focus {
149
+ border-color: #6c5ce7;
150
+ }
151
+ [data-pin-point] .pp-popover-actions {
152
+ display: flex;
153
+ justify-content: flex-end;
154
+ gap: 8px;
155
+ margin-top: 10px;
156
+ position: relative;
157
+ }
158
+ [data-pin-point] .pp-btn {
159
+ padding: 6px 14px;
160
+ border-radius: 6px;
161
+ font-size: 12px;
162
+ cursor: pointer;
163
+ font-family:
164
+ system-ui,
165
+ -apple-system,
166
+ sans-serif;
167
+ }
168
+ [data-pin-point] .pp-btn--cancel {
169
+ border: 1px solid #ddd;
170
+ background: #fff;
171
+ color: #666;
172
+ }
173
+ [data-pin-point] .pp-btn--submit {
174
+ border: none;
175
+ background: #6c5ce7;
176
+ color: #fff;
177
+ font-weight: 600;
178
+ }
179
+ [data-pin-point] .pp-btn--submit:disabled {
180
+ opacity: 0.5;
181
+ cursor: not-allowed;
182
+ }
183
+ [data-pin-point] .pp-popover-error {
184
+ font-size: 12px;
185
+ color: #e74c3c;
186
+ margin-top: 8px;
187
+ position: relative;
188
+ }
189
+ [data-pin-point] .pp-toolbar {
190
+ position: fixed;
191
+ bottom: 24px;
192
+ left: 50%;
193
+ transform: translateX(-50%);
194
+ background: rgba(20, 20, 32, 0.78);
195
+ backdrop-filter: blur(20px) saturate(180%);
196
+ -webkit-backdrop-filter: blur(20px) saturate(180%);
197
+ color: #fff;
198
+ padding: 8px 12px;
199
+ border-radius: 999px;
200
+ font-family:
201
+ system-ui,
202
+ -apple-system,
203
+ sans-serif;
204
+ font-size: 13px;
205
+ display: flex;
206
+ align-items: center;
207
+ gap: 8px;
208
+ border: 1px solid rgba(255, 255, 255, 0.08);
209
+ box-shadow:
210
+ inset 0 1px 0 rgba(255, 255, 255, 0.08),
211
+ 0 1px 2px rgba(0, 0, 0, 0.2),
212
+ 0 12px 32px rgba(0, 0, 0, 0.35);
213
+ z-index: 2147483647;
214
+ user-select: none;
215
+ }
216
+ [data-pin-point] .pp-toolbar-dot {
217
+ width: 6px;
218
+ height: 6px;
219
+ background: #6c5ce7;
220
+ border-radius: 50%;
221
+ box-shadow: 0 0 0 3px rgba(108, 92, 231, 0.18);
222
+ margin: 0 4px 0 6px;
223
+ }
224
+ [data-pin-point] .pp-toolbar-badge {
225
+ background: rgba(255, 255, 255, 0.08);
226
+ padding: 4px 12px;
227
+ border-radius: 999px;
228
+ font-size: 12px;
229
+ font-weight: 500;
230
+ color: rgba(255, 255, 255, 0.85);
231
+ letter-spacing: 0.01em;
232
+ }
233
+ [data-pin-point] .pp-toolbar-btn {
234
+ display: inline-flex;
235
+ align-items: center;
236
+ justify-content: center;
237
+ width: 32px;
238
+ height: 32px;
239
+ background: rgba(255, 255, 255, 0.06);
240
+ color: rgba(255, 255, 255, 0.92);
241
+ border: 1px solid rgba(255, 255, 255, 0.1);
242
+ border-radius: 10px;
243
+ cursor: pointer;
244
+ font-size: 14px;
245
+ padding: 0;
246
+ transition:
247
+ background 150ms ease,
248
+ border-color 150ms ease,
249
+ color 150ms ease,
250
+ transform 100ms ease,
251
+ box-shadow 150ms ease;
252
+ }
253
+ [data-pin-point] .pp-toolbar-btn:hover:not(:disabled) {
254
+ background: rgba(255, 255, 255, 0.14);
255
+ border-color: rgba(255, 255, 255, 0.22);
256
+ color: #fff;
257
+ }
258
+ [data-pin-point] .pp-toolbar-btn:active:not(:disabled) {
259
+ transform: scale(0.94);
260
+ }
261
+ [data-pin-point] .pp-toolbar-btn[aria-pressed=true] {
262
+ background: #6c5ce7;
263
+ border-color: #7d6df0;
264
+ color: #fff;
265
+ box-shadow: 0 4px 12px rgba(108, 92, 231, 0.4);
266
+ }
267
+ [data-pin-point] .pp-toolbar-btn[aria-pressed=true]:hover:not(:disabled) {
268
+ background: #7d6df0;
269
+ border-color: #8e7ef8;
270
+ }
271
+ [data-pin-point] .pp-toolbar-btn:disabled {
272
+ opacity: 0.42;
273
+ cursor: not-allowed;
274
+ }
275
+ [data-pin-point] .pp-toolbar-error {
276
+ color: #ff6b6b;
277
+ font-size: 12px;
278
+ font-weight: 500;
279
+ padding: 0 6px;
280
+ }
281
+ @media (prefers-reduced-motion: reduce) {
282
+ [data-pin-point] .pp-toolbar-btn {
283
+ transition: none;
284
+ }
285
+ [data-pin-point] .pp-toolbar-btn:active:not(:disabled) {
286
+ transform: none;
287
+ }
288
+ }
289
+ @keyframes pp-pulse {
290
+ 0%, 100% {
291
+ box-shadow:
292
+ inset 0 1px 0 rgba(255, 255, 255, 0.35),
293
+ inset 0 -1px 0 rgba(0, 0, 0, 0.18),
294
+ 0 0 0 1px rgba(108, 92, 231, 0.35),
295
+ 0 2px 4px rgba(0, 0, 0, 0.15),
296
+ 0 6px 16px rgba(108, 92, 231, 0.5),
297
+ 0 0 0 0 rgba(108, 92, 231, 0.55);
298
+ }
299
+ 50% {
300
+ box-shadow:
301
+ inset 0 1px 0 rgba(255, 255, 255, 0.4),
302
+ inset 0 -1px 0 rgba(0, 0, 0, 0.18),
303
+ 0 0 0 1px rgba(108, 92, 231, 0.45),
304
+ 0 2px 4px rgba(0, 0, 0, 0.15),
305
+ 0 8px 20px rgba(108, 92, 231, 0.6),
306
+ 0 0 0 14px rgba(108, 92, 231, 0);
307
+ }
308
+ }
309
+ [data-pin-point] .pp-popover-footer {
310
+ display: flex;
311
+ align-items: center;
312
+ justify-content: space-between;
313
+ margin-top: 10px;
314
+ position: relative;
315
+ }
316
+ [data-pin-point] .pp-popover-actions-row {
317
+ display: flex;
318
+ gap: 2px;
319
+ }
320
+ [data-pin-point] .pp-action-btn {
321
+ display: flex;
322
+ align-items: center;
323
+ justify-content: center;
324
+ width: 28px;
325
+ height: 28px;
326
+ background: none;
327
+ border: none;
328
+ border-radius: 6px;
329
+ cursor: pointer;
330
+ color: #999;
331
+ transition: all 0.15s ease;
332
+ }
333
+ [data-pin-point] .pp-action-btn:hover {
334
+ background: #f0eeff;
335
+ color: #6c5ce7;
336
+ }
337
+ [data-pin-point] .pp-action-btn--danger:hover {
338
+ background: #fef2f2;
339
+ color: #dc3545;
340
+ }
341
+ [data-pin-point] .pp-delete-confirm {
342
+ display: flex;
343
+ flex-direction: column;
344
+ align-items: center;
345
+ gap: 8px;
346
+ padding: 4px 0;
347
+ position: relative;
348
+ }
349
+ [data-pin-point] .pp-delete-confirm-icon {
350
+ width: 36px;
351
+ height: 36px;
352
+ border-radius: 50%;
353
+ background: #fef2f2;
354
+ display: flex;
355
+ align-items: center;
356
+ justify-content: center;
357
+ color: #dc3545;
358
+ }
359
+ [data-pin-point] .pp-delete-confirm-text {
360
+ margin: 0;
361
+ font-size: 13px;
362
+ font-weight: 500;
363
+ color: #333;
364
+ font-family:
365
+ system-ui,
366
+ -apple-system,
367
+ sans-serif;
368
+ }
369
+ [data-pin-point] .pp-delete-confirm-actions {
370
+ display: flex;
371
+ gap: 8px;
372
+ width: 100%;
373
+ }
374
+ [data-pin-point] .pp-delete-confirm-actions .pp-btn {
375
+ flex: 1;
376
+ text-align: center;
377
+ }
378
+ [data-pin-point] .pp-btn--danger {
379
+ border: none;
380
+ background: #dc3545;
381
+ color: #fff;
382
+ font-weight: 600;
383
+ }
384
+ [data-pin-point] .pp-btn--danger:hover {
385
+ background: #c82333;
386
+ }
387
+ [data-pin-point] .pp-modal-backdrop {
388
+ position: fixed;
389
+ inset: 0;
390
+ background: rgba(0, 0, 0, 0.5);
391
+ display: flex;
392
+ align-items: center;
393
+ justify-content: center;
394
+ z-index: 2147483647;
395
+ }
396
+ [data-pin-point] .pp-modal {
397
+ background: #1a1a1a;
398
+ color: #fff;
399
+ border-radius: 8px;
400
+ padding: 20px;
401
+ min-width: 320px;
402
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
403
+ font-family:
404
+ system-ui,
405
+ -apple-system,
406
+ sans-serif;
407
+ }
408
+ [data-pin-point] .pp-modal h3 {
409
+ margin: 0 0 12px;
410
+ font-size: 16px;
411
+ }
412
+ [data-pin-point] .pp-modal input {
413
+ width: 100%;
414
+ padding: 8px 12px;
415
+ background: #0a0a0a;
416
+ border: 1px solid #333;
417
+ border-radius: 4px;
418
+ color: #fff;
419
+ box-sizing: border-box;
420
+ font-family: inherit;
421
+ font-size: 13px;
422
+ }
423
+ [data-pin-point] .pp-modal-error {
424
+ color: #ff6b6b;
425
+ margin-top: 8px;
426
+ font-size: 13px;
427
+ }
428
+ [data-pin-point] .pp-modal-actions {
429
+ display: flex;
430
+ gap: 8px;
431
+ justify-content: flex-end;
432
+ margin-top: 16px;
433
+ }
434
+ [data-pin-point] .pp-modal-actions button {
435
+ padding: 6px 14px;
436
+ background: #2a2a2a;
437
+ color: #fff;
438
+ border: 1px solid #444;
439
+ border-radius: 4px;
440
+ cursor: pointer;
441
+ font-family: inherit;
442
+ font-size: 12px;
443
+ }
444
+ [data-pin-point] .pp-modal-actions button:disabled {
445
+ opacity: 0.5;
446
+ cursor: not-allowed;
447
+ }
448
+ [data-pin-point] .pp-share-wrapper {
449
+ display: inline-flex;
450
+ }
451
+ [data-pin-point] .pp-share-btn {
452
+ display: inline-flex;
453
+ align-items: center;
454
+ gap: 6px;
455
+ height: 32px;
456
+ padding: 0 14px;
457
+ background:
458
+ linear-gradient(
459
+ 180deg,
460
+ #7d6df0 0%,
461
+ #6c5ce7 100%);
462
+ color: #fff;
463
+ border: 1px solid rgba(255, 255, 255, 0.18);
464
+ border-radius: 999px;
465
+ font-family:
466
+ system-ui,
467
+ -apple-system,
468
+ sans-serif;
469
+ font-size: 12px;
470
+ font-weight: 600;
471
+ letter-spacing: 0.01em;
472
+ cursor: pointer;
473
+ box-shadow:
474
+ inset 0 1px 0 rgba(255, 255, 255, 0.25),
475
+ 0 1px 2px rgba(0, 0, 0, 0.25),
476
+ 0 4px 12px rgba(108, 92, 231, 0.35);
477
+ transition:
478
+ background 150ms ease,
479
+ box-shadow 150ms ease,
480
+ transform 100ms ease,
481
+ border-color 150ms ease;
482
+ }
483
+ [data-pin-point] .pp-share-btn:hover:not(:disabled) {
484
+ background:
485
+ linear-gradient(
486
+ 180deg,
487
+ #8e7ef8 0%,
488
+ #7d6df0 100%);
489
+ border-color: rgba(255, 255, 255, 0.28);
490
+ box-shadow:
491
+ inset 0 1px 0 rgba(255, 255, 255, 0.3),
492
+ 0 1px 2px rgba(0, 0, 0, 0.25),
493
+ 0 6px 16px rgba(108, 92, 231, 0.45);
494
+ }
495
+ [data-pin-point] .pp-share-btn:active:not(:disabled) {
496
+ transform: scale(0.96);
497
+ }
498
+ [data-pin-point] .pp-share-btn:disabled {
499
+ cursor: not-allowed;
500
+ opacity: 0.7;
501
+ }
502
+ [data-pin-point] .pp-share-btn[data-state=copied] {
503
+ background:
504
+ linear-gradient(
505
+ 180deg,
506
+ #2ecc71 0%,
507
+ #27ae60 100%);
508
+ border-color: rgba(255, 255, 255, 0.28);
509
+ box-shadow:
510
+ inset 0 1px 0 rgba(255, 255, 255, 0.3),
511
+ 0 1px 2px rgba(0, 0, 0, 0.25),
512
+ 0 4px 12px rgba(46, 204, 113, 0.4);
513
+ opacity: 1;
514
+ }
515
+ @media (prefers-reduced-motion: reduce) {
516
+ [data-pin-point] .pp-share-btn {
517
+ transition: none;
518
+ }
519
+ [data-pin-point] .pp-share-btn:active:not(:disabled) {
520
+ transform: none;
521
+ }
522
+ }
523
+ /*# sourceMappingURL=pin-point.css.map */