@buoy-gg/ask-buoy 7.0.34 → 7.0.35

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.
Files changed (239) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/blocks/AskBlocks.js +338 -1
  3. package/lib/commonjs/blocks/AskBlocks.js.map +1 -0
  4. package/lib/commonjs/blocks/BlockRenderer.js +250 -1
  5. package/lib/commonjs/blocks/BlockRenderer.js.map +1 -0
  6. package/lib/commonjs/blocks/ChromePrototypes.js +514 -1
  7. package/lib/commonjs/blocks/ChromePrototypes.js.map +1 -0
  8. package/lib/commonjs/blocks/DataBlocks.js +688 -1
  9. package/lib/commonjs/blocks/DataBlocks.js.map +1 -0
  10. package/lib/commonjs/blocks/ExtraBlocks.js +1854 -1
  11. package/lib/commonjs/blocks/ExtraBlocks.js.map +1 -0
  12. package/lib/commonjs/blocks/MediaBlocks.js +140 -1
  13. package/lib/commonjs/blocks/MediaBlocks.js.map +1 -0
  14. package/lib/commonjs/blocks/ReceiptBlocks.js +586 -1
  15. package/lib/commonjs/blocks/ReceiptBlocks.js.map +1 -0
  16. package/lib/commonjs/blocks/context.js +42 -1
  17. package/lib/commonjs/blocks/context.js.map +1 -0
  18. package/lib/commonjs/blocks/icons.js +96 -1
  19. package/lib/commonjs/blocks/icons.js.map +1 -0
  20. package/lib/commonjs/blocks/index.js +95 -1
  21. package/lib/commonjs/blocks/index.js.map +1 -0
  22. package/lib/commonjs/blocks/listRow.test.js +55 -0
  23. package/lib/commonjs/blocks/listRow.test.js.map +1 -0
  24. package/lib/commonjs/blocks/pageState.js +34 -0
  25. package/lib/commonjs/blocks/pageState.js.map +1 -0
  26. package/lib/commonjs/blocks/pageState.test.js +57 -0
  27. package/lib/commonjs/blocks/pageState.test.js.map +1 -0
  28. package/lib/commonjs/blocks/primitives.js +401 -1
  29. package/lib/commonjs/blocks/primitives.js.map +1 -0
  30. package/lib/commonjs/blocks/primitivesIndex.js +62 -1
  31. package/lib/commonjs/blocks/primitivesIndex.js.map +1 -0
  32. package/lib/commonjs/components/ApprovalCard.js +140 -1
  33. package/lib/commonjs/components/ApprovalCard.js.map +1 -0
  34. package/lib/commonjs/components/AskBuoyHeader.js +164 -1
  35. package/lib/commonjs/components/AskBuoyHeader.js.map +1 -0
  36. package/lib/commonjs/components/AskBuoyIcon.js +19 -1
  37. package/lib/commonjs/components/AskBuoyIcon.js.map +1 -0
  38. package/lib/commonjs/components/AskBuoyModal.js +353 -1
  39. package/lib/commonjs/components/AskBuoyModal.js.map +1 -0
  40. package/lib/commonjs/components/AskBuoySettings.js +69 -0
  41. package/lib/commonjs/components/AskBuoySettings.js.map +1 -0
  42. package/lib/commonjs/components/ChangesBar.js +211 -1
  43. package/lib/commonjs/components/ChangesBar.js.map +1 -0
  44. package/lib/commonjs/components/Composer.js +175 -1
  45. package/lib/commonjs/components/Composer.js.map +1 -0
  46. package/lib/commonjs/components/EmptyState.js +154 -1
  47. package/lib/commonjs/components/EmptyState.js.map +1 -0
  48. package/lib/commonjs/components/Markdown.js +252 -1
  49. package/lib/commonjs/components/Markdown.js.map +1 -0
  50. package/lib/commonjs/components/MessageList.js +683 -1
  51. package/lib/commonjs/components/MessageList.js.map +1 -0
  52. package/lib/commonjs/components/ThinkingStrip.js +223 -0
  53. package/lib/commonjs/components/ThinkingStrip.js.map +1 -0
  54. package/lib/commonjs/components/TypingDots.js +63 -1
  55. package/lib/commonjs/components/TypingDots.js.map +1 -0
  56. package/lib/commonjs/components/useCopyAction.js +50 -0
  57. package/lib/commonjs/components/useCopyAction.js.map +1 -0
  58. package/lib/commonjs/index.js +252 -1
  59. package/lib/commonjs/index.js.map +1 -0
  60. package/lib/commonjs/preset.js +90 -1
  61. package/lib/commonjs/preset.js.map +1 -0
  62. package/lib/commonjs/store/askBuoySettings.js +67 -0
  63. package/lib/commonjs/store/askBuoySettings.js.map +1 -0
  64. package/lib/commonjs/store/askBuoyStore.js +365 -1
  65. package/lib/commonjs/store/askBuoyStore.js.map +1 -0
  66. package/lib/commonjs/store/restoredIds.test.js +47 -0
  67. package/lib/commonjs/store/restoredIds.test.js.map +1 -0
  68. package/lib/commonjs/store/traceText.js +81 -0
  69. package/lib/commonjs/store/traceText.js.map +1 -0
  70. package/lib/commonjs/store/traceText.test.js +112 -0
  71. package/lib/commonjs/store/traceText.test.js.map +1 -0
  72. package/lib/commonjs/store/transcriptPersistence.js +208 -0
  73. package/lib/commonjs/store/transcriptPersistence.js.map +1 -0
  74. package/lib/commonjs/store/transcriptPersistence.test.js +185 -0
  75. package/lib/commonjs/store/transcriptPersistence.test.js.map +1 -0
  76. package/lib/commonjs/store/useAskBuoy.js +400 -1
  77. package/lib/commonjs/store/useAskBuoy.js.map +1 -0
  78. package/lib/commonjs/store/useAskBuoySettings.js +14 -0
  79. package/lib/commonjs/store/useAskBuoySettings.js.map +1 -0
  80. package/lib/commonjs/sync/askBuoySyncAdapter.js +119 -1
  81. package/lib/commonjs/sync/askBuoySyncAdapter.js.map +1 -0
  82. package/lib/commonjs/sync/askBuoySyncAdapter.test.js +141 -1
  83. package/lib/commonjs/sync/askBuoySyncAdapter.test.js.map +1 -0
  84. package/lib/commonjs/sync/wire.js +58 -1
  85. package/lib/commonjs/sync/wire.js.map +1 -0
  86. package/lib/commonjs/types.js +6 -1
  87. package/lib/commonjs/types.js.map +1 -0
  88. package/lib/module/blocks/AskBlocks.js +331 -1
  89. package/lib/module/blocks/AskBlocks.js.map +1 -0
  90. package/lib/module/blocks/BlockRenderer.js +245 -1
  91. package/lib/module/blocks/BlockRenderer.js.map +1 -0
  92. package/lib/module/blocks/ChromePrototypes.js +503 -1
  93. package/lib/module/blocks/ChromePrototypes.js.map +1 -0
  94. package/lib/module/blocks/DataBlocks.js +674 -1
  95. package/lib/module/blocks/DataBlocks.js.map +1 -0
  96. package/lib/module/blocks/ExtraBlocks.js +1827 -1
  97. package/lib/module/blocks/ExtraBlocks.js.map +1 -0
  98. package/lib/module/blocks/MediaBlocks.js +135 -1
  99. package/lib/module/blocks/MediaBlocks.js.map +1 -0
  100. package/lib/module/blocks/ReceiptBlocks.js +574 -1
  101. package/lib/module/blocks/ReceiptBlocks.js.map +1 -0
  102. package/lib/module/blocks/context.js +35 -1
  103. package/lib/module/blocks/context.js.map +1 -0
  104. package/lib/module/blocks/icons.js +91 -1
  105. package/lib/module/blocks/icons.js.map +1 -0
  106. package/lib/module/blocks/index.js +8 -1
  107. package/lib/module/blocks/index.js.map +1 -0
  108. package/lib/module/blocks/listRow.test.js +56 -0
  109. package/lib/module/blocks/listRow.test.js.map +1 -0
  110. package/lib/module/blocks/pageState.js +30 -0
  111. package/lib/module/blocks/pageState.js.map +1 -0
  112. package/lib/module/blocks/pageState.test.js +56 -0
  113. package/lib/module/blocks/pageState.test.js.map +1 -0
  114. package/lib/module/blocks/primitives.js +389 -1
  115. package/lib/module/blocks/primitives.js.map +1 -0
  116. package/lib/module/blocks/primitivesIndex.js +5 -1
  117. package/lib/module/blocks/primitivesIndex.js.map +1 -0
  118. package/lib/module/components/ApprovalCard.js +135 -1
  119. package/lib/module/components/ApprovalCard.js.map +1 -0
  120. package/lib/module/components/AskBuoyHeader.js +161 -1
  121. package/lib/module/components/AskBuoyHeader.js.map +1 -0
  122. package/lib/module/components/AskBuoyIcon.js +8 -1
  123. package/lib/module/components/AskBuoyIcon.js.map +1 -0
  124. package/lib/module/components/AskBuoyModal.js +348 -1
  125. package/lib/module/components/AskBuoyModal.js.map +1 -0
  126. package/lib/module/components/AskBuoySettings.js +64 -0
  127. package/lib/module/components/AskBuoySettings.js.map +1 -0
  128. package/lib/module/components/ChangesBar.js +206 -1
  129. package/lib/module/components/ChangesBar.js.map +1 -0
  130. package/lib/module/components/Composer.js +170 -1
  131. package/lib/module/components/Composer.js.map +1 -0
  132. package/lib/module/components/EmptyState.js +149 -1
  133. package/lib/module/components/EmptyState.js.map +1 -0
  134. package/lib/module/components/Markdown.js +246 -1
  135. package/lib/module/components/Markdown.js.map +1 -0
  136. package/lib/module/components/MessageList.js +677 -1
  137. package/lib/module/components/MessageList.js.map +1 -0
  138. package/lib/module/components/ThinkingStrip.js +218 -0
  139. package/lib/module/components/ThinkingStrip.js.map +1 -0
  140. package/lib/module/components/TypingDots.js +58 -1
  141. package/lib/module/components/TypingDots.js.map +1 -0
  142. package/lib/module/components/useCopyAction.js +46 -0
  143. package/lib/module/components/useCopyAction.js.map +1 -0
  144. package/lib/module/index.js +34 -1
  145. package/lib/module/index.js.map +1 -0
  146. package/lib/module/preset.js +73 -1
  147. package/lib/module/preset.js.map +1 -0
  148. package/lib/module/store/askBuoySettings.js +62 -0
  149. package/lib/module/store/askBuoySettings.js.map +1 -0
  150. package/lib/module/store/askBuoyStore.js +361 -1
  151. package/lib/module/store/askBuoyStore.js.map +1 -0
  152. package/lib/module/store/restoredIds.test.js +46 -0
  153. package/lib/module/store/restoredIds.test.js.map +1 -0
  154. package/lib/module/store/traceText.js +75 -0
  155. package/lib/module/store/traceText.js.map +1 -0
  156. package/lib/module/store/traceText.test.js +111 -0
  157. package/lib/module/store/traceText.test.js.map +1 -0
  158. package/lib/module/store/transcriptPersistence.js +198 -0
  159. package/lib/module/store/transcriptPersistence.js.map +1 -0
  160. package/lib/module/store/transcriptPersistence.test.js +184 -0
  161. package/lib/module/store/transcriptPersistence.test.js.map +1 -0
  162. package/lib/module/store/useAskBuoy.js +394 -1
  163. package/lib/module/store/useAskBuoy.js.map +1 -0
  164. package/lib/module/store/useAskBuoySettings.js +9 -0
  165. package/lib/module/store/useAskBuoySettings.js.map +1 -0
  166. package/lib/module/sync/askBuoySyncAdapter.js +114 -1
  167. package/lib/module/sync/askBuoySyncAdapter.js.map +1 -0
  168. package/lib/module/sync/askBuoySyncAdapter.test.js +140 -1
  169. package/lib/module/sync/askBuoySyncAdapter.test.js.map +1 -0
  170. package/lib/module/sync/wire.js +47 -1
  171. package/lib/module/sync/wire.js.map +1 -0
  172. package/lib/module/types.js +4 -1
  173. package/lib/module/types.js.map +1 -0
  174. package/lib/typescript/blocks/AskBlocks.d.ts.map +1 -0
  175. package/lib/typescript/blocks/BlockRenderer.d.ts.map +1 -0
  176. package/lib/typescript/blocks/ChromePrototypes.d.ts.map +1 -0
  177. package/lib/typescript/blocks/DataBlocks.d.ts +31 -0
  178. package/lib/typescript/blocks/DataBlocks.d.ts.map +1 -0
  179. package/lib/typescript/blocks/ExtraBlocks.d.ts +11 -0
  180. package/lib/typescript/blocks/ExtraBlocks.d.ts.map +1 -0
  181. package/lib/typescript/blocks/MediaBlocks.d.ts.map +1 -0
  182. package/lib/typescript/blocks/ReceiptBlocks.d.ts.map +1 -0
  183. package/lib/typescript/blocks/context.d.ts.map +1 -0
  184. package/lib/typescript/blocks/icons.d.ts.map +1 -0
  185. package/lib/typescript/blocks/index.d.ts.map +1 -0
  186. package/lib/typescript/blocks/listRow.test.d.ts +2 -0
  187. package/lib/typescript/blocks/listRow.test.d.ts.map +1 -0
  188. package/lib/typescript/blocks/pageState.d.ts +23 -0
  189. package/lib/typescript/blocks/pageState.d.ts.map +1 -0
  190. package/lib/typescript/blocks/pageState.test.d.ts +2 -0
  191. package/lib/typescript/blocks/pageState.test.d.ts.map +1 -0
  192. package/lib/typescript/blocks/primitives.d.ts +39 -9
  193. package/lib/typescript/blocks/primitives.d.ts.map +1 -0
  194. package/lib/typescript/blocks/primitivesIndex.d.ts +2 -1
  195. package/lib/typescript/blocks/primitivesIndex.d.ts.map +1 -0
  196. package/lib/typescript/components/ApprovalCard.d.ts.map +1 -0
  197. package/lib/typescript/components/AskBuoyHeader.d.ts +11 -1
  198. package/lib/typescript/components/AskBuoyHeader.d.ts.map +1 -0
  199. package/lib/typescript/components/AskBuoyIcon.d.ts.map +1 -0
  200. package/lib/typescript/components/AskBuoyModal.d.ts.map +1 -0
  201. package/lib/typescript/components/AskBuoySettings.d.ts +2 -0
  202. package/lib/typescript/components/AskBuoySettings.d.ts.map +1 -0
  203. package/lib/typescript/components/ChangesBar.d.ts.map +1 -0
  204. package/lib/typescript/components/Composer.d.ts.map +1 -0
  205. package/lib/typescript/components/EmptyState.d.ts.map +1 -0
  206. package/lib/typescript/components/Markdown.d.ts.map +1 -0
  207. package/lib/typescript/components/MessageList.d.ts +12 -5
  208. package/lib/typescript/components/MessageList.d.ts.map +1 -0
  209. package/lib/typescript/components/ThinkingStrip.d.ts +5 -0
  210. package/lib/typescript/components/ThinkingStrip.d.ts.map +1 -0
  211. package/lib/typescript/components/TypingDots.d.ts.map +1 -0
  212. package/lib/typescript/components/useCopyAction.d.ts +5 -0
  213. package/lib/typescript/components/useCopyAction.d.ts.map +1 -0
  214. package/lib/typescript/index.d.ts +5 -0
  215. package/lib/typescript/index.d.ts.map +1 -0
  216. package/lib/typescript/preset.d.ts.map +1 -0
  217. package/lib/typescript/store/askBuoySettings.d.ts +22 -0
  218. package/lib/typescript/store/askBuoySettings.d.ts.map +1 -0
  219. package/lib/typescript/store/askBuoyStore.d.ts +74 -13
  220. package/lib/typescript/store/askBuoyStore.d.ts.map +1 -0
  221. package/lib/typescript/store/restoredIds.test.d.ts +2 -0
  222. package/lib/typescript/store/restoredIds.test.d.ts.map +1 -0
  223. package/lib/typescript/store/traceText.d.ts +33 -0
  224. package/lib/typescript/store/traceText.d.ts.map +1 -0
  225. package/lib/typescript/store/traceText.test.d.ts +2 -0
  226. package/lib/typescript/store/traceText.test.d.ts.map +1 -0
  227. package/lib/typescript/store/transcriptPersistence.d.ts +40 -0
  228. package/lib/typescript/store/transcriptPersistence.d.ts.map +1 -0
  229. package/lib/typescript/store/transcriptPersistence.test.d.ts +2 -0
  230. package/lib/typescript/store/transcriptPersistence.test.d.ts.map +1 -0
  231. package/lib/typescript/store/useAskBuoy.d.ts.map +1 -0
  232. package/lib/typescript/store/useAskBuoySettings.d.ts +3 -0
  233. package/lib/typescript/store/useAskBuoySettings.d.ts.map +1 -0
  234. package/lib/typescript/sync/askBuoySyncAdapter.d.ts.map +1 -0
  235. package/lib/typescript/sync/askBuoySyncAdapter.test.d.ts.map +1 -0
  236. package/lib/typescript/sync/wire.d.ts.map +1 -0
  237. package/lib/typescript/types.d.ts +24 -1
  238. package/lib/typescript/types.d.ts.map +1 -0
  239. package/package.json +8 -8
