@buoy-gg/scenarios 7.0.77 → 7.0.79

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.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.RunProgressScreen=RunProgressScreen;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _core=require("@buoy-gg/core");var _scnTheme=require("../ui/scnTheme");var _primitives=require("../ui/primitives");var _jsxRuntime=require("react/jsx-runtime");function RunProgressScreen({runState:r,busy:l,onUndoPartial:i,onKeepPartial:c,onRetry:a,onDone:d,onBack:p}){const t=r.report;const o=!!t&&!t.ok;(0,_core.useToolHeader)({title:o?"Run failed":r.done?"Run complete":"Running\u2026",subtitle:r.name,onBack:r.done?p:void 0,searchable:false},[r.done,o,r.name]);const n=t?.steps??r.steps;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.fill,children:[(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.fill,contentContainerStyle:styles.content,testID:"scenario-run-scroll",children:[(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{icon:_sharedUi.Layers,color:o?_scnTheme.scn.color.danger:_scnTheme.scn.color.accent,children:"Steps"}),(0,_jsxRuntime.jsxs)(_primitives.Panel,{tone:o?"danger":"neutral",children:[n.length===0?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.step,children:[(0,_jsxRuntime.jsx)(_reactNative.ActivityIndicator,{size:"small",color:_scnTheme.scn.color.accent}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.stepLabel,children:"Starting\u2026"})]}):null,n.map((e,s)=>(0,_jsxRuntime.jsxs)(_react.Fragment,{children:[s>0?(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.step,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.mark,children:e.skipped?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.skipped,children:"\u2013"}):e.ok?(0,_jsxRuntime.jsx)(_sharedUi.Check,{size:13,color:_scnTheme.scn.color.accent}):(0,_jsxRuntime.jsx)(_sharedUi.X,{size:13,color:_scnTheme.scn.color.danger})}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.stepBody,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.stepLabel,e.skipped?styles.dim:null],testID:`scenario-step-${s}`,children:e.label}),e.error?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.error,testID:`scenario-step-${s}-error`,children:e.error}):null,e.skipped?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.dimSmall,children:"skipped"}):null]}),e.ms?(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.ms,children:[e.ms,"ms"]}):null]})]},e.id)),!r.done&&n.length?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.step,children:[(0,_jsxRuntime.jsx)(_reactNative.ActivityIndicator,{size:"small",color:_scnTheme.scn.color.accent}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.stepLabel,children:"Working\u2026"})]})]}):null]}),o?(0,_jsxRuntime.jsx)(_primitives.Notice,{tone:"danger",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.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]}),o?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.footer,children:[(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Undo applied steps",variant:"primary",onPress:i,disabled:l,style:styles.grow,testID:"scenario-undo-partial"}),(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Keep",variant:"ghost",onPress:c,testID:"scenario-keep-partial"}),(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Retry",variant:"ghost",onPress:a,disabled:l,icon:(0,_jsxRuntime.jsx)(_sharedUi.RefreshCw,{size:12,color:_scnTheme.scn.color.textSecondary}),testID:"scenario-retry"})]}):r.done?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.footer,children:(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Done",variant:"primary",onPress:d,style:styles.grow,testID:"scenario-run-done"})}):null]})}const styles=_reactNative.StyleSheet.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:24},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:_scnTheme.scn.textInset,paddingVertical:10},mark:{width:18,alignItems:"center",marginTop:1},skipped:{color:_scnTheme.scn.color.textTertiary,fontSize:13,fontFamily:_scnTheme.SCN_MONO},stepBody:{flex:1,minWidth:0},stepLabel:{color:_scnTheme.scn.color.text,fontSize:_scnTheme.scn.font.control},dim:{color:_scnTheme.scn.color.textTertiary},dimSmall:{color:_scnTheme.scn.color.textTertiary,fontSize:_scnTheme.scn.font.mono,marginTop:2,fontFamily:_scnTheme.SCN_MONO},error:{color:_scnTheme.scn.color.danger,fontSize:_scnTheme.scn.font.mono,marginTop:3,fontFamily:_scnTheme.SCN_MONO},ms:{color:_scnTheme.scn.color.textTertiary,fontSize:_scnTheme.scn.font.micro,fontFamily:_scnTheme.SCN_MONO,marginTop:3},errorText:{color:_scnTheme.scn.color.danger,fontSize:_scnTheme.scn.font.control,lineHeight:17},footer:{flexDirection:"row",gap:8,paddingHorizontal:_scnTheme.scn.gutter,paddingTop:10,paddingBottom:14,borderTopWidth:1,borderTopColor:_scnTheme.scn.color.border,backgroundColor:_scnTheme.scn.color.surface},grow:{flex:1}});
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.RunProgressScreen=RunProgressScreen;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _core=require("@buoy-gg/core");var _scnTheme=require("../ui/scnTheme");var _primitives=require("../ui/primitives");var _jsxRuntime=require("react/jsx-runtime");function RunProgressScreen({runState:r,busy:l,onUndoPartial:i,onKeepPartial:c,onRetry:a,onDone:d,onBack:p}){const t=r.report;const o=!!t&&!t.ok;(0,_core.useToolHeader)({title:o?"Run failed":r.done?"Run complete":"Running\u2026",subtitle:r.name,onBack:r.done?p:void 0,searchable:false},[r.done,o,r.name]);const n=t?.steps??r.steps;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.fill,children:[(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{keyboardShouldPersistTaps:"handled",style:styles.fill,contentContainerStyle:styles.content,testID:"scenario-run-scroll",children:[(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{icon:_sharedUi.Layers,color:o?_scnTheme.scn.color.danger:_scnTheme.scn.color.accent,children:"Steps"}),(0,_jsxRuntime.jsxs)(_primitives.Panel,{tone:o?"danger":"neutral",children:[n.length===0?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.step,children:[(0,_jsxRuntime.jsx)(_reactNative.ActivityIndicator,{size:"small",color:_scnTheme.scn.color.accent}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.stepLabel,children:"Starting\u2026"})]}):null,n.map((e,s)=>(0,_jsxRuntime.jsxs)(_react.Fragment,{children:[s>0?(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.step,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.mark,children:e.skipped?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.skipped,children:"\u2013"}):e.ok?(0,_jsxRuntime.jsx)(_sharedUi.Check,{size:13,color:_scnTheme.scn.color.accent}):(0,_jsxRuntime.jsx)(_sharedUi.X,{size:13,color:_scnTheme.scn.color.danger})}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.stepBody,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.stepLabel,e.skipped?styles.dim:null],testID:`scenario-step-${s}`,children:e.label}),e.error?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.error,testID:`scenario-step-${s}-error`,children:e.error}):null,e.skipped?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.dimSmall,children:"skipped"}):null]}),e.ms?(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.ms,children:[e.ms,"ms"]}):null]})]},e.id)),!r.done&&n.length?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.step,children:[(0,_jsxRuntime.jsx)(_reactNative.ActivityIndicator,{size:"small",color:_scnTheme.scn.color.accent}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.stepLabel,children:"Working\u2026"})]})]}):null]}),o?(0,_jsxRuntime.jsx)(_primitives.Notice,{tone:"danger",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.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]}),o?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.footer,children:[(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Undo applied steps",variant:"primary",onPress:i,disabled:l,style:styles.grow,testID:"scenario-undo-partial"}),(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Keep",variant:"ghost",onPress:c,testID:"scenario-keep-partial"}),(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Retry",variant:"ghost",onPress:a,disabled:l,icon:(0,_jsxRuntime.jsx)(_sharedUi.RefreshCw,{size:12,color:_scnTheme.scn.color.textSecondary}),testID:"scenario-retry"})]}):r.done?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.footer,children:(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Done",variant:"primary",onPress:d,style:styles.grow,testID:"scenario-run-done"})}):null]})}const styles=_reactNative.StyleSheet.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:24},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:_scnTheme.scn.textInset,paddingVertical:10},mark:{width:18,alignItems:"center",marginTop:1},skipped:{color:_scnTheme.scn.color.textTertiary,fontSize:13,fontFamily:_scnTheme.SCN_MONO},stepBody:{flex:1,minWidth:0},stepLabel:{color:_scnTheme.scn.color.text,fontSize:_scnTheme.scn.font.control},dim:{color:_scnTheme.scn.color.textTertiary},dimSmall:{color:_scnTheme.scn.color.textTertiary,fontSize:_scnTheme.scn.font.mono,marginTop:2,fontFamily:_scnTheme.SCN_MONO},error:{color:_scnTheme.scn.color.danger,fontSize:_scnTheme.scn.font.mono,marginTop:3,fontFamily:_scnTheme.SCN_MONO},ms:{color:_scnTheme.scn.color.textTertiary,fontSize:_scnTheme.scn.font.micro,fontFamily:_scnTheme.SCN_MONO,marginTop:3},errorText:{color:_scnTheme.scn.color.danger,fontSize:_scnTheme.scn.font.control,lineHeight:17},footer:{flexDirection:"row",gap:8,paddingHorizontal:_scnTheme.scn.gutter,paddingTop:10,paddingBottom:14,borderTopWidth:1,borderTopColor:_scnTheme.scn.color.border,backgroundColor:_scnTheme.scn.color.surface},grow:{flex:1}});
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ScenarioDetailScreen=ScenarioDetailScreen;exports.sourceText=sourceText;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _core=require("@buoy-gg/core");var _catalog=require("../catalog");var _folders=require("../folders");var _scnTheme=require("../ui/scnTheme");var _primitives=require("../ui/primitives");var _ScenarioRow=require("./ScenarioRow");var _jsxRuntime=require("react/jsx-runtime");const DURABILITY_TEXT={durable:"survives restart",session:"until restart",transient:"until refetch \u26A0","one-shot":"one-shot"};function tone(e){if(e==="durable")return"durable";if(e==="transient")return"transient";return"neutral"}function sourceText(e){if(e.source==="code")return"shipped with this app";if(e.source==="team")return`shared with your team by ${e.team?.sharedBy.label??"a teammate"}`;if(e.source==="draft")return"a draft, waiting for review";return"saved on this device"}function ScenarioDetailScreen({scenario:e,onRun:o,onDelete:s,onDuplicate:t,onExported:l,onMoveToFolder:n,onShare:c,onRemoveFromTeam:d,teamBusy:i,onBack:p}){(0,_core.useToolHeader)({title:(0,_ScenarioRow.displayName)(e.name),subtitle:sourceText(e),onBack:p,searchable:false},[e.id]);const a=e.source==="device";const u=(0,_folders.normalizeFolder)(e.folder);return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.fill,contentContainerStyle:styles.content,testID:"scenario-detail-scroll",children:[e.description?(0,_jsxRuntime.jsx)(_primitives.Footnote,{children:e.description}):null,(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{icon:_sharedUi.Layers,count:e.steps.length,children:"Steps"}),(0,_jsxRuntime.jsx)(_primitives.Panel,{children:e.steps.map((r,x)=>{const h=(0,_catalog.stepDurability)(r);return(0,_jsxRuntime.jsxs)(_react.Fragment,{children:[x>0?(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.step,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.stepIndex,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.stepIndexText,children:x+1})}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.stepBody,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.stepLabel,children:(0,_catalog.describeStep)(r)}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.stepTool,children:[r.tool,".",r.action,(0,_catalog.isAdvancedStep)(r)?" \xB7 advanced":""]})]}),(0,_jsxRuntime.jsx)(_primitives.DurabilityChip,{label:DURABILITY_TEXT[h],tone:tone(h)})]})]},r.id)})}),e.expectedOutcome?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{icon:_sharedUi.CheckCircle,children:"Expected outcome"}),(0,_jsxRuntime.jsx)(_primitives.Panel,{children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.expected,children:e.expectedOutcome})})]}):null,(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{icon:_sharedUi.FileText,children:"Details"}),(0,_jsxRuntime.jsxs)(_primitives.Panel,{children:[(0,_jsxRuntime.jsx)(Detail,{label:"Folder",value:u??"No folder",muted:!u,onPress:a?n:void 0,testID:"scenario-detail-folder"}),(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Source",value:sourceText(e),testID:"scenario-detail-source"}),(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Version",value:`v${e.version}`}),e.author?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Author",value:e.author})]}):null,e.authoredAgainst?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Authored against",value:e.authoredAgainst})]}):null,(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Runs",value:String(e.usage?.runs??0)}),e.tags?.length?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Tags",value:e.tags.join(", ")})]}):null]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.footer,children:[(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Run",variant:"primary",onPress:o,icon:(0,_jsxRuntime.jsx)(_sharedUi.Play,{size:12,color:_scnTheme.scn.color.accent}),style:styles.grow,testID:"scenario-detail-run"}),(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Export",variant:"ghost",onPress:()=>{void(0,_sharedUi.copyToClipboard)(JSON.stringify(e,null,2));l?.()},icon:(0,_jsxRuntime.jsx)(_sharedUi.Copy,{size:12,color:_scnTheme.scn.color.textSecondary}),style:styles.grow,testID:"scenario-detail-export"})]}),a&&c?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.footer,children:(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:i?"Sharing\u2026":"Share with team",variant:"ghost",onPress:c,disabled:i,icon:(0,_jsxRuntime.jsx)(_sharedUi.Upload,{size:12,color:_scnTheme.scn.color.textSecondary}),style:styles.grow,testID:"scenario-detail-share"})}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.footer,children:[a?(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Delete",variant:"danger",onPress:s,icon:(0,_jsxRuntime.jsx)(_sharedUi.Trash,{size:12,color:_scnTheme.scn.color.danger}),style:styles.grow,testID:"scenario-detail-delete"}):(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Make an editable copy",variant:"ghost",onPress:t,style:styles.grow,testID:"scenario-detail-duplicate"}),e.source==="team"&&d?(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:i?"Removing\u2026":"Remove from team",variant:"danger",onPress:d,disabled:i,icon:(0,_jsxRuntime.jsx)(_sharedUi.Users,{size:12,color:_scnTheme.scn.color.danger}),style:styles.grow,testID:"scenario-detail-remove-team"}):null]}),e.source==="code"?(0,_jsxRuntime.jsx)(_primitives.Footnote,{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"?(0,_jsxRuntime.jsx)(_primitives.Footnote,{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,a&&c?(0,_jsxRuntime.jsx)(_primitives.Footnote,{children:"Share with team puts this scenario in Scenarios for everyone on your team, in this app."}):null]})}function Detail({label:e,value:o,muted:s,onPress:t,testID:l}){const n=(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailLabel,children:e}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.detailValue,s&&styles.detailValueMuted,t&&styles.detailValueAction],numberOfLines:2,children:o}),t?(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:13,color:_scnTheme.scn.color.textTertiary}):null]});if(!t){return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.detail,testID:l,children:n})}return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{style:styles.detail,onPress:t,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`${e}: ${o}. Change it.`,testID:l,children:n})}const styles=_reactNative.StyleSheet.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:32},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:_scnTheme.scn.textInset,paddingVertical:10},stepIndex:{width:18,height:18,borderRadius:_scnTheme.scn.radius.badge,backgroundColor:_scnTheme.scn.color.fill,alignItems:"center",justifyContent:"center",marginTop:1},stepIndexText:{color:_scnTheme.scn.color.textTertiary,fontSize:10,fontWeight:"700",fontFamily:_scnTheme.SCN_MONO},stepBody:{flex:1,minWidth:0},stepLabel:{color:_scnTheme.scn.color.text,fontSize:_scnTheme.scn.font.control},stepTool:{color:_scnTheme.scn.color.textTertiary,fontSize:_scnTheme.scn.font.mono,fontFamily:_scnTheme.SCN_MONO,marginTop:2},expected:{color:_scnTheme.scn.color.textSecondary,fontSize:_scnTheme.scn.font.control,lineHeight:18,paddingHorizontal:_scnTheme.scn.textInset,paddingVertical:12},detail:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:8,minHeight:40,paddingHorizontal:_scnTheme.scn.textInset,paddingVertical:10},detailLabel:{color:_scnTheme.scn.color.textTertiary,fontSize:_scnTheme.scn.font.control},detailValue:{flex:1,textAlign:"right",color:_scnTheme.scn.color.textSecondary,fontSize:_scnTheme.scn.font.control,fontFamily:_scnTheme.SCN_MONO},detailValueMuted:{color:_scnTheme.scn.color.textTertiary},detailValueAction:{color:_scnTheme.scn.color.accent},footer:{flexDirection:"row",gap:8,paddingHorizontal:_scnTheme.scn.gutter,paddingTop:12},grow:{flex:1}});
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ScenarioDetailScreen=ScenarioDetailScreen;exports.sourceText=sourceText;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _core=require("@buoy-gg/core");var _catalog=require("../catalog");var _folders=require("../folders");var _scnTheme=require("../ui/scnTheme");var _primitives=require("../ui/primitives");var _ScenarioRow=require("./ScenarioRow");var _jsxRuntime=require("react/jsx-runtime");const DURABILITY_TEXT={durable:"survives restart",session:"until restart",transient:"until refetch \u26A0","one-shot":"one-shot"};function tone(e){if(e==="durable")return"durable";if(e==="transient")return"transient";return"neutral"}function sourceText(e){if(e.source==="code")return"shipped with this app";if(e.source==="team")return`shared with your team by ${e.team?.sharedBy.label??"a teammate"}`;if(e.source==="draft")return"a draft, waiting for review";return"saved on this device"}function ScenarioDetailScreen({scenario:e,onRun:o,onDelete:s,onDuplicate:t,onExported:l,onMoveToFolder:n,onShare:c,onRemoveFromTeam:d,teamBusy:i,onBack:p}){(0,_core.useToolHeader)({title:(0,_ScenarioRow.displayName)(e.name),subtitle:sourceText(e),onBack:p,searchable:false},[e.id]);const a=e.source==="device";const u=(0,_folders.normalizeFolder)(e.folder);return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{keyboardShouldPersistTaps:"handled",style:styles.fill,contentContainerStyle:styles.content,testID:"scenario-detail-scroll",children:[e.description?(0,_jsxRuntime.jsx)(_primitives.Footnote,{children:e.description}):null,(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{icon:_sharedUi.Layers,count:e.steps.length,children:"Steps"}),(0,_jsxRuntime.jsx)(_primitives.Panel,{children:e.steps.map((r,x)=>{const h=(0,_catalog.stepDurability)(r);return(0,_jsxRuntime.jsxs)(_react.Fragment,{children:[x>0?(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.step,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.stepIndex,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.stepIndexText,children:x+1})}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.stepBody,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.stepLabel,children:(0,_catalog.describeStep)(r)}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.stepTool,children:[r.tool,".",r.action,(0,_catalog.isAdvancedStep)(r)?" \xB7 advanced":""]})]}),(0,_jsxRuntime.jsx)(_primitives.DurabilityChip,{label:DURABILITY_TEXT[h],tone:tone(h)})]})]},r.id)})}),e.expectedOutcome?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{icon:_sharedUi.CheckCircle,children:"Expected outcome"}),(0,_jsxRuntime.jsx)(_primitives.Panel,{children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.expected,children:e.expectedOutcome})})]}):null,(0,_jsxRuntime.jsx)(_primitives.SectionLabel,{icon:_sharedUi.FileText,children:"Details"}),(0,_jsxRuntime.jsxs)(_primitives.Panel,{children:[(0,_jsxRuntime.jsx)(Detail,{label:"Folder",value:u??"No folder",muted:!u,onPress:a?n:void 0,testID:"scenario-detail-folder"}),(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Source",value:sourceText(e),testID:"scenario-detail-source"}),(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Version",value:`v${e.version}`}),e.author?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Author",value:e.author})]}):null,e.authoredAgainst?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Authored against",value:e.authoredAgainst})]}):null,(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Runs",value:String(e.usage?.runs??0)}),e.tags?.length?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_primitives.PanelSeparator,{}),(0,_jsxRuntime.jsx)(Detail,{label:"Tags",value:e.tags.join(", ")})]}):null]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.footer,children:[(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Run",variant:"primary",onPress:o,icon:(0,_jsxRuntime.jsx)(_sharedUi.Play,{size:12,color:_scnTheme.scn.color.accent}),style:styles.grow,testID:"scenario-detail-run"}),(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Export",variant:"ghost",onPress:()=>{void(0,_sharedUi.copyToClipboard)(JSON.stringify(e,null,2));l?.()},icon:(0,_jsxRuntime.jsx)(_sharedUi.Copy,{size:12,color:_scnTheme.scn.color.textSecondary}),style:styles.grow,testID:"scenario-detail-export"})]}),a&&c?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.footer,children:(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:i?"Sharing\u2026":"Share with team",variant:"ghost",onPress:c,disabled:i,icon:(0,_jsxRuntime.jsx)(_sharedUi.Upload,{size:12,color:_scnTheme.scn.color.textSecondary}),style:styles.grow,testID:"scenario-detail-share"})}):null,(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.footer,children:[a?(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Delete",variant:"danger",onPress:s,icon:(0,_jsxRuntime.jsx)(_sharedUi.Trash,{size:12,color:_scnTheme.scn.color.danger}),style:styles.grow,testID:"scenario-detail-delete"}):(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:"Make an editable copy",variant:"ghost",onPress:t,style:styles.grow,testID:"scenario-detail-duplicate"}),e.source==="team"&&d?(0,_jsxRuntime.jsx)(_sharedUi.ToolButton,{label:i?"Removing\u2026":"Remove from team",variant:"danger",onPress:d,disabled:i,icon:(0,_jsxRuntime.jsx)(_sharedUi.Users,{size:12,color:_scnTheme.scn.color.danger}),style:styles.grow,testID:"scenario-detail-remove-team"}):null]}),e.source==="code"?(0,_jsxRuntime.jsx)(_primitives.Footnote,{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"?(0,_jsxRuntime.jsx)(_primitives.Footnote,{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,a&&c?(0,_jsxRuntime.jsx)(_primitives.Footnote,{children:"Share with team puts this scenario in Scenarios for everyone on your team, in this app."}):null]})}function Detail({label:e,value:o,muted:s,onPress:t,testID:l}){const n=(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.detailLabel,children:e}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.detailValue,s&&styles.detailValueMuted,t&&styles.detailValueAction],numberOfLines:2,children:o}),t?(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:13,color:_scnTheme.scn.color.textTertiary}):null]});if(!t){return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.detail,testID:l,children:n})}return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{style:styles.detail,onPress:t,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`${e}: ${o}. Change it.`,testID:l,children:n})}const styles=_reactNative.StyleSheet.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:32},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:_scnTheme.scn.textInset,paddingVertical:10},stepIndex:{width:18,height:18,borderRadius:_scnTheme.scn.radius.badge,backgroundColor:_scnTheme.scn.color.fill,alignItems:"center",justifyContent:"center",marginTop:1},stepIndexText:{color:_scnTheme.scn.color.textTertiary,fontSize:10,fontWeight:"700",fontFamily:_scnTheme.SCN_MONO},stepBody:{flex:1,minWidth:0},stepLabel:{color:_scnTheme.scn.color.text,fontSize:_scnTheme.scn.font.control},stepTool:{color:_scnTheme.scn.color.textTertiary,fontSize:_scnTheme.scn.font.mono,fontFamily:_scnTheme.SCN_MONO,marginTop:2},expected:{color:_scnTheme.scn.color.textSecondary,fontSize:_scnTheme.scn.font.control,lineHeight:18,paddingHorizontal:_scnTheme.scn.textInset,paddingVertical:12},detail:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:8,minHeight:40,paddingHorizontal:_scnTheme.scn.textInset,paddingVertical:10},detailLabel:{color:_scnTheme.scn.color.textTertiary,fontSize:_scnTheme.scn.font.control},detailValue:{flex:1,textAlign:"right",color:_scnTheme.scn.color.textSecondary,fontSize:_scnTheme.scn.font.control,fontFamily:_scnTheme.SCN_MONO},detailValueMuted:{color:_scnTheme.scn.color.textTertiary},detailValueAction:{color:_scnTheme.scn.color.accent},footer:{flexDirection:"row",gap:8,paddingHorizontal:_scnTheme.scn.gutter,paddingTop:12},grow:{flex:1}});
@@ -1 +1 @@
1
- "use strict";import{Fragment as z}from"react";import{ActivityIndicator as g,ScrollView as I,StyleSheet as S,Text as i,View as s}from"react-native";import{Check as w,Layers as D,RefreshCw as C,ToolButton as c,X as F}from"@buoy-gg/shared-ui";import{useToolHeader as P}from"@buoy-gg/core";import{scn as e,SCN_MONO as d}from"../ui/scnTheme";import{Notice as B,Panel as L,PanelSeparator as y,SectionLabel as R}from"../ui/primitives";import{jsx as o,jsxs as t,Fragment as v}from"react/jsx-runtime";export function RunProgressScreen({runState:n,busy:h,onUndoPartial:u,onKeepPartial:x,onRetry:b,onDone:T,onBack:k}){const p=n.report;const a=!!p&&!p.ok;P({title:a?"Run failed":n.done?"Run complete":"Running\u2026",subtitle:n.name,onBack:n.done?k:void 0,searchable:false},[n.done,a,n.name]);const m=p?.steps??n.steps;return t(s,{style:r.fill,children:[t(I,{style:r.fill,contentContainerStyle:r.content,testID:"scenario-run-scroll",children:[o(R,{icon:D,color:a?e.color.danger:e.color.accent,children:"Steps"}),t(L,{tone:a?"danger":"neutral",children:[m.length===0?t(s,{style:r.step,children:[o(g,{size:"small",color:e.color.accent}),o(i,{style:r.stepLabel,children:"Starting\u2026"})]}):null,m.map((l,f)=>t(z,{children:[f>0?o(y,{}):null,t(s,{style:r.step,children:[o(s,{style:r.mark,children:l.skipped?o(i,{style:r.skipped,children:"\u2013"}):l.ok?o(w,{size:13,color:e.color.accent}):o(F,{size:13,color:e.color.danger})}),t(s,{style:r.stepBody,children:[o(i,{style:[r.stepLabel,l.skipped?r.dim:null],testID:`scenario-step-${f}`,children:l.label}),l.error?o(i,{style:r.error,testID:`scenario-step-${f}-error`,children:l.error}):null,l.skipped?o(i,{style:r.dimSmall,children:"skipped"}):null]}),l.ms?t(i,{style:r.ms,children:[l.ms,"ms"]}):null]})]},l.id)),!n.done&&m.length?t(v,{children:[o(y,{}),t(s,{style:r.step,children:[o(g,{size:"small",color:e.color.accent}),o(i,{style:r.stepLabel,children:"Working\u2026"})]})]}):null]}),a?o(B,{tone:"danger",children:o(i,{style:r.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]}),a?t(s,{style:r.footer,children:[o(c,{label:"Undo applied steps",variant:"primary",onPress:u,disabled:h,style:r.grow,testID:"scenario-undo-partial"}),o(c,{label:"Keep",variant:"ghost",onPress:x,testID:"scenario-keep-partial"}),o(c,{label:"Retry",variant:"ghost",onPress:b,disabled:h,icon:o(C,{size:12,color:e.color.textSecondary}),testID:"scenario-retry"})]}):n.done?o(s,{style:r.footer,children:o(c,{label:"Done",variant:"primary",onPress:T,style:r.grow,testID:"scenario-run-done"})}):null]})}const r=S.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:24},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:e.textInset,paddingVertical:10},mark:{width:18,alignItems:"center",marginTop:1},skipped:{color:e.color.textTertiary,fontSize:13,fontFamily:d},stepBody:{flex:1,minWidth:0},stepLabel:{color:e.color.text,fontSize:e.font.control},dim:{color:e.color.textTertiary},dimSmall:{color:e.color.textTertiary,fontSize:e.font.mono,marginTop:2,fontFamily:d},error:{color:e.color.danger,fontSize:e.font.mono,marginTop:3,fontFamily:d},ms:{color:e.color.textTertiary,fontSize:e.font.micro,fontFamily:d,marginTop:3},errorText:{color:e.color.danger,fontSize:e.font.control,lineHeight:17},footer:{flexDirection:"row",gap:8,paddingHorizontal:e.gutter,paddingTop:10,paddingBottom:14,borderTopWidth:1,borderTopColor:e.color.border,backgroundColor:e.color.surface},grow:{flex:1}});
1
+ "use strict";import{Fragment as z}from"react";import{ActivityIndicator as g,ScrollView as S,StyleSheet as I,Text as i,View as s}from"react-native";import{Check as w,Layers as D,RefreshCw as P,ToolButton as c,X as C}from"@buoy-gg/shared-ui";import{useToolHeader as F}from"@buoy-gg/core";import{scn as e,SCN_MONO as d}from"../ui/scnTheme";import{Notice as B,Panel as L,PanelSeparator as y,SectionLabel as R}from"../ui/primitives";import{jsx as o,jsxs as t,Fragment as v}from"react/jsx-runtime";export function RunProgressScreen({runState:n,busy:h,onUndoPartial:u,onKeepPartial:b,onRetry:x,onDone:T,onBack:k}){const p=n.report;const a=!!p&&!p.ok;F({title:a?"Run failed":n.done?"Run complete":"Running\u2026",subtitle:n.name,onBack:n.done?k:void 0,searchable:false},[n.done,a,n.name]);const m=p?.steps??n.steps;return t(s,{style:r.fill,children:[t(S,{keyboardShouldPersistTaps:"handled",style:r.fill,contentContainerStyle:r.content,testID:"scenario-run-scroll",children:[o(R,{icon:D,color:a?e.color.danger:e.color.accent,children:"Steps"}),t(L,{tone:a?"danger":"neutral",children:[m.length===0?t(s,{style:r.step,children:[o(g,{size:"small",color:e.color.accent}),o(i,{style:r.stepLabel,children:"Starting\u2026"})]}):null,m.map((l,f)=>t(z,{children:[f>0?o(y,{}):null,t(s,{style:r.step,children:[o(s,{style:r.mark,children:l.skipped?o(i,{style:r.skipped,children:"\u2013"}):l.ok?o(w,{size:13,color:e.color.accent}):o(C,{size:13,color:e.color.danger})}),t(s,{style:r.stepBody,children:[o(i,{style:[r.stepLabel,l.skipped?r.dim:null],testID:`scenario-step-${f}`,children:l.label}),l.error?o(i,{style:r.error,testID:`scenario-step-${f}-error`,children:l.error}):null,l.skipped?o(i,{style:r.dimSmall,children:"skipped"}):null]}),l.ms?t(i,{style:r.ms,children:[l.ms,"ms"]}):null]})]},l.id)),!n.done&&m.length?t(v,{children:[o(y,{}),t(s,{style:r.step,children:[o(g,{size:"small",color:e.color.accent}),o(i,{style:r.stepLabel,children:"Working\u2026"})]})]}):null]}),a?o(B,{tone:"danger",children:o(i,{style:r.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]}),a?t(s,{style:r.footer,children:[o(c,{label:"Undo applied steps",variant:"primary",onPress:u,disabled:h,style:r.grow,testID:"scenario-undo-partial"}),o(c,{label:"Keep",variant:"ghost",onPress:b,testID:"scenario-keep-partial"}),o(c,{label:"Retry",variant:"ghost",onPress:x,disabled:h,icon:o(P,{size:12,color:e.color.textSecondary}),testID:"scenario-retry"})]}):n.done?o(s,{style:r.footer,children:o(c,{label:"Done",variant:"primary",onPress:T,style:r.grow,testID:"scenario-run-done"})}):null]})}const r=I.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:24},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:e.textInset,paddingVertical:10},mark:{width:18,alignItems:"center",marginTop:1},skipped:{color:e.color.textTertiary,fontSize:13,fontFamily:d},stepBody:{flex:1,minWidth:0},stepLabel:{color:e.color.text,fontSize:e.font.control},dim:{color:e.color.textTertiary},dimSmall:{color:e.color.textTertiary,fontSize:e.font.mono,marginTop:2,fontFamily:d},error:{color:e.color.danger,fontSize:e.font.mono,marginTop:3,fontFamily:d},ms:{color:e.color.textTertiary,fontSize:e.font.micro,fontFamily:d,marginTop:3},errorText:{color:e.color.danger,fontSize:e.font.control,lineHeight:17},footer:{flexDirection:"row",gap:8,paddingHorizontal:e.gutter,paddingTop:10,paddingBottom:14,borderTopWidth:1,borderTopColor:e.color.border,backgroundColor:e.color.surface},grow:{flex:1}});
@@ -1 +1 @@
1
- "use strict";import{Fragment as A}from"react";import{ScrollView as F,StyleSheet as L,Text as s,TouchableOpacity as O,View as i}from"react-native";import{CheckCircle as P,ChevronRight as j,Copy as H,FileText as R,Layers as k,Play as M,ToolButton as u,Trash as N,Upload as _,Users as $,copyToClipboard as B}from"@buoy-gg/shared-ui";import{useToolHeader as E}from"@buoy-gg/core";import{describeStep as U,isAdvancedStep as W,stepDurability as Y}from"../catalog";import{normalizeFolder as q}from"../folders";import{scn as l,SCN_MONO as S}from"../ui/scnTheme";import{DurabilityChip as J,Footnote as b,Panel as I,PanelSeparator as n,SectionLabel as T}from"../ui/primitives";import{displayName as X}from"./ScenarioRow";import{jsx as e,jsxs as r,Fragment as h}from"react/jsx-runtime";const G={durable:"survives restart",session:"until restart",transient:"until refetch \u26A0","one-shot":"one-shot"};function K(t){if(t==="durable")return"durable";if(t==="transient")return"transient";return"neutral"}export function sourceText(t){if(t.source==="code")return"shipped with this app";if(t.source==="team")return`shared with your team by ${t.team?.sharedBy.label??"a teammate"}`;if(t.source==="draft")return"a draft, waiting for review";return"saved on this device"}export function ScenarioDetailScreen({scenario:t,onRun:p,onDelete:x,onDuplicate:c,onExported:f,onMoveToFolder:g,onShare:v,onRemoveFromTeam:w,teamBusy:y,onBack:V}){E({title:X(t.name),subtitle:sourceText(t),onBack:V,searchable:false},[t.id]);const m=t.source==="device";const D=q(t.folder);return r(F,{style:o.fill,contentContainerStyle:o.content,testID:"scenario-detail-scroll",children:[t.description?e(b,{children:t.description}):null,e(T,{icon:k,count:t.steps.length,children:"Steps"}),e(I,{children:t.steps.map((d,z)=>{const C=Y(d);return r(A,{children:[z>0?e(n,{}):null,r(i,{style:o.step,children:[e(i,{style:o.stepIndex,children:e(s,{style:o.stepIndexText,children:z+1})}),r(i,{style:o.stepBody,children:[e(s,{style:o.stepLabel,children:U(d)}),r(s,{style:o.stepTool,children:[d.tool,".",d.action,W(d)?" \xB7 advanced":""]})]}),e(J,{label:G[C],tone:K(C)})]})]},d.id)})}),t.expectedOutcome?r(h,{children:[e(T,{icon:P,children:"Expected outcome"}),e(I,{children:e(s,{style:o.expected,children:t.expectedOutcome})})]}):null,e(T,{icon:R,children:"Details"}),r(I,{children:[e(a,{label:"Folder",value:D??"No folder",muted:!D,onPress:m?g:void 0,testID:"scenario-detail-folder"}),e(n,{}),e(a,{label:"Source",value:sourceText(t),testID:"scenario-detail-source"}),e(n,{}),e(a,{label:"Version",value:`v${t.version}`}),t.author?r(h,{children:[e(n,{}),e(a,{label:"Author",value:t.author})]}):null,t.authoredAgainst?r(h,{children:[e(n,{}),e(a,{label:"Authored against",value:t.authoredAgainst})]}):null,e(n,{}),e(a,{label:"Runs",value:String(t.usage?.runs??0)}),t.tags?.length?r(h,{children:[e(n,{}),e(a,{label:"Tags",value:t.tags.join(", ")})]}):null]}),r(i,{style:o.footer,children:[e(u,{label:"Run",variant:"primary",onPress:p,icon:e(M,{size:12,color:l.color.accent}),style:o.grow,testID:"scenario-detail-run"}),e(u,{label:"Export",variant:"ghost",onPress:()=>{void B(JSON.stringify(t,null,2));f?.()},icon:e(H,{size:12,color:l.color.textSecondary}),style:o.grow,testID:"scenario-detail-export"})]}),m&&v?e(i,{style:o.footer,children:e(u,{label:y?"Sharing\u2026":"Share with team",variant:"ghost",onPress:v,disabled:y,icon:e(_,{size:12,color:l.color.textSecondary}),style:o.grow,testID:"scenario-detail-share"})}):null,r(i,{style:o.footer,children:[m?e(u,{label:"Delete",variant:"danger",onPress:x,icon:e(N,{size:12,color:l.color.danger}),style:o.grow,testID:"scenario-detail-delete"}):e(u,{label:"Make an editable copy",variant:"ghost",onPress:c,style:o.grow,testID:"scenario-detail-duplicate"}),t.source==="team"&&w?e(u,{label:y?"Removing\u2026":"Remove from team",variant:"danger",onPress:w,disabled:y,icon:e($,{size:12,color:l.color.danger}),style:o.grow,testID:"scenario-detail-remove-team"}):null]}),t.source==="code"?e(b,{children:"Shipped scenarios are read-only on the device \u2014 they change in a pull request, with the code they bend."}):null,t.source==="team"?e(b,{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,m&&v?e(b,{children:"Share with team puts this scenario in Scenarios for everyone on your team, in this app."}):null]})}function a({label:t,value:p,muted:x,onPress:c,testID:f}){const g=r(h,{children:[e(s,{style:o.detailLabel,children:t}),e(s,{style:[o.detailValue,x&&o.detailValueMuted,c&&o.detailValueAction],numberOfLines:2,children:p}),c?e(j,{size:13,color:l.color.textTertiary}):null]});if(!c){return e(i,{style:o.detail,testID:f,children:g})}return e(O,{style:o.detail,onPress:c,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`${t}: ${p}. Change it.`,testID:f,children:g})}const o=L.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:32},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:l.textInset,paddingVertical:10},stepIndex:{width:18,height:18,borderRadius:l.radius.badge,backgroundColor:l.color.fill,alignItems:"center",justifyContent:"center",marginTop:1},stepIndexText:{color:l.color.textTertiary,fontSize:10,fontWeight:"700",fontFamily:S},stepBody:{flex:1,minWidth:0},stepLabel:{color:l.color.text,fontSize:l.font.control},stepTool:{color:l.color.textTertiary,fontSize:l.font.mono,fontFamily:S,marginTop:2},expected:{color:l.color.textSecondary,fontSize:l.font.control,lineHeight:18,paddingHorizontal:l.textInset,paddingVertical:12},detail:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:8,minHeight:40,paddingHorizontal:l.textInset,paddingVertical:10},detailLabel:{color:l.color.textTertiary,fontSize:l.font.control},detailValue:{flex:1,textAlign:"right",color:l.color.textSecondary,fontSize:l.font.control,fontFamily:S},detailValueMuted:{color:l.color.textTertiary},detailValueAction:{color:l.color.accent},footer:{flexDirection:"row",gap:8,paddingHorizontal:l.gutter,paddingTop:12},grow:{flex:1}});
1
+ "use strict";import{Fragment as A}from"react";import{ScrollView as F,StyleSheet as L,Text as c,TouchableOpacity as P,View as i}from"react-native";import{CheckCircle as O,ChevronRight as j,Copy as H,FileText as R,Layers as k,Play as M,ToolButton as u,Trash as N,Upload as _,Users as $,copyToClipboard as B}from"@buoy-gg/shared-ui";import{useToolHeader as E}from"@buoy-gg/core";import{describeStep as U,isAdvancedStep as W,stepDurability as Y}from"../catalog";import{normalizeFolder as q}from"../folders";import{scn as l,SCN_MONO as S}from"../ui/scnTheme";import{DurabilityChip as J,Footnote as b,Panel as I,PanelSeparator as n,SectionLabel as T}from"../ui/primitives";import{displayName as X}from"./ScenarioRow";import{jsx as e,jsxs as r,Fragment as h}from"react/jsx-runtime";const G={durable:"survives restart",session:"until restart",transient:"until refetch \u26A0","one-shot":"one-shot"};function K(t){if(t==="durable")return"durable";if(t==="transient")return"transient";return"neutral"}export function sourceText(t){if(t.source==="code")return"shipped with this app";if(t.source==="team")return`shared with your team by ${t.team?.sharedBy.label??"a teammate"}`;if(t.source==="draft")return"a draft, waiting for review";return"saved on this device"}export function ScenarioDetailScreen({scenario:t,onRun:p,onDelete:x,onDuplicate:d,onExported:f,onMoveToFolder:g,onShare:v,onRemoveFromTeam:w,teamBusy:y,onBack:V}){E({title:X(t.name),subtitle:sourceText(t),onBack:V,searchable:false},[t.id]);const m=t.source==="device";const D=q(t.folder);return r(F,{keyboardShouldPersistTaps:"handled",style:o.fill,contentContainerStyle:o.content,testID:"scenario-detail-scroll",children:[t.description?e(b,{children:t.description}):null,e(T,{icon:k,count:t.steps.length,children:"Steps"}),e(I,{children:t.steps.map((s,z)=>{const C=Y(s);return r(A,{children:[z>0?e(n,{}):null,r(i,{style:o.step,children:[e(i,{style:o.stepIndex,children:e(c,{style:o.stepIndexText,children:z+1})}),r(i,{style:o.stepBody,children:[e(c,{style:o.stepLabel,children:U(s)}),r(c,{style:o.stepTool,children:[s.tool,".",s.action,W(s)?" \xB7 advanced":""]})]}),e(J,{label:G[C],tone:K(C)})]})]},s.id)})}),t.expectedOutcome?r(h,{children:[e(T,{icon:O,children:"Expected outcome"}),e(I,{children:e(c,{style:o.expected,children:t.expectedOutcome})})]}):null,e(T,{icon:R,children:"Details"}),r(I,{children:[e(a,{label:"Folder",value:D??"No folder",muted:!D,onPress:m?g:void 0,testID:"scenario-detail-folder"}),e(n,{}),e(a,{label:"Source",value:sourceText(t),testID:"scenario-detail-source"}),e(n,{}),e(a,{label:"Version",value:`v${t.version}`}),t.author?r(h,{children:[e(n,{}),e(a,{label:"Author",value:t.author})]}):null,t.authoredAgainst?r(h,{children:[e(n,{}),e(a,{label:"Authored against",value:t.authoredAgainst})]}):null,e(n,{}),e(a,{label:"Runs",value:String(t.usage?.runs??0)}),t.tags?.length?r(h,{children:[e(n,{}),e(a,{label:"Tags",value:t.tags.join(", ")})]}):null]}),r(i,{style:o.footer,children:[e(u,{label:"Run",variant:"primary",onPress:p,icon:e(M,{size:12,color:l.color.accent}),style:o.grow,testID:"scenario-detail-run"}),e(u,{label:"Export",variant:"ghost",onPress:()=>{void B(JSON.stringify(t,null,2));f?.()},icon:e(H,{size:12,color:l.color.textSecondary}),style:o.grow,testID:"scenario-detail-export"})]}),m&&v?e(i,{style:o.footer,children:e(u,{label:y?"Sharing\u2026":"Share with team",variant:"ghost",onPress:v,disabled:y,icon:e(_,{size:12,color:l.color.textSecondary}),style:o.grow,testID:"scenario-detail-share"})}):null,r(i,{style:o.footer,children:[m?e(u,{label:"Delete",variant:"danger",onPress:x,icon:e(N,{size:12,color:l.color.danger}),style:o.grow,testID:"scenario-detail-delete"}):e(u,{label:"Make an editable copy",variant:"ghost",onPress:d,style:o.grow,testID:"scenario-detail-duplicate"}),t.source==="team"&&w?e(u,{label:y?"Removing\u2026":"Remove from team",variant:"danger",onPress:w,disabled:y,icon:e($,{size:12,color:l.color.danger}),style:o.grow,testID:"scenario-detail-remove-team"}):null]}),t.source==="code"?e(b,{children:"Shipped scenarios are read-only on the device \u2014 they change in a pull request, with the code they bend."}):null,t.source==="team"?e(b,{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,m&&v?e(b,{children:"Share with team puts this scenario in Scenarios for everyone on your team, in this app."}):null]})}function a({label:t,value:p,muted:x,onPress:d,testID:f}){const g=r(h,{children:[e(c,{style:o.detailLabel,children:t}),e(c,{style:[o.detailValue,x&&o.detailValueMuted,d&&o.detailValueAction],numberOfLines:2,children:p}),d?e(j,{size:13,color:l.color.textTertiary}):null]});if(!d){return e(i,{style:o.detail,testID:f,children:g})}return e(P,{style:o.detail,onPress:d,activeOpacity:.7,accessibilityRole:"button",accessibilityLabel:`${t}: ${p}. Change it.`,testID:f,children:g})}const o=L.create({fill:{flex:1,backgroundColor:"transparent"},content:{paddingBottom:32},step:{flexDirection:"row",alignItems:"flex-start",gap:9,paddingHorizontal:l.textInset,paddingVertical:10},stepIndex:{width:18,height:18,borderRadius:l.radius.badge,backgroundColor:l.color.fill,alignItems:"center",justifyContent:"center",marginTop:1},stepIndexText:{color:l.color.textTertiary,fontSize:10,fontWeight:"700",fontFamily:S},stepBody:{flex:1,minWidth:0},stepLabel:{color:l.color.text,fontSize:l.font.control},stepTool:{color:l.color.textTertiary,fontSize:l.font.mono,fontFamily:S,marginTop:2},expected:{color:l.color.textSecondary,fontSize:l.font.control,lineHeight:18,paddingHorizontal:l.textInset,paddingVertical:12},detail:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:8,minHeight:40,paddingHorizontal:l.textInset,paddingVertical:10},detailLabel:{color:l.color.textTertiary,fontSize:l.font.control},detailValue:{flex:1,textAlign:"right",color:l.color.textSecondary,fontSize:l.font.control,fontFamily:S},detailValueMuted:{color:l.color.textTertiary},detailValueAction:{color:l.color.accent},footer:{flexDirection:"row",gap:8,paddingHorizontal:l.gutter,paddingTop:12},grow:{flex:1}});
package/lib/web/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
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};
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,{keyboardShouldPersistTaps:"handled",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,{keyboardShouldPersistTaps:"handled",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.77",
3
+ "version": "7.0.79",
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.77",
21
- "@buoy-gg/shared-ui": "^7.0.77"
20
+ "@buoy-gg/shared-ui": "^7.0.79",
21
+ "@buoy-gg/floating-tools-core": "^7.0.79"
22
22
  },
23
23
  "peerDependencies": {
24
- "@buoy-gg/license": "7.0.77",
24
+ "@buoy-gg/license": "7.0.79",
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.77",
32
- "@buoy-gg/core": "^7.0.77"
31
+ "@buoy-gg/core": "^7.0.79",
32
+ "@buoy-gg/license": "^7.0.79"
33
33
  },
34
34
  "react-native-builder-bob": {
35
35
  "source": "src",