proto-plugin 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/AGENTS.md +350 -0
- package/README.md +279 -0
- package/components.json +18 -0
- package/package.json +73 -0
- package/scripts/download-mobbin-reference-images.mjs +112 -0
- package/scripts/lib/host-config.example.sh +48 -0
- package/scripts/lib/host-config.sh +25 -0
- package/scripts/lib/resolve-host-root.mjs +18 -0
- package/scripts/lib/source-path.sh +49 -0
- package/scripts/link-source-db.sh +128 -0
- package/scripts/link-source.sh +40 -0
- package/scripts/publish-package.sh +147 -0
- package/scripts/share-prototype.sh +279 -0
- package/scripts/sync-from-source.sh +74 -0
- package/scripts/verify-prototype-component-ids.mjs +151 -0
- package/scripts/verify-prototype-preview-states.mjs +135 -0
- package/src/app.ts +4 -0
- package/src/components/platform-ui/code-block.tsx +21 -0
- package/src/components/platform-ui/controls-panel-options.tsx +71 -0
- package/src/components/platform-ui/controls-panel-select.tsx +438 -0
- package/src/components/platform-ui/empty-state.tsx +15 -0
- package/src/components/platform-ui/icon-button.tsx +18 -0
- package/src/components/platform-ui/panel-select.tsx +123 -0
- package/src/components/platform-ui/panel.tsx +97 -0
- package/src/components/platform-ui/review-dropdown-menu.tsx +35 -0
- package/src/components/platform-ui/sidebar.tsx +293 -0
- package/src/components/platform-ui/toolbar-icon-button.tsx +34 -0
- package/src/components/platform-ui/toolbar.tsx +37 -0
- package/src/components/prototype-gallery-client.tsx +57 -0
- package/src/components/prototype-provider.tsx +20 -0
- package/src/components/prototypes/mini-pill-label.tsx +37 -0
- package/src/components/prototypes/prototype-change-log-panel.tsx +207 -0
- package/src/components/prototypes/prototype-comment-provider.tsx +61 -0
- package/src/components/prototypes/prototype-comment-toolbar.tsx +65 -0
- package/src/components/prototypes/prototype-control.tsx +31 -0
- package/src/components/prototypes/prototype-controls.tsx +553 -0
- package/src/components/prototypes/prototype-create-exploration-modal.tsx +117 -0
- package/src/components/prototypes/prototype-create-state-modal.tsx +117 -0
- package/src/components/prototypes/prototype-default-state-map-page.tsx +66 -0
- package/src/components/prototypes/prototype-design-brief-modal.tsx +128 -0
- package/src/components/prototypes/prototype-design-brief-panel.tsx +525 -0
- package/src/components/prototypes/prototype-design-context-panel.tsx +65 -0
- package/src/components/prototypes/prototype-floating-pill.module.scss +1341 -0
- package/src/components/prototypes/prototype-mobbin-gallery.tsx +330 -0
- package/src/components/prototypes/prototype-reference-docs.tsx +222 -0
- package/src/components/prototypes/prototype-review-chrome.module.scss +630 -0
- package/src/components/prototypes/prototype-review-chrome.tsx +1241 -0
- package/src/components/prototypes/prototype-review-dropdown-menu-item.tsx +1 -0
- package/src/components/prototypes/prototype-review-dropdown-menu-separator.tsx +1 -0
- package/src/components/prototypes/prototype-review-panel-menu-item.tsx +1 -0
- package/src/components/prototypes/prototype-review-panel-menu-separator.tsx +1 -0
- package/src/components/prototypes/prototype-review-panel-select.tsx +4 -0
- package/src/components/prototypes/prototype-review-sidebar.tsx +167 -0
- package/src/components/prototypes/prototype-share-link-restore.tsx +75 -0
- package/src/components/prototypes/prototype-share-mode.tsx +206 -0
- package/src/components/prototypes/prototype-spec-panel-content.tsx +538 -0
- package/src/components/prototypes/prototype-state-canvas-overlay.module.scss +336 -0
- package/src/components/prototypes/prototype-state-canvas-overlay.tsx +1023 -0
- package/src/components/prototypes/prototype-state-canvas.tsx +38 -0
- package/src/components/prototypes/prototype-state-screenshot-preview.tsx +47 -0
- package/src/components/prototypes/prototype-target.tsx +120 -0
- package/src/components/prototypes/prototype-tweak-highlight.tsx +132 -0
- package/src/components/prototypes/prototype-tweaks.tsx +48 -0
- package/src/components/prototypes/prototype-variant-explorer.tsx +347 -0
- package/src/components/prototypes/prototype-variant-rationale-panel.tsx +49 -0
- package/src/components/prototypes/prototype-variant-tabs.tsx +207 -0
- package/src/components/prototypes/prototype-vercel-preview-modal.tsx +120 -0
- package/src/components/prototypes/state-map-annotation-tooltip.module.scss +89 -0
- package/src/components/prototypes/state-map-annotation-tooltip.tsx +137 -0
- package/src/components/prototypes/state-map-wireframe-highlight.module.scss +25 -0
- package/src/components/prototypes/state-map-wireframe-highlight.tsx +82 -0
- package/src/components/shell/prototype-gallery-shell.tsx +79 -0
- package/src/components/shell/prototype-screenshot-capture.tsx +45 -0
- package/src/components/shell/prototype-shell.module.scss +194 -0
- package/src/components/shell/prototype-shell.tsx +160 -0
- package/src/components/shell/prototype-state-screenshot-capture.tsx +68 -0
- package/src/components/ui/button.tsx +58 -0
- package/src/components/ui/dialog.module.scss +81 -0
- package/src/components/ui/dialog.tsx +127 -0
- package/src/components/ui/dropdown-menu.tsx +200 -0
- package/src/components/ui/input.tsx +22 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/option-select.tsx +81 -0
- package/src/components/ui/scroll-area.tsx +48 -0
- package/src/components/ui/separator.tsx +31 -0
- package/src/components/ui/slider.tsx +28 -0
- package/src/components/ui/switch.tsx +29 -0
- package/src/components/ui/tabs.tsx +55 -0
- package/src/components/ui/toggle-group.tsx +80 -0
- package/src/components/ui/tooltip.tsx +32 -0
- package/src/config/create-prototype-gallery-page.tsx +65 -0
- package/src/config/create-prototype-host-app.tsx +121 -0
- package/src/config/create-prototype-page.tsx +41 -0
- package/src/config/create-prototype-site-layout.tsx +28 -0
- package/src/config/define-prototype-config.ts +7 -0
- package/src/config/prototype-icon.tsx +25 -0
- package/src/config/prototype-site-layout-client.tsx +35 -0
- package/src/config/with-prototype.ts +20 -0
- package/src/index.ts +303 -0
- package/src/lib/pr-split/build-pr-agent-prompt.ts +68 -0
- package/src/lib/pr-split/build-pr-split-prototype-url.ts +12 -0
- package/src/lib/pr-split/pr-split-highlight.ts +6 -0
- package/src/lib/pr-split/pr-split-types.ts +58 -0
- package/src/lib/pr-split/resolve-source-preview-url.ts +45 -0
- package/src/lib/pr-split/use-pr-vercel-previews.ts +69 -0
- package/src/lib/prototype-comments/core/annotation-channel.ts +41 -0
- package/src/lib/prototype-comments/core/annotation-status.ts +60 -0
- package/src/lib/prototype-comments/core/annotation-target.ts +567 -0
- package/src/lib/prototype-comments/core/capture-theme.ts +41 -0
- package/src/lib/prototype-comments/core/capture.ts +11 -0
- package/src/lib/prototype-comments/core/comment-capture-blocked.ts +47 -0
- package/src/lib/prototype-comments/core/comment-threads.ts +52 -0
- package/src/lib/prototype-comments/core/element-identification.ts +615 -0
- package/src/lib/prototype-comments/core/export.ts +35 -0
- package/src/lib/prototype-comments/core/freeze-animations.ts +266 -0
- package/src/lib/prototype-comments/core/identify-element.ts +76 -0
- package/src/lib/prototype-comments/core/normalize-viewport.ts +35 -0
- package/src/lib/prototype-comments/core/react-detection.ts +704 -0
- package/src/lib/prototype-comments/core/restore.ts +7 -0
- package/src/lib/prototype-comments/core/screenshot.ts +428 -0
- package/src/lib/prototype-comments/core/source-location.ts +906 -0
- package/src/lib/prototype-comments/core/storage.ts +80 -0
- package/src/lib/prototype-comments/core/types.ts +79 -0
- package/src/lib/prototype-comments/core/validation.ts +17 -0
- package/src/lib/prototype-comments/hooks/useLayoutShift.ts +61 -0
- package/src/lib/prototype-comments/index.ts +58 -0
- package/src/lib/prototype-comments/react/CommentCaptureToolbar.tsx +1398 -0
- package/src/lib/prototype-comments/react/CommentProvider.tsx +298 -0
- package/src/lib/prototype-comments/scss.d.ts +10 -0
- package/src/lib/prototype-comments/ui/CommentAnnotationOverlay.tsx +253 -0
- package/src/lib/prototype-comments/ui/CommentDetailPage.tsx +56 -0
- package/src/lib/prototype-comments/ui/CommentHeaderCount.tsx +28 -0
- package/src/lib/prototype-comments/ui/CommentThread.tsx +331 -0
- package/src/lib/prototype-comments/ui/CommentsGrid.tsx +780 -0
- package/src/lib/prototype-comments/ui/CommentsListPage.tsx +25 -0
- package/src/lib/prototype-comments/ui/CommentsSidebar.tsx +77 -0
- package/src/lib/prototype-comments/ui/annotation-marker/index.tsx +200 -0
- package/src/lib/prototype-comments/ui/annotation-marker/styles.module.scss +194 -0
- package/src/lib/prototype-comments/ui/annotation-popup/index.tsx +335 -0
- package/src/lib/prototype-comments/ui/annotation-popup/styles.module.scss +469 -0
- package/src/lib/prototype-comments/ui/capture-styles.module.scss +2225 -0
- package/src/lib/prototype-comments/ui/comment-highlight.ts +48 -0
- package/src/lib/prototype-comments/ui/comment-thread.module.scss +203 -0
- package/src/lib/prototype-comments/ui/comments-grid-card.module.scss +253 -0
- package/src/lib/prototype-comments/ui/comments-sidebar.module.scss +123 -0
- package/src/lib/prototype-comments/ui/icon-transitions.module.scss +51 -0
- package/src/lib/prototype-comments/ui/icons.tsx +1086 -0
- package/src/lib/prototype-comments/ui/is-comment-detail-path.ts +7 -0
- package/src/lib/prototypes/capture-prototype-viewport.ts +32 -0
- package/src/lib/prototypes/changelog-meta-context.tsx +162 -0
- package/src/lib/prototypes/changelog-meta-storage.ts +62 -0
- package/src/lib/prototypes/changelog-meta.ts +95 -0
- package/src/lib/prototypes/create-prototype-registry.ts +74 -0
- package/src/lib/prototypes/create-state-screenshot-thumbnail.ts +46 -0
- package/src/lib/prototypes/design-exploration-default-storage.ts +68 -0
- package/src/lib/prototypes/design-exploration-default.ts +51 -0
- package/src/lib/prototypes/design-exploration-types.ts +203 -0
- package/src/lib/prototypes/prototype-comment-registry.tsx +145 -0
- package/src/lib/prototypes/prototype-comment-review-bridge.tsx +40 -0
- package/src/lib/prototypes/prototype-comment-review-state.ts +57 -0
- package/src/lib/prototypes/prototype-component-registry.ts +40 -0
- package/src/lib/prototypes/prototype-config-types.ts +34 -0
- package/src/lib/prototypes/prototype-preview-state-registry.ts +443 -0
- package/src/lib/prototypes/prototype-preview-state-types.ts +89 -0
- package/src/lib/prototypes/prototype-review-context.tsx +905 -0
- package/src/lib/prototypes/prototype-review-url.ts +134 -0
- package/src/lib/prototypes/prototype-share-link.ts +175 -0
- package/src/lib/prototypes/prototype-state-canvas-constants.ts +118 -0
- package/src/lib/prototypes/prototype-state-canvas-types.ts +159 -0
- package/src/lib/prototypes/prototype-state-screenshot.ts +39 -0
- package/src/lib/prototypes/prototype-tweak-registry.ts +96 -0
- package/src/lib/prototypes/prototype-tweak-types.ts +31 -0
- package/src/lib/prototypes/reference-docs.ts +137 -0
- package/src/lib/prototypes/screenshot-manifest.ts +33 -0
- package/src/lib/prototypes/screenshot-src.ts +7 -0
- package/src/lib/prototypes/share-command.ts +8 -0
- package/src/lib/prototypes/state-map-annotation.ts +70 -0
- package/src/lib/prototypes/use-design-exploration-default.ts +114 -0
- package/src/lib/prototypes/use-persisted-local-state.ts +140 -0
- package/src/lib/prototypes/use-prototype-comments.ts +63 -0
- package/src/lib/prototypes/use-prototype-mobile-viewport-frame.ts +46 -0
- package/src/lib/prototypes/use-prototype-state-screenshot-src.ts +71 -0
- package/src/lib/prototypes/use-prototype-tool-theme.tsx +115 -0
- package/src/lib/prototypes/use-prototype-viewport-frame.ts +34 -0
- package/src/lib/prototypes/use-register-prototype-reference-docs.ts +16 -0
- package/src/lib/prototypes/use-snap-corner-position.ts +417 -0
- package/src/lib/prototypes/use-toolbar-hover-panel.ts +98 -0
- package/src/lib/prototypes/variant-set-lucide-icon.tsx +55 -0
- package/src/lib/tool-portal.ts +33 -0
- package/src/lib/use-copy-to-clipboard.ts +81 -0
- package/src/lib/utils.ts +6 -0
- package/src/lib/vercel-preview/parse-vercel-github-comment.ts +81 -0
- package/src/server/create-host-api-route.ts +100 -0
- package/src/server/create-prototype-api-routes.ts +428 -0
- package/src/server/gallery/create-gallery-api.ts +56 -0
- package/src/server/gallery/folders-route.ts +156 -0
- package/src/server/gallery/gallery-env.ts +39 -0
- package/src/server/gallery/gallery-route.ts +150 -0
- package/src/server/gallery/gallery-types.ts +15 -0
- package/src/server/gallery/image-route.ts +59 -0
- package/src/server/gallery/item-route.ts +92 -0
- package/src/server/pr-vercel-preview-route.ts +162 -0
- package/src/server/redis/client.ts +55 -0
- package/src/server/redis/prototype-changelog-meta.ts +31 -0
- package/src/server/redis/prototype-comments.ts +92 -0
- package/src/server/redis/prototype-design-exploration-default.ts +32 -0
- package/src/server.ts +51 -0
- package/src/styles/globals.css +624 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Freeze Animations
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// Monkey-patches setTimeout, setInterval, and requestAnimationFrame so that
|
|
6
|
+
// callbacks are silently skipped while frozen. Also injects CSS to pause
|
|
7
|
+
// CSS animations/transitions, pauses WAAPI animations, and pauses videos.
|
|
8
|
+
//
|
|
9
|
+
// Toolbar/popup code must import `originalSetTimeout` etc. to bypass the patch.
|
|
10
|
+
//
|
|
11
|
+
// Patches are installed as a side effect of importing this module.
|
|
12
|
+
// =============================================================================
|
|
13
|
+
|
|
14
|
+
// Exclude selectors — prototype comment UI elements should never be frozen
|
|
15
|
+
const EXCLUDE_ATTRS = [
|
|
16
|
+
"data-feedback-toolbar",
|
|
17
|
+
"data-annotation-popup",
|
|
18
|
+
"data-annotation-marker",
|
|
19
|
+
];
|
|
20
|
+
const NOT_SELECTORS = EXCLUDE_ATTRS
|
|
21
|
+
.flatMap((a) => [`:not([${a}])`, `:not([${a}] *)`])
|
|
22
|
+
.join("");
|
|
23
|
+
|
|
24
|
+
const STYLE_ID = "feedback-freeze-styles";
|
|
25
|
+
const STATE_KEY = "__prototype_comment_freeze";
|
|
26
|
+
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Shared mutable state on window (survives HMR module re-execution)
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
interface FreezeState {
|
|
31
|
+
frozen: boolean;
|
|
32
|
+
installed: boolean;
|
|
33
|
+
origSetTimeout: typeof setTimeout;
|
|
34
|
+
origSetInterval: typeof setInterval;
|
|
35
|
+
origRAF: typeof requestAnimationFrame;
|
|
36
|
+
// Queues live on window so they survive HMR module re-execution
|
|
37
|
+
pausedAnimations: Animation[];
|
|
38
|
+
frozenTimeoutQueue: Array<() => void>;
|
|
39
|
+
frozenRAFQueue: FrameRequestCallback[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getState(): FreezeState {
|
|
43
|
+
if (typeof window === "undefined") {
|
|
44
|
+
// SSR stub
|
|
45
|
+
return {
|
|
46
|
+
frozen: false,
|
|
47
|
+
installed: true, // prevent patching on server
|
|
48
|
+
origSetTimeout: setTimeout,
|
|
49
|
+
origSetInterval: setInterval,
|
|
50
|
+
origRAF: (cb: FrameRequestCallback) => 0 as any,
|
|
51
|
+
pausedAnimations: [],
|
|
52
|
+
frozenTimeoutQueue: [],
|
|
53
|
+
frozenRAFQueue: [],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const w = window as any;
|
|
57
|
+
if (!w[STATE_KEY]) {
|
|
58
|
+
w[STATE_KEY] = {
|
|
59
|
+
frozen: false,
|
|
60
|
+
installed: false,
|
|
61
|
+
origSetTimeout: null,
|
|
62
|
+
origSetInterval: null,
|
|
63
|
+
origRAF: null,
|
|
64
|
+
pausedAnimations: [],
|
|
65
|
+
frozenTimeoutQueue: [],
|
|
66
|
+
frozenRAFQueue: [],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return w[STATE_KEY];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const _s = getState();
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Install patches (once — survives HMR because `installed` lives on window)
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
if (typeof window !== "undefined" && !_s.installed) {
|
|
78
|
+
// Save the real functions
|
|
79
|
+
_s.origSetTimeout = window.setTimeout.bind(window);
|
|
80
|
+
_s.origSetInterval = window.setInterval.bind(window);
|
|
81
|
+
_s.origRAF = window.requestAnimationFrame.bind(window);
|
|
82
|
+
|
|
83
|
+
// Patch setTimeout — queue callback when frozen (replayed on unfreeze)
|
|
84
|
+
(window as any).setTimeout = (
|
|
85
|
+
handler: TimerHandler,
|
|
86
|
+
timeout?: number,
|
|
87
|
+
...args: any[]
|
|
88
|
+
): ReturnType<typeof setTimeout> => {
|
|
89
|
+
if (typeof handler === "string") {
|
|
90
|
+
return _s.origSetTimeout(handler, timeout) as unknown as ReturnType<typeof setTimeout>;
|
|
91
|
+
}
|
|
92
|
+
return _s.origSetTimeout(
|
|
93
|
+
(...a: any[]) => {
|
|
94
|
+
if (_s.frozen) {
|
|
95
|
+
_s.frozenTimeoutQueue.push(() => (handler as Function)(...a));
|
|
96
|
+
} else {
|
|
97
|
+
(handler as Function)(...a);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
timeout,
|
|
101
|
+
...args,
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Patch setInterval — skip callback when frozen
|
|
106
|
+
(window as any).setInterval = (
|
|
107
|
+
handler: TimerHandler,
|
|
108
|
+
timeout?: number,
|
|
109
|
+
...args: any[]
|
|
110
|
+
): ReturnType<typeof setInterval> => {
|
|
111
|
+
if (typeof handler === "string") {
|
|
112
|
+
return _s.origSetInterval(handler, timeout) as unknown as ReturnType<typeof setInterval>;
|
|
113
|
+
}
|
|
114
|
+
return _s.origSetInterval(
|
|
115
|
+
(...a: any[]) => {
|
|
116
|
+
if (!_s.frozen) (handler as Function)(...a);
|
|
117
|
+
},
|
|
118
|
+
timeout,
|
|
119
|
+
...args,
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// Patch requestAnimationFrame — queue callback when frozen (no CPU spin)
|
|
124
|
+
// The wrapper fires once on the next frame; if still frozen the callback
|
|
125
|
+
// is stored in _s.frozenRAFQueue and replayed on unfreeze.
|
|
126
|
+
(window as any).requestAnimationFrame = (
|
|
127
|
+
callback: FrameRequestCallback,
|
|
128
|
+
): number => {
|
|
129
|
+
return _s.origRAF((timestamp: number) => {
|
|
130
|
+
if (_s.frozen) {
|
|
131
|
+
_s.frozenRAFQueue.push(callback);
|
|
132
|
+
} else {
|
|
133
|
+
callback(timestamp);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
_s.installed = true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
// Exports — original (unpatched) timing functions for toolbar/popup use
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
export const originalSetTimeout = _s.origSetTimeout;
|
|
145
|
+
export const originalSetInterval = _s.origSetInterval;
|
|
146
|
+
export const originalRequestAnimationFrame = _s.origRAF;
|
|
147
|
+
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
// Freeze / Unfreeze
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
|
|
152
|
+
function isPrototypeCommentChromeElement(el: Element | null): boolean {
|
|
153
|
+
if (!el) return false;
|
|
154
|
+
return EXCLUDE_ATTRS.some((attr) => !!el.closest?.(`[${attr}]`));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function freeze(): void {
|
|
158
|
+
if (typeof document === "undefined") return;
|
|
159
|
+
if (_s.frozen) return;
|
|
160
|
+
_s.frozen = true;
|
|
161
|
+
_s.frozenTimeoutQueue = [];
|
|
162
|
+
_s.frozenRAFQueue = [];
|
|
163
|
+
|
|
164
|
+
// CSS injection — pause CSS animations and kill transitions
|
|
165
|
+
let style = document.getElementById(STYLE_ID);
|
|
166
|
+
if (!style) {
|
|
167
|
+
style = document.createElement("style");
|
|
168
|
+
style.id = STYLE_ID;
|
|
169
|
+
}
|
|
170
|
+
style.textContent = `
|
|
171
|
+
*${NOT_SELECTORS},
|
|
172
|
+
*${NOT_SELECTORS}::before,
|
|
173
|
+
*${NOT_SELECTORS}::after {
|
|
174
|
+
animation-play-state: paused !important;
|
|
175
|
+
transition: none !important;
|
|
176
|
+
}
|
|
177
|
+
`;
|
|
178
|
+
document.head.appendChild(style);
|
|
179
|
+
|
|
180
|
+
// WAAPI — pause only RUNNING non-prototype-comment animations and store references
|
|
181
|
+
// (pausing finished animations would restart them on play(), breaking entrance anims)
|
|
182
|
+
_s.pausedAnimations = [];
|
|
183
|
+
try {
|
|
184
|
+
document.getAnimations().forEach((anim) => {
|
|
185
|
+
if (anim.playState !== "running") return;
|
|
186
|
+
const target = (anim.effect as KeyframeEffect)?.target as Element | null;
|
|
187
|
+
if (!isPrototypeCommentChromeElement(target)) {
|
|
188
|
+
anim.pause();
|
|
189
|
+
_s.pausedAnimations.push(anim);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
} catch {
|
|
193
|
+
// getAnimations may not be available in all environments
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Pause videos
|
|
197
|
+
document.querySelectorAll("video").forEach((video) => {
|
|
198
|
+
if (!video.paused) {
|
|
199
|
+
video.dataset.wasPaused = "false";
|
|
200
|
+
video.pause();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function unfreeze(): void {
|
|
206
|
+
if (typeof document === "undefined") return;
|
|
207
|
+
if (!_s.frozen) return;
|
|
208
|
+
_s.frozen = false;
|
|
209
|
+
|
|
210
|
+
// Replay queued setTimeout callbacks asynchronously (resolves stuck delay()
|
|
211
|
+
// Promises, restarts animation loops interrupted by visibilitychange, etc.)
|
|
212
|
+
// Using origSetTimeout(cb, 0) avoids blocking the main thread in one go.
|
|
213
|
+
// Re-check _s.frozen before executing — if freeze() was called again between
|
|
214
|
+
// scheduling and execution, re-queue the callback instead of running it.
|
|
215
|
+
const timeoutQueue = _s.frozenTimeoutQueue;
|
|
216
|
+
_s.frozenTimeoutQueue = [];
|
|
217
|
+
for (const cb of timeoutQueue) {
|
|
218
|
+
_s.origSetTimeout(() => {
|
|
219
|
+
if (_s.frozen) {
|
|
220
|
+
_s.frozenTimeoutQueue.push(cb);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
cb();
|
|
225
|
+
} catch (e) {
|
|
226
|
+
console.warn("[prototype-comments] Error replaying queued timeout:", e);
|
|
227
|
+
}
|
|
228
|
+
}, 0);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Schedule queued rAF callbacks for the next frame.
|
|
232
|
+
// Re-check _s.frozen — if re-frozen before the frame fires, re-queue.
|
|
233
|
+
const rafQueue = _s.frozenRAFQueue;
|
|
234
|
+
_s.frozenRAFQueue = [];
|
|
235
|
+
for (const cb of rafQueue) {
|
|
236
|
+
_s.origRAF((ts: number) => {
|
|
237
|
+
if (_s.frozen) {
|
|
238
|
+
_s.frozenRAFQueue.push(cb);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
cb(ts);
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// WAAPI — resume the exact animations we paused BEFORE removing CSS
|
|
246
|
+
// (removing CSS first can cause the browser to replace animation objects)
|
|
247
|
+
for (const anim of _s.pausedAnimations) {
|
|
248
|
+
try {
|
|
249
|
+
anim.play();
|
|
250
|
+
} catch (e) {
|
|
251
|
+
console.warn("[prototype-comments] Error resuming animation:", e);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
_s.pausedAnimations = [];
|
|
255
|
+
|
|
256
|
+
// Now remove CSS injection
|
|
257
|
+
document.getElementById(STYLE_ID)?.remove();
|
|
258
|
+
|
|
259
|
+
// Resume videos
|
|
260
|
+
document.querySelectorAll("video").forEach((video) => {
|
|
261
|
+
if (video.dataset.wasPaused === "false") {
|
|
262
|
+
video.play().catch(() => {});
|
|
263
|
+
delete video.dataset.wasPaused;
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAccessibilityInfo,
|
|
3
|
+
getDetailedComputedStyles,
|
|
4
|
+
getElementClasses,
|
|
5
|
+
getElementPath,
|
|
6
|
+
getForensicComputedStyles,
|
|
7
|
+
getFullElementPath,
|
|
8
|
+
getNearbyElements,
|
|
9
|
+
getNearbyText,
|
|
10
|
+
identifyElement,
|
|
11
|
+
} from "./element-identification";
|
|
12
|
+
import { getReactComponentName } from "./react-detection";
|
|
13
|
+
import {
|
|
14
|
+
formatSourceLocation,
|
|
15
|
+
findNearestComponentSource,
|
|
16
|
+
getSourceLocation,
|
|
17
|
+
} from "./source-location";
|
|
18
|
+
|
|
19
|
+
export type ReactComponentMode = "smart" | "filtered" | "all" | "off";
|
|
20
|
+
|
|
21
|
+
export function identifyElementWithReact(
|
|
22
|
+
element: HTMLElement,
|
|
23
|
+
reactMode: ReactComponentMode = "filtered",
|
|
24
|
+
): {
|
|
25
|
+
name: string;
|
|
26
|
+
elementName: string;
|
|
27
|
+
path: string;
|
|
28
|
+
reactComponents: string | null;
|
|
29
|
+
} {
|
|
30
|
+
const { name: elementName, path } = identifyElement(element);
|
|
31
|
+
|
|
32
|
+
if (reactMode === "off") {
|
|
33
|
+
return { name: elementName, elementName, path, reactComponents: null };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const reactInfo = getReactComponentName(element, { mode: reactMode });
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
name: reactInfo.path ? `${reactInfo.path} ${elementName}` : elementName,
|
|
40
|
+
elementName,
|
|
41
|
+
path,
|
|
42
|
+
reactComponents: reactInfo.path,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function isElementFixed(element: HTMLElement): boolean {
|
|
47
|
+
let current: HTMLElement | null = element;
|
|
48
|
+
while (current && current !== document.body) {
|
|
49
|
+
const style = window.getComputedStyle(current);
|
|
50
|
+
const position = style.position;
|
|
51
|
+
if (position === "fixed" || position === "sticky") {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
current = current.parentElement;
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function detectSourceFile(element: Element): string | undefined {
|
|
60
|
+
const result = getSourceLocation(element as HTMLElement);
|
|
61
|
+
const loc = result.found ? result : findNearestComponentSource(element as HTMLElement);
|
|
62
|
+
if (loc.found && loc.source) {
|
|
63
|
+
return formatSourceLocation(loc.source, "path");
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export {
|
|
69
|
+
getAccessibilityInfo,
|
|
70
|
+
getDetailedComputedStyles,
|
|
71
|
+
getElementClasses,
|
|
72
|
+
getForensicComputedStyles,
|
|
73
|
+
getFullElementPath,
|
|
74
|
+
getNearbyElements,
|
|
75
|
+
getNearbyText,
|
|
76
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AnnotationBoundingBox, CaptureViewport, CommentAnnotationFields } from "./types";
|
|
2
|
+
|
|
3
|
+
type ViewportNormalizeInput = Pick<
|
|
4
|
+
CommentAnnotationFields,
|
|
5
|
+
"boundingBox" | "isFixed" | "viewportBoundingBox" | "captureViewport"
|
|
6
|
+
>;
|
|
7
|
+
|
|
8
|
+
export function normalizeAnnotationViewport(annotation: ViewportNormalizeInput): {
|
|
9
|
+
captureViewport: CaptureViewport | undefined;
|
|
10
|
+
viewportBoundingBox: AnnotationBoundingBox | undefined;
|
|
11
|
+
} {
|
|
12
|
+
const captureViewport =
|
|
13
|
+
annotation.captureViewport ??
|
|
14
|
+
(typeof window !== "undefined"
|
|
15
|
+
? {
|
|
16
|
+
width: window.innerWidth,
|
|
17
|
+
height: window.innerHeight,
|
|
18
|
+
scrollY: window.scrollY,
|
|
19
|
+
}
|
|
20
|
+
: undefined);
|
|
21
|
+
|
|
22
|
+
const viewportBoundingBox =
|
|
23
|
+
annotation.boundingBox && captureViewport
|
|
24
|
+
? {
|
|
25
|
+
x: annotation.boundingBox.x,
|
|
26
|
+
y: annotation.isFixed
|
|
27
|
+
? annotation.boundingBox.y
|
|
28
|
+
: annotation.boundingBox.y - captureViewport.scrollY,
|
|
29
|
+
width: annotation.boundingBox.width,
|
|
30
|
+
height: annotation.boundingBox.height,
|
|
31
|
+
}
|
|
32
|
+
: annotation.viewportBoundingBox;
|
|
33
|
+
|
|
34
|
+
return { captureViewport, viewportBoundingBox };
|
|
35
|
+
}
|