@@ -1 +1,1827 @@
1
- "use strict";import{useEffect,useRef,useState}from"react";import{Animated,Image,Pressable,ScrollView,StyleSheet,Switch,Text,TextInput,View}from"react-native";import{AlertTriangle,Check,ChevronDown,ChevronRight,night,RefreshCw,Search,X}from"@buoy-gg/shared-ui";import{BlockRenderer}from"./BlockRenderer";import{useBlockHandlers}from"./context";import{ActionRow,blockStyles as b,Card,toneColor}from"./primitives";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";const fmt=e=>"string"==typeof e?e:void 0===e?"—":JSON.stringify(e);export function Suggestions({block:e}){const t=useBlockHandlers();return _jsx(View,{style:styles.chips,testID:`buoy-block-suggestions-${e.id}`,children:e.chips.slice(0,4).map(l=>_jsx(Pressable,{disabled:!!t.busy,onPress:()=>{t.runAction({label:l.label,send:l.send??l.label},e.id)},style:({pressed:e})=>[styles.chip,e&&styles.pressed],accessibilityRole:"button",children:_jsx(Text,{style:styles.chipText,children:l.label})},l.label))})}export function MultiSelect({block:e}){const t=useBlockHandlers(),l=t.answered[e.id],o=!!l,[i,s]=useState([]),n="multi"===l?.kind?l.optionIds:i,r=i.length>=(e.min??1)&&(!e.max||i.length<=e.max);return _jsxs(Card,{testID:`buoy-block-multi-${e.id}`,tone:o?void 0:"info",children:[_jsx(Text,{style:styles.question,children:e.question}),_jsx(View,{style:styles.optionsBox,children:e.options.map((e,t)=>{const l=n.includes(e.id);return _jsxs(Pressable,{disabled:o,onPress:()=>{return t=e.id,s(e=>e.includes(t)?e.filter(e=>e!==t):[...e,t]);var t},style:[styles.option,t>0&&b.rowDivider,o&&!l&&styles.dim],accessibilityRole:"checkbox",accessibilityState:{checked:l},children:[_jsx(View,{style:[styles.checkbox,l&&styles.checkboxOn],children:l?_jsx(Check,{size:11,color:night.color.onAccent}):null}),_jsxs(View,{style:styles.flex,children:[_jsx(Text,{style:styles.optionLabel,children:e.label}),e.detail?_jsx(Text,{style:styles.optionDetail,children:e.detail}):null]})]},e.id)})}),o?null:_jsx(View,{style:styles.rowEnd,children:_jsx(Pressable,{testID:"buoy-block-multi-submit",disabled:!r,onPress:()=>t.answer({blockId:e.id,kind:"multi",optionIds:i,labels:e.options.filter(e=>i.includes(e.id)).map(e=>e.label)}),style:[styles.button,styles.buttonPrimary,!r&&styles.disabled],children:_jsx(Text,{style:styles.buttonTextPrimary,children:e.submitLabel??`Use ${i.length||""}`.trim()})})})]})}export function Select({block:e}){const t=useBlockHandlers(),l=t.answered[e.id],[o,i]=useState(""),[s,n]=useState(!1),r="select"===l?.kind?l.label:null,a=e.options.filter(e=>!o||e.label.toLowerCase().includes(o.toLowerCase())).slice(0,8);return _jsxs(Card,{testID:`buoy-block-select-${e.id}`,tone:l?void 0:"info",children:[_jsx(Text,{style:styles.question,children:e.label}),r?_jsx(Text,{style:styles.decided,children:r}):_jsxs(View,{style:styles.selectBox,children:[_jsxs(Pressable,{onPress:()=>n(e=>!e),style:styles.selectField,accessibilityRole:"button",children:[_jsx(Text,{style:styles.selectPlaceholder,children:s?"Choose…":`${e.options.length} options`}),_jsx(ChevronDown,{size:14,color:night.color.textSecondary})]}),s&&_jsxs(_Fragment,{children:[!1!==e.searchable&&_jsxs(View,{style:styles.search,children:[_jsx(Search,{size:12,color:night.color.textSecondary}),_jsx(TextInput,{style:styles.searchInput,value:o,onChangeText:i,placeholder:"Search",placeholderTextColor:night.color.placeholder,autoCapitalize:"none",autoCorrect:!1})]}),a.map((l,o)=>_jsxs(Pressable,{onPress:()=>t.answer({blockId:e.id,kind:"select",optionId:l.id,label:l.label}),style:[styles.option,o>0&&b.rowDivider],accessibilityRole:"button",children:[_jsxs(View,{style:styles.flex,children:[_jsx(Text,{style:styles.optionLabel,children:l.label}),l.detail?_jsx(Text,{style:styles.optionDetail,children:l.detail}):null]}),_jsx(ChevronRight,{size:12,color:night.color.textTertiary})]},l.id)),e.options.length>a.length?_jsxs(Text,{style:styles.hint,children:[e.options.length-a.length," more — keep typing"]}):null]})]})]})}function SliderControl({min:e,max:t,step:l=1,value:o,unit:i,onChange:s,disabled:n}){const r=useRef(0),a=t>e?(o-e)/(t-e)*100:0,c=o=>Math.min(t,Math.max(e,+(Math.round((o-e)/l)*l+e).toFixed(6))),d=e=>!n&&s(c(o+e*l));return _jsxs(View,{style:styles.sliderRow,children:[_jsx(Pressable,{disabled:n,onPress:()=>d(-1),style:styles.stepBtn,accessibilityRole:"button",accessibilityLabel:"Decrease",children:_jsx(Text,{style:styles.stepText,children:"−"})}),_jsx(Pressable,{style:styles.trackHit,onLayout:e=>{r.current=e.nativeEvent.layout.width},onPress:l=>{if(n||r.current<=0)return;const o=Math.min(1,Math.max(0,l.nativeEvent.locationX/r.current));s(c(e+o*(t-e)))},disabled:n,accessibilityRole:"adjustable",accessibilityValue:{min:e,max:t,now:o},accessibilityActions:[{name:"increment"},{name:"decrement"}],onAccessibilityAction:e=>d("increment"===e.nativeEvent.actionName?1:-1),children:_jsxs(View,{style:styles.track,pointerEvents:"none",children:[_jsx(View,{style:[styles.fill,{width:`${a}%`}]}),_jsx(View,{style:[styles.thumb,{left:`${a}%`}]})]})}),_jsx(Pressable,{disabled:n,onPress:()=>d(1),style:styles.stepBtn,accessibilityRole:"button",accessibilityLabel:"Increase",children:_jsx(Text,{style:styles.stepText,children:"+"})}),_jsxs(Text,{style:styles.sliderValue,children:[o,i?` ${i}`:""]})]})}export function Slider({block:e}){const t=useBlockHandlers(),l=t.answered[e.id],[o,i]=useState(e.value??e.min);return _jsxs(Card,{testID:`buoy-block-slider-${e.id}`,tone:l?void 0:"info",children:[_jsx(Text,{style:styles.question,children:e.label}),_jsx(View,{style:styles.pad,children:_jsx(SliderControl,{min:e.min,max:e.max,step:e.step,value:"slider"===l?.kind?l.value:o,unit:e.unit,onChange:i,disabled:!!l})}),l?null:_jsx(View,{style:styles.rowEnd,children:_jsx(Pressable,{onPress:()=>t.answer({blockId:e.id,kind:"slider",value:o,unit:e.unit}),style:[styles.button,styles.buttonPrimary],children:_jsxs(Text,{style:styles.buttonTextPrimary,children:["Use ",o,e.unit?` ${e.unit}`:""]})})})]})}export function DateTime({block:e}){const t=useBlockHandlers(),l=t.answered[e.id],[o,i]=useState(""),s=e.presets??[{label:"Now",value:(new Date).toISOString()},{label:"Tomorrow",value:new Date(Date.now()+864e5).toISOString()},{label:"+7 days",value:new Date(Date.now()+6048e5).toISOString()},{label:"+30 days",value:new Date(Date.now()+2592e6).toISOString()}];return _jsxs(Card,{testID:`buoy-block-datetime-${e.id}`,tone:l?void 0:"info",children:[_jsx(Text,{style:styles.question,children:e.label}),l?_jsx(Text,{style:styles.decided,children:"dateTime"===l.kind?l.label??l.value:"(skipped)"}):_jsxs(_Fragment,{children:[_jsx(View,{style:[styles.chips,styles.pad],children:s.map(l=>_jsx(Pressable,{onPress:()=>t.answer({blockId:e.id,kind:"dateTime",value:l.value,label:l.label}),style:styles.chip,children:_jsx(Text,{style:styles.chipText,children:l.label})},l.label))}),_jsxs(View,{style:[styles.inputRow,styles.pad],children:[_jsx(TextInput,{style:styles.input,value:o,onChangeText:i,placeholder:"time"===e.mode?"14:30":"2026-09-15",placeholderTextColor:night.color.placeholder,keyboardType:"numbers-and-punctuation"}),_jsx(Pressable,{disabled:!o.trim(),onPress:()=>t.answer({blockId:e.id,kind:"dateTime",value:o.trim()}),style:[styles.button,styles.buttonPrimary,!o.trim()&&styles.disabled],children:_jsx(Text,{style:styles.buttonTextPrimary,children:"Use"})})]})]})]})}function FieldRow({f:e,value:t,onChange:l,disabled:o}){return"toggle"===e.type?_jsxs(View,{style:styles.fieldRow,children:[_jsx(Text,{style:styles.fieldLabel,children:e.label}),_jsx(Switch,{value:!!t,onValueChange:l,disabled:o,trackColor:{true:night.color.accent,false:night.color.fillTertiary},thumbColor:night.color.knob})]}):"select"===e.type?_jsxs(View,{style:styles.fieldCol,children:[_jsx(Text,{style:styles.fieldLabel,children:e.label}),_jsx(View,{style:styles.chips,children:e.options.map(e=>_jsx(Pressable,{disabled:o,onPress:()=>l(e.id),style:[styles.chip,t===e.id&&styles.chipOn],children:_jsx(Text,{style:[styles.chipText,t===e.id&&styles.chipTextOn],children:e.label})},e.id))})]}):"slider"===e.type?_jsxs(View,{style:styles.fieldCol,children:[_jsx(Text,{style:styles.fieldLabel,children:e.label}),_jsx(SliderControl,{min:e.min,max:e.max,step:e.step,unit:e.unit,value:"number"==typeof t?t:e.min,onChange:l,disabled:o})]}):_jsxs(View,{style:styles.fieldRow,children:[_jsx(Text,{style:styles.fieldLabel,children:e.label}),_jsx(TextInput,{style:styles.fieldInput,value:null==t?"":String(t),onChangeText:l,editable:!o,placeholder:e.placeholder??"",placeholderTextColor:night.color.placeholder,keyboardType:"number"===e.type?"numeric":"ascii-capable",secureTextEntry:"secret"===e.type,autoCapitalize:"none",autoCorrect:!1})]})}function useFormValues(e){const[t,l]=useState(()=>Object.fromEntries(e.map(e=>[e.key,e.value])));return{values:t,set:(e,t)=>l(l=>({...l,[e]:t}))}}export function Form({block:e}){const t=useBlockHandlers(),l=t.answered[e.id],{values:o,set:i}=useFormValues(e.fields);return _jsxs(Card,{title:e.title,testID:`buoy-block-form-${e.id}`,tone:l?void 0:"info",children:[_jsx(View,{style:styles.pad,children:e.fields.map(e=>_jsx(FieldRow,{f:e,value:o[e.key],onChange:t=>i(e.key,t),disabled:!!l},e.key))}),l?_jsx(Text,{style:styles.decided,children:"Sent"}):_jsx(View,{style:styles.rowEnd,children:_jsx(Pressable,{onPress:()=>t.answer({blockId:e.id,kind:"form",values:o}),style:[styles.button,styles.buttonPrimary],children:_jsx(Text,{style:styles.buttonTextPrimary,children:e.submitLabel??"Send"})})})]})}export function Proposal({block:e}){const t=useBlockHandlers(),l=t.answered[e.id],{values:o,set:i}=useFormValues(e.fields),s="proposal"===l?.kind?l.approved:null;return _jsxs(Card,{testID:`buoy-block-proposal-${e.id}`,tone:l?void 0:"warning",children:[_jsx(Text,{style:styles.confirmTitle,children:e.title}),_jsx(Text,{style:styles.confirmChange,children:e.change}),_jsx(View,{style:styles.pad,children:e.fields.map(e=>_jsx(FieldRow,{f:e,value:o[e.key],onChange:t=>i(e.key,t),disabled:!!l},e.key))}),e.consequence?_jsx(Text,{style:styles.consequence,children:e.consequence}):null,_jsx(View,{style:styles.actionsRow,children:l?_jsx(Text,{style:styles.decided,children:s?"✓ Applied with these values":"✕ Not applied"}):_jsxs(_Fragment,{children:[_jsx(Pressable,{onPress:()=>t.answer({blockId:e.id,kind:"proposal",approved:!0,values:o}),style:[styles.button,styles.buttonPrimary],children:_jsx(Text,{style:styles.buttonTextPrimary,children:e.approveLabel??"Apply"})}),_jsx(Pressable,{onPress:()=>t.answer({blockId:e.id,kind:"proposal",approved:!1}),style:[styles.button,styles.buttonPlate],children:_jsx(Text,{style:styles.buttonTextPlate,children:"Not now"})})]})})]})}export function Claim({block:e}){const t=useBlockHandlers(),[l,o]=useState(null),i=t.actionState?.[`${e.id}:${e.verify?.label??"Verify"}`],s=e.verified||"done"===i;return _jsxs(View,{style:styles.claim,testID:`buoy-block-claim-${e.id}`,children:[_jsxs(Text,{style:styles.claimText,children:[e.text,e.sources.map((e,t)=>_jsxs(Text,{onPress:()=>o(l===t?null:t),style:styles.cite,children:[" [",t+1,"]"]},t)),s?_jsx(Text,{style:styles.verified,children:" ✓ verified"}):null]}),null!==l&&e.sources[l]?_jsxs(View,{style:styles.citeBox,children:[_jsxs(Text,{style:styles.citeLabel,children:["[",l+1,"] ",e.sources[l].label]}),e.sources[l].detail?_jsx(Text,{style:styles.citeDetail,children:e.sources[l].detail}):null]}):null,e.verify&&!s?_jsxs(Pressable,{onPress:()=>{t.runAction(e.verify,e.id)},style:styles.verifyBtn,accessibilityRole:"button",children:[_jsx(RefreshCw,{size:11,color:night.color.accent}),_jsx(Text,{style:styles.verifyText,children:"running"===i?"Checking…":e.verify.label})]}):null]})}export function Details({block:e}){const[t,l]=useState(!!e.open);return _jsxs(Card,{testID:`buoy-block-details-${e.id}`,children:[_jsxs(Pressable,{onPress:()=>l(e=>!e),style:b.row,accessibilityRole:"button",accessibilityState:{expanded:t},children:[_jsx(Text,{style:b.rowTitle,children:e.summary}),_jsx(t?ChevronDown:ChevronRight,{size:12,color:night.color.textTertiary})]}),t?_jsx(Text,{style:styles.detailsBody,selectable:!0,children:e.body}):null]})}export function Tabs({block:e}){const[t,l]=useState(0);return _jsxs(View,{style:styles.tabsWrap,testID:`buoy-block-tabs-${e.id}`,children:[_jsx(View,{style:styles.tabBar,children:e.tabs.map((e,o)=>_jsx(Pressable,{onPress:()=>l(o),style:[styles.tab,t===o&&styles.tabOn],accessibilityRole:"tab",children:_jsx(Text,{style:[styles.tabText,t===o&&styles.tabTextOn],children:e.label})},e.label))}),e.tabs[t]?_jsx(BlockRenderer,{block:e.tabs[t].block}):null]})}export function Timeline({block:e}){return _jsxs(Card,{title:e.title??"What happened",source:e.source,testID:`buoy-block-timeline-${e.id}`,children:[e.events.slice(0,10).map((t,l)=>_jsxs(View,{style:styles.tlRow,children:[_jsx(Text,{style:styles.tlAt,children:t.at}),_jsxs(View,{style:styles.tlLine,children:[_jsx(View,{style:[styles.tlDot,{backgroundColor:toneColor(t.tone??"muted")}]}),l<e.events.length-1?_jsx(View,{style:styles.tlStem}):null]}),_jsxs(View,{style:styles.flex,children:[_jsx(Text,{style:styles.tlSource,children:t.source.toUpperCase()}),_jsx(Text,{style:b.rowTitle,numberOfLines:2,children:t.label})]})]},l)),e.total&&e.total>e.events.length?_jsxs(Text,{style:styles.hint,children:["+",e.total-e.events.length," more"]}):null]})}export function Sparkline({block:e}){const t=e.series.slice(-60),l=Math.max(1,...t),o=Math.min(...t,0);return _jsxs(Card,{title:e.title,source:e.source,testID:`buoy-block-sparkline-${e.id}`,children:[_jsxs(View,{style:styles.sparkHead,children:[_jsxs(Text,{style:styles.sparkCurrent,children:[e.current??t[t.length-1],e.unit?_jsxs(Text,{style:styles.sparkUnit,children:[" ",e.unit]}):null]}),e.live?_jsx(LivePill,{}):null]}),_jsx(View,{style:[styles.spark,{height:44}],children:t.map((e,i)=>_jsx(View,{style:[styles.sparkBar,{height:Math.max(2,(e-o)/(l-o||1)*44),backgroundColor:i===t.length-1?night.color.accent:night.color.accentBorderStrong}]},i))}),e.label?_jsx(Text,{style:styles.hint,children:e.label}):null]})}export function LivePill(){const e=useRef(new Animated.Value(1)).current;return useEffect(()=>{const t=Animated.loop(Animated.sequence([Animated.timing(e,{toValue:.3,duration:700,useNativeDriver:!0}),Animated.timing(e,{toValue:1,duration:700,useNativeDriver:!0})]));return t.start(),()=>t.stop()},[e]),_jsxs(View,{style:styles.live,children:[_jsx(Animated.View,{style:[styles.liveDot,{opacity:e}]}),_jsx(Text,{style:styles.liveText,children:"LIVE"})]})}export function Compare({block:e}){const t=[...new Set([...e.left.pairs.map(e=>e.key),...e.right.pairs.map(e=>e.key)])],l=Object.fromEntries(e.left.pairs.map(e=>[e.key,e.value])),o=Object.fromEntries(e.right.pairs.map(e=>[e.key,e.value]));return _jsxs(Card,{title:e.title,source:e.source,testID:`buoy-block-compare-${e.id}`,children:[_jsxs(View,{style:styles.cmpHead,children:[_jsx(Text,{style:styles.cmpKey}),_jsx(Text,{style:styles.cmpCol,children:e.left.title}),_jsx(Text,{style:styles.cmpCol,children:e.right.title})]}),t.map((e,t)=>{const i=JSON.stringify(l[e])!==JSON.stringify(o[e]);return _jsxs(View,{style:[styles.cmpRow,t>0&&b.rowDivider,i&&styles.cmpDiff],children:[_jsx(Text,{style:styles.cmpKey,numberOfLines:1,children:e}),_jsx(Text,{style:[styles.cmpVal,i&&{color:night.color.danger}],numberOfLines:2,children:fmt(l[e])}),_jsx(Text,{style:[styles.cmpVal,i&&{color:night.color.accent}],numberOfLines:2,children:fmt(o[e])})]},e)})]})}function CardBody({c:e,id:t}){return _jsxs(_Fragment,{children:[e.image?_jsx(Image,{source:{uri:e.image},style:styles.cardImage,resizeMode:"cover",accessibilityLabel:e.title}):null,_jsxs(View,{style:styles.cardText,children:[_jsx(Text,{style:styles.cardTitle,numberOfLines:2,children:e.title}),e.subtitle?_jsx(Text,{style:b.rowSub,numberOfLines:2,children:e.subtitle}):null,e.facts?.slice(0,4).map(e=>_jsxs(View,{style:styles.fact,children:[_jsx(Text,{style:styles.factLabel,children:e.label}),_jsx(Text,{style:[styles.factValue,e.tone&&{color:toneColor(e.tone)}],children:e.value})]},e.label))]}),_jsx(ActionRow,{actions:e.actions,blockId:t})]})}export function CardView({block:e}){return _jsx(Card,{source:e.source,testID:`buoy-block-card-${e.id}`,children:_jsx(CardBody,{c:e,id:e.id})})}export function CardCarousel({block:e}){return _jsxs(View,{testID:`buoy-block-cardcarousel-${e.id}`,children:[e.title?_jsx(Text,{style:styles.carouselTitle,children:e.title}):null,_jsx(ScrollView,{horizontal:!0,showsHorizontalScrollIndicator:!1,snapToInterval:232,decelerationRate:"fast",contentContainerStyle:styles.carousel,children:e.cards.slice(0,8).map((t,l)=>_jsx(View,{style:styles.carouselCard,children:_jsx(CardBody,{c:t,id:`${e.id}-${l}`})},`${t.title}-${l}`))})]})}export function Screenshot({block:e}){const[t,l]=useState(!1);return _jsxs(Card,{title:e.route?`Screen · ${e.route}`:"Screen",source:e.source,testID:`buoy-block-screenshot-${e.id}`,children:[_jsx(Pressable,{onPress:()=>l(e=>!e),accessibilityRole:"imagebutton",accessibilityLabel:e.caption??"Screenshot",children:_jsx(Image,{source:{uri:e.url},style:[styles.shot,t&&styles.shotBig],resizeMode:"contain"})}),e.caption?_jsx(Text,{style:styles.hint,children:e.caption}):null]})}export function Plan({block:e}){const t=e.steps.filter(e=>"done"===e.state).length;return _jsxs(Card,{title:e.title,testID:`buoy-block-plan-${e.id}`,tone:e.pending?"info":void 0,children:[_jsx(View,{style:styles.progress,children:_jsx(View,{style:[styles.progressFill,{width:t/Math.max(1,e.steps.length)*100+"%"}]})}),e.steps.map((e,t)=>_jsxs(View,{style:[styles.step,t>0&&b.rowDivider],children:[_jsx(View,{style:[styles.stepMark,"done"===e.state&&styles.stepDone,"failed"===e.state&&styles.stepFailed,"running"===e.state&&styles.stepRunning],children:"done"===e.state?_jsx(Check,{size:10,color:night.color.onAccent}):"failed"===e.state?_jsx(X,{size:10,color:night.color.text}):_jsx(Text,{style:styles.stepNum,children:t+1})}),_jsxs(Text,{style:[b.rowTitle,"done"===e.state&&styles.muted],children:[e.text,"running"===e.state?"…":""]})]},t)),_jsx(ActionRow,{actions:e.actions??(e.pending?[{label:"Go",primary:!0,send:"Go ahead with the plan."},{label:"Change it",send:"Let me change the plan first."}]:void 0),blockId:e.id})]})}export function Checkpoint({block:e}){const t=useBlockHandlers();return _jsxs(Pressable,{testID:`buoy-block-checkpoint-${e.id}`,disabled:!e.restore,onPress:()=>e.restore&&void t.runAction(e.restore,e.id),style:styles.checkpoint,accessibilityRole:"button",children:[_jsx(View,{style:styles.cpFlag}),_jsxs(Text,{style:styles.cpText,children:[e.label,e.at?` · ${e.at}`:""]}),e.restore?_jsx(Text,{style:styles.cpRestore,children:e.restore.label}):null]})}export function Task({block:e}){const t="failed"===e.status?night.color.danger:"done"===e.status?night.color.accent:night.color.info;return _jsxs(Card,{testID:`buoy-block-task-${e.id}`,children:[_jsxs(View,{style:styles.taskHead,children:[_jsx(Text,{style:styles.cardTitle,children:e.title}),_jsx(View,{style:[b.pill,{backgroundColor:`${t}22`}],children:_jsx(Text,{style:[b.pillText,{color:t}],children:e.status.toUpperCase()})})]}),void 0!==e.progress?_jsx(View,{style:[styles.progress,styles.pad],children:_jsx(View,{style:[styles.progressFill,{width:`${Math.round(100*e.progress)}%`,backgroundColor:t}]})}):null,e.detail?_jsx(Text,{style:styles.hint,children:e.detail}):null,_jsx(ActionRow,{actions:e.actions,blockId:e.id})]})}export function Banner({block:e}){const t="danger"===e.tone?night.color.danger:"warning"===e.tone?night.color.warning:night.color.info;return _jsxs(View,{style:[styles.banner,{borderColor:t,backgroundColor:`${t}1A`}],testID:`buoy-block-banner-${e.id}`,children:[_jsx(AlertTriangle,{size:13,color:t}),_jsx(Text,{style:[styles.bannerText,{color:t}],numberOfLines:2,children:e.text}),e.actions?.[0]?_jsx(ActionRow,{actions:e.actions.slice(0,1),blockId:e.id,align:"right"}):null]})}export function File({block:e}){return _jsxs(Card,{testID:`buoy-block-file-${e.id}`,children:[_jsxs(View,{style:b.row,children:[_jsx(View,{style:styles.fileIcon,children:_jsx(Text,{style:styles.fileExt,children:(e.type??e.name.split(".").pop()??"file").toUpperCase().slice(0,4)})}),_jsxs(View,{style:styles.flex,children:[_jsx(Text,{style:b.rowTitle,numberOfLines:1,children:e.name}),e.size?_jsx(Text,{style:b.rowSub,children:e.size}):null]})]}),_jsx(ActionRow,{actions:e.actions,blockId:e.id})]})}export function Upload({block:e}){const t=useBlockHandlers(),l=t.answered[e.id];return _jsxs(Card,{testID:`buoy-block-upload-${e.id}`,tone:l?void 0:"info",children:[_jsx(Text,{style:styles.question,children:e.label}),l?_jsx(Text,{style:styles.decided,children:"upload"===l.kind?`Attached ${l.name}`:"(skipped)"}):_jsx(View,{style:[styles.rowEnd,{justifyContent:"flex-start"}],children:_jsx(Pressable,{onPress:()=>t.answer({blockId:e.id,kind:"upload",name:"screenshot.png"}),style:[styles.button,styles.buttonPlate],children:_jsx(Text,{style:styles.buttonTextPlate,children:"image"===e.accept?"Choose a screenshot":"Choose a file"})})})]})}const styles=StyleSheet.create({flex:{flex:1},pad:{paddingHorizontal:12,paddingBottom:8},muted:{color:night.color.textSecondary},dim:{opacity:.45},disabled:{opacity:.5},pressed:{opacity:.7},question:{color:night.color.text,fontSize:night.font.row,fontWeight:"600",lineHeight:20,paddingHorizontal:12,paddingTop:12,paddingBottom:8},hint:{color:night.color.textTertiary,fontSize:night.font.micro,paddingHorizontal:12,paddingBottom:10},decided:{color:night.color.textSecondary,fontSize:night.font.caption,fontWeight:"600",paddingHorizontal:12,paddingVertical:10},rowEnd:{flexDirection:"row",justifyContent:"flex-end",paddingHorizontal:12,paddingBottom:12,gap:8},actionsRow:{flexDirection:"row",gap:8,paddingHorizontal:12,paddingVertical:12,alignItems:"center"},button:{paddingHorizontal:14,paddingVertical:9,borderRadius:night.radius.row},buttonPrimary:{backgroundColor:night.color.accent},buttonPlate:{backgroundColor:night.color.button},buttonTextPrimary:{color:night.color.onAccent,fontSize:night.font.caption,fontWeight:"600"},buttonTextPlate:{color:night.color.text,fontSize:night.font.caption,fontWeight:"600"},chips:{flexDirection:"row",flexWrap:"wrap",gap:6},chip:{paddingHorizontal:12,paddingVertical:7,borderRadius:night.radius.chip,backgroundColor:night.color.fill,borderWidth:StyleSheet.hairlineWidth,borderColor:night.color.border},chipOn:{backgroundColor:night.color.accentSoft,borderColor:night.color.accentBorderStrong},chipText:{color:night.color.text,fontSize:night.font.caption},chipTextOn:{color:night.color.accent,fontWeight:"600"},optionsBox:{marginHorizontal:8,marginBottom:8,borderRadius:night.radius.row,backgroundColor:night.color.surfaceElevated,overflow:"hidden"},option:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:12,paddingVertical:10},optionLabel:{color:night.color.text,fontSize:night.font.body,fontWeight:"500"},optionDetail:{color:night.color.textSecondary,fontSize:night.font.caption},checkbox:{width:20,height:20,borderRadius:6,borderWidth:1.5,borderColor:night.color.textTertiary,alignItems:"center",justifyContent:"center"},checkboxOn:{backgroundColor:night.color.accent,borderColor:night.color.accent},selectBox:{marginHorizontal:12,marginBottom:12,borderRadius:night.radius.row,backgroundColor:night.color.surfaceElevated,overflow:"hidden"},selectField:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingHorizontal:12,paddingVertical:11},selectPlaceholder:{color:night.color.textSecondary,fontSize:night.font.body},search:{flexDirection:"row",alignItems:"center",gap:6,paddingHorizontal:12,paddingVertical:6,borderTopWidth:StyleSheet.hairlineWidth,borderTopColor:night.color.separator},searchInput:{flex:1,color:night.color.text,fontSize:night.font.caption,paddingVertical:4},sliderRow:{flexDirection:"row",alignItems:"center",gap:8},stepBtn:{width:28,height:28,borderRadius:14,backgroundColor:night.color.fill,alignItems:"center",justifyContent:"center"},stepText:{color:night.color.text,fontSize:16,fontWeight:"600"},trackHit:{flex:1,height:36,justifyContent:"center"},track:{height:6,borderRadius:3,backgroundColor:night.color.fillTertiary,justifyContent:"center"},fill:{height:6,borderRadius:3,backgroundColor:night.color.accent},thumb:{position:"absolute",width:20,height:20,borderRadius:10,backgroundColor:night.color.knob,marginLeft:-10,shadowColor:"#000",shadowOpacity:.35,shadowRadius:3,shadowOffset:{width:0,height:1}},sliderValue:{width:64,textAlign:"right",color:night.color.text,fontSize:night.font.caption,fontWeight:"600"},inputRow:{flexDirection:"row",alignItems:"center",gap:8,paddingBottom:12},input:{flex:1,height:38,paddingHorizontal:12,borderRadius:night.radius.row,backgroundColor:night.color.surfaceElevated,color:night.color.text,fontSize:night.font.body},fieldRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:10,paddingVertical:6},fieldCol:{paddingVertical:6,gap:6},fieldLabel:{color:night.color.textSecondary,fontSize:night.font.caption,width:110},fieldInput:{flex:1,height:34,paddingHorizontal:10,borderRadius:night.radius.segment,backgroundColor:night.color.surfaceElevated,color:night.color.text,fontSize:night.font.caption},confirmTitle:{color:night.color.text,fontSize:night.font.row,fontWeight:"600",paddingHorizontal:12,paddingTop:12},confirmChange:{color:night.color.text,fontSize:night.font.body,lineHeight:19,paddingHorizontal:12,paddingTop:6,paddingBottom:6},consequence:{color:night.color.warning,fontSize:night.font.caption,paddingHorizontal:12},claim:{gap:6,paddingHorizontal:2},claimText:{color:night.color.text,fontSize:night.font.row,lineHeight:22},cite:{color:night.color.accent,fontSize:night.font.caption,fontWeight:"700"},verified:{color:night.color.accent,fontSize:night.font.caption,fontWeight:"600"},citeBox:{padding:10,borderRadius:night.radius.row,backgroundColor:night.color.surface,borderWidth:StyleSheet.hairlineWidth,borderColor:night.color.border,gap:2},citeLabel:{color:night.color.text,fontSize:night.font.caption,fontWeight:"600"},citeDetail:{color:night.color.textSecondary,fontSize:night.font.caption,fontFamily:"Menlo"},verifyBtn:{alignSelf:"flex-start",flexDirection:"row",alignItems:"center",gap:5,paddingHorizontal:10,paddingVertical:5,borderRadius:night.radius.chip,backgroundColor:night.color.accentSoft},verifyText:{color:night.color.accent,fontSize:night.font.micro,fontWeight:"700"},detailsBody:{color:night.color.textSecondary,fontSize:night.font.caption,lineHeight:18,paddingHorizontal:12,paddingBottom:12},tabsWrap:{gap:8},tabBar:{flexDirection:"row",gap:6},tab:{paddingHorizontal:12,paddingVertical:6,borderRadius:night.radius.badge,backgroundColor:night.color.fill},tabOn:{backgroundColor:night.color.accentSoft},tabText:{color:night.color.textSecondary,fontSize:night.font.caption,fontWeight:"600"},tabTextOn:{color:night.color.accent},tlRow:{flexDirection:"row",gap:10,paddingHorizontal:12,paddingVertical:4,alignItems:"flex-start"},tlAt:{width:46,color:night.color.textTertiary,fontSize:night.font.micro,fontFamily:"Menlo",paddingTop:3},tlLine:{width:12,alignItems:"center"},tlDot:{width:8,height:8,borderRadius:4,marginTop:5},tlStem:{width:1,flex:1,minHeight:18,backgroundColor:night.color.separator,marginTop:2},tlSource:{color:night.color.textTertiary,fontSize:9,fontWeight:"700",letterSpacing:.6},sparkHead:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingHorizontal:12,paddingTop:8},sparkCurrent:{color:night.color.text,fontSize:22,fontWeight:"700"},sparkUnit:{color:night.color.textSecondary,fontSize:night.font.caption,fontWeight:"500"},spark:{flexDirection:"row",alignItems:"flex-end",gap:2,paddingHorizontal:12,paddingTop:6,paddingBottom:6},sparkBar:{flex:1,borderRadius:1},live:{flexDirection:"row",alignItems:"center",gap:5,paddingHorizontal:8,paddingVertical:3,borderRadius:night.radius.badge,backgroundColor:night.color.dangerSoft},liveDot:{width:6,height:6,borderRadius:3,backgroundColor:night.color.danger},liveText:{color:night.color.danger,fontSize:9,fontWeight:"800",letterSpacing:.8},cmpHead:{flexDirection:"row",paddingHorizontal:12,paddingVertical:6,backgroundColor:night.color.fill,gap:8},cmpCol:{flex:1,color:night.color.textTertiary,fontSize:night.font.micro,fontWeight:"700",letterSpacing:.6,textTransform:"uppercase"},cmpRow:{flexDirection:"row",paddingHorizontal:12,paddingVertical:8,gap:8,alignItems:"flex-start"},cmpDiff:{backgroundColor:night.color.fill},cmpKey:{width:90,color:night.color.textSecondary,fontSize:night.font.caption},cmpVal:{flex:1,color:night.color.text,fontSize:night.font.caption,fontFamily:"Menlo"},cardImage:{width:"100%",height:140,backgroundColor:night.color.fill},cardText:{paddingHorizontal:12,paddingTop:10,paddingBottom:4,gap:4},cardTitle:{color:night.color.text,fontSize:night.font.row,fontWeight:"600"},fact:{flexDirection:"row",justifyContent:"space-between",gap:8},factLabel:{color:night.color.textSecondary,fontSize:night.font.caption},factValue:{color:night.color.text,fontSize:night.font.caption,fontWeight:"500"},carouselTitle:{color:night.color.text,fontSize:night.font.caption,fontWeight:"600",paddingBottom:8},carousel:{gap:8,paddingRight:8},carouselCard:{width:224,borderRadius:night.radius.card,borderWidth:StyleSheet.hairlineWidth,borderColor:night.color.border,backgroundColor:night.color.surface,overflow:"hidden"},shot:{width:"100%",height:220,backgroundColor:night.color.fill},shotBig:{height:520},progress:{height:4,backgroundColor:night.color.fill,marginHorizontal:12,marginTop:6,marginBottom:8,borderRadius:2,overflow:"hidden"},progressFill:{height:4,backgroundColor:night.color.accent},step:{flexDirection:"row",alignItems:"center",gap:10,paddingHorizontal:12,paddingVertical:9},stepMark:{width:20,height:20,borderRadius:10,backgroundColor:night.color.fillTertiary,alignItems:"center",justifyContent:"center"},stepDone:{backgroundColor:night.color.accent},stepFailed:{backgroundColor:night.color.danger},stepRunning:{backgroundColor:night.color.info},stepNum:{color:night.color.text,fontSize:night.font.micro,fontWeight:"700"},checkpoint:{alignSelf:"flex-start",flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:12,paddingVertical:7,borderRadius:night.radius.chip,backgroundColor:night.color.fill},cpFlag:{width:8,height:8,borderRadius:2,backgroundColor:night.color.info},cpText:{color:night.color.textSecondary,fontSize:night.font.caption},cpRestore:{color:night.color.accent,fontSize:night.font.caption,fontWeight:"600"},taskHead:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:8,paddingHorizontal:12,paddingTop:12},banner:{flexDirection:"row",alignItems:"center",gap:8,paddingLeft:12,paddingRight:4,paddingVertical:4,borderRadius:night.radius.row,borderWidth:StyleSheet.hairlineWidth},bannerText:{flex:1,fontSize:night.font.caption,fontWeight:"600"},fileIcon:{width:40,height:40,borderRadius:8,backgroundColor:night.color.fill,alignItems:"center",justifyContent:"center"},fileExt:{color:night.color.textSecondary,fontSize:10,fontWeight:"800"}});
1
+ "use strict";
2
+
3
+ /**
4
+ * Second-wave blocks from the survey (plan §11). Prototype-quality on purpose:
5
+ * each one exists so it can be judged on the review page, and the ones that
6
+ * survive get the same care as the first wave.
7
+ */
8
+ import { useEffect, useRef, useState } from "react";
9
+ import { Animated, Image, Pressable, ScrollView, StyleSheet, Switch, Text, TextInput, View } from "react-native";
10
+ import { AlertTriangle, Check, ChevronDown, ChevronRight, night, NightSegmented, RefreshCw, Search, X } from "@buoy-gg/shared-ui";
11
+ import { BlockRenderer } from "./BlockRenderer";
12
+ import { useBlockHandlers } from "./context";
13
+ import { ActionRow, blockStyles as b, Card, More, toneColor, usePaged } from "./primitives";
14
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
15
+ const fmt = v => typeof v === "string" ? v : v === undefined ? "—" : JSON.stringify(v);
16
+
17
+ // ---------------------------------------------------------------- Suggestions
18
+ export function Suggestions({
19
+ block
20
+ }) {
21
+ const h = useBlockHandlers();
22
+ return /*#__PURE__*/_jsx(View, {
23
+ style: styles.chips,
24
+ testID: `buoy-block-suggestions-${block.id}`,
25
+ children: block.chips.slice(0, 4).map(c => /*#__PURE__*/_jsx(Pressable, {
26
+ disabled: !!h.busy,
27
+ onPress: () => void h.runAction({
28
+ label: c.label,
29
+ send: c.send ?? c.label
30
+ }, block.id),
31
+ style: ({
32
+ pressed
33
+ }) => [styles.chip, pressed && styles.pressed],
34
+ accessibilityRole: "button",
35
+ children: /*#__PURE__*/_jsx(Text, {
36
+ style: styles.chipText,
37
+ children: c.label
38
+ })
39
+ }, c.label))
40
+ });
41
+ }
42
+
43
+ // ---------------------------------------------------------------- MultiSelect
44
+ export function MultiSelect({
45
+ block
46
+ }) {
47
+ const h = useBlockHandlers();
48
+ const answer = h.answered[block.id];
49
+ const locked = !!answer;
50
+ const [picked, setPicked] = useState([]);
51
+ const chosen = answer?.kind === "multi" ? answer.optionIds : picked;
52
+ const toggle = id => setPicked(p => p.includes(id) ? p.filter(x => x !== id) : [...p, id]);
53
+ const ok = picked.length >= (block.min ?? 1) && (!block.max || picked.length <= block.max);
54
+ return /*#__PURE__*/_jsxs(Card, {
55
+ testID: `buoy-block-multi-${block.id}`,
56
+ tone: locked ? undefined : "info",
57
+ children: [/*#__PURE__*/_jsx(Text, {
58
+ style: styles.question,
59
+ children: block.question
60
+ }), /*#__PURE__*/_jsx(View, {
61
+ style: styles.optionsBox,
62
+ children: block.options.map((o, i) => {
63
+ const on = chosen.includes(o.id);
64
+ return /*#__PURE__*/_jsxs(Pressable, {
65
+ disabled: locked,
66
+ onPress: () => toggle(o.id),
67
+ style: [styles.option, i > 0 && b.rowDivider, locked && !on && styles.dim],
68
+ accessibilityRole: "checkbox",
69
+ accessibilityState: {
70
+ checked: on
71
+ },
72
+ children: [/*#__PURE__*/_jsx(View, {
73
+ style: [styles.checkbox, on && styles.checkboxOn],
74
+ children: on ? /*#__PURE__*/_jsx(Check, {
75
+ size: 11,
76
+ color: night.color.onAccent
77
+ }) : null
78
+ }), /*#__PURE__*/_jsxs(View, {
79
+ style: styles.flex,
80
+ children: [/*#__PURE__*/_jsx(Text, {
81
+ style: styles.optionLabel,
82
+ children: o.label
83
+ }), o.detail ? /*#__PURE__*/_jsx(Text, {
84
+ style: styles.optionDetail,
85
+ children: o.detail
86
+ }) : null]
87
+ })]
88
+ }, o.id);
89
+ })
90
+ }), locked ? null : /*#__PURE__*/_jsx(View, {
91
+ style: styles.rowEnd,
92
+ children: /*#__PURE__*/_jsx(Pressable, {
93
+ testID: "buoy-block-multi-submit",
94
+ disabled: !ok,
95
+ onPress: () => h.answer({
96
+ blockId: block.id,
97
+ kind: "multi",
98
+ optionIds: picked,
99
+ labels: block.options.filter(o => picked.includes(o.id)).map(o => o.label)
100
+ }),
101
+ style: [styles.button, styles.buttonPrimary, !ok && styles.disabled],
102
+ children: /*#__PURE__*/_jsx(Text, {
103
+ style: styles.buttonTextPrimary,
104
+ children: block.submitLabel ?? `Use ${picked.length || ""}`.trim()
105
+ })
106
+ })
107
+ })]
108
+ });
109
+ }
110
+
111
+ // ---------------------------------------------------------------- Select (long list)
112
+ export function Select({
113
+ block
114
+ }) {
115
+ const h = useBlockHandlers();
116
+ const answer = h.answered[block.id];
117
+ const [q, setQ] = useState("");
118
+ const [open, setOpen] = useState(false);
119
+ const chosen = answer?.kind === "select" ? answer.label : null;
120
+ const items = block.options.filter(o => !q || o.label.toLowerCase().includes(q.toLowerCase())).slice(0, 8);
121
+ return /*#__PURE__*/_jsxs(Card, {
122
+ testID: `buoy-block-select-${block.id}`,
123
+ tone: answer ? undefined : "info",
124
+ children: [/*#__PURE__*/_jsx(Text, {
125
+ style: styles.question,
126
+ children: block.label
127
+ }), chosen ? /*#__PURE__*/_jsx(Text, {
128
+ style: styles.decided,
129
+ children: chosen
130
+ }) : /*#__PURE__*/_jsxs(View, {
131
+ style: styles.selectBox,
132
+ children: [/*#__PURE__*/_jsxs(Pressable, {
133
+ onPress: () => setOpen(v => !v),
134
+ style: styles.selectField,
135
+ accessibilityRole: "button",
136
+ children: [/*#__PURE__*/_jsx(Text, {
137
+ style: styles.selectPlaceholder,
138
+ children: open ? "Choose…" : `${block.options.length} options`
139
+ }), /*#__PURE__*/_jsx(ChevronDown, {
140
+ size: 14,
141
+ color: night.color.textSecondary
142
+ })]
143
+ }), open && /*#__PURE__*/_jsxs(_Fragment, {
144
+ children: [block.searchable !== false && /*#__PURE__*/_jsxs(View, {
145
+ style: styles.search,
146
+ children: [/*#__PURE__*/_jsx(Search, {
147
+ size: 12,
148
+ color: night.color.textSecondary
149
+ }), /*#__PURE__*/_jsx(TextInput, {
150
+ style: styles.searchInput,
151
+ value: q,
152
+ onChangeText: setQ,
153
+ placeholder: "Search",
154
+ placeholderTextColor: night.color.placeholder,
155
+ autoCapitalize: "none",
156
+ autoCorrect: false
157
+ })]
158
+ }), items.map((o, i) => /*#__PURE__*/_jsxs(Pressable, {
159
+ onPress: () => h.answer({
160
+ blockId: block.id,
161
+ kind: "select",
162
+ optionId: o.id,
163
+ label: o.label
164
+ }),
165
+ style: [styles.option, i > 0 && b.rowDivider],
166
+ accessibilityRole: "button",
167
+ children: [/*#__PURE__*/_jsxs(View, {
168
+ style: styles.flex,
169
+ children: [/*#__PURE__*/_jsx(Text, {
170
+ style: styles.optionLabel,
171
+ children: o.label
172
+ }), o.detail ? /*#__PURE__*/_jsx(Text, {
173
+ style: styles.optionDetail,
174
+ children: o.detail
175
+ }) : null]
176
+ }), /*#__PURE__*/_jsx(ChevronRight, {
177
+ size: 12,
178
+ color: night.color.textTertiary
179
+ })]
180
+ }, o.id)), block.options.length > items.length ? /*#__PURE__*/_jsxs(Text, {
181
+ style: styles.hint,
182
+ children: [block.options.length - items.length, " more \u2014 keep typing"]
183
+ }) : null]
184
+ })]
185
+ })]
186
+ });
187
+ }
188
+
189
+ // ---------------------------------------------------------------- Slider
190
+ /**
191
+ * Tap anywhere on the track to jump there, or use the − / + steppers. No drag
192
+ * on purpose: a drag inside a scrolling transcript fights the list for the
193
+ * gesture, and a tap-to-place slider does the job with none of that.
194
+ */
195
+ function SliderControl({
196
+ min,
197
+ max,
198
+ step = 1,
199
+ value,
200
+ unit,
201
+ onChange,
202
+ disabled
203
+ }) {
204
+ const width = useRef(0);
205
+ const pct = max > min ? (value - min) / (max - min) * 100 : 0;
206
+ const quantise = raw => Math.min(max, Math.max(min, +(Math.round((raw - min) / step) * step + min).toFixed(6)));
207
+ const bump = d => !disabled && onChange(quantise(value + d * step));
208
+ const onTrackPress = e => {
209
+ if (disabled || width.current <= 0) return;
210
+ const ratio = Math.min(1, Math.max(0, e.nativeEvent.locationX / width.current));
211
+ onChange(quantise(min + ratio * (max - min)));
212
+ };
213
+ const onLayout = e => {
214
+ width.current = e.nativeEvent.layout.width;
215
+ };
216
+ return /*#__PURE__*/_jsxs(View, {
217
+ style: styles.sliderRow,
218
+ children: [/*#__PURE__*/_jsx(Pressable, {
219
+ disabled: disabled,
220
+ onPress: () => bump(-1),
221
+ style: styles.stepBtn,
222
+ accessibilityRole: "button",
223
+ accessibilityLabel: "Decrease",
224
+ children: /*#__PURE__*/_jsx(Text, {
225
+ style: styles.stepText,
226
+ children: "\u2212"
227
+ })
228
+ }), /*#__PURE__*/_jsx(Pressable, {
229
+ style: styles.trackHit,
230
+ onLayout: onLayout,
231
+ onPress: onTrackPress,
232
+ disabled: disabled,
233
+ accessibilityRole: "adjustable",
234
+ accessibilityValue: {
235
+ min,
236
+ max,
237
+ now: value
238
+ },
239
+ accessibilityActions: [{
240
+ name: "increment"
241
+ }, {
242
+ name: "decrement"
243
+ }],
244
+ onAccessibilityAction: e => bump(e.nativeEvent.actionName === "increment" ? 1 : -1),
245
+ children: /*#__PURE__*/_jsxs(View, {
246
+ style: styles.track,
247
+ pointerEvents: "none",
248
+ children: [/*#__PURE__*/_jsx(View, {
249
+ style: [styles.fill, {
250
+ width: `${pct}%`
251
+ }]
252
+ }), /*#__PURE__*/_jsx(View, {
253
+ style: [styles.thumb, {
254
+ left: `${pct}%`
255
+ }]
256
+ })]
257
+ })
258
+ }), /*#__PURE__*/_jsx(Pressable, {
259
+ disabled: disabled,
260
+ onPress: () => bump(1),
261
+ style: styles.stepBtn,
262
+ accessibilityRole: "button",
263
+ accessibilityLabel: "Increase",
264
+ children: /*#__PURE__*/_jsx(Text, {
265
+ style: styles.stepText,
266
+ children: "+"
267
+ })
268
+ }), /*#__PURE__*/_jsxs(Text, {
269
+ style: styles.sliderValue,
270
+ children: [value, unit ? ` ${unit}` : ""]
271
+ })]
272
+ });
273
+ }
274
+ export function Slider({
275
+ block
276
+ }) {
277
+ const h = useBlockHandlers();
278
+ const answer = h.answered[block.id];
279
+ const [v, setV] = useState(block.value ?? block.min);
280
+ return /*#__PURE__*/_jsxs(Card, {
281
+ testID: `buoy-block-slider-${block.id}`,
282
+ tone: answer ? undefined : "info",
283
+ children: [/*#__PURE__*/_jsx(Text, {
284
+ style: styles.question,
285
+ children: block.label
286
+ }), /*#__PURE__*/_jsx(View, {
287
+ style: styles.pad,
288
+ children: /*#__PURE__*/_jsx(SliderControl, {
289
+ min: block.min,
290
+ max: block.max,
291
+ step: block.step,
292
+ value: answer?.kind === "slider" ? answer.value : v,
293
+ unit: block.unit,
294
+ onChange: setV,
295
+ disabled: !!answer
296
+ })
297
+ }), answer ? null : /*#__PURE__*/_jsx(View, {
298
+ style: styles.rowEnd,
299
+ children: /*#__PURE__*/_jsx(Pressable, {
300
+ onPress: () => h.answer({
301
+ blockId: block.id,
302
+ kind: "slider",
303
+ value: v,
304
+ unit: block.unit
305
+ }),
306
+ style: [styles.button, styles.buttonPrimary],
307
+ children: /*#__PURE__*/_jsxs(Text, {
308
+ style: styles.buttonTextPrimary,
309
+ children: ["Use ", v, block.unit ? ` ${block.unit}` : ""]
310
+ })
311
+ })
312
+ })]
313
+ });
314
+ }
315
+
316
+ // ---------------------------------------------------------------- DateTime
317
+ export function DateTime({
318
+ block
319
+ }) {
320
+ const h = useBlockHandlers();
321
+ const answer = h.answered[block.id];
322
+ const [text, setText] = useState("");
323
+ const presets = block.presets ?? [{
324
+ label: "Now",
325
+ value: new Date().toISOString()
326
+ }, {
327
+ label: "Tomorrow",
328
+ value: new Date(Date.now() + 864e5).toISOString()
329
+ }, {
330
+ label: "+7 days",
331
+ value: new Date(Date.now() + 7 * 864e5).toISOString()
332
+ }, {
333
+ label: "+30 days",
334
+ value: new Date(Date.now() + 30 * 864e5).toISOString()
335
+ }];
336
+ return /*#__PURE__*/_jsxs(Card, {
337
+ testID: `buoy-block-datetime-${block.id}`,
338
+ tone: answer ? undefined : "info",
339
+ children: [/*#__PURE__*/_jsx(Text, {
340
+ style: styles.question,
341
+ children: block.label
342
+ }), answer ? /*#__PURE__*/_jsx(Text, {
343
+ style: styles.decided,
344
+ children: answer.kind === "dateTime" ? answer.label ?? answer.value : "(skipped)"
345
+ }) : /*#__PURE__*/_jsxs(_Fragment, {
346
+ children: [/*#__PURE__*/_jsx(View, {
347
+ style: [styles.chips, styles.pad],
348
+ children: presets.map(p => /*#__PURE__*/_jsx(Pressable, {
349
+ onPress: () => h.answer({
350
+ blockId: block.id,
351
+ kind: "dateTime",
352
+ value: p.value,
353
+ label: p.label
354
+ }),
355
+ style: styles.chip,
356
+ children: /*#__PURE__*/_jsx(Text, {
357
+ style: styles.chipText,
358
+ children: p.label
359
+ })
360
+ }, p.label))
361
+ }), /*#__PURE__*/_jsxs(View, {
362
+ style: [styles.inputRow, styles.pad],
363
+ children: [/*#__PURE__*/_jsx(TextInput, {
364
+ style: styles.input,
365
+ value: text,
366
+ onChangeText: setText,
367
+ placeholder: block.mode === "time" ? "14:30" : "2026-09-15",
368
+ placeholderTextColor: night.color.placeholder,
369
+ keyboardType: "numbers-and-punctuation"
370
+ }), /*#__PURE__*/_jsx(Pressable, {
371
+ disabled: !text.trim(),
372
+ onPress: () => h.answer({
373
+ blockId: block.id,
374
+ kind: "dateTime",
375
+ value: text.trim()
376
+ }),
377
+ style: [styles.button, styles.buttonPrimary, !text.trim() && styles.disabled],
378
+ children: /*#__PURE__*/_jsx(Text, {
379
+ style: styles.buttonTextPrimary,
380
+ children: "Use"
381
+ })
382
+ })]
383
+ })]
384
+ })]
385
+ });
386
+ }
387
+
388
+ // ---------------------------------------------------------------- Form / Proposal
389
+ function FieldRow({
390
+ f,
391
+ value,
392
+ onChange,
393
+ disabled
394
+ }) {
395
+ if (f.type === "toggle") {
396
+ return /*#__PURE__*/_jsxs(View, {
397
+ style: styles.fieldRow,
398
+ children: [/*#__PURE__*/_jsx(Text, {
399
+ style: styles.fieldLabel,
400
+ children: f.label
401
+ }), /*#__PURE__*/_jsx(Switch, {
402
+ value: !!value,
403
+ onValueChange: onChange,
404
+ disabled: disabled,
405
+ trackColor: {
406
+ true: night.color.accent,
407
+ false: night.color.fillTertiary
408
+ },
409
+ thumbColor: night.color.knob
410
+ })]
411
+ });
412
+ }
413
+ if (f.type === "select") {
414
+ return /*#__PURE__*/_jsxs(View, {
415
+ style: styles.fieldCol,
416
+ children: [/*#__PURE__*/_jsx(Text, {
417
+ style: styles.fieldLabel,
418
+ children: f.label
419
+ }), /*#__PURE__*/_jsx(View, {
420
+ style: styles.chips,
421
+ children: f.options.map(o => /*#__PURE__*/_jsx(Pressable, {
422
+ disabled: disabled,
423
+ onPress: () => onChange(o.id),
424
+ style: [styles.chip, value === o.id && styles.chipOn],
425
+ children: /*#__PURE__*/_jsx(Text, {
426
+ style: [styles.chipText, value === o.id && styles.chipTextOn],
427
+ children: o.label
428
+ })
429
+ }, o.id))
430
+ })]
431
+ });
432
+ }
433
+ if (f.type === "slider") {
434
+ return /*#__PURE__*/_jsxs(View, {
435
+ style: styles.fieldCol,
436
+ children: [/*#__PURE__*/_jsx(Text, {
437
+ style: styles.fieldLabel,
438
+ children: f.label
439
+ }), /*#__PURE__*/_jsx(SliderControl, {
440
+ min: f.min,
441
+ max: f.max,
442
+ step: f.step,
443
+ unit: f.unit,
444
+ value: typeof value === "number" ? value : f.min,
445
+ onChange: onChange,
446
+ disabled: disabled
447
+ })]
448
+ });
449
+ }
450
+ return /*#__PURE__*/_jsxs(View, {
451
+ style: styles.fieldRow,
452
+ children: [/*#__PURE__*/_jsx(Text, {
453
+ style: styles.fieldLabel,
454
+ children: f.label
455
+ }), /*#__PURE__*/_jsx(TextInput, {
456
+ style: styles.fieldInput,
457
+ value: value === undefined || value === null ? "" : String(value),
458
+ onChangeText: onChange,
459
+ editable: !disabled,
460
+ placeholder: f.placeholder ?? "",
461
+ placeholderTextColor: night.color.placeholder,
462
+ keyboardType: f.type === "number" ? "numeric" : "ascii-capable",
463
+ secureTextEntry: f.type === "secret",
464
+ autoCapitalize: "none",
465
+ autoCorrect: false
466
+ })]
467
+ });
468
+ }
469
+ function useFormValues(fields) {
470
+ const [values, setValues] = useState(() => Object.fromEntries(fields.map(f => [f.key, f.value])));
471
+ return {
472
+ values,
473
+ set: (k, v) => setValues(m => ({
474
+ ...m,
475
+ [k]: v
476
+ }))
477
+ };
478
+ }
479
+ export function Form({
480
+ block
481
+ }) {
482
+ const h = useBlockHandlers();
483
+ const answer = h.answered[block.id];
484
+ const {
485
+ values,
486
+ set
487
+ } = useFormValues(block.fields);
488
+ return /*#__PURE__*/_jsxs(Card, {
489
+ title: block.title,
490
+ testID: `buoy-block-form-${block.id}`,
491
+ tone: answer ? undefined : "info",
492
+ children: [/*#__PURE__*/_jsx(View, {
493
+ style: styles.pad,
494
+ children: block.fields.map(f => /*#__PURE__*/_jsx(FieldRow, {
495
+ f: f,
496
+ value: values[f.key],
497
+ onChange: v => set(f.key, v),
498
+ disabled: !!answer
499
+ }, f.key))
500
+ }), answer ? /*#__PURE__*/_jsx(Text, {
501
+ style: styles.decided,
502
+ children: "Sent"
503
+ }) : /*#__PURE__*/_jsx(View, {
504
+ style: styles.rowEnd,
505
+ children: /*#__PURE__*/_jsx(Pressable, {
506
+ onPress: () => h.answer({
507
+ blockId: block.id,
508
+ kind: "form",
509
+ values
510
+ }),
511
+ style: [styles.button, styles.buttonPrimary],
512
+ children: /*#__PURE__*/_jsx(Text, {
513
+ style: styles.buttonTextPrimary,
514
+ children: block.submitLabel ?? "Send"
515
+ })
516
+ })
517
+ })]
518
+ });
519
+ }
520
+ export function Proposal({
521
+ block
522
+ }) {
523
+ const h = useBlockHandlers();
524
+ const answer = h.answered[block.id];
525
+ const {
526
+ values,
527
+ set
528
+ } = useFormValues(block.fields);
529
+ const approved = answer?.kind === "proposal" ? answer.approved : null;
530
+ return /*#__PURE__*/_jsxs(Card, {
531
+ testID: `buoy-block-proposal-${block.id}`,
532
+ tone: answer ? undefined : "warning",
533
+ children: [/*#__PURE__*/_jsx(Text, {
534
+ style: styles.confirmTitle,
535
+ children: block.title
536
+ }), /*#__PURE__*/_jsx(Text, {
537
+ style: styles.confirmChange,
538
+ children: block.change
539
+ }), /*#__PURE__*/_jsx(View, {
540
+ style: styles.pad,
541
+ children: block.fields.map(f => /*#__PURE__*/_jsx(FieldRow, {
542
+ f: f,
543
+ value: values[f.key],
544
+ onChange: v => set(f.key, v),
545
+ disabled: !!answer
546
+ }, f.key))
547
+ }), block.consequence ? /*#__PURE__*/_jsx(Text, {
548
+ style: styles.consequence,
549
+ children: block.consequence
550
+ }) : null, /*#__PURE__*/_jsx(View, {
551
+ style: styles.actionsRow,
552
+ children: answer ? /*#__PURE__*/_jsx(Text, {
553
+ style: styles.decided,
554
+ children: approved ? "✓ Applied with these values" : "✕ Not applied"
555
+ }) : /*#__PURE__*/_jsxs(_Fragment, {
556
+ children: [/*#__PURE__*/_jsx(Pressable, {
557
+ onPress: () => h.answer({
558
+ blockId: block.id,
559
+ kind: "proposal",
560
+ approved: true,
561
+ values
562
+ }),
563
+ style: [styles.button, styles.buttonPrimary],
564
+ children: /*#__PURE__*/_jsx(Text, {
565
+ style: styles.buttonTextPrimary,
566
+ children: block.approveLabel ?? "Apply"
567
+ })
568
+ }), /*#__PURE__*/_jsx(Pressable, {
569
+ onPress: () => h.answer({
570
+ blockId: block.id,
571
+ kind: "proposal",
572
+ approved: false
573
+ }),
574
+ style: [styles.button, styles.buttonPlate],
575
+ children: /*#__PURE__*/_jsx(Text, {
576
+ style: styles.buttonTextPlate,
577
+ children: "Not now"
578
+ })
579
+ })]
580
+ })
581
+ })]
582
+ });
583
+ }
584
+
585
+ // ---------------------------------------------------------------- Claim (citations + verify)
586
+ export function Claim({
587
+ block
588
+ }) {
589
+ const h = useBlockHandlers();
590
+ const [open, setOpen] = useState(null);
591
+ const state = h.actionState?.[`${block.id}:${block.verify?.label ?? "Verify"}`];
592
+ const verified = block.verified || state === "done";
593
+ return /*#__PURE__*/_jsxs(View, {
594
+ style: styles.claim,
595
+ testID: `buoy-block-claim-${block.id}`,
596
+ children: [/*#__PURE__*/_jsxs(Text, {
597
+ style: styles.claimText,
598
+ children: [block.text, block.sources.map((s, i) => /*#__PURE__*/_jsxs(Text, {
599
+ onPress: () => setOpen(open === i ? null : i),
600
+ style: styles.cite,
601
+ children: [" [", i + 1, "]"]
602
+ }, i)), verified ? /*#__PURE__*/_jsx(Text, {
603
+ style: styles.verified,
604
+ children: " \u2713 verified"
605
+ }) : null]
606
+ }), open !== null && block.sources[open] ? /*#__PURE__*/_jsxs(View, {
607
+ style: styles.citeBox,
608
+ children: [/*#__PURE__*/_jsxs(Text, {
609
+ style: styles.citeLabel,
610
+ children: ["[", open + 1, "] ", block.sources[open].label]
611
+ }), block.sources[open].detail ? /*#__PURE__*/_jsx(Text, {
612
+ style: styles.citeDetail,
613
+ children: block.sources[open].detail
614
+ }) : null]
615
+ }) : null, block.verify && !verified ? /*#__PURE__*/_jsxs(Pressable, {
616
+ onPress: () => void h.runAction(block.verify, block.id),
617
+ style: styles.verifyBtn,
618
+ accessibilityRole: "button",
619
+ children: [/*#__PURE__*/_jsx(RefreshCw, {
620
+ size: 11,
621
+ color: night.color.accent
622
+ }), /*#__PURE__*/_jsx(Text, {
623
+ style: styles.verifyText,
624
+ children: state === "running" ? "Checking…" : block.verify.label
625
+ })]
626
+ }) : null]
627
+ });
628
+ }
629
+
630
+ // ---------------------------------------------------------------- Details / Tabs
631
+ export function Details({
632
+ block
633
+ }) {
634
+ const [open, setOpen] = useState(!!block.open);
635
+ return /*#__PURE__*/_jsxs(Card, {
636
+ testID: `buoy-block-details-${block.id}`,
637
+ children: [/*#__PURE__*/_jsxs(Pressable, {
638
+ onPress: () => setOpen(v => !v),
639
+ style: b.row,
640
+ accessibilityRole: "button",
641
+ accessibilityState: {
642
+ expanded: open
643
+ },
644
+ children: [/*#__PURE__*/_jsx(Text, {
645
+ style: b.rowTitle,
646
+ children: block.summary
647
+ }), open ? /*#__PURE__*/_jsx(ChevronDown, {
648
+ size: 12,
649
+ color: night.color.textTertiary
650
+ }) : /*#__PURE__*/_jsx(ChevronRight, {
651
+ size: 12,
652
+ color: night.color.textTertiary
653
+ })]
654
+ }), open ? /*#__PURE__*/_jsx(Text, {
655
+ style: styles.detailsBody,
656
+ selectable: true,
657
+ children: block.body
658
+ }) : null]
659
+ });
660
+ }
661
+
662
+ /**
663
+ * The tool-header segmented control, not a strip of this block's own.
664
+ *
665
+ * `NightSegmented` is what the dial settings and the network tool mount, so a
666
+ * tabbed block now reads as part of the same product rather than as a
667
+ * lookalike drawn next to it. `sm` is its compact variant, which is what a
668
+ * control inside a chat bubble wants.
669
+ *
670
+ * Keyed by INDEX, not label: two tabs may legitimately share a label, and a
671
+ * duplicate key would collapse them into one.
672
+ */
673
+ export function Tabs({
674
+ block
675
+ }) {
676
+ const [i, setI] = useState(0);
677
+ const tabs = block.tabs.map((t, k) => ({
678
+ key: String(k),
679
+ label: t.label
680
+ }));
681
+ const active = block.tabs[i];
682
+ return /*#__PURE__*/_jsxs(View, {
683
+ style: styles.tabsWrap,
684
+ testID: `buoy-block-tabs-${block.id}`,
685
+ children: [/*#__PURE__*/_jsx(NightSegmented, {
686
+ tabs: tabs,
687
+ activeKey: String(i),
688
+ onChange: key => setI(Number(key)),
689
+ size: "sm"
690
+ }), active ? /*#__PURE__*/_jsx(BlockRenderer, {
691
+ block: active.block
692
+ }) : null]
693
+ });
694
+ }
695
+
696
+ // ---------------------------------------------------------------- Timeline
697
+ /** Ten fits a phone without the answer above it scrolling away. */
698
+ const TIMELINE_CAP = 10;
699
+ export function Timeline({
700
+ block
701
+ }) {
702
+ /**
703
+ * The cap used to be a bare `.slice(0, 10)` while the "+N more" line below
704
+ * compared `total` against the FULL event array — so eleven events with a
705
+ * matching total rendered ten and said nothing about the eleventh, and a
706
+ * total larger than the array rendered a "+N more" that was only ever a
707
+ * label. Both counts come from the pager now.
708
+ */
709
+ const paged = usePaged(block.events, TIMELINE_CAP);
710
+ return /*#__PURE__*/_jsxs(Card, {
711
+ title: block.title ?? "What happened",
712
+ source: block.source,
713
+ testID: `buoy-block-timeline-${block.id}`,
714
+ children: [paged.visible.map((e, i) => /*#__PURE__*/_jsxs(View, {
715
+ style: styles.tlRow,
716
+ children: [/*#__PURE__*/_jsx(Text, {
717
+ style: styles.tlAt,
718
+ children: e.at
719
+ }), /*#__PURE__*/_jsxs(View, {
720
+ style: styles.tlLine,
721
+ children: [/*#__PURE__*/_jsx(View, {
722
+ style: [styles.tlDot, {
723
+ backgroundColor: toneColor(e.tone ?? "muted")
724
+ }]
725
+ }), i < paged.visible.length - 1 ? /*#__PURE__*/_jsx(View, {
726
+ style: styles.tlStem
727
+ }) : null]
728
+ }), /*#__PURE__*/_jsxs(View, {
729
+ style: styles.flex,
730
+ children: [/*#__PURE__*/_jsx(Text, {
731
+ style: styles.tlSource,
732
+ children: e.source.toUpperCase()
733
+ }), /*#__PURE__*/_jsx(Text, {
734
+ style: b.rowTitle,
735
+ numberOfLines: 2,
736
+ children: e.label
737
+ })]
738
+ })]
739
+ }, i)), /*#__PURE__*/_jsx(More, {
740
+ paged: paged
741
+ })]
742
+ });
743
+ }
744
+
745
+ // ---------------------------------------------------------------- Sparkline
746
+ export function Sparkline({
747
+ block
748
+ }) {
749
+ const s = block.series.slice(-60);
750
+ const max = Math.max(1, ...s);
751
+ const min = Math.min(...s, 0);
752
+ const H = 44;
753
+ return /*#__PURE__*/_jsxs(Card, {
754
+ title: block.title,
755
+ source: block.source,
756
+ testID: `buoy-block-sparkline-${block.id}`,
757
+ children: [/*#__PURE__*/_jsxs(View, {
758
+ style: styles.sparkHead,
759
+ children: [/*#__PURE__*/_jsxs(Text, {
760
+ style: styles.sparkCurrent,
761
+ children: [block.current ?? s[s.length - 1], block.unit ? /*#__PURE__*/_jsxs(Text, {
762
+ style: styles.sparkUnit,
763
+ children: [" ", block.unit]
764
+ }) : null]
765
+ }), block.live ? /*#__PURE__*/_jsx(LivePill, {}) : null]
766
+ }), /*#__PURE__*/_jsx(View, {
767
+ style: [styles.spark, {
768
+ height: H
769
+ }],
770
+ children: s.map((v, i) => /*#__PURE__*/_jsx(View, {
771
+ style: [styles.sparkBar, {
772
+ height: Math.max(2, (v - min) / (max - min || 1) * H),
773
+ backgroundColor: i === s.length - 1 ? night.color.accent : night.color.accentBorderStrong
774
+ }]
775
+ }, i))
776
+ }), block.label ? /*#__PURE__*/_jsx(Text, {
777
+ style: styles.hint,
778
+ children: block.label
779
+ }) : null]
780
+ });
781
+ }
782
+ export function LivePill() {
783
+ const o = useRef(new Animated.Value(1)).current;
784
+ useEffect(() => {
785
+ const loop = Animated.loop(Animated.sequence([Animated.timing(o, {
786
+ toValue: 0.3,
787
+ duration: 700,
788
+ useNativeDriver: true
789
+ }), Animated.timing(o, {
790
+ toValue: 1,
791
+ duration: 700,
792
+ useNativeDriver: true
793
+ })]));
794
+ loop.start();
795
+ return () => loop.stop();
796
+ }, [o]);
797
+ return /*#__PURE__*/_jsxs(View, {
798
+ style: styles.live,
799
+ children: [/*#__PURE__*/_jsx(Animated.View, {
800
+ style: [styles.liveDot, {
801
+ opacity: o
802
+ }]
803
+ }), /*#__PURE__*/_jsx(Text, {
804
+ style: styles.liveText,
805
+ children: "LIVE"
806
+ })]
807
+ });
808
+ }
809
+
810
+ // ---------------------------------------------------------------- Compare
811
+ export function Compare({
812
+ block
813
+ }) {
814
+ const keys = [...new Set([...block.left.pairs.map(p => p.key), ...block.right.pairs.map(p => p.key)])];
815
+ const l = Object.fromEntries(block.left.pairs.map(p => [p.key, p.value]));
816
+ const r = Object.fromEntries(block.right.pairs.map(p => [p.key, p.value]));
817
+ return /*#__PURE__*/_jsxs(Card, {
818
+ title: block.title,
819
+ source: block.source,
820
+ testID: `buoy-block-compare-${block.id}`,
821
+ children: [/*#__PURE__*/_jsxs(View, {
822
+ style: styles.cmpHead,
823
+ children: [/*#__PURE__*/_jsx(Text, {
824
+ style: styles.cmpKey
825
+ }), /*#__PURE__*/_jsx(Text, {
826
+ style: styles.cmpCol,
827
+ children: block.left.title
828
+ }), /*#__PURE__*/_jsx(Text, {
829
+ style: styles.cmpCol,
830
+ children: block.right.title
831
+ })]
832
+ }), keys.map((k, i) => {
833
+ const diff = JSON.stringify(l[k]) !== JSON.stringify(r[k]);
834
+ return /*#__PURE__*/_jsxs(View, {
835
+ style: [styles.cmpRow, i > 0 && b.rowDivider, diff && styles.cmpDiff],
836
+ children: [/*#__PURE__*/_jsx(Text, {
837
+ style: styles.cmpKey,
838
+ numberOfLines: 1,
839
+ children: k
840
+ }), /*#__PURE__*/_jsx(Text, {
841
+ style: [styles.cmpVal, diff && {
842
+ color: night.color.danger
843
+ }],
844
+ numberOfLines: 2,
845
+ children: fmt(l[k])
846
+ }), /*#__PURE__*/_jsx(Text, {
847
+ style: [styles.cmpVal, diff && {
848
+ color: night.color.accent
849
+ }],
850
+ numberOfLines: 2,
851
+ children: fmt(r[k])
852
+ })]
853
+ }, k);
854
+ })]
855
+ });
856
+ }
857
+
858
+ // ---------------------------------------------------------------- Card / carousel
859
+ function CardBody({
860
+ c,
861
+ id
862
+ }) {
863
+ return /*#__PURE__*/_jsxs(_Fragment, {
864
+ children: [c.image ? /*#__PURE__*/_jsx(Image, {
865
+ source: {
866
+ uri: c.image
867
+ },
868
+ style: styles.cardImage,
869
+ resizeMode: "contain",
870
+ accessibilityLabel: c.title
871
+ }) : null, /*#__PURE__*/_jsxs(View, {
872
+ style: styles.cardText,
873
+ children: [/*#__PURE__*/_jsx(Text, {
874
+ style: styles.cardTitle,
875
+ numberOfLines: 2,
876
+ children: c.title
877
+ }), c.subtitle ? /*#__PURE__*/_jsx(Text, {
878
+ style: b.rowSub,
879
+ numberOfLines: 2,
880
+ children: c.subtitle
881
+ }) : null, c.facts?.slice(0, 4).map(f => /*#__PURE__*/_jsxs(View, {
882
+ style: styles.fact,
883
+ children: [/*#__PURE__*/_jsx(Text, {
884
+ style: styles.factLabel,
885
+ children: f.label
886
+ }), /*#__PURE__*/_jsx(Text, {
887
+ style: [styles.factValue, f.tone && {
888
+ color: toneColor(f.tone)
889
+ }],
890
+ children: f.value
891
+ })]
892
+ }, f.label))]
893
+ }), /*#__PURE__*/_jsx(ActionRow, {
894
+ actions: c.actions,
895
+ blockId: id
896
+ })]
897
+ });
898
+ }
899
+ export function CardView({
900
+ block
901
+ }) {
902
+ return /*#__PURE__*/_jsx(Card, {
903
+ source: block.source,
904
+ testID: `buoy-block-card-${block.id}`,
905
+ children: /*#__PURE__*/_jsx(CardBody, {
906
+ c: block,
907
+ id: block.id
908
+ })
909
+ });
910
+ }
911
+ export function CardCarousel({
912
+ block
913
+ }) {
914
+ return /*#__PURE__*/_jsxs(View, {
915
+ testID: `buoy-block-cardcarousel-${block.id}`,
916
+ children: [block.title ? /*#__PURE__*/_jsx(Text, {
917
+ style: styles.carouselTitle,
918
+ children: block.title
919
+ }) : null, /*#__PURE__*/_jsx(ScrollView, {
920
+ horizontal: true,
921
+ showsHorizontalScrollIndicator: false,
922
+ snapToInterval: 232,
923
+ decelerationRate: "fast",
924
+ contentContainerStyle: styles.carousel,
925
+ children: block.cards.slice(0, 8).map((c, i) => /*#__PURE__*/_jsx(View, {
926
+ style: styles.carouselCard,
927
+ children: /*#__PURE__*/_jsx(CardBody, {
928
+ c: c,
929
+ id: `${block.id}-${i}`
930
+ })
931
+ }, `${c.title}-${i}`))
932
+ })]
933
+ });
934
+ }
935
+
936
+ // ---------------------------------------------------------------- Screenshot
937
+ export function Screenshot({
938
+ block
939
+ }) {
940
+ const [big, setBig] = useState(false);
941
+ return /*#__PURE__*/_jsxs(Card, {
942
+ title: block.route ? `Screen · ${block.route}` : "Screen",
943
+ source: block.source,
944
+ testID: `buoy-block-screenshot-${block.id}`,
945
+ children: [/*#__PURE__*/_jsx(Pressable, {
946
+ onPress: () => setBig(v => !v),
947
+ accessibilityRole: "imagebutton",
948
+ accessibilityLabel: block.caption ?? "Screenshot",
949
+ children: /*#__PURE__*/_jsx(Image, {
950
+ source: {
951
+ uri: block.url
952
+ },
953
+ style: [styles.shot, big && styles.shotBig],
954
+ resizeMode: "contain"
955
+ })
956
+ }), block.caption ? /*#__PURE__*/_jsx(Text, {
957
+ style: styles.hint,
958
+ children: block.caption
959
+ }) : null]
960
+ });
961
+ }
962
+
963
+ // ---------------------------------------------------------------- Plan / Checkpoint / Task
964
+ export function Plan({
965
+ block
966
+ }) {
967
+ const done = block.steps.filter(s => s.state === "done").length;
968
+ return /*#__PURE__*/_jsxs(Card, {
969
+ title: block.title,
970
+ testID: `buoy-block-plan-${block.id}`,
971
+ tone: block.pending ? "info" : undefined,
972
+ children: [/*#__PURE__*/_jsx(View, {
973
+ style: styles.progress,
974
+ children: /*#__PURE__*/_jsx(View, {
975
+ style: [styles.progressFill, {
976
+ width: `${done / Math.max(1, block.steps.length) * 100}%`
977
+ }]
978
+ })
979
+ }), block.steps.map((s, i) => /*#__PURE__*/_jsxs(View, {
980
+ style: [styles.step, i > 0 && b.rowDivider],
981
+ children: [/*#__PURE__*/_jsx(View, {
982
+ style: [styles.stepMark, s.state === "done" && styles.stepDone, s.state === "failed" && styles.stepFailed, s.state === "running" && styles.stepRunning],
983
+ children: s.state === "done" ? /*#__PURE__*/_jsx(Check, {
984
+ size: 10,
985
+ color: night.color.onAccent
986
+ }) : s.state === "failed" ? /*#__PURE__*/_jsx(X, {
987
+ size: 10,
988
+ color: night.color.text
989
+ }) : /*#__PURE__*/_jsx(Text, {
990
+ style: styles.stepNum,
991
+ children: i + 1
992
+ })
993
+ }), /*#__PURE__*/_jsxs(Text, {
994
+ style: [b.rowTitle, s.state === "done" && styles.muted],
995
+ children: [s.text, s.state === "running" ? "…" : ""]
996
+ })]
997
+ }, i)), /*#__PURE__*/_jsx(ActionRow, {
998
+ actions: block.actions ?? (block.pending ? [{
999
+ label: "Go",
1000
+ primary: true,
1001
+ send: "Go ahead with the plan."
1002
+ }, {
1003
+ label: "Change it",
1004
+ send: "Let me change the plan first."
1005
+ }] : undefined),
1006
+ blockId: block.id
1007
+ })]
1008
+ });
1009
+ }
1010
+ export function Checkpoint({
1011
+ block
1012
+ }) {
1013
+ const h = useBlockHandlers();
1014
+ return /*#__PURE__*/_jsxs(Pressable, {
1015
+ testID: `buoy-block-checkpoint-${block.id}`,
1016
+ disabled: !block.restore,
1017
+ onPress: () => block.restore && void h.runAction(block.restore, block.id),
1018
+ style: styles.checkpoint,
1019
+ accessibilityRole: "button",
1020
+ children: [/*#__PURE__*/_jsx(View, {
1021
+ style: styles.cpFlag
1022
+ }), /*#__PURE__*/_jsxs(Text, {
1023
+ style: styles.cpText,
1024
+ children: [block.label, block.at ? ` · ${block.at}` : ""]
1025
+ }), block.restore ? /*#__PURE__*/_jsx(Text, {
1026
+ style: styles.cpRestore,
1027
+ children: block.restore.label
1028
+ }) : null]
1029
+ });
1030
+ }
1031
+ export function Task({
1032
+ block
1033
+ }) {
1034
+ const color = block.status === "failed" ? night.color.danger : block.status === "done" ? night.color.accent : night.color.info;
1035
+ return /*#__PURE__*/_jsxs(Card, {
1036
+ testID: `buoy-block-task-${block.id}`,
1037
+ children: [/*#__PURE__*/_jsxs(View, {
1038
+ style: styles.taskHead,
1039
+ children: [/*#__PURE__*/_jsx(Text, {
1040
+ style: styles.cardTitle,
1041
+ children: block.title
1042
+ }), /*#__PURE__*/_jsx(View, {
1043
+ style: [b.pill, {
1044
+ backgroundColor: `${color}22`
1045
+ }],
1046
+ children: /*#__PURE__*/_jsx(Text, {
1047
+ style: [b.pillText, {
1048
+ color
1049
+ }],
1050
+ children: block.status.toUpperCase()
1051
+ })
1052
+ })]
1053
+ }), block.progress !== undefined ? /*#__PURE__*/_jsx(View, {
1054
+ style: [styles.progress, styles.pad],
1055
+ children: /*#__PURE__*/_jsx(View, {
1056
+ style: [styles.progressFill, {
1057
+ width: `${Math.round(block.progress * 100)}%`,
1058
+ backgroundColor: color
1059
+ }]
1060
+ })
1061
+ }) : null, block.detail ? /*#__PURE__*/_jsx(Text, {
1062
+ style: styles.hint,
1063
+ children: block.detail
1064
+ }) : null, /*#__PURE__*/_jsx(ActionRow, {
1065
+ actions: block.actions,
1066
+ blockId: block.id
1067
+ })]
1068
+ });
1069
+ }
1070
+
1071
+ // ---------------------------------------------------------------- Banner / File / Upload / NotBuilt
1072
+ export function Banner({
1073
+ block
1074
+ }) {
1075
+ const color = block.tone === "danger" ? night.color.danger : block.tone === "warning" ? night.color.warning : night.color.info;
1076
+ return /*#__PURE__*/_jsxs(View, {
1077
+ style: [styles.banner, {
1078
+ borderColor: color,
1079
+ backgroundColor: `${color}1A`
1080
+ }],
1081
+ testID: `buoy-block-banner-${block.id}`,
1082
+ children: [/*#__PURE__*/_jsx(AlertTriangle, {
1083
+ size: 13,
1084
+ color: color
1085
+ }), /*#__PURE__*/_jsx(Text, {
1086
+ style: [styles.bannerText, {
1087
+ color
1088
+ }],
1089
+ numberOfLines: 2,
1090
+ children: block.text
1091
+ }), block.actions?.[0] ? /*#__PURE__*/_jsx(ActionRow, {
1092
+ actions: block.actions.slice(0, 1),
1093
+ blockId: block.id,
1094
+ align: "right"
1095
+ }) : null]
1096
+ });
1097
+ }
1098
+ export function File({
1099
+ block
1100
+ }) {
1101
+ return /*#__PURE__*/_jsxs(Card, {
1102
+ testID: `buoy-block-file-${block.id}`,
1103
+ children: [/*#__PURE__*/_jsxs(View, {
1104
+ style: b.row,
1105
+ children: [/*#__PURE__*/_jsx(View, {
1106
+ style: styles.fileIcon,
1107
+ children: /*#__PURE__*/_jsx(Text, {
1108
+ style: styles.fileExt,
1109
+ children: (block.type ?? block.name.split(".").pop() ?? "file").toUpperCase().slice(0, 4)
1110
+ })
1111
+ }), /*#__PURE__*/_jsxs(View, {
1112
+ style: styles.flex,
1113
+ children: [/*#__PURE__*/_jsx(Text, {
1114
+ style: b.rowTitle,
1115
+ numberOfLines: 1,
1116
+ children: block.name
1117
+ }), block.size ? /*#__PURE__*/_jsx(Text, {
1118
+ style: b.rowSub,
1119
+ children: block.size
1120
+ }) : null]
1121
+ })]
1122
+ }), /*#__PURE__*/_jsx(ActionRow, {
1123
+ actions: block.actions,
1124
+ blockId: block.id
1125
+ })]
1126
+ });
1127
+ }
1128
+ export function Upload({
1129
+ block
1130
+ }) {
1131
+ const h = useBlockHandlers();
1132
+ const answer = h.answered[block.id];
1133
+ return /*#__PURE__*/_jsxs(Card, {
1134
+ testID: `buoy-block-upload-${block.id}`,
1135
+ tone: answer ? undefined : "info",
1136
+ children: [/*#__PURE__*/_jsx(Text, {
1137
+ style: styles.question,
1138
+ children: block.label
1139
+ }), answer ? /*#__PURE__*/_jsx(Text, {
1140
+ style: styles.decided,
1141
+ children: answer.kind === "upload" ? `Attached ${answer.name}` : "(skipped)"
1142
+ }) : /*#__PURE__*/_jsx(View, {
1143
+ style: [styles.rowEnd, {
1144
+ justifyContent: "flex-start"
1145
+ }],
1146
+ children: /*#__PURE__*/_jsx(Pressable, {
1147
+ onPress: () => h.answer({
1148
+ blockId: block.id,
1149
+ kind: "upload",
1150
+ name: "screenshot.png"
1151
+ }),
1152
+ style: [styles.button, styles.buttonPlate],
1153
+ children: /*#__PURE__*/_jsx(Text, {
1154
+ style: styles.buttonTextPlate,
1155
+ children: block.accept === "image" ? "Choose a screenshot" : "Choose a file"
1156
+ })
1157
+ })
1158
+ })]
1159
+ });
1160
+ }
1161
+ const styles = StyleSheet.create({
1162
+ flex: {
1163
+ flex: 1
1164
+ },
1165
+ pad: {
1166
+ paddingHorizontal: 12,
1167
+ paddingBottom: 8
1168
+ },
1169
+ muted: {
1170
+ color: night.color.textSecondary
1171
+ },
1172
+ dim: {
1173
+ opacity: 0.45
1174
+ },
1175
+ disabled: {
1176
+ opacity: 0.5
1177
+ },
1178
+ pressed: {
1179
+ opacity: 0.7
1180
+ },
1181
+ question: {
1182
+ color: night.color.text,
1183
+ fontSize: night.font.row,
1184
+ fontWeight: "600",
1185
+ lineHeight: 20,
1186
+ paddingHorizontal: 12,
1187
+ paddingTop: 12,
1188
+ paddingBottom: 8
1189
+ },
1190
+ hint: {
1191
+ color: night.color.textTertiary,
1192
+ fontSize: night.font.micro,
1193
+ paddingHorizontal: 12,
1194
+ paddingBottom: 10
1195
+ },
1196
+ decided: {
1197
+ color: night.color.textSecondary,
1198
+ fontSize: night.font.caption,
1199
+ fontWeight: "600",
1200
+ paddingHorizontal: 12,
1201
+ paddingVertical: 10
1202
+ },
1203
+ rowEnd: {
1204
+ flexDirection: "row",
1205
+ justifyContent: "flex-end",
1206
+ paddingHorizontal: 12,
1207
+ paddingBottom: 12,
1208
+ gap: 8
1209
+ },
1210
+ actionsRow: {
1211
+ flexDirection: "row",
1212
+ gap: 8,
1213
+ paddingHorizontal: 12,
1214
+ paddingVertical: 12,
1215
+ alignItems: "center"
1216
+ },
1217
+ button: {
1218
+ paddingHorizontal: 14,
1219
+ paddingVertical: 9,
1220
+ borderRadius: night.radius.row
1221
+ },
1222
+ buttonPrimary: {
1223
+ backgroundColor: night.color.accent
1224
+ },
1225
+ buttonPlate: {
1226
+ backgroundColor: night.color.button
1227
+ },
1228
+ buttonTextPrimary: {
1229
+ color: night.color.onAccent,
1230
+ fontSize: night.font.caption,
1231
+ fontWeight: "600"
1232
+ },
1233
+ buttonTextPlate: {
1234
+ color: night.color.text,
1235
+ fontSize: night.font.caption,
1236
+ fontWeight: "600"
1237
+ },
1238
+ chips: {
1239
+ flexDirection: "row",
1240
+ flexWrap: "wrap",
1241
+ gap: 6
1242
+ },
1243
+ chip: {
1244
+ paddingHorizontal: 12,
1245
+ paddingVertical: 7,
1246
+ borderRadius: night.radius.chip,
1247
+ backgroundColor: night.color.fill,
1248
+ borderWidth: StyleSheet.hairlineWidth,
1249
+ borderColor: night.color.border
1250
+ },
1251
+ chipOn: {
1252
+ backgroundColor: night.color.accentSoft,
1253
+ borderColor: night.color.accentBorderStrong
1254
+ },
1255
+ chipText: {
1256
+ color: night.color.text,
1257
+ fontSize: night.font.caption
1258
+ },
1259
+ chipTextOn: {
1260
+ color: night.color.accent,
1261
+ fontWeight: "600"
1262
+ },
1263
+ optionsBox: {
1264
+ marginHorizontal: 8,
1265
+ marginBottom: 8,
1266
+ borderRadius: night.radius.row,
1267
+ backgroundColor: night.color.surfaceElevated,
1268
+ overflow: "hidden"
1269
+ },
1270
+ option: {
1271
+ flexDirection: "row",
1272
+ alignItems: "center",
1273
+ gap: 10,
1274
+ paddingHorizontal: 12,
1275
+ paddingVertical: 10
1276
+ },
1277
+ optionLabel: {
1278
+ color: night.color.text,
1279
+ fontSize: night.font.body,
1280
+ fontWeight: "500"
1281
+ },
1282
+ optionDetail: {
1283
+ color: night.color.textSecondary,
1284
+ fontSize: night.font.caption
1285
+ },
1286
+ checkbox: {
1287
+ width: 20,
1288
+ height: 20,
1289
+ borderRadius: 6,
1290
+ borderWidth: 1.5,
1291
+ borderColor: night.color.textTertiary,
1292
+ alignItems: "center",
1293
+ justifyContent: "center"
1294
+ },
1295
+ checkboxOn: {
1296
+ backgroundColor: night.color.accent,
1297
+ borderColor: night.color.accent
1298
+ },
1299
+ selectBox: {
1300
+ marginHorizontal: 12,
1301
+ marginBottom: 12,
1302
+ borderRadius: night.radius.row,
1303
+ backgroundColor: night.color.surfaceElevated,
1304
+ overflow: "hidden"
1305
+ },
1306
+ selectField: {
1307
+ flexDirection: "row",
1308
+ alignItems: "center",
1309
+ justifyContent: "space-between",
1310
+ paddingHorizontal: 12,
1311
+ paddingVertical: 11
1312
+ },
1313
+ selectPlaceholder: {
1314
+ color: night.color.textSecondary,
1315
+ fontSize: night.font.body
1316
+ },
1317
+ search: {
1318
+ flexDirection: "row",
1319
+ alignItems: "center",
1320
+ gap: 6,
1321
+ paddingHorizontal: 12,
1322
+ paddingVertical: 6,
1323
+ borderTopWidth: StyleSheet.hairlineWidth,
1324
+ borderTopColor: night.color.separator
1325
+ },
1326
+ searchInput: {
1327
+ flex: 1,
1328
+ color: night.color.text,
1329
+ fontSize: night.font.caption,
1330
+ paddingVertical: 4
1331
+ },
1332
+ sliderRow: {
1333
+ flexDirection: "row",
1334
+ alignItems: "center",
1335
+ gap: 8
1336
+ },
1337
+ stepBtn: {
1338
+ width: 28,
1339
+ height: 28,
1340
+ borderRadius: 14,
1341
+ backgroundColor: night.color.fill,
1342
+ alignItems: "center",
1343
+ justifyContent: "center"
1344
+ },
1345
+ stepText: {
1346
+ color: night.color.text,
1347
+ fontSize: 16,
1348
+ fontWeight: "600"
1349
+ },
1350
+ trackHit: {
1351
+ flex: 1,
1352
+ height: 36,
1353
+ justifyContent: "center"
1354
+ },
1355
+ track: {
1356
+ height: 6,
1357
+ borderRadius: 3,
1358
+ backgroundColor: night.color.fillTertiary,
1359
+ justifyContent: "center"
1360
+ },
1361
+ fill: {
1362
+ height: 6,
1363
+ borderRadius: 3,
1364
+ backgroundColor: night.color.accent
1365
+ },
1366
+ thumb: {
1367
+ position: "absolute",
1368
+ width: 20,
1369
+ height: 20,
1370
+ borderRadius: 10,
1371
+ backgroundColor: night.color.knob,
1372
+ marginLeft: -10,
1373
+ shadowColor: "#000",
1374
+ shadowOpacity: 0.35,
1375
+ shadowRadius: 3,
1376
+ shadowOffset: {
1377
+ width: 0,
1378
+ height: 1
1379
+ }
1380
+ },
1381
+ sliderValue: {
1382
+ width: 64,
1383
+ textAlign: "right",
1384
+ color: night.color.text,
1385
+ fontSize: night.font.caption,
1386
+ fontWeight: "600"
1387
+ },
1388
+ inputRow: {
1389
+ flexDirection: "row",
1390
+ alignItems: "center",
1391
+ gap: 8,
1392
+ paddingBottom: 12
1393
+ },
1394
+ input: {
1395
+ flex: 1,
1396
+ height: 38,
1397
+ paddingHorizontal: 12,
1398
+ borderRadius: night.radius.row,
1399
+ backgroundColor: night.color.surfaceElevated,
1400
+ color: night.color.text,
1401
+ fontSize: night.font.body
1402
+ },
1403
+ fieldRow: {
1404
+ flexDirection: "row",
1405
+ alignItems: "center",
1406
+ justifyContent: "space-between",
1407
+ gap: 10,
1408
+ paddingVertical: 6
1409
+ },
1410
+ fieldCol: {
1411
+ paddingVertical: 6,
1412
+ gap: 6
1413
+ },
1414
+ fieldLabel: {
1415
+ color: night.color.textSecondary,
1416
+ fontSize: night.font.caption,
1417
+ width: 110
1418
+ },
1419
+ fieldInput: {
1420
+ flex: 1,
1421
+ height: 34,
1422
+ paddingHorizontal: 10,
1423
+ borderRadius: night.radius.segment,
1424
+ backgroundColor: night.color.surfaceElevated,
1425
+ color: night.color.text,
1426
+ fontSize: night.font.caption
1427
+ },
1428
+ confirmTitle: {
1429
+ color: night.color.text,
1430
+ fontSize: night.font.row,
1431
+ fontWeight: "600",
1432
+ paddingHorizontal: 12,
1433
+ paddingTop: 12
1434
+ },
1435
+ confirmChange: {
1436
+ color: night.color.text,
1437
+ fontSize: night.font.body,
1438
+ lineHeight: 19,
1439
+ paddingHorizontal: 12,
1440
+ paddingTop: 6,
1441
+ paddingBottom: 6
1442
+ },
1443
+ consequence: {
1444
+ color: night.color.warning,
1445
+ fontSize: night.font.caption,
1446
+ paddingHorizontal: 12
1447
+ },
1448
+ claim: {
1449
+ gap: 6,
1450
+ paddingHorizontal: 2
1451
+ },
1452
+ claimText: {
1453
+ color: night.color.text,
1454
+ fontSize: night.font.row,
1455
+ lineHeight: 22
1456
+ },
1457
+ cite: {
1458
+ color: night.color.accent,
1459
+ fontSize: night.font.caption,
1460
+ fontWeight: "700"
1461
+ },
1462
+ verified: {
1463
+ color: night.color.accent,
1464
+ fontSize: night.font.caption,
1465
+ fontWeight: "600"
1466
+ },
1467
+ citeBox: {
1468
+ padding: 10,
1469
+ borderRadius: night.radius.row,
1470
+ backgroundColor: night.color.surface,
1471
+ borderWidth: StyleSheet.hairlineWidth,
1472
+ borderColor: night.color.border,
1473
+ gap: 2
1474
+ },
1475
+ citeLabel: {
1476
+ color: night.color.text,
1477
+ fontSize: night.font.caption,
1478
+ fontWeight: "600"
1479
+ },
1480
+ citeDetail: {
1481
+ color: night.color.textSecondary,
1482
+ fontSize: night.font.caption,
1483
+ fontFamily: "Menlo"
1484
+ },
1485
+ verifyBtn: {
1486
+ alignSelf: "flex-start",
1487
+ flexDirection: "row",
1488
+ alignItems: "center",
1489
+ gap: 5,
1490
+ paddingHorizontal: 10,
1491
+ paddingVertical: 5,
1492
+ borderRadius: night.radius.chip,
1493
+ backgroundColor: night.color.accentSoft
1494
+ },
1495
+ verifyText: {
1496
+ color: night.color.accent,
1497
+ fontSize: night.font.micro,
1498
+ fontWeight: "700"
1499
+ },
1500
+ detailsBody: {
1501
+ color: night.color.textSecondary,
1502
+ fontSize: night.font.caption,
1503
+ lineHeight: 18,
1504
+ paddingHorizontal: 12,
1505
+ paddingBottom: 12
1506
+ },
1507
+ tabsWrap: {
1508
+ gap: 8
1509
+ },
1510
+ tabBar: {
1511
+ flexDirection: "row",
1512
+ gap: 6
1513
+ },
1514
+ tab: {
1515
+ paddingHorizontal: 12,
1516
+ paddingVertical: 6,
1517
+ borderRadius: night.radius.badge,
1518
+ backgroundColor: night.color.fill
1519
+ },
1520
+ tabOn: {
1521
+ backgroundColor: night.color.accentSoft
1522
+ },
1523
+ tabText: {
1524
+ color: night.color.textSecondary,
1525
+ fontSize: night.font.caption,
1526
+ fontWeight: "600"
1527
+ },
1528
+ tabTextOn: {
1529
+ color: night.color.accent
1530
+ },
1531
+ tlRow: {
1532
+ flexDirection: "row",
1533
+ gap: 10,
1534
+ paddingHorizontal: 12,
1535
+ paddingVertical: 4,
1536
+ alignItems: "flex-start"
1537
+ },
1538
+ tlAt: {
1539
+ width: 46,
1540
+ color: night.color.textTertiary,
1541
+ fontSize: night.font.micro,
1542
+ fontFamily: "Menlo",
1543
+ paddingTop: 3
1544
+ },
1545
+ tlLine: {
1546
+ width: 12,
1547
+ alignItems: "center"
1548
+ },
1549
+ tlDot: {
1550
+ width: 8,
1551
+ height: 8,
1552
+ borderRadius: 4,
1553
+ marginTop: 5
1554
+ },
1555
+ tlStem: {
1556
+ width: 1,
1557
+ flex: 1,
1558
+ minHeight: 18,
1559
+ backgroundColor: night.color.separator,
1560
+ marginTop: 2
1561
+ },
1562
+ tlSource: {
1563
+ color: night.color.textTertiary,
1564
+ fontSize: 9,
1565
+ fontWeight: "700",
1566
+ letterSpacing: 0.6
1567
+ },
1568
+ sparkHead: {
1569
+ flexDirection: "row",
1570
+ alignItems: "center",
1571
+ justifyContent: "space-between",
1572
+ paddingHorizontal: 12,
1573
+ paddingTop: 8
1574
+ },
1575
+ sparkCurrent: {
1576
+ color: night.color.text,
1577
+ fontSize: 22,
1578
+ fontWeight: "700"
1579
+ },
1580
+ sparkUnit: {
1581
+ color: night.color.textSecondary,
1582
+ fontSize: night.font.caption,
1583
+ fontWeight: "500"
1584
+ },
1585
+ spark: {
1586
+ flexDirection: "row",
1587
+ alignItems: "flex-end",
1588
+ gap: 2,
1589
+ paddingHorizontal: 12,
1590
+ paddingTop: 6,
1591
+ paddingBottom: 6
1592
+ },
1593
+ sparkBar: {
1594
+ flex: 1,
1595
+ borderRadius: 1
1596
+ },
1597
+ live: {
1598
+ flexDirection: "row",
1599
+ alignItems: "center",
1600
+ gap: 5,
1601
+ paddingHorizontal: 8,
1602
+ paddingVertical: 3,
1603
+ borderRadius: night.radius.badge,
1604
+ backgroundColor: night.color.dangerSoft
1605
+ },
1606
+ liveDot: {
1607
+ width: 6,
1608
+ height: 6,
1609
+ borderRadius: 3,
1610
+ backgroundColor: night.color.danger
1611
+ },
1612
+ liveText: {
1613
+ color: night.color.danger,
1614
+ fontSize: 9,
1615
+ fontWeight: "800",
1616
+ letterSpacing: 0.8
1617
+ },
1618
+ cmpHead: {
1619
+ flexDirection: "row",
1620
+ paddingHorizontal: 12,
1621
+ paddingVertical: 6,
1622
+ backgroundColor: night.color.fill,
1623
+ gap: 8
1624
+ },
1625
+ cmpCol: {
1626
+ flex: 1,
1627
+ color: night.color.textTertiary,
1628
+ fontSize: night.font.micro,
1629
+ fontWeight: "700",
1630
+ letterSpacing: 0.6,
1631
+ textTransform: "uppercase"
1632
+ },
1633
+ cmpRow: {
1634
+ flexDirection: "row",
1635
+ paddingHorizontal: 12,
1636
+ paddingVertical: 8,
1637
+ gap: 8,
1638
+ alignItems: "flex-start"
1639
+ },
1640
+ cmpDiff: {
1641
+ backgroundColor: night.color.fill
1642
+ },
1643
+ cmpKey: {
1644
+ width: 90,
1645
+ color: night.color.textSecondary,
1646
+ fontSize: night.font.caption
1647
+ },
1648
+ cmpVal: {
1649
+ flex: 1,
1650
+ color: night.color.text,
1651
+ fontSize: night.font.caption,
1652
+ fontFamily: "Menlo"
1653
+ },
1654
+ /**
1655
+ * A fixed box the image is fitted INTO, never cropped to.
1656
+ *
1657
+ * This was `cover`, which is right for a decorative banner and wrong for
1658
+ * everything the agent actually passes: product art, avatars and sprites are
1659
+ * square, and a square scaled to fill a 2.4:1 box loses its top and bottom —
1660
+ * a Charizard reduced to a band of its own middle. These pictures are the
1661
+ * app's DATA, being looked at in a devtool; cropping hides the thing you
1662
+ * opened the card to see. `contain` letterboxes a wide image instead, which
1663
+ * costs a little space and no information. The fill behind it is the
1664
+ * letterbox. Same reasoning as the screenshot block, which was already
1665
+ * `contain`.
1666
+ */
1667
+ cardImage: {
1668
+ width: "100%",
1669
+ height: 140,
1670
+ backgroundColor: night.color.fill
1671
+ },
1672
+ cardText: {
1673
+ paddingHorizontal: 12,
1674
+ paddingTop: 10,
1675
+ paddingBottom: 4,
1676
+ gap: 4
1677
+ },
1678
+ cardTitle: {
1679
+ color: night.color.text,
1680
+ fontSize: night.font.row,
1681
+ fontWeight: "600"
1682
+ },
1683
+ fact: {
1684
+ flexDirection: "row",
1685
+ justifyContent: "space-between",
1686
+ gap: 8
1687
+ },
1688
+ factLabel: {
1689
+ color: night.color.textSecondary,
1690
+ fontSize: night.font.caption
1691
+ },
1692
+ factValue: {
1693
+ color: night.color.text,
1694
+ fontSize: night.font.caption,
1695
+ fontWeight: "500"
1696
+ },
1697
+ carouselTitle: {
1698
+ color: night.color.text,
1699
+ fontSize: night.font.caption,
1700
+ fontWeight: "600",
1701
+ paddingBottom: 8
1702
+ },
1703
+ carousel: {
1704
+ gap: 8,
1705
+ paddingRight: 8
1706
+ },
1707
+ carouselCard: {
1708
+ width: 224,
1709
+ borderRadius: night.radius.card,
1710
+ borderWidth: StyleSheet.hairlineWidth,
1711
+ borderColor: night.color.border,
1712
+ backgroundColor: night.color.surface,
1713
+ overflow: "hidden"
1714
+ },
1715
+ shot: {
1716
+ width: "100%",
1717
+ height: 220,
1718
+ backgroundColor: night.color.fill
1719
+ },
1720
+ shotBig: {
1721
+ height: 520
1722
+ },
1723
+ progress: {
1724
+ height: 4,
1725
+ backgroundColor: night.color.fill,
1726
+ marginHorizontal: 12,
1727
+ marginTop: 6,
1728
+ marginBottom: 8,
1729
+ borderRadius: 2,
1730
+ overflow: "hidden"
1731
+ },
1732
+ progressFill: {
1733
+ height: 4,
1734
+ backgroundColor: night.color.accent
1735
+ },
1736
+ step: {
1737
+ flexDirection: "row",
1738
+ alignItems: "center",
1739
+ gap: 10,
1740
+ paddingHorizontal: 12,
1741
+ paddingVertical: 9
1742
+ },
1743
+ stepMark: {
1744
+ width: 20,
1745
+ height: 20,
1746
+ borderRadius: 10,
1747
+ backgroundColor: night.color.fillTertiary,
1748
+ alignItems: "center",
1749
+ justifyContent: "center"
1750
+ },
1751
+ stepDone: {
1752
+ backgroundColor: night.color.accent
1753
+ },
1754
+ stepFailed: {
1755
+ backgroundColor: night.color.danger
1756
+ },
1757
+ stepRunning: {
1758
+ backgroundColor: night.color.info
1759
+ },
1760
+ stepNum: {
1761
+ color: night.color.text,
1762
+ fontSize: night.font.micro,
1763
+ fontWeight: "700"
1764
+ },
1765
+ checkpoint: {
1766
+ alignSelf: "flex-start",
1767
+ flexDirection: "row",
1768
+ alignItems: "center",
1769
+ gap: 8,
1770
+ paddingHorizontal: 12,
1771
+ paddingVertical: 7,
1772
+ borderRadius: night.radius.chip,
1773
+ backgroundColor: night.color.fill
1774
+ },
1775
+ cpFlag: {
1776
+ width: 8,
1777
+ height: 8,
1778
+ borderRadius: 2,
1779
+ backgroundColor: night.color.info
1780
+ },
1781
+ cpText: {
1782
+ color: night.color.textSecondary,
1783
+ fontSize: night.font.caption
1784
+ },
1785
+ cpRestore: {
1786
+ color: night.color.accent,
1787
+ fontSize: night.font.caption,
1788
+ fontWeight: "600"
1789
+ },
1790
+ taskHead: {
1791
+ flexDirection: "row",
1792
+ alignItems: "center",
1793
+ justifyContent: "space-between",
1794
+ gap: 8,
1795
+ paddingHorizontal: 12,
1796
+ paddingTop: 12
1797
+ },
1798
+ banner: {
1799
+ flexDirection: "row",
1800
+ alignItems: "center",
1801
+ gap: 8,
1802
+ paddingLeft: 12,
1803
+ paddingRight: 4,
1804
+ paddingVertical: 4,
1805
+ borderRadius: night.radius.row,
1806
+ borderWidth: StyleSheet.hairlineWidth
1807
+ },
1808
+ bannerText: {
1809
+ flex: 1,
1810
+ fontSize: night.font.caption,
1811
+ fontWeight: "600"
1812
+ },
1813
+ fileIcon: {
1814
+ width: 40,
1815
+ height: 40,
1816
+ borderRadius: 8,
1817
+ backgroundColor: night.color.fill,
1818
+ alignItems: "center",
1819
+ justifyContent: "center"
1820
+ },
1821
+ fileExt: {
1822
+ color: night.color.textSecondary,
1823
+ fontSize: 10,
1824
+ fontWeight: "800"
1825
+ }
1826
+ });
1827
+ //# sourceMappingURL=ExtraBlocks.js.map