@codefilm/recorder 3.0.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,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAC;AAE3B,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,IAAI,EACJ,YAAY,EACZ,6BAA6B,EAC7B,2BAA2B,EAC3B,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,2BAA2B,EAC3B,gCAAgC,EAChC,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,cAAc,cAAc,CAAC;AAC7B,YAAY,EACV,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,yBAAyB,EACzB,sBAAsB,EACtB,0BAA0B,EAC1B,2BAA2B,EAC3B,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,qBAAqB,EACrB,2BAA2B,EAC3B,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,0BAA0B,EAC1B,4BAA4B,EAC5B,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,0BAA0B,EAC1B,2BAA2B,EAC3B,qBAAqB,EACrB,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EACV,IAAI,EACJ,UAAU,EACV,KAAK,EACL,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,gCAAgC,EAChC,6BAA6B,EAC7B,6BAA6B,EAC7B,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ /* empty css */
2
+ import { COLS as o, DEFAULT_COMPLETION_TIMEOUT_MS as t, DEFAULT_RESOLUTIONS as m, DEFAULT_SELECTOR_TIMEOUT_MS as i, FilmRecorder as a, HUMAN_TYPING_PRESET as c, MIN_BOX_COLS as S, SDK_TYPING_DEFAULTS as A } from "./core/FilmRecorder.js";
3
+ import { RegionRecorderUI as l } from "./vanilla/RegionRecorderUI.js";
4
+ import { useFilmRecorder as T } from "./react/useFilmRecorder.js";
5
+ import { RegionRecorder as s } from "./react/RegionRecorder.js";
6
+ import { createRecorderAgentRunner as I, createWebAssistantAgent as _ } from "./core/agent.js";
7
+ import { AppFilmGenerationError as n, generateAppFilmScript as O, parseAppFilmSetup as L, prepareAppFilmScript as M, repairAppFilmScript as U, serializeAppFilmSetup as g, stripAppFilmSetup as x, validateAppFilmScript as u } from "./core/app-script.js";
8
+ import { createRecorderIframeClient as N, createRecorderIframeHost as D, createRecorderIframeMessage as P, getRecorderIframeShortcutCommand as G, isRecorderIframeMessage as v } from "./core/iframe-bridge.js";
9
+ import { cameraOverlay as Y } from "./core/recording-overlays.js";
10
+ export {
11
+ n as AppFilmGenerationError,
12
+ o as COLS,
13
+ t as DEFAULT_COMPLETION_TIMEOUT_MS,
14
+ m as DEFAULT_RESOLUTIONS,
15
+ i as DEFAULT_SELECTOR_TIMEOUT_MS,
16
+ a as FilmRecorder,
17
+ c as HUMAN_TYPING_PRESET,
18
+ S as MIN_BOX_COLS,
19
+ s as RegionRecorder,
20
+ l as RegionRecorderUI,
21
+ A as SDK_TYPING_DEFAULTS,
22
+ Y as cameraOverlay,
23
+ I as createRecorderAgentRunner,
24
+ N as createRecorderIframeClient,
25
+ D as createRecorderIframeHost,
26
+ P as createRecorderIframeMessage,
27
+ _ as createWebAssistantAgent,
28
+ O as generateAppFilmScript,
29
+ G as getRecorderIframeShortcutCommand,
30
+ v as isRecorderIframeMessage,
31
+ L as parseAppFilmSetup,
32
+ M as prepareAppFilmScript,
33
+ U as repairAppFilmScript,
34
+ g as serializeAppFilmSetup,
35
+ x as stripAppFilmSetup,
36
+ T as useFilmRecorder,
37
+ u as validateAppFilmScript
38
+ };
@@ -0,0 +1,156 @@
1
+ (function(f,v){typeof exports=="object"&&typeof module<"u"?v(exports,require("react"),require("react/jsx-runtime"),require("@openai/agents"),require("openai")):typeof define=="function"&&define.amd?define(["exports","react","react/jsx-runtime","@openai/agents","openai"],v):(f=typeof globalThis<"u"?globalThis:f||self,v(f.CodeFilm={},f.React,f.React,f.OpenAIAgents,f.OpenAI))})(this,(function(f,v,g,A,Fe){"use strict";function Ie(i){return{type:"camera",...i}}function $e(i,e){return new Ne(i,e)}function Le(i,e){return new ze(i,e)}class Ne{id;element;includeInCapture=!0;videoEl;fallbackEl;resizeHandle;stream=null;visible=!1;position;size;minSize;maxSize;shape;draggable;resizable;mirror;requestOnShow;onEvent;constructor(e,t){this.id=e.id,this.position=e.position??"top-left",this.size=e.size??168,this.minSize=e.minSize??96,this.maxSize=e.maxSize??360,this.shape=e.shape??"circle",this.draggable=e.draggable??!0,this.resizable=e.resizable??!0,this.mirror=e.mirror??!0,this.requestOnShow=e.requestOnShow??!0,this.onEvent=t,this.element=document.createElement("div"),this.element.className=["cfr-recording-overlay","cfr-camera-overlay",e.className].filter(Boolean).join(" "),this.element.dataset.codeFilmOverlay=this.id,this.videoEl=document.createElement("video"),this.videoEl.muted=!0,this.videoEl.playsInline=!0,this.videoEl.autoplay=!0,this.fallbackEl=document.createElement("div"),this.fallbackEl.className="cfr-camera-overlay-fallback",this.fallbackEl.textContent="Camera unavailable",this.resizeHandle=document.createElement("div"),this.resizeHandle.className="cfr-recording-overlay-resize",this.element.append(this.videoEl,this.fallbackEl,this.resizeHandle),this.applyElementStyle(),this.installPointerHandlers(),(e.enabled??!1)&&this.show()}async requestPermission(){if(this.stream)return!0;try{if(!navigator.mediaDevices?.getUserMedia)throw new Error("Camera capture is not available in this browser.");return this.stream=await navigator.mediaDevices.getUserMedia({video:!0,audio:!1}),this.videoEl.srcObject=this.stream,this.fallbackEl.style.display="none",await this.videoEl.play().catch(()=>{}),!0}catch(e){return this.stopTracks(),this.fallbackEl.style.display="flex",this.emit("error",{message:e instanceof Error?e.message:String(e)}),!1}}async show(){this.mount(),this.visible=!0,this.element.style.display="block",this.requestOnShow&&await this.requestPermission(),this.emit("shown",this.snapshot())}hide(){this.visible=!1,this.element.style.display="none",this.stopTracks(),this.emit("hidden",this.snapshot())}moveTo(e){this.position=e,this.applyElementStyle(),this.emit("moved",this.snapshot())}setSize(e){this.size=U(e,this.minSize,this.maxSize),this.applyElementStyle(),this.emit("resized",this.snapshot())}destroy(){this.hide(),this.element.remove()}draw(e,t,r){if(!this.visible)return;const n=$(this.position,this.size,t,r);De(e,n.x,n.y,n.size,this.shape,()=>{this.stream&&this.videoEl.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA?this.mirror?(e.save(),e.translate(n.x+n.size,n.y),e.scale(-1,1),e.drawImage(this.videoEl,0,0,n.size,n.size),e.restore()):e.drawImage(this.videoEl,n.x,n.y,n.size,n.size):Be(e,n.x,n.y,n.size)})}mount(){typeof document>"u"||this.element.isConnected||document.body.appendChild(this.element)}applyElementStyle(){const e=$(this.position,this.size,typeof window>"u"?1280:window.innerWidth,typeof window>"u"?720:window.innerHeight);Object.assign(this.element.style,{display:this.visible?"block":"none",position:"fixed",left:`${e.x}px`,top:`${e.y}px`,width:`${e.size}px`,height:`${e.size}px`,borderRadius:this.shape==="circle"?"9999px":this.shape==="rounded"?"24px":"0",overflow:"hidden",zIndex:"2147483646",background:"#111827",boxShadow:"0 18px 55px rgba(0,0,0,0.32), 0 0 0 1px rgba(255,255,255,0.2)",touchAction:"none",cursor:this.draggable?"grab":"default"}),Object.assign(this.videoEl.style,{width:"100%",height:"100%",objectFit:"cover",transform:this.mirror?"scaleX(-1)":"none"}),this.resizeHandle.style.display=this.resizable?"block":"none"}installPointerHandlers(){let e=null;const t=o=>{const a=o.target===this.resizeHandle;!this.draggable&&!a||!this.resizable&&a||(o.preventDefault(),this.element.setPointerCapture(o.pointerId),e={type:a?"resize":"move",pointerId:o.pointerId,startX:o.clientX,startY:o.clientY,startPosition:this.position,startSize:this.size})},r=o=>{if(!e||e.pointerId!==o.pointerId)return;const a=o.clientX-e.startX,l=o.clientY-e.startY;if(e.type==="resize")this.setSize(e.startSize+Math.max(a,l));else{const s=$(e.startPosition,e.startSize,window.innerWidth,window.innerHeight);this.moveTo({x:s.x+a,y:s.y+l})}},n=o=>{!e||e.pointerId!==o.pointerId||(this.element.releasePointerCapture(o.pointerId),e=null)};this.element.addEventListener("pointerdown",t),this.element.addEventListener("pointermove",r),this.element.addEventListener("pointerup",n),this.element.addEventListener("pointercancel",n)}stopTracks(){this.stream?.getTracks().forEach(e=>e.stop()),this.stream=null,this.videoEl.srcObject=null}emit(e,t){this.onEvent?.({id:this.id,type:e,data:t})}snapshot(){return{position:this.position,size:this.size,shape:this.shape}}}class ze{id;element;includeInCapture;visible;position;size;trackTimeline;onEvent;constructor(e,t){this.id=e.id,this.element=e.element,this.includeInCapture=e.includeInCapture??!0,this.trackTimeline=e.trackTimeline??!0,this.visible=e.enabled??!0,this.position=e.position??"top-left",this.size=e.size??168,this.onEvent=t,e.optOutOfSdkStyles||(this.element.classList.add("cfr-recording-overlay"),e.className&&this.element.classList.add(...e.className.split(/\s+/)),this.element.dataset.codeFilmOverlay=this.id),this.applyElementStyle()}show(){this.visible=!0,this.element.style.display="",this.emit("shown",this.snapshot())}hide(){this.visible=!1,this.element.style.display="none",this.emit("hidden",this.snapshot())}moveTo(e){this.position=e,this.applyElementStyle(),this.emit("moved",this.snapshot())}setSize(e){this.size=Math.max(1,e),this.applyElementStyle(),this.emit("resized",this.snapshot())}destroy(){this.hide()}draw(e,t,r){if(!this.visible||!this.includeInCapture)return;const n=$(this.position,this.size,t,r);this.element instanceof HTMLCanvasElement?e.drawImage(this.element,n.x,n.y,n.size,n.size):(this.element instanceof HTMLImageElement||this.element instanceof HTMLVideoElement)&&e.drawImage(this.element,n.x,n.y,n.size,n.size)}applyElementStyle(){const e=$(this.position,this.size,typeof window>"u"?1280:window.innerWidth,typeof window>"u"?720:window.innerHeight);Object.assign(this.element.style,{position:"fixed",left:`${e.x}px`,top:`${e.y}px`,width:`${e.size}px`,height:`${e.size}px`,zIndex:"2147483646"})}emit(e,t){this.trackTimeline&&this.onEvent?.({id:this.id,type:e,data:t})}snapshot(){return{position:this.position,size:this.size}}}function $(i,e,t,r){if(typeof i=="object")return{x:U(i.x,0,Math.max(0,t-e)),y:U(i.y,0,Math.max(0,r-e)),size:e};const n=t-e-24,o=r-e-24;return{x:i.endsWith("right")?n:24,y:i.startsWith("bottom")?o:24,size:e}}function De(i,e,t,r,n,o){i.save(),n==="circle"?(i.beginPath(),i.arc(e+r/2,t+r/2,r/2,0,Math.PI*2),i.clip()):n==="rounded"&&(je(i,e,t,r,r,Math.min(24,r/5)),i.clip()),o(),i.restore()}function Be(i,e,t,r){i.save(),i.fillStyle="#111827",i.fillRect(e,t,r,r),i.fillStyle="#e5e7eb",i.font=`${Math.max(12,Math.round(r/12))}px system-ui, sans-serif`,i.textAlign="center",i.textBaseline="middle",i.fillText("Camera unavailable",e+r/2,t+r/2,r-20),i.restore()}function je(i,e,t,r,n,o){i.beginPath(),i.moveTo(e+o,t),i.lineTo(e+r-o,t),i.quadraticCurveTo(e+r,t,e+r,t+o),i.lineTo(e+r,t+n-o),i.quadraticCurveTo(e+r,t+n,e+r-o,t+n),i.lineTo(e+o,t+n),i.quadraticCurveTo(e,t+n,e,t+n-o),i.lineTo(e,t+o),i.quadraticCurveTo(e,t,e+o,t),i.closePath()}function U(i,e,t){return Math.min(t,Math.max(e,i))}const H=[{label:"YouTube HD (16:9)",w:1920,h:1080},{label:"Twitter / X (16:9)",w:1200,h:675},{label:"Instagram Post (4:5)",w:1080,h:1350},{label:"Instagram Reel / Story (9:16)",w:1080,h:1920},{label:"TikTok (9:16)",w:1080,h:1920}],b=24,B=6,_e=1e3,qe=12,Ue=.08,He=.015,Ge=3e3,We=500,P=56,O=2,L="j",te=12e4,ie=3e3,re=Object.freeze({cps:24,jitter:.22,punctuationPauseMs:120,mistakeRate:.012}),Ze=Object.freeze({cps:24,jitter:.22,punctuationPauseMs:120,mistakeRate:.012});class ne{options;listeners=new Set;state;videoEl;canvasEl;recorder=null;stream=null;chunks=[];lastRecording=null;lastRecordingError=null;recordingStartedAt=0;timelineMetadata=null;activeFilmTitle=null;destroyed=!1;cameraRafId=0;renderRafId=0;targetRect;liveRect;mousePosGlobal={x:0,y:0};holdTimer=null;zoomOutTimer=null;scrollPausedUntil=0;anchorX=0;anchorY=0;pointerEl=null;pointerX=0;pointerY=0;tourRafId=0;tourAbortController=null;activeFilmScriptContext=null;activeFilmScriptOptions=null;activeExecutionPromise=null;finalizationPromise=null;pendingActionGates=[];activeTypingRandom=Math.random;ignoredElements=new Map;overlays=new Map;constructor(e={}){const t={fps:e.fps??60,resolutions:e.resolutions??H,defaultResolutionIndex:e.defaultResolutionIndex??0,autoZoom:e.autoZoom??!0,pauseDuringScroll:e.pauseDuringScroll??!0,showGrid:e.showGrid??!0,showOutline:e.showOutline??!1,enableShortcuts:e.enableShortcuts??!0,elementSelector:e.elementSelector??null,elementPadding:e.elementPadding??1.1,fixedRecordingRegion:e.fixedRecordingRegion??null,movePointerToSelector:e.movePointerToSelector??null,pointerClassName:e.pointerClassName??"",pointerFillColor:e.pointerFillColor??"#ffffff",pointerBorderColor:e.pointerBorderColor??"#18181b",pointerRippleColor:e.pointerRippleColor??"#64748b",disableRipple:e.disableRipple??!1,ignoreSelector:e.ignoreSelector??null,overlays:e.overlays??[],autoDownload:e.autoDownload??!0,includeTimelineMetadata:e.includeTimelineMetadata??!1,selectorTimeoutMs:e.selectorTimeoutMs??ie,typingDefaults:this.resolveTypingOptions(e.typingDefaults),typingSeed:e.typingSeed??"",onRecordingStart:e.onRecordingStart??(()=>{}),onRecordingStop:e.onRecordingStop??(()=>{}),onRecordingError:e.onRecordingError??(()=>{}),onTourStart:e.onTourStart??(()=>{}),onTourStop:e.onTourStop??(()=>{}),onReadyToEnd:e.onReadyToEnd??(()=>{}),onTourError:e.onTourError??(()=>{}),onSceneStart:e.onSceneStart??(()=>{}),onSceneEnd:e.onSceneEnd??(()=>{}),onActionStart:e.onActionStart??(()=>{}),onActionEnd:e.onActionEnd??(()=>{})};this.options=t;const r=this.options.resolutions[this.options.defaultResolutionIndex]||H[0],n={w:typeof window<"u"?window.innerWidth:1280,h:typeof window<"u"?window.innerHeight:720},o=this.computeGrid(n.w,n.h);let a;if(this.options.elementSelector){const l=this.calculateElementRect(this.options.elementSelector,this.options.elementPadding,r.w/r.h);if(l)a=l;else{const s=this.getRecordingRegionBox(r.w/r.h,b,o.rows,b),u=Math.floor((b-s.w)/2),c=Math.floor((o.rows-s.h)/2);a={col:u,row:c,w:s.w,h:s.h}}}else{const l=this.getRecordingRegionBox(r.w/r.h,b,o.rows,b),s=Math.floor((b-l.w)/2),u=Math.floor((o.rows-l.h)/2);a={col:s,row:u,w:l.w,h:l.h}}this.targetRect={col:a.col,row:a.row,w:a.w,h:a.h},this.liveRect={...this.targetRect},this.state={recording:!1,showGrid:this.options.showGrid,autoZoom:this.options.autoZoom,pauseDuringScroll:this.options.pauseDuringScroll,resolution:r,mousePaused:!1,viewport:n,displayRect:{...this.liveRect},showOutline:this.options.showOutline,elementSelector:this.options.elementSelector,elementPadding:this.options.elementPadding,fixedRecordingRegion:this.options.fixedRecordingRegion,movePointerToSelector:this.options.movePointerToSelector,pointerClassName:this.options.pointerClassName,pointerFillColor:this.options.pointerFillColor,pointerBorderColor:this.options.pointerBorderColor,pointerRippleColor:this.options.pointerRippleColor,disableRipple:this.options.disableRipple,ignoreSelector:this.options.ignoreSelector,tourState:"idle",executionState:"idle",currentScene:null},typeof window<"u"?(this.videoEl=document.createElement("video"),this.videoEl.muted=!0,this.videoEl.playsInline=!0,this.videoEl.style.display="none",document.body.appendChild(this.videoEl),this.canvasEl=document.createElement("canvas"),this.canvasEl.style.display="none",document.body.appendChild(this.canvasEl),this.setupEventListeners(),this.startCameraLoop(),this.options.overlays.forEach(l=>{l.type==="camera"&&this.createCameraOverlay(l)})):(this.videoEl={},this.canvasEl={})}computeGrid(e,t){const r=e/b,n=r*9/16,o=Math.max(0,t-P),a=Math.max(1,Math.floor(o/n));return{cellW:r,cellH:n,rows:a}}getAspectBox(e,t,r,n){let o=1,a=1,l=1/0;const s=Math.min(t,n);for(let u=1;u<=s;u++){const c=u*16/(9*e),d=[Math.floor(c),Math.ceil(c)].filter(h=>h>=1&&h<=r);for(const h of d){const m=u/h*1.7777777777777777,y=Math.abs(m-e);(y<l-1e-6||Math.abs(y-l)<1e-6&&u>o)&&(l=y,o=u,a=h)}}return{w:o,h:a}}getRecordingRegionBox(e,t,r,n){return this.options.fixedRecordingRegion==="smallest-16:9"?this.getAspectBox(16/9,t,r,B):this.getAspectBox(e,t,r,n)}clampRect(e,t){const r=Math.min(b,Math.max(1,e.w)),n=Math.min(t,Math.max(1,e.h)),o=Math.min(b-r,Math.max(0,e.col)),a=Math.min(t-n,Math.max(0,e.row));return{col:o,row:a,w:r,h:n}}centeredRectOnPoint(e,t,r,n,o){const{cellW:a,cellH:l,rows:s}=this.computeGrid(r,n),u=Math.max(0,t-P),c=Math.min(b-1,Math.max(0,Math.floor(e/a))),d=Math.min(s-1,Math.max(0,Math.floor(u/l))),{w:h,h:m}=this.getRecordingRegionBox(o,b,s,B);return this.clampRect({col:Math.round(c-h/2+.5),row:Math.round(d-m/2+.5),w:h,h:m},s)}setupEventListeners(){window.addEventListener("resize",this.handleResize),window.addEventListener("mousemove",this.handleMouseMove),window.addEventListener("wheel",this.handleScrollOrWheel,{passive:!0}),window.addEventListener("scroll",this.handleScrollOrWheel,{passive:!0}),this.options.enableShortcuts&&window.addEventListener("keydown",this.handleKeyDown)}cleanupEventListeners(){window.removeEventListener("resize",this.handleResize),window.removeEventListener("mousemove",this.handleMouseMove),window.removeEventListener("wheel",this.handleScrollOrWheel),window.removeEventListener("scroll",this.handleScrollOrWheel),window.removeEventListener("keydown",this.handleKeyDown)}handleResize=()=>{const e=window.innerWidth,t=window.innerHeight;if(this.updateState({viewport:{w:e,h:t}}),this.options.elementSelector)return;const r=this.computeGrid(e,t),n=this.state.resolution.w/this.state.resolution.h,{w:o,h:a}=this.getRecordingRegionBox(n,b,r.rows,b),l=Math.floor((b-o)/2),s=Math.floor((r.rows-a)/2);this.targetRect={col:l,row:s,w:o,h:a}};handleMouseMove=e=>{this.state.mousePaused||this.options.elementSelector||(this.mousePosGlobal={x:e.clientX,y:e.clientY},Math.hypot(e.clientX-this.anchorX,e.clientY-this.anchorY)>qe&&(this.armHold(e.clientX,e.clientY),this.zoomOutTimer&&(clearTimeout(this.zoomOutTimer),this.zoomOutTimer=null)))};handleScrollOrWheel=()=>{this.options.elementSelector||(this.scrollPausedUntil=performance.now()+We,this.holdTimer&&clearTimeout(this.holdTimer))};handleKeyDown=e=>{if(!(e.metaKey||e.ctrlKey))return;const r=e.key.toLowerCase();r===L?(e.preventDefault(),this.state.recording?this.stopRecording():this.startRecording()):r==="l"?(e.preventDefault(),this.setMousePaused(!this.state.mousePaused)):e.key==="ArrowUp"?(e.preventDefault(),this.options.elementSelector?this.setElementSelector(null):this.zoomTop()):e.key==="ArrowDown"&&(e.preventDefault(),this.options.elementSelector||this.zoomBottom())};armHold(e,t){this.holdTimer&&clearTimeout(this.holdTimer),this.anchorX=e,this.anchorY=t,this.holdTimer=setTimeout(()=>{this.state.autoZoom&&(this.state.pauseDuringScroll&&performance.now()<this.scrollPausedUntil||(this.zoomToMouse(),this.scheduleIdleZoomOut()))},_e)}scheduleIdleZoomOut(){this.zoomOutTimer&&clearTimeout(this.zoomOutTimer),this.zoomOutTimer=setTimeout(()=>{this.zoomOutTimer=null,!(!this.state.autoZoom||this.options.elementSelector)&&(this.state.pauseDuringScroll&&performance.now()<this.scrollPausedUntil||this.resetFullScreen())},Ge)}calculateElementRect(e,t=1.1,r){if(typeof document>"u")return null;const n=document.querySelector(e);if(!n)return null;const o=n.getBoundingClientRect(),a=window.innerWidth,l=window.innerHeight,s=this.computeGrid(a,l),u=o.left+o.width/2,c=o.top+o.height/2,d=u/s.cellW,h=(c-P)/s.cellH,m=o.width/s.cellW,y=o.height/s.cellH,p=r??this.state.resolution.w/this.state.resolution.h,w=s.cellH/s.cellW,E=p*w;if(this.options.fixedRecordingRegion){const{w:q,h:N}=this.getRecordingRegionBox(p,b,s.rows,B);return this.clampRect({col:d-q/2,row:h-N/2,w:q,h:N},s.rows)}const S=m*t,T=y*t;let R=Math.max(S,T*E),M=R/E;const Q=d-R/2,ee=h-M/2;return this.clampRect({col:Q,row:ee,w:R,h:M},s.rows)}startCameraLoop(){const e=()=>{if(this.options.elementSelector){const a=this.calculateElementRect(this.options.elementSelector,this.options.elementPadding);a&&(this.targetRect=a)}const t=this.targetRect,r=this.liveRect,o=t.w>r.w?He:Ue;this.liveRect={col:r.col+(t.col-r.col)*o,row:r.row+(t.row-r.row)*o,w:r.w+(t.w-r.w)*o,h:r.h+(t.h-r.h)*o},this.updateState({displayRect:{...this.liveRect}}),this.cameraRafId=requestAnimationFrame(e)};this.cameraRafId=requestAnimationFrame(e)}zoomToMouse(){const e=this.state.resolution.w/this.state.resolution.h;this.targetRect=this.centeredRectOnPoint(this.mousePosGlobal.x,this.mousePosGlobal.y,window.innerWidth,window.innerHeight,e)}getFullFrameRect(e){const t=this.state.resolution.w/this.state.resolution.h,r=this.computeGrid(window.innerWidth,window.innerHeight),{w:n,h:o}=this.getRecordingRegionBox(t,b,r.rows,b),a=e==="top"?0:e==="bottom"?r.rows-o:Math.floor((r.rows-o)/2);return{col:Math.floor((b-n)/2),row:a,w:n,h:o}}setFullFrameRect(e,t=!1){const r=this.getFullFrameRect(e);this.targetRect=r,t&&(this.liveRect={...r},this.updateState({displayRect:{...r}}))}zoomTop(e=!1){this.setFullFrameRect("top",e)}zoomCenter(e=!1){this.setFullFrameRect("center",e)}zoomBottom(e=!1){this.setFullFrameRect("bottom",e)}zoomBottomFold(){this.zoomBottom()}zoomTopFold(e=!1){this.zoomTop(e)}resetFullScreen(){this.zoomCenter()}zoomTopFullFrame(e=!1){this.zoomTop(e)}getRecordingElapsedMs(){return this.recordingStartedAt?Math.max(0,Math.round(performance.now()-this.recordingStartedAt)):0}beginTimelineMetadata(){if(!this.options.includeTimelineMetadata){this.timelineMetadata=null;return}this.timelineMetadata={schema:"code-film.timeline.v1",title:this.activeFilmTitle,fps:this.options.fps,width:this.state.resolution.w,height:this.state.resolution.h,scenes:[],actions:[],markers:[]},this.recordTimelineMarker("recording:start")}finishTimelineMetadata(){if(this.timelineMetadata)return this.recordTimelineMarker("recording:stop"),{...this.timelineMetadata,scenes:this.timelineMetadata.scenes.map(e=>({...e})),actions:this.timelineMetadata.actions.map(e=>({...e})),markers:this.timelineMetadata.markers.map(e=>({...e}))}}recordTimelineMarker(e,t={}){this.timelineMetadata&&this.timelineMetadata.markers.push({timeMs:this.getRecordingElapsedMs(),name:e,...t})}recordOverlayEvent(e){this.recordTimelineMarker(`overlay:${e.type}`,{data:{id:e.id,...e.data}})}renderRecordingOverlays(e){this.overlays.forEach(t=>{t.includeInCapture&&t.draw(e,this.state.resolution.w,this.state.resolution.h)})}createCameraOverlay(e){if(typeof document>"u")throw new Error("[FilmRecorder] createCameraOverlay requires a browser document.");const t=$e(e,r=>{this.recordOverlayEvent(r)});return this.overlays.set(t.id,t),t}registerOverlay(e){if(typeof document>"u")throw new Error("[FilmRecorder] registerOverlay requires a browser document.");const t=Le(e,r=>{this.recordOverlayEvent(r)});return this.overlays.set(t.id,t),t}getOverlay(e){return this.overlays.get(e)??null}removeOverlay(e){const t=this.overlays.get(e);t&&(t.destroy(),this.overlays.delete(e))}setOverlays(e){this.overlays.forEach(t=>t.destroy()),this.overlays.clear(),e.forEach(t=>{t.type==="camera"&&this.createCameraOverlay(t)})}startTimelineScene(e,t){if(!this.timelineMetadata)return null;const r={id:`scene-${t+1}`,name:e.name,declaredStartMs:Math.round(e.startTime*1e3),declaredEndMs:Math.round(e.endTime*1e3),actualStartMs:this.getRecordingElapsedMs(),actualEndMs:null};return this.timelineMetadata.scenes.push(r),this.recordTimelineMarker("scene:start",{data:{label:e.name},scene:e.name}),r}endTimelineScene(e){e&&(e.actualEndMs=this.getRecordingElapsedMs(),this.recordTimelineMarker("scene:end",{data:{label:e.name},scene:e.name}))}startTimelineAction(e,t,r){if(!this.timelineMetadata||!e)return null;const n={type:t.type,startMs:this.getRecordingElapsedMs(),endMs:null,commandIndex:r,scene:e.name,selector:t.selector,to:t.to,padding:t.padding,text:t.text,durationMs:t.durationMs};return this.timelineMetadata.actions.push(n),this.recordTimelineMarker(`command:${t.type}:start`,{data:{label:t.selector??t.to??t.text??t.type},scene:e.name,commandIndex:r}),n}endTimelineAction(e,t){!e||!t||(t.endMs=this.getRecordingElapsedMs(),this.recordTimelineMarker(`command:${t.type}:end`,{data:{label:t.selector??t.to??t.text??t.type},scene:e.name,commandIndex:t.commandIndex}))}getLastRecording(){return this.lastRecording}clearLastRecording(){this.lastRecording&&(URL.revokeObjectURL(this.lastRecording.url),this.lastRecording=null)}getLastRecordingError(){return this.lastRecordingError}normalizeRecordingError(e){return e instanceof Error?e:new Error(typeof e=="string"?e:"Unknown recording error")}handleRecordingError(e){const t=this.normalizeRecordingError(e);return this.lastRecordingError=t,this.updateState({showGrid:this.options.showGrid}),this.options.onRecordingError?.(t),t}async requestCaptureStream(){return navigator.mediaDevices.getDisplayMedia({video:{frameRate:this.options.fps,width:{ideal:3840},height:{ideal:2160}},audio:!0,preferCurrentTab:!0})}async attachCaptureStream(e){this.stream=e,this.videoEl.srcObject=e,await this.videoEl.play(),await this.waitForCaptureVideoFrame()}async waitForCaptureVideoFrame(e=3e3){this.videoEl.videoWidth>0&&this.videoEl.videoHeight>0||await new Promise((t,r)=>{let n=0;const o=window.setTimeout(()=>{a(),r(new Error("Screen capture started, but no video frame was available."))},e),a=()=>{window.clearTimeout(o),n&&cancelAnimationFrame(n),this.videoEl.removeEventListener("loadedmetadata",l),this.videoEl.removeEventListener("canplay",l)},l=()=>{if(this.videoEl.videoWidth>0&&this.videoEl.videoHeight>0){a(),t();return}n=requestAnimationFrame(l)};this.videoEl.addEventListener("loadedmetadata",l),this.videoEl.addEventListener("canplay",l),l()})}stopCaptureStream(){this.stream?.getTracks().forEach(e=>e.stop()),this.stream=null,this.videoEl.srcObject=null}hideIgnoredElements(){this.restoreIgnoredElements(),!(!this.options.ignoreSelector||typeof document>"u")&&document.querySelectorAll(this.options.ignoreSelector).forEach(e=>{e instanceof HTMLElement&&(e.closest(".cfr-settings-bar, .cfr-recording-overlay")||(this.ignoredElements.set(e,{visibility:e.style.getPropertyValue("visibility"),priority:e.style.getPropertyPriority("visibility")}),e.style.setProperty("visibility","hidden","important")))})}restoreIgnoredElements(){this.ignoredElements.forEach((e,t)=>{t.style.setProperty("visibility",e.visibility,e.priority)}),this.ignoredElements.clear()}getActiveCaptureStream(){return this.stream&&this.stream.getTracks().some(e=>e.readyState==="live")?this.stream:null}async prepareCapture(){if(this.getActiveCaptureStream())return!0;try{const e=await this.requestCaptureStream();return await this.attachCaptureStream(e),this.lastRecordingError=null,!0}catch(e){throw this.stopCaptureStream(),this.handleRecordingError(e)}}async startRecording(){if(this.state.recording)return!1;try{const e=this.getActiveCaptureStream();e?await this.attachCaptureStream(e):await this.prepareCapture();const t=this.getActiveCaptureStream();if(!t)throw new Error("No active capture stream is available.");this.options.elementSelector&&(this.options.elementSelector=null,this.updateState({elementSelector:null})),this.zoomTopFullFrame(!0),this.resetPointerEntryPosition(),this.hideIgnoredElements(),this.updateState({showGrid:!1});const r=this.canvasEl.getContext("2d");r.imageSmoothingEnabled=!0,r.imageSmoothingQuality="high",this.canvasEl.width=this.state.resolution.w,this.canvasEl.height=this.state.resolution.h;const n=()=>{const s=window.innerWidth,u=window.innerHeight,c=this.computeGrid(s,u),d=this.liveRect,h=this.videoEl.videoWidth/s,m=this.videoEl.videoHeight/u;r.drawImage(this.videoEl,d.col*c.cellW*h,(P+d.row*c.cellH)*m,d.w*c.cellW*h,d.h*c.cellH*m,0,0,this.state.resolution.w,this.state.resolution.h),this.renderRecordingOverlays(r),this.renderRafId=requestAnimationFrame(n)};n();const o=this.canvasEl.captureStream(this.options.fps);t.getAudioTracks().forEach(s=>o.addTrack(s));const a=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm","video/mp4"].find(s=>MediaRecorder.isTypeSupported(s)),l=new MediaRecorder(o,{...a&&{mimeType:a},videoBitsPerSecond:1e7});return this.chunks=[],this.recordingStartedAt=performance.now(),this.beginTimelineMetadata(),l.ondataavailable=s=>{s.data.size&&this.chunks.push(s.data)},l.onstop=()=>{const s=performance.now(),u=new Blob(this.chunks,{type:l.mimeType}),c=URL.createObjectURL(u),d=l.mimeType.includes("mp4")?"capture.mp4":"capture.webm",h=Math.max(0,Math.round(s-this.recordingStartedAt)),m={blob:u,url:c,mimeType:l.mimeType,filename:d,durationMs:h,startedAt:this.recordingStartedAt,stoppedAt:s,timeline:this.finishTimelineMetadata(),webm:l.mimeType.includes("webm")?{seekable:!1,hasDurationMetadata:!1,durationMs:h,sizeBytes:u.size}:void 0};this.clearLastRecording(),this.lastRecording=m;try{this.options.onRecordingStop?.(m)}finally{if(this.options.autoDownload){const y=document.createElement("a");y.href=m.url,y.download=m.filename,y.click()}this.destroyed&&this.clearLastRecording(),this.timelineMetadata=null,this.recordingStartedAt=0,this.activeFilmTitle=null}},l.start(1e3),this.recorder=l,this.lastRecordingError=null,this.updateState({recording:!0}),this.options.onRecordingStart?.(),this.options.movePointerToSelector&&setTimeout(()=>{this.options.movePointerToSelector&&this.state.recording&&this.playPointerTour(this.options.movePointerToSelector)},500),!0}catch(e){throw e===this.lastRecordingError?e:(cancelAnimationFrame(this.renderRafId),this.renderRafId=0,this.stopCaptureStream(),this.restoreIgnoredElements(),this.recorder=null,this.handleRecordingError(e))}}stopRecording(){this.state.recording&&(cancelAnimationFrame(this.renderRafId),this.recorder?.stop(),this.stopCaptureStream(),this.restoreIgnoredElements(),this.recorder=null,this.pointerEl&&(this.pointerEl.style.display="none",this.pointerEl.classList.remove("cfr-holding")),this.tourRafId&&(cancelAnimationFrame(this.tourRafId),this.tourRafId=0),this.updateState({recording:!1,showGrid:this.options.showGrid}))}captureBitmap(){this.state.recording&&this.canvasEl.toBlob(e=>{if(!e)return;const t=document.createElement("a");t.href=URL.createObjectURL(e),t.download="capture.png",t.click(),setTimeout(()=>URL.revokeObjectURL(t.href),1e3)},"image/png")}ensurePointerEl(){typeof window>"u"||typeof document>"u"||(this.pointerEl||(this.pointerEl=document.createElement("div"),this.pointerX=window.innerWidth/2,this.pointerY=window.innerHeight+40,this.pointerEl.style.left=`${this.pointerX}px`,this.pointerEl.style.top=`${this.pointerY}px`,document.body.appendChild(this.pointerEl)),this.applyPointerClassName(),this.applyPointerColors(),this.pointerEl.style.display="block")}applyPointerClassName(){if(!this.pointerEl)return;const e=this.pointerEl.classList.contains("cfr-holding"),t=this.options.pointerClassName.split(/\s+/).filter(Boolean);this.pointerEl.className=["cfr-simulated-pointer",...t].join(" "),e&&this.pointerEl.classList.add("cfr-holding"),this.pointerEl.classList.toggle("cfr-ripple-disabled",this.options.disableRipple)}validatePointerColor(e,t){if(!/^#[0-9a-f]{6}$/i.test(e))throw new TypeError(`[FilmRecorder] ${t} must be a 6-digit hex color.`);return e}applyPointerColors(){if(!this.pointerEl)return;const e=this.validatePointerColor(this.options.pointerFillColor,"pointerFillColor"),t=this.validatePointerColor(this.options.pointerBorderColor,"pointerBorderColor"),r=this.validatePointerColor(this.options.pointerRippleColor,"pointerRippleColor"),n=`<svg xmlns="http://www.w3.org/2000/svg" width="24" height="30" viewBox="0 0 24 30" fill="none"><path d="M2 2.25V23.15L7.55 17.83L11.65 27.4L16.05 25.52L12.08 16.25H20.2L2 2.25Z" fill="${e}" stroke="${t}" stroke-width="2.2" stroke-linejoin="round"/></svg>`;this.pointerEl.style.backgroundImage=`url("data:image/svg+xml,${encodeURIComponent(n)}")`,this.pointerEl.style.setProperty("--cfr-pointer-ripple-color",r)}resetPointerEntryPosition(){this.ensurePointerEl(),this.pointerEl&&(this.pointerX=window.innerWidth/2,this.pointerY=window.innerHeight+40,this.pointerEl.style.left=`${this.pointerX}px`,this.pointerEl.style.top=`${this.pointerY}px`,this.pointerEl.classList.remove("cfr-holding"))}async getTargetElement(e,t,r,n=this.options.selectorTimeoutMs){if(typeof e!="string")return e;const o=performance.now();for(;;){if(r?.aborted)throw new DOMException("Aborted","AbortError");const a=document.querySelector(e);if(a)return a;if(performance.now()-o>n)throw this.createSelectorError(e,t);await new Promise(l=>setTimeout(l,50))}}async animatePointerTo(e,t=800,r,n=this.options.selectorTimeoutMs){if(typeof window>"u"||typeof document>"u")return;if(this.ensurePointerEl(),r?.aborted)throw new DOMException("Aborted","AbortError");const o=await this.getTargetElement(e,"animatePointerTo",r,n),a=o.getBoundingClientRect(),l=a.left+a.width/2,s=a.top+a.height/2,u=this.pointerX,c=this.pointerY,d=performance.now();return this.tourRafId&&cancelAnimationFrame(this.tourRafId),new Promise((h,m)=>{const y=()=>{cancelAnimationFrame(this.tourRafId),m(new DOMException("Aborted","AbortError"))};r&&r.addEventListener("abort",y);const p=w=>{if(r?.aborted)return;const E=w-d,S=Math.min(E/t,1),T=S<.5?2*S*S:1-Math.pow(-2*S+2,2)/2,R=u+(l-u)*T,M=c+(s-c)*T;this.pointerX=R,this.pointerY=M,this.pointerEl&&(this.pointerEl.style.left=`${R}px`,this.pointerEl.style.top=`${M}px`),S<1?this.tourRafId=requestAnimationFrame(p):(this.dispatchPointerHover(o,l,s),r&&r.removeEventListener("abort",y),h())};this.tourRafId=requestAnimationFrame(p)})}dispatchPointerHover(e,t,r){const n={bubbles:!0,cancelable:!0,view:window,clientX:t,clientY:r};e.dispatchEvent(new MouseEvent("mouseover",n)),e.dispatchEvent(new MouseEvent("mouseenter",{...n,bubbles:!1})),e.dispatchEvent(new MouseEvent("mousemove",n))}async simulateClick(e,t,r=this.options.selectorTimeoutMs){if(typeof window>"u"||typeof document>"u")return;if(t?.aborted)throw new DOMException("Aborted","AbortError");if(await this.animatePointerTo(e,600,t,r),t?.aborted)throw new DOMException("Aborted","AbortError");this.pointerEl&&this.pointerEl.classList.add("cfr-holding");let n;try{n=await this.getTargetElement(e,"simulateClick",t,r)}catch(s){throw this.pointerEl&&this.pointerEl.classList.remove("cfr-holding"),s}const o=new MouseEvent("mousedown",{bubbles:!0,cancelable:!0,view:window}),a=new MouseEvent("mouseup",{bubbles:!0,cancelable:!0,view:window}),l=new MouseEvent("click",{bubbles:!0,cancelable:!0,view:window});n.dispatchEvent(o),n.dispatchEvent(a),n instanceof HTMLElement?n.click():n.dispatchEvent(l),await new Promise((s,u)=>{const c=()=>{clearTimeout(d),this.pointerEl&&this.pointerEl.classList.remove("cfr-holding"),u(new DOMException("Aborted","AbortError"))};t&&t.addEventListener("abort",c);const d=setTimeout(()=>{t&&t.removeEventListener("abort",c),this.pointerEl&&this.pointerEl.classList.remove("cfr-holding"),s()},250)})}isFormTypingTarget(e){return typeof HTMLInputElement<"u"&&typeof HTMLTextAreaElement<"u"&&(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement)?!0:"value"in e&&typeof e.value=="string"}isContentEditableTypingTarget(e){return e instanceof HTMLElement&&e.isContentEditable}dispatchKeyboardInputEvents(e,t,r="insertText"){const n=new KeyboardEvent("keydown",{key:t,charCode:t.length===1?t.charCodeAt(0):0,bubbles:!0}),o=new KeyboardEvent("keypress",{key:t,charCode:t.length===1?t.charCodeAt(0):0,bubbles:!0}),a=new InputEvent("input",{data:r==="insertText"?t:null,inputType:r,bubbles:!0}),l=new KeyboardEvent("keyup",{key:t,charCode:t.length===1?t.charCodeAt(0):0,bubbles:!0});e.dispatchEvent(n),r==="insertText"&&e.dispatchEvent(o),e.dispatchEvent(a),e.dispatchEvent(l)}typeChar(e,t){if(!this.isFormTypingTarget(e)){this.typeContentEditableChar(e,t);return}const r=e.selectionStart??e.value.length,n=e.selectionEnd??e.value.length,o=e.value;e.value=o.substring(0,r)+t+o.substring(n),e.selectionStart=e.selectionEnd=r+1;const a=e._valueTracker;a&&a.setValue(o),this.dispatchKeyboardInputEvents(e,t),e.dispatchEvent(new Event("change",{bubbles:!0}))}typeContentEditableChar(e,t){const r=window.getSelection();if(!r)return;if(!r.rangeCount||!e.contains(r.anchorNode)){const a=document.createRange();a.selectNodeContents(e),a.collapse(!1),r.removeAllRanges(),r.addRange(a)}const n=r.getRangeAt(0);n.deleteContents();const o=document.createTextNode(t);n.insertNode(o),n.setStartAfter(o),n.collapse(!0),r.removeAllRanges(),r.addRange(n),this.dispatchKeyboardInputEvents(e,t),e.dispatchEvent(new Event("change",{bubbles:!0}))}simulateBackspace(e){if(!this.isFormTypingTarget(e)){this.simulateContentEditableBackspace(e);return}const t=e.value;if(t.length===0)return;const r=e.selectionStart??t.length,n=e.selectionEnd??t.length;let o=t,a=r;r!==n?o=t.substring(0,r)+t.substring(n):r>0&&(o=t.substring(0,r-1)+t.substring(r),a=r-1),e.value=o,e.selectionStart=e.selectionEnd=a;const l=e._valueTracker;l&&l.setValue(t),this.dispatchKeyboardInputEvents(e,"Backspace","deleteContentBackward"),e.dispatchEvent(new Event("change",{bubbles:!0}))}simulateContentEditableBackspace(e){const t=window.getSelection();if(!t)return;if(!t.rangeCount||!e.contains(t.anchorNode)){const n=document.createRange();n.selectNodeContents(e),n.collapse(!1),t.removeAllRanges(),t.addRange(n)}const r=t.getRangeAt(0);if(!r.collapsed)r.deleteContents();else if(r.startContainer.nodeType===Node.TEXT_NODE&&r.startOffset>0){const n=r.startContainer;n.textContent=(n.textContent??"").slice(0,r.startOffset-1)+(n.textContent??"").slice(r.startOffset),r.setStart(n,r.startOffset-1),r.collapse(!0)}else return;t.removeAllRanges(),t.addRange(r),this.dispatchKeyboardInputEvents(e,"Backspace","deleteContentBackward"),e.dispatchEvent(new Event("change",{bubbles:!0}))}async focusTypingTarget(e,t,r=this.options.selectorTimeoutMs){const n=await this.getTargetElement(e,"simulateType",t,r);if(!(n instanceof HTMLInputElement||n instanceof HTMLTextAreaElement||this.isContentEditableTypingTarget(n)))throw new Error("[FilmRecorder] Target element for simulateType must be an input, textarea, or contenteditable element.");return await this.simulateClick(n,t,r),n.focus(),n}async simulateType(e,t,r,n){await this.simulateTypeWithRandom(e,t,r,n,Math.random,this.options.selectorTimeoutMs)}async simulateTypeWithRandom(e,t,r,n,o,a=this.options.selectorTimeoutMs){if(typeof window>"u"||typeof document>"u")return;this.throwIfAborted(n);const l=this.resolveTypingOptions(typeof r=="number"?{cps:r}:r),{cps:s,jitter:u,punctuationPauseMs:c,mistakeRate:d}=l,h=await this.focusTypingTarget(e,n,a),m=1e3/s,y=(p,w,E=!1)=>{if(u<=0)return m;let S=1;if(!E&&p>0){const z=t[p-1],D=w;D===z&&/[a-zA-Z0-9]/.test(D)?S=.4:/[a-zA-Z0-9]/.test(z)&&/[a-zA-Z0-9]/.test(D)?S=.75:D===" "?S=1.5:z===" "&&/[a-zA-Z0-9]/.test(D)&&(S=1.25)}const T=/[A-Z]/.test(w),R=p>0&&/[A-Z]/.test(t[p-1]);T&&!R&&!E&&(S+=.4);const M=o(),Q=o(),ee=Math.sqrt(-2*Math.log(M||1e-4))*Math.cos(2*Math.PI*Q),q=Math.exp(ee*u*.8);let N=m*S*q;if(!E&&p>0&&p%18===0&&o()<.6){const z=m*(1.5+o()*2)*u;N+=z}const Ot=Math.max(10,m*.25),Ft=m*4;return Math.min(Ft,Math.max(Ot,N))};for(let p=0;p<t.length;p++){this.throwIfAborted(n);const w=t[p];if(d>0&&o()<d&&/[a-z0-9]/i.test(w)){const S=this.getPlausibleTypo(w,o);this.typeChar(h,S);const T=y(p,S,!0)*1.3;await this.delay(T,n),this.throwIfAborted(n),this.simulateBackspace(h);const R=y(p,"Backspace",!0)*1.1;await this.delay(R,n)}this.typeChar(h,w);let E=y(p,w);/[.,!?;;:]/.test(w)&&(E+=c),await this.delay(E,n)}}getPlausibleTypo(e,t){const r={a:"sqwz",b:"vghn",c:"xdfv",d:"ersfcx",e:"wsdr",f:"rtgdvc",g:"tyfhvb",h:"yugjbn",i:"ujko",j:"uikhmn",k:"ijolm",l:"kop",m:"njk",n:"bhjm",o:"iklp",p:"ol",q:"wa",r:"edft",s:"wedxza",t:"rfgy",u:"yhji",v:"cfgb",w:"qase",x:"zsdc",y:"tghu",z:"asx"},n=e.toLowerCase(),o=r[n]??"abcdefghijklmnopqrstuvwxyz",a=o[Math.floor(t()*o.length)];return e===e.toUpperCase()?a.toUpperCase():a}playPointerTour(e,t){if(typeof window>"u"||typeof document>"u")return Promise.resolve();const r=t?.moveDuration??1e3,n=t?.holdDuration??2e3;if(this.ensurePointerEl(),!this.pointerEl)return Promise.resolve();this.pointerEl.style.display="block",this.pointerEl.classList.remove("cfr-holding"),this.resetFullScreen();const o=document.querySelector(e);if(!o)return console.warn(`[FilmRecorder] Pointer tour target element not found: ${e}`),Promise.resolve();const a=o.getBoundingClientRect(),l=a.left+a.width/2,s=a.top+a.height/2,u=this.pointerX,c=this.pointerY,d=performance.now();return this.tourRafId&&cancelAnimationFrame(this.tourRafId),new Promise(h=>{const m=y=>{const p=y-d,w=Math.min(p/r,1),E=w<.5?2*w*w:1-Math.pow(-2*w+2,2)/2,S=u+(l-u)*E,T=c+(s-c)*E;if(this.pointerX=S,this.pointerY=T,this.pointerEl&&(this.pointerEl.style.left=`${S}px`,this.pointerEl.style.top=`${T}px`),w<1)this.tourRafId=requestAnimationFrame(m);else{this.pointerEl&&this.pointerEl.classList.add("cfr-holding"),this.mousePosGlobal={x:l,y:s};const R=this.state.resolution.w/this.state.resolution.h;this.targetRect=this.centeredRectOnPoint(l,s,window.innerWidth,window.innerHeight,R),setTimeout(()=>{this.pointerEl&&this.pointerEl.classList.remove("cfr-holding"),this.resetFullScreen(),setTimeout(()=>{this.pointerEl&&!this.pointerEl.classList.contains("cfr-holding")&&(this.pointerEl.style.display="none"),h()},1e3)},n)}};this.tourRafId=requestAnimationFrame(m)})}getState(){return{...this.state}}onStateChange(e){return this.listeners.add(e),e(this.getState()),()=>this.listeners.delete(e)}updateState(e){this.state={...this.state,...e},this.listeners.forEach(t=>t(this.state))}setResolution(e){if(this.state.recording)return;this.updateState({resolution:e});const t=this.computeGrid(window.innerWidth,window.innerHeight),r=e.w/e.h,{w:n,h:o}=this.getRecordingRegionBox(r,b,t.rows,b),a=Math.floor((b-n)/2),l=Math.floor((t.rows-o)/2);this.targetRect={col:a,row:l,w:n,h:o},this.liveRect={...this.targetRect}}setAutoZoom(e){this.updateState({autoZoom:e})}setPauseDuringScroll(e){this.updateState({pauseDuringScroll:e})}setShowGrid(e){this.updateState({showGrid:e})}setShowOutline(e){this.updateState({showOutline:e})}setMousePaused(e){this.updateState({mousePaused:e})}setElementSelector(e){if(this.options.elementSelector=e,this.updateState({elementSelector:e}),e){const t=this.calculateElementRect(e,this.options.elementPadding);t&&(this.targetRect=t)}else this.resetFullScreen()}setElementPadding(e){if(this.options.elementPadding=e,this.updateState({elementPadding:e}),this.options.elementSelector){const t=this.calculateElementRect(this.options.elementSelector,e);t&&(this.targetRect=t)}}setFixedRecordingRegion(e){if(this.options.fixedRecordingRegion=e,this.updateState({fixedRecordingRegion:e}),this.options.elementSelector){const t=this.calculateElementRect(this.options.elementSelector,this.options.elementPadding);t&&(this.targetRect=t)}else this.resetFullScreen()}setMovePointerToSelector(e){this.options.movePointerToSelector=e,this.updateState({movePointerToSelector:e})}setPointerClassName(e){this.options.pointerClassName=e,this.updateState({pointerClassName:e}),this.applyPointerClassName()}setPointerFillColor(e){this.options.pointerFillColor=this.validatePointerColor(e,"pointerFillColor"),this.updateState({pointerFillColor:this.options.pointerFillColor}),this.applyPointerColors()}setPointerBorderColor(e){this.options.pointerBorderColor=this.validatePointerColor(e,"pointerBorderColor"),this.updateState({pointerBorderColor:this.options.pointerBorderColor}),this.applyPointerColors()}setPointerRippleColor(e){this.options.pointerRippleColor=this.validatePointerColor(e,"pointerRippleColor"),this.updateState({pointerRippleColor:this.options.pointerRippleColor}),this.applyPointerColors()}setDisableRipple(e){this.options.disableRipple=e,this.updateState({disableRipple:e}),this.applyPointerClassName()}setIgnoreSelector(e){this.restoreIgnoredElements(),this.options.ignoreSelector=e,this.updateState({ignoreSelector:e}),this.state.recording&&this.hideIgnoredElements()}setTypingDefaults(e){this.options.typingDefaults=this.resolveTypingOptions(e)}resolveSelectorTimeoutMs(e){const t=e??this.options.selectorTimeoutMs;if(!Number.isFinite(t)||t<0)throw new TypeError("[FilmRecorder] selectorTimeoutMs must be a finite number >= 0.");return t}resolveTypingOptions(...e){const t={...re};for(const r of e)if(r)for(const n of Object.keys(r)){const o=r[n];o!==void 0&&(t[n]=o)}return this.validateTypingOptions(t),{...t}}validateTypingOptions(e,t="[FilmRecorder] Invalid typing options"){const r=[["cps",e.cps,"must be a finite number greater than 0"],["jitter",e.jitter,"must be between 0 and 1"],["punctuationPauseMs",e.punctuationPauseMs,"must be a finite number greater than or equal to 0"],["mistakeRate",e.mistakeRate,"must be between 0 and 1"]];for(const[n,o,a]of r){if(o===void 0)continue;if(!(Number.isFinite(o)&&(n==="cps"?o>0:n==="punctuationPauseMs"?o>=0:o>=0&&o<=1)))throw new TypeError(`${t}: ${n} ${a}; received ${String(o)}.`)}}delay(e,t){return new Promise((r,n)=>{if(t?.aborted)return n(new DOMException("Aborted","AbortError"));const o=()=>{clearTimeout(a),n(new DOMException("Aborted","AbortError"))};t&&t.addEventListener("abort",o);const a=setTimeout(()=>{t&&t.removeEventListener("abort",o),r()},e)})}findElementByText(e){if(typeof document>"u")return null;try{const r=`//*[text()='${e}' or contains(text(), '${e}')]`,o=document.evaluate(r,document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;if(o)return o}catch{}const t=Array.from(document.querySelectorAll("button, a, label, span, div, h1, h2, h3, h4, p"));for(const r of t)if(r.textContent?.trim()===e)return r;for(const r of t)if(r.textContent?.includes(e))return r;return null}async findElementByTextAsync(e,t,r=3e3){const n=performance.now();for(;;){if(t?.aborted)throw new DOMException("Aborted","AbortError");const o=this.findElementByText(e);if(o)return o;if(performance.now()-n>r)return null;await new Promise(a=>setTimeout(a,50))}}async clickText(e,t){const r=await this.findElementByTextAsync(e,t,this.options.selectorTimeoutMs);if(!r)throw this.createSelectorError(e,"clickText");await this.simulateClick(r,t)}async focusText(e,t){const r=await this.findElementByTextAsync(e,t,this.options.selectorTimeoutMs);if(!r)throw this.createSelectorError(e,"focusText");const n="data-cfr-temp-focus";r.setAttribute(n,"true"),this.setElementSelector(`[${n}="true"]`),await this.animatePointerTo(r,800,t)}createSelectorError(e,t){const r=this.state.currentScene?` in scene "${this.state.currentScene}"`:"";return new Error(`[FilmRecorder] Selector safety check failed for "${e}" during action "${t}"${r}.
2
+ Suggested fix: Ensure the element is mounted in the DOM, or add a stable attribute like data-film-target="${e}" or data-testid.`)}validateFilmScript(e){const t=G(e),r=[];t.length===0&&r.push({line:1,scene:null,commandIndex:null,message:"No film script scenes were found."});for(const n of t)n.commands.forEach((o,a)=>{if(["camera","type","click","pointer","move"].includes(o.type)&&o.type!=="camera"&&!o.selector&&r.push({line:o.sourceLine??1,scene:n.name,commandIndex:a,message:`${o.type} requires a non-empty selector.`}),o.type==="type"&&o.text===void 0&&r.push({line:o.sourceLine??1,scene:n.name,commandIndex:a,message:"type requires text."}),o.type==="type")try{this.validateTypingOptions({cps:o.cps,jitter:o.jitter,punctuationPauseMs:o.punctuationPauseMs,mistakeRate:o.mistakeRate},`[FilmRecorder] Invalid type command in scene "${n.name}"`)}catch(l){r.push({line:o.sourceLine??1,scene:n.name,commandIndex:a,message:l instanceof Error?l.message:String(l)})}});return{valid:r.length===0,scenes:t,diagnostics:r}}createScriptValidationError(e){const t=e.map(r=>{const n=r.scene?` scene "${r.scene}"`:"",o=r.commandIndex===null?"":` command ${r.commandIndex}`;return`line ${r.line}${n}${o}: ${r.message}`}).join(`
3
+ `);return new Error(`[FilmRecorder] Invalid film script:
4
+ ${t}`)}updateTourState(e,t=null){this.updateState({tourState:e,currentScene:t})}async stopTour(){this.tourAbortController&&(this.tourAbortController.abort(),this.tourAbortController=null),this.activeExecutionPromise=null,this.finalizationPromise=null,this.pendingActionGates=[],this.activeFilmScriptContext=null,this.activeFilmScriptOptions=null,this.updateState({tourState:"stopped",executionState:"finished",currentScene:null}),await this.options.onTourStop?.()}async stopAll(){await this.stopTour(),this.stopRecording()}finishRecording(e){const t=typeof e=="function"?{onReadyToEnd:e}:e??{};if(this.finalizationPromise&&!t.force)return this.finalizationPromise;const r=this.finalizeRecording(t);return t.force||(this.finalizationPromise=r),r}async finalizeRecording(e){const t=this.activeFilmScriptContext??{recorder:this,signal:new AbortController().signal,scenes:[]};try{e.force?this.tourAbortController?.abort():(await this.activeExecutionPromise,this.updateState({executionState:"waiting"}),await this.awaitActionGates(t)),this.updateState({executionState:"finalizing"}),await e.onReadyToEnd?.(t),await this.activeFilmScriptOptions?.onReadyToEnd?.(t),await this.options.onReadyToEnd?.(t),this.options.elementSelector&&(this.options.elementSelector=null,this.updateState({elementSelector:null})),this.zoomTopFullFrame(),await this.delay(1e3,e.force?void 0:t.signal),this.state.recording&&this.stopRecording(),await this.completeActiveFilmScript(t)}catch(r){throw await this.failActiveFilmScript(t,r),r}}executeFilmScript(e,t={}){this.activeFilmTitle=Xe(e),this.timelineMetadata&&!this.timelineMetadata.title&&(this.timelineMetadata.title=this.activeFilmTitle);const r=this.validateFilmScript(e);if(!r.valid)return Promise.reject(this.createScriptValidationError(r.diagnostics));try{this.resolveTypingOptions(this.options.typingDefaults,t.typingDefaults)}catch(o){return Promise.reject(o)}this.tourAbortController&&this.tourAbortController.abort(),this.pendingActionGates=[],this.finalizationPromise=null;const n=this.executeFilmScriptScenes(r.scenes,t);return this.activeExecutionPromise=n,n.finally(()=>{this.activeExecutionPromise===n&&(this.activeExecutionPromise=null),this.state.executionState==="executing"&&this.updateState({executionState:"waiting"})})}async executeFilmScriptScenes(e,t){const r=this.resolveTypingOptions(this.options.typingDefaults,t.typingDefaults);this.activeTypingRandom=this.createSeededRandom(t.typingSeed??this.options.typingSeed);const n=this.resolveSelectorTimeoutMs(t.selectorTimeoutMs);this.tourAbortController=new AbortController;const o=t.signal?this.linkAbortSignals(t.signal,this.tourAbortController.signal):this.tourAbortController.signal,a={recorder:this,signal:o,scenes:e};this.activeFilmScriptContext=a,this.activeFilmScriptOptions=t,this.updateState({tourState:"running",executionState:"executing",currentScene:null});try{await this.options.onTourStart?.();for(const[l,s]of e.entries()){this.throwIfAborted(o);const u=performance.now(),c=this.startTimelineScene(s,l);this.updateTourState("running",s.name),await t.onSceneStart?.(s),await this.options.onSceneStart?.(s);for(const[y,p]of s.commands.entries()){this.throwIfAborted(o);const w=performance.now(),E=this.startTimelineAction(c,p,y),S=R=>{const M=Promise.resolve(R).then(()=>{});M.catch(()=>{}),this.pendingActionGates.push({promise:M,scene:s,command:p,commandIndex:y})},T=()=>({...a,scene:s,command:p,commandIndex:y,elapsedMs:performance.now()-w,waitUntil:S});switch(await t.onActionStart?.(T()),await this.options.onActionStart?.(T()),p.type){case"camera":p.selector?(this.setElementSelector(p.selector),this.setElementPadding(p.padding??1.1)):(this.setElementSelector(null),this.zoomCenter());break;case"zoom":this.setElementSelector(null),p.to==="top"?this.zoomTop():p.to==="bottom"?this.zoomBottom():this.zoomCenter();break;case"type":if(p.selector&&p.text){const R=this.resolveTypingOptions(r,{cps:p.cps,jitter:p.jitter,punctuationPauseMs:p.punctuationPauseMs,mistakeRate:p.mistakeRate});await this.simulateTypeWithRandom(p.selector,p.text,R,o,this.activeTypingRandom,n)}break;case"click":p.selector&&await this.simulateClick(p.selector,o,n);break;case"pointer":case"move":p.selector&&await this.animatePointerTo(p.selector,p.durationMs??800,o,n);break;case"wait":p.durationMs&&await this.delay(p.durationMs,o);break}await t.onActionEnd?.(T()),await this.options.onActionEnd?.(T()),this.endTimelineAction(c,E)}const d=(s.endTime-s.startTime)*1e3,h=performance.now()-u,m=d-h;m>0&&await this.delay(m,o),await t.onSceneEnd?.(s),await this.options.onSceneEnd?.(s),this.endTimelineScene(c)}}catch(l){throw await this.failActiveFilmScript(a,l),l}}async runFilmScript(e,t={}){try{await this.executeFilmScript(e,t);const r=this.activeFilmScriptContext;if(!r)return;if(t.waitForCompletion){const n=Promise.resolve(t.waitForCompletion(r)).then(()=>{});n.catch(()=>{}),this.pendingActionGates.push({promise:n,scene:r.scenes[r.scenes.length-1]??{name:"completion",startTime:0,endTime:0,commands:[]},command:{type:"wait"},commandIndex:-1})}await this.finishRecording()}catch(r){const n=this.activeFilmScriptContext;if(n&&await this.failActiveFilmScript(n,r),!this.isAbortError(r))throw r}}async awaitActionGates(e){const t=this.activeFilmScriptOptions?.completionTimeoutMs??te;for(let r=0;r<this.pendingActionGates.length;r++){const n=this.pendingActionGates[r];try{await this.waitForCompletion(n.promise,e.signal,t)}catch(o){if(this.isAbortError(o))throw o;const a=o instanceof Error?o.message:String(o);throw new Error(`[FilmRecorder] Completion gate failed in scene "${n.scene.name}", command ${n.commandIndex} (${n.command.type}): ${a}`)}}}async waitForCompletion(e,t,r){if(!Number.isFinite(r)||r<=0)throw new Error("[FilmRecorder] completionTimeoutMs must be a positive finite number.");this.throwIfAborted(t);let n,o;const a=new Promise((s,u)=>{n=setTimeout(()=>{u(new Error(`[FilmRecorder] waitForCompletion timed out after ${r}ms.`))},r)}),l=new Promise((s,u)=>{o=()=>u(new DOMException("Aborted","AbortError")),t.addEventListener("abort",o,{once:!0})});try{await Promise.race([Promise.resolve(e),a,l])}finally{n&&clearTimeout(n),o&&t.removeEventListener("abort",o)}}throwIfAborted(e){if(e?.aborted)throw new DOMException("Aborted","AbortError")}createSeededRandom(e){if(e===void 0||e==="")return Math.random;let t=2166136261;for(const r of String(e))t^=r.charCodeAt(0),t=Math.imul(t,16777619);return()=>{t+=1831565813;let r=t;return r=Math.imul(r^r>>>15,r|1),r^=r+Math.imul(r^r>>>7,r|61),((r^r>>>14)>>>0)/4294967296}}isAbortError(e){return typeof e=="object"&&e!==null&&"name"in e&&e.name==="AbortError"}async completeActiveFilmScript(e){if(!this.activeFilmScriptContext&&e.scenes.length===0){this.updateState({executionState:"finished"});return}this.activeFilmScriptContext===e&&(this.activeFilmScriptContext=null,this.activeFilmScriptOptions=null,this.tourAbortController=null,this.activeExecutionPromise=null,this.pendingActionGates=[],this.updateState({tourState:"stopped",executionState:"finished",currentScene:null}),await this.options.onTourStop?.())}async failActiveFilmScript(e,t){if(this.activeFilmScriptContext!==e)return;if(this.tourAbortController?.abort(),this.activeFilmScriptContext=null,this.activeFilmScriptOptions=null,this.tourAbortController=null,this.activeExecutionPromise=null,this.pendingActionGates=[],this.isAbortError(t)){this.updateState({tourState:"stopped",executionState:"finished",currentScene:null}),await this.options.onTourStop?.();return}const r=t instanceof Error?t:new Error(String(t));this.updateState({tourState:"error",executionState:"error",currentScene:null}),await this.options.onTourError?.(r)}linkAbortSignals(e,t){const r=new AbortController,n=()=>r.abort();return e.aborted||t.aborted?(r.abort(),r.signal):(e.addEventListener("abort",n),t.addEventListener("abort",n),r.signal.addEventListener("abort",()=>{e.removeEventListener("abort",n),t.removeEventListener("abort",n)}),r.signal)}destroy(){this.destroyed=!0,this.cleanupEventListeners(),cancelAnimationFrame(this.cameraRafId),cancelAnimationFrame(this.renderRafId),this.holdTimer&&clearTimeout(this.holdTimer),this.zoomOutTimer&&clearTimeout(this.zoomOutTimer),this.state.recording?this.stopRecording():(this.stopCaptureStream(),this.restoreIgnoredElements()),this.pointerEl&&this.pointerEl.parentNode&&(this.pointerEl.parentNode.removeChild(this.pointerEl),this.pointerEl=null),this.overlays.forEach(e=>e.destroy()),this.overlays.clear(),this.tourRafId&&cancelAnimationFrame(this.tourRafId),this.videoEl&&this.videoEl.parentNode&&this.videoEl.parentNode.removeChild(this.videoEl),this.canvasEl&&this.canvasEl.parentNode&&this.canvasEl.parentNode.removeChild(this.canvasEl),this.clearLastRecording(),this.listeners.clear()}}function Xe(i){const e=/\bfilm\s+"([^"]+)"/.exec(i);return e?e[1]:null}function G(i){const e=[],t=/scene\s+"([^"]+)"\s+@(\d+(?:\.\d+)?)s\s*->\s*(\d+(?:\.\d+)?)s\s*\{/g;let r;for(;(r=t.exec(i))!==null;){const n=r[1],o=parseFloat(r[2]),a=parseFloat(r[3]);let l=1,s=t.lastIndex;const u=s;for(;l>0&&s<i.length;){const m=i[s];m==="{"?l++:m==="}"&&l--,s++}const c=i.substring(u,s-1),d=i.slice(0,r.index).split(`
5
+ `).length,h=Ye(c,d);e.push({name:n,startTime:o,endTime:a,commands:h})}return e}function Ye(i,e){const t=[],r=i.replace(/\/\/.*$/gm,l=>" ".repeat(l.length)),n=(l,s)=>{Object.defineProperty(l,"sourceLine",{value:s,enumerable:!1,configurable:!0}),t.push(l)},o=/\b(camera|zoom|type|click|pointer|move)\s*\{([\s\S]*?)\}|\bwait\s+(\d+(?:\.\d+)?)(ms|s)/g;let a;for(;(a=o.exec(r))!==null;){const l=e+i.slice(0,a.index).split(`
6
+ `).length;if(a[3]){const p=parseFloat(a[3]);n({type:"wait",durationMs:a[4]==="s"?p*1e3:p},l);continue}const s=a[1],u=a[2],c=p=>{const w=new RegExp(`${p}:\\s*(?:"([^"]*)"|'([^']*)')`).exec(u);return w?w[1]??w[2]:void 0},d=p=>{const w=new RegExp(`${p}:\\s*([^\\s}]+)`).exec(u);return w?Number(w[1]):void 0},h=()=>{const p=c("to")??c("position");return p==="top"||p==="bottom"||p==="center"?p:void 0},y=/selector:\s*(null|undefined)/.exec(u)?null:c("selector");n(s==="camera"?{type:s,selector:y??null,padding:d("padding")??1.1}:s==="zoom"?{type:s,to:h()??"center"}:s==="type"?{type:s,selector:y,text:c("text"),cps:d("cps"),jitter:d("jitter"),punctuationPauseMs:d("punctuationPauseMs"),mistakeRate:d("mistakeRate")}:s==="pointer"||s==="move"?{type:s,selector:y,durationMs:d("durationMs")??800}:{type:s,selector:y},l)}return t}class Ke{recorder;container;unsubscribe=null;settingsBar=null;gridOverlay=null;cropBox=null;recordBtn=null;pngBtn=null;resSelect=null;gridCheckbox=null;autoZoomCheckbox=null;pauseScrollCheckbox=null;outlineCheckbox=null;constructor(e,t=document.body){this.recorder=e,this.container=t,this.mount()}mount(){if(typeof window>"u")return;this.settingsBar=document.createElement("div"),this.settingsBar.className="cfr-settings-bar",this.settingsBar.innerHTML=`
7
+ <div class="cfr-settings-bar-content">
8
+ <button class="cfr-btn cfr-btn-default" id="cfr-record-btn" aria-label="Start recording">
9
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" style="margin-right:4px;"><circle cx="12" cy="12" r="10"/></svg>
10
+ Record <span class="cfr-kbd"></span>
11
+ </button>
12
+ <button class="cfr-btn cfr-btn-secondary" id="cfr-png-btn" disabled>
13
+ PNG frame
14
+ </button>
15
+ <button class="cfr-btn cfr-btn-ghost" id="cfr-full-btn">
16
+ Full <span class="cfr-kbd"></span>
17
+ </button>
18
+ <button class="cfr-btn cfr-btn-ghost" id="cfr-focus-btn">
19
+ Focus mouse <span class="cfr-kbd"></span>
20
+ </button>
21
+ <button class="cfr-btn cfr-btn-ghost" id="cfr-pause-mouse-btn">
22
+ Pause mouse <span class="cfr-kbd"></span>
23
+ </button>
24
+
25
+ <div class="cfr-divider"></div>
26
+
27
+ <div class="cfr-select-wrapper">
28
+ <select class="cfr-select" id="cfr-res-select"></select>
29
+ </div>
30
+
31
+ <div class="cfr-divider"></div>
32
+
33
+ <label class="cfr-checkbox-container">
34
+ <input type="checkbox" class="cfr-checkbox" id="cfr-grid-check">
35
+ <span class="cfr-label">Grid</span>
36
+ </label>
37
+ <label class="cfr-checkbox-container">
38
+ <input type="checkbox" class="cfr-checkbox" id="cfr-auto-zoom-check">
39
+ <span class="cfr-label">Auto-zoom on hold</span>
40
+ </label>
41
+ <label class="cfr-checkbox-container">
42
+ <input type="checkbox" class="cfr-checkbox" id="cfr-pause-scroll-check">
43
+ <span class="cfr-label">Pause zoom while scrolling</span>
44
+ </label>
45
+ <label class="cfr-checkbox-container">
46
+ <input type="checkbox" class="cfr-checkbox" id="cfr-outline-check">
47
+ <span class="cfr-label">Show outline border</span>
48
+ </label>
49
+ </div>
50
+ `,this.container.appendChild(this.settingsBar),this.gridOverlay=document.createElement("div"),this.gridOverlay.className="cfr-grid-overlay",this.gridOverlay.setAttribute("aria-hidden","true"),this.gridOverlay.style.top=`${P}px`,this.container.appendChild(this.gridOverlay),this.cropBox=document.createElement("div"),this.cropBox.className="cfr-crop-box",this.cropBox.setAttribute("aria-label","Cinematic 16:9 capture region");const e=this.recorder.getState().showOutline;this.cropBox.style.outline=e?`${O}px solid var(--cfr-outline)`:"none",this.cropBox.style.outlineOffset=e?`${O}px`:"0",this.container.appendChild(this.cropBox),this.recordBtn=this.container.querySelector("#cfr-record-btn"),this.pngBtn=this.container.querySelector("#cfr-png-btn"),this.resSelect=this.container.querySelector("#cfr-res-select"),this.gridCheckbox=this.container.querySelector("#cfr-grid-check"),this.autoZoomCheckbox=this.container.querySelector("#cfr-auto-zoom-check"),this.pauseScrollCheckbox=this.container.querySelector("#cfr-pause-scroll-check"),this.outlineCheckbox=this.container.querySelector("#cfr-outline-check");const t=this.container.querySelector("#cfr-full-btn"),r=this.container.querySelector("#cfr-focus-btn"),n=this.container.querySelector("#cfr-pause-mouse-btn"),o=/Mac/i.test(navigator.platform)?"⌘":"Ctrl";this.recordBtn&&(this.recordBtn.querySelector(".cfr-kbd").textContent=`${o}+${L.toUpperCase()}`),t&&(t.querySelector(".cfr-kbd").textContent=`${o}+↑`),r&&(r.querySelector(".cfr-kbd").textContent=`${o}+↓`),n&&(n.querySelector(".cfr-kbd").textContent=`${o}+L`),this.recorder.getState();const a=this.recorder.options.resolutions;a.forEach(l=>{const s=document.createElement("option");s.value=l.label,s.textContent=l.label,this.resSelect&&this.resSelect.appendChild(s)}),this.recordBtn?.addEventListener("click",()=>{this.recorder.getState().recording?this.recorder.stopRecording():this.recorder.startRecording()}),this.pngBtn?.addEventListener("click",()=>this.recorder.captureBitmap()),t?.addEventListener("click",()=>this.recorder.resetFullScreen()),r?.addEventListener("click",()=>this.recorder.zoomToMouse()),n?.addEventListener("click",()=>{const l=this.recorder.getState().mousePaused;this.recorder.setMousePaused(!l)}),this.resSelect?.addEventListener("change",l=>{const s=l.target.value,u=a.find(c=>c.label===s);u&&this.recorder.setResolution(u)}),this.gridCheckbox?.addEventListener("change",l=>{this.recorder.setShowGrid(l.target.checked)}),this.autoZoomCheckbox?.addEventListener("change",l=>{this.recorder.setAutoZoom(l.target.checked)}),this.pauseScrollCheckbox?.addEventListener("change",l=>{this.recorder.setPauseDuringScroll(l.target.checked)}),this.outlineCheckbox?.addEventListener("change",l=>{this.recorder.setShowOutline(l.target.checked)}),this.unsubscribe=this.recorder.onStateChange(l=>this.updateDOM(l))}updateDOM(e){if(typeof window>"u")return;const t=this.recorder.computeGrid(e.viewport.w,e.viewport.h);if(this.recordBtn&&(e.recording?(this.recordBtn.className="cfr-btn cfr-btn-destructive",this.recordBtn.innerHTML=`
51
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" style="margin-right:4px;"><rect x="3" y="3" width="18" height="18" rx="2"/></svg>
52
+ ${e.mousePaused?"Paused":"Stop"}
53
+ <span class="cfr-kbd">${/Mac/i.test(navigator.platform)?"⌘":"Ctrl"}+${L.toUpperCase()}</span>
54
+ `):(this.recordBtn.className="cfr-btn cfr-btn-default",this.recordBtn.innerHTML=`
55
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" style="margin-right:4px;"><circle cx="12" cy="12" r="10"/></svg>
56
+ Record
57
+ <span class="cfr-kbd">${/Mac/i.test(navigator.platform)?"⌘":"Ctrl"}+${L.toUpperCase()}</span>
58
+ `)),this.pngBtn&&(this.pngBtn.disabled=!e.recording),this.resSelect&&(this.resSelect.disabled=e.recording,this.resSelect.value=e.resolution.label),this.gridCheckbox&&(this.gridCheckbox.disabled=e.recording,this.gridCheckbox.checked=e.showGrid),this.autoZoomCheckbox&&(this.autoZoomCheckbox.checked=e.autoZoom),this.pauseScrollCheckbox&&(this.pauseScrollCheckbox.checked=e.pauseDuringScroll),this.outlineCheckbox&&(this.outlineCheckbox.checked=e.showOutline),this.gridOverlay){const r=e.showGrid&&!e.recording;this.gridOverlay.style.display=r?"block":"none",r&&(this.gridOverlay.style.backgroundImage=`
59
+ linear-gradient(to right, var(--cfr-border) 1px, transparent 1px),
60
+ linear-gradient(to bottom, var(--cfr-border) 1px, transparent 1px)
61
+ `,this.gridOverlay.style.backgroundSize=`${t.cellW}px ${t.cellH}px`)}if(this.cropBox){const r={x:e.displayRect.col*t.cellW,y:P+e.displayRect.row*t.cellH,width:e.displayRect.w*t.cellW,height:e.displayRect.h*t.cellH};this.cropBox.style.left=`${r.x}px`,this.cropBox.style.top=`${r.y}px`,this.cropBox.style.width=`${r.width}px`,this.cropBox.style.height=`${r.height}px`,this.cropBox.style.outline=e.showOutline?`${O}px solid var(--cfr-outline)`:"none",this.cropBox.style.outlineOffset=e.showOutline?`${O}px`:"0"}}unmount(){this.unsubscribe&&(this.unsubscribe(),this.unsubscribe=null),this.settingsBar&&this.settingsBar.parentNode&&this.settingsBar.parentNode.removeChild(this.settingsBar),this.gridOverlay&&this.gridOverlay.parentNode&&this.gridOverlay.parentNode.removeChild(this.gridOverlay),this.cropBox&&this.cropBox.parentNode&&this.cropBox.parentNode.removeChild(this.cropBox)}}function oe(i={}){const e=v.useRef(i);e.current=i;const[t,r]=v.useState(null),[n,o]=v.useState("idle"),[a,l]=v.useState(null),s=v.useRef(null);v.useEffect(()=>{const d=new ne(e.current);s.current=d;const h=d.getState();r(h),o(h.tourState),l(h.currentScene);const m=d.onStateChange(y=>{r(y),o(y.tourState),l(y.currentScene)});return()=>{m(),d.destroy(),s.current=null}},[]),v.useEffect(()=>{s.current&&i.autoZoom!==void 0&&s.current.setAutoZoom(i.autoZoom)},[i.autoZoom]),v.useEffect(()=>{s.current&&i.pauseDuringScroll!==void 0&&s.current.setPauseDuringScroll(i.pauseDuringScroll)},[i.pauseDuringScroll]),v.useEffect(()=>{s.current&&i.showGrid!==void 0&&s.current.setShowGrid(i.showGrid)},[i.showGrid]),v.useEffect(()=>{s.current&&i.showOutline!==void 0&&s.current.setShowOutline(i.showOutline)},[i.showOutline]),v.useEffect(()=>{s.current&&i.elementSelector!==void 0&&s.current.setElementSelector(i.elementSelector)},[i.elementSelector]),v.useEffect(()=>{s.current&&i.elementPadding!==void 0&&s.current.setElementPadding(i.elementPadding)},[i.elementPadding]),v.useEffect(()=>{s.current&&i.fixedRecordingRegion!==void 0&&s.current.setFixedRecordingRegion(i.fixedRecordingRegion)},[i.fixedRecordingRegion]),v.useEffect(()=>{s.current&&i.movePointerToSelector!==void 0&&s.current.setMovePointerToSelector(i.movePointerToSelector)},[i.movePointerToSelector]),v.useEffect(()=>{s.current&&i.ignoreSelector!==void 0&&s.current.setIgnoreSelector(i.ignoreSelector)},[i.ignoreSelector]),v.useEffect(()=>{s.current&&i.pointerClassName!==void 0&&s.current.setPointerClassName(i.pointerClassName)},[i.pointerClassName]),v.useEffect(()=>{s.current&&i.pointerFillColor!==void 0&&s.current.setPointerFillColor(i.pointerFillColor)},[i.pointerFillColor]),v.useEffect(()=>{s.current&&i.pointerBorderColor!==void 0&&s.current.setPointerBorderColor(i.pointerBorderColor)},[i.pointerBorderColor]),v.useEffect(()=>{s.current&&i.pointerRippleColor!==void 0&&s.current.setPointerRippleColor(i.pointerRippleColor)},[i.pointerRippleColor]),v.useEffect(()=>{s.current&&i.disableRipple!==void 0&&s.current.setDisableRipple(i.disableRipple)},[i.disableRipple]),v.useEffect(()=>{s.current&&i.overlays!==void 0&&s.current.setOverlays(i.overlays)},[i.overlays]);const u=()=>s.current?.stopTour()??Promise.resolve(),c=()=>s.current?.stopAll()??Promise.resolve();return{recorder:s.current,state:t,tourState:n,currentScene:a,stopTour:u,stopAll:c}}const Ve=({options:i={}})=>{const{recorder:e,state:t}=oe(i);if(!t||!e)return null;const r=e.computeGrid(t.viewport.w,t.viewport.h),n={x:t.displayRect.col*r.cellW,y:P+t.displayRect.row*r.cellH,width:t.displayRect.w*r.cellW,height:t.displayRect.h*r.cellH},o=typeof navigator<"u"&&/Mac/i.test(navigator.platform)?"⌘":"Ctrl",a=t.showGrid&&!t.recording,l=e.options.resolutions;return g.jsxs(g.Fragment,{children:[g.jsx("div",{className:"cfr-settings-bar",children:g.jsxs("div",{className:"cfr-settings-bar-content",children:[g.jsxs("button",{onClick:()=>t.recording?e.stopRecording():e.startRecording(),className:`cfr-btn ${t.recording?"cfr-btn-destructive":"cfr-btn-default"}`,"aria-label":t.recording?"Stop recording":"Start recording",children:[t.recording?g.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"currentColor",style:{marginRight:4},children:g.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"})}):g.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"currentColor",style:{marginRight:4},children:g.jsx("circle",{cx:"12",cy:"12",r:"10"})}),t.recording?t.mousePaused?"Paused":"Stop":"Record",g.jsxs("kbd",{className:"cfr-kbd",children:[o,"+",L.toUpperCase()]})]}),g.jsx("button",{onClick:()=>e.captureBitmap(),className:"cfr-btn cfr-btn-secondary",disabled:!t.recording,children:"PNG frame"}),g.jsxs("button",{onClick:()=>e.resetFullScreen(),className:"cfr-btn cfr-btn-ghost",children:["Full ",g.jsxs("kbd",{className:"cfr-kbd",children:[o,"+↑"]})]}),g.jsxs("button",{onClick:()=>e.zoomToMouse(),className:"cfr-btn cfr-btn-ghost",children:["Focus mouse ",g.jsxs("kbd",{className:"cfr-kbd",children:[o,"+↓"]})]}),g.jsxs("button",{onClick:()=>e.setMousePaused(!t.mousePaused),className:`cfr-btn ${t.mousePaused?"cfr-btn-secondary":"cfr-btn-ghost"}`,children:[t.mousePaused?"Resume mouse":"Pause mouse"," ",g.jsxs("kbd",{className:"cfr-kbd",children:[o,"+L"]})]}),g.jsx("div",{className:"cfr-divider"}),g.jsx("div",{className:"cfr-select-wrapper",children:g.jsx("select",{value:t.resolution.label,onChange:s=>{const u=l.find(c=>c.label===s.target.value);u&&e.setResolution(u)},disabled:t.recording,className:"cfr-select",children:l.map(s=>g.jsx("option",{value:s.label,children:s.label},s.label))})}),g.jsx("div",{className:"cfr-divider"}),g.jsxs("label",{className:"cfr-checkbox-container",children:[g.jsx("input",{type:"checkbox",checked:t.showGrid,onChange:s=>e.setShowGrid(s.target.checked),disabled:t.recording,className:"cfr-checkbox"}),g.jsx("span",{className:"cfr-label",children:"Grid"})]}),g.jsxs("label",{className:"cfr-checkbox-container",children:[g.jsx("input",{type:"checkbox",checked:t.autoZoom,onChange:s=>e.setAutoZoom(s.target.checked),className:"cfr-checkbox"}),g.jsx("span",{className:"cfr-label",children:"Auto-zoom on hold"})]}),g.jsxs("label",{className:"cfr-checkbox-container",children:[g.jsx("input",{type:"checkbox",checked:t.pauseDuringScroll,onChange:s=>e.setPauseDuringScroll(s.target.checked),className:"cfr-checkbox"}),g.jsx("span",{className:"cfr-label",children:"Pause zoom while scrolling"})]}),g.jsxs("label",{className:"cfr-checkbox-container",children:[g.jsx("input",{type:"checkbox",checked:t.showOutline,onChange:s=>e.setShowOutline(s.target.checked),className:"cfr-checkbox"}),g.jsx("span",{className:"cfr-label",children:"Show outline border"})]})]})}),a&&g.jsx("div",{"aria-hidden":!0,className:"cfr-grid-overlay",style:{top:P,backgroundImage:`
62
+ linear-gradient(to right, var(--cfr-border) 1px, transparent 1px),
63
+ linear-gradient(to bottom, var(--cfr-border) 1px, transparent 1px)
64
+ `,backgroundSize:`${r.cellW}px ${r.cellH}px`}}),g.jsx("div",{"aria-label":"Cinematic 16:9 capture region",className:"cfr-crop-box",style:{left:n.x,top:n.y,width:n.width,height:n.height,outline:t.showOutline?`${O}px solid var(--cfr-outline)`:"none",outlineOffset:t.showOutline?`${O}px`:"0"}})]})};function se(i,e={}){const t=A.tool({name:"navigate",description:"Navigate browser or shell to a target route, URL hash, or URL",strict:!0,parameters:{type:"object",properties:{url:{type:"string",description:"The URL path, hash route, or URL to navigate to"}},required:["url"],additionalProperties:!1},execute:async c=>{const{url:d}=c;return typeof window>"u"?"Cannot navigate: not in browser context":(window.router?window.router.navigate({to:d}):window.location.hash=d,`Successfully navigated to: ${d}`)}}),r=A.tool({name:"click",description:"Simulate a visual pointer click and trigger a DOM click event on the target selector",strict:!0,parameters:{type:"object",properties:{selector:{type:"string",description:"CSS selector of the target element to click"}},required:["selector"],additionalProperties:!1},execute:async c=>{const{selector:d}=c;try{return await i.simulateClick(d),`Successfully clicked element: ${d}`}catch(h){return`Failed to click ${d}: ${h.message}`}}}),n=A.tool({name:"moveMousePointerTo",description:"Smoothly move the simulated visual pointer cursor to the center of the specified selector",strict:!0,parameters:{type:"object",properties:{selector:{type:"string",description:"CSS selector of the target element to hover"},durationMs:{type:"number",description:"Duration of the pointer movement in milliseconds",default:800}},required:["selector","durationMs"],additionalProperties:!1},execute:async c=>{const{selector:d,durationMs:h=800}=c;try{return await i.animatePointerTo(d,h),`Moved mouse pointer to: ${d}`}catch(m){return`Failed to move pointer to ${d}: ${m.message}`}}}),o=A.tool({name:"drawRegionAroundCssSelector",description:"Adjust the recording camera crop-box to focus/zoom onto the specified element, or reset to fullscreen",strict:!0,parameters:{type:"object",properties:{selector:{type:["string","null"],description:"CSS selector to zoom into. Provide null or empty string to zoom out to full screen"},padding:{type:"number",description:"Padding multiplier around the selector boundaries",default:1.1}},required:["selector","padding"],additionalProperties:!1},execute:async c=>{const{selector:d,padding:h=1.1}=c;return d?(i.setElementSelector(d),i.setElementPadding(h),`Focused camera region on element: ${d}`):(i.setElementSelector(null),i.resetFullScreen(),"Reset camera to full viewport")}}),a=A.tool({name:"typeText",description:"Simulate keystrokes to type text into an input field or textarea",strict:!0,parameters:{type:"object",properties:{selector:{type:"string",description:"CSS selector of the target input/textarea element"},text:{type:"string",description:"The text content to type into the field"},cps:{type:"number",description:"Typing speed in characters per second",default:24},jitter:{type:"number",description:"Per-character timing variation from 0 to 1",default:.22},punctuationPauseMs:{type:"number",description:"Extra pause after punctuation in milliseconds",default:120},mistakeRate:{type:"number",description:"Corrected typo probability from 0 to 1",default:.012}},required:["selector","text","cps","jitter","punctuationPauseMs","mistakeRate"],additionalProperties:!1},execute:async c=>{const{selector:d,text:h,cps:m=24,jitter:y=.22,punctuationPauseMs:p=120,mistakeRate:w=.012}=c;try{return await i.simulateType(d,h,{cps:m,jitter:y,punctuationPauseMs:p,mistakeRate:w}),`Typed "${h}" into element: ${d}`}catch(E){return`Failed to type text into ${d}: ${E.message}`}}}),l=A.tool({name:"wait",description:"Pause execution for a specific duration in milliseconds to align with scene timing",strict:!0,parameters:{type:"object",properties:{durationMs:{type:"number",description:"Duration to pause in milliseconds"}},required:["durationMs"],additionalProperties:!1},execute:async c=>{const{durationMs:d}=c;return await new Promise(h=>setTimeout(h,d)),`Waited for ${d}ms`}}),s=`
65
+ You are an automated video-demo assistant. Your task is to interpret a film script scene-by-scene
66
+ and execute the corresponding UI interactions (navigating, moving the cursor, typing, and clicking)
67
+ while adjusting the recording camera zoom around active components.
68
+
69
+ Ensure actions are timed logically according to the scene start/end intervals.
70
+
71
+ Every generated film must visibly demonstrate user interaction.
72
+
73
+ Interaction rules:
74
+ - Never rely on passive waits alone.
75
+ - Before each interaction, focus the camera on its target.
76
+ - Every type command internally moves the pointer, clicks/focuses the input, then types.
77
+ - Use cps 20-30, jitter 0.12-0.28, punctuationPauseMs 80-180, and mistakeRate 0-0.015 for natural prompt entry.
78
+ - Omit command-level typing values when recorder or run defaults already define the intended cadence.
79
+ - Do not add a separate click immediately before type unless the interaction genuinely requires two clicks.
80
+ - Use pointer commands to visibly focus targets without clicking them.
81
+ - Every navigation or submission must use a visible pointer click.
82
+ - Use stable CSS selectors only.
83
+ - Keep camera padding between 1.05 and 1.18.
84
+ - After submitting, focus the camera on the response area.
85
+ - Move between at least two meaningful camera targets.
86
+ - End with \`camera { selector: null }\`.
87
+ - Video/Script duration must always be a multiple of 5 seconds (e.g. 5s, 10s, 15s). If the script finishes fast or ends early, append or extend a \`wait\` command to round up the final total script length to the next closest multiple of 5 seconds.
88
+ - Before entering text on the prompt box, the mouse must always move to and pause on the top-left corner of the prompt box.
89
+
90
+ Example prompt sequence:
91
+ camera { selector: ".demo-input-card" padding: 1.16 }
92
+ move { selector: "#demo-prompt-input" }
93
+ wait 500ms
94
+ type { selector: "#demo-prompt-input" text: "<user request>" cps: 24 jitter: 0.22 punctuationPauseMs: 120 mistakeRate: 0.012 }
95
+ wait 250ms
96
+ click { selector: ".demo-submit-button" }
97
+ camera { selector: ".demo-output-panel" padding: 1.12 }
98
+
99
+ Reject or regenerate scripts when:
100
+ - They contain navigation without pointer clicks.
101
+ - They stay fullscreen for the entire film.
102
+ - They use only \`wait\` commands to represent activity.
103
+ - They omit the final zoom-out.
104
+ `,u=e.instructions?`${s}
105
+
106
+ Additional Instructions:
107
+ ${e.instructions}`:s;return new A.Agent({name:"Web Assistant",instructions:u,tools:[t,r,n,o,a,l]})}function Je(i,e={}){const t=e.apiKey||"proxied-by-server",r=e.baseURL,n=e.tracingDisabled??!0,o=new Fe({apiKey:t,baseURL:r,dangerouslyAllowBrowser:!0}),a=new A.OpenAIProvider({openAIClient:o}),l=new A.Runner({modelProvider:a,tracingDisabled:n,model:e.model}),s=l.run.bind(l);l.run=(async(c,d,h={})=>{const m=await s(c,d,{maxTurns:e.maxTurns??20,...h});return i.getState().recording&&await i.finishRecording(),m});const u=se(i,{instructions:e.instructions});return{runner:l,agent:u}}class W extends Error{trace;constructor(e,t){super(e),this.name="AppFilmGenerationError",this.cause=t?.cause,this.trace=t?.trace}}const Z=/^\s*#\s*setup\s+([A-Za-z0-9_.:-]+)\s*:\s*(.*)$/;function F(i,e=""){const t=[];for(const r of i.split(/\r?\n/)){const n=Z.exec(r);n&&t.push({type:n[1],value:ut(n[2].trim())})}return{appId:e,entries:t}}function I(i){return i.split(/\r?\n/).filter(e=>!Z.test(e)).join(`
108
+ `).replace(/^\s+/,"")}function ae(i){return i.entries.map(e=>`# setup ${e.type}: ${pt(e.value)}`).join(`
109
+ `)}function Qe(i,e={}){const t=i.trim(),r=ht(e.app)||e.setup?.appId||"",n=F(t,r),o=mt(n,e.setup,r),a=I(t).trim(),l=t.split(/\r?\n/).filter(d=>Z.test(d)).join(`
110
+ `),s=e.stripSetupForDisplay??!0,u=e.stripSetupForPlayback??!0;return{isFilmScript:/^\s*film\s+/i.test(a),fullScript:t,displayScript:s?a:t,runnableScript:u?a:t,setup:o,setupComments:l,filmBody:a}}function j(i,e){const t=V(F(i,e.id),e),r=G(I(i)),n=[];r.length===0&&n.push({line:1,scene:null,commandIndex:null,message:"No film script scenes were found."});const o=yt(t),a=Object.values(e.selectors);for(const l of r)l.commands.forEach((s,u)=>{if(!s.selector)return;const c=a.find(d=>d.selector===s.selector);if(!c){n.push({line:s.sourceLine??1,scene:l.name,commandIndex:u,message:`Selector "${s.selector}" is not declared in app profile "${e.id}".`});return}for(const d of c.requiresSetup??[])o.has(d)||n.push({line:s.sourceLine??1,scene:l.name,commandIndex:u,message:`Selector "${s.selector}" requires setup "${d}", but that setup was not provided.`})});return wt(t,e,n),vt(I(i),t,e,n),{valid:n.length===0,scenes:r,diagnostics:n}}async function et(i){Me(i.signal);const e=ue(i.trace);try{let t,r=[];const n=[];if(rt(i)){t=await it(i,e);const c=Ee(t,i.app);r=c.diagnostics,n.push(...c.warnings),Y(e,"intent",{diagnostics:c.diagnostics,warnings:c.warnings})}const o=await X("script",{instructions:ce(i.app,t),input:de(i.input,t),tools:[we(i.app)],toolChoice:"required",signal:i.signal},i.complete,e),a=Te(o);if(t=t??a.intent,a.intent){const c=Ee(a.intent,i.app);r.push(...c.diagnostics),n.push(...c.warnings)}let l=V(gt(a.setup??F(a.script,i.app.id),t,i.app),i.app),s=J(a.script,l),u=j(s,i.app);if(n.push(...a.warnings??[]),Y(e,"script",{diagnostics:[...r,...u.diagnostics],warnings:n}),(r.length>0||!u.valid)&&i.repair){const c=await le(s,{app:i.app,input:de(i.input,t),complete:i.complete,signal:i.signal,diagnostics:[...r,...u.diagnostics]},e);s=c.script,l=c.setup,u={valid:c.diagnostics.length===0,scenes:G(I(c.script)),diagnostics:c.diagnostics},n.push(...c.warnings)}return me({intent:t,script:s,setup:l,diagnostics:[...r,...u.diagnostics],warnings:n},e)}catch(t){fe(t,e)}}async function tt(i,e){Me(e.signal);const t=ue(e.trace);return le(i,e,t)}async function le(i,e,t){try{const r=e.diagnostics??j(i,e.app).diagnostics,n=await X("repair",{instructions:nt(e.app,r),input:[e.input?`User request:
111
+ ${e.input}`:"",`Invalid script:
112
+ ${i}`,`Diagnostics:
113
+ ${r.map(u=>u.message).join(`
114
+ `)}`].filter(Boolean).join(`
115
+
116
+ `),tools:[we(e.app)],toolChoice:"required",signal:e.signal},e.complete,t),o=Te(n),a=V(o.setup??F(o.script,e.app.id),e.app),l=J(o.script,a),s=j(l,e.app);return Y(t,"repair",{diagnostics:s.diagnostics,warnings:o.warnings??[]}),me({script:l,setup:a,diagnostics:s.diagnostics,warnings:o.warnings??[]},t)}catch(r){fe(r,t)}}async function it(i,e){const t=await X("intent",{instructions:ot(i.app),input:i.input,tools:[dt(i.app)],toolChoice:"required",signal:i.signal},i.complete,e);return Tt(Rt(t),i.app)}function rt(i){return i.intentMode!=="off"&&(i.app.intents?.length??0)>0}function ce(i,e){return[`You generate code.film scripts for ${i.name}.`,i.description?`App description: ${i.description}`:"","Return the result by calling the create_film_script tool.","Do not return prose outside the tool call.","Use only selectors declared in the app profile.","Honor any approval or permission-mode guidance declared by the app profile; do not invent older permission labels.","Include setup entries for every selector that requires setup.","Prefer the smallest meaningful camera scope unless the user asks for page chrome, navigation, sidebars, collections, or multiple regions.",e?"Follow the resolved intent exactly. Only submit a prompt when resolvedIntent.submitPrompt is true.":"",e?`Resolved intent:
117
+ ${JSON.stringify(e,null,2)}`:"","Preserve setup comments at the top of the script for compatibility.","",ye(i)].filter(Boolean).join(`
118
+ `)}function nt(i,e){return[ce(i),"","Repair the script so validation passes.","Keep the user intent, but add missing setup or switch to valid selectors as needed.","Validation diagnostics:",e.map(t=>`- ${t.message}`).join(`
119
+ `)].join(`
120
+ `)}function ot(i){return[`Resolve user film requests for ${i.name}.`,i.description?`App description: ${i.description}`:"","Return the result by calling the resolve_film_intent tool.","Do not return prose outside the tool call.","Choose exactly one declared intent recipe.","Use examples, synonyms, and negative examples as model context, not as literal substring rules.","Do not assume a short prompt should be submitted to the app. Only set submitPrompt true when the chosen intent requires app prompt submission.","When prompt tools or attachments are needed, return them as structured promptTools or attachments.","",ye(i)].filter(Boolean).join(`
121
+ `)}function de(i,e){return e?[`User request:
122
+ ${i}`,`Resolved intent:
123
+ ${JSON.stringify(e,null,2)}`].join(`
124
+
125
+ `):i}function ue(i){const e=st(i);return{options:e,trace:e.enabled?{calls:[]}:void 0}}function st(i){return i?i===!0?{enabled:!0,includeInstructions:!0,includeRaw:!1}:{enabled:i.enabled!==!1,includeInstructions:i.includeInstructions??!0,includeRaw:i.includeRaw??!1,redact:i.redact}:{enabled:!1,includeInstructions:!1,includeRaw:!1}}async function X(i,e,t,r){if(!r.trace)return t(e);const n=Date.now(),o={phase:i,request:at(e,r.options),startedAt:new Date(n).toISOString()};r.trace.calls.push(o);try{const a=await t(e);return o.response=lt(a,r.options),pe(o,n),he(r,o),a}catch(a){throw o.error=ct(a),pe(o,n),he(r,o),a}}function at(i,e){return{instructions:e.includeInstructions?i.instructions:void 0,input:i.input,tools:i.tools,toolChoice:i.toolChoice}}function lt(i,e){return{toolName:i.toolName,arguments:i.arguments,raw:e.includeRaw?i.raw:void 0}}function pe(i,e){const t=Date.now();i.finishedAt=new Date(t).toISOString(),i.durationMs=t-e}function Y(i,e,t){if(!i.trace)return;const r=[...i.trace.calls].reverse().find(n=>n.phase===e);r&&(t.diagnostics&&(r.diagnostics=t.diagnostics),t.warnings&&(r.warnings=t.warnings))}function he(i,e){if(!i.trace||!i.options.redact)return;const t=i.trace.calls.indexOf(e);t!==-1&&(i.trace.calls[t]=i.options.redact(e))}function me(i,e){return e.trace?{...i,trace:e.trace}:i}function fe(i,e){throw e.trace?i instanceof W?(i.trace=i.trace??e.trace,i):new W(ge(i),{cause:i,trace:e.trace}):i}function ct(i){return{message:ge(i),name:i instanceof Error?i.name:void 0}}function ge(i){return i instanceof Error?i.message:String(i)}function ye(i){const e=Object.entries(i.selectors).map(([c,d])=>{const h=d.requiresSetup?.length?` Requires setup: ${d.requiresSetup.join(", ")}.`:"";return`- ${c}: ${d.selector} (${d.role??"component"}) - ${d.description}.${h}`}).join(`
126
+ `),t=Object.entries(i.pages).map(([c,d])=>`- ${c}: ${d.description}; container ${d.containerSelector}`+(d.defaultScopeSelector?`; default scope ${d.defaultScopeSelector}`:"")).join(`
127
+ `),r=i.setupCapabilities.map(c=>`- ${c}`).join(`
128
+ `),n=(i.rules??[]).map(c=>`- ${c}`).join(`
129
+ `),o=Object.entries(i.vocabulary??{}).map(([c,d])=>`- ${c}: ${d.join(", ")}`).join(`
130
+ `),a=(i.examples??[]).map(c=>`User: ${c.input}
131
+ Script:
132
+ ${J(c.script,c.setup??F(c.script,i.id))}`).join(`
133
+
134
+ `),l=(i.intents??[]).map(c=>[`- ${c.id}: ${c.description}`,` Page: ${c.page}; submitPrompt: ${c.submitPrompt}`,c.defaultScopeSelector?` Default scope: ${c.defaultScopeSelector}`:"",c.examples.length?` Examples: ${c.examples.join("; ")}`:"",c.synonyms?.length?` Synonyms: ${c.synonyms.join("; ")}`:"",c.negativeExamples?.length?` Negative examples: ${c.negativeExamples.join("; ")}`:"",c.requiredSetup?.length?` Required setup: ${c.requiredSetup.join(", ")}`:"",c.scriptGuidance?` Script guidance: ${c.scriptGuidance}`:""].filter(Boolean).join(`
135
+ `)).join(`
136
+ `),s=(i.promptTools??[]).map(c=>{const d=c.installed===!1?"uninstalled":"installed";return[`- ${c.id}: ${c.name} (${c.mention}, ${d}) - ${c.description}`,c.aliases?.length?` Aliases: ${c.aliases.join("; ")}`:"",c.examples?.length?` Examples: ${c.examples.join("; ")}`:""].filter(Boolean).join(`
137
+ `)}).join(`
138
+ `),u=(i.attachmentTypes??[]).map(c=>[`- ${c.id}: ${c.label}`,c.aliases?.length?` Aliases: ${c.aliases.join("; ")}`:"",c.examples?.length?` Examples: ${c.examples.join("; ")}`:""].filter(Boolean).join(`
139
+ `)).join(`
140
+ `);return["Selectors:",e,"","Pages:",t,"","Setup capabilities:",r,i.defaults?`
141
+ Generation defaults:
142
+ ${JSON.stringify(i.defaults,null,2)}`:"",l?`
143
+ Intent recipes:
144
+ ${l}`:"",s?`
145
+ Prompt tools:
146
+ ${s}`:"",u?`
147
+ Attachment types:
148
+ ${u}`:"",n?`
149
+ Rules:
150
+ ${n}`:"",o?`
151
+ Vocabulary:
152
+ ${o}`:"",a?`
153
+ Examples:
154
+ ${a}`:""].join(`
155
+ `)}function dt(i){const e=(i.intents??[]).map(o=>o.id),t=Object.keys(i.pages),r=(i.promptTools??[]).map(o=>o.id),n=(i.attachmentTypes??[]).map(o=>o.id);return{type:"function",name:"resolve_film_intent",description:"Resolve a user film request into one declared app intent.",strict:!0,parameters:{type:"object",properties:{intentId:_(e),confidence:K({type:"number"}),page:_(t),scopeSelector:x(),submitPrompt:{type:"boolean"},promptText:x(),promptTools:{anyOf:[{type:"array",items:ve(r)},{type:"null"}]},attachments:{anyOf:[{type:"array",items:be(n)},{type:"null"}]},setupNeeded:{anyOf:[{type:"array",items:{type:"string"}},{type:"null"}]},rationale:{type:"string"}},required:["intentId","confidence","page","scopeSelector","submitPrompt","promptText","promptTools","attachments","setupNeeded","rationale"],additionalProperties:!1}}}function we(i){const e=(i.promptTools??[]).map(r=>r.id),t=(i.attachmentTypes??[]).map(r=>r.id);return{type:"function",name:"create_film_script",description:"Create a code.film script and structured setup for a host app.",strict:!0,parameters:{type:"object",properties:{intent:{anyOf:[{type:"object",properties:{id:{type:"string"},confidence:K({type:"number"}),page:{type:"string"},scopeSelector:x(),submitPrompt:{type:"boolean"},promptText:x(),promptTools:{anyOf:[{type:"array",items:ve(e)},{type:"null"}]},attachments:{anyOf:[{type:"array",items:be(t)},{type:"null"}]},setupNeeded:{anyOf:[{type:"array",items:{type:"string"}},{type:"null"}]},rationale:x()},required:["id","confidence","page","scopeSelector","submitPrompt","promptText","promptTools","attachments","setupNeeded","rationale"],additionalProperties:!1},{type:"null"}]},script:{type:"string",description:"Complete code.film script. Include setup comments at the top when setup is required."},setup:{type:"object",properties:{appId:{type:"string",enum:[i.id]},entries:{type:"array",items:{type:"object",properties:{type:{type:"string"},value:{type:"string",description:"Setup value as JSON text for objects/arrays/strings, or plain text for simple values."}},required:["type","value"],additionalProperties:!1}}},required:["appId","entries"],additionalProperties:!1},warnings:{type:"array",items:{type:"string"}}},required:["intent","script","setup","warnings"],additionalProperties:!1}}}function _(i=[]){return i.length>0?{type:"string",enum:i}:{type:"string"}}function x(){return K({type:"string"})}function K(i){return{anyOf:[i,{type:"null"}]}}function ve(i=[]){return{type:"object",properties:{id:_(i),mention:{type:"string"},label:x(),reason:x()},required:["id","mention","label","reason"],additionalProperties:!1}}function be(i=[]){return{type:"object",properties:{type:_(i),name:x(),label:x(),reason:x()},required:["type","name","label","reason"],additionalProperties:!1}}function ut(i){if(i==="")return"";try{return JSON.parse(i)}catch{return i}}function pt(i){return typeof i=="string"?i:JSON.stringify(i)}function V(i,e){return{appId:i.appId||e.id,entries:i.entries.map(t=>({type:e.setupAliases?.[t.type]??t.type,value:t.value}))}}function ht(i){return i?typeof i=="string"?i:i.id:""}function mt(i,e,t){const r=[...i.entries];for(const n of e?.entries??[])r.some(o=>ft(o,n))||r.push(n);return{appId:t||i.appId||e?.appId||"",entries:r}}function ft(i,e){return i.type===e.type&&JSON.stringify(i.value)===JSON.stringify(e.value)}function gt(i,e,t){if(!e)return i;const r=t.intents?.find(o=>o.id===e.id),n=[...i.entries];for(const o of r?.setup??[])n.some(a=>a.type===o.type)||n.push(o);for(const o of e.promptTools??[])n.some(a=>Se(a,o))||n.push({type:"promptTool",value:o});for(const o of e.attachments??[])n.some(a=>bt(a,o))||n.push({type:"attachment",value:o});return{...i,entries:n}}function yt(i){const e=new Set;for(const t of i.entries)e.add(t.type),C(t.value)&&(typeof t.value.type=="string"&&e.add(`${t.type}:${t.value.type}`),typeof t.value.id=="string"&&e.add(`${t.type}:${t.value.id}`));return e}function wt(i,e,t){const r=new Set(e.setupCapabilities),n=new Set(e.setupCapabilities.map(o=>o.split(":")[0]));for(const o of i.entries)!(r.has(o.type)||C(o.value)&&typeof o.value.type=="string"&&r.has(`${o.type}:${o.value.type}`))&&!n.has(o.type)&&t.push({line:1,scene:null,commandIndex:null,message:`Setup "${o.type}" is not declared in app profile "${e.id}".`})}function vt(i,e,t,r){for(const n of t.promptTools??[]){if(!i.includes(n.mention))continue;e.entries.some(a=>Se(a,{id:n.id,mention:n.mention}))||r.push(k(`Script uses prompt tool mention "${n.mention}" without matching promptTool setup.`))}}function Se(i,e){return i.type!=="promptTool"||!C(i.value)?!1:i.value.id===e.id||i.value.mention===e.mention}function bt(i,e){return i.type!=="attachment"||!C(i.value)?!1:i.value.type===e.type&&(e.name===void 0||i.value.name===e.name)}function St(i,e){const t=new Set(e.setupCapabilities),r=new Set(e.setupCapabilities.map(n=>n.split(":")[0]));return t.has(i)||r.has(i.split(":")[0])}function Ee(i,e){const t=[],r=[],n=e.intents?.find(o=>o.id===i.id);n||t.push(k(`Resolved intent "${i.id}" is not declared in app profile "${e.id}".`)),e.pages[i.page]||t.push(k(`Resolved intent page "${i.page}" is not declared in app profile "${e.id}".`)),i.scopeSelector&&!Et(i.scopeSelector,e)&&t.push(k(`Resolved intent scope selector "${i.scopeSelector}" is not declared in app profile "${e.id}".`));for(const o of i.setupNeeded??[])St(o,e)||t.push(k(`Resolved intent setup "${o}" is not declared in app profile "${e.id}".`));for(const o of i.promptTools??[]){const a=e.promptTools?.find(l=>l.id===o.id);if(!a){t.push(k(`Resolved prompt tool "${o.id}" is not declared in app profile "${e.id}".`));continue}o.mention!==a.mention&&t.push(k(`Resolved prompt tool "${o.id}" mention "${o.mention}" does not match declared mention "${a.mention}".`)),a.installed===!1&&r.push(`Prompt tool "${a.name}" is declared but not installed.`)}for(const o of i.attachments??[])e.attachmentTypes?.some(a=>a.id===o.type)||t.push(k(`Resolved attachment type "${o.type}" is not declared in app profile "${e.id}".`));return n&&i.submitPrompt!==n.submitPrompt&&r.push(`Resolved intent "${i.id}" changed submitPrompt from recipe default ${n.submitPrompt} to ${i.submitPrompt}.`),{diagnostics:t,warnings:r}}function Et(i,e){return Object.values(e.selectors).some(t=>t.selector===i)?!0:Object.values(e.pages).some(t=>t.containerSelector===i||t.defaultScopeSelector===i)}function k(i){return{line:1,scene:null,commandIndex:null,message:i}}function Tt(i,e){const t=e.intents?.find(r=>r.id===i.intentId);return{id:i.intentId,confidence:i.confidence,page:i.page||t?.page||"",scopeSelector:i.scopeSelector??t?.defaultScopeSelector,submitPrompt:i.submitPrompt,promptText:i.promptText,promptTools:i.promptTools,attachments:i.attachments,setupNeeded:i.setupNeeded??t?.requiredSetup,rationale:i.rationale}}function Rt(i){if(i.toolName!=="resolve_film_intent")throw new Error(`[code-film] Expected resolve_film_intent tool call, received "${i.toolName}".`);if(!C(i.arguments))throw new Error("[code-film] resolve_film_intent arguments must be an object.");if(typeof i.arguments.intentId!="string")throw new Error("[code-film] resolve_film_intent.intentId must be a string.");if(typeof i.arguments.page!="string")throw new Error("[code-film] resolve_film_intent.page must be a string.");if(typeof i.arguments.submitPrompt!="boolean")throw new Error("[code-film] resolve_film_intent.submitPrompt must be a boolean.");if(typeof i.arguments.rationale!="string")throw new Error("[code-film] resolve_film_intent.rationale must be a string.");return{intentId:i.arguments.intentId,confidence:typeof i.arguments.confidence=="number"?i.arguments.confidence:void 0,page:i.arguments.page,scopeSelector:typeof i.arguments.scopeSelector=="string"?i.arguments.scopeSelector:void 0,submitPrompt:i.arguments.submitPrompt,promptText:typeof i.arguments.promptText=="string"?i.arguments.promptText:void 0,promptTools:Re(i.arguments.promptTools),attachments:Ce(i.arguments.attachments),setupNeeded:xe(i.arguments.setupNeeded),rationale:i.arguments.rationale}}function Te(i){if(i.toolName!=="create_film_script")throw new Error(`[code-film] Expected create_film_script tool call, received "${i.toolName}".`);if(!C(i.arguments))throw new Error("[code-film] create_film_script arguments must be an object.");if(typeof i.arguments.script!="string")throw new Error("[code-film] create_film_script.script must be a string.");return{intent:Ct(i.arguments.intent),script:i.arguments.script,setup:xt(i.arguments.setup)?i.arguments.setup:void 0,warnings:Array.isArray(i.arguments.warnings)?i.arguments.warnings.filter(e=>typeof e=="string"):[]}}function Ct(i){if(C(i)&&!(typeof i.id!="string"||typeof i.page!="string"||typeof i.submitPrompt!="boolean"))return{id:i.id,confidence:typeof i.confidence=="number"?i.confidence:void 0,page:i.page,scopeSelector:typeof i.scopeSelector=="string"?i.scopeSelector:void 0,submitPrompt:i.submitPrompt,promptText:typeof i.promptText=="string"?i.promptText:void 0,promptTools:Re(i.promptTools),attachments:Ce(i.attachments),setupNeeded:xe(i.setupNeeded),rationale:typeof i.rationale=="string"?i.rationale:void 0}}function Re(i){if(Array.isArray(i))return i.filter(C).flatMap(e=>typeof e.id!="string"||typeof e.mention!="string"?[]:[{id:e.id,mention:e.mention,label:typeof e.label=="string"?e.label:void 0,reason:typeof e.reason=="string"?e.reason:void 0}])}function Ce(i){if(Array.isArray(i))return i.filter(C).flatMap(e=>typeof e.type!="string"?[]:[{type:e.type,name:typeof e.name=="string"?e.name:void 0,label:typeof e.label=="string"?e.label:void 0,reason:typeof e.reason=="string"?e.reason:void 0}])}function xe(i){if(Array.isArray(i))return i.filter(e=>typeof e=="string")}function J(i,e){const t=I(i);return e.entries.length===0?t:`${ae(e)}
156
+ ${t}`}function C(i){return typeof i=="object"&&i!==null&&!Array.isArray(i)}function xt(i){return C(i)&&typeof i.appId=="string"&&Array.isArray(i.entries)&&i.entries.every(e=>C(e)&&typeof e.type=="string"&&"value"in e)}function Me(i){if(i?.aborted)throw new DOMException("Aborted","AbortError")}function Mt(i,e={}){let t=!1;const r=o=>{Pt(o.origin,e.allowedOrigins)&&Pe(o.data)&&Oe(i,o.data.command)},n={start(){return t||typeof window>"u"||(window.addEventListener("message",r),t=!0),n},stop(){!t||typeof window>"u"||(window.removeEventListener("message",r),t=!1)},destroy(){n.stop()},execute(o){return Oe(i,o)}};return n}function At(i){let e=!1;const t=i.shortcuts??!0,r=a=>{const l=i.targetWindow??(typeof window<"u"?window.parent:void 0);l&&l.postMessage(Ae(a),i.targetOrigin)},n=a=>{const l=ke(a);l&&(a.preventDefault(),r(l))},o={start(){return e||!t||typeof window>"u"||(window.addEventListener("keydown",n),e=!0),o},stop(){!e||typeof window>"u"||(window.removeEventListener("keydown",n),e=!1)},destroy(){o.stop()},sendCommand:r};return o}function Ae(i){return{source:"code-film",channel:"recorder-iframe",type:"command",command:i}}function Pe(i){if(!i||typeof i!="object")return!1;const e=i;return e.source==="code-film"&&e.channel==="recorder-iframe"&&e.type==="command"&&kt(e.command)}function ke(i){if(!(i.ctrlKey||i.metaKey))return null;const t=i.key.toLowerCase();return t==="j"?"toggle-recording":t==="l"?"toggle-mouse-pause":i.key==="ArrowUp"?"reset-full":i.key==="ArrowDown"?"focus-mouse":null}async function Oe(i,e){switch(e){case"toggle-recording":i.getState().recording?i.stopRecording():await i.startRecording();return;case"start-recording":await i.startRecording();return;case"stop-recording":i.stopRecording();return;case"focus-mouse":i.zoomToMouse();return;case"reset-full":i.setElementSelector(null),i.resetFullScreen();return;case"toggle-mouse-pause":{const t=i.getState();i.setMousePaused(!t.mousePaused);return}}}function Pt(i,e){return!e||e.length===0?!0:e.includes("*")||e.includes(i)}function kt(i){return i==="toggle-recording"||i==="start-recording"||i==="stop-recording"||i==="focus-mouse"||i==="reset-full"||i==="toggle-mouse-pause"}f.AppFilmGenerationError=W,f.COLS=b,f.DEFAULT_COMPLETION_TIMEOUT_MS=te,f.DEFAULT_RESOLUTIONS=H,f.DEFAULT_SELECTOR_TIMEOUT_MS=ie,f.FilmRecorder=ne,f.HUMAN_TYPING_PRESET=Ze,f.MIN_BOX_COLS=B,f.RegionRecorder=Ve,f.RegionRecorderUI=Ke,f.SDK_TYPING_DEFAULTS=re,f.cameraOverlay=Ie,f.createRecorderAgentRunner=Je,f.createRecorderIframeClient=At,f.createRecorderIframeHost=Mt,f.createRecorderIframeMessage=Ae,f.createWebAssistantAgent=se,f.generateAppFilmScript=et,f.getRecorderIframeShortcutCommand=ke,f.isRecorderIframeMessage=Pe,f.parseAppFilmSetup=F,f.prepareAppFilmScript=Qe,f.repairAppFilmScript=tt,f.serializeAppFilmSetup=ae,f.stripAppFilmSetup=I,f.useFilmRecorder=oe,f.validateAppFilmScript=j,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}));
@@ -0,0 +1,7 @@
1
+ import { default as React } from 'react';
2
+ import { FilmRecorderOptions } from '../core/types';
3
+ export interface RegionRecorderProps {
4
+ options?: FilmRecorderOptions;
5
+ }
6
+ export declare const RegionRecorder: React.FC<RegionRecorderProps>;
7
+ //# sourceMappingURL=RegionRecorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegionRecorder.d.ts","sourceRoot":"","sources":["../../src/react/RegionRecorder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGpD,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAmLxD,CAAC"}
@@ -0,0 +1,190 @@
1
+ import { jsxs as t, Fragment as g, jsx as c } from "react/jsx-runtime";
2
+ import { useFilmRecorder as f } from "./useFilmRecorder.js";
3
+ import { HEADER_PX as d, SHORTCUT_KEY as p, OUTLINE_PX as h } from "../core/FilmRecorder.js";
4
+ const v = ({ options: u = {} }) => {
5
+ const { recorder: r, state: e } = f(u);
6
+ if (!e || !r)
7
+ return null;
8
+ const o = r.computeGrid(e.viewport.w, e.viewport.h), a = {
9
+ x: e.displayRect.col * o.cellW,
10
+ y: d + e.displayRect.row * o.cellH,
11
+ width: e.displayRect.w * o.cellW,
12
+ height: e.displayRect.h * o.cellH
13
+ }, s = typeof navigator < "u" && /Mac/i.test(navigator.platform) ? "⌘" : "Ctrl", b = e.showGrid && !e.recording, i = r.options.resolutions;
14
+ return /* @__PURE__ */ t(g, { children: [
15
+ /* @__PURE__ */ c("div", { className: "cfr-settings-bar", children: /* @__PURE__ */ t("div", { className: "cfr-settings-bar-content", children: [
16
+ /* @__PURE__ */ t(
17
+ "button",
18
+ {
19
+ onClick: () => e.recording ? r.stopRecording() : r.startRecording(),
20
+ className: `cfr-btn ${e.recording ? "cfr-btn-destructive" : "cfr-btn-default"}`,
21
+ "aria-label": e.recording ? "Stop recording" : "Start recording",
22
+ children: [
23
+ e.recording ? /* @__PURE__ */ c(
24
+ "svg",
25
+ {
26
+ width: "12",
27
+ height: "12",
28
+ viewBox: "0 0 24 24",
29
+ fill: "currentColor",
30
+ style: { marginRight: 4 },
31
+ children: /* @__PURE__ */ c("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" })
32
+ }
33
+ ) : /* @__PURE__ */ c(
34
+ "svg",
35
+ {
36
+ width: "12",
37
+ height: "12",
38
+ viewBox: "0 0 24 24",
39
+ fill: "currentColor",
40
+ style: { marginRight: 4 },
41
+ children: /* @__PURE__ */ c("circle", { cx: "12", cy: "12", r: "10" })
42
+ }
43
+ ),
44
+ e.recording ? e.mousePaused ? "Paused" : "Stop" : "Record",
45
+ /* @__PURE__ */ t("kbd", { className: "cfr-kbd", children: [
46
+ s,
47
+ "+",
48
+ p.toUpperCase()
49
+ ] })
50
+ ]
51
+ }
52
+ ),
53
+ /* @__PURE__ */ c(
54
+ "button",
55
+ {
56
+ onClick: () => r.captureBitmap(),
57
+ className: "cfr-btn cfr-btn-secondary",
58
+ disabled: !e.recording,
59
+ children: "PNG frame"
60
+ }
61
+ ),
62
+ /* @__PURE__ */ t("button", { onClick: () => r.resetFullScreen(), className: "cfr-btn cfr-btn-ghost", children: [
63
+ "Full ",
64
+ /* @__PURE__ */ t("kbd", { className: "cfr-kbd", children: [
65
+ s,
66
+ "+↑"
67
+ ] })
68
+ ] }),
69
+ /* @__PURE__ */ t("button", { onClick: () => r.zoomToMouse(), className: "cfr-btn cfr-btn-ghost", children: [
70
+ "Focus mouse ",
71
+ /* @__PURE__ */ t("kbd", { className: "cfr-kbd", children: [
72
+ s,
73
+ "+↓"
74
+ ] })
75
+ ] }),
76
+ /* @__PURE__ */ t(
77
+ "button",
78
+ {
79
+ onClick: () => r.setMousePaused(!e.mousePaused),
80
+ className: `cfr-btn ${e.mousePaused ? "cfr-btn-secondary" : "cfr-btn-ghost"}`,
81
+ children: [
82
+ e.mousePaused ? "Resume mouse" : "Pause mouse",
83
+ " ",
84
+ /* @__PURE__ */ t("kbd", { className: "cfr-kbd", children: [
85
+ s,
86
+ "+L"
87
+ ] })
88
+ ]
89
+ }
90
+ ),
91
+ /* @__PURE__ */ c("div", { className: "cfr-divider" }),
92
+ /* @__PURE__ */ c("div", { className: "cfr-select-wrapper", children: /* @__PURE__ */ c(
93
+ "select",
94
+ {
95
+ value: e.resolution.label,
96
+ onChange: (l) => {
97
+ const n = i.find((m) => m.label === l.target.value);
98
+ n && r.setResolution(n);
99
+ },
100
+ disabled: e.recording,
101
+ className: "cfr-select",
102
+ children: i.map((l) => /* @__PURE__ */ c("option", { value: l.label, children: l.label }, l.label))
103
+ }
104
+ ) }),
105
+ /* @__PURE__ */ c("div", { className: "cfr-divider" }),
106
+ /* @__PURE__ */ t("label", { className: "cfr-checkbox-container", children: [
107
+ /* @__PURE__ */ c(
108
+ "input",
109
+ {
110
+ type: "checkbox",
111
+ checked: e.showGrid,
112
+ onChange: (l) => r.setShowGrid(l.target.checked),
113
+ disabled: e.recording,
114
+ className: "cfr-checkbox"
115
+ }
116
+ ),
117
+ /* @__PURE__ */ c("span", { className: "cfr-label", children: "Grid" })
118
+ ] }),
119
+ /* @__PURE__ */ t("label", { className: "cfr-checkbox-container", children: [
120
+ /* @__PURE__ */ c(
121
+ "input",
122
+ {
123
+ type: "checkbox",
124
+ checked: e.autoZoom,
125
+ onChange: (l) => r.setAutoZoom(l.target.checked),
126
+ className: "cfr-checkbox"
127
+ }
128
+ ),
129
+ /* @__PURE__ */ c("span", { className: "cfr-label", children: "Auto-zoom on hold" })
130
+ ] }),
131
+ /* @__PURE__ */ t("label", { className: "cfr-checkbox-container", children: [
132
+ /* @__PURE__ */ c(
133
+ "input",
134
+ {
135
+ type: "checkbox",
136
+ checked: e.pauseDuringScroll,
137
+ onChange: (l) => r.setPauseDuringScroll(l.target.checked),
138
+ className: "cfr-checkbox"
139
+ }
140
+ ),
141
+ /* @__PURE__ */ c("span", { className: "cfr-label", children: "Pause zoom while scrolling" })
142
+ ] }),
143
+ /* @__PURE__ */ t("label", { className: "cfr-checkbox-container", children: [
144
+ /* @__PURE__ */ c(
145
+ "input",
146
+ {
147
+ type: "checkbox",
148
+ checked: e.showOutline,
149
+ onChange: (l) => r.setShowOutline(l.target.checked),
150
+ className: "cfr-checkbox"
151
+ }
152
+ ),
153
+ /* @__PURE__ */ c("span", { className: "cfr-label", children: "Show outline border" })
154
+ ] })
155
+ ] }) }),
156
+ b && /* @__PURE__ */ c(
157
+ "div",
158
+ {
159
+ "aria-hidden": !0,
160
+ className: "cfr-grid-overlay",
161
+ style: {
162
+ top: d,
163
+ backgroundImage: `
164
+ linear-gradient(to right, var(--cfr-border) 1px, transparent 1px),
165
+ linear-gradient(to bottom, var(--cfr-border) 1px, transparent 1px)
166
+ `,
167
+ backgroundSize: `${o.cellW}px ${o.cellH}px`
168
+ }
169
+ }
170
+ ),
171
+ /* @__PURE__ */ c(
172
+ "div",
173
+ {
174
+ "aria-label": "Cinematic 16:9 capture region",
175
+ className: "cfr-crop-box",
176
+ style: {
177
+ left: a.x,
178
+ top: a.y,
179
+ width: a.width,
180
+ height: a.height,
181
+ outline: e.showOutline ? `${h}px solid var(--cfr-outline)` : "none",
182
+ outlineOffset: e.showOutline ? `${h}px` : "0"
183
+ }
184
+ }
185
+ )
186
+ ] });
187
+ };
188
+ export {
189
+ v as RegionRecorder
190
+ };