@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.
- package/README.md +119 -0
- package/dist/index.d.mts +32 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +941 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +914 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles/pin-point.css +523 -0
- package/dist/styles/pin-point.css.map +1 -0
- package/dist/styles/pin-point.d.mts +2 -0
- package/dist/styles/pin-point.d.ts +2 -0
- package/package.json +62 -0
|
@@ -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 */
|