@buoy-gg/scenarios 7.0.76 → 7.0.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/web/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- "use client";var Ht=Object.defineProperty;var qr=Object.getOwnPropertyDescriptor;var Ur=Object.getOwnPropertyNames;var _r=Object.prototype.hasOwnProperty;var Jr=(e,t)=>{for(var r in t)Ht(e,r,{get:t[r],enumerable:true})},jt=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Ur(t))!_r.call(e,a)&&a!==r&&Ht(e,a,{get:()=>t[a],enumerable:!(o=qr(t,a))||o.enumerable});return e},Gr=(e,t,r)=>(jt(e,t,"default"),r&&jt(r,t,"default"));var Ft=(()=>{try{let e=globalThis.Capacitor;if(e&&typeof e.isNativePlatform=="function"&&e.isNativePlatform())return e.DEBUG===true}catch{}return process.env.NODE_ENV!=="production"})();typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);import{ScenariosIcon as Nt,SCENARIOS_ICON_COLOR as Wt}from"@buoy-gg/floating-tools-core/web";import{useCallback as ge,useMemo as Yr,useState as dt}from"react";var Mt={};Jr(Mt,{AccessibilityInfo:()=>eo,ActivityIndicator:()=>mt,Alert:()=>gt,Animated:()=>fe,AppRegistry:()=>ro,AppState:()=>oo,Appearance:()=>to,BackHandler:()=>no,Button:()=>Zo,CheckBox:()=>vo,Clipboard:()=>ao,DeviceEventEmitter:()=>Oo,Dimensions:()=>io,Easing:()=>so,FlatList:()=>wo,I18nManager:()=>lo,Image:()=>So,ImageBackground:()=>xo,InteractionManager:()=>uo,Keyboard:()=>co,KeyboardAvoidingView:()=>To,LayoutAnimation:()=>ho,Linking:()=>fo,LogBox:()=>Bo,Modal:()=>Qo,NativeEventEmitter:()=>po,NativeModules:()=>Zr,PanResponder:()=>ut,Picker:()=>Io,PixelRatio:()=>mo,Platform:()=>ht,Pressable:()=>Xo,ProgressBar:()=>Do,RefreshControl:()=>ko,SafeAreaView:()=>Co,ScrollView:()=>pe,SectionList:()=>$o,Share:()=>go,StatusBar:()=>Ro,StyleSheet:()=>V,Switch:()=>Gt,Text:()=>p,TextInput:()=>_e,Touchable:()=>Ao,TouchableHighlight:()=>Go,TouchableNativeFeedback:()=>Eo,TouchableOpacity:()=>F,TouchableWithoutFeedback:()=>Yo,UIManager:()=>yo,Vibration:()=>bo,View:()=>m,VirtualizedList:()=>Lo,YellowBox:()=>zo,findNodeHandle:()=>en,unstable_createElement:()=>Qr,useColorScheme:()=>Po,useLocaleContext:()=>Vo,useWindowDimensions:()=>Ho});Gr(Mt,Xr);import*as Xr from"react-native-web";import{unstable_createElement as Qr,NativeModules as Zr,AccessibilityInfo as eo,Appearance as to,AppRegistry as ro,AppState as oo,BackHandler as no,Clipboard as ao,Dimensions as io,Easing as so,I18nManager as lo,Keyboard as co,InteractionManager as uo,LayoutAnimation as ho,Linking as fo,NativeEventEmitter as po,PanResponder as ut,PixelRatio as mo,Platform as ht,Share as go,UIManager as yo,Vibration as bo,CheckBox as vo,FlatList as wo,Image as So,ImageBackground as xo,KeyboardAvoidingView as To,Picker as Io,ProgressBar as Do,RefreshControl as ko,SafeAreaView as Co,SectionList as $o,StatusBar as Ro,Touchable as Ao,TouchableNativeFeedback as Eo,VirtualizedList as Lo,YellowBox as zo,LogBox as Bo,DeviceEventEmitter as Oo,useColorScheme as Po,useLocaleContext as Vo,useWindowDimensions as Ho}from"react-native-web";import*as M from"react-native-web";import{createElement as ft,forwardRef as Kt,useCallback as jo,useRef as Fo}from"react";import{useEffect as No,useState as Wo}from"react";import{createPortal as Mo}from"react-dom";var Ko='-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';import{jsx as qo}from"react/jsx-runtime";var Ve=Symbol.for("@buoy-gg/portal-host"),qt=e=>{if(!(e instanceof Element))return false;if(e.closest("input, textarea, select"))return true;let t=e.closest("[contenteditable]")?.getAttribute("contenteditable")?.toLowerCase();return t===""||t==="true"||t==="plaintext-only"};function Ut(){let e=document;if(e[Ve])return e[Ve].host;let t=document.createElement("div");t.dataset.buoyPortalHost="",Object.assign(t.style,{position:"fixed",inset:"0",zIndex:"2147483647",pointerEvents:"none",fontFamily:Ko});let r=()=>{let u=document.fullscreenElement,d=u&&u.tagName!=="CANVAS"?u:document.body;t.parentElement!==d&&d.appendChild(t)},o=new Map,a=u=>{(!t.contains(u.target)||!qt(u.target))&&o.set(u.code||u.key,{key:u.key,code:u.code,location:u.location,keyCode:u.keyCode,which:u.which,altKey:u.altKey,ctrlKey:u.ctrlKey,metaKey:u.metaKey,shiftKey:u.shiftKey})},i=u=>{o.delete(u.code||u.key)},l=()=>o.clear(),c=()=>{let u=[...o.values()];o.clear();for(let d of u)document.dispatchEvent(new KeyboardEvent("keyup",{...d,bubbles:true}))},s=u=>{qt(u.target)&&u.stopPropagation()},h=u=>u.stopPropagation();return r(),document.addEventListener("fullscreenchange",r),document.addEventListener("keydown",a,true),document.addEventListener("keyup",i,true),window.addEventListener("blur",l),t.addEventListener("focusin",c),t.addEventListener("keydown",s),t.addEventListener("keyup",s),t.addEventListener("keypress",s),t.addEventListener("wheel",h,{passive:true}),e[Ve]={host:t,users:0,dispose:()=>{document.removeEventListener("fullscreenchange",r),document.removeEventListener("keydown",a,true),document.removeEventListener("keyup",i,true),window.removeEventListener("blur",l),t.remove(),delete e[Ve]}},t}function Uo({children:e}){let[t,r]=Wo(null);return No(()=>{let o=Ut(),a=document[Ve];return a.users++,r(o),()=>{--a.users===0&&a.dispose()}},[]),t?Mo(qo("div",{"data-buoy-root":"",style:{display:"contents",pointerEvents:"auto"},children:e}),t):null}var Ie=M,_o=["shadowColor","shadowOffset","shadowOpacity","shadowRadius","textShadowColor","textShadowOffset","textShadowRadius"],De=e=>typeof e=="number"?`${e}px`:e;function pt(e){if(Array.isArray(e)){let d=e.map(pt);return d.some((w,v)=>w!==e[v])?d:e}if(!e||typeof e!="object"||!_o.some(d=>e[d]!=null))return e;let{shadowColor:t,shadowOffset:r,shadowOpacity:o,shadowRadius:a,textShadowColor:i,textShadowOffset:l,textShadowRadius:c,...s}=e;if(t!=null||r!=null||o!=null||a!=null){let d=t??"black",w=o==null?d:`color-mix(in srgb, ${d} ${Math.min(o,1)*100}%, transparent)`,v=`${De(r?.width??0)} ${De(r?.height??0)} ${De(a??0)} ${w}`;s.boxShadow=typeof s.boxShadow=="string"?`${s.boxShadow}, ${v}`:s.boxShadow??v}let{width:h=0,height:u=0}=l??{};if(i&&(h||u||c)){let d=`${De(h)} ${De(u)} ${De(c??0)} ${i}`;s.textShadow=s.textShadow?`${s.textShadow}, ${d}`:d}return s}var Jo=Ie.StyleSheet.create({auto:{pointerEvents:"auto"},none:{pointerEvents:"none"},"box-none":{pointerEvents:"box-none"},"box-only":{pointerEvents:"box-only"}});function _t(e,t){if(typeof e=="function")return o=>_t(e(o),t);let r=pt(e);return t?[r,Jo[t]]:r}var V={...Ie.StyleSheet,create:e=>Ie.StyleSheet.create(Object.fromEntries(Object.entries(e).map(([t,r])=>[t,pt(r)])))};function G(e){let t=Kt((o,a)=>{let{accessibilityState:i,accessibilityValue:l,pointerEvents:c,...s}=o;for(let u of["busy","checked","disabled","expanded","selected"])i?.[u]!==void 0&&s[`aria-${u}`]===void 0&&(s[`aria-${u}`]=i[u]);for(let[u,d]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))l?.[u]!==void 0&&s[`aria-${d}`]===void 0&&(s[`aria-${d}`]=l[u]);let h=_t(s.style,c);return h!==s.style&&(s.style=h),ft(e,{...s,ref:a})}),r=e.State;return r&&Object.assign(t,{State:r}),t.displayName=e.displayName??e.name??"NativeWebView",t}var m=G(M.View),p=G(M.Text),fe={...Ie.Animated,View:Ie.Animated.createAnimatedComponent(m),Text:Ie.Animated.createAnimatedComponent(p)},_e=G(M.TextInput),F=G(M.TouchableOpacity),Go=G(M.TouchableHighlight),Yo=G(M.TouchableWithoutFeedback),Xo=G(M.Pressable),pe=G(M.ScrollView),Jt=Kt((e,t)=>{let r=Fo(null),o=jo(a=>{if(a){let i=a;for(;i.parentElement&&i.parentElement!==document.body;)i=i.parentElement;i.parentElement===document.body&&(r.current=i,Object.assign(i.style,{position:"relative",zIndex:"2147483647",pointerEvents:"auto"}),Ut().appendChild(i))}else r.current&&(document.body.appendChild(r.current),r.current=null);typeof t=="function"?t(a):t&&(t.current=a)},[t]);return ft(Uo,null,ft(M.Modal,{...e,ref:o}))});Jt.displayName="Modal";var Qo=G(Jt),Gt=G(M.Switch),mt=G(M.ActivityIndicator),Zo=G(M.Button),en=M.findNodeHandle,gt={alert(e,t,r,o){if(typeof document>"u")return;let a=document.createElement("dialog");a.dataset.buoyRoot="",a.setAttribute("aria-label",e),a.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let i=document.createElement("h2");if(i.textContent=e,i.style.cssText="font-size:18px;margin:0 0 12px",a.appendChild(i),t){let h=document.createElement("p");h.textContent=t,h.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",a.appendChild(h)}let l=document.createElement("div");l.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let c=r?.length?r:[{text:"OK"}],s=()=>{a.close?.(),a.remove()};for(let h of c){let u=document.createElement("button");u.type="button",u.textContent=h.text??"OK",u.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${h.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,u.onclick=()=>{s(),h.onPress?.()},l.appendChild(u)}a.addEventListener("cancel",h=>{h.preventDefault(),o?.cancelable!==false&&(s(),o?.onDismiss?.())}),a.appendChild(l),document.body.appendChild(a),a.showModal?a.showModal():a.setAttribute("open","")}};import{Box as tn,FileText as rn,Smartphone as on,ToolbarCopyButton as nn,Zap as an,useLimit as sn,useSafeAreaInsets as ln}from"@buoy-gg/shared-ui/web";import{useToolHeader as cn,useToolHost as dn}from"@buoy-gg/core/web";var Yt=/\{\{\s*(\w+)\s*\}\}/g,un=/^\{\{\s*(\w+)\s*\}\}$/;function He(e,t=new Set){if(typeof e=="string"){for(let r of e.matchAll(Yt))t.add(r[1]);return t}if(Array.isArray(e)){for(let r of e)He(r,t);return t}if(e&&typeof e=="object")for(let r of Object.values(e))He(r,t);return t}function ye(e,t){let r=e.match(un);return r&&r[1]in t?t[r[1]]:e.replace(Yt,(o,a)=>a in t?String(t[a]):o)}function me(e,t){if(typeof e=="string")return ye(e,t);if(Array.isArray(e))return e.map(r=>me(r,t));if(e&&typeof e=="object"){let r={};for(let[o,a]of Object.entries(e))r[o]=me(a,t);return r}return e}function je(e,t={}){let r={};for(let o of e)o.default!==void 0&&(r[o.key]=o.default);for(let[o,a]of Object.entries(t))a!==void 0&&(r[o]=a);return r}function hn(e,t){return e.filter(r=>!(r.key in t)).map(r=>r.key)}function Xt(e,t){if(e.type==="number"){let r=typeof t=="number"?t:Number(t);return Number.isFinite(r)?r:0}return e.type==="boolean"?typeof t=="boolean"?t:t==="true"||t===1:t}import{devToolsStorageKeys as Qt,persistentStorage as Fe,dispatchToolAction as ke,assertAccountAccess as yt,hasAccountAccess as Zt,getToolAdapters as fn,listToolActions as pn,listToolIds as er,waitForToolRegistry as mn}from"@buoy-gg/shared-ui/web";var be="scenario",C=(e,t="")=>typeof e=="string"?e:e==null?t:String(e);function tr(e){let t=e.rule;return t&&typeof t=="object"?t:e}function gn(e){let t=tr(e),r=Array.isArray(t.methods)?t.methods.join("/"):"any",o=C(t.urlPattern,"(no pattern)"),a=C(t.kind,"respond");if(a==="fail")return`${r} ${o} \u2192 fail (${C(t.failKind,"network")})`;if(a==="delay")return`${r} ${o} \u2192 delay ${t.delayMs??0}ms`;let i=typeof t.status=="number"?t.status:200,l=t.body!=null?", replaced body":"";return`${r} ${o} \u2192 respond ${i}${l}`}var rr=[{tool:"network",action:"upsertOverrideRule",title:"Override a request",durability:"durable",describe:gn,conflictKeys:e=>{let t=tr(e),r=C(t.urlPattern);return r?[`net:${r}`]:[]}},{tool:"network",action:"deleteOverrideRule",title:"Remove an override",durability:"one-shot",describe:e=>`Remove override rule ${C(e.id,"?")}`},{tool:"network",action:"setOverridesEnabled",title:"Toggle all overrides",durability:"session",describe:e=>`Turn overrides ${e.enabled===false?"off":"on"}`},{tool:"storage",action:"async.setItem",title:"Set storage value",durability:"durable",describe:e=>`Set storage ${C(e.key,"?")}`,conflictKeys:e=>e.key?[`storage:${C(e.key)}`]:[]},{tool:"storage",action:"async.removeItem",title:"Remove storage key",durability:"durable",describe:e=>`Remove storage ${C(e.key,"?")}`,conflictKeys:e=>e.key?[`storage:${C(e.key)}`]:[]},{tool:"storage",action:"async.multiSet",title:"Set several storage values",durability:"durable",describe:e=>{let t=Array.isArray(e.pairs)?e.pairs.length:0;return`Set ${t} storage key${t===1?"":"s"}`},conflictKeys:e=>Array.isArray(e.pairs)?e.pairs.map(t=>Array.isArray(t)?`storage:${C(t[0])}`:"").filter(Boolean):[]},{tool:"storage",action:"mmkv.set",title:"Set MMKV value",durability:"durable",describe:e=>`Set MMKV ${C(e.key,"?")}`,conflictKeys:e=>e.key?[`mmkv:${C(e.key)}`]:[]},{tool:"impersonate",action:"startImpersonation",title:"Impersonate a user",durability:"durable",describe:e=>{let t=e.user;return`Impersonate ${C(t?.name)||C(t?.email)||C(t?.id)||"a user"}`},conflictKeys:()=>["impersonation"]},{tool:"impersonate",action:"stopImpersonation",title:"Stop impersonating",durability:"one-shot",describe:()=>"Stop impersonating",conflictKeys:()=>["impersonation"]},{tool:"route-events",action:"navigate",title:"Go to a screen",durability:"one-shot",describe:e=>`${e.replace?"Replace with":"Go to"} ${C(e.path,"?")}`},{tool:"query",action:"setQueryData",title:"Poke the query cache",durability:"transient",describe:e=>`Poke ${C(e.queryKey,"?")} cache (until next refetch)`},{tool:"query",action:"invalidate",title:"Refetch queries",durability:"one-shot",describe:e=>`Refetch ${C(e.queryKey,"all queries")}`},{tool:"time-machine",action:"restore",title:"Restore a snapshot",durability:"durable",describe:e=>`Restore snapshot ${C(e.id,"?")}`},{tool:be,action:"wait",title:"Wait",durability:"one-shot",describe:e=>`Wait ${typeof e.ms=="number"?e.ms:0}ms`},{tool:"highlight-updates",action:"tapElement",title:"Tap something on screen",durability:"one-shot",describe:e=>{let t=C(e.testID)||C(e.query)||"an element";return typeof e.text=="string"?`Type \u201C${e.text}\u201D into ${t}`:e.value!==void 0?`Set ${t} to ${JSON.stringify(e.value)}`:e.longPress?`Press and hold \u201C${t}\u201D`:`Tap \u201C${t}\u201D`}},{tool:be,action:"waitFor",title:"Wait for a screen",durability:"one-shot",describe:e=>e.route?`Wait for ${C(e.route)}`:`Wait for \u201C${C(e.element,"?")}\u201D`},{tool:"zustand",action:"setState",title:"Set a store's state",durability:e=>e.persisted?"durable":"session",describe:e=>`Set ${C(e.storeName,"a store")}`,conflictKeys:e=>e.storeName?[`zustand:${C(e.storeName)}`]:[]}],yn=new Map(rr.map(e=>[`${e.tool}.${e.action}`,e]));function Ce(e,t){return yn.get(`${e}.${t}`)}function $e(e,t){if(e.label)return e.label;let r=Ce(e.tool,e.action),o=t??e.params??{};if(!r)return`${e.tool}.${e.action}`;try{return r.describe(o)}catch{return`${e.tool}.${e.action}`}}function Ne(e){let t=Ce(e.tool,e.action);if(!t)return"one-shot";if(typeof t.durability!="function")return t.durability;try{return t.durability(e.params??{})}catch{return"one-shot"}}function or(e){return!e.label&&!Ce(e.tool,e.action)}function bt(e,t){let r=Ce(e.tool,e.action);if(!r?.conflictKeys)return[];try{return r.conflictKeys(t??e.params??{})}catch{return[]}}function nr(e,t){if(e===t)return true;let r="net:";if(!e.startsWith(r)||!t.startsWith(r))return false;let o=e.slice(r.length),a=t.slice(r.length);return ar(o,a)||ar(a,o)}function ar(e,t){try{let r=e.replace(/[[\]{}()\\.^$+|\-,?]/g,"\\$&").split("*").join(".*"),o=t.split("*").join("x");return new RegExp(`^${r}$`).test(o)}catch{return false}}var bn={durable:"survives refresh & restart",session:"until the app restarts",transient:"until next refetch","one-shot":"one-shot"};var vt=1e4,ir=6e4,sr=6e3,vn=150,wn=new Set(["scenarios"]);function Sn(e){return e.action==="reloadApp"||e.action==="reload"}function lr(e,t,r){let o=[],a=[];e.source==="draft"&&o.push("This scenario is still a draft \u2014 review and accept it before running."),e.steps.length||o.push("This scenario has no steps.");let i=new Set(e.vars.map(d=>d.key)),l=new Set;for(let d of e.steps)He(d.params,l);He(e.name,l);for(let d of l)i.has(d)?d in t||o.push(`Variable "${d}" needs a value.`):o.push(`{{${d}}} is used but never declared as a variable.`);for(let d of i)l.has(d)||a.push(`Variable "${d}" is never used.`);let c=new Set(r.availableTools);e.steps.forEach((d,w)=>{let v=`Step ${w+1}`;if(wn.has(d.tool)){o.push(`${v}: a scenario cannot run another scenario.`);return}if(d.tool===be)return;if(!c.has(d.tool)){o.push(`${v}: "${d.tool}" is not installed in this app, so this step cannot run.`);return}let A=r.availableActions?.[d.tool];A&&!A.includes(d.action)&&o.push(`${v}: "${d.tool}" has no action "${d.action}".`),Sn(d)&&w!==e.steps.length-1&&o.push(`${v}: reloading the app is only allowed as the last step.`),Ce(d.tool,d.action)||a.push(`${v}: ${d.tool}.${d.action} is an advanced step \u2014 its effects are not described or automatically undone.`)});let s=new Set;for(let d of e.steps)for(let w of bt(d,me(d.params,t)))s.add(w);let h=null,u=r.activeScenario;if(u&&u.scenarioId!==e.id){let d=u.conflictKeys.filter(w=>[...s].some(v=>nr(w,v)));d.length&&(h={activeScenarioId:u.scenarioId,activeName:u.name,overlaps:d})}return r.extraErrors?.length&&o.push(...r.extraErrors),{ok:o.length===0,errors:o,warnings:a,conflict:h,conflictKeys:[...s]}}function cr(e,t,r,o){return new Promise((a,i)=>{let l=()=>{clearTimeout(c),i(new Error("Scenario cancelled"))},c=setTimeout(()=>{o?.removeEventListener("abort",l),i(new Error(`${r} timed out after ${t}ms`))},t);o?.aborted?l():o?.addEventListener("abort",l,{once:true}),e.then(s=>{clearTimeout(c),o?.removeEventListener("abort",l),a(s)},s=>{clearTimeout(c),o?.removeEventListener("abort",l),i(s)})})}function dr(e,t){return new Promise((r,o)=>{let a=()=>{clearTimeout(i),o(new Error("Scenario cancelled"))},i=setTimeout(()=>{t?.removeEventListener("abort",a),r()},e);t?.aborted?a():t?.addEventListener("abort",a,{once:true})})}async function xn(e,t,r,o){let a=typeof e.route=="string"?e.route:null,i=typeof e.element=="string"?e.element:null;if(!a&&!i)return;let l=Date.now()+r,c="nothing";for(;Date.now()<l;){if(o?.aborted)throw new Error("Scenario cancelled");if(a){let s=await t("route-events","getCurrentRoute").catch(()=>null);if(s?.path===a)return;typeof s?.path=="string"&&(c=s.path)}else if(i){let s=await t("highlight-updates","describeScreen").catch(()=>null),h=i.toLowerCase();if((s?.elements??[]).some(u=>[u.testID,u.text,u.label].some(d=>typeof d=="string"&&d.toLowerCase().includes(h))))return;c=`${s?.elements?.length??0} elements`}await dr(vn,o)}throw new Error(a?`Still on ${c} after ${r}ms \u2014 expected ${a}`:`\u201C${i}\u201D never appeared within ${r}ms`)}function Tn(e){if(e&&typeof e=="object"&&"ok"in e){let t=e;if(t.ok===false)return typeof t.error=="string"?t.error:"The step was rejected."}return null}function In(e,t,r,o){if(e.tool==="network"&&e.action==="upsertOverrideRule"){let i=r?.rule?.id;return typeof i=="string"?{kind:"override-rule",label:o,ruleId:i}:null}if(e.tool==="impersonate"&&e.action==="startImpersonation"){let i=t.user,l=typeof i?.id=="string"?i.id:void 0;return{kind:"impersonation",label:o,userId:l}}if(e.tool==="storage"){let[i,l=""]=e.action.split(".");if(/^(setItem|removeItem|multiSet|multiRemove|clear|set|remove)$/.test(l)){let c=typeof t.key=="string"?t.key:"";if(!c&&Array.isArray(t.pairs)){let s=t.pairs[0];c=Array.isArray(s)?String(s[0]??""):""}return!c&&Array.isArray(t.keys)&&(c=String(t.keys[0]??"")),!c&&l==="clear"&&(c="(all keys)"),{kind:"storage-write",label:o,backend:i,key:c}}}let a=Dn(e,t);return a!==null?{kind:"state-write",label:o,tool:e.tool,store:a}:e.tool===be?null:{kind:"transient",label:o,tool:e.tool,action:e.action}}function Dn(e,t){let r=o=>typeof t[o]=="string"?t[o]:"";if(e.tool==="zustand"&&e.action==="setState")return r("storeName")||"a store";if(e.tool==="jotai"&&e.action==="setAtom")return r("atom")||r("atomName")||"an atom";if(e.tool==="redux"&&e.action==="dispatch"){let o=t.action;return typeof o?.type=="string"?o.type:"the redux store"}return null}async function kn(e,t){let r=e.user,o=r?.id;if(!r||typeof o!="string"&&typeof o!="number")return e;let a=[r.email,r.name,r.displayName,o].filter(i=>typeof i=="string"||typeof i=="number");for(let i of a)try{let l=await t("impersonate","searchUsers",{query:String(i)}),c=Array.isArray(l)?l.find(s=>String(s?.id)===String(o)):void 0;if(c)return{...e,user:c}}catch{}return e}async function wt(e,t,r,o){let a=[],i=[],l=Date.now(),c=false;for(let s=0;s<e.steps.length;s++){let h=e.steps[s],u=me(h.params??{},t),d=$e(h,u);if(c){a.push({id:h.id,label:d,ok:false,skipped:true,ms:0});continue}o?.onStep?.(s,"start");let w=Date.now();try{if(o?.signal?.aborted)throw new Error("Scenario cancelled");if(Date.now()-l>ir)throw new Error("Scenario exceeded its overall time budget");let v;if(h.tool===be&&h.action==="wait"){let R=typeof u.ms=="number"?u.ms:0;await dr(Math.min(R,vt),o?.signal)}else if(h.tool===be&&h.action==="waitFor")await cr(xn(u,r,h.timeoutMs??sr,o?.signal),h.timeoutMs??sr,d,o?.signal);else{let R=h.tool==="impersonate"&&h.action==="startImpersonation"?await kn(u,r):u;v=await cr(Promise.resolve(r(h.tool,h.action,R)),h.timeoutMs??vt,d,o?.signal);let z=Tn(v);if(z)throw new Error(z)}let A=Date.now()-w;a.push({id:h.id,label:d,ok:true,ms:A});let y=In(h,u,v,d);y&&i.push(y),o?.onStep?.(s,"ok")}catch(v){let A=Date.now()-w,y=v instanceof Error?v.message:String(v);a.push({id:h.id,label:d,ok:false,error:y,ms:A}),o?.onStep?.(s,"error",y),c=true}}return{ok:!c,scenarioId:e.id,name:String(ye(e.name,t)),steps:a,effects:i}}async function We(e,t){let r=0,o=false,a=0,i=[],l=[],c=[];for(let s of e)try{s.kind==="override-rule"?(await t("network","deleteOverrideRule",{id:s.ruleId}),r++):s.kind==="impersonation"?(await t("impersonate","stopImpersonation",{}),o=true):s.kind==="storage-write"?s.key&&i.push(s.key):s.kind==="state-write"?s.store&&l.push(s.store):a++}catch(h){c.push(h instanceof Error?h.message:String(h))}return{removedRules:r,stoppedImpersonation:o,clearedTransients:a,unrestoredStorageKeys:i,unrestoredState:l,errors:c}}var ur="Ungrouped",Cn=32;function le(e){return typeof e!="string"?void 0:e.replace(/\s+/g," ").trim().slice(0,32)||void 0}function St(e,t){let r=le(e);return r?t.find(o=>o.toLowerCase()===r.toLowerCase())??r:void 0}function hr(e){let t=new Map;for(let r of e){let o=le(r.folder);if(!o)continue;let a=o.toLowerCase();t.has(a)||t.set(a,o)}return[...t.values()].sort((r,o)=>r.localeCompare(o,void 0,{sensitivity:"base"}))}function xt(e,t){let r=le(e.folder);return t===void 0?!r:!!r&&r.toLowerCase()===t.toLowerCase()}function Tt(e,t){return e.reduce((r,o)=>xt(o,t)?r+1:r,0)}function Je(e=[],t){return e.map((r,o)=>({...r,id:r.id??`${t}${o+1}`}))}function $n(e){let t=Date.now();return{id:e.id,name:e.name,description:e.description,version:e.version??1,source:"code",author:e.author,vars:e.vars??[],steps:Je(e.steps,"s"),undoSteps:e.undoSteps?Je(e.undoSteps,"u"):void 0,tags:e.tags,folder:le(e.folder),expectedOutcome:e.expectedOutcome,authoredAgainst:e.authoredAgainst,createdAt:t,updatedAt:t,usage:{runs:0}}}var fr=Qt.scenarios.library(),It=Qt.scenarios.active(),Dt=100,Z=null;function Rn(e){Z=e}function pr(){return!(typeof Ft<"u"&&!Ft)}var An=class{constructor(){this.state={code:[],device:[],drafts:[],active:null,runState:null,lastDeactivateReport:null,hasLoaded:false,lastVarValues:{}};this.listeners=new Set;this.loadPromise=null;this.expiryTimer=null;this.runController=null;this.getState=()=>this.state;this.subscribe=e=>(this.listeners.add(e),this.ensureLoaded(),()=>{this.listeners.delete(e)})}setState(e){this.state={...this.state,...e},this.listeners.forEach(t=>{try{t()}catch{}})}allScenarios(){let e=new Set(this.state.code.map(t=>t.id));return[...this.state.code,...this.state.device.filter(t=>!e.has(t.id))]}find(e){return this.allScenarios().find(t=>t.id===e)??this.state.drafts.find(t=>t.id===e)}folders(){return hr([...this.state.code,...this.state.device,...this.state.drafts])}registerCodeScenarios(e){let t=new Map(this.state.code.map(r=>[r.id,r]));for(let r of e)t.set(r.id,{...r,source:"code"});this.setState({code:[...t.values()]})}ensureLoaded(){return Z?Promise.resolve():(this.loadPromise||(this.loadPromise=this.load()),this.loadPromise)}async load(){let e=[],t=[],r={};try{let a=await Fe.getItem(fr);if(a){let i=JSON.parse(a);e=Array.isArray(i.device)?i.device:[],t=Array.isArray(i.drafts)?i.drafts:[],r=i.lastVarValues&&typeof i.lastVarValues=="object"?i.lastVarValues:{}}}catch{}let o=null;try{let a=await Fe.getItem(It);a&&(o=JSON.parse(a))}catch{o=null}this.setState({device:e,drafts:t,lastVarValues:r,active:o,hasLoaded:true}),o&&await this.reconcileActive()}async persistLibrary(){if(Z)return;let e={version:1,device:this.state.device,drafts:this.state.drafts,lastVarValues:this.state.lastVarValues};try{await Fe.setItem(fr,JSON.stringify(e))}catch{}}async persistActive(){if(!Z)try{this.state.active?await Fe.setItem(It,JSON.stringify(this.state.active)):await Fe.removeItem(It)}catch{}}async reconcileActive(){let e=this.state.active;if(!(!e||!e.effects.filter(t=>t.kind==="override-rule").length)&&er().includes("network"))try{let t=await ke("network","listOverrideRules",{}),r=new Set((t?.rules??[]).map(a=>a.id)),o=e.effects.filter(a=>a.kind!=="override-rule"||r.has(a.ruleId));if(o.length===e.effects.length)return;o.length?this.setState({active:{...e,effects:o}}):this.setState({active:null}),await this.persistActive()}catch{}}checkBeforeRun(e,t,r=[]){let o=this.state.active,a=[...r];pr()||a.push("Scenarios cannot run in a production build.");let i=je(e.vars,t);return lr(e,i,{availableTools:er(),availableActions:pn(),activeScenario:o?{scenarioId:o.scenarioId,name:o.name,conflictKeys:this.activeConflictKeys()}:null,extraErrors:a})}holdObservers(e){let t=[],r=fn();for(let o of e){let a=r[o]?.subscribe;if(a)try{t.push(a(()=>{}))}catch{}}return t}activeConflictKeys(){let e=this.state.active;if(!e)return[];let t=this.find(e.scenarioId);if(!t)return[];let r=new Set;for(let o of t.steps)for(let a of bt(o,me(o.params,e.varValues)))r.add(a);return[...r]}async run(e,t={},r={}){if(yt(),Z)return await Z("run",{id:e,params:t});await this.ensureLoaded(),yt();let o=this.find(e);if(!o)throw new Error(`No scenario "${e}"`);if(o.source==="draft")throw new Error("Drafts must be accepted before they can run.");if(!pr())throw new Error("Scenarios cannot run in a production build.");if(!await mn())throw new Error("Buoy tools are still starting up \u2014 try again in a moment.");let a=je(o.vars,t);if(this.state.active&&this.state.active.scenarioId!==e)await this.deactivate();else if(this.state.active){let s=this.state.active;await We(s.effects.filter(h=>h.kind==="override-rule"),ke),this.setState({active:{...s,effects:s.effects.filter(h=>h.kind!=="override-rule")}})}yt(),this.setState({runState:{scenarioId:e,name:ye(o.name,a),steps:[],current:0,done:false}});let i=this.holdObservers(["route-events"]),l;this.runController?.abort();let c=new AbortController;this.runController=c;try{l=await wt(o,a,ke,{signal:c.signal,onStep:s=>{let h=this.state.runState;h&&this.setState({runState:{...h,current:s}})}})}finally{this.runController===c&&(this.runController=null),i.forEach(s=>{try{s()}catch{}})}if(this.setState({runState:{scenarioId:e,name:ye(o.name,a),steps:l.steps,current:-1,done:true,report:l}}),l.ok&&Zt()){let s={scenarioId:e,name:ye(o.name,a),version:o.version,source:o.source,runAt:Date.now(),varValues:a,effects:l.effects,expiresAt:r.expiresInMs?Date.now()+r.expiresInMs:void 0};this.setState({active:s,lastDeactivateReport:null,lastVarValues:{...this.state.lastVarValues,[e]:a}}),this.bumpUsage(e),this.armExpiry(),await this.persistActive(),await this.persistLibrary()}return l}async undoPartialRun(){let e=this.state.runState?.report;if(!e)return{removedRules:0,stoppedImpersonation:false,clearedTransients:0,unrestoredStorageKeys:[],unrestoredState:[],undoStepsRan:0,errors:[]};let t={...await We(e.effects,ke),undoStepsRan:0};return this.setState({runState:null,lastDeactivateReport:t}),t}clearRunState(){this.setState({runState:null})}bumpUsage(e){let t=r=>r.map(o=>o.id===e?{...o,usage:{runs:(o.usage?.runs??0)+1,lastRunAt:Date.now()}}:o);this.setState({code:t(this.state.code),device:t(this.state.device)})}async deactivate(){if(Z)return await Z("deactivate",{});let e=this.state.active;if(!e)return{removedRules:0,stoppedImpersonation:false,clearedTransients:0,unrestoredStorageKeys:[],unrestoredState:[],undoStepsRan:0,errors:[]};let t=await We(e.effects,ke),r=[...t.errors],o=0,a=this.find(e.scenarioId),i=a?.undoSteps??[];if(i.length){let c=await wt({...a,steps:i},e.varValues,ke);o=c.steps.filter(s=>s.ok).length;for(let s of c.steps)!s.ok&&s.error&&r.push(s.error)}let l={removedRules:t.removedRules,stoppedImpersonation:t.stoppedImpersonation,clearedTransients:t.clearedTransients,unrestoredStorageKeys:o?[]:t.unrestoredStorageKeys,unrestoredState:o?[]:t.unrestoredState,undoStepsRan:o,errors:r};return this.clearExpiry(),this.setState({active:null,lastDeactivateReport:l}),await this.persistActive(),l}async disposeAccountSession(e){if(this.runController?.abort(),this.runController=null,Zt())return;this.clearExpiry();let t=this.state.active;if(!t||Z)return;let r=await We(t.effects.filter(o=>o.kind==="override-rule"),e);if(this.setState({active:null}),await this.persistActive(),r.errors.length)throw new Error(r.errors.join("; "))}dismissDeactivateReport(){this.setState({lastDeactivateReport:null})}armExpiry(){this.clearExpiry();let e=this.state.active?.expiresAt;if(!e)return;let t=Math.max(0,e-Date.now());this.expiryTimer=setTimeout(()=>{this.deactivate()},t)}clearExpiry(){this.expiryTimer&&(clearTimeout(this.expiryTimer),this.expiryTimer=null)}isLongRunning(e=480*60*1e3){let t=this.state.active;return!!t&&Date.now()-t.runAt>e}async saveScenario(e,t={}){await this.ensureLoaded();let r=Date.now(),o=t.asDraft??false,a=o?this.state.drafts:this.state.device,i=a.findIndex(s=>s.id===e.id),l={...e,steps:Je(e.steps,"s"),undoSteps:e.undoSteps?Je(e.undoSteps,"u"):void 0,folder:St(e.folder,this.folders()),source:o?"draft":"device",version:i>=0?(a[i].version??1)+1:e.version||1,createdAt:i>=0?a[i].createdAt:r,updatedAt:r,usage:i>=0?a[i].usage:{runs:0}};if(!o&&i<0&&this.state.device.length>=Dt)throw new Error(`This device already holds ${Dt} scenarios \u2014 delete one first.`);let c=[...a];return i>=0?c[i]=l:c.unshift(l),this.setState(o?{drafts:c}:{device:c}),await this.persistLibrary(),l}async acceptDraft(e){await this.ensureLoaded();let t=this.state.drafts.find(o=>o.id===e);if(!t)throw new Error(`No draft "${e}"`);let r={...t,source:"device",unsavedToRepo:true,updatedAt:Date.now()};return this.setState({drafts:this.state.drafts.filter(o=>o.id!==e),device:[r,...this.state.device]}),await this.persistLibrary(),r}async discardDraft(e){await this.ensureLoaded(),this.setState({drafts:this.state.drafts.filter(t=>t.id!==e)}),await this.persistLibrary()}async setFolder(e,t){if(await this.ensureLoaded(),Z)return(await Z("setFolder",{id:e,folder:t})).scenario;if(this.state.code.some(c=>c.id===e))throw new Error("Scenarios shipped with the app are filed in code \u2014 change `folder` in defineScenario().");let r=St(t,this.folders()),o,a=c=>c.map(s=>s.id!==e?s:(o={...s,folder:r,updatedAt:Date.now()},o)),i=a(this.state.device),l=o?this.state.drafts:a(this.state.drafts);if(!o)throw new Error(`No scenario "${e}"`);return this.setState({device:i,drafts:l}),await this.persistLibrary(),o}async deleteScenario(e){await this.ensureLoaded(),this.state.active?.scenarioId===e&&await this.deactivate(),this.setState({device:this.state.device.filter(t=>t.id!==e)}),await this.persistLibrary()}rememberVarValues(e,t){this.setState({lastVarValues:{...this.state.lastVarValues,[e]:t}}),this.persistLibrary()}lastValuesFor(e){return this.state.lastVarValues[e]??{}}replaceFromSnapshot(e){this.setState({code:e.code??[],device:e.device??[],drafts:e.drafts??[],active:e.active??null,runState:e.runState??null,hasLoaded:true})}},g=new An;function En(e){g.replaceFromSnapshot(e)}import{useSyncExternalStore as Ge}from"react";import{dispatchToolAction as Ln,getToolAdapters as mr}from"@buoy-gg/shared-ui/web";var ve="highlight-updates",Re="route-events",Ae="zustand",zn=new Set(["item","row","card","btn","button","cta","link","cell","tile","popular","open","tap","press","go"]);function gr(e){let t=e.split(/[-_.]/).filter(Boolean),r=t.length>=3?t.slice(1):t,o=r.filter(i=>!zn.has(i.toLowerCase())),a=(o.length?o:r).join(" ").trim();return a?a.charAt(0).toUpperCase()+a.slice(1):e}var yr=28;function br(e){let t=e.testID?gr(e.testID):void 0,r=(e.control==="text"?[e.label,t,e.text]:[e.label,e.text,t]).filter(a=>typeof a=="string"&&a.trim().length>0),o=r.find(a=>a.trim().length<=yr);return o?o.trim():r.length?Ye(r[0].trim(),yr):e.name}function vr(e){if(e.testID)return{testID:e.testID};let t=e.label??e.text;return t&&t.trim()?{query:t.trim()}:null}function Ye(e,t=32){let r=typeof e=="string"?e:JSON.stringify(e);return typeof r!="string"?"":r.length>t?`${r.slice(0,t)}\u2026`:r}function kt(e){let{touch:t}=e,r=br(t.target);switch(t.kind){case"text":return`Type \u201C${Ye(t.value)}\u201D into ${r}`;case"toggle":return`${t.value===false?"Turn off":"Turn on"} ${r}`;case"slider":return`Set ${r} to ${Ye(t.value)}`;case"longPress":return`Press and hold \u201C${r}\u201D`;default:return`Tap \u201C${r}\u201D`}}function Bn(e){if(e==null||typeof e!="object")return;let t=[];for(let[r,o]of Object.entries(e))if(typeof o!="function"){if(Array.isArray(o))t.push(`${o.length} ${r}`);else if(o==null||typeof o!="object"){if(o===null||o===""||o===false||o===0)continue;t.push(`${r} ${Ye(o,16)}`)}if(t.length>=3)break}return t.length?t.join(", "):void 0}function On(e){let t=[];e.effects.route&&e.effects.route!==e.routeBefore&&t.push(`went to ${e.effects.route}`);for(let r of e.effects.stores??[]){let o=Bn(r.state);t.push(o?`${r.name} \u2192 ${o}`:`changed ${r.name}`)}return t.length?t.join(" \xB7 "):void 0}var Pn=0,Ee=e=>`${e}-${Date.now().toString(36)}-${(Pn++).toString(36)}`;function Vn(e){let t=vr(e.touch.target);if(!t)return[];let r={...t},{touch:o}=e;o.kind==="longPress"&&(r.longPress=true),o.kind==="text"&&(r.text=o.value),(o.kind==="toggle"||o.kind==="slider")&&(r.value=o.value);let a=[{id:Ee("ui"),tool:ve,action:"tapElement",params:r,label:kt(e)}],i=e.effects.route;return i&&i!==e.routeBefore&&a.push({id:Ee("wait"),tool:"scenario",action:"waitFor",params:{route:i},label:`Wait for ${i}`}),a}function Hn(e){let t=[];for(let o of e.effects.stores??[])t.push({id:Ee("state"),tool:Ae,action:"setState",params:{storeName:o.name,state:o.state,replace:true,persisted:o.persisted??false},label:`Set ${o.name}`});let r=e.effects.route;return r&&r!==e.routeBefore&&t.push({id:Ee("nav"),tool:Re,action:"navigate",params:{path:r},label:`Go to ${r}`}),t}function jn(e){let t={id:Ee("start"),tool:Re,action:"navigate",params:{path:e,reset:true},label:`Go to ${e}`};return{id:Ee("pre"),precondition:true,title:`Start from ${e}`,detail:"so it can run from anywhere",lane:"state",lanes:["state"],enabled:true,noise:false,ui:[],state:[t]}}function wr(e,t){let r=e.map(o=>{let a=Vn(o),i=Hn(o),l=[];return a.length&&l.push("ui"),i.length&&l.push("state"),{id:o.id,title:kt(o),detail:On(o),lane:l.includes("ui")?"ui":"state",lanes:l,enabled:l.length>0,noise:l.length===0,ui:a,state:i}});return t&&r.length?[jn(t),...r]:r}function Fn(e){if(e.tool===Ae&&e.action==="setState"){let t=e.params?.storeName;return t?`${Ae}:${t}`:null}return e.tool===Re&&e.action==="navigate"?"route":null}function Ct(e){let t=[],r=new Map,o=0,a=()=>{for(let i of r.values())t.push(i);r=new Map,o=0};for(let i of e){if(!i.enabled||i.noise)continue;let l=i.lane==="state"?i.state:i.ui;if(l.length){if(i.lane!=="state"){a(),t.push(...l);continue}for(let c of l){let s=Fn(c);if(s==null){r.set(`\0${o++}`,c);continue}r.delete(s),r.set(s,c)}}}return a(),t}function Nn(e,t){return e.map((r,o)=>r.precondition?r:o>t?{...r,lane:"ui",enabled:!r.noise&&r.lanes.length>0}:r.lanes.includes("state")?{...r,lane:"state",enabled:true}:{...r,enabled:false})}function Wn(e){return e.map(t=>t.precondition?t:{...t,lane:t.lanes.includes("ui")?"ui":"state",enabled:t.lanes.length>0&&!t.noise})}function Mn(e){let t=-1;for(let r=0;r<e.length;r++){let o=e[r];if(!o.precondition){if(o.enabled&&o.lane==="state"){t=r;continue}if(o.enabled)break}}return t}var Kn=/^(continue|next|ok|done|submit|save|confirm|apply|back|close|cancel|open|add\b|view\b|go to\b|place order|checkout|check out)/i;function qn(e){let t=e.filter(l=>l.enabled&&!l.noise),r;for(let l of t)for(let c of l.state??[]){let s=c.params?.path;c.tool===Re&&c.action==="navigate"&&typeof s=="string"&&(r=s)}let o=r?.split("?")[0].split("/").filter(Boolean).pop(),a=r===void 0?"":o?Un(o.replace(/[-_]/g," ")):"Home",i="";for(let l of[...t].reverse()){if(l.precondition)continue;let c=l.title.match(/“([^”]+)”/)?.[1]?.split(",")[0].trim();if(c&&!Kn.test(c)){i=c;break}}return a&&i?`${a} \xB7 ${i}`:a||i?a||i:t.length?`${t.length} recorded step${t.length===1?"":"s"}`:""}function Un(e){return e.replace(/\b\w/g,t=>t.toUpperCase())}var _n=250,Jn=1200,Sr={status:"idle",reason:null,startedAt:null,startRoute:void 0,actions:[],draft:null},Gn=0,Yn=()=>`act-${Date.now().toString(36)}-${(Gn++).toString(36)}`,Xn=class{constructor(){this.state=Sr;this.listeners=new Set;this.timer=null;this.sinceSeq=0;this.storeChanges=new Map;this.holds=[];this.ticking=false;this.getState=()=>this.state;this.subscribe=e=>(this.listeners.add(e),()=>{this.listeners.delete(e)})}setState(e){this.state={...this.state,...e},this.listeners.forEach(t=>{try{t()}catch{}})}canRecord(){return typeof mr()[ve]?.actions?.startTouchCapture=="function"}async start(){if(this.state.status==="recording")return;if(!this.canRecord()){this.setState({status:"unavailable",reason:"Recording needs the Highlight Updates tool installed \u2014 it owns the screen reader this uses to name what you tap."});return}this.holds=[];for(let t of[Re,Ae]){let r=mr()[t]?.subscribe;if(r)try{this.holds.push(r(()=>{}))}catch{}}await this.call(ve,"clearTouchCapture");let e=await this.call(ve,"startTouchCapture");if(e?.status!=="capturing"){this.releaseHolds(),this.setState({status:"unavailable",reason:e?.reason??"This build of React Native doesn't expose the touch stream Buoy records from."});return}this.sinceSeq=0,this.route=await this.readRoute(),this.storeChanges=await this.readStoreChanges(),this.setState({status:"recording",reason:null,startedAt:Date.now(),startRoute:this.route,actions:[],draft:null}),this.timer=setInterval(()=>void this.tick(),_n)}async stop(){this.state.status==="recording"&&(this.clearTimer(),await new Promise(e=>setTimeout(e,Jn)),await this.tick(),await this.call(ve,"stopTouchCapture"),this.releaseHolds(),this.setState({status:"review",draft:wr(this.state.actions,this.state.startRoute)}))}async cancel(){this.clearTimer(),this.state.status==="recording"&&await this.call(ve,"stopTouchCapture"),this.releaseHolds(),this.setState({...Sr})}setDraft(e){this.state.status==="review"&&this.setState({draft:e})}clearTimer(){this.timer&&(clearInterval(this.timer),this.timer=null)}releaseHolds(){this.holds.forEach(e=>{try{e()}catch{}}),this.holds=[]}async tick(){if(!this.ticking){this.ticking=true;try{let e=await this.call(ve,"readTouchCapture",{sinceSeq:this.sinceSeq}),t=[...this.state.actions],r=false;for(let c of e?.records??[])t.push({id:Yn(),touch:c,routeBefore:this.route,effects:{}}),r=true;e?.seq&&(this.sinceSeq=e.seq);let o=t[t.length-1],a=await this.readRoute();a!==void 0&&a!==this.route&&(this.route=a,o&&(o.effects={...o.effects,route:a},r=true));let i=await this.readStoreChanges(),l=[];for(let[c,s]of i){let h=this.storeChanges.get(c);h!==void 0&&h.changes!==s.changes&&l.push({name:c,persisted:s.persisted})}if(this.storeChanges=i,o&&l.length){let c=[...o.effects.stores??[]];for(let{name:s,persisted:h}of l){let u=await this.readStoreState(s);if(u===void 0)continue;let d=c.findIndex(w=>w.name===s);d>=0?c[d]={name:s,state:u,persisted:h}:c.push({name:s,state:u,persisted:h})}c.length&&(o.effects={...o.effects,stores:c},r=true)}r&&this.setState({actions:t})}finally{this.ticking=false}}}async call(e,t,r){try{return await Ln(e,t,r)}catch{return null}}async readRoute(){let e=(await this.call(Re,"getCurrentRoute"))?.path;return typeof e=="string"?e:void 0}async readStoreChanges(){let e=await this.call(Ae,"listStores",{}),t=new Map;for(let r of e?.stores??[])r?.name&&t.set(r.name,{changes:r.changes??0,persisted:r.isPersisted===true});return t}async readStoreState(e){let t=await this.call(Ae,"getStoreState",{storeName:e});if(t?.found)return t.currentState}},ee=new Xn;function xr(){return Ge(g.subscribe,g.getState)}function $t(){return Ge(g.subscribe,()=>g.getState().active)}function Tr(){return Ge(g.subscribe,()=>g.getState().runState)}function Ir(){return Ge(ee.subscribe,ee.getState)}import{useCallback as Dr,useMemo as Le,useRef as Qn,useState as Zn}from"react";import{Bookmark as ea,ToolButton as kr,Zap as ta,useSafeAreaInsets as ra,ToolEmptyState as oa}from"@buoy-gg/shared-ui/web";import{useToolHeader as na}from"@buoy-gg/core/web";import{night as P}from"@buoy-gg/shared-ui/web";import{monoFont as aa}from"@buoy-gg/shared-ui/web";var n={color:{bg:P.color.bg,surface:"rgba(12, 12, 12, 0.9)",row:P.color.surfaceElevated,chip:P.color.buttonSurface,border:P.color.border,separator:P.color.separator,fill:P.color.fill,text:P.color.text,textSecondary:P.color.textSecondary,textTertiary:P.color.textTertiary,accent:P.color.accent,accentSoft:P.color.accentSoft,accentBorder:P.color.accentBorder,accentBorderStrong:P.color.accentBorderStrong,onAccent:P.color.onAccent,sim:P.color.warning,simSoft:P.color.warningSoft,simBorder:"rgba(255, 131, 41, 0.35)",onSim:"#000000",danger:P.color.danger,dangerSoft:P.color.dangerSoft,dangerBorder:"rgba(255, 59, 48, 0.30)",info:P.color.info,infoSoft:P.color.infoSoft,infoBorder:"rgba(30, 109, 255, 0.25)"},radius:{card:8,row:6,badge:4,pill:6},gutter:12,textInset:12,rowMinHeight:44,font:{row:13,control:12,label:11,footnote:11,mono:11,micro:9}},H=aa;import{SectionHeader as Xe,Pill as Cr}from"@buoy-gg/shared-ui/web";import{jsx as ne,jsxs as ia}from"react/jsx-runtime";function K({children:e,icon:t,count:r,color:o=n.color.accent,testID:a,countTestID:i}){return ne(m,{testID:a,collapsable:false,children:ia(Xe,{children:[t?ne(Xe.Icon,{icon:t,color:o,size:14}):null,ne(Xe.Title,{children:e}),r!==void 0?ne(Xe.Badge,{count:r,color:o,testID:i}):null]})})}function ae({children:e,centered:t,tone:r="secondary",testID:o}){return ne(p,{style:[_.footnote,t?_.footnoteCentered:null,r==="warning"?_.footnoteWarning:null,r==="danger"?_.footnoteDanger:null],testID:o,children:e})}function q({children:e,tone:t="neutral",style:r,testID:o}){return ne(m,{style:[_.panel,t==="sim"?_.panelSim:null,t==="danger"?_.panelDanger:null,t==="info"?_.panelInfo:null,r],testID:o,children:e})}function U(){return ne(m,{style:_.panelSeparator})}function ce({children:e,tone:t,testID:r}){return ne(m,{style:[_.notice,t==="sim"?_.noticeSim:null,t==="danger"?_.noticeDanger:null,t==="info"?_.noticeInfo:null],testID:r,children:e})}function sa({label:e,color:t,testID:r}){return ne(Cr,{label:e,color:t,variant:"tinted",style:{height:26,paddingHorizontal:10,borderRadius:n.radius.pill,justifyContent:"center"},testID:r})}function Me({label:e,tone:t,testID:r}){let o=t==="durable"?n.color.accent:t==="transient"?n.color.sim:n.color.textTertiary;return ne(Cr,{label:e,color:o,variant:"tinted",mono:true,uppercase:false,testID:r})}var _=V.create({footnote:{color:n.color.textTertiary,fontSize:n.font.footnote,lineHeight:n.font.footnote*1.45,paddingHorizontal:n.gutter+4,paddingTop:8},footnoteCentered:{textAlign:"center"},footnoteWarning:{color:n.color.sim},footnoteDanger:{color:n.color.danger},panel:{marginHorizontal:n.gutter,marginVertical:4,backgroundColor:n.color.surface,borderRadius:n.radius.card,borderWidth:1,borderColor:n.color.border,overflow:"hidden"},panelSim:{borderColor:n.color.simBorder},panelDanger:{borderColor:n.color.dangerBorder},panelInfo:{borderColor:n.color.infoBorder},panelSeparator:{height:V.hairlineWidth,marginLeft:n.textInset,backgroundColor:n.color.separator},notice:{marginHorizontal:n.gutter,marginTop:8,borderRadius:n.radius.card,borderWidth:1,paddingHorizontal:n.textInset,paddingVertical:10,gap:3},noticeSim:{backgroundColor:n.color.simSoft,borderColor:n.color.simBorder},noticeDanger:{backgroundColor:n.color.dangerSoft,borderColor:n.color.dangerBorder},noticeInfo:{backgroundColor:n.color.infoSoft,borderColor:n.color.infoBorder}});import{jsx as $,jsxs as te}from"react/jsx-runtime";function $r({draft:e,onChange:t,onSave:r,onDiscard:o,busy:a}){let i=ra({minBottom:16}),[l,c]=Zn(()=>qn(e)),s=Qn(o);s.current=o;let h=Dr(()=>s.current(),[]);na({title:"Review recording",onBack:h,searchable:false},[]);let u=Le(()=>e.filter(f=>f.enabled&&!f.noise),[e]),d=Le(()=>e.filter(f=>f.noise),[e]),w=Le(()=>Mn(e),[e]),v=Le(()=>{let f=0;return e.map(I=>I.precondition?0:++f)},[e]),A=Dr((f,I)=>{t(e.map(k=>k.id===f?{...k,...I}:k))},[e,t]),y=Le(()=>Ct(e),[e]),R=Le(()=>y.filter(f=>f.tool===be&&f.action==="waitFor").length,[y]),z=u.length-(y.length-R);return te(pe,{style:D.fill,contentContainerStyle:[D.content,{paddingBottom:i.bottom}],keyboardShouldPersistTaps:"handled",testID:"macro-review-scroll",children:[$(K,{icon:ea,children:"Name"}),$(q,{children:$(_e,{style:D.nameInput,value:l,onChangeText:c,placeholder:"Bag with a Charizard in it",placeholderTextColor:n.color.textTertiary,maxLength:80,returnKeyType:"done",testID:"macro-name-input"})}),$(K,{icon:ta,count:u.length,children:"Steps"}),w>=0?$(m,{style:D.modeBar,children:$(F,{style:D.reset,onPress:()=>t(Wn(e)),activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:"Perform every step instead of starting partway",testID:"macro-replay-all",children:$(p,{style:D.resetText,children:"\u21BA Perform every step"})})}):null,te(q,{children:[e.map((f,I)=>te(m,{children:[I>0?$(U,{}):null,$(la,{step:f,index:v[I],before:I<=w,onStartHere:f.lanes.includes("state")&&!f.precondition?()=>t(Nn(e,I)):void 0,onToggleEnabled:()=>A(f.id,{enabled:!f.enabled})}),I===w?te(m,{style:D.startLine,testID:"macro-start-line",children:[$(m,{style:D.startRule}),$(p,{style:D.startLabel,children:"the app starts here \xB7 the rest is performed"}),$(m,{style:D.startRule})]}):null]},f.id)),e.length===0?$(oa,{testID:"macro-review-empty",otto:"shrug",title:"Nothing was recorded",message:"Taps on Buoy's own controls are ignored on purpose \u2014 drive the app itself and try again."}):null]}),z>0?$(ce,{tone:"info",testID:"macro-review-collapsed",children:te(p,{style:D.noticeText,children:[z," shortcut step",z===1?"":"s"," collapsed \u2014 consecutive writes to the same store save once, at the value they ended on."]})}):null,R>0?$(ce,{tone:"info",testID:"macro-review-waits",children:te(p,{style:D.noticeText,children:["Saves as ",y.length," steps: ",R," of them wait for the screen a tap opened, so the replay never runs ahead of the app."]})}):null,d.length?$(ce,{tone:"sim",testID:"macro-review-unnameable",children:te(p,{style:D.noticeText,children:[d.length," tap",d.length===1?"":"s"," landed on something with no testID, label or text, so it can't be found again. Add a testID to replay ",d.length===1?"it":"them","."]})}):null,te(m,{style:D.actions,children:[$(kr,{label:"Discard",variant:"ghost",onPress:o,disabled:a,testID:"macro-discard"}),$(kr,{label:`Save ${y.length} step${y.length===1?"":"s"}`,variant:"primary",disabled:a||!y.length||!l.trim(),onPress:()=>r(l.trim(),e),testID:"macro-save"})]}),$(ae,{children:"Every step is performed the way you did it, which keeps working when the app's internals change. Tap \u201CStart here\u201D on the step you actually want to test and everything before it is written instantly instead \u2014 the setup stops costing you a minute a run, and it survives those earlier screens being redesigned."})]})}function la({step:e,index:t,before:r,onStartHere:o,onToggleEnabled:a}){let i=!e.enabled||e.noise;return te(m,{style:D.row,children:[te(F,{style:D.rowMain,onPress:a,disabled:e.noise,activeOpacity:.7,accessibilityRole:"checkbox",accessibilityState:{checked:!i},accessibilityLabel:e.title,testID:`macro-step-${t}`,children:[$(p,{style:[D.index,i&&D.dim],children:e.precondition?"\u21B1":t}),te(m,{style:D.rowText,children:[$(p,{style:[D.title,i&&D.dim,i&&D.struck],numberOfLines:2,children:e.title}),e.detail?$(p,{style:D.detail,numberOfLines:1,children:e.detail}):null]})]}),o&&!r?$(F,{style:D.startHere,onPress:o,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`Start the macro here \u2014 everything up to \u201C${e.title}\u201D is set instantly`,testID:`macro-step-${t}-start-here`,children:$(p,{style:D.startHereText,children:"Start here"})}):$(p,{style:[D.laneStatic,r&&D.laneStaticInstant],testID:`macro-step-${t}-lane`,children:e.precondition?"first":e.noise?"can\u2019t replay":r?e.lane==="state"?"instant":"skipped":"performed"})]})}var D=V.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:32},nameInput:{color:n.color.text,fontSize:n.font.row,paddingHorizontal:n.textInset,paddingVertical:12},modeBar:{paddingHorizontal:n.gutter,paddingBottom:4},row:{flexDirection:"row",alignItems:"center",gap:8,paddingRight:n.textInset,minHeight:n.rowMinHeight},rowMain:{flex:1,minWidth:0,flexDirection:"row",alignItems:"center",gap:10,paddingLeft:n.textInset,paddingVertical:10},index:{color:n.color.textTertiary,fontSize:n.font.micro,fontWeight:"700",minWidth:14},rowText:{flex:1,minWidth:0},title:{color:n.color.text,fontSize:n.font.row,lineHeight:17},detail:{color:n.color.textTertiary,fontSize:n.font.micro,marginTop:2},dim:{color:n.color.textTertiary},struck:{textDecorationLine:"line-through"},startHere:{paddingHorizontal:8,paddingVertical:5,borderRadius:n.radius.pill,borderWidth:1,borderColor:n.color.border,backgroundColor:n.color.chip},startHereText:{color:n.color.textSecondary,fontSize:n.font.micro,fontWeight:"700"},laneStatic:{color:n.color.textTertiary,fontSize:n.font.micro},laneStaticInstant:{color:n.color.sim},startLine:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:n.textInset,paddingVertical:8,backgroundColor:n.color.simSoft},startRule:{flex:1,height:1,backgroundColor:n.color.simBorder},startLabel:{color:n.color.sim,fontSize:n.font.micro,fontWeight:"700",letterSpacing:.3},reset:{alignSelf:"flex-start",paddingVertical:4},resetText:{color:n.color.textSecondary,fontSize:n.font.footnote,fontWeight:"600"},noticeText:{color:n.color.textSecondary,fontSize:n.font.footnote,lineHeight:16},actions:{flexDirection:"row",justifyContent:"flex-end",gap:8,paddingHorizontal:n.gutter,paddingTop:12},empty:{color:n.color.textTertiary,fontSize:n.font.control,lineHeight:18,paddingHorizontal:n.textInset,paddingVertical:14}});import{useCallback as ca,useState as da}from"react";import{Copy as ua,Power as ha,RefreshCw as fa,ToolButton as Rt,copyToClipboard as pa}from"@buoy-gg/shared-ui/web";import{jsx as Y,jsxs as ze}from"react/jsx-runtime";function ma(e){switch(e.kind){case"override-rule":return{label:"survives restart",tone:"durable"};case"impersonation":return{label:"survives restart",tone:"durable"};case"storage-write":return{label:"not auto-undone",tone:"transient"};default:return{label:"one-shot",tone:"neutral"}}}function ga(e,t){let r=Object.entries(e.varValues).map(([o,a])=>`${o}=${String(a)}`).join(", ");return["\u2014 Bug report context (Buoy Scenarios) \u2014",`Scenario: ${e.name} (v${e.version}, ${e.source})`,`Variables: ${r||"none"}`,`Active since: ${new Date(e.runAt).toISOString()}`,t?`App build: ${t}`:null,`Effects: ${e.effects.map(o=>o.label).join(" \xB7 ")}`].filter(Boolean).join(`
2
- `)}function ya({active:e,build:t,busy:r,onDeactivate:o,onRerun:a,onCopied:i}){let[l]=da(()=>Math.max(1,Math.round((Date.now()-e.runAt)/6e4))),c=ca(()=>{pa(ga(e,t)),i?.()},[e,t,i]);return ze(q,{tone:"sim",testID:"scenario-active-card",children:[ze(m,{style:de.head,children:[Y(m,{style:de.dot}),ze(m,{style:de.headText,children:[Y(p,{style:de.simulated,children:"SIMULATED"}),Y(p,{style:de.name,numberOfLines:2,testID:"scenario-active-name",children:e.name})]}),ze(p,{style:de.ago,children:[l,"m ago"]})]}),Y(U,{}),e.effects.map((s,h)=>{let u=ma(s);return ze(m,{style:de.effect,children:[Y(p,{style:de.effectText,numberOfLines:1,children:s.label}),Y(Me,{label:u.label,tone:u.tone})]},`${s.kind}-${h}`)}),ze(m,{style:de.actions,children:[Y(Rt,{label:"Deactivate",variant:"warning",size:"small",onPress:o,disabled:r,icon:Y(ha,{size:11,color:n.color.sim}),testID:"scenario-deactivate"}),Y(Rt,{label:"Copy repro info",variant:"ghost",size:"small",onPress:c,icon:Y(ua,{size:11,color:n.color.textSecondary}),testID:"scenario-copy-repro"}),Y(Rt,{label:"Re-run",variant:"ghost",size:"small",onPress:a,disabled:r,icon:Y(fa,{size:11,color:n.color.textSecondary}),testID:"scenario-rerun"})]})]})}var de=V.create({head:{flexDirection:"row",alignItems:"flex-start",gap:8,paddingHorizontal:n.textInset,paddingTop:10,paddingBottom:10},dot:{width:8,height:8,borderRadius:4,backgroundColor:n.color.sim,marginTop:4},headText:{flex:1,minWidth:0},simulated:{color:n.color.sim,fontSize:n.font.micro,fontWeight:"700",letterSpacing:.8,fontFamily:H},name:{color:n.color.text,fontSize:n.font.row,fontWeight:"600",marginTop:2},ago:{color:n.color.textTertiary,fontSize:n.font.micro,fontFamily:H,marginTop:2},effect:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:n.textInset,paddingVertical:7},effectText:{flex:1,minWidth:0,color:n.color.textSecondary,fontSize:n.font.control,fontFamily:H},actions:{flexDirection:"row",flexWrap:"wrap",gap:6,paddingHorizontal:n.textInset,paddingTop:8,paddingBottom:10}});import{AlertTriangle as ba,Check as va,ToolButton as wa}from"@buoy-gg/shared-ui/web";import{jsx as we,jsxs as Rr}from"react/jsx-runtime";function Sa({report:e,onDismiss:t}){let r=[];e.removedRules&&r.push({tone:"ok",text:`${e.removedRules} override rule${e.removedRules===1?"":"s"} removed \u2014 pull to refresh shows real data`}),e.stoppedImpersonation&&r.push({tone:"ok",text:"Impersonation ended"}),e.clearedTransients&&r.push({tone:"ok",text:`${e.clearedTransients} one-shot effect${e.clearedTransients===1?"":"s"} had nothing to remove`}),e.undoStepsRan&&r.push({tone:"ok",text:`${e.undoStepsRan} undo step${e.undoStepsRan===1?"":"s"} ran`}),e.unrestoredStorageKeys.length&&r.push({tone:"warn",text:`${e.unrestoredStorageKeys.length} storage key${e.unrestoredStorageKeys.length===1?"":"s"} NOT restored: ${e.unrestoredStorageKeys.join(", ")} \u2014 a storage write has no automatic inverse. Re-run your login flow, or restore a Time Machine snapshot.`});let o=e.unrestoredState??[];o.length&&r.push({tone:"warn",text:`${o.length} store${o.length===1?"":"s"} still hold${o.length===1?"s":""} what this scenario wrote: ${o.join(", ")} \u2014 a state write has no automatic inverse. Reset it in its own tool, or restore a Time Machine snapshot.`});for(let i of e.errors)r.push({tone:"warn",text:i});r.length||r.push({tone:"ok",text:"Nothing left to undo \u2014 the app is real."});let a=r.every(i=>i.tone==="ok");return we(q,{tone:a?"neutral":"sim",children:Rr(m,{style:Ke.body,children:[we(p,{style:Ke.title,testID:"scenario-deactivate-report",children:"DEACTIVATED"}),r.map((i,l)=>Rr(m,{style:Ke.line,children:[i.tone==="ok"?we(va,{size:12,color:n.color.accent}):we(ba,{size:12,color:n.color.sim}),we(p,{style:Ke.text,children:i.text})]},`${i.tone}-${l}`)),we(m,{style:Ke.actions,children:we(wa,{label:"Done",variant:"primary",size:"small",onPress:t,testID:"scenario-dismiss-report"})})]})})}var Ke=V.create({body:{padding:n.textInset,gap:8},title:{color:n.color.textSecondary,fontSize:n.font.micro,fontWeight:"700",letterSpacing:.8,fontFamily:H},line:{flexDirection:"row",gap:8,alignItems:"flex-start"},text:{flex:1,color:n.color.textSecondary,fontSize:n.font.control,lineHeight:17},actions:{flexDirection:"row",marginTop:2}});import{Fragment as Ar,useCallback as xa,useMemo as Ta,useState as Ia}from"react";import{Layers as Da,Play as ka,Hash as Ca,ToolButton as At}from"@buoy-gg/shared-ui/web";import{useToolHeader as $a}from"@buoy-gg/core/web";import{Fragment as Er,jsx as x,jsxs as j}from"react/jsx-runtime";function Ra(e){return e==="durable"?"durable":e==="transient"?"transient":"neutral"}var Aa={durable:"survives restart",session:"until restart",transient:"until refetch \u26A0","one-shot":"one-shot"};function Ea({variable:e,value:t,onChange:r}){let o=e.label??e.key,a=`scenario-var-${e.key}`;return e.type==="enum"&&e.options?.length?j(m,{style:S.field,children:[x(p,{style:S.fieldLabel,children:o}),x(m,{style:S.segs,children:e.options.map(i=>{let l=String(t)===String(i);return x(F,{style:[S.seg,l?S.segOn:null],onPress:()=>r(i),accessibilityRole:"button",accessibilityState:{selected:l},testID:`${a}-${String(i)}`,children:x(p,{style:[S.segText,l?S.segTextOn:null],children:String(i)})},String(i))})})]}):e.type==="boolean"?j(m,{style:[S.field,S.fieldRow],children:[x(p,{style:S.fieldLabel,children:o}),x(Gt,{value:t===true,onValueChange:i=>r(i),testID:a})]}):j(m,{style:S.field,children:[x(p,{style:S.fieldLabel,children:o}),x(_e,{style:S.input,value:t===void 0?"":String(t),onChangeText:i=>r(Xt(e,i)),keyboardType:e.type==="number"?"numeric":"default",placeholder:e.type==="number"?"0":"value",placeholderTextColor:n.color.textTertiary,autoCapitalize:"none",autoCorrect:false,testID:a})]})}function La({scenario:e,initialValues:t,check:r,currentBuild:o,mode:a,onRun:i,onAcceptDraft:l,onDiscardDraft:c,onBack:s}){let[h,u]=Ia(t);$a({title:a==="review-draft"?"Review draft":"Before you run",subtitle:ye(e.name,h),onBack:s,searchable:false},[e.id,a]);let d=Ta(()=>r(h),[r,h]),w=xa((y,R)=>{u(z=>({...z,[y]:R}))},[]),v=!!e.authoredAgainst&&!!o&&e.authoredAgainst!==o&&e.verifiedAt?.build!==o,A=!d.ok;return j(m,{style:S.fill,children:[j(pe,{style:S.fill,contentContainerStyle:S.content,keyboardShouldPersistTaps:"handled",testID:"scenario-preview-scroll",children:[e.description?x(ae,{testID:"scenario-preview-description",children:e.description}):null,e.vars.length?j(Er,{children:[x(K,{icon:Ca,count:e.vars.length,children:"Variables"}),x(q,{children:e.vars.map((y,R)=>j(Ar,{children:[R>0?x(U,{}):null,x(Ea,{variable:y,value:h[y.key],onChange:z=>w(y.key,z)})]},y.key))})]}):null,x(K,{icon:Da,count:e.steps.length,children:"What this will do"}),x(q,{children:e.steps.map((y,R)=>{let z=me(y.params??{},h),f=Ne(y);return j(Ar,{children:[R>0?x(U,{}):null,j(m,{style:S.step,children:[x(m,{style:S.stepIndex,children:x(p,{style:S.stepIndexText,children:R+1})}),j(m,{style:S.stepBody,children:[x(p,{style:S.stepLabel,children:$e(y,z)}),j(p,{style:S.stepTool,children:[y.tool,".",y.action]})]}),x(Me,{label:Aa[f],tone:Ra(f)})]})]},y.id)})}),v?x(ce,{tone:"sim",testID:"scenario-preview-stale",children:j(p,{style:S.warnText,children:["Authored against app ",e.authoredAgainst," \u2014 unverified on this build. The response shape it overrides may have drifted."]})}):null,d.conflict?x(ce,{tone:"sim",testID:"scenario-preview-conflict",children:j(p,{style:S.warnText,children:["Conflict: \u201C",d.conflict.activeName,"\u201D is active and touches the same ",d.conflict.overlaps.length===1?"target":"targets",". Running will swap \u2014 it deactivates first, so the two can never overlap silently."]})}):null,d.errors.length?x(ce,{tone:"danger",testID:"scenario-preview-errors",children:d.errors.map(y=>j(p,{style:S.errorText,children:["\u2022 ",y]},y))}):null,d.warnings.length?x(ce,{tone:"sim",children:d.warnings.map(y=>j(p,{style:S.warnText,children:["\u2022 ",y]},y))}):null,e.expectedOutcome?x(ce,{tone:"info",testID:"scenario-preview-expected",children:j(p,{style:S.infoText,children:[x(p,{style:S.infoStrong,children:"Expected outcome: "}),e.expectedOutcome]})}):null]}),x(m,{style:S.footer,children:a==="review-draft"?j(Er,{children:[x(At,{label:"Discard",variant:"ghost",onPress:()=>c?.(),style:S.grow,testID:"scenario-discard-draft"}),x(At,{label:"Accept to library",variant:"primary",onPress:()=>l?.(),style:S.grow,testID:"scenario-accept-draft"})]}):x(At,{label:d.conflict?"Swap & run":"Run",variant:"primary",onPress:()=>i(h),disabled:A,icon:x(ka,{size:12,color:n.color.accent}),style:S.grow,testID:"scenario-confirm-run"})})]})}var S=V.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:24},field:{paddingHorizontal:n.textInset,paddingVertical:10,gap:6},fieldRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between"},fieldLabel:{color:n.color.textTertiary,fontSize:n.font.micro,fontWeight:"600",letterSpacing:.6,textTransform:"uppercase"},segs:{flexDirection:"row",flexWrap:"wrap",gap:6},seg:{borderRadius:n.radius.row,borderWidth:1,borderColor:n.color.border,backgroundColor:n.color.chip,paddingHorizontal:12,paddingVertical:6},segOn:{backgroundColor:n.color.accentSoft,borderColor:n.color.accentBorderStrong},segText:{color:n.color.textSecondary,fontSize:n.font.control,fontFamily:H},segTextOn:{color:n.color.accent,fontWeight:"700"},input:{backgroundColor:n.color.row,borderRadius:n.radius.row,borderWidth:1,borderColor:n.color.border,color:n.color.text,fontSize:n.font.row,fontFamily:H,paddingHorizontal:10,paddingVertical:8},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:n.textInset,paddingVertical:10},stepIndex:{width:18,height:18,borderRadius:n.radius.badge,backgroundColor:n.color.fill,alignItems:"center",justifyContent:"center",marginTop:1},stepIndexText:{color:n.color.textTertiary,fontSize:10,fontWeight:"700",fontFamily:H},stepBody:{flex:1,minWidth:0},stepLabel:{color:n.color.text,fontSize:n.font.control},stepTool:{color:n.color.textTertiary,fontSize:n.font.mono,fontFamily:H,marginTop:2},warnText:{color:n.color.sim,fontSize:n.font.control,lineHeight:17},errorText:{color:n.color.danger,fontSize:n.font.control,lineHeight:17},infoText:{color:"#7FA9FF",fontSize:n.font.control,lineHeight:17},infoStrong:{fontWeight:"700"},footer:{flexDirection:"row",gap:8,paddingHorizontal:n.gutter,paddingTop:10,paddingBottom:14,borderTopWidth:1,borderTopColor:n.color.border,backgroundColor:n.color.surface},grow:{flex:1}});import{Fragment as za}from"react";import{Check as Ba,Layers as Oa,RefreshCw as Pa,ToolButton as Qe,X as Va}from"@buoy-gg/shared-ui/web";import{useToolHeader as Ha}from"@buoy-gg/core/web";import{Fragment as ja,jsx as L,jsxs as re}from"react/jsx-runtime";function Fa({runState:e,busy:t,onUndoPartial:r,onKeepPartial:o,onRetry:a,onDone:i,onBack:l}){let c=e.report,s=!!c&&!c.ok;Ha({title:s?"Run failed":e.done?"Run complete":"Running\u2026",subtitle:e.name,onBack:e.done?l:void 0,searchable:false},[e.done,s,e.name]);let h=c?.steps??e.steps;return re(m,{style:B.fill,children:[re(pe,{style:B.fill,contentContainerStyle:B.content,testID:"scenario-run-scroll",children:[L(K,{icon:Oa,color:s?n.color.danger:n.color.accent,children:"Steps"}),re(q,{tone:s?"danger":"neutral",children:[h.length===0?re(m,{style:B.step,children:[L(mt,{size:"small",color:n.color.accent}),L(p,{style:B.stepLabel,children:"Starting\u2026"})]}):null,h.map((u,d)=>re(za,{children:[d>0?L(U,{}):null,re(m,{style:B.step,children:[L(m,{style:B.mark,children:u.skipped?L(p,{style:B.skipped,children:"\u2013"}):u.ok?L(Ba,{size:13,color:n.color.accent}):L(Va,{size:13,color:n.color.danger})}),re(m,{style:B.stepBody,children:[L(p,{style:[B.stepLabel,u.skipped?B.dim:null],testID:`scenario-step-${d}`,children:u.label}),u.error?L(p,{style:B.error,testID:`scenario-step-${d}-error`,children:u.error}):null,u.skipped?L(p,{style:B.dimSmall,children:"skipped"}):null]}),u.ms?re(p,{style:B.ms,children:[u.ms,"ms"]}):null]})]},u.id)),!e.done&&h.length?re(ja,{children:[L(U,{}),re(m,{style:B.step,children:[L(mt,{size:"small",color:n.color.accent}),L(p,{style:B.stepLabel,children:"Working\u2026"})]})]}):null]}),s?L(ce,{tone:"danger",children:L(p,{style:B.errorText,children:"The run stopped at the failing step. Nothing after it ran \u2014 but the steps before it did, so choose what happens to them."})}):null]}),s?re(m,{style:B.footer,children:[L(Qe,{label:"Undo applied steps",variant:"primary",onPress:r,disabled:t,style:B.grow,testID:"scenario-undo-partial"}),L(Qe,{label:"Keep",variant:"ghost",onPress:o,testID:"scenario-keep-partial"}),L(Qe,{label:"Retry",variant:"ghost",onPress:a,disabled:t,icon:L(Pa,{size:12,color:n.color.textSecondary}),testID:"scenario-retry"})]}):e.done?L(m,{style:B.footer,children:L(Qe,{label:"Done",variant:"primary",onPress:i,style:B.grow,testID:"scenario-run-done"})}):null]})}var B=V.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:24},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:n.textInset,paddingVertical:10},mark:{width:18,alignItems:"center",marginTop:1},skipped:{color:n.color.textTertiary,fontSize:13,fontFamily:H},stepBody:{flex:1,minWidth:0},stepLabel:{color:n.color.text,fontSize:n.font.control},dim:{color:n.color.textTertiary},dimSmall:{color:n.color.textTertiary,fontSize:n.font.mono,marginTop:2,fontFamily:H},error:{color:n.color.danger,fontSize:n.font.mono,marginTop:3,fontFamily:H},ms:{color:n.color.textTertiary,fontSize:n.font.micro,fontFamily:H,marginTop:3},errorText:{color:n.color.danger,fontSize:n.font.control,lineHeight:17},footer:{flexDirection:"row",gap:8,paddingHorizontal:n.gutter,paddingTop:10,paddingBottom:14,borderTopWidth:1,borderTopColor:n.color.border,backgroundColor:n.color.surface},grow:{flex:1}});import{Fragment as Na}from"react";import{CheckCircle as Wa,ChevronRight as Ma,Copy as Ka,FileText as qa,Layers as Ua,Play as _a,ToolButton as Ze,Trash as Ja,copyToClipboard as Ga}from"@buoy-gg/shared-ui/web";import{useToolHeader as Ya}from"@buoy-gg/core/web";import{memo as Xa}from"react";import{CompactRow as Qa}from"@buoy-gg/shared-ui/web";import{Fragment as Za,jsx as Be,jsxs as ei}from"react/jsx-runtime";function Oe(e){return e.replace(/\{\{\s*(\w+)\s*\}\}/g,"\u27E8$1\u27E9")}function Lr(e){let t=[`v${e.version}`];e.author&&t.push(e.author);let r=e.usage?.runs??0;return r&&t.push(`${r}\xD7`),e.unsavedToRepo&&t.push("unsaved to repo"),e.source==="draft"&&t.push("inert until you accept"),t.join(" \xB7 ")}function ti(e){return e.source==="code"?{label:"Shipped",color:n.color.accent}:e.source==="draft"?{label:"Draft",color:n.color.sim}:{label:"Saved",color:n.color.info}}function ri({scenario:e,currentBuild:t,disabled:r,showFolder:o,onOpen:a,onRun:i,testID:l}){let c=l??`scenario-row-${e.id}`,s=ti(e),h=le(e.folder),u=e.source==="draft"?{label:"Review",color:n.color.sim}:{label:"Run",color:n.color.accent},d=!!e.authoredAgainst&&!!t&&e.authoredAgainst!==t&&e.verifiedAt?.build!==t;return Be(Qa,{statusDotColor:s.color,statusLabel:s.label,statusSublabel:`${e.steps.length} step${e.steps.length===1?"":"s"}`,primaryText:Oe(e.name),primaryTestID:`${c}-name`,secondaryText:Lr(e),secondaryTestID:`${c}-meta`,secondaryAccessory:ei(Za,{children:[o&&h?Be(Me,{label:h,tone:"neutral",testID:`${c}-folder`}):null,d?Be(Me,{label:`stale \xB7 ${e.authoredAgainst}`,tone:"transient",testID:`${c}-stale`}):null]}),trailingAction:Be(F,{onPress:i,disabled:r,style:r?ni.disabled:null,hitSlop:oi,accessibilityRole:"button",accessibilityLabel:`${u.label} ${Oe(e.name)}`,testID:`${c}-run`,children:Be(m,{children:Be(sa,{label:u.label,color:u.color})})}),showChevron:true,onPress:a,testID:c,accessibilityLabel:`${Oe(e.name)}. ${s.label}, ${e.steps.length} step${e.steps.length===1?"":"s"}, ${Lr(e)}. Open details.`})}var Et=Xa(ri),oi={top:8,bottom:8,left:8,right:8},ni=V.create({disabled:{opacity:.4}});import{Fragment as qe,jsx as b,jsxs as X}from"react/jsx-runtime";var ai={durable:"survives restart",session:"until restart",transient:"until refetch \u26A0","one-shot":"one-shot"};function ii(e){return e==="durable"?"durable":e==="transient"?"transient":"neutral"}function si({scenario:e,onRun:t,onDelete:r,onDuplicate:o,onExported:a,onMoveToFolder:i,onBack:l}){Ya({title:Oe(e.name),subtitle:e.source==="code"?"shipped with this app":"saved on this device",onBack:l,searchable:false},[e.id]);let c=e.source==="device",s=le(e.folder);return X(pe,{style:O.fill,contentContainerStyle:O.content,testID:"scenario-detail-scroll",children:[e.description?b(ae,{children:e.description}):null,b(K,{icon:Ua,count:e.steps.length,children:"Steps"}),b(q,{children:e.steps.map((h,u)=>{let d=Ne(h);return X(Na,{children:[u>0?b(U,{}):null,X(m,{style:O.step,children:[b(m,{style:O.stepIndex,children:b(p,{style:O.stepIndexText,children:u+1})}),X(m,{style:O.stepBody,children:[b(p,{style:O.stepLabel,children:$e(h)}),X(p,{style:O.stepTool,children:[h.tool,".",h.action,or(h)?" \xB7 advanced":""]})]}),b(Me,{label:ai[d],tone:ii(d)})]})]},h.id)})}),e.expectedOutcome?X(qe,{children:[b(K,{icon:Wa,children:"Expected outcome"}),b(q,{children:b(p,{style:O.expected,children:e.expectedOutcome})})]}):null,b(K,{icon:qa,children:"Details"}),X(q,{children:[b(Se,{label:"Folder",value:s??"No folder",muted:!s,onPress:c?i:void 0,testID:"scenario-detail-folder"}),b(U,{}),b(Se,{label:"Source",value:e.source==="code"?"shipped with this app":"saved on this device"}),b(U,{}),b(Se,{label:"Version",value:`v${e.version}`}),e.author?X(qe,{children:[b(U,{}),b(Se,{label:"Author",value:e.author})]}):null,e.authoredAgainst?X(qe,{children:[b(U,{}),b(Se,{label:"Authored against",value:e.authoredAgainst})]}):null,b(U,{}),b(Se,{label:"Runs",value:String(e.usage?.runs??0)}),e.tags?.length?X(qe,{children:[b(U,{}),b(Se,{label:"Tags",value:e.tags.join(", ")})]}):null]}),X(m,{style:O.footer,children:[b(Ze,{label:"Run",variant:"primary",onPress:t,icon:b(_a,{size:12,color:n.color.accent}),style:O.grow,testID:"scenario-detail-run"}),b(Ze,{label:"Export",variant:"ghost",onPress:()=>{Ga(JSON.stringify(e,null,2)),a?.()},icon:b(Ka,{size:12,color:n.color.textSecondary}),style:O.grow,testID:"scenario-detail-export"})]}),b(m,{style:O.footer,children:c?b(Ze,{label:"Delete",variant:"danger",onPress:r,icon:b(Ja,{size:12,color:n.color.danger}),style:O.grow,testID:"scenario-detail-delete"}):b(Ze,{label:"Make an editable copy",variant:"ghost",onPress:o,style:O.grow,testID:"scenario-detail-duplicate"})}),e.source==="code"?b(ae,{children:"Shipped scenarios are read-only on the device \u2014 they change in a pull request, with the code they bend."}):null]})}function Se({label:e,value:t,muted:r,onPress:o,testID:a}){let i=X(qe,{children:[b(p,{style:O.detailLabel,children:e}),b(p,{style:[O.detailValue,r&&O.detailValueMuted,o&&O.detailValueAction],numberOfLines:2,children:t}),o?b(Ma,{size:13,color:n.color.textTertiary}):null]});return o?b(F,{style:O.detail,onPress:o,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`${e}: ${t}. Change it.`,testID:a,children:i}):b(m,{style:O.detail,testID:a,children:i})}var O=V.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:32},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:n.textInset,paddingVertical:10},stepIndex:{width:18,height:18,borderRadius:n.radius.badge,backgroundColor:n.color.fill,alignItems:"center",justifyContent:"center",marginTop:1},stepIndexText:{color:n.color.textTertiary,fontSize:10,fontWeight:"700",fontFamily:H},stepBody:{flex:1,minWidth:0},stepLabel:{color:n.color.text,fontSize:n.font.control},stepTool:{color:n.color.textTertiary,fontSize:n.font.mono,fontFamily:H,marginTop:2},expected:{color:n.color.textSecondary,fontSize:n.font.control,lineHeight:18,paddingHorizontal:n.textInset,paddingVertical:12},detail:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:8,minHeight:40,paddingHorizontal:n.textInset,paddingVertical:10},detailLabel:{color:n.color.textTertiary,fontSize:n.font.control},detailValue:{flex:1,textAlign:"right",color:n.color.textSecondary,fontSize:n.font.control,fontFamily:H},detailValueMuted:{color:n.color.textTertiary},detailValueAction:{color:n.color.accent},footer:{flexDirection:"row",gap:8,paddingHorizontal:n.gutter,paddingTop:12},grow:{flex:1}});import{jsx as et,jsxs as li}from"react/jsx-runtime";function ci(e,t){return t===null?true:xt(e,t)}function Lt(e){return e===null?"__all__":e===void 0?"__ungrouped__":e}function di({folders:e,active:t,onChange:r,scenarios:o}){let a=Tt(o,void 0),i=[{filter:null,label:"All",count:o.length},...e.map(l=>({filter:l,label:l,count:Tt(o,l)}))];return a&&i.push({filter:void 0,label:ur,count:a}),et(pe,{horizontal:true,showsHorizontalScrollIndicator:false,style:ie.scroll,contentContainerStyle:ie.row,testID:"scenarios-folder-bar",children:i.map(l=>{let c=t===l.filter||typeof t=="string"&&typeof l.filter=="string"&&t.toLowerCase()===l.filter.toLowerCase();return li(F,{testID:`scenarios-folder-${Lt(l.filter)}`,accessibilityRole:"button",accessibilityLabel:`Show ${l.label} scenarios`,accessibilityState:{selected:c},activeOpacity:.8,onPress:()=>r(l.filter),style:[ie.chip,c&&ie.chipActive],children:[et(p,{style:[ie.label,c&&ie.labelActive],numberOfLines:1,children:l.label}),et(m,{style:[ie.countPill,c&&ie.countPillActive],children:et(p,{style:[ie.count,c&&ie.countActive],testID:`scenarios-folder-${Lt(l.filter)}-count`,children:l.count})})]},Lt(l.filter))})})}var ie=V.create({scroll:{flexGrow:0},row:{flexDirection:"row",gap:8,paddingHorizontal:n.gutter,paddingTop:10,paddingBottom:2},chip:{flexDirection:"row",alignItems:"center",gap:6,backgroundColor:n.color.chip,borderRadius:n.radius.card,borderWidth:1,borderColor:n.color.border,paddingVertical:6,paddingHorizontal:10,minHeight:32,maxWidth:200},chipActive:{backgroundColor:n.color.accentSoft,borderColor:n.color.accentBorderStrong},label:{fontSize:n.font.footnote,color:n.color.textSecondary,fontWeight:"500",flexShrink:1},labelActive:{color:n.color.accent,fontWeight:"600"},countPill:{minWidth:18,alignItems:"center",borderRadius:n.radius.badge,backgroundColor:n.color.fill,paddingHorizontal:4,paddingVertical:1},countPillActive:{backgroundColor:n.color.accentSoft},count:{fontSize:n.font.micro,fontWeight:"600",fontFamily:H,color:n.color.textTertiary},countActive:{color:n.color.accent}});import{useState as ui}from"react";import{Bookmark as hi,Check as fi,Plus as pi,ToolButton as mi}from"@buoy-gg/shared-ui/web";import{useToolHeader as gi}from"@buoy-gg/core/web";import{jsx as Q,jsxs as Pe}from"react/jsx-runtime";function yi({scenario:e,folders:t,onPick:r,onBack:o}){let[a,i]=ui("");gi({title:"Move to folder",subtitle:Oe(e.name),onBack:o,searchable:false},[e.id]);let l=le(e.folder),c=le(a),s=!!c&&!t.some(h=>h.toLowerCase()===c.toLowerCase());return Pe(pe,{style:ue.fill,contentContainerStyle:ue.content,keyboardShouldPersistTaps:"handled",testID:"scenario-folder-scroll",children:[Q(K,{icon:hi,count:t.length,children:"Folders"}),Pe(q,{children:[Q(zr,{label:"No folder",hint:"Shows under Ungrouped",selected:!l,onPress:()=>r(void 0),testID:"scenario-folder-none"}),t.map(h=>Pe(m,{children:[Q(U,{}),Q(zr,{label:h,selected:!!l&&l.toLowerCase()===h.toLowerCase(),onPress:()=>r(h),testID:`scenario-folder-pick-${h.toLowerCase().replace(/\s+/g,"-")}`})]},h))]}),Q(K,{icon:pi,children:"New folder"}),Q(q,{children:Pe(m,{style:ue.newRow,children:[Q(_e,{style:ue.input,value:a,onChangeText:i,placeholder:"Checkout",placeholderTextColor:n.color.textTertiary,maxLength:32,autoCapitalize:"words",autoCorrect:false,returnKeyType:"done",onSubmitEditing:()=>c&&r(c),testID:"scenario-folder-new-input"}),Q(mi,{label:c&&!s?"Use":"Create",variant:"primary",size:"small",disabled:!c,onPress:()=>c&&r(c),testID:"scenario-folder-create"})]})}),Q(ae,{children:"A folder exists as long as something is filed in it \u2014 empty it and it goes away. Typing a name that already exists files it there instead of making a second one."})]})}function zr({label:e,hint:t,selected:r,onPress:o,testID:a}){return Pe(F,{style:ue.row,onPress:o,activeOpacity:.7,accessibilityRole:"button",accessibilityState:{selected:r},accessibilityLabel:`File under ${e}`,testID:a,children:[Pe(m,{style:ue.rowText,children:[Q(p,{style:[ue.rowLabel,r&&ue.rowLabelSelected],numberOfLines:1,children:e}),t?Q(p,{style:ue.rowHint,children:t}):null]}),r?Q(fi,{size:14,color:n.color.accent}):null]})}var ue=V.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:32},row:{flexDirection:"row",alignItems:"center",gap:12,minHeight:n.rowMinHeight,paddingHorizontal:n.textInset,paddingVertical:10},rowText:{flex:1,minWidth:0},rowLabel:{color:n.color.text,fontSize:n.font.row},rowLabelSelected:{color:n.color.accent,fontWeight:"600"},rowHint:{color:n.color.textTertiary,fontSize:n.font.micro,marginTop:2},newRow:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:n.textInset,paddingVertical:10},input:{flex:1,backgroundColor:n.color.row,borderRadius:n.radius.row,borderWidth:1,borderColor:n.color.border,color:n.color.text,fontSize:n.font.row,fontFamily:H,paddingHorizontal:10,paddingVertical:8}});import{Fragment as Br,jsx as T,jsxs as xe}from"react/jsx-runtime";function bi(e){return`macro-${e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,40)||"recording"}-${Date.now().toString(36)}`}function tt({currentBuild:e}){let t=xr(),r=Tr(),o=Ir(),a=dn(),i=ln({minBottom:16}),l=sn("scenarios.saved"),[c,s]=dt({name:"list"}),[h,u]=dt(false),d=ge(()=>s({name:"list"}),[]),w=ge(f=>I=>g.checkBeforeRun(f,I),[]),v=ge(async(f,I)=>{u(true),s({name:"run"});try{let k=await g.run(f,I);k.ok&&(a.showToast(`Scenario active \u2014 ${k.effects.length} change${k.effects.length===1?"":"s"}`,"success"),g.clearRunState(),s({name:"list"}),a.minimize())}catch(k){a.showToast(k instanceof Error?k.message:String(k),"error"),s({name:"list"})}finally{u(false)}},[a]),A=ge(async()=>{u(true);try{await g.deactivate()}finally{u(false)}},[]),y=ge(async()=>{await ee.start();let{status:f,reason:I}=ee.getState();if(f!=="recording"){a.showToast(I??"Recording isn't available in this app.","error");return}a.minimize()},[a]),R=ge(async(f,I)=>{u(true);try{let k=Ct(I),Te=Date.now();await g.saveScenario({id:bi(f),name:f,version:1,source:"device",author:"recorded here",vars:[],steps:k,authoredAgainst:e,unsavedToRepo:true,createdAt:Te,updatedAt:Te,usage:{runs:0}}),await ee.cancel(),a.showToast(`Saved \u201C${f}\u201D`,"success"),d()}catch(k){a.showToast(k instanceof Error?k.message:String(k),"error")}finally{u(false)}},[e,d,a]);if(o.status==="review"&&o.draft)return T($r,{draft:o.draft,busy:h,onChange:f=>ee.setDraft(f),onSave:R,onDiscard:()=>{gt.alert("Discard this recording?","The steps you just recorded will be thrown away.",[{text:"Keep",style:"cancel"},{text:"Discard",style:"destructive",onPress:()=>{ee.cancel(),d()}}])}});if(c.name==="run"&&r)return T(Fa,{runState:r,busy:h,onUndoPartial:async()=>{u(true);try{await g.undoPartialRun(),a.showToast("Applied steps undone","success")}finally{u(false),d()}},onKeepPartial:()=>{g.clearRunState(),d()},onRetry:()=>{let f=r.scenarioId;g.find(f)&&v(f,g.lastValuesFor(f))},onDone:()=>{g.clearRunState(),d()},onBack:()=>{g.clearRunState(),d()}});if(c.name==="preview"){let f=g.find(c.scenarioId);if(!f)return T(rt,{...z()});let I={...je(f.vars),...g.lastValuesFor(f.id)};return T(La,{scenario:f,initialValues:I,check:w(f),currentBuild:e,mode:c.mode,onRun:k=>{g.rememberVarValues(f.id,k),v(f.id,k)},onAcceptDraft:async()=>{await g.acceptDraft(f.id),a.showToast("Accepted \u2014 it's now in your library","success"),d()},onDiscardDraft:async()=>{await g.discardDraft(f.id),a.showToast("Draft discarded","info"),d()},onBack:d})}if(c.name==="detail"){let f=g.find(c.scenarioId);return f?T(si,{scenario:f,onRun:()=>s({name:"preview",scenarioId:f.id,mode:"run"}),onDelete:()=>{gt.alert("Delete scenario?",`\u201C${Oe(f.name)}\u201D will be removed from this device.`,[{text:"Cancel",style:"cancel"},{text:"Delete",style:"destructive",onPress:()=>{g.deleteScenario(f.id),d()}}])},onDuplicate:async()=>{let I={...f,id:`${f.id}-copy-${Date.now().toString(36)}`,name:`${f.name} (copy)`,source:"device",version:1,unsavedToRepo:true};await g.saveScenario(I),a.showToast("Copied to this device","success"),d()},onExported:()=>a.showToast("Scenario JSON copied","success"),onMoveToFolder:()=>s({name:"folder",scenarioId:f.id}),onBack:d}):T(rt,{...z()})}if(c.name==="folder"){let f=g.find(c.scenarioId);return f?T(yi,{scenario:f,folders:g.folders(),onPick:async I=>{try{await g.setFolder(f.id,I),a.showToast(I?`Filed under ${I}`:"Removed from its folder","success")}catch(k){a.showToast(k instanceof Error?k.message:String(k),"error")}s({name:"detail",scenarioId:f.id})},onBack:()=>s({name:"detail",scenarioId:f.id})}):T(rt,{...z()})}function z(){return{state:t,insets:i,host:a,busy:h,savedLimit:l,currentBuild:e,onOpen:f=>s({name:"detail",scenarioId:f}),onRun:f=>s({name:"preview",scenarioId:f,mode:"run"}),onReviewDraft:f=>s({name:"preview",scenarioId:f,mode:"review-draft"}),onDeactivate:A,onRerun:()=>{let f=t.active;f&&v(f.scenarioId,f.varValues)},onStartRecording:y,canRecord:ee.canRecord(),recordUnavailable:o.status==="unavailable"?o.reason:null}}return T(rt,{...z()})}function Or(e,t,r){return e?"No matches.":t===void 0?"Nothing unfiled here.":t!==null?`Nothing in ${t}.`:r}function rt({state:e,insets:t,host:r,busy:o,savedLimit:a,currentBuild:i,onOpen:l,onRun:c,onReviewDraft:s,onDeactivate:h,onRerun:u,onStartRecording:d,canRecord:w,recordUnavailable:v}){let[A,y]=dt(null),R=r.search.trim().toLowerCase(),z=E=>!R||E.name.toLowerCase().includes(R)||(E.folder??"").toLowerCase().includes(R)||(E.tags??[]).some(Kr=>Kr.toLowerCase().includes(R))||(E.author??"").toLowerCase().includes(R),f={code:e.code.filter(z),device:e.device.filter(z),drafts:e.drafts.filter(z)},I=g.folders(),k=[...f.code,...f.device,...f.drafts],Te=E=>ci(E,A),it=f.code.filter(Te),st=f.device.filter(Te),lt=f.drafts.filter(Te),Wr=e.device.length>=a,Mr=g.isLongRunning(),ct=A===null&&I.length>0,Pt=ge(()=>({shipped:e.code,saved:e.device,drafts:e.drafts,active:e.active??null}),[e.code,e.device,e.drafts,e.active]),Vt=Yr(()=>T(nn,{value:Pt,buttonStyle:oe.headerButton,testID:"scenarios-copy-library",accessibilityLabel:"Copy the scenario library as JSON"}),[Pt]);return cn({actions:Vt},[Vt]),xe(m,{style:oe.fill,children:[I.length?T(di,{folders:I,active:A,onChange:y,scenarios:k}):null,xe(pe,{style:oe.fill,contentContainerStyle:[oe.content,{paddingBottom:t.bottom}],keyboardShouldPersistTaps:"handled",testID:"scenarios-scroll",children:[w?xe(F,{style:oe.record,onPress:d,disabled:o,activeOpacity:.75,accessibilityRole:"button",accessibilityLabel:"Record what you do next as a macro",testID:"scenarios-record",children:[T(m,{style:oe.recordDot}),xe(m,{style:oe.recordText,children:[T(p,{style:oe.recordTitle,children:"Record a macro"}),T(p,{style:oe.recordHint,children:"Do the flow once. Buoy writes down the steps."})]})]}):null,v?T(ae,{tone:"warning",testID:"scenarios-record-unavailable",children:v}):null,e.lastDeactivateReport?T(Sa,{report:e.lastDeactivateReport,onDismiss:()=>g.dismissDeactivateReport()}):null,e.active?xe(Br,{children:[T(K,{icon:an,color:n.color.sim,testID:"scenarios-active-label",children:"Active now"}),T(ya,{active:e.active,build:i,busy:o,onDeactivate:h,onRerun:u,onCopied:()=>r.showToast("Repro info copied \u2014 paste into the ticket","success")}),Mr?T(ae,{tone:"warning",testID:"scenarios-long-running",children:"This scenario has been active for a while. If you have moved on to something else, deactivate it before you test anything real."}):null]}):null,lt.length?xe(Br,{children:[T(K,{icon:rn,color:n.color.sim,count:lt.length,testID:"scenarios-drafts-label",children:"Awaiting review"}),lt.map(E=>T(Et,{scenario:E,currentBuild:i,disabled:o,showFolder:ct,onOpen:()=>s(E.id),onRun:()=>s(E.id),testID:`scenario-draft-${E.id}`},E.id)),T(ae,{children:"A scenario sent from chat or the desktop never runs on its own. You review what it will do, then accept it."})]}):null,T(K,{icon:tn,count:it.length,testID:"scenarios-code-label",children:"Shipped with this app"}),it.length?it.map(E=>T(Et,{scenario:E,currentBuild:i,disabled:o,showFolder:ct,onOpen:()=>l(E.id),onRun:()=>c(E.id)},E.id)):T(q,{children:T(p,{style:oe.empty,testID:"scenarios-code-empty",children:Or(R,A,"None yet \u2014 your developers can ship a QA menu with the app using defineScenario().")})}),T(K,{icon:on,color:n.color.info,count:st.length,testID:"scenarios-device-label",children:"Saved on this device"}),st.length?st.map(E=>T(Et,{scenario:E,currentBuild:i,disabled:o,showFolder:ct,onOpen:()=>l(E.id),onRun:()=>c(E.id)},E.id)):T(q,{children:T(p,{style:oe.empty,testID:"scenarios-device-empty",children:Or(R,A,"Nothing saved here yet. Ask your AI assistant to save the state you just set up as a scenario.")})}),Wr?xe(ae,{tone:"warning",testID:"scenarios-limit",children:["Your plan keeps ",a," saved scenario",a===1?"":"s"," on a device. Scenarios shipped in code don't count toward it."]}):null,T(ae,{children:I.length?"Scenarios only run in development builds. Tap a row to see exactly what it will do before you run it.":"Scenarios only run in development builds. Open one and tap its Folder row to group it by flow \u2014 Checkout, Login \u2014 and a folder bar appears up here."})]})]})}var oe=V.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:24},record:{flexDirection:"row",alignItems:"center",gap:10,marginHorizontal:n.gutter,marginTop:8,marginBottom:4,paddingHorizontal:n.textInset,paddingVertical:12,borderRadius:n.radius.card,borderWidth:1,borderColor:n.color.simBorder,backgroundColor:n.color.simSoft},recordDot:{width:10,height:10,borderRadius:5,backgroundColor:n.color.sim},recordText:{flex:1,minWidth:0},recordTitle:{color:n.color.sim,fontSize:n.font.row,fontWeight:"700"},recordHint:{color:n.color.textSecondary,fontSize:n.font.micro,marginTop:2},headerButton:{width:32,height:32,borderRadius:8,backgroundColor:n.color.chip,borderWidth:1,borderColor:n.color.border,alignItems:"center",justifyContent:"center"},empty:{color:n.color.textTertiary,fontSize:n.font.control,lineHeight:18,paddingHorizontal:n.textInset,paddingVertical:14}});import{jsx as Pr}from"react/jsx-runtime";var ot={id:"scenarios",name:"SCENARIOS",description:"One-tap app states for QA, support and demos",slot:"both",icon:({size:e,color:t})=>Pr(Nt,{size:e,color:t||Wt}),component:tt,modal:{subtitle:"saved one-tap app states",searchable:true,searchPlaceholder:"Search name, tag, author\u2026"}};function vi(e={}){return e.scenarios?.length&&g.registerCodeScenarios(e.scenarios),{...ot,name:e.name??ot.name,description:e.description??ot.description,component:()=>Pr(tt,{currentBuild:e.currentBuild})}}import{useCallback as wi,useEffect as Si,useState as Ue}from"react";import{useSafeAreaInsets as xi}from"@buoy-gg/shared-ui/web";import{useCallback as Vr,useState as nt}from"react";import{openBuoyTool as Ti,useSafeAreaInsets as Ii}from"@buoy-gg/shared-ui/web";import{Fragment as Di,jsx as se,jsxs as zt}from"react/jsx-runtime";var Bt=52,ki=54;function Hr(){let e=Ir(),t=$t(),r=Ii({minBottom:0}),[o]=nt(()=>new fe.ValueXY({x:0,y:0})),[a,i]=nt(false),[l,c]=nt(false),s=Vr(async()=>{i(true);try{await ee.stop()}finally{i(false)}},[]),h=Vr(()=>{Ti("scenarios")||c(true)},[]),[u]=nt(()=>ut.create({onMoveShouldSetPanResponder:(A,y)=>Math.abs(y.dy)>6,onPanResponderMove:fe.event([null,{dy:o.y}],{useNativeDriver:false}),onPanResponderRelease:()=>o.extractOffset()})),d=e.status==="review";if(e.status!=="recording"&&!d)return null;let w=d?(e.draft??[]).filter(A=>A.enabled&&!A.noise).length:e.actions.length,v=e.actions[e.actions.length-1];return se(fe.View,{style:[W.wrap,{top:r.top+Bt+(t?ki:0)},{transform:o.getTranslateTransform()}],pointerEvents:"box-none",...u.panHandlers,children:zt(m,{style:[W.banner,d&&W.bannerReview],testID:"recording-banner",accessible:false,children:[se(m,{style:[W.dot,d&&W.dotReview]}),zt(m,{style:W.text,children:[se(p,{style:[W.title,d&&W.titleReview],children:d?`RECORDED \xB7 ${w} step${w===1?"":"s"}`:`\u25CF RECORDING \xB7 ${w} step${w===1?"":"s"}`}),se(p,{style:W.subtitle,numberOfLines:1,children:d?l?"Open Scenarios to review and save it.":"Review the steps, then save.":v?Ci(v.touch.target):"Drive the app \u2014 taps on Buoy itself are ignored."})]}),d?zt(Di,{children:[se(F,{style:W.discard,onPress:()=>void ee.cancel(),accessibilityRole:"button",accessibilityLabel:"Discard the recording",testID:"recording-discard",children:se(p,{style:W.discardText,children:"Discard"})}),l?null:se(F,{style:W.review,onPress:h,accessibilityRole:"button",accessibilityLabel:"Review the recorded steps",testID:"recording-review",children:se(p,{style:W.reviewText,children:"Review"})})]}):se(F,{style:W.stop,onPress:s,disabled:a,accessibilityRole:"button",accessibilityLabel:"Stop recording and review the steps",testID:"recording-stop",children:se(p,{style:W.stopText,children:a?"\u2026":"Stop"})})]})})}function Ci(e){return e.label??e.text??e.testID??e.name}var W=V.create({wrap:{position:"absolute",left:12,right:12,zIndex:10001,alignItems:"center"},banner:{flexDirection:"row",alignItems:"center",gap:8,maxWidth:520,width:"100%",paddingLeft:14,paddingRight:8,paddingVertical:8,borderRadius:22,backgroundColor:"rgba(20, 20, 20, 0.94)",borderWidth:V.hairlineWidth,borderColor:n.color.dangerBorder,...ht.select({ios:{shadowColor:"#000",shadowOpacity:.35,shadowRadius:12,shadowOffset:{width:0,height:6}},android:{elevation:8},default:{}})},dot:{width:8,height:8,borderRadius:4,backgroundColor:n.color.danger},text:{flex:1,minWidth:0},title:{color:n.color.danger,fontSize:10,fontWeight:"800",letterSpacing:.8},subtitle:{color:"rgba(255,255,255,0.85)",fontSize:11.5,marginTop:1},stop:{paddingHorizontal:12,height:28,borderRadius:14,alignItems:"center",justifyContent:"center",backgroundColor:"rgba(255, 59, 48, 0.15)"},stopText:{color:n.color.danger,fontSize:12,fontWeight:"700"},bannerReview:{borderColor:n.color.simBorder},dotReview:{backgroundColor:n.color.sim},titleReview:{color:n.color.sim},discard:{paddingHorizontal:12,height:28,borderRadius:14,alignItems:"center",justifyContent:"center",backgroundColor:"rgba(255,255,255,0.08)"},discardText:{color:"rgba(255,255,255,0.75)",fontSize:12,fontWeight:"600"},review:{paddingHorizontal:12,height:28,borderRadius:14,alignItems:"center",justifyContent:"center",backgroundColor:n.color.simSoft,borderWidth:V.hairlineWidth,borderColor:n.color.simBorder},reviewText:{color:n.color.sim,fontSize:12,fontWeight:"700"}});import{Fragment as $i,jsx as J,jsxs as at}from"react/jsx-runtime";function Ri(e){if(!e)return null;let t=e-Date.now();if(t<=0)return"expiring";let r=Math.floor(t/36e5),o=Math.round(t%36e5/6e4);return r?`auto-off ${r}h`:`auto-off ${o}m`}function jr(){let e=$t(),t=xi({minBottom:0}),[r,o]=Ue(false),[a]=Ue(()=>new fe.ValueXY({x:0,y:0})),i=wi(()=>{g.deactivate()},[]),[l,c]=Ue(false),[s,h]=Ue(false);Si(()=>{if(!s)return;let w=setTimeout(()=>h(false),2200);return()=>clearTimeout(w)},[s]);let[u]=Ue(()=>ut.create({onMoveShouldSetPanResponder:(w,v)=>Math.abs(v.dy)>6,onPanResponderMove:fe.event([null,{dy:a.y}],{useNativeDriver:false}),onPanResponderRelease:()=>{a.extractOffset()}}));if(!e)return null;let d=Ri(e.expiresAt);return r?J(fe.View,{style:[N.wrap,{top:t.top+Bt},{transform:a.getTranslateTransform()}],pointerEvents:"box-none",...u.panHandlers,children:at(F,{style:N.pill,onPress:()=>o(false),accessibilityRole:"button",accessibilityLabel:"Simulation active. Expand for details.",testID:"scenario-banner-pill",children:[J(m,{style:N.dot}),J(p,{style:N.pillText,children:"SIMULATED"})]})}):J(fe.View,{style:[N.wrap,{top:t.top+Bt},{transform:a.getTranslateTransform()}],pointerEvents:"box-none",...u.panHandlers,children:at(m,{style:N.banner,testID:"scenario-banner",accessible:false,children:[J(m,{style:N.dot}),at(F,{style:N.text,onPress:()=>o(true),accessibilityRole:"button",accessibilityLabel:`Simulated: ${e.name}. ${e.effects.length} changes.`,testID:"scenario-banner-body",children:[J(p,{style:N.title,children:"\u25B2 SIMULATED"}),J(p,{style:[N.subtitle,s&&N.hint],numberOfLines:1,children:s?"Hold \u23FB to stop the scenario":`${e.name} \xB7 ${e.effects.length} ${e.effects.length===1?"change":"changes"}`})]}),d?J(m,{style:N.expiry,children:J(p,{style:N.expiryText,children:d})}):null,J(F,{style:[N.off,l&&N.offHolding],onPress:()=>h(true),onLongPress:i,delayLongPress:600,onPressIn:()=>c(true),onPressOut:()=>c(false),accessibilityActions:[{name:"activate"},{name:"longpress"}],onAccessibilityAction:i,accessibilityHint:"Hold to stop",accessibilityRole:"button",accessibilityLabel:"Deactivate the scenario",testID:"scenario-stop-simulation",children:J(p,{style:N.offText,children:"\u23FB"})})]})})}var N=V.create({wrap:{position:"absolute",left:12,right:12,zIndex:9998,alignItems:"center"},banner:{flexDirection:"row",alignItems:"center",gap:8,maxWidth:520,width:"100%",paddingLeft:14,paddingRight:8,paddingVertical:8,borderRadius:22,backgroundColor:"rgba(20, 20, 20, 0.94)",borderWidth:V.hairlineWidth,borderColor:n.color.simBorder,...ht.select({ios:{shadowColor:"#000",shadowOpacity:.35,shadowRadius:12,shadowOffset:{width:0,height:6}},android:{elevation:8},default:{}})},pill:{flexDirection:"row",alignItems:"center",gap:6,paddingHorizontal:12,paddingVertical:6,borderRadius:22,backgroundColor:"rgba(20, 20, 20, 0.94)",borderWidth:V.hairlineWidth,borderColor:n.color.simBorder},pillText:{color:n.color.sim,fontSize:10,fontWeight:"800",letterSpacing:.8},dot:{width:7,height:7,borderRadius:2,backgroundColor:n.color.sim},text:{flex:1,minWidth:0},title:{color:n.color.sim,fontSize:10,fontWeight:"800",letterSpacing:.8},subtitle:{color:"rgba(255,255,255,0.85)",fontSize:11.5,marginTop:1},expiry:{paddingHorizontal:6,paddingVertical:2,borderRadius:6,backgroundColor:n.color.simSoft},expiryText:{color:n.color.sim,fontSize:10,fontWeight:"600"},off:{width:28,height:28,borderRadius:14,alignItems:"center",justifyContent:"center",backgroundColor:"rgba(255, 131, 41, 0.15)"},offHolding:{backgroundColor:n.color.sim},offText:{color:n.color.sim,fontSize:13},hint:{color:n.color.sim}});function Ai(){return at($i,{children:[J(jr,{}),J(Hr,{})]})}var Ei=64*1024,Li=256*1024;function he(e,t){let r=e?.[t];return typeof r=="string"&&r.trim()?r.trim():void 0}function Fr(e){let t=e?.params;if(!t||typeof t!="object")return{};let r={};for(let[o,a]of Object.entries(t))(typeof a=="string"||typeof a=="number"||typeof a=="boolean")&&(r[o]=a);return r}var zi=8*1024;function Ot(e){return{id:e.id,name:e.name,description:e.description,version:e.version,source:e.source,author:e.author,folder:e.folder,tags:e.tags,vars:e.vars,stepCount:e.steps.length,expectedOutcome:e.expectedOutcome,authoredAgainst:e.authoredAgainst,verifiedAt:e.verifiedAt,unsavedToRepo:e.unsavedToRepo,usage:e.usage,createdAt:e.createdAt,updatedAt:e.updatedAt,steps:e.steps.map(t=>JSON.stringify(t.params??{}).length>zi?{...t,params:void 0,paramsOmitted:true}:t),stepLines:e.steps.map(t=>({label:$e(t),durability:Ne(t)}))}}function Bi(e){let t=[];(!e.id||typeof e.id!="string")&&t.push("A scenario needs a string `id`."),(!e.name||typeof e.name!="string")&&t.push("A scenario needs a `name`."),!Array.isArray(e.steps)||!e.steps.length?t.push("A scenario needs at least one step."):e.steps.forEach((o,a)=>{if(!o||typeof o!="object"){t.push(`Step ${a+1} is not an object.`);return}(!o.tool||!o.action)&&t.push(`Step ${a+1} needs both \`tool\` and \`action\`.`);let i=JSON.stringify(o.params??{}).length;i>Ei&&t.push(`Step ${a+1} is ${Math.round(i/1024)}KB \u2014 over the 64KB limit. Use a smaller response body.`)}),e.vars&&!Array.isArray(e.vars)&&t.push("`vars` must be an array.");let r=JSON.stringify(e).length;return r>Li&&t.push(`The scenario is ${Math.round(r/1024)}KB \u2014 over the 256KB limit.`),t}function Nr(){let e=g.getState();return{code:e.code.map(Ot),device:e.device.map(Ot),drafts:e.drafts.map(Ot),active:e.active,runState:e.runState,hasLoaded:e.hasLoaded,folders:g.folders()}}var Oi={dispose:e=>g.disposeAccountSession(e),version:1,getSnapshot:()=>Nr(),subscribe:e=>g.subscribe(e),actions:{listScenarios:()=>Nr(),getScenario:e=>{let t=he(e,"id");if(!t)throw new Error("getScenario requires an `id`");let r=g.find(t);if(!r)throw new Error(`No scenario "${t}"`);return{scenario:r}},save:async e=>{let t=(e??{}).scenario;if(!t)return{ok:false,error:"save requires a `scenario`."};let r=Bi(t);if(r.length)return{ok:false,errors:r};let o=Date.now(),a={id:t.id,name:t.name,description:t.description,version:t.version??1,source:"draft",author:t.author??"remote",vars:t.vars??[],steps:t.steps,undoSteps:t.undoSteps,folder:t.folder,tags:t.tags,expectedOutcome:t.expectedOutcome,authoredAgainst:t.authoredAgainst,unsavedToRepo:true,createdAt:o,updatedAt:o,usage:{runs:0}};return{ok:true,savedAsDraft:true,id:(await g.saveScenario(a,{asDraft:true})).id,message:"Saved as a draft. Open Scenarios on the device to review and accept it."}},acceptDraft:async e=>{let t=he(e,"id");if(!t)throw new Error("acceptDraft requires an `id`");return{ok:true,id:(await g.acceptDraft(t)).id}},discardDraft:async e=>{let t=he(e,"id");if(!t)throw new Error("discardDraft requires an `id`");return await g.discardDraft(t),{ok:true,id:t}},preview:e=>{let t=he(e,"id");if(!t)throw new Error("preview requires an `id`");let r=g.find(t);if(!r)throw new Error(`No scenario "${t}"`);let o=je(r.vars,Fr(e)),a=g.checkBeforeRun(r,o);return{willDo:r.steps.map(i=>({label:$e(i,me(i.params??{},o)),durability:Ne(i)})),values:o,ok:a.ok,errors:a.errors,warnings:a.warnings,conflict:a.conflict,expectedOutcome:r.expectedOutcome}},run:async e=>{let t=he(e,"id");if(!t)throw new Error("run requires an `id`");let r=Fr(e),o=g.find(t);if(!o)throw new Error(`No scenario "${t}"`);let a=g.checkBeforeRun(o,r);return a.ok?await g.run(t,r):{ok:false,preflightErrors:a.errors,conflict:a.conflict}},deactivate:async()=>({ok:true,report:await g.deactivate()}),delete:async e=>{let t=he(e,"id");if(!t)throw new Error("delete requires an `id`");return await g.deleteScenario(t),{ok:true,id:t}},listFolders:()=>({folders:g.folders()}),setFolder:async e=>{let t=he(e,"id");if(!t)throw new Error("setFolder requires an `id`");let r=he(e,"folder"),o=await g.setFolder(t,r);return{ok:true,id:o.id,folder:o.folder??null}},getActive:()=>({active:g.getState().active}),export:e=>{let t=he(e,"id");if(!t)throw new Error("export requires an `id`");let r=g.find(t);if(!r)throw new Error(`No scenario "${t}"`);return{json:JSON.stringify(r,null,2)}}}};import{jsx as Pi}from"react/jsx-runtime";function Vi({currentBuild:e}){return Pi(tt,{currentBuild:e})}g.ensureLoaded();export{bn as DURABILITY_LABEL,Dt as MAX_DEVICE_SCENARIOS,Cn as MAX_FOLDER_LENGTH,$r as MacroReviewScreen,Hr as RecordingBanner,Wt as SCENARIOS_ICON_COLOR,ir as SCENARIO_TIMEOUT_MS,rr as STEP_CATALOG,vt as STEP_TIMEOUT_MS,jr as ScenarioBanner,tt as ScenariosBody,Nt as ScenariosIcon,Ai as ScenariosOverlay,Vi as ScenariosToolView,ur as UNGROUPED,Ce as catalogEntry,Xt as coerceVarValue,He as collectPlaceholders,wr as condense,nr as conflictKeysOverlap,Tt as countInFolder,vi as createScenariosTool,$n as defineScenario,$e as describeStep,br as describeTarget,gr as humanizeTestID,xt as inFolder,me as interpolate,ye as interpolateString,or as isAdvancedStep,hr as listFolders,Ct as macroToSteps,hn as missingVarKeys,le as normalizeFolder,lr as preflight,ee as recorderStore,En as replaceScenariosFromSnapshot,St as resolveFolder,je as resolveVarValues,We as revertEffects,wt as runScenario,g as scenariosStore,Oi as scenariosSyncAdapter,ot as scenariosToolPreset,vr as selectorFor,Rn as setRemoteScenariosHandler,bt as stepConflictKeys,Ne as stepDurability,kt as titleFor,$t as useActiveScenario,Tr as useScenariosRunState,xr as useScenariosState};
1
+ "use client";var Xt=Object.defineProperty;var oo=Object.getOwnPropertyDescriptor;var ao=Object.getOwnPropertyNames;var no=Object.prototype.hasOwnProperty;var io=(e,t)=>{for(var r in t)Xt(e,r,{get:t[r],enumerable:true})},Yt=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of ao(t))!no.call(e,n)&&n!==r&&Xt(e,n,{get:()=>t[n],enumerable:!(o=oo(t,n))||o.enumerable});return e},so=(e,t,r)=>(Yt(e,t,"default"),r&&Yt(r,t,"default"));var Qt=(()=>{try{let e=globalThis.Capacitor;if(e&&typeof e.isNativePlatform=="function"&&e.isNativePlatform())return e.DEBUG===true}catch{}return process.env.NODE_ENV!=="production"})();typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);import{ScenariosIcon as Zt,SCENARIOS_ICON_COLOR as er}from"@buoy-gg/floating-tools-core/web";import{useCallback as Se,useEffect as lo,useMemo as co,useState as et}from"react";var tr={};io(tr,{AccessibilityInfo:()=>po,ActivityIndicator:()=>Tt,Alert:()=>We,Animated:()=>ge,AppRegistry:()=>go,AppState:()=>yo,Appearance:()=>mo,BackHandler:()=>bo,Button:()=>ha,CheckBox:()=>Bo,Clipboard:()=>vo,DeviceEventEmitter:()=>Jo,Dimensions:()=>wo,Easing:()=>So,FlatList:()=>Lo,I18nManager:()=>xo,Image:()=>zo,ImageBackground:()=>Po,InteractionManager:()=>To,Keyboard:()=>Io,KeyboardAvoidingView:()=>Oo,LayoutAnimation:()=>Do,Linking:()=>ko,LogBox:()=>_o,Modal:()=>ua,NativeEventEmitter:()=>Co,NativeModules:()=>fo,PanResponder:()=>wt,Picker:()=>Vo,PixelRatio:()=>Ro,Platform:()=>St,Pressable:()=>da,ProgressBar:()=>Ho,RefreshControl:()=>Fo,SafeAreaView:()=>jo,ScrollView:()=>ye,SectionList:()=>Wo,Share:()=>$o,StatusBar:()=>No,StyleSheet:()=>H,Switch:()=>sr,Text:()=>f,TextInput:()=>tt,Touchable:()=>Mo,TouchableHighlight:()=>la,TouchableNativeFeedback:()=>Ko,TouchableOpacity:()=>W,TouchableWithoutFeedback:()=>ca,UIManager:()=>Ao,Vibration:()=>Eo,View:()=>g,VirtualizedList:()=>qo,YellowBox:()=>Uo,findNodeHandle:()=>fa,unstable_createElement:()=>ho,useColorScheme:()=>Go,useLocaleContext:()=>Xo,useWindowDimensions:()=>Yo});so(tr,uo);import*as uo from"react-native-web";import{unstable_createElement as ho,NativeModules as fo,AccessibilityInfo as po,Appearance as mo,AppRegistry as go,AppState as yo,BackHandler as bo,Clipboard as vo,Dimensions as wo,Easing as So,I18nManager as xo,Keyboard as Io,InteractionManager as To,LayoutAnimation as Do,Linking as ko,NativeEventEmitter as Co,PanResponder as wt,PixelRatio as Ro,Platform as St,Share as $o,UIManager as Ao,Vibration as Eo,CheckBox as Bo,FlatList as Lo,Image as zo,ImageBackground as Po,KeyboardAvoidingView as Oo,Picker as Vo,ProgressBar as Ho,RefreshControl as Fo,SafeAreaView as jo,SectionList as Wo,StatusBar as No,Touchable as Mo,TouchableNativeFeedback as Ko,VirtualizedList as qo,YellowBox as Uo,LogBox as _o,DeviceEventEmitter as Jo,useColorScheme as Go,useLocaleContext as Xo,useWindowDimensions as Yo}from"react-native-web";import*as G from"react-native-web";import{createElement as xt,forwardRef as rr,useCallback as Qo,useRef as Zo}from"react";import{useEffect as ea,useState as ta}from"react";import{createPortal as ra}from"react-dom";var oa='-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';import{jsx as aa}from"react/jsx-runtime";var je=Symbol.for("@buoy-gg/portal-host"),or=e=>{if(!(e instanceof Element))return false;if(e.closest("input, textarea, select"))return true;let t=e.closest("[contenteditable]")?.getAttribute("contenteditable")?.toLowerCase();return t===""||t==="true"||t==="plaintext-only"};function ar(){let e=document;if(e[je])return e[je].host;let t=document.createElement("div");t.dataset.buoyPortalHost="",Object.assign(t.style,{position:"fixed",inset:"0",zIndex:"2147483647",pointerEvents:"none",fontFamily:oa});let r=()=>{let d=document.fullscreenElement,h=d&&d.tagName!=="CANVAS"?d:document.body;t.parentElement!==h&&h.appendChild(t)},o=new Map,n=d=>{(!t.contains(d.target)||!or(d.target))&&o.set(d.code||d.key,{key:d.key,code:d.code,location:d.location,keyCode:d.keyCode,which:d.which,altKey:d.altKey,ctrlKey:d.ctrlKey,metaKey:d.metaKey,shiftKey:d.shiftKey})},i=d=>{o.delete(d.code||d.key)},c=()=>o.clear(),s=()=>{let d=[...o.values()];o.clear();for(let h of d)document.dispatchEvent(new KeyboardEvent("keyup",{...h,bubbles:true}))},l=d=>{or(d.target)&&d.stopPropagation()},u=d=>d.stopPropagation();return r(),document.addEventListener("fullscreenchange",r),document.addEventListener("keydown",n,true),document.addEventListener("keyup",i,true),window.addEventListener("blur",c),t.addEventListener("focusin",s),t.addEventListener("keydown",l),t.addEventListener("keyup",l),t.addEventListener("keypress",l),t.addEventListener("wheel",u,{passive:true}),e[je]={host:t,users:0,dispose:()=>{document.removeEventListener("fullscreenchange",r),document.removeEventListener("keydown",n,true),document.removeEventListener("keyup",i,true),window.removeEventListener("blur",c),t.remove(),delete e[je]}},t}function na({children:e}){let[t,r]=ta(null);return ea(()=>{let o=ar(),n=document[je];return n.users++,r(o),()=>{--n.users===0&&n.dispose()}},[]),t?ra(aa("div",{"data-buoy-root":"",style:{display:"contents",pointerEvents:"auto"},children:e}),t):null}var Ce=G,ia=["shadowColor","shadowOffset","shadowOpacity","shadowRadius","textShadowColor","textShadowOffset","textShadowRadius"],Re=e=>typeof e=="number"?`${e}px`:e;function It(e){if(Array.isArray(e)){let h=e.map(It);return h.some((v,y)=>v!==e[y])?h:e}if(!e||typeof e!="object"||!ia.some(h=>e[h]!=null))return e;let{shadowColor:t,shadowOffset:r,shadowOpacity:o,shadowRadius:n,textShadowColor:i,textShadowOffset:c,textShadowRadius:s,...l}=e;if(t!=null||r!=null||o!=null||n!=null){let h=t??"black",v=o==null?h:`color-mix(in srgb, ${h} ${Math.min(o,1)*100}%, transparent)`,y=`${Re(r?.width??0)} ${Re(r?.height??0)} ${Re(n??0)} ${v}`;l.boxShadow=typeof l.boxShadow=="string"?`${l.boxShadow}, ${y}`:l.boxShadow??y}let{width:u=0,height:d=0}=c??{};if(i&&(u||d||s)){let h=`${Re(u)} ${Re(d)} ${Re(s??0)} ${i}`;l.textShadow=l.textShadow?`${l.textShadow}, ${h}`:h}return l}var sa=Ce.StyleSheet.create({auto:{pointerEvents:"auto"},none:{pointerEvents:"none"},"box-none":{pointerEvents:"box-none"},"box-only":{pointerEvents:"box-only"}});function nr(e,t){if(typeof e=="function")return o=>nr(e(o),t);let r=It(e);return t?[r,sa[t]]:r}var H={...Ce.StyleSheet,create:e=>Ce.StyleSheet.create(Object.fromEntries(Object.entries(e).map(([t,r])=>[t,It(r)])))};function ee(e){let t=rr((o,n)=>{let{accessibilityState:i,accessibilityValue:c,pointerEvents:s,...l}=o;for(let d of["busy","checked","disabled","expanded","selected"])i?.[d]!==void 0&&l[`aria-${d}`]===void 0&&(l[`aria-${d}`]=i[d]);for(let[d,h]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))c?.[d]!==void 0&&l[`aria-${h}`]===void 0&&(l[`aria-${h}`]=c[d]);let u=nr(l.style,s);return u!==l.style&&(l.style=u),xt(e,{...l,ref:n})}),r=e.State;return r&&Object.assign(t,{State:r}),t.displayName=e.displayName??e.name??"NativeWebView",t}var g=ee(G.View),f=ee(G.Text),ge={...Ce.Animated,View:Ce.Animated.createAnimatedComponent(g),Text:Ce.Animated.createAnimatedComponent(f)},tt=ee(G.TextInput),W=ee(G.TouchableOpacity),la=ee(G.TouchableHighlight),ca=ee(G.TouchableWithoutFeedback),da=ee(G.Pressable),ye=ee(G.ScrollView),ir=rr((e,t)=>{let r=Zo(null),o=Qo(n=>{if(n){let i=n;for(;i.parentElement&&i.parentElement!==document.body;)i=i.parentElement;i.parentElement===document.body&&(r.current=i,Object.assign(i.style,{position:"relative",zIndex:"2147483647",pointerEvents:"auto"}),ar().appendChild(i))}else r.current&&(document.body.appendChild(r.current),r.current=null);typeof t=="function"?t(n):t&&(t.current=n)},[t]);return xt(na,null,xt(G.Modal,{...e,ref:o}))});ir.displayName="Modal";var ua=ee(ir),sr=ee(G.Switch),Tt=ee(G.ActivityIndicator),ha=ee(G.Button),fa=G.findNodeHandle,We={alert(e,t,r,o){if(typeof document>"u")return;let n=document.createElement("dialog");n.dataset.buoyRoot="",n.setAttribute("aria-label",e),n.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let i=document.createElement("h2");if(i.textContent=e,i.style.cssText="font-size:18px;margin:0 0 12px",n.appendChild(i),t){let u=document.createElement("p");u.textContent=t,u.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",n.appendChild(u)}let c=document.createElement("div");c.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let s=r?.length?r:[{text:"OK"}],l=()=>{n.close?.(),n.remove()};for(let u of s){let d=document.createElement("button");d.type="button",d.textContent=u.text??"OK",d.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${u.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,d.onclick=()=>{l(),u.onPress?.()},c.appendChild(d)}n.addEventListener("cancel",u=>{u.preventDefault(),o?.cancelable!==false&&(l(),o?.onDismiss?.())}),n.appendChild(c),document.body.appendChild(n),n.showModal?n.showModal():n.setAttribute("open","")}};import{Box as pa,FileText as ma,RefreshCw as ga,Smartphone as ya,ToolbarCopyButton as ba,Users as va,subscribeAccountAccess as wa,Zap as Sa,useLimit as xa,useSafeAreaInsets as Ia}from"@buoy-gg/shared-ui/web";import{useToolHeader as Ta,useToolHost as Da}from"@buoy-gg/core/web";var lr=/\{\{\s*(\w+)\s*\}\}/g,ka=/^\{\{\s*(\w+)\s*\}\}$/;function Ne(e,t=new Set){if(typeof e=="string"){for(let r of e.matchAll(lr))t.add(r[1]);return t}if(Array.isArray(e)){for(let r of e)Ne(r,t);return t}if(e&&typeof e=="object")for(let r of Object.values(e))Ne(r,t);return t}function xe(e,t){let r=e.match(ka);return r&&r[1]in t?t[r[1]]:e.replace(lr,(o,n)=>n in t?String(t[n]):o)}function be(e,t){if(typeof e=="string")return xe(e,t);if(Array.isArray(e))return e.map(r=>be(r,t));if(e&&typeof e=="object"){let r={};for(let[o,n]of Object.entries(e))r[o]=be(n,t);return r}return e}function Me(e,t={}){let r={};for(let o of e)o.default!==void 0&&(r[o.key]=o.default);for(let[o,n]of Object.entries(t))n!==void 0&&(r[o]=n);return r}function Ca(e,t){return e.filter(r=>!(r.key in t)).map(r=>r.key)}function cr(e,t){if(e.type==="number"){let r=typeof t=="number"?t:Number(t);return Number.isFinite(r)?r:0}return e.type==="boolean"?typeof t=="boolean"?t:t==="true"||t===1:t}import{devToolsStorageKeys as Dt,persistentStorage as ve,dispatchToolAction as $e,assertAccountAccess as kt,hasAccountAccess as dr,getToolAdapters as Ra,listToolActions as $a,listToolIds as ur,waitForToolRegistry as Aa}from"@buoy-gg/shared-ui/web";var Ie="scenario",E=(e,t="")=>typeof e=="string"?e:e==null?t:String(e);function hr(e){let t=e.rule;return t&&typeof t=="object"?t:e}function Ea(e){let t=hr(e),r=Array.isArray(t.methods)?t.methods.join("/"):"any",o=E(t.urlPattern,"(no pattern)"),n=E(t.kind,"respond");if(n==="fail")return`${r} ${o} \u2192 fail (${E(t.failKind,"network")})`;if(n==="delay")return`${r} ${o} \u2192 delay ${t.delayMs??0}ms`;let i=typeof t.status=="number"?t.status:200,c=t.body!=null?", replaced body":"";return`${r} ${o} \u2192 respond ${i}${c}`}var fr=[{tool:"network",action:"upsertOverrideRule",title:"Override a request",durability:"durable",describe:Ea,conflictKeys:e=>{let t=hr(e),r=E(t.urlPattern);return r?[`net:${r}`]:[]}},{tool:"network",action:"deleteOverrideRule",title:"Remove an override",durability:"one-shot",describe:e=>`Remove override rule ${E(e.id,"?")}`},{tool:"network",action:"setOverridesEnabled",title:"Toggle all overrides",durability:"session",describe:e=>`Turn overrides ${e.enabled===false?"off":"on"}`},{tool:"storage",action:"async.setItem",title:"Set storage value",durability:"durable",describe:e=>`Set storage ${E(e.key,"?")}`,conflictKeys:e=>e.key?[`storage:${E(e.key)}`]:[]},{tool:"storage",action:"async.removeItem",title:"Remove storage key",durability:"durable",describe:e=>`Remove storage ${E(e.key,"?")}`,conflictKeys:e=>e.key?[`storage:${E(e.key)}`]:[]},{tool:"storage",action:"async.multiSet",title:"Set several storage values",durability:"durable",describe:e=>{let t=Array.isArray(e.pairs)?e.pairs.length:0;return`Set ${t} storage key${t===1?"":"s"}`},conflictKeys:e=>Array.isArray(e.pairs)?e.pairs.map(t=>Array.isArray(t)?`storage:${E(t[0])}`:"").filter(Boolean):[]},{tool:"storage",action:"mmkv.set",title:"Set MMKV value",durability:"durable",describe:e=>`Set MMKV ${E(e.key,"?")}`,conflictKeys:e=>e.key?[`mmkv:${E(e.key)}`]:[]},{tool:"impersonate",action:"startImpersonation",title:"Impersonate a user",durability:"durable",describe:e=>{let t=e.user;return`Impersonate ${E(t?.name)||E(t?.email)||E(t?.id)||"a user"}`},conflictKeys:()=>["impersonation"]},{tool:"impersonate",action:"stopImpersonation",title:"Stop impersonating",durability:"one-shot",describe:()=>"Stop impersonating",conflictKeys:()=>["impersonation"]},{tool:"route-events",action:"navigate",title:"Go to a screen",durability:"one-shot",describe:e=>`${e.replace?"Replace with":"Go to"} ${E(e.path,"?")}`},{tool:"query",action:"setQueryData",title:"Poke the query cache",durability:"transient",describe:e=>`Poke ${E(e.queryKey,"?")} cache (until next refetch)`},{tool:"query",action:"invalidate",title:"Refetch queries",durability:"one-shot",describe:e=>`Refetch ${E(e.queryKey,"all queries")}`},{tool:"time-machine",action:"restore",title:"Restore a snapshot",durability:"durable",describe:e=>`Restore snapshot ${E(e.id,"?")}`},{tool:Ie,action:"wait",title:"Wait",durability:"one-shot",describe:e=>`Wait ${typeof e.ms=="number"?e.ms:0}ms`},{tool:"highlight-updates",action:"tapElement",title:"Tap something on screen",durability:"one-shot",describe:e=>{let t=E(e.testID)||E(e.query)||"an element";return typeof e.text=="string"?`Type \u201C${e.text}\u201D into ${t}`:e.value!==void 0?`Set ${t} to ${JSON.stringify(e.value)}`:e.longPress?`Press and hold \u201C${t}\u201D`:`Tap \u201C${t}\u201D`}},{tool:Ie,action:"waitFor",title:"Wait for a screen",durability:"one-shot",describe:e=>e.route?`Wait for ${E(e.route)}`:`Wait for \u201C${E(e.element,"?")}\u201D`},{tool:"zustand",action:"setState",title:"Set a store's state",durability:e=>e.persisted?"durable":"session",describe:e=>`Set ${E(e.storeName,"a store")}`,conflictKeys:e=>e.storeName?[`zustand:${E(e.storeName)}`]:[]}],Ba=new Map(fr.map(e=>[`${e.tool}.${e.action}`,e]));function Ae(e,t){return Ba.get(`${e}.${t}`)}function Ee(e,t){if(e.label)return e.label;let r=Ae(e.tool,e.action),o=t??e.params??{};if(!r)return`${e.tool}.${e.action}`;try{return r.describe(o)}catch{return`${e.tool}.${e.action}`}}function Ke(e){let t=Ae(e.tool,e.action);if(!t)return"one-shot";if(typeof t.durability!="function")return t.durability;try{return t.durability(e.params??{})}catch{return"one-shot"}}function pr(e){return!e.label&&!Ae(e.tool,e.action)}function Ct(e,t){let r=Ae(e.tool,e.action);if(!r?.conflictKeys)return[];try{return r.conflictKeys(t??e.params??{})}catch{return[]}}function mr(e,t){if(e===t)return true;let r="net:";if(!e.startsWith(r)||!t.startsWith(r))return false;let o=e.slice(r.length),n=t.slice(r.length);return gr(o,n)||gr(n,o)}function gr(e,t){try{let r=e.replace(/[[\]{}()\\.^$+|\-,?]/g,"\\$&").split("*").join(".*"),o=t.split("*").join("x");return new RegExp(`^${r}$`).test(o)}catch{return false}}var La={durable:"survives refresh & restart",session:"until the app restarts",transient:"until next refetch","one-shot":"one-shot"};var Rt=1e4,yr=6e4,br=6e3,za=150,Pa=new Set(["scenarios"]);function Oa(e){return e.action==="reloadApp"||e.action==="reload"}function vr(e,t,r){let o=[],n=[];e.source==="draft"&&o.push("This scenario is still a draft \u2014 review and accept it before running."),e.steps.length||o.push("This scenario has no steps.");let i=new Set(e.vars.map(h=>h.key)),c=new Set;for(let h of e.steps)Ne(h.params,c);Ne(e.name,c);for(let h of c)i.has(h)?h in t||o.push(`Variable "${h}" needs a value.`):o.push(`{{${h}}} is used but never declared as a variable.`);for(let h of i)c.has(h)||n.push(`Variable "${h}" is never used.`);let s=new Set(r.availableTools);e.steps.forEach((h,v)=>{let y=`Step ${v+1}`;if(Pa.has(h.tool)){o.push(`${y}: a scenario cannot run another scenario.`);return}if(h.tool===Ie)return;if(!s.has(h.tool)){o.push(`${y}: "${h.tool}" is not installed in this app, so this step cannot run.`);return}let C=r.availableActions?.[h.tool];C&&!C.includes(h.action)&&o.push(`${y}: "${h.tool}" has no action "${h.action}".`),Oa(h)&&v!==e.steps.length-1&&o.push(`${y}: reloading the app is only allowed as the last step.`),Ae(h.tool,h.action)||n.push(`${y}: ${h.tool}.${h.action} is an advanced step \u2014 its effects are not described or automatically undone.`)});let l=new Set;for(let h of e.steps)for(let v of Ct(h,be(h.params,t)))l.add(v);let u=null,d=r.activeScenario;if(d&&d.scenarioId!==e.id){let h=d.conflictKeys.filter(v=>[...l].some(y=>mr(v,y)));h.length&&(u={activeScenarioId:d.scenarioId,activeName:d.name,overlaps:h})}return r.extraErrors?.length&&o.push(...r.extraErrors),{ok:o.length===0,errors:o,warnings:n,conflict:u,conflictKeys:[...l]}}function wr(e,t,r,o){return new Promise((n,i)=>{let c=()=>{clearTimeout(s),i(new Error("Scenario cancelled"))},s=setTimeout(()=>{o?.removeEventListener("abort",c),i(new Error(`${r} timed out after ${t}ms`))},t);o?.aborted?c():o?.addEventListener("abort",c,{once:true}),e.then(l=>{clearTimeout(s),o?.removeEventListener("abort",c),n(l)},l=>{clearTimeout(s),o?.removeEventListener("abort",c),i(l)})})}function Sr(e,t){return new Promise((r,o)=>{let n=()=>{clearTimeout(i),o(new Error("Scenario cancelled"))},i=setTimeout(()=>{t?.removeEventListener("abort",n),r()},e);t?.aborted?n():t?.addEventListener("abort",n,{once:true})})}async function Va(e,t,r,o){let n=typeof e.route=="string"?e.route:null,i=typeof e.element=="string"?e.element:null;if(!n&&!i)return;let c=Date.now()+r,s="nothing";for(;Date.now()<c;){if(o?.aborted)throw new Error("Scenario cancelled");if(n){let l=await t("route-events","getCurrentRoute").catch(()=>null);if(l?.path===n)return;typeof l?.path=="string"&&(s=l.path)}else if(i){let l=await t("highlight-updates","describeScreen").catch(()=>null),u=i.toLowerCase();if((l?.elements??[]).some(d=>[d.testID,d.text,d.label].some(h=>typeof h=="string"&&h.toLowerCase().includes(u))))return;s=`${l?.elements?.length??0} elements`}await Sr(za,o)}throw new Error(n?`Still on ${s} after ${r}ms \u2014 expected ${n}`:`\u201C${i}\u201D never appeared within ${r}ms`)}function Ha(e){if(e&&typeof e=="object"&&"ok"in e){let t=e;if(t.ok===false)return typeof t.error=="string"?t.error:"The step was rejected."}return null}function Fa(e,t,r,o){if(e.tool==="network"&&e.action==="upsertOverrideRule"){let i=r?.rule?.id;return typeof i=="string"?{kind:"override-rule",label:o,ruleId:i}:null}if(e.tool==="impersonate"&&e.action==="startImpersonation"){let i=t.user,c=typeof i?.id=="string"?i.id:void 0;return{kind:"impersonation",label:o,userId:c}}if(e.tool==="storage"){let[i,c=""]=e.action.split(".");if(/^(setItem|removeItem|multiSet|multiRemove|clear|set|remove)$/.test(c)){let s=typeof t.key=="string"?t.key:"";if(!s&&Array.isArray(t.pairs)){let l=t.pairs[0];s=Array.isArray(l)?String(l[0]??""):""}return!s&&Array.isArray(t.keys)&&(s=String(t.keys[0]??"")),!s&&c==="clear"&&(s="(all keys)"),{kind:"storage-write",label:o,backend:i,key:s}}}let n=ja(e,t);return n!==null?{kind:"state-write",label:o,tool:e.tool,store:n}:e.tool===Ie?null:{kind:"transient",label:o,tool:e.tool,action:e.action}}function ja(e,t){let r=o=>typeof t[o]=="string"?t[o]:"";if(e.tool==="zustand"&&e.action==="setState")return r("storeName")||"a store";if(e.tool==="jotai"&&e.action==="setAtom")return r("atom")||r("atomName")||"an atom";if(e.tool==="redux"&&e.action==="dispatch"){let o=t.action;return typeof o?.type=="string"?o.type:"the redux store"}return null}async function Wa(e,t){let r=e.user,o=r?.id;if(!r||typeof o!="string"&&typeof o!="number")return e;let n=[r.email,r.name,r.displayName,o].filter(i=>typeof i=="string"||typeof i=="number");for(let i of n)try{let c=await t("impersonate","searchUsers",{query:String(i)}),s=Array.isArray(c)?c.find(l=>String(l?.id)===String(o)):void 0;if(s)return{...e,user:s}}catch{}return e}async function $t(e,t,r,o){let n=[],i=[],c=Date.now(),s=false;for(let l=0;l<e.steps.length;l++){let u=e.steps[l],d=be(u.params??{},t),h=Ee(u,d);if(s){n.push({id:u.id,label:h,ok:false,skipped:true,ms:0});continue}o?.onStep?.(l,"start");let v=Date.now();try{if(o?.signal?.aborted)throw new Error("Scenario cancelled");if(Date.now()-c>yr)throw new Error("Scenario exceeded its overall time budget");let y;if(u.tool===Ie&&u.action==="wait"){let R=typeof d.ms=="number"?d.ms:0;await Sr(Math.min(R,Rt),o?.signal)}else if(u.tool===Ie&&u.action==="waitFor")await wr(Va(d,r,u.timeoutMs??br,o?.signal),u.timeoutMs??br,h,o?.signal);else{let R=u.tool==="impersonate"&&u.action==="startImpersonation"?await Wa(d,r):d;y=await wr(Promise.resolve(r(u.tool,u.action,R)),u.timeoutMs??Rt,h,o?.signal);let V=Ha(y);if(V)throw new Error(V)}let C=Date.now()-v;n.push({id:u.id,label:h,ok:true,ms:C});let w=Fa(u,d,y,h);w&&i.push(w),o?.onStep?.(l,"ok")}catch(y){let C=Date.now()-v,w=y instanceof Error?y.message:String(y);n.push({id:u.id,label:h,ok:false,error:w,ms:C}),o?.onStep?.(l,"error",w),s=true}}return{ok:!s,scenarioId:e.id,name:String(xe(e.name,t)),steps:n,effects:i}}async function qe(e,t){let r=0,o=false,n=0,i=[],c=[],s=[];for(let l of e)try{l.kind==="override-rule"?(await t("network","deleteOverrideRule",{id:l.ruleId}),r++):l.kind==="impersonation"?(await t("impersonate","stopImpersonation",{}),o=true):l.kind==="storage-write"?l.key&&i.push(l.key):l.kind==="state-write"?l.store&&c.push(l.store):n++}catch(u){s.push(u instanceof Error?u.message:String(u))}return{removedRules:r,stoppedImpersonation:o,clearedTransients:n,unrestoredStorageKeys:i,unrestoredState:c,errors:s}}var xr="Ungrouped",Na=32;function ue(e){return typeof e!="string"?void 0:e.replace(/\s+/g," ").trim().slice(0,32)||void 0}function At(e,t){let r=ue(e);return r?t.find(o=>o.toLowerCase()===r.toLowerCase())??r:void 0}function Ir(e){let t=new Map;for(let r of e){let o=ue(r.folder);if(!o)continue;let n=o.toLowerCase();t.has(n)||t.set(n,o)}return[...t.values()].sort((r,o)=>r.localeCompare(o,void 0,{sensitivity:"base"}))}function Et(e,t){let r=ue(e.folder);return t===void 0?!r:!!r&&r.toLowerCase()===t.toLowerCase()}function Bt(e,t){return e.reduce((r,o)=>Et(o,t)?r+1:r,0)}function rt(e=[],t){return e.map((r,o)=>({...r,id:r.id??`${t}${o+1}`}))}function Ma(e){let t=Date.now();return{id:e.id,name:e.name,description:e.description,version:e.version??1,source:"code",author:e.author,vars:e.vars??[],steps:rt(e.steps,"s"),undoSteps:e.undoSteps?rt(e.undoSteps,"u"):void 0,tags:e.tags,folder:ue(e.folder),expectedOutcome:e.expectedOutcome,authoredAgainst:e.authoredAgainst,createdAt:t,updatedAt:t,usage:{runs:0}}}import{getBuoyAppId as Ka,getTeamCredential as qa}from"@buoy-gg/shared-ui/web";var Ua=15e3,_a="Sign in with a Business team account to share scenarios with your team.",Ja="Buoy can't tell which app this is. Pass signIn={{ appId }} to FloatingDevTools to name it.";function ot(){return{credential:qa,appId:Ka,fetch:(e,t)=>fetch(e,t)}}function at(e){return e.credential()?.appId??e.appId()}async function Lt(e,t,r){let o=r.credential();if(!o)return{ok:false,code:"no-team",message:_a};let n=o.appId??r.appId();if(!n)return{ok:false,code:"no-app",message:Ja};let i=typeof AbortController<"u"?new AbortController:void 0,c=setTimeout(()=>i?.abort(),Ua),s,l;try{let d=await r.fetch(`${o.origin.replace(/\/$/,"")}${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({access_token:o.token,app:n,...t}),signal:i?.signal});s=d.status,l=await d.json().catch(()=>null)}catch{return{ok:false,code:"network",message:"Buoy could not reach buoy.gg. Check the connection and try again."}}finally{clearTimeout(c)}if(s===200&&l&&typeof l=="object")return{ok:true,value:l};let u=l?.error_description;return s>=500||s===429?{ok:false,code:"network",message:typeof u=="string"?u:"buoy.gg is busy. Try again in a minute."}:{ok:false,code:"refused",message:typeof u=="string"?u:"buoy.gg said no to that."}}function Tr(e){let t=e;return!!t&&typeof t.id=="string"&&!!t.scenario&&typeof t.scenario=="object"&&Array.isArray(t.scenario.steps)}async function Ga(e=ot()){let t=await Lt("/api/scenarios/team/pull",{},e);if(!t.ok)return t;let r=t.value;return{ok:true,value:{scenarios:Array.isArray(r.scenarios)?r.scenarios.filter(Tr):[],you:typeof r.you=="string"?r.you:"",admin:r.admin===true}}}function Xa(e){let{usage:t,source:r,verifiedAt:o,team:n,...i}=e;return i}async function Ya(e,t=ot()){let r=await Lt("/api/scenarios/team/share",{scenario:Xa(e)},t);return r.ok?Tr(r.value.scenario)?{ok:true,value:r.value.scenario}:{ok:false,code:"refused",message:"buoy.gg sent back a scenario this app could not read."}:r}async function Qa(e,t=ot()){let r=await Lt("/api/scenarios/team/remove",{id:e},t);return r.ok?{ok:true,value:true}:r}var Dr=Dt.scenarios.library(),zt=Dt.scenarios.active(),Pt=Dt.scenarios.team(),Za=3e4,en=null;function Ue(){return en??ot()}function Ot(e){return{...e.scenario,id:e.id,source:"team",author:e.sharedBy.label,version:e.version,createdAt:e.scenario.createdAt??e.sharedAt,updatedAt:e.updatedAt,usage:{runs:0},team:{sharedBy:e.sharedBy,sharedAt:e.sharedAt,updatedAt:e.updatedAt,app:e.app}}}var Vt=100,F=null;function tn(e){F=e}function kr(){return!(typeof Qt<"u"&&!Qt)}var rn=class{constructor(){this.state={code:[],device:[],drafts:[],team:[],teamInfo:{status:"idle",you:null,admin:false},active:null,runState:null,lastDeactivateReport:null,hasLoaded:false,lastVarValues:{}};this.listeners=new Set;this.loadPromise=null;this.expiryTimer=null;this.runController=null;this.getState=()=>this.state;this.subscribe=e=>(this.listeners.add(e),this.ensureLoaded(),()=>{this.listeners.delete(e)});this.teamRows=[];this.teamPull=null;this.teamCredentialKey=null}setState(e){this.state={...this.state,...e},this.listeners.forEach(t=>{try{t()}catch{}})}allScenarios(){let e=new Set(this.state.code.map(o=>o.id)),t=this.state.team.filter(o=>!e.has(o.id)),r=new Set([...e,...t.map(o=>o.id)]);return[...this.state.code,...t,...this.state.device.filter(o=>!r.has(o.id))]}find(e){return this.allScenarios().find(t=>t.id===e)??this.state.drafts.find(t=>t.id===e)}folders(){return Ir([...this.state.code,...this.state.team,...this.state.device,...this.state.drafts])}registerCodeScenarios(e){let t=new Map(this.state.code.map(r=>[r.id,r]));for(let r of e)t.set(r.id,{...r,source:"code"});this.setState({code:[...t.values()]})}ensureLoaded(){return F?Promise.resolve():(this.loadPromise||(this.loadPromise=this.load()),this.loadPromise)}async load(){let e=[],t=[],r={};try{let c=await ve.getItem(Dr);if(c){let s=JSON.parse(c);e=Array.isArray(s.device)?s.device:[],t=Array.isArray(s.drafts)?s.drafts:[],r=s.lastVarValues&&typeof s.lastVarValues=="object"?s.lastVarValues:{}}}catch{}let o=null;try{let c=await ve.getItem(zt);c&&(o=JSON.parse(c))}catch{o=null}let n=[],i=this.state.teamInfo;try{let c=await ve.getItem(Pt),s=c?JSON.parse(c):null,l=at(Ue());s&&Array.isArray(s.rows)&&(!l||s.app===l)&&(this.teamRows=s.rows,n=s.rows.map(Ot),i={status:"idle",you:s.you||null,admin:s.admin,pulledAt:s.pulledAt})}catch{}this.setState({device:e,drafts:t,team:n,teamInfo:i,lastVarValues:r,active:o,hasLoaded:true}),o&&await this.reconcileActive()}async persistLibrary(){if(F)return;let e={version:1,device:this.state.device,drafts:this.state.drafts,lastVarValues:this.state.lastVarValues};try{await ve.setItem(Dr,JSON.stringify(e))}catch{}}async persistActive(){if(!F)try{this.state.active?await ve.setItem(zt,JSON.stringify(this.state.active)):await ve.removeItem(zt)}catch{}}async persistTeam(e,t){if(!F)try{if(!e||!t){await ve.removeItem(Pt);return}let{you:r,admin:o,pulledAt:n}=this.state.teamInfo,i={version:1,app:t,you:r??"",admin:o,pulledAt:n??Date.now(),rows:e};await ve.setItem(Pt,JSON.stringify(i))}catch{}}credentialKey(e){let t=e.credential();return t?`${t.team}:${t.token}`:""}onAccountChange(){return F||this.credentialKey(Ue())===this.teamCredentialKey?Promise.resolve():this.refreshTeam({force:true})}refreshTeam(e={}){if(F)return Promise.resolve();let{pulledAt:t,status:r}=this.state.teamInfo;return!e.force&&r==="ready"&&t&&Date.now()-t<Za?Promise.resolve():(this.teamPull||(this.teamPull=this.pullTeam().finally(()=>{this.teamPull=null})),this.teamPull)}async pullTeam(){await this.ensureLoaded();let e=Ue();this.teamCredentialKey=this.credentialKey(e),this.setState({teamInfo:{...this.state.teamInfo,status:"loading",message:void 0}});let t=await Ga(e);if(!t.ok){if(t.code==="network"){this.setState({teamInfo:{...this.state.teamInfo,status:"error",message:t.message}});return}this.teamRows=[],this.setState({team:[],teamInfo:{status:"off",reason:t.code,message:t.message,you:null,admin:false}}),await this.persistTeam(null,null);return}this.teamRows=t.value.scenarios,this.setState({team:t.value.scenarios.map(Ot),teamInfo:{status:"ready",you:t.value.you,admin:t.value.admin,pulledAt:Date.now()}}),await this.persistTeam(this.teamRows,at(e))}async shareWithTeam(e){if(await this.ensureLoaded(),F)throw new Error("Share from the app on the device.");let t=this.state.device.find(c=>c.id===e);if(!t)throw new Error("Only a scenario saved on this device can be shared.");let r=Ue(),o=await Ya(t,r);if(!o.ok)throw new Error(o.message);let n=o.value;this.teamRows=[n,...this.teamRows.filter(c=>c.id!==n.id)];let i=Ot(n);return this.setState({team:[i,...this.state.team.filter(c=>c.id!==n.id)],teamInfo:{...this.state.teamInfo,status:"ready",message:void 0,you:this.state.teamInfo.you??n.sharedBy.id,pulledAt:this.state.teamInfo.pulledAt??Date.now()}}),await this.persistTeam(this.teamRows,at(r)),i}isMirror(){return F!==null}canRemoveFromTeam(e){if(F||e.source!=="team"||!e.team)return false;let{you:t,admin:r}=this.state.teamInfo;return r||!!t&&e.team.sharedBy.id===t}async removeFromTeam(e){if(await this.ensureLoaded(),F)throw new Error("Remove it from the app on the device.");if(!this.state.team.some(o=>o.id===e))throw new Error("That scenario is not on the team's list.");let t=Ue(),r=await Qa(e,t);if(!r.ok)throw new Error(r.message);this.teamRows=this.teamRows.filter(o=>o.id!==e),this.setState({team:this.state.team.filter(o=>o.id!==e)}),await this.persistTeam(this.teamRows,at(t))}async reconcileActive(){let e=this.state.active;if(!(!e||!e.effects.filter(t=>t.kind==="override-rule").length)&&ur().includes("network"))try{let t=await $e("network","listOverrideRules",{}),r=new Set((t?.rules??[]).map(n=>n.id)),o=e.effects.filter(n=>n.kind!=="override-rule"||r.has(n.ruleId));if(o.length===e.effects.length)return;o.length?this.setState({active:{...e,effects:o}}):this.setState({active:null}),await this.persistActive()}catch{}}checkBeforeRun(e,t,r=[]){let o=this.state.active,n=[...r];kr()||n.push("Scenarios cannot run in a production build.");let i=Me(e.vars,t);return vr(e,i,{availableTools:ur(),availableActions:$a(),activeScenario:o?{scenarioId:o.scenarioId,name:o.name,conflictKeys:this.activeConflictKeys()}:null,extraErrors:n})}holdObservers(e){let t=[],r=Ra();for(let o of e){let n=r[o]?.subscribe;if(n)try{t.push(n(()=>{}))}catch{}}return t}activeConflictKeys(){let e=this.state.active;if(!e)return[];let t=this.find(e.scenarioId);if(!t)return[];let r=new Set;for(let o of t.steps)for(let n of Ct(o,be(o.params,e.varValues)))r.add(n);return[...r]}async run(e,t={},r={}){if(kt(),F)return await F("run",{id:e,params:t});await this.ensureLoaded(),kt();let o=this.find(e);if(!o)throw new Error(`No scenario "${e}"`);if(o.source==="draft")throw new Error("Drafts must be accepted before they can run.");if(!kr())throw new Error("Scenarios cannot run in a production build.");if(!await Aa())throw new Error("Buoy tools are still starting up \u2014 try again in a moment.");let n=Me(o.vars,t);if(this.state.active&&this.state.active.scenarioId!==e)await this.deactivate();else if(this.state.active){let l=this.state.active;await qe(l.effects.filter(u=>u.kind==="override-rule"),$e),this.setState({active:{...l,effects:l.effects.filter(u=>u.kind!=="override-rule")}})}kt(),this.setState({runState:{scenarioId:e,name:xe(o.name,n),steps:[],current:0,done:false}});let i=this.holdObservers(["route-events"]),c;this.runController?.abort();let s=new AbortController;this.runController=s;try{c=await $t(o,n,$e,{signal:s.signal,onStep:l=>{let u=this.state.runState;u&&this.setState({runState:{...u,current:l}})}})}finally{this.runController===s&&(this.runController=null),i.forEach(l=>{try{l()}catch{}})}if(this.setState({runState:{scenarioId:e,name:xe(o.name,n),steps:c.steps,current:-1,done:true,report:c}}),c.ok&&dr()){let l={scenarioId:e,name:xe(o.name,n),version:o.version,source:o.source,runAt:Date.now(),varValues:n,effects:c.effects,expiresAt:r.expiresInMs?Date.now()+r.expiresInMs:void 0,undoSteps:o.undoSteps};this.setState({active:l,lastDeactivateReport:null,lastVarValues:{...this.state.lastVarValues,[e]:n}}),this.bumpUsage(e),this.armExpiry(),await this.persistActive(),await this.persistLibrary()}return c}async undoPartialRun(){let e=this.state.runState?.report;if(!e)return{removedRules:0,stoppedImpersonation:false,clearedTransients:0,unrestoredStorageKeys:[],unrestoredState:[],undoStepsRan:0,errors:[]};let t={...await qe(e.effects,$e),undoStepsRan:0};return this.setState({runState:null,lastDeactivateReport:t}),t}clearRunState(){this.setState({runState:null})}bumpUsage(e){let t=r=>r.map(o=>o.id===e?{...o,usage:{runs:(o.usage?.runs??0)+1,lastRunAt:Date.now()}}:o);this.setState({code:t(this.state.code),team:t(this.state.team),device:t(this.state.device)})}async deactivate(){if(F)return await F("deactivate",{});let e=this.state.active;if(!e)return{removedRules:0,stoppedImpersonation:false,clearedTransients:0,unrestoredStorageKeys:[],unrestoredState:[],undoStepsRan:0,errors:[]};let t=await qe(e.effects,$e),r=[...t.errors],o=0,n=this.find(e.scenarioId),i=e.undoSteps??n?.undoSteps??[];if(i.length){let s=n??{id:e.scenarioId,name:e.name,version:e.version,source:e.source,vars:[],steps:[],createdAt:e.runAt,updatedAt:e.runAt,usage:{runs:0}},l=await $t({...s,steps:i},e.varValues,$e);o=l.steps.filter(u=>u.ok).length;for(let u of l.steps)!u.ok&&u.error&&r.push(u.error)}let c={removedRules:t.removedRules,stoppedImpersonation:t.stoppedImpersonation,clearedTransients:t.clearedTransients,unrestoredStorageKeys:o?[]:t.unrestoredStorageKeys,unrestoredState:o?[]:t.unrestoredState,undoStepsRan:o,errors:r};return this.clearExpiry(),this.setState({active:null,lastDeactivateReport:c}),await this.persistActive(),c}async disposeAccountSession(e){if(this.runController?.abort(),this.runController=null,dr())return;this.clearExpiry();let t=this.state.active;if(!t||F)return;let r=await qe(t.effects.filter(o=>o.kind==="override-rule"),e);if(this.setState({active:null}),await this.persistActive(),r.errors.length)throw new Error(r.errors.join("; "))}dismissDeactivateReport(){this.setState({lastDeactivateReport:null})}armExpiry(){this.clearExpiry();let e=this.state.active?.expiresAt;if(!e)return;let t=Math.max(0,e-Date.now());this.expiryTimer=setTimeout(()=>{this.deactivate()},t)}clearExpiry(){this.expiryTimer&&(clearTimeout(this.expiryTimer),this.expiryTimer=null)}isLongRunning(e=480*60*1e3){let t=this.state.active;return!!t&&Date.now()-t.runAt>e}async saveScenario(e,t={}){await this.ensureLoaded();let r=Date.now(),o=t.asDraft??false,n=o?this.state.drafts:this.state.device,i=n.findIndex(l=>l.id===e.id),c={...e,steps:rt(e.steps,"s"),undoSteps:e.undoSteps?rt(e.undoSteps,"u"):void 0,folder:At(e.folder,this.folders()),source:o?"draft":"device",version:i>=0?(n[i].version??1)+1:e.version||1,createdAt:i>=0?n[i].createdAt:r,updatedAt:r,usage:i>=0?n[i].usage:{runs:0}};if(!o&&i<0&&this.state.device.length>=Vt)throw new Error(`This device already holds ${Vt} scenarios \u2014 delete one first.`);let s=[...n];return i>=0?s[i]=c:s.unshift(c),this.setState(o?{drafts:s}:{device:s}),await this.persistLibrary(),c}async acceptDraft(e){await this.ensureLoaded();let t=this.state.drafts.find(o=>o.id===e);if(!t)throw new Error(`No draft "${e}"`);let r={...t,source:"device",unsavedToRepo:true,updatedAt:Date.now()};return this.setState({drafts:this.state.drafts.filter(o=>o.id!==e),device:[r,...this.state.device]}),await this.persistLibrary(),r}async discardDraft(e){await this.ensureLoaded(),this.setState({drafts:this.state.drafts.filter(t=>t.id!==e)}),await this.persistLibrary()}async setFolder(e,t){if(await this.ensureLoaded(),F)return(await F("setFolder",{id:e,folder:t})).scenario;if(this.state.code.some(s=>s.id===e))throw new Error("Scenarios shipped with the app are filed in code \u2014 change `folder` in defineScenario().");if(this.state.team.some(s=>s.id===e)&&!this.state.device.some(s=>s.id===e))throw new Error("A team scenario keeps the folder its sharer gave it. Make an editable copy to file it here.");let r=At(t,this.folders()),o,n=s=>s.map(l=>l.id!==e?l:(o={...l,folder:r,updatedAt:Date.now()},o)),i=n(this.state.device),c=o?this.state.drafts:n(this.state.drafts);if(!o)throw new Error(`No scenario "${e}"`);return this.setState({device:i,drafts:c}),await this.persistLibrary(),o}async deleteScenario(e){await this.ensureLoaded(),this.state.active?.scenarioId===e&&await this.deactivate(),this.setState({device:this.state.device.filter(t=>t.id!==e)}),await this.persistLibrary()}rememberVarValues(e,t){this.setState({lastVarValues:{...this.state.lastVarValues,[e]:t}}),this.persistLibrary()}lastValuesFor(e){return this.state.lastVarValues[e]??{}}replaceFromSnapshot(e){this.setState({code:e.code??[],device:e.device??[],drafts:e.drafts??[],team:e.team??[],teamInfo:e.teamInfo??{status:"idle",you:null,admin:false},active:e.active??null,runState:e.runState??null,hasLoaded:true})}},m=new rn;function on(e){m.replaceFromSnapshot(e)}import{useSyncExternalStore as nt}from"react";import{dispatchToolAction as an,getToolAdapters as Cr}from"@buoy-gg/shared-ui/web";var Te="highlight-updates",Be="route-events",Le="zustand",nn=new Set(["item","row","card","btn","button","cta","link","cell","tile","popular","open","tap","press","go"]);function Rr(e){let t=e.split(/[-_.]/).filter(Boolean),r=t.length>=3?t.slice(1):t,o=r.filter(i=>!nn.has(i.toLowerCase())),n=(o.length?o:r).join(" ").trim();return n?n.charAt(0).toUpperCase()+n.slice(1):e}var $r=28;function Ar(e){let t=e.testID?Rr(e.testID):void 0,r=(e.control==="text"?[e.label,t,e.text]:[e.label,e.text,t]).filter(n=>typeof n=="string"&&n.trim().length>0),o=r.find(n=>n.trim().length<=$r);return o?o.trim():r.length?it(r[0].trim(),$r):e.name}function Er(e){if(e.testID)return{testID:e.testID};let t=e.label??e.text;return t&&t.trim()?{query:t.trim()}:null}function it(e,t=32){let r=typeof e=="string"?e:JSON.stringify(e);return typeof r!="string"?"":r.length>t?`${r.slice(0,t)}\u2026`:r}function Ht(e){let{touch:t}=e,r=Ar(t.target);switch(t.kind){case"text":return`Type \u201C${it(t.value)}\u201D into ${r}`;case"toggle":return`${t.value===false?"Turn off":"Turn on"} ${r}`;case"slider":return`Set ${r} to ${it(t.value)}`;case"longPress":return`Press and hold \u201C${r}\u201D`;default:return`Tap \u201C${r}\u201D`}}function sn(e){if(e==null||typeof e!="object")return;let t=[];for(let[r,o]of Object.entries(e))if(typeof o!="function"){if(Array.isArray(o))t.push(`${o.length} ${r}`);else if(o==null||typeof o!="object"){if(o===null||o===""||o===false||o===0)continue;t.push(`${r} ${it(o,16)}`)}if(t.length>=3)break}return t.length?t.join(", "):void 0}function ln(e){let t=[];e.effects.route&&e.effects.route!==e.routeBefore&&t.push(`went to ${e.effects.route}`);for(let r of e.effects.stores??[]){let o=sn(r.state);t.push(o?`${r.name} \u2192 ${o}`:`changed ${r.name}`)}return t.length?t.join(" \xB7 "):void 0}var cn=0,ze=e=>`${e}-${Date.now().toString(36)}-${(cn++).toString(36)}`;function dn(e){let t=Er(e.touch.target);if(!t)return[];let r={...t},{touch:o}=e;o.kind==="longPress"&&(r.longPress=true),o.kind==="text"&&(r.text=o.value),(o.kind==="toggle"||o.kind==="slider")&&(r.value=o.value);let n=[{id:ze("ui"),tool:Te,action:"tapElement",params:r,label:Ht(e)}],i=e.effects.route;return i&&i!==e.routeBefore&&n.push({id:ze("wait"),tool:"scenario",action:"waitFor",params:{route:i},label:`Wait for ${i}`}),n}function un(e){let t=[];for(let o of e.effects.stores??[])t.push({id:ze("state"),tool:Le,action:"setState",params:{storeName:o.name,state:o.state,replace:true,persisted:o.persisted??false},label:`Set ${o.name}`});let r=e.effects.route;return r&&r!==e.routeBefore&&t.push({id:ze("nav"),tool:Be,action:"navigate",params:{path:r},label:`Go to ${r}`}),t}function hn(e){let t={id:ze("start"),tool:Be,action:"navigate",params:{path:e,reset:true},label:`Go to ${e}`};return{id:ze("pre"),precondition:true,title:`Start from ${e}`,detail:"so it can run from anywhere",lane:"state",lanes:["state"],enabled:true,noise:false,ui:[],state:[t]}}function Br(e,t){let r=e.map(o=>{let n=dn(o),i=un(o),c=[];return n.length&&c.push("ui"),i.length&&c.push("state"),{id:o.id,title:Ht(o),detail:ln(o),lane:c.includes("ui")?"ui":"state",lanes:c,enabled:c.length>0,noise:c.length===0,ui:n,state:i}});return t&&r.length?[hn(t),...r]:r}function fn(e){if(e.tool===Le&&e.action==="setState"){let t=e.params?.storeName;return t?`${Le}:${t}`:null}return e.tool===Be&&e.action==="navigate"?"route":null}function Ft(e){let t=[],r=new Map,o=0,n=()=>{for(let i of r.values())t.push(i);r=new Map,o=0};for(let i of e){if(!i.enabled||i.noise)continue;let c=i.lane==="state"?i.state:i.ui;if(c.length){if(i.lane!=="state"){n(),t.push(...c);continue}for(let s of c){let l=fn(s);if(l==null){r.set(`\0${o++}`,s);continue}r.delete(l),r.set(l,s)}}}return n(),t}function pn(e,t){return e.map((r,o)=>r.precondition?r:o>t?{...r,lane:"ui",enabled:!r.noise&&r.lanes.length>0}:r.lanes.includes("state")?{...r,lane:"state",enabled:true}:{...r,enabled:false})}function mn(e){return e.map(t=>t.precondition?t:{...t,lane:t.lanes.includes("ui")?"ui":"state",enabled:t.lanes.length>0&&!t.noise})}function gn(e){let t=-1;for(let r=0;r<e.length;r++){let o=e[r];if(!o.precondition){if(o.enabled&&o.lane==="state"){t=r;continue}if(o.enabled)break}}return t}var yn=/^(continue|next|ok|done|submit|save|confirm|apply|back|close|cancel|open|add\b|view\b|go to\b|place order|checkout|check out)/i;function bn(e){let t=e.filter(c=>c.enabled&&!c.noise),r;for(let c of t)for(let s of c.state??[]){let l=s.params?.path;s.tool===Be&&s.action==="navigate"&&typeof l=="string"&&(r=l)}let o=r?.split("?")[0].split("/").filter(Boolean).pop(),n=r===void 0?"":o?vn(o.replace(/[-_]/g," ")):"Home",i="";for(let c of[...t].reverse()){if(c.precondition)continue;let s=c.title.match(/“([^”]+)”/)?.[1]?.split(",")[0].trim();if(s&&!yn.test(s)){i=s;break}}return n&&i?`${n} \xB7 ${i}`:n||i?n||i:t.length?`${t.length} recorded step${t.length===1?"":"s"}`:""}function vn(e){return e.replace(/\b\w/g,t=>t.toUpperCase())}var wn=250,Sn=1200,Lr={status:"idle",reason:null,startedAt:null,startRoute:void 0,actions:[],draft:null},xn=0,In=()=>`act-${Date.now().toString(36)}-${(xn++).toString(36)}`,Tn=class{constructor(){this.state=Lr;this.listeners=new Set;this.timer=null;this.sinceSeq=0;this.storeChanges=new Map;this.holds=[];this.ticking=false;this.getState=()=>this.state;this.subscribe=e=>(this.listeners.add(e),()=>{this.listeners.delete(e)})}setState(e){this.state={...this.state,...e},this.listeners.forEach(t=>{try{t()}catch{}})}canRecord(){return typeof Cr()[Te]?.actions?.startTouchCapture=="function"}async start(){if(this.state.status==="recording")return;if(!this.canRecord()){this.setState({status:"unavailable",reason:"Recording needs the Highlight Updates tool installed \u2014 it owns the screen reader this uses to name what you tap."});return}this.holds=[];for(let t of[Be,Le]){let r=Cr()[t]?.subscribe;if(r)try{this.holds.push(r(()=>{}))}catch{}}await this.call(Te,"clearTouchCapture");let e=await this.call(Te,"startTouchCapture");if(e?.status!=="capturing"){this.releaseHolds(),this.setState({status:"unavailable",reason:e?.reason??"This build of React Native doesn't expose the touch stream Buoy records from."});return}this.sinceSeq=0,this.route=await this.readRoute(),this.storeChanges=await this.readStoreChanges(),this.setState({status:"recording",reason:null,startedAt:Date.now(),startRoute:this.route,actions:[],draft:null}),this.timer=setInterval(()=>void this.tick(),wn)}async stop(){this.state.status==="recording"&&(this.clearTimer(),await new Promise(e=>setTimeout(e,Sn)),await this.tick(),await this.call(Te,"stopTouchCapture"),this.releaseHolds(),this.setState({status:"review",draft:Br(this.state.actions,this.state.startRoute)}))}async cancel(){this.clearTimer(),this.state.status==="recording"&&await this.call(Te,"stopTouchCapture"),this.releaseHolds(),this.setState({...Lr})}setDraft(e){this.state.status==="review"&&this.setState({draft:e})}clearTimer(){this.timer&&(clearInterval(this.timer),this.timer=null)}releaseHolds(){this.holds.forEach(e=>{try{e()}catch{}}),this.holds=[]}async tick(){if(!this.ticking){this.ticking=true;try{let e=await this.call(Te,"readTouchCapture",{sinceSeq:this.sinceSeq}),t=[...this.state.actions],r=false;for(let s of e?.records??[])t.push({id:In(),touch:s,routeBefore:this.route,effects:{}}),r=true;e?.seq&&(this.sinceSeq=e.seq);let o=t[t.length-1],n=await this.readRoute();n!==void 0&&n!==this.route&&(this.route=n,o&&(o.effects={...o.effects,route:n},r=true));let i=await this.readStoreChanges(),c=[];for(let[s,l]of i){let u=this.storeChanges.get(s);u!==void 0&&u.changes!==l.changes&&c.push({name:s,persisted:l.persisted})}if(this.storeChanges=i,o&&c.length){let s=[...o.effects.stores??[]];for(let{name:l,persisted:u}of c){let d=await this.readStoreState(l);if(d===void 0)continue;let h=s.findIndex(v=>v.name===l);h>=0?s[h]={name:l,state:d,persisted:u}:s.push({name:l,state:d,persisted:u})}s.length&&(o.effects={...o.effects,stores:s},r=true)}r&&this.setState({actions:t})}finally{this.ticking=false}}}async call(e,t,r){try{return await an(e,t,r)}catch{return null}}async readRoute(){let e=(await this.call(Be,"getCurrentRoute"))?.path;return typeof e=="string"?e:void 0}async readStoreChanges(){let e=await this.call(Le,"listStores",{}),t=new Map;for(let r of e?.stores??[])r?.name&&t.set(r.name,{changes:r.changes??0,persisted:r.isPersisted===true});return t}async readStoreState(e){let t=await this.call(Le,"getStoreState",{storeName:e});if(t?.found)return t.currentState}},ae=new Tn;function zr(){return nt(m.subscribe,m.getState)}function jt(){return nt(m.subscribe,()=>m.getState().active)}function Pr(){return nt(m.subscribe,()=>m.getState().runState)}function Or(){return nt(ae.subscribe,ae.getState)}import{useCallback as Vr,useMemo as Pe,useRef as Dn,useState as kn}from"react";import{Bookmark as Cn,ToolButton as Hr,Zap as Rn,useSafeAreaInsets as $n,ToolEmptyState as An}from"@buoy-gg/shared-ui/web";import{useToolHeader as En}from"@buoy-gg/core/web";import{night as O}from"@buoy-gg/shared-ui/web";import{monoFont as Bn}from"@buoy-gg/shared-ui/web";var a={color:{bg:O.color.bg,surface:"rgba(12, 12, 12, 0.9)",row:O.color.surfaceElevated,chip:O.color.buttonSurface,border:O.color.border,separator:O.color.separator,fill:O.color.fill,text:O.color.text,textSecondary:O.color.textSecondary,textTertiary:O.color.textTertiary,accent:O.color.accent,accentSoft:O.color.accentSoft,accentBorder:O.color.accentBorder,accentBorderStrong:O.color.accentBorderStrong,onAccent:O.color.onAccent,sim:O.color.warning,simSoft:O.color.warningSoft,simBorder:"rgba(255, 131, 41, 0.35)",onSim:"#000000",danger:O.color.danger,dangerSoft:O.color.dangerSoft,dangerBorder:"rgba(255, 59, 48, 0.30)",info:O.color.info,infoSoft:O.color.infoSoft,infoBorder:"rgba(30, 109, 255, 0.25)"},radius:{card:8,row:6,badge:4,pill:6},gutter:12,textInset:12,rowMinHeight:44,font:{row:13,control:12,label:11,footnote:11,mono:11,micro:9}},N=Bn;import{SectionHeader as st,Pill as Fr}from"@buoy-gg/shared-ui/web";import{jsx as se,jsxs as Ln}from"react/jsx-runtime";function U({children:e,icon:t,count:r,color:o=a.color.accent,testID:n,countTestID:i}){return se(g,{testID:n,collapsable:false,children:Ln(st,{children:[t?se(st.Icon,{icon:t,color:o,size:14}):null,se(st.Title,{children:e}),r!==void 0?se(st.Badge,{count:r,color:o,testID:i}):null]})})}function te({children:e,centered:t,tone:r="secondary",testID:o}){return se(f,{style:[Y.footnote,t?Y.footnoteCentered:null,r==="warning"?Y.footnoteWarning:null,r==="danger"?Y.footnoteDanger:null],testID:o,children:e})}function _({children:e,tone:t="neutral",style:r,testID:o}){return se(g,{style:[Y.panel,t==="sim"?Y.panelSim:null,t==="danger"?Y.panelDanger:null,t==="info"?Y.panelInfo:null,r],testID:o,children:e})}function X(){return se(g,{style:Y.panelSeparator})}function he({children:e,tone:t,testID:r}){return se(g,{style:[Y.notice,t==="sim"?Y.noticeSim:null,t==="danger"?Y.noticeDanger:null,t==="info"?Y.noticeInfo:null],testID:r,children:e})}function zn({label:e,color:t,testID:r}){return se(Fr,{label:e,color:t,variant:"tinted",style:{height:26,paddingHorizontal:10,borderRadius:a.radius.pill,justifyContent:"center"},testID:r})}function _e({label:e,tone:t,testID:r}){let o=t==="durable"?a.color.accent:t==="transient"?a.color.sim:a.color.textTertiary;return se(Fr,{label:e,color:o,variant:"tinted",mono:true,uppercase:false,testID:r})}var Y=H.create({footnote:{color:a.color.textTertiary,fontSize:a.font.footnote,lineHeight:a.font.footnote*1.45,paddingHorizontal:a.gutter+4,paddingTop:8},footnoteCentered:{textAlign:"center"},footnoteWarning:{color:a.color.sim},footnoteDanger:{color:a.color.danger},panel:{marginHorizontal:a.gutter,marginVertical:4,backgroundColor:a.color.surface,borderRadius:a.radius.card,borderWidth:1,borderColor:a.color.border,overflow:"hidden"},panelSim:{borderColor:a.color.simBorder},panelDanger:{borderColor:a.color.dangerBorder},panelInfo:{borderColor:a.color.infoBorder},panelSeparator:{height:H.hairlineWidth,marginLeft:a.textInset,backgroundColor:a.color.separator},notice:{marginHorizontal:a.gutter,marginTop:8,borderRadius:a.radius.card,borderWidth:1,paddingHorizontal:a.textInset,paddingVertical:10,gap:3},noticeSim:{backgroundColor:a.color.simSoft,borderColor:a.color.simBorder},noticeDanger:{backgroundColor:a.color.dangerSoft,borderColor:a.color.dangerBorder},noticeInfo:{backgroundColor:a.color.infoSoft,borderColor:a.color.infoBorder}});import{jsx as B,jsxs as ne}from"react/jsx-runtime";function jr({draft:e,onChange:t,onSave:r,onDiscard:o,busy:n}){let i=$n({minBottom:16}),[c,s]=kn(()=>bn(e)),l=Dn(o);l.current=o;let u=Vr(()=>l.current(),[]);En({title:"Review recording",onBack:u,searchable:false},[]);let d=Pe(()=>e.filter($=>$.enabled&&!$.noise),[e]),h=Pe(()=>e.filter($=>$.noise),[e]),v=Pe(()=>gn(e),[e]),y=Pe(()=>{let $=0;return e.map(j=>j.precondition?0:++$)},[e]),C=Vr(($,j)=>{t(e.map(p=>p.id===$?{...p,...j}:p))},[e,t]),w=Pe(()=>Ft(e),[e]),R=Pe(()=>w.filter($=>$.tool===Ie&&$.action==="waitFor").length,[w]),V=d.length-(w.length-R);return ne(ye,{style:k.fill,contentContainerStyle:[k.content,{paddingBottom:i.bottom}],keyboardShouldPersistTaps:"handled",testID:"macro-review-scroll",children:[B(U,{icon:Cn,children:"Name"}),B(_,{children:B(tt,{style:k.nameInput,value:c,onChangeText:s,placeholder:"Bag with a Charizard in it",placeholderTextColor:a.color.textTertiary,maxLength:80,returnKeyType:"done",testID:"macro-name-input"})}),B(U,{icon:Rn,count:d.length,children:"Steps"}),v>=0?B(g,{style:k.modeBar,children:B(W,{style:k.reset,onPress:()=>t(mn(e)),activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:"Perform every step instead of starting partway",testID:"macro-replay-all",children:B(f,{style:k.resetText,children:"\u21BA Perform every step"})})}):null,ne(_,{children:[e.map(($,j)=>ne(g,{children:[j>0?B(X,{}):null,B(Pn,{step:$,index:y[j],before:j<=v,onStartHere:$.lanes.includes("state")&&!$.precondition?()=>t(pn(e,j)):void 0,onToggleEnabled:()=>C($.id,{enabled:!$.enabled})}),j===v?ne(g,{style:k.startLine,testID:"macro-start-line",children:[B(g,{style:k.startRule}),B(f,{style:k.startLabel,children:"the app starts here \xB7 the rest is performed"}),B(g,{style:k.startRule})]}):null]},$.id)),e.length===0?B(An,{testID:"macro-review-empty",otto:"shrug",title:"Nothing was recorded",message:"Taps on Buoy's own controls are ignored on purpose \u2014 drive the app itself and try again."}):null]}),V>0?B(he,{tone:"info",testID:"macro-review-collapsed",children:ne(f,{style:k.noticeText,children:[V," shortcut step",V===1?"":"s"," collapsed \u2014 consecutive writes to the same store save once, at the value they ended on."]})}):null,R>0?B(he,{tone:"info",testID:"macro-review-waits",children:ne(f,{style:k.noticeText,children:["Saves as ",w.length," steps: ",R," of them wait for the screen a tap opened, so the replay never runs ahead of the app."]})}):null,h.length?B(he,{tone:"sim",testID:"macro-review-unnameable",children:ne(f,{style:k.noticeText,children:[h.length," tap",h.length===1?"":"s"," landed on something with no testID, label or text, so it can't be found again. Add a testID to replay ",h.length===1?"it":"them","."]})}):null,ne(g,{style:k.actions,children:[B(Hr,{label:"Discard",variant:"ghost",onPress:o,disabled:n,testID:"macro-discard"}),B(Hr,{label:`Save ${w.length} step${w.length===1?"":"s"}`,variant:"primary",disabled:n||!w.length||!c.trim(),onPress:()=>r(c.trim(),e),testID:"macro-save"})]}),B(te,{children:"Every step is performed the way you did it, which keeps working when the app's internals change. Tap \u201CStart here\u201D on the step you actually want to test and everything before it is written instantly instead \u2014 the setup stops costing you a minute a run, and it survives those earlier screens being redesigned."})]})}function Pn({step:e,index:t,before:r,onStartHere:o,onToggleEnabled:n}){let i=!e.enabled||e.noise;return ne(g,{style:k.row,children:[ne(W,{style:k.rowMain,onPress:n,disabled:e.noise,activeOpacity:.7,accessibilityRole:"checkbox",accessibilityState:{checked:!i},accessibilityLabel:e.title,testID:`macro-step-${t}`,children:[B(f,{style:[k.index,i&&k.dim],children:e.precondition?"\u21B1":t}),ne(g,{style:k.rowText,children:[B(f,{style:[k.title,i&&k.dim,i&&k.struck],numberOfLines:2,children:e.title}),e.detail?B(f,{style:k.detail,numberOfLines:1,children:e.detail}):null]})]}),o&&!r?B(W,{style:k.startHere,onPress:o,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`Start the macro here \u2014 everything up to \u201C${e.title}\u201D is set instantly`,testID:`macro-step-${t}-start-here`,children:B(f,{style:k.startHereText,children:"Start here"})}):B(f,{style:[k.laneStatic,r&&k.laneStaticInstant],testID:`macro-step-${t}-lane`,children:e.precondition?"first":e.noise?"can\u2019t replay":r?e.lane==="state"?"instant":"skipped":"performed"})]})}var k=H.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:32},nameInput:{color:a.color.text,fontSize:a.font.row,paddingHorizontal:a.textInset,paddingVertical:12},modeBar:{paddingHorizontal:a.gutter,paddingBottom:4},row:{flexDirection:"row",alignItems:"center",gap:8,paddingRight:a.textInset,minHeight:a.rowMinHeight},rowMain:{flex:1,minWidth:0,flexDirection:"row",alignItems:"center",gap:10,paddingLeft:a.textInset,paddingVertical:10},index:{color:a.color.textTertiary,fontSize:a.font.micro,fontWeight:"700",minWidth:14},rowText:{flex:1,minWidth:0},title:{color:a.color.text,fontSize:a.font.row,lineHeight:17},detail:{color:a.color.textTertiary,fontSize:a.font.micro,marginTop:2},dim:{color:a.color.textTertiary},struck:{textDecorationLine:"line-through"},startHere:{paddingHorizontal:8,paddingVertical:5,borderRadius:a.radius.pill,borderWidth:1,borderColor:a.color.border,backgroundColor:a.color.chip},startHereText:{color:a.color.textSecondary,fontSize:a.font.micro,fontWeight:"700"},laneStatic:{color:a.color.textTertiary,fontSize:a.font.micro},laneStaticInstant:{color:a.color.sim},startLine:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:a.textInset,paddingVertical:8,backgroundColor:a.color.simSoft},startRule:{flex:1,height:1,backgroundColor:a.color.simBorder},startLabel:{color:a.color.sim,fontSize:a.font.micro,fontWeight:"700",letterSpacing:.3},reset:{alignSelf:"flex-start",paddingVertical:4},resetText:{color:a.color.textSecondary,fontSize:a.font.footnote,fontWeight:"600"},noticeText:{color:a.color.textSecondary,fontSize:a.font.footnote,lineHeight:16},actions:{flexDirection:"row",justifyContent:"flex-end",gap:8,paddingHorizontal:a.gutter,paddingTop:12},empty:{color:a.color.textTertiary,fontSize:a.font.control,lineHeight:18,paddingHorizontal:a.textInset,paddingVertical:14}});import{useCallback as On,useState as Vn}from"react";import{Copy as Hn,Power as Fn,RefreshCw as jn,ToolButton as Wt,copyToClipboard as Wn}from"@buoy-gg/shared-ui/web";import{jsx as re,jsxs as Oe}from"react/jsx-runtime";function Nn(e){switch(e.kind){case"override-rule":return{label:"survives restart",tone:"durable"};case"impersonation":return{label:"survives restart",tone:"durable"};case"storage-write":return{label:"not auto-undone",tone:"transient"};default:return{label:"one-shot",tone:"neutral"}}}function Mn(e,t){let r=Object.entries(e.varValues).map(([o,n])=>`${o}=${String(n)}`).join(", ");return["\u2014 Bug report context (Buoy Scenarios) \u2014",`Scenario: ${e.name} (v${e.version}, ${e.source})`,`Variables: ${r||"none"}`,`Active since: ${new Date(e.runAt).toISOString()}`,t?`App build: ${t}`:null,`Effects: ${e.effects.map(o=>o.label).join(" \xB7 ")}`].filter(Boolean).join(`
2
+ `)}function Kn({active:e,build:t,busy:r,onDeactivate:o,onRerun:n,onCopied:i}){let[c]=Vn(()=>Math.max(1,Math.round((Date.now()-e.runAt)/6e4))),s=On(()=>{Wn(Mn(e,t)),i?.()},[e,t,i]);return Oe(_,{tone:"sim",testID:"scenario-active-card",children:[Oe(g,{style:fe.head,children:[re(g,{style:fe.dot}),Oe(g,{style:fe.headText,children:[re(f,{style:fe.simulated,children:"SIMULATED"}),re(f,{style:fe.name,numberOfLines:2,testID:"scenario-active-name",children:e.name})]}),Oe(f,{style:fe.ago,children:[c,"m ago"]})]}),re(X,{}),e.effects.map((l,u)=>{let d=Nn(l);return Oe(g,{style:fe.effect,children:[re(f,{style:fe.effectText,numberOfLines:1,children:l.label}),re(_e,{label:d.label,tone:d.tone})]},`${l.kind}-${u}`)}),Oe(g,{style:fe.actions,children:[re(Wt,{label:"Deactivate",variant:"warning",size:"small",onPress:o,disabled:r,icon:re(Fn,{size:11,color:a.color.sim}),testID:"scenario-deactivate"}),re(Wt,{label:"Copy repro info",variant:"ghost",size:"small",onPress:s,icon:re(Hn,{size:11,color:a.color.textSecondary}),testID:"scenario-copy-repro"}),re(Wt,{label:"Re-run",variant:"ghost",size:"small",onPress:n,disabled:r,icon:re(jn,{size:11,color:a.color.textSecondary}),testID:"scenario-rerun"})]})]})}var fe=H.create({head:{flexDirection:"row",alignItems:"flex-start",gap:8,paddingHorizontal:a.textInset,paddingTop:10,paddingBottom:10},dot:{width:8,height:8,borderRadius:4,backgroundColor:a.color.sim,marginTop:4},headText:{flex:1,minWidth:0},simulated:{color:a.color.sim,fontSize:a.font.micro,fontWeight:"700",letterSpacing:.8,fontFamily:N},name:{color:a.color.text,fontSize:a.font.row,fontWeight:"600",marginTop:2},ago:{color:a.color.textTertiary,fontSize:a.font.micro,fontFamily:N,marginTop:2},effect:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:a.textInset,paddingVertical:7},effectText:{flex:1,minWidth:0,color:a.color.textSecondary,fontSize:a.font.control,fontFamily:N},actions:{flexDirection:"row",flexWrap:"wrap",gap:6,paddingHorizontal:a.textInset,paddingTop:8,paddingBottom:10}});import{AlertTriangle as qn,Check as Un,ToolButton as _n}from"@buoy-gg/shared-ui/web";import{jsx as De,jsxs as Wr}from"react/jsx-runtime";function Jn({report:e,onDismiss:t}){let r=[];e.removedRules&&r.push({tone:"ok",text:`${e.removedRules} override rule${e.removedRules===1?"":"s"} removed \u2014 pull to refresh shows real data`}),e.stoppedImpersonation&&r.push({tone:"ok",text:"Impersonation ended"}),e.clearedTransients&&r.push({tone:"ok",text:`${e.clearedTransients} one-shot effect${e.clearedTransients===1?"":"s"} had nothing to remove`}),e.undoStepsRan&&r.push({tone:"ok",text:`${e.undoStepsRan} undo step${e.undoStepsRan===1?"":"s"} ran`}),e.unrestoredStorageKeys.length&&r.push({tone:"warn",text:`${e.unrestoredStorageKeys.length} storage key${e.unrestoredStorageKeys.length===1?"":"s"} NOT restored: ${e.unrestoredStorageKeys.join(", ")} \u2014 a storage write has no automatic inverse. Re-run your login flow, or restore a Time Machine snapshot.`});let o=e.unrestoredState??[];o.length&&r.push({tone:"warn",text:`${o.length} store${o.length===1?"":"s"} still hold${o.length===1?"s":""} what this scenario wrote: ${o.join(", ")} \u2014 a state write has no automatic inverse. Reset it in its own tool, or restore a Time Machine snapshot.`});for(let i of e.errors)r.push({tone:"warn",text:i});r.length||r.push({tone:"ok",text:"Nothing left to undo \u2014 the app is real."});let n=r.every(i=>i.tone==="ok");return De(_,{tone:n?"neutral":"sim",children:Wr(g,{style:Je.body,children:[De(f,{style:Je.title,testID:"scenario-deactivate-report",children:"DEACTIVATED"}),r.map((i,c)=>Wr(g,{style:Je.line,children:[i.tone==="ok"?De(Un,{size:12,color:a.color.accent}):De(qn,{size:12,color:a.color.sim}),De(f,{style:Je.text,children:i.text})]},`${i.tone}-${c}`)),De(g,{style:Je.actions,children:De(_n,{label:"Done",variant:"primary",size:"small",onPress:t,testID:"scenario-dismiss-report"})})]})})}var Je=H.create({body:{padding:a.textInset,gap:8},title:{color:a.color.textSecondary,fontSize:a.font.micro,fontWeight:"700",letterSpacing:.8,fontFamily:N},line:{flexDirection:"row",gap:8,alignItems:"flex-start"},text:{flex:1,color:a.color.textSecondary,fontSize:a.font.control,lineHeight:17},actions:{flexDirection:"row",marginTop:2}});import{Fragment as Nr,useCallback as Gn,useMemo as Xn,useState as Yn}from"react";import{Layers as Qn,Play as Zn,Hash as ei,ToolButton as Nt}from"@buoy-gg/shared-ui/web";import{useToolHeader as ti}from"@buoy-gg/core/web";import{Fragment as Mr,jsx as I,jsxs as M}from"react/jsx-runtime";function ri(e){return e==="durable"?"durable":e==="transient"?"transient":"neutral"}var oi={durable:"survives restart",session:"until restart",transient:"until refetch \u26A0","one-shot":"one-shot"};function ai({variable:e,value:t,onChange:r}){let o=e.label??e.key,n=`scenario-var-${e.key}`;return e.type==="enum"&&e.options?.length?M(g,{style:x.field,children:[I(f,{style:x.fieldLabel,children:o}),I(g,{style:x.segs,children:e.options.map(i=>{let c=String(t)===String(i);return I(W,{style:[x.seg,c?x.segOn:null],onPress:()=>r(i),accessibilityRole:"button",accessibilityState:{selected:c},testID:`${n}-${String(i)}`,children:I(f,{style:[x.segText,c?x.segTextOn:null],children:String(i)})},String(i))})})]}):e.type==="boolean"?M(g,{style:[x.field,x.fieldRow],children:[I(f,{style:x.fieldLabel,children:o}),I(sr,{value:t===true,onValueChange:i=>r(i),testID:n})]}):M(g,{style:x.field,children:[I(f,{style:x.fieldLabel,children:o}),I(tt,{style:x.input,value:t===void 0?"":String(t),onChangeText:i=>r(cr(e,i)),keyboardType:e.type==="number"?"numeric":"default",placeholder:e.type==="number"?"0":"value",placeholderTextColor:a.color.textTertiary,autoCapitalize:"none",autoCorrect:false,testID:n})]})}function ni({scenario:e,initialValues:t,check:r,currentBuild:o,mode:n,onRun:i,onAcceptDraft:c,onDiscardDraft:s,onBack:l}){let[u,d]=Yn(t);ti({title:n==="review-draft"?"Review draft":"Before you run",subtitle:xe(e.name,u),onBack:l,searchable:false},[e.id,n]);let h=Xn(()=>r(u),[r,u]),v=Gn((w,R)=>{d(V=>({...V,[w]:R}))},[]),y=!!e.authoredAgainst&&!!o&&e.authoredAgainst!==o&&e.verifiedAt?.build!==o,C=!h.ok;return M(g,{style:x.fill,children:[M(ye,{style:x.fill,contentContainerStyle:x.content,keyboardShouldPersistTaps:"handled",testID:"scenario-preview-scroll",children:[e.description?I(te,{testID:"scenario-preview-description",children:e.description}):null,e.vars.length?M(Mr,{children:[I(U,{icon:ei,count:e.vars.length,children:"Variables"}),I(_,{children:e.vars.map((w,R)=>M(Nr,{children:[R>0?I(X,{}):null,I(ai,{variable:w,value:u[w.key],onChange:V=>v(w.key,V)})]},w.key))})]}):null,I(U,{icon:Qn,count:e.steps.length,children:"What this will do"}),I(_,{children:e.steps.map((w,R)=>{let V=be(w.params??{},u),$=Ke(w);return M(Nr,{children:[R>0?I(X,{}):null,M(g,{style:x.step,children:[I(g,{style:x.stepIndex,children:I(f,{style:x.stepIndexText,children:R+1})}),M(g,{style:x.stepBody,children:[I(f,{style:x.stepLabel,children:Ee(w,V)}),M(f,{style:x.stepTool,children:[w.tool,".",w.action]})]}),I(_e,{label:oi[$],tone:ri($)})]})]},w.id)})}),y?I(he,{tone:"sim",testID:"scenario-preview-stale",children:M(f,{style:x.warnText,children:["Authored against app ",e.authoredAgainst," \u2014 unverified on this build. The response shape it overrides may have drifted."]})}):null,h.conflict?I(he,{tone:"sim",testID:"scenario-preview-conflict",children:M(f,{style:x.warnText,children:["Conflict: \u201C",h.conflict.activeName,"\u201D is active and touches the same ",h.conflict.overlaps.length===1?"target":"targets",". Running will swap \u2014 it deactivates first, so the two can never overlap silently."]})}):null,h.errors.length?I(he,{tone:"danger",testID:"scenario-preview-errors",children:h.errors.map(w=>M(f,{style:x.errorText,children:["\u2022 ",w]},w))}):null,h.warnings.length?I(he,{tone:"sim",children:h.warnings.map(w=>M(f,{style:x.warnText,children:["\u2022 ",w]},w))}):null,e.expectedOutcome?I(he,{tone:"info",testID:"scenario-preview-expected",children:M(f,{style:x.infoText,children:[I(f,{style:x.infoStrong,children:"Expected outcome: "}),e.expectedOutcome]})}):null]}),I(g,{style:x.footer,children:n==="review-draft"?M(Mr,{children:[I(Nt,{label:"Discard",variant:"ghost",onPress:()=>s?.(),style:x.grow,testID:"scenario-discard-draft"}),I(Nt,{label:"Accept to library",variant:"primary",onPress:()=>c?.(),style:x.grow,testID:"scenario-accept-draft"})]}):I(Nt,{label:h.conflict?"Swap & run":"Run",variant:"primary",onPress:()=>i(u),disabled:C,icon:I(Zn,{size:12,color:a.color.accent}),style:x.grow,testID:"scenario-confirm-run"})})]})}var x=H.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:24},field:{paddingHorizontal:a.textInset,paddingVertical:10,gap:6},fieldRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between"},fieldLabel:{color:a.color.textTertiary,fontSize:a.font.micro,fontWeight:"600",letterSpacing:.6,textTransform:"uppercase"},segs:{flexDirection:"row",flexWrap:"wrap",gap:6},seg:{borderRadius:a.radius.row,borderWidth:1,borderColor:a.color.border,backgroundColor:a.color.chip,paddingHorizontal:12,paddingVertical:6},segOn:{backgroundColor:a.color.accentSoft,borderColor:a.color.accentBorderStrong},segText:{color:a.color.textSecondary,fontSize:a.font.control,fontFamily:N},segTextOn:{color:a.color.accent,fontWeight:"700"},input:{backgroundColor:a.color.row,borderRadius:a.radius.row,borderWidth:1,borderColor:a.color.border,color:a.color.text,fontSize:a.font.row,fontFamily:N,paddingHorizontal:10,paddingVertical:8},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:a.textInset,paddingVertical:10},stepIndex:{width:18,height:18,borderRadius:a.radius.badge,backgroundColor:a.color.fill,alignItems:"center",justifyContent:"center",marginTop:1},stepIndexText:{color:a.color.textTertiary,fontSize:10,fontWeight:"700",fontFamily:N},stepBody:{flex:1,minWidth:0},stepLabel:{color:a.color.text,fontSize:a.font.control},stepTool:{color:a.color.textTertiary,fontSize:a.font.mono,fontFamily:N,marginTop:2},warnText:{color:a.color.sim,fontSize:a.font.control,lineHeight:17},errorText:{color:a.color.danger,fontSize:a.font.control,lineHeight:17},infoText:{color:"#7FA9FF",fontSize:a.font.control,lineHeight:17},infoStrong:{fontWeight:"700"},footer:{flexDirection:"row",gap:8,paddingHorizontal:a.gutter,paddingTop:10,paddingBottom:14,borderTopWidth:1,borderTopColor:a.color.border,backgroundColor:a.color.surface},grow:{flex:1}});import{Fragment as ii}from"react";import{Check as si,Layers as li,RefreshCw as ci,ToolButton as lt,X as di}from"@buoy-gg/shared-ui/web";import{useToolHeader as ui}from"@buoy-gg/core/web";import{Fragment as hi,jsx as z,jsxs as ie}from"react/jsx-runtime";function fi({runState:e,busy:t,onUndoPartial:r,onKeepPartial:o,onRetry:n,onDone:i,onBack:c}){let s=e.report,l=!!s&&!s.ok;ui({title:l?"Run failed":e.done?"Run complete":"Running\u2026",subtitle:e.name,onBack:e.done?c:void 0,searchable:false},[e.done,l,e.name]);let u=s?.steps??e.steps;return ie(g,{style:P.fill,children:[ie(ye,{style:P.fill,contentContainerStyle:P.content,testID:"scenario-run-scroll",children:[z(U,{icon:li,color:l?a.color.danger:a.color.accent,children:"Steps"}),ie(_,{tone:l?"danger":"neutral",children:[u.length===0?ie(g,{style:P.step,children:[z(Tt,{size:"small",color:a.color.accent}),z(f,{style:P.stepLabel,children:"Starting\u2026"})]}):null,u.map((d,h)=>ie(ii,{children:[h>0?z(X,{}):null,ie(g,{style:P.step,children:[z(g,{style:P.mark,children:d.skipped?z(f,{style:P.skipped,children:"\u2013"}):d.ok?z(si,{size:13,color:a.color.accent}):z(di,{size:13,color:a.color.danger})}),ie(g,{style:P.stepBody,children:[z(f,{style:[P.stepLabel,d.skipped?P.dim:null],testID:`scenario-step-${h}`,children:d.label}),d.error?z(f,{style:P.error,testID:`scenario-step-${h}-error`,children:d.error}):null,d.skipped?z(f,{style:P.dimSmall,children:"skipped"}):null]}),d.ms?ie(f,{style:P.ms,children:[d.ms,"ms"]}):null]})]},d.id)),!e.done&&u.length?ie(hi,{children:[z(X,{}),ie(g,{style:P.step,children:[z(Tt,{size:"small",color:a.color.accent}),z(f,{style:P.stepLabel,children:"Working\u2026"})]})]}):null]}),l?z(he,{tone:"danger",children:z(f,{style:P.errorText,children:"The run stopped at the failing step. Nothing after it ran \u2014 but the steps before it did, so choose what happens to them."})}):null]}),l?ie(g,{style:P.footer,children:[z(lt,{label:"Undo applied steps",variant:"primary",onPress:r,disabled:t,style:P.grow,testID:"scenario-undo-partial"}),z(lt,{label:"Keep",variant:"ghost",onPress:o,testID:"scenario-keep-partial"}),z(lt,{label:"Retry",variant:"ghost",onPress:n,disabled:t,icon:z(ci,{size:12,color:a.color.textSecondary}),testID:"scenario-retry"})]}):e.done?z(g,{style:P.footer,children:z(lt,{label:"Done",variant:"primary",onPress:i,style:P.grow,testID:"scenario-run-done"})}):null]})}var P=H.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:24},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:a.textInset,paddingVertical:10},mark:{width:18,alignItems:"center",marginTop:1},skipped:{color:a.color.textTertiary,fontSize:13,fontFamily:N},stepBody:{flex:1,minWidth:0},stepLabel:{color:a.color.text,fontSize:a.font.control},dim:{color:a.color.textTertiary},dimSmall:{color:a.color.textTertiary,fontSize:a.font.mono,marginTop:2,fontFamily:N},error:{color:a.color.danger,fontSize:a.font.mono,marginTop:3,fontFamily:N},ms:{color:a.color.textTertiary,fontSize:a.font.micro,fontFamily:N,marginTop:3},errorText:{color:a.color.danger,fontSize:a.font.control,lineHeight:17},footer:{flexDirection:"row",gap:8,paddingHorizontal:a.gutter,paddingTop:10,paddingBottom:14,borderTopWidth:1,borderTopColor:a.color.border,backgroundColor:a.color.surface},grow:{flex:1}});import{Fragment as pi}from"react";import{CheckCircle as mi,ChevronRight as gi,Copy as yi,FileText as bi,Layers as vi,Play as wi,ToolButton as Ve,Trash as Si,Upload as xi,Users as Ii,copyToClipboard as Ti}from"@buoy-gg/shared-ui/web";import{useToolHeader as Di}from"@buoy-gg/core/web";import{memo as ki}from"react";import{CompactRow as Ci}from"@buoy-gg/shared-ui/web";import{Fragment as Ri,jsx as He,jsxs as $i}from"react/jsx-runtime";function we(e){return e.replace(/\{\{\s*(\w+)\s*\}\}/g,"\u27E8$1\u27E9")}function Kr(e){let t=[`v${e.version}`];e.source==="team"&&e.team?t.push(`shared by ${e.team.sharedBy.label}`):e.author&&t.push(e.author);let r=e.usage?.runs??0;return r&&t.push(`${r}\xD7`),e.unsavedToRepo&&t.push("unsaved to repo"),e.source==="draft"&&t.push("inert until you accept"),t.join(" \xB7 ")}function Ai(e){return e.source==="code"?{label:"Shipped",color:a.color.accent}:e.source==="draft"?{label:"Draft",color:a.color.sim}:e.source==="team"?{label:"Team",color:a.color.accent}:{label:"Saved",color:a.color.info}}function Ei({scenario:e,currentBuild:t,disabled:r,showFolder:o,onOpen:n,onRun:i,testID:c}){let s=c??`scenario-row-${e.id}`,l=Ai(e),u=ue(e.folder),d=e.source==="draft"?{label:"Review",color:a.color.sim}:{label:"Run",color:a.color.accent},h=!!e.authoredAgainst&&!!t&&e.authoredAgainst!==t&&e.verifiedAt?.build!==t;return He(Ci,{statusDotColor:l.color,statusLabel:l.label,statusSublabel:`${e.steps.length} step${e.steps.length===1?"":"s"}`,primaryText:we(e.name),primaryTestID:`${s}-name`,secondaryText:Kr(e),secondaryTestID:`${s}-meta`,secondaryAccessory:$i(Ri,{children:[o&&u?He(_e,{label:u,tone:"neutral",testID:`${s}-folder`}):null,h?He(_e,{label:`stale \xB7 ${e.authoredAgainst}`,tone:"transient",testID:`${s}-stale`}):null]}),trailingAction:He(W,{onPress:i,disabled:r,style:r?Li.disabled:null,hitSlop:Bi,accessibilityRole:"button",accessibilityLabel:`${d.label} ${we(e.name)}`,testID:`${s}-run`,children:He(g,{children:He(zn,{label:d.label,color:d.color})})}),showChevron:true,onPress:n,testID:s,accessibilityLabel:`${we(e.name)}. ${l.label}, ${e.steps.length} step${e.steps.length===1?"":"s"}, ${Kr(e)}. Open details.`})}var ct=ki(Ei),Bi={top:8,bottom:8,left:8,right:8},Li=H.create({disabled:{opacity:.4}});import{Fragment as Ge,jsx as b,jsxs as Q}from"react/jsx-runtime";var zi={durable:"survives restart",session:"until restart",transient:"until refetch \u26A0","one-shot":"one-shot"};function Pi(e){return e==="durable"?"durable":e==="transient"?"transient":"neutral"}function qr(e){return e.source==="code"?"shipped with this app":e.source==="team"?`shared with your team by ${e.team?.sharedBy.label??"a teammate"}`:e.source==="draft"?"a draft, waiting for review":"saved on this device"}function Oi({scenario:e,onRun:t,onDelete:r,onDuplicate:o,onExported:n,onMoveToFolder:i,onShare:c,onRemoveFromTeam:s,teamBusy:l,onBack:u}){Di({title:we(e.name),subtitle:qr(e),onBack:u,searchable:false},[e.id]);let d=e.source==="device",h=ue(e.folder);return Q(ye,{style:L.fill,contentContainerStyle:L.content,testID:"scenario-detail-scroll",children:[e.description?b(te,{children:e.description}):null,b(U,{icon:vi,count:e.steps.length,children:"Steps"}),b(_,{children:e.steps.map((v,y)=>{let C=Ke(v);return Q(pi,{children:[y>0?b(X,{}):null,Q(g,{style:L.step,children:[b(g,{style:L.stepIndex,children:b(f,{style:L.stepIndexText,children:y+1})}),Q(g,{style:L.stepBody,children:[b(f,{style:L.stepLabel,children:Ee(v)}),Q(f,{style:L.stepTool,children:[v.tool,".",v.action,pr(v)?" \xB7 advanced":""]})]}),b(_e,{label:zi[C],tone:Pi(C)})]})]},v.id)})}),e.expectedOutcome?Q(Ge,{children:[b(U,{icon:mi,children:"Expected outcome"}),b(_,{children:b(f,{style:L.expected,children:e.expectedOutcome})})]}):null,b(U,{icon:bi,children:"Details"}),Q(_,{children:[b(ke,{label:"Folder",value:h??"No folder",muted:!h,onPress:d?i:void 0,testID:"scenario-detail-folder"}),b(X,{}),b(ke,{label:"Source",value:qr(e),testID:"scenario-detail-source"}),b(X,{}),b(ke,{label:"Version",value:`v${e.version}`}),e.author?Q(Ge,{children:[b(X,{}),b(ke,{label:"Author",value:e.author})]}):null,e.authoredAgainst?Q(Ge,{children:[b(X,{}),b(ke,{label:"Authored against",value:e.authoredAgainst})]}):null,b(X,{}),b(ke,{label:"Runs",value:String(e.usage?.runs??0)}),e.tags?.length?Q(Ge,{children:[b(X,{}),b(ke,{label:"Tags",value:e.tags.join(", ")})]}):null]}),Q(g,{style:L.footer,children:[b(Ve,{label:"Run",variant:"primary",onPress:t,icon:b(wi,{size:12,color:a.color.accent}),style:L.grow,testID:"scenario-detail-run"}),b(Ve,{label:"Export",variant:"ghost",onPress:()=>{Ti(JSON.stringify(e,null,2)),n?.()},icon:b(yi,{size:12,color:a.color.textSecondary}),style:L.grow,testID:"scenario-detail-export"})]}),d&&c?b(g,{style:L.footer,children:b(Ve,{label:l?"Sharing\u2026":"Share with team",variant:"ghost",onPress:c,disabled:l,icon:b(xi,{size:12,color:a.color.textSecondary}),style:L.grow,testID:"scenario-detail-share"})}):null,Q(g,{style:L.footer,children:[d?b(Ve,{label:"Delete",variant:"danger",onPress:r,icon:b(Si,{size:12,color:a.color.danger}),style:L.grow,testID:"scenario-detail-delete"}):b(Ve,{label:"Make an editable copy",variant:"ghost",onPress:o,style:L.grow,testID:"scenario-detail-duplicate"}),e.source==="team"&&s?b(Ve,{label:l?"Removing\u2026":"Remove from team",variant:"danger",onPress:s,disabled:l,icon:b(Ii,{size:12,color:a.color.danger}),style:L.grow,testID:"scenario-detail-remove-team"}):null]}),e.source==="code"?b(te,{children:"Shipped scenarios are read-only on the device \u2014 they change in a pull request, with the code they bend."}):null,e.source==="team"?b(te,{testID:"scenario-detail-team-note",children:"Your whole team sees this scenario in this app. It can't be changed here. Make an editable copy to change it on this device."}):null,d&&c?b(te,{children:"Share with team puts this scenario in Scenarios for everyone on your team, in this app."}):null]})}function ke({label:e,value:t,muted:r,onPress:o,testID:n}){let i=Q(Ge,{children:[b(f,{style:L.detailLabel,children:e}),b(f,{style:[L.detailValue,r&&L.detailValueMuted,o&&L.detailValueAction],numberOfLines:2,children:t}),o?b(gi,{size:13,color:a.color.textTertiary}):null]});return o?b(W,{style:L.detail,onPress:o,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`${e}: ${t}. Change it.`,testID:n,children:i}):b(g,{style:L.detail,testID:n,children:i})}var L=H.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:32},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:a.textInset,paddingVertical:10},stepIndex:{width:18,height:18,borderRadius:a.radius.badge,backgroundColor:a.color.fill,alignItems:"center",justifyContent:"center",marginTop:1},stepIndexText:{color:a.color.textTertiary,fontSize:10,fontWeight:"700",fontFamily:N},stepBody:{flex:1,minWidth:0},stepLabel:{color:a.color.text,fontSize:a.font.control},stepTool:{color:a.color.textTertiary,fontSize:a.font.mono,fontFamily:N,marginTop:2},expected:{color:a.color.textSecondary,fontSize:a.font.control,lineHeight:18,paddingHorizontal:a.textInset,paddingVertical:12},detail:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:8,minHeight:40,paddingHorizontal:a.textInset,paddingVertical:10},detailLabel:{color:a.color.textTertiary,fontSize:a.font.control},detailValue:{flex:1,textAlign:"right",color:a.color.textSecondary,fontSize:a.font.control,fontFamily:N},detailValueMuted:{color:a.color.textTertiary},detailValueAction:{color:a.color.accent},footer:{flexDirection:"row",gap:8,paddingHorizontal:a.gutter,paddingTop:12},grow:{flex:1}});import{jsx as dt,jsxs as Vi}from"react/jsx-runtime";function Hi(e,t){return t===null?true:Et(e,t)}function Mt(e){return e===null?"__all__":e===void 0?"__ungrouped__":e}function Fi({folders:e,active:t,onChange:r,scenarios:o}){let n=Bt(o,void 0),i=[{filter:null,label:"All",count:o.length},...e.map(c=>({filter:c,label:c,count:Bt(o,c)}))];return n&&i.push({filter:void 0,label:xr,count:n}),dt(ye,{horizontal:true,showsHorizontalScrollIndicator:false,style:le.scroll,contentContainerStyle:le.row,testID:"scenarios-folder-bar",children:i.map(c=>{let s=t===c.filter||typeof t=="string"&&typeof c.filter=="string"&&t.toLowerCase()===c.filter.toLowerCase();return Vi(W,{testID:`scenarios-folder-${Mt(c.filter)}`,accessibilityRole:"button",accessibilityLabel:`Show ${c.label} scenarios`,accessibilityState:{selected:s},activeOpacity:.8,onPress:()=>r(c.filter),style:[le.chip,s&&le.chipActive],children:[dt(f,{style:[le.label,s&&le.labelActive],numberOfLines:1,children:c.label}),dt(g,{style:[le.countPill,s&&le.countPillActive],children:dt(f,{style:[le.count,s&&le.countActive],testID:`scenarios-folder-${Mt(c.filter)}-count`,children:c.count})})]},Mt(c.filter))})})}var le=H.create({scroll:{flexGrow:0},row:{flexDirection:"row",gap:8,paddingHorizontal:a.gutter,paddingTop:10,paddingBottom:2},chip:{flexDirection:"row",alignItems:"center",gap:6,backgroundColor:a.color.chip,borderRadius:a.radius.card,borderWidth:1,borderColor:a.color.border,paddingVertical:6,paddingHorizontal:10,minHeight:32,maxWidth:200},chipActive:{backgroundColor:a.color.accentSoft,borderColor:a.color.accentBorderStrong},label:{fontSize:a.font.footnote,color:a.color.textSecondary,fontWeight:"500",flexShrink:1},labelActive:{color:a.color.accent,fontWeight:"600"},countPill:{minWidth:18,alignItems:"center",borderRadius:a.radius.badge,backgroundColor:a.color.fill,paddingHorizontal:4,paddingVertical:1},countPillActive:{backgroundColor:a.color.accentSoft},count:{fontSize:a.font.micro,fontWeight:"600",fontFamily:N,color:a.color.textTertiary},countActive:{color:a.color.accent}});import{useState as ji}from"react";import{Bookmark as Wi,Check as Ni,Plus as Mi,ToolButton as Ki}from"@buoy-gg/shared-ui/web";import{useToolHeader as qi}from"@buoy-gg/core/web";import{jsx as oe,jsxs as Fe}from"react/jsx-runtime";function Ui({scenario:e,folders:t,onPick:r,onBack:o}){let[n,i]=ji("");qi({title:"Move to folder",subtitle:we(e.name),onBack:o,searchable:false},[e.id]);let c=ue(e.folder),s=ue(n),l=!!s&&!t.some(u=>u.toLowerCase()===s.toLowerCase());return Fe(ye,{style:pe.fill,contentContainerStyle:pe.content,keyboardShouldPersistTaps:"handled",testID:"scenario-folder-scroll",children:[oe(U,{icon:Wi,count:t.length,children:"Folders"}),Fe(_,{children:[oe(Ur,{label:"No folder",hint:"Shows under Ungrouped",selected:!c,onPress:()=>r(void 0),testID:"scenario-folder-none"}),t.map(u=>Fe(g,{children:[oe(X,{}),oe(Ur,{label:u,selected:!!c&&c.toLowerCase()===u.toLowerCase(),onPress:()=>r(u),testID:`scenario-folder-pick-${u.toLowerCase().replace(/\s+/g,"-")}`})]},u))]}),oe(U,{icon:Mi,children:"New folder"}),oe(_,{children:Fe(g,{style:pe.newRow,children:[oe(tt,{style:pe.input,value:n,onChangeText:i,placeholder:"Checkout",placeholderTextColor:a.color.textTertiary,maxLength:32,autoCapitalize:"words",autoCorrect:false,returnKeyType:"done",onSubmitEditing:()=>s&&r(s),testID:"scenario-folder-new-input"}),oe(Ki,{label:s&&!l?"Use":"Create",variant:"primary",size:"small",disabled:!s,onPress:()=>s&&r(s),testID:"scenario-folder-create"})]})}),oe(te,{children:"A folder exists as long as something is filed in it \u2014 empty it and it goes away. Typing a name that already exists files it there instead of making a second one."})]})}function Ur({label:e,hint:t,selected:r,onPress:o,testID:n}){return Fe(W,{style:pe.row,onPress:o,activeOpacity:.7,accessibilityRole:"button",accessibilityState:{selected:r},accessibilityLabel:`File under ${e}`,testID:n,children:[Fe(g,{style:pe.rowText,children:[oe(f,{style:[pe.rowLabel,r&&pe.rowLabelSelected],numberOfLines:1,children:e}),t?oe(f,{style:pe.rowHint,children:t}):null]}),r?oe(Ni,{size:14,color:a.color.accent}):null]})}var pe=H.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:32},row:{flexDirection:"row",alignItems:"center",gap:12,minHeight:a.rowMinHeight,paddingHorizontal:a.textInset,paddingVertical:10},rowText:{flex:1,minWidth:0},rowLabel:{color:a.color.text,fontSize:a.font.row},rowLabelSelected:{color:a.color.accent,fontWeight:"600"},rowHint:{color:a.color.textTertiary,fontSize:a.font.micro,marginTop:2},newRow:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:a.textInset,paddingVertical:10},input:{flex:1,backgroundColor:a.color.row,borderRadius:a.radius.row,borderWidth:1,borderColor:a.color.border,color:a.color.text,fontSize:a.font.row,fontFamily:N,paddingHorizontal:10,paddingVertical:8}});import{Fragment as Kt,jsx as S,jsxs as ce}from"react/jsx-runtime";function _i(e){return`macro-${e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,40)||"recording"}-${Date.now().toString(36)}`}function ut({currentBuild:e}){let t=zr(),r=Pr(),o=Or(),n=Da(),i=Ia({minBottom:16}),c=xa("scenarios.saved"),[s,l]=et({name:"list"}),[u,d]=et(false),[h,v]=et(false);lo(()=>(m.refreshTeam(),wa(()=>{m.onAccountChange()})),[]);let y=Se(()=>l({name:"list"}),[]),C=Se(p=>T=>m.checkBeforeRun(p,T),[]),w=Se(async(p,T)=>{d(true),l({name:"run"});try{let A=await m.run(p,T);A.ok&&(n.showToast(`Scenario active \u2014 ${A.effects.length} change${A.effects.length===1?"":"s"}`,"success"),m.clearRunState(),l({name:"list"}),n.minimize())}catch(A){n.showToast(A instanceof Error?A.message:String(A),"error"),l({name:"list"})}finally{d(false)}},[n]),R=Se(async()=>{d(true);try{await m.deactivate()}finally{d(false)}},[]),V=Se(async()=>{await ae.start();let{status:p,reason:T}=ae.getState();if(p!=="recording"){n.showToast(T??"Recording isn't available in this app.","error");return}n.minimize()},[n]),$=Se(async(p,T)=>{d(true);try{let A=Ft(T),Ye=Date.now();await m.saveScenario({id:_i(p),name:p,version:1,source:"device",author:"recorded here",vars:[],steps:A,authoredAgainst:e,unsavedToRepo:true,createdAt:Ye,updatedAt:Ye,usage:{runs:0}}),await ae.cancel(),n.showToast(`Saved \u201C${p}\u201D`,"success"),y()}catch(A){n.showToast(A instanceof Error?A.message:String(A),"error")}finally{d(false)}},[e,y,n]);if(o.status==="review"&&o.draft)return S(jr,{draft:o.draft,busy:u,onChange:p=>ae.setDraft(p),onSave:$,onDiscard:()=>{We.alert("Discard this recording?","The steps you just recorded will be thrown away.",[{text:"Keep",style:"cancel"},{text:"Discard",style:"destructive",onPress:()=>{ae.cancel(),y()}}])}});if(s.name==="run"&&r)return S(fi,{runState:r,busy:u,onUndoPartial:async()=>{d(true);try{await m.undoPartialRun(),n.showToast("Applied steps undone","success")}finally{d(false),y()}},onKeepPartial:()=>{m.clearRunState(),y()},onRetry:()=>{let p=r.scenarioId;m.find(p)&&w(p,m.lastValuesFor(p))},onDone:()=>{m.clearRunState(),y()},onBack:()=>{m.clearRunState(),y()}});if(s.name==="preview"){let p=m.find(s.scenarioId);if(!p)return S(ht,{...j()});let T={...Me(p.vars),...m.lastValuesFor(p.id)};return S(ni,{scenario:p,initialValues:T,check:C(p),currentBuild:e,mode:s.mode,onRun:A=>{m.rememberVarValues(p.id,A),w(p.id,A)},onAcceptDraft:async()=>{await m.acceptDraft(p.id),n.showToast("Accepted \u2014 it's now in your library","success"),y()},onDiscardDraft:async()=>{await m.discardDraft(p.id),n.showToast("Draft discarded","info"),y()},onBack:y})}if(s.name==="detail"){let p=m.find(s.scenarioId);return p?S(Oi,{scenario:p,onRun:()=>l({name:"preview",scenarioId:p.id,mode:"run"}),onDelete:()=>{We.alert("Delete scenario?",`\u201C${we(p.name)}\u201D will be removed from this device.`,[{text:"Cancel",style:"cancel"},{text:"Delete",style:"destructive",onPress:()=>{m.deleteScenario(p.id),y()}}])},onDuplicate:async()=>{let T={...p,id:`${p.id}-copy-${Date.now().toString(36)}`,name:`${p.name} (copy)`,source:"device",version:1,unsavedToRepo:true,team:void 0};await m.saveScenario(T),n.showToast("Copied to this device","success"),y()},onExported:()=>n.showToast("Scenario JSON copied","success"),onMoveToFolder:()=>l({name:"folder",scenarioId:p.id}),teamBusy:h,onShare:p.source==="device"&&!m.isMirror()&&(t.teamInfo.status==="ready"||t.teamInfo.status==="error")?()=>{We.alert("Share with your team?",`Everyone on your team will see \u201C${we(p.name)}\u201D in Scenarios in this app.`,[{text:"Cancel",style:"cancel"},{text:"Share",onPress:async()=>{v(true);try{await m.shareWithTeam(p.id),n.showToast("Shared with your team","success")}catch(T){n.showToast(T instanceof Error?T.message:"Could not share it.","error")}finally{v(false)}}}])}:void 0,onRemoveFromTeam:m.canRemoveFromTeam(p)?()=>{We.alert("Remove from team?",`\u201C${we(p.name)}\u201D leaves Scenarios for everyone on your team.`,[{text:"Cancel",style:"cancel"},{text:"Remove",style:"destructive",onPress:async()=>{v(true);try{await m.removeFromTeam(p.id),n.showToast("Removed from your team","success"),y()}catch(T){n.showToast(T instanceof Error?T.message:"Could not remove it.","error")}finally{v(false)}}}])}:void 0,onBack:y}):S(ht,{...j()})}if(s.name==="folder"){let p=m.find(s.scenarioId);return p?S(Ui,{scenario:p,folders:m.folders(),onPick:async T=>{try{await m.setFolder(p.id,T),n.showToast(T?`Filed under ${T}`:"Removed from its folder","success")}catch(A){n.showToast(A instanceof Error?A.message:String(A),"error")}l({name:"detail",scenarioId:p.id})},onBack:()=>l({name:"detail",scenarioId:p.id})}):S(ht,{...j()})}function j(){return{state:t,insets:i,host:n,busy:u,savedLimit:c,currentBuild:e,onOpen:p=>l({name:"detail",scenarioId:p}),onRun:p=>l({name:"preview",scenarioId:p,mode:"run"}),onReviewDraft:p=>l({name:"preview",scenarioId:p,mode:"review-draft"}),onDeactivate:R,onRerun:()=>{let p=t.active;p&&w(p.scenarioId,p.varValues)},onStartRecording:V,canRecord:ae.canRecord(),recordUnavailable:o.status==="unavailable"?o.reason:null}}return S(ht,{...j()})}function qt(e,t,r){return e?"No matches.":t===void 0?"Nothing unfiled here.":t!==null?`Nothing in ${t}.`:r}function ht({state:e,insets:t,host:r,busy:o,savedLimit:n,currentBuild:i,onOpen:c,onRun:s,onReviewDraft:l,onDeactivate:u,onRerun:d,onStartRecording:h,canRecord:v,recordUnavailable:y}){let[C,w]=et(null),R=r.search.trim().toLowerCase(),V=D=>!R||D.name.toLowerCase().includes(R)||(D.folder??"").toLowerCase().includes(R)||(D.tags??[]).some(ro=>ro.toLowerCase().includes(R))||(D.author??"").toLowerCase().includes(R),$=new Set(e.code.map(D=>D.id)),j=e.team.filter(D=>!$.has(D.id)),p=new Set(j.map(D=>D.id)),T={code:e.code.filter(V),team:j.filter(V),device:e.device.filter(D=>!p.has(D.id)).filter(V),drafts:e.drafts.filter(V)},A=m.folders(),Ye=[...T.code,...T.team,...T.device,...T.drafts],Qe=D=>Hi(D,C),yt=T.code.filter(Qe),Zr=T.team.filter(Qe),bt=T.device.filter(Qe),vt=T.drafts.filter(Qe),eo=e.device.length>=n,to=m.isLongRunning(),Ze=C===null&&A.length>0,Jt=Se(()=>({shipped:e.code,saved:e.device,drafts:e.drafts,active:e.active??null}),[e.code,e.device,e.drafts,e.active]),Gt=co(()=>S(ba,{value:Jt,buttonStyle:K.headerButton,testID:"scenarios-copy-library",accessibilityLabel:"Copy the scenario library as JSON"}),[Jt]);return Ta({actions:Gt},[Gt]),ce(g,{style:K.fill,children:[A.length?S(Fi,{folders:A,active:C,onChange:w,scenarios:Ye}):null,ce(ye,{style:K.fill,contentContainerStyle:[K.content,{paddingBottom:t.bottom}],keyboardShouldPersistTaps:"handled",testID:"scenarios-scroll",children:[v?ce(W,{style:K.record,onPress:h,disabled:o,activeOpacity:.75,accessibilityRole:"button",accessibilityLabel:"Record what you do next as a macro",testID:"scenarios-record",children:[S(g,{style:K.recordDot}),ce(g,{style:K.recordText,children:[S(f,{style:K.recordTitle,children:"Record a macro"}),S(f,{style:K.recordHint,children:"Do the flow once. Buoy writes down the steps."})]})]}):null,y?S(te,{tone:"warning",testID:"scenarios-record-unavailable",children:y}):null,e.lastDeactivateReport?S(Jn,{report:e.lastDeactivateReport,onDismiss:()=>m.dismissDeactivateReport()}):null,e.active?ce(Kt,{children:[S(U,{icon:Sa,color:a.color.sim,testID:"scenarios-active-label",children:"Active now"}),S(Kn,{active:e.active,build:i,busy:o,onDeactivate:u,onRerun:d,onCopied:()=>r.showToast("Repro info copied \u2014 paste into the ticket","success")}),to?S(te,{tone:"warning",testID:"scenarios-long-running",children:"This scenario has been active for a while. If you have moved on to something else, deactivate it before you test anything real."}):null]}):null,vt.length?ce(Kt,{children:[S(U,{icon:ma,color:a.color.sim,count:vt.length,testID:"scenarios-drafts-label",children:"Awaiting review"}),vt.map(D=>S(ct,{scenario:D,currentBuild:i,disabled:o,showFolder:Ze,onOpen:()=>l(D.id),onRun:()=>l(D.id),testID:`scenario-draft-${D.id}`},D.id)),S(te,{children:"A scenario sent from chat or the desktop never runs on its own. You review what it will do, then accept it."})]}):null,S(U,{icon:pa,count:yt.length,testID:"scenarios-code-label",children:"Shipped with this app"}),yt.length?yt.map(D=>S(ct,{scenario:D,currentBuild:i,disabled:o,showFolder:Ze,onOpen:()=>c(D.id),onRun:()=>s(D.id)},D.id)):S(_,{children:S(f,{style:K.empty,testID:"scenarios-code-empty",children:qt(R,C,"None yet \u2014 your developers can ship a QA menu with the app using defineScenario().")})}),S(Ji,{info:e.teamInfo,scenarios:Zr,query:R,folder:C,currentBuild:i,busy:o,showFolder:Ze,onOpen:c,onRun:s}),S(U,{icon:ya,color:a.color.info,count:bt.length,testID:"scenarios-device-label",children:"Saved on this device"}),bt.length?bt.map(D=>S(ct,{scenario:D,currentBuild:i,disabled:o,showFolder:Ze,onOpen:()=>c(D.id),onRun:()=>s(D.id)},D.id)):S(_,{children:S(f,{style:K.empty,testID:"scenarios-device-empty",children:qt(R,C,"Nothing saved here yet. Ask your AI assistant to save the state you just set up as a scenario.")})}),eo?ce(te,{tone:"warning",testID:"scenarios-limit",children:["Your plan keeps ",n," saved scenario",n===1?"":"s"," on a device. Scenarios shipped in code don't count toward it."]}):null,S(te,{children:A.length?"Scenarios only run in development builds. Tap a row to see exactly what it will do before you run it.":"Scenarios only run in development builds. Open one and tap its Folder row to group it by flow \u2014 Checkout, Login \u2014 and a folder bar appears up here."})]})]})}function Ji({info:e,scenarios:t,query:r,folder:o,currentBuild:n,busy:i,showFolder:c,onOpen:s,onRun:l}){if(!(t.length>0||e.status==="ready"||e.status==="error"||e.status==="off"&&e.reason!=="no-team"))return null;let u=e.status==="loading"?"Checking buoy.gg\u2026":e.status==="error"||e.status==="off"?e.message:null;return ce(Kt,{children:[S(U,{icon:va,color:a.color.accent,count:t.length,testID:"scenarios-team-label",children:"Shared with your team"}),ce(g,{style:K.teamBar,children:[S(f,{style:[K.teamStatus,(e.status==="error"||e.status==="off")&&K.teamStatusWarn],numberOfLines:3,testID:"scenarios-team-status",children:u??"Everyone on your team sees these in this app."}),!m.isMirror()&&(e.status!=="off"||e.reason!=="no-app")?ce(W,{style:K.teamRefresh,onPress:()=>void m.refreshTeam({force:true}),disabled:e.status==="loading",accessibilityRole:"button",accessibilityLabel:"Refresh the team's scenarios",testID:"scenarios-team-refresh",children:[S(ga,{size:12,color:a.color.textSecondary}),S(f,{style:K.teamRefreshText,children:"Refresh"})]}):null]}),t.length?t.map(d=>S(ct,{scenario:d,currentBuild:n,disabled:i,showFolder:c,onOpen:()=>s(d.id),onRun:()=>l(d.id),testID:`scenario-team-${d.id}`},d.id)):e.status==="ready"?S(_,{children:S(f,{style:K.empty,testID:"scenarios-team-empty",children:qt(r,o,"Nothing shared yet. Open a scenario saved on this device and tap Share with team.")})}):null]})}var K=H.create({teamBar:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:a.textInset,marginBottom:6},teamStatus:{flex:1,color:a.color.textTertiary,fontSize:a.font.footnote},teamStatusWarn:{color:a.color.sim},teamRefresh:{flexDirection:"row",alignItems:"center",gap:4,paddingVertical:4,paddingHorizontal:8,borderRadius:a.radius.pill,borderWidth:1,borderColor:a.color.border,backgroundColor:a.color.chip},teamRefreshText:{color:a.color.textSecondary,fontSize:a.font.control},fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:24},record:{flexDirection:"row",alignItems:"center",gap:10,marginHorizontal:a.gutter,marginTop:8,marginBottom:4,paddingHorizontal:a.textInset,paddingVertical:12,borderRadius:a.radius.card,borderWidth:1,borderColor:a.color.simBorder,backgroundColor:a.color.simSoft},recordDot:{width:10,height:10,borderRadius:5,backgroundColor:a.color.sim},recordText:{flex:1,minWidth:0},recordTitle:{color:a.color.sim,fontSize:a.font.row,fontWeight:"700"},recordHint:{color:a.color.textSecondary,fontSize:a.font.micro,marginTop:2},headerButton:{width:32,height:32,borderRadius:8,backgroundColor:a.color.chip,borderWidth:1,borderColor:a.color.border,alignItems:"center",justifyContent:"center"},empty:{color:a.color.textTertiary,fontSize:a.font.control,lineHeight:18,paddingHorizontal:a.textInset,paddingVertical:14}});import{jsx as _r}from"react/jsx-runtime";var ft={id:"scenarios",name:"SCENARIOS",description:"One-tap app states for QA, support and demos",slot:"both",icon:({size:e,color:t})=>_r(Zt,{size:e,color:t||er}),component:ut,modal:{subtitle:"saved one-tap app states",searchable:true,searchPlaceholder:"Search name, tag, author\u2026"}};function Gi(e={}){return e.scenarios?.length&&m.registerCodeScenarios(e.scenarios),{...ft,name:e.name??ft.name,description:e.description??ft.description,component:()=>_r(ut,{currentBuild:e.currentBuild})}}import{useCallback as Xi,useEffect as Yi,useState as Xe}from"react";import{useSafeAreaInsets as Qi}from"@buoy-gg/shared-ui/web";import{useCallback as Jr,useState as pt}from"react";import{openBuoyTool as Zi,useSafeAreaInsets as es}from"@buoy-gg/shared-ui/web";import{Fragment as ts,jsx as de,jsxs as Ut}from"react/jsx-runtime";var _t=52,rs=54;function Gr(){let e=Or(),t=jt(),r=es({minBottom:0}),[o]=pt(()=>new ge.ValueXY({x:0,y:0})),[n,i]=pt(false),[c,s]=pt(false),l=Jr(async()=>{i(true);try{await ae.stop()}finally{i(false)}},[]),u=Jr(()=>{Zi("scenarios")||s(true)},[]),[d]=pt(()=>wt.create({onMoveShouldSetPanResponder:(C,w)=>Math.abs(w.dy)>6,onPanResponderMove:ge.event([null,{dy:o.y}],{useNativeDriver:false}),onPanResponderRelease:()=>o.extractOffset()})),h=e.status==="review";if(e.status!=="recording"&&!h)return null;let v=h?(e.draft??[]).filter(C=>C.enabled&&!C.noise).length:e.actions.length,y=e.actions[e.actions.length-1];return de(ge.View,{style:[J.wrap,{top:r.top+_t+(t?rs:0)},{transform:o.getTranslateTransform()}],pointerEvents:"box-none",...d.panHandlers,children:Ut(g,{style:[J.banner,h&&J.bannerReview],testID:"recording-banner",accessible:false,children:[de(g,{style:[J.dot,h&&J.dotReview]}),Ut(g,{style:J.text,children:[de(f,{style:[J.title,h&&J.titleReview],children:h?`RECORDED \xB7 ${v} step${v===1?"":"s"}`:`\u25CF RECORDING \xB7 ${v} step${v===1?"":"s"}`}),de(f,{style:J.subtitle,numberOfLines:1,children:h?c?"Open Scenarios to review and save it.":"Review the steps, then save.":y?os(y.touch.target):"Drive the app \u2014 taps on Buoy itself are ignored."})]}),h?Ut(ts,{children:[de(W,{style:J.discard,onPress:()=>void ae.cancel(),accessibilityRole:"button",accessibilityLabel:"Discard the recording",testID:"recording-discard",children:de(f,{style:J.discardText,children:"Discard"})}),c?null:de(W,{style:J.review,onPress:u,accessibilityRole:"button",accessibilityLabel:"Review the recorded steps",testID:"recording-review",children:de(f,{style:J.reviewText,children:"Review"})})]}):de(W,{style:J.stop,onPress:l,disabled:n,accessibilityRole:"button",accessibilityLabel:"Stop recording and review the steps",testID:"recording-stop",children:de(f,{style:J.stopText,children:n?"\u2026":"Stop"})})]})})}function os(e){return e.label??e.text??e.testID??e.name}var J=H.create({wrap:{position:"absolute",left:12,right:12,zIndex:10001,alignItems:"center"},banner:{flexDirection:"row",alignItems:"center",gap:8,maxWidth:520,width:"100%",paddingLeft:14,paddingRight:8,paddingVertical:8,borderRadius:22,backgroundColor:"rgba(20, 20, 20, 0.94)",borderWidth:H.hairlineWidth,borderColor:a.color.dangerBorder,...St.select({ios:{shadowColor:"#000",shadowOpacity:.35,shadowRadius:12,shadowOffset:{width:0,height:6}},android:{elevation:8},default:{}})},dot:{width:8,height:8,borderRadius:4,backgroundColor:a.color.danger},text:{flex:1,minWidth:0},title:{color:a.color.danger,fontSize:10,fontWeight:"800",letterSpacing:.8},subtitle:{color:"rgba(255,255,255,0.85)",fontSize:11.5,marginTop:1},stop:{paddingHorizontal:12,height:28,borderRadius:14,alignItems:"center",justifyContent:"center",backgroundColor:"rgba(255, 59, 48, 0.15)"},stopText:{color:a.color.danger,fontSize:12,fontWeight:"700"},bannerReview:{borderColor:a.color.simBorder},dotReview:{backgroundColor:a.color.sim},titleReview:{color:a.color.sim},discard:{paddingHorizontal:12,height:28,borderRadius:14,alignItems:"center",justifyContent:"center",backgroundColor:"rgba(255,255,255,0.08)"},discardText:{color:"rgba(255,255,255,0.75)",fontSize:12,fontWeight:"600"},review:{paddingHorizontal:12,height:28,borderRadius:14,alignItems:"center",justifyContent:"center",backgroundColor:a.color.simSoft,borderWidth:H.hairlineWidth,borderColor:a.color.simBorder},reviewText:{color:a.color.sim,fontSize:12,fontWeight:"700"}});import{Fragment as as,jsx as Z,jsxs as mt}from"react/jsx-runtime";function ns(e){if(!e)return null;let t=e-Date.now();if(t<=0)return"expiring";let r=Math.floor(t/36e5),o=Math.round(t%36e5/6e4);return r?`auto-off ${r}h`:`auto-off ${o}m`}function Xr(){let e=jt(),t=Qi({minBottom:0}),[r,o]=Xe(false),[n]=Xe(()=>new ge.ValueXY({x:0,y:0})),i=Xi(()=>{m.deactivate()},[]),[c,s]=Xe(false),[l,u]=Xe(false);Yi(()=>{if(!l)return;let v=setTimeout(()=>u(false),2200);return()=>clearTimeout(v)},[l]);let[d]=Xe(()=>wt.create({onMoveShouldSetPanResponder:(v,y)=>Math.abs(y.dy)>6,onPanResponderMove:ge.event([null,{dy:n.y}],{useNativeDriver:false}),onPanResponderRelease:()=>{n.extractOffset()}}));if(!e)return null;let h=ns(e.expiresAt);return r?Z(ge.View,{style:[q.wrap,{top:t.top+_t},{transform:n.getTranslateTransform()}],pointerEvents:"box-none",...d.panHandlers,children:mt(W,{style:q.pill,onPress:()=>o(false),accessibilityRole:"button",accessibilityLabel:"Simulation active. Expand for details.",testID:"scenario-banner-pill",children:[Z(g,{style:q.dot}),Z(f,{style:q.pillText,children:"SIMULATED"})]})}):Z(ge.View,{style:[q.wrap,{top:t.top+_t},{transform:n.getTranslateTransform()}],pointerEvents:"box-none",...d.panHandlers,children:mt(g,{style:q.banner,testID:"scenario-banner",accessible:false,children:[Z(g,{style:q.dot}),mt(W,{style:q.text,onPress:()=>o(true),accessibilityRole:"button",accessibilityLabel:`Simulated: ${e.name}. ${e.effects.length} changes.`,testID:"scenario-banner-body",children:[Z(f,{style:q.title,children:"\u25B2 SIMULATED"}),Z(f,{style:[q.subtitle,l&&q.hint],numberOfLines:1,children:l?"Hold \u23FB to stop the scenario":`${e.name} \xB7 ${e.effects.length} ${e.effects.length===1?"change":"changes"}`})]}),h?Z(g,{style:q.expiry,children:Z(f,{style:q.expiryText,children:h})}):null,Z(W,{style:[q.off,c&&q.offHolding],onPress:()=>u(true),onLongPress:i,delayLongPress:600,onPressIn:()=>s(true),onPressOut:()=>s(false),accessibilityActions:[{name:"activate"},{name:"longpress"}],onAccessibilityAction:i,accessibilityHint:"Hold to stop",accessibilityRole:"button",accessibilityLabel:"Deactivate the scenario",testID:"scenario-stop-simulation",children:Z(f,{style:q.offText,children:"\u23FB"})})]})})}var q=H.create({wrap:{position:"absolute",left:12,right:12,zIndex:9998,alignItems:"center"},banner:{flexDirection:"row",alignItems:"center",gap:8,maxWidth:520,width:"100%",paddingLeft:14,paddingRight:8,paddingVertical:8,borderRadius:22,backgroundColor:"rgba(20, 20, 20, 0.94)",borderWidth:H.hairlineWidth,borderColor:a.color.simBorder,...St.select({ios:{shadowColor:"#000",shadowOpacity:.35,shadowRadius:12,shadowOffset:{width:0,height:6}},android:{elevation:8},default:{}})},pill:{flexDirection:"row",alignItems:"center",gap:6,paddingHorizontal:12,paddingVertical:6,borderRadius:22,backgroundColor:"rgba(20, 20, 20, 0.94)",borderWidth:H.hairlineWidth,borderColor:a.color.simBorder},pillText:{color:a.color.sim,fontSize:10,fontWeight:"800",letterSpacing:.8},dot:{width:7,height:7,borderRadius:2,backgroundColor:a.color.sim},text:{flex:1,minWidth:0},title:{color:a.color.sim,fontSize:10,fontWeight:"800",letterSpacing:.8},subtitle:{color:"rgba(255,255,255,0.85)",fontSize:11.5,marginTop:1},expiry:{paddingHorizontal:6,paddingVertical:2,borderRadius:6,backgroundColor:a.color.simSoft},expiryText:{color:a.color.sim,fontSize:10,fontWeight:"600"},off:{width:28,height:28,borderRadius:14,alignItems:"center",justifyContent:"center",backgroundColor:"rgba(255, 131, 41, 0.15)"},offHolding:{backgroundColor:a.color.sim},offText:{color:a.color.sim,fontSize:13},hint:{color:a.color.sim}});function is(){return mt(as,{children:[Z(Xr,{}),Z(Gr,{})]})}var ss=64*1024,ls=256*1024;function me(e,t){let r=e?.[t];return typeof r=="string"&&r.trim()?r.trim():void 0}function Yr(e){let t=e?.params;if(!t||typeof t!="object")return{};let r={};for(let[o,n]of Object.entries(t))(typeof n=="string"||typeof n=="number"||typeof n=="boolean")&&(r[o]=n);return r}var cs=8*1024;function gt(e){return{id:e.id,name:e.name,description:e.description,version:e.version,source:e.source,author:e.author,folder:e.folder,tags:e.tags,vars:e.vars,stepCount:e.steps.length,expectedOutcome:e.expectedOutcome,authoredAgainst:e.authoredAgainst,verifiedAt:e.verifiedAt,unsavedToRepo:e.unsavedToRepo,usage:e.usage,createdAt:e.createdAt,updatedAt:e.updatedAt,team:e.team,steps:e.steps.map(t=>JSON.stringify(t.params??{}).length>cs?{...t,params:void 0,paramsOmitted:true}:t),stepLines:e.steps.map(t=>({label:Ee(t),durability:Ke(t)}))}}function ds(e){let t=[];(!e.id||typeof e.id!="string")&&t.push("A scenario needs a string `id`."),(!e.name||typeof e.name!="string")&&t.push("A scenario needs a `name`."),!Array.isArray(e.steps)||!e.steps.length?t.push("A scenario needs at least one step."):e.steps.forEach((o,n)=>{if(!o||typeof o!="object"){t.push(`Step ${n+1} is not an object.`);return}(!o.tool||!o.action)&&t.push(`Step ${n+1} needs both \`tool\` and \`action\`.`);let i=JSON.stringify(o.params??{}).length;i>ss&&t.push(`Step ${n+1} is ${Math.round(i/1024)}KB \u2014 over the 64KB limit. Use a smaller response body.`)}),e.vars&&!Array.isArray(e.vars)&&t.push("`vars` must be an array.");let r=JSON.stringify(e).length;return r>ls&&t.push(`The scenario is ${Math.round(r/1024)}KB \u2014 over the 256KB limit.`),t}function Qr(){let e=m.getState();return{code:e.code.map(gt),device:e.device.map(gt),drafts:e.drafts.map(gt),team:e.team.map(gt),teamInfo:e.teamInfo,active:e.active,runState:e.runState,hasLoaded:e.hasLoaded,folders:m.folders()}}var us={dispose:e=>m.disposeAccountSession(e),version:1,getSnapshot:()=>Qr(),subscribe:e=>m.subscribe(e),actions:{listScenarios:()=>Qr(),getScenario:e=>{let t=me(e,"id");if(!t)throw new Error("getScenario requires an `id`");let r=m.find(t);if(!r)throw new Error(`No scenario "${t}"`);return{scenario:r}},save:async e=>{let t=(e??{}).scenario;if(!t)return{ok:false,error:"save requires a `scenario`."};let r=ds(t);if(r.length)return{ok:false,errors:r};let o=Date.now(),n={id:t.id,name:t.name,description:t.description,version:t.version??1,source:"draft",author:t.author??"remote",vars:t.vars??[],steps:t.steps,undoSteps:t.undoSteps,folder:t.folder,tags:t.tags,expectedOutcome:t.expectedOutcome,authoredAgainst:t.authoredAgainst,unsavedToRepo:true,createdAt:o,updatedAt:o,usage:{runs:0}};return{ok:true,savedAsDraft:true,id:(await m.saveScenario(n,{asDraft:true})).id,message:"Saved as a draft. Open Scenarios on the device to review and accept it."}},acceptDraft:async e=>{let t=me(e,"id");if(!t)throw new Error("acceptDraft requires an `id`");return{ok:true,id:(await m.acceptDraft(t)).id}},discardDraft:async e=>{let t=me(e,"id");if(!t)throw new Error("discardDraft requires an `id`");return await m.discardDraft(t),{ok:true,id:t}},preview:e=>{let t=me(e,"id");if(!t)throw new Error("preview requires an `id`");let r=m.find(t);if(!r)throw new Error(`No scenario "${t}"`);let o=Me(r.vars,Yr(e)),n=m.checkBeforeRun(r,o);return{willDo:r.steps.map(i=>({label:Ee(i,be(i.params??{},o)),durability:Ke(i)})),values:o,ok:n.ok,errors:n.errors,warnings:n.warnings,conflict:n.conflict,expectedOutcome:r.expectedOutcome}},run:async e=>{let t=me(e,"id");if(!t)throw new Error("run requires an `id`");let r=Yr(e),o=m.find(t);if(!o)throw new Error(`No scenario "${t}"`);let n=m.checkBeforeRun(o,r);return n.ok?await m.run(t,r):{ok:false,preflightErrors:n.errors,conflict:n.conflict}},deactivate:async()=>({ok:true,report:await m.deactivate()}),delete:async e=>{let t=me(e,"id");if(!t)throw new Error("delete requires an `id`");return await m.deleteScenario(t),{ok:true,id:t}},listFolders:()=>({folders:m.folders()}),setFolder:async e=>{let t=me(e,"id");if(!t)throw new Error("setFolder requires an `id`");let r=me(e,"folder"),o=await m.setFolder(t,r);return{ok:true,id:o.id,folder:o.folder??null}},getActive:()=>({active:m.getState().active}),export:e=>{let t=me(e,"id");if(!t)throw new Error("export requires an `id`");let r=m.find(t);if(!r)throw new Error(`No scenario "${t}"`);return{json:JSON.stringify(r,null,2)}}}};import{jsx as hs}from"react/jsx-runtime";function fs({currentBuild:e}){return hs(ut,{currentBuild:e})}m.ensureLoaded();export{La as DURABILITY_LABEL,Vt as MAX_DEVICE_SCENARIOS,Na as MAX_FOLDER_LENGTH,jr as MacroReviewScreen,Gr as RecordingBanner,er as SCENARIOS_ICON_COLOR,yr as SCENARIO_TIMEOUT_MS,fr as STEP_CATALOG,Rt as STEP_TIMEOUT_MS,Xr as ScenarioBanner,ut as ScenariosBody,Zt as ScenariosIcon,is as ScenariosOverlay,fs as ScenariosToolView,xr as UNGROUPED,Ae as catalogEntry,cr as coerceVarValue,Ne as collectPlaceholders,Br as condense,mr as conflictKeysOverlap,Bt as countInFolder,Gi as createScenariosTool,Ma as defineScenario,Ee as describeStep,Ar as describeTarget,Rr as humanizeTestID,Et as inFolder,be as interpolate,xe as interpolateString,pr as isAdvancedStep,Ir as listFolders,Ft as macroToSteps,Ca as missingVarKeys,ue as normalizeFolder,vr as preflight,ae as recorderStore,on as replaceScenariosFromSnapshot,At as resolveFolder,Me as resolveVarValues,qe as revertEffects,$t as runScenario,m as scenariosStore,us as scenariosSyncAdapter,ft as scenariosToolPreset,Er as selectorFor,tn as setRemoteScenariosHandler,Ct as stepConflictKeys,Ke as stepDurability,Ht as titleFor,jt as useActiveScenario,Pr as useScenariosRunState,zr as useScenariosState};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-gg/scenarios",
3
- "version": "7.0.76",
3
+ "version": "7.0.77",
4
4
  "description": "Scenarios - saved, parameterized one-tap app states (network overrides, storage, impersonation, navigation) for React Native DevTools",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -17,19 +17,19 @@
17
17
  "./lib/web/**/*.mjs"
18
18
  ],
19
19
  "dependencies": {
20
- "@buoy-gg/floating-tools-core": "^7.0.76",
21
- "@buoy-gg/shared-ui": "^7.0.76"
20
+ "@buoy-gg/floating-tools-core": "^7.0.77",
21
+ "@buoy-gg/shared-ui": "^7.0.77"
22
22
  },
23
23
  "peerDependencies": {
24
- "@buoy-gg/license": "7.0.76",
24
+ "@buoy-gg/license": "7.0.77",
25
25
  "react": "*"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/react": "^19.1.0",
29
29
  "@types/react-native": "^0.73.0",
30
30
  "typescript": "~5.8.3",
31
- "@buoy-gg/license": "^7.0.76",
32
- "@buoy-gg/core": "^7.0.76"
31
+ "@buoy-gg/license": "^7.0.77",
32
+ "@buoy-gg/core": "^7.0.77"
33
33
  },
34
34
  "react-native-builder-bob": {
35
35
  "source": "src",