@buoy-gg/ask-buoy 7.0.33 → 7.0.34

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 (153) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/blocks/AskBlocks.js +1 -338
  3. package/lib/commonjs/blocks/BlockRenderer.js +1 -250
  4. package/lib/commonjs/blocks/ChromePrototypes.js +1 -514
  5. package/lib/commonjs/blocks/DataBlocks.js +1 -545
  6. package/lib/commonjs/blocks/ExtraBlocks.js +1 -1821
  7. package/lib/commonjs/blocks/MediaBlocks.js +1 -140
  8. package/lib/commonjs/blocks/ReceiptBlocks.js +1 -596
  9. package/lib/commonjs/blocks/context.js +1 -42
  10. package/lib/commonjs/blocks/icons.js +1 -96
  11. package/lib/commonjs/blocks/index.js +1 -95
  12. package/lib/commonjs/blocks/primitives.js +1 -312
  13. package/lib/commonjs/blocks/primitivesIndex.js +1 -56
  14. package/lib/commonjs/components/ApprovalCard.js +1 -140
  15. package/lib/commonjs/components/AskBuoyHeader.js +1 -127
  16. package/lib/commonjs/components/AskBuoyIcon.js +1 -19
  17. package/lib/commonjs/components/AskBuoyModal.js +1 -322
  18. package/lib/commonjs/components/ChangesBar.js +1 -211
  19. package/lib/commonjs/components/Composer.js +1 -175
  20. package/lib/commonjs/components/EmptyState.js +1 -154
  21. package/lib/commonjs/components/Markdown.js +1 -252
  22. package/lib/commonjs/components/MessageList.js +1 -648
  23. package/lib/commonjs/components/TypingDots.js +1 -63
  24. package/lib/commonjs/index.js +1 -205
  25. package/lib/commonjs/preset.js +1 -90
  26. package/lib/commonjs/store/askBuoyStore.js +1 -279
  27. package/lib/commonjs/store/useAskBuoy.js +1 -299
  28. package/lib/commonjs/sync/askBuoySyncAdapter.js +1 -119
  29. package/lib/commonjs/sync/askBuoySyncAdapter.test.js +1 -136
  30. package/lib/commonjs/sync/wire.js +1 -58
  31. package/lib/commonjs/types.js +1 -6
  32. package/lib/module/blocks/AskBlocks.js +1 -331
  33. package/lib/module/blocks/BlockRenderer.js +1 -245
  34. package/lib/module/blocks/ChromePrototypes.js +1 -503
  35. package/lib/module/blocks/DataBlocks.js +1 -532
  36. package/lib/module/blocks/ExtraBlocks.js +1 -1794
  37. package/lib/module/blocks/MediaBlocks.js +1 -135
  38. package/lib/module/blocks/ReceiptBlocks.js +1 -584
  39. package/lib/module/blocks/context.js +1 -35
  40. package/lib/module/blocks/icons.js +1 -91
  41. package/lib/module/blocks/index.js +1 -8
  42. package/lib/module/blocks/primitives.js +1 -301
  43. package/lib/module/blocks/primitivesIndex.js +1 -5
  44. package/lib/module/components/ApprovalCard.js +1 -135
  45. package/lib/module/components/AskBuoyHeader.js +1 -124
  46. package/lib/module/components/AskBuoyIcon.js +1 -8
  47. package/lib/module/components/AskBuoyModal.js +1 -317
  48. package/lib/module/components/ChangesBar.js +1 -206
  49. package/lib/module/components/Composer.js +1 -170
  50. package/lib/module/components/EmptyState.js +1 -149
  51. package/lib/module/components/Markdown.js +1 -246
  52. package/lib/module/components/MessageList.js +1 -642
  53. package/lib/module/components/TypingDots.js +1 -58
  54. package/lib/module/index.js +1 -29
  55. package/lib/module/preset.js +1 -73
  56. package/lib/module/store/askBuoyStore.js +1 -275
  57. package/lib/module/store/useAskBuoy.js +1 -293
  58. package/lib/module/sync/askBuoySyncAdapter.js +1 -114
  59. package/lib/module/sync/askBuoySyncAdapter.test.js +1 -135
  60. package/lib/module/sync/wire.js +1 -47
  61. package/lib/module/types.js +1 -4
  62. package/lib/typescript/preset.d.ts +1 -1
  63. package/package.json +8 -8
  64. package/lib/commonjs/blocks/AskBlocks.js.map +0 -1
  65. package/lib/commonjs/blocks/BlockRenderer.js.map +0 -1
  66. package/lib/commonjs/blocks/ChromePrototypes.js.map +0 -1
  67. package/lib/commonjs/blocks/DataBlocks.js.map +0 -1
  68. package/lib/commonjs/blocks/ExtraBlocks.js.map +0 -1
  69. package/lib/commonjs/blocks/MediaBlocks.js.map +0 -1
  70. package/lib/commonjs/blocks/ReceiptBlocks.js.map +0 -1
  71. package/lib/commonjs/blocks/context.js.map +0 -1
  72. package/lib/commonjs/blocks/icons.js.map +0 -1
  73. package/lib/commonjs/blocks/index.js.map +0 -1
  74. package/lib/commonjs/blocks/primitives.js.map +0 -1
  75. package/lib/commonjs/blocks/primitivesIndex.js.map +0 -1
  76. package/lib/commonjs/components/ApprovalCard.js.map +0 -1
  77. package/lib/commonjs/components/AskBuoyHeader.js.map +0 -1
  78. package/lib/commonjs/components/AskBuoyIcon.js.map +0 -1
  79. package/lib/commonjs/components/AskBuoyModal.js.map +0 -1
  80. package/lib/commonjs/components/ChangesBar.js.map +0 -1
  81. package/lib/commonjs/components/Composer.js.map +0 -1
  82. package/lib/commonjs/components/EmptyState.js.map +0 -1
  83. package/lib/commonjs/components/Markdown.js.map +0 -1
  84. package/lib/commonjs/components/MessageList.js.map +0 -1
  85. package/lib/commonjs/components/TypingDots.js.map +0 -1
  86. package/lib/commonjs/index.js.map +0 -1
  87. package/lib/commonjs/preset.js.map +0 -1
  88. package/lib/commonjs/store/askBuoyStore.js.map +0 -1
  89. package/lib/commonjs/store/useAskBuoy.js.map +0 -1
  90. package/lib/commonjs/sync/askBuoySyncAdapter.js.map +0 -1
  91. package/lib/commonjs/sync/askBuoySyncAdapter.test.js.map +0 -1
  92. package/lib/commonjs/sync/wire.js.map +0 -1
  93. package/lib/commonjs/types.js.map +0 -1
  94. package/lib/module/blocks/AskBlocks.js.map +0 -1
  95. package/lib/module/blocks/BlockRenderer.js.map +0 -1
  96. package/lib/module/blocks/ChromePrototypes.js.map +0 -1
  97. package/lib/module/blocks/DataBlocks.js.map +0 -1
  98. package/lib/module/blocks/ExtraBlocks.js.map +0 -1
  99. package/lib/module/blocks/MediaBlocks.js.map +0 -1
  100. package/lib/module/blocks/ReceiptBlocks.js.map +0 -1
  101. package/lib/module/blocks/context.js.map +0 -1
  102. package/lib/module/blocks/icons.js.map +0 -1
  103. package/lib/module/blocks/index.js.map +0 -1
  104. package/lib/module/blocks/primitives.js.map +0 -1
  105. package/lib/module/blocks/primitivesIndex.js.map +0 -1
  106. package/lib/module/components/ApprovalCard.js.map +0 -1
  107. package/lib/module/components/AskBuoyHeader.js.map +0 -1
  108. package/lib/module/components/AskBuoyIcon.js.map +0 -1
  109. package/lib/module/components/AskBuoyModal.js.map +0 -1
  110. package/lib/module/components/ChangesBar.js.map +0 -1
  111. package/lib/module/components/Composer.js.map +0 -1
  112. package/lib/module/components/EmptyState.js.map +0 -1
  113. package/lib/module/components/Markdown.js.map +0 -1
  114. package/lib/module/components/MessageList.js.map +0 -1
  115. package/lib/module/components/TypingDots.js.map +0 -1
  116. package/lib/module/index.js.map +0 -1
  117. package/lib/module/preset.js.map +0 -1
  118. package/lib/module/store/askBuoyStore.js.map +0 -1
  119. package/lib/module/store/useAskBuoy.js.map +0 -1
  120. package/lib/module/sync/askBuoySyncAdapter.js.map +0 -1
  121. package/lib/module/sync/askBuoySyncAdapter.test.js.map +0 -1
  122. package/lib/module/sync/wire.js.map +0 -1
  123. package/lib/module/types.js.map +0 -1
  124. package/lib/typescript/blocks/AskBlocks.d.ts.map +0 -1
  125. package/lib/typescript/blocks/BlockRenderer.d.ts.map +0 -1
  126. package/lib/typescript/blocks/ChromePrototypes.d.ts.map +0 -1
  127. package/lib/typescript/blocks/DataBlocks.d.ts.map +0 -1
  128. package/lib/typescript/blocks/ExtraBlocks.d.ts.map +0 -1
  129. package/lib/typescript/blocks/MediaBlocks.d.ts.map +0 -1
  130. package/lib/typescript/blocks/ReceiptBlocks.d.ts.map +0 -1
  131. package/lib/typescript/blocks/context.d.ts.map +0 -1
  132. package/lib/typescript/blocks/icons.d.ts.map +0 -1
  133. package/lib/typescript/blocks/index.d.ts.map +0 -1
  134. package/lib/typescript/blocks/primitives.d.ts.map +0 -1
  135. package/lib/typescript/blocks/primitivesIndex.d.ts.map +0 -1
  136. package/lib/typescript/components/ApprovalCard.d.ts.map +0 -1
  137. package/lib/typescript/components/AskBuoyHeader.d.ts.map +0 -1
  138. package/lib/typescript/components/AskBuoyIcon.d.ts.map +0 -1
  139. package/lib/typescript/components/AskBuoyModal.d.ts.map +0 -1
  140. package/lib/typescript/components/ChangesBar.d.ts.map +0 -1
  141. package/lib/typescript/components/Composer.d.ts.map +0 -1
  142. package/lib/typescript/components/EmptyState.d.ts.map +0 -1
  143. package/lib/typescript/components/Markdown.d.ts.map +0 -1
  144. package/lib/typescript/components/MessageList.d.ts.map +0 -1
  145. package/lib/typescript/components/TypingDots.d.ts.map +0 -1
  146. package/lib/typescript/index.d.ts.map +0 -1
  147. package/lib/typescript/preset.d.ts.map +0 -1
  148. package/lib/typescript/store/askBuoyStore.d.ts.map +0 -1
  149. package/lib/typescript/store/useAskBuoy.d.ts.map +0 -1
  150. package/lib/typescript/sync/askBuoySyncAdapter.d.ts.map +0 -1
  151. package/lib/typescript/sync/askBuoySyncAdapter.test.d.ts.map +0 -1
  152. package/lib/typescript/sync/wire.d.ts.map +0 -1
  153. package/lib/typescript/types.d.ts.map +0 -1
@@ -1,1794 +1 @@
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, 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, toneColor } 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
- export function Tabs({
662
- block
663
- }) {
664
- const [i, setI] = useState(0);
665
- return /*#__PURE__*/_jsxs(View, {
666
- style: styles.tabsWrap,
667
- testID: `buoy-block-tabs-${block.id}`,
668
- children: [/*#__PURE__*/_jsx(View, {
669
- style: styles.tabBar,
670
- children: block.tabs.map((t, k) => /*#__PURE__*/_jsx(Pressable, {
671
- onPress: () => setI(k),
672
- style: [styles.tab, i === k && styles.tabOn],
673
- accessibilityRole: "tab",
674
- children: /*#__PURE__*/_jsx(Text, {
675
- style: [styles.tabText, i === k && styles.tabTextOn],
676
- children: t.label
677
- })
678
- }, t.label))
679
- }), block.tabs[i] ? /*#__PURE__*/_jsx(BlockRenderer, {
680
- block: block.tabs[i].block
681
- }) : null]
682
- });
683
- }
684
-
685
- // ---------------------------------------------------------------- Timeline
686
- export function Timeline({
687
- block
688
- }) {
689
- return /*#__PURE__*/_jsxs(Card, {
690
- title: block.title ?? "What happened",
691
- source: block.source,
692
- testID: `buoy-block-timeline-${block.id}`,
693
- children: [block.events.slice(0, 10).map((e, i) => /*#__PURE__*/_jsxs(View, {
694
- style: styles.tlRow,
695
- children: [/*#__PURE__*/_jsx(Text, {
696
- style: styles.tlAt,
697
- children: e.at
698
- }), /*#__PURE__*/_jsxs(View, {
699
- style: styles.tlLine,
700
- children: [/*#__PURE__*/_jsx(View, {
701
- style: [styles.tlDot, {
702
- backgroundColor: toneColor(e.tone ?? "muted")
703
- }]
704
- }), i < block.events.length - 1 ? /*#__PURE__*/_jsx(View, {
705
- style: styles.tlStem
706
- }) : null]
707
- }), /*#__PURE__*/_jsxs(View, {
708
- style: styles.flex,
709
- children: [/*#__PURE__*/_jsx(Text, {
710
- style: styles.tlSource,
711
- children: e.source.toUpperCase()
712
- }), /*#__PURE__*/_jsx(Text, {
713
- style: b.rowTitle,
714
- numberOfLines: 2,
715
- children: e.label
716
- })]
717
- })]
718
- }, i)), block.total && block.total > block.events.length ? /*#__PURE__*/_jsxs(Text, {
719
- style: styles.hint,
720
- children: ["+", block.total - block.events.length, " more"]
721
- }) : null]
722
- });
723
- }
724
-
725
- // ---------------------------------------------------------------- Sparkline
726
- export function Sparkline({
727
- block
728
- }) {
729
- const s = block.series.slice(-60);
730
- const max = Math.max(1, ...s);
731
- const min = Math.min(...s, 0);
732
- const H = 44;
733
- return /*#__PURE__*/_jsxs(Card, {
734
- title: block.title,
735
- source: block.source,
736
- testID: `buoy-block-sparkline-${block.id}`,
737
- children: [/*#__PURE__*/_jsxs(View, {
738
- style: styles.sparkHead,
739
- children: [/*#__PURE__*/_jsxs(Text, {
740
- style: styles.sparkCurrent,
741
- children: [block.current ?? s[s.length - 1], block.unit ? /*#__PURE__*/_jsxs(Text, {
742
- style: styles.sparkUnit,
743
- children: [" ", block.unit]
744
- }) : null]
745
- }), block.live ? /*#__PURE__*/_jsx(LivePill, {}) : null]
746
- }), /*#__PURE__*/_jsx(View, {
747
- style: [styles.spark, {
748
- height: H
749
- }],
750
- children: s.map((v, i) => /*#__PURE__*/_jsx(View, {
751
- style: [styles.sparkBar, {
752
- height: Math.max(2, (v - min) / (max - min || 1) * H),
753
- backgroundColor: i === s.length - 1 ? night.color.accent : night.color.accentBorderStrong
754
- }]
755
- }, i))
756
- }), block.label ? /*#__PURE__*/_jsx(Text, {
757
- style: styles.hint,
758
- children: block.label
759
- }) : null]
760
- });
761
- }
762
- export function LivePill() {
763
- const o = useRef(new Animated.Value(1)).current;
764
- useEffect(() => {
765
- const loop = Animated.loop(Animated.sequence([Animated.timing(o, {
766
- toValue: 0.3,
767
- duration: 700,
768
- useNativeDriver: true
769
- }), Animated.timing(o, {
770
- toValue: 1,
771
- duration: 700,
772
- useNativeDriver: true
773
- })]));
774
- loop.start();
775
- return () => loop.stop();
776
- }, [o]);
777
- return /*#__PURE__*/_jsxs(View, {
778
- style: styles.live,
779
- children: [/*#__PURE__*/_jsx(Animated.View, {
780
- style: [styles.liveDot, {
781
- opacity: o
782
- }]
783
- }), /*#__PURE__*/_jsx(Text, {
784
- style: styles.liveText,
785
- children: "LIVE"
786
- })]
787
- });
788
- }
789
-
790
- // ---------------------------------------------------------------- Compare
791
- export function Compare({
792
- block
793
- }) {
794
- const keys = [...new Set([...block.left.pairs.map(p => p.key), ...block.right.pairs.map(p => p.key)])];
795
- const l = Object.fromEntries(block.left.pairs.map(p => [p.key, p.value]));
796
- const r = Object.fromEntries(block.right.pairs.map(p => [p.key, p.value]));
797
- return /*#__PURE__*/_jsxs(Card, {
798
- title: block.title,
799
- source: block.source,
800
- testID: `buoy-block-compare-${block.id}`,
801
- children: [/*#__PURE__*/_jsxs(View, {
802
- style: styles.cmpHead,
803
- children: [/*#__PURE__*/_jsx(Text, {
804
- style: styles.cmpKey
805
- }), /*#__PURE__*/_jsx(Text, {
806
- style: styles.cmpCol,
807
- children: block.left.title
808
- }), /*#__PURE__*/_jsx(Text, {
809
- style: styles.cmpCol,
810
- children: block.right.title
811
- })]
812
- }), keys.map((k, i) => {
813
- const diff = JSON.stringify(l[k]) !== JSON.stringify(r[k]);
814
- return /*#__PURE__*/_jsxs(View, {
815
- style: [styles.cmpRow, i > 0 && b.rowDivider, diff && styles.cmpDiff],
816
- children: [/*#__PURE__*/_jsx(Text, {
817
- style: styles.cmpKey,
818
- numberOfLines: 1,
819
- children: k
820
- }), /*#__PURE__*/_jsx(Text, {
821
- style: [styles.cmpVal, diff && {
822
- color: night.color.danger
823
- }],
824
- numberOfLines: 2,
825
- children: fmt(l[k])
826
- }), /*#__PURE__*/_jsx(Text, {
827
- style: [styles.cmpVal, diff && {
828
- color: night.color.accent
829
- }],
830
- numberOfLines: 2,
831
- children: fmt(r[k])
832
- })]
833
- }, k);
834
- })]
835
- });
836
- }
837
-
838
- // ---------------------------------------------------------------- Card / carousel
839
- function CardBody({
840
- c,
841
- id
842
- }) {
843
- return /*#__PURE__*/_jsxs(_Fragment, {
844
- children: [c.image ? /*#__PURE__*/_jsx(Image, {
845
- source: {
846
- uri: c.image
847
- },
848
- style: styles.cardImage,
849
- resizeMode: "cover",
850
- accessibilityLabel: c.title
851
- }) : null, /*#__PURE__*/_jsxs(View, {
852
- style: styles.cardText,
853
- children: [/*#__PURE__*/_jsx(Text, {
854
- style: styles.cardTitle,
855
- numberOfLines: 2,
856
- children: c.title
857
- }), c.subtitle ? /*#__PURE__*/_jsx(Text, {
858
- style: b.rowSub,
859
- numberOfLines: 2,
860
- children: c.subtitle
861
- }) : null, c.facts?.slice(0, 4).map(f => /*#__PURE__*/_jsxs(View, {
862
- style: styles.fact,
863
- children: [/*#__PURE__*/_jsx(Text, {
864
- style: styles.factLabel,
865
- children: f.label
866
- }), /*#__PURE__*/_jsx(Text, {
867
- style: [styles.factValue, f.tone && {
868
- color: toneColor(f.tone)
869
- }],
870
- children: f.value
871
- })]
872
- }, f.label))]
873
- }), /*#__PURE__*/_jsx(ActionRow, {
874
- actions: c.actions,
875
- blockId: id
876
- })]
877
- });
878
- }
879
- export function CardView({
880
- block
881
- }) {
882
- return /*#__PURE__*/_jsx(Card, {
883
- source: block.source,
884
- testID: `buoy-block-card-${block.id}`,
885
- children: /*#__PURE__*/_jsx(CardBody, {
886
- c: block,
887
- id: block.id
888
- })
889
- });
890
- }
891
- export function CardCarousel({
892
- block
893
- }) {
894
- return /*#__PURE__*/_jsxs(View, {
895
- testID: `buoy-block-cardcarousel-${block.id}`,
896
- children: [block.title ? /*#__PURE__*/_jsx(Text, {
897
- style: styles.carouselTitle,
898
- children: block.title
899
- }) : null, /*#__PURE__*/_jsx(ScrollView, {
900
- horizontal: true,
901
- showsHorizontalScrollIndicator: false,
902
- snapToInterval: 232,
903
- decelerationRate: "fast",
904
- contentContainerStyle: styles.carousel,
905
- children: block.cards.slice(0, 8).map((c, i) => /*#__PURE__*/_jsx(View, {
906
- style: styles.carouselCard,
907
- children: /*#__PURE__*/_jsx(CardBody, {
908
- c: c,
909
- id: `${block.id}-${i}`
910
- })
911
- }, `${c.title}-${i}`))
912
- })]
913
- });
914
- }
915
-
916
- // ---------------------------------------------------------------- Screenshot
917
- export function Screenshot({
918
- block
919
- }) {
920
- const [big, setBig] = useState(false);
921
- return /*#__PURE__*/_jsxs(Card, {
922
- title: block.route ? `Screen · ${block.route}` : "Screen",
923
- source: block.source,
924
- testID: `buoy-block-screenshot-${block.id}`,
925
- children: [/*#__PURE__*/_jsx(Pressable, {
926
- onPress: () => setBig(v => !v),
927
- accessibilityRole: "imagebutton",
928
- accessibilityLabel: block.caption ?? "Screenshot",
929
- children: /*#__PURE__*/_jsx(Image, {
930
- source: {
931
- uri: block.url
932
- },
933
- style: [styles.shot, big && styles.shotBig],
934
- resizeMode: "contain"
935
- })
936
- }), block.caption ? /*#__PURE__*/_jsx(Text, {
937
- style: styles.hint,
938
- children: block.caption
939
- }) : null]
940
- });
941
- }
942
-
943
- // ---------------------------------------------------------------- Plan / Checkpoint / Task
944
- export function Plan({
945
- block
946
- }) {
947
- const done = block.steps.filter(s => s.state === "done").length;
948
- return /*#__PURE__*/_jsxs(Card, {
949
- title: block.title,
950
- testID: `buoy-block-plan-${block.id}`,
951
- tone: block.pending ? "info" : undefined,
952
- children: [/*#__PURE__*/_jsx(View, {
953
- style: styles.progress,
954
- children: /*#__PURE__*/_jsx(View, {
955
- style: [styles.progressFill, {
956
- width: `${done / Math.max(1, block.steps.length) * 100}%`
957
- }]
958
- })
959
- }), block.steps.map((s, i) => /*#__PURE__*/_jsxs(View, {
960
- style: [styles.step, i > 0 && b.rowDivider],
961
- children: [/*#__PURE__*/_jsx(View, {
962
- style: [styles.stepMark, s.state === "done" && styles.stepDone, s.state === "failed" && styles.stepFailed, s.state === "running" && styles.stepRunning],
963
- children: s.state === "done" ? /*#__PURE__*/_jsx(Check, {
964
- size: 10,
965
- color: night.color.onAccent
966
- }) : s.state === "failed" ? /*#__PURE__*/_jsx(X, {
967
- size: 10,
968
- color: night.color.text
969
- }) : /*#__PURE__*/_jsx(Text, {
970
- style: styles.stepNum,
971
- children: i + 1
972
- })
973
- }), /*#__PURE__*/_jsxs(Text, {
974
- style: [b.rowTitle, s.state === "done" && styles.muted],
975
- children: [s.text, s.state === "running" ? "…" : ""]
976
- })]
977
- }, i)), /*#__PURE__*/_jsx(ActionRow, {
978
- actions: block.actions ?? (block.pending ? [{
979
- label: "Go",
980
- primary: true,
981
- send: "Go ahead with the plan."
982
- }, {
983
- label: "Change it",
984
- send: "Let me change the plan first."
985
- }] : undefined),
986
- blockId: block.id
987
- })]
988
- });
989
- }
990
- export function Checkpoint({
991
- block
992
- }) {
993
- const h = useBlockHandlers();
994
- return /*#__PURE__*/_jsxs(Pressable, {
995
- testID: `buoy-block-checkpoint-${block.id}`,
996
- disabled: !block.restore,
997
- onPress: () => block.restore && void h.runAction(block.restore, block.id),
998
- style: styles.checkpoint,
999
- accessibilityRole: "button",
1000
- children: [/*#__PURE__*/_jsx(View, {
1001
- style: styles.cpFlag
1002
- }), /*#__PURE__*/_jsxs(Text, {
1003
- style: styles.cpText,
1004
- children: [block.label, block.at ? ` · ${block.at}` : ""]
1005
- }), block.restore ? /*#__PURE__*/_jsx(Text, {
1006
- style: styles.cpRestore,
1007
- children: block.restore.label
1008
- }) : null]
1009
- });
1010
- }
1011
- export function Task({
1012
- block
1013
- }) {
1014
- const color = block.status === "failed" ? night.color.danger : block.status === "done" ? night.color.accent : night.color.info;
1015
- return /*#__PURE__*/_jsxs(Card, {
1016
- testID: `buoy-block-task-${block.id}`,
1017
- children: [/*#__PURE__*/_jsxs(View, {
1018
- style: styles.taskHead,
1019
- children: [/*#__PURE__*/_jsx(Text, {
1020
- style: styles.cardTitle,
1021
- children: block.title
1022
- }), /*#__PURE__*/_jsx(View, {
1023
- style: [b.pill, {
1024
- backgroundColor: `${color}22`
1025
- }],
1026
- children: /*#__PURE__*/_jsx(Text, {
1027
- style: [b.pillText, {
1028
- color
1029
- }],
1030
- children: block.status.toUpperCase()
1031
- })
1032
- })]
1033
- }), block.progress !== undefined ? /*#__PURE__*/_jsx(View, {
1034
- style: [styles.progress, styles.pad],
1035
- children: /*#__PURE__*/_jsx(View, {
1036
- style: [styles.progressFill, {
1037
- width: `${Math.round(block.progress * 100)}%`,
1038
- backgroundColor: color
1039
- }]
1040
- })
1041
- }) : null, block.detail ? /*#__PURE__*/_jsx(Text, {
1042
- style: styles.hint,
1043
- children: block.detail
1044
- }) : null, /*#__PURE__*/_jsx(ActionRow, {
1045
- actions: block.actions,
1046
- blockId: block.id
1047
- })]
1048
- });
1049
- }
1050
-
1051
- // ---------------------------------------------------------------- Banner / File / Upload / NotBuilt
1052
- export function Banner({
1053
- block
1054
- }) {
1055
- const color = block.tone === "danger" ? night.color.danger : block.tone === "warning" ? night.color.warning : night.color.info;
1056
- return /*#__PURE__*/_jsxs(View, {
1057
- style: [styles.banner, {
1058
- borderColor: color,
1059
- backgroundColor: `${color}1A`
1060
- }],
1061
- testID: `buoy-block-banner-${block.id}`,
1062
- children: [/*#__PURE__*/_jsx(AlertTriangle, {
1063
- size: 13,
1064
- color: color
1065
- }), /*#__PURE__*/_jsx(Text, {
1066
- style: [styles.bannerText, {
1067
- color
1068
- }],
1069
- numberOfLines: 2,
1070
- children: block.text
1071
- }), block.actions?.[0] ? /*#__PURE__*/_jsx(ActionRow, {
1072
- actions: block.actions.slice(0, 1),
1073
- blockId: block.id,
1074
- align: "right"
1075
- }) : null]
1076
- });
1077
- }
1078
- export function File({
1079
- block
1080
- }) {
1081
- return /*#__PURE__*/_jsxs(Card, {
1082
- testID: `buoy-block-file-${block.id}`,
1083
- children: [/*#__PURE__*/_jsxs(View, {
1084
- style: b.row,
1085
- children: [/*#__PURE__*/_jsx(View, {
1086
- style: styles.fileIcon,
1087
- children: /*#__PURE__*/_jsx(Text, {
1088
- style: styles.fileExt,
1089
- children: (block.type ?? block.name.split(".").pop() ?? "file").toUpperCase().slice(0, 4)
1090
- })
1091
- }), /*#__PURE__*/_jsxs(View, {
1092
- style: styles.flex,
1093
- children: [/*#__PURE__*/_jsx(Text, {
1094
- style: b.rowTitle,
1095
- numberOfLines: 1,
1096
- children: block.name
1097
- }), block.size ? /*#__PURE__*/_jsx(Text, {
1098
- style: b.rowSub,
1099
- children: block.size
1100
- }) : null]
1101
- })]
1102
- }), /*#__PURE__*/_jsx(ActionRow, {
1103
- actions: block.actions,
1104
- blockId: block.id
1105
- })]
1106
- });
1107
- }
1108
- export function Upload({
1109
- block
1110
- }) {
1111
- const h = useBlockHandlers();
1112
- const answer = h.answered[block.id];
1113
- return /*#__PURE__*/_jsxs(Card, {
1114
- testID: `buoy-block-upload-${block.id}`,
1115
- tone: answer ? undefined : "info",
1116
- children: [/*#__PURE__*/_jsx(Text, {
1117
- style: styles.question,
1118
- children: block.label
1119
- }), answer ? /*#__PURE__*/_jsx(Text, {
1120
- style: styles.decided,
1121
- children: answer.kind === "upload" ? `Attached ${answer.name}` : "(skipped)"
1122
- }) : /*#__PURE__*/_jsx(View, {
1123
- style: [styles.rowEnd, {
1124
- justifyContent: "flex-start"
1125
- }],
1126
- children: /*#__PURE__*/_jsx(Pressable, {
1127
- onPress: () => h.answer({
1128
- blockId: block.id,
1129
- kind: "upload",
1130
- name: "screenshot.png"
1131
- }),
1132
- style: [styles.button, styles.buttonPlate],
1133
- children: /*#__PURE__*/_jsx(Text, {
1134
- style: styles.buttonTextPlate,
1135
- children: block.accept === "image" ? "Choose a screenshot" : "Choose a file"
1136
- })
1137
- })
1138
- })]
1139
- });
1140
- }
1141
- const styles = StyleSheet.create({
1142
- flex: {
1143
- flex: 1
1144
- },
1145
- pad: {
1146
- paddingHorizontal: 12,
1147
- paddingBottom: 8
1148
- },
1149
- muted: {
1150
- color: night.color.textSecondary
1151
- },
1152
- dim: {
1153
- opacity: 0.45
1154
- },
1155
- disabled: {
1156
- opacity: 0.5
1157
- },
1158
- pressed: {
1159
- opacity: 0.7
1160
- },
1161
- question: {
1162
- color: night.color.text,
1163
- fontSize: night.font.row,
1164
- fontWeight: "600",
1165
- lineHeight: 20,
1166
- paddingHorizontal: 12,
1167
- paddingTop: 12,
1168
- paddingBottom: 8
1169
- },
1170
- hint: {
1171
- color: night.color.textTertiary,
1172
- fontSize: night.font.micro,
1173
- paddingHorizontal: 12,
1174
- paddingBottom: 10
1175
- },
1176
- decided: {
1177
- color: night.color.textSecondary,
1178
- fontSize: night.font.caption,
1179
- fontWeight: "600",
1180
- paddingHorizontal: 12,
1181
- paddingVertical: 10
1182
- },
1183
- rowEnd: {
1184
- flexDirection: "row",
1185
- justifyContent: "flex-end",
1186
- paddingHorizontal: 12,
1187
- paddingBottom: 12,
1188
- gap: 8
1189
- },
1190
- actionsRow: {
1191
- flexDirection: "row",
1192
- gap: 8,
1193
- paddingHorizontal: 12,
1194
- paddingVertical: 12,
1195
- alignItems: "center"
1196
- },
1197
- button: {
1198
- paddingHorizontal: 14,
1199
- paddingVertical: 9,
1200
- borderRadius: night.radius.row
1201
- },
1202
- buttonPrimary: {
1203
- backgroundColor: night.color.accent
1204
- },
1205
- buttonPlate: {
1206
- backgroundColor: night.color.button
1207
- },
1208
- buttonTextPrimary: {
1209
- color: night.color.onAccent,
1210
- fontSize: night.font.caption,
1211
- fontWeight: "600"
1212
- },
1213
- buttonTextPlate: {
1214
- color: night.color.text,
1215
- fontSize: night.font.caption,
1216
- fontWeight: "600"
1217
- },
1218
- chips: {
1219
- flexDirection: "row",
1220
- flexWrap: "wrap",
1221
- gap: 6
1222
- },
1223
- chip: {
1224
- paddingHorizontal: 12,
1225
- paddingVertical: 7,
1226
- borderRadius: night.radius.chip,
1227
- backgroundColor: night.color.fill,
1228
- borderWidth: StyleSheet.hairlineWidth,
1229
- borderColor: night.color.border
1230
- },
1231
- chipOn: {
1232
- backgroundColor: night.color.accentSoft,
1233
- borderColor: night.color.accentBorderStrong
1234
- },
1235
- chipText: {
1236
- color: night.color.text,
1237
- fontSize: night.font.caption
1238
- },
1239
- chipTextOn: {
1240
- color: night.color.accent,
1241
- fontWeight: "600"
1242
- },
1243
- optionsBox: {
1244
- marginHorizontal: 8,
1245
- marginBottom: 8,
1246
- borderRadius: night.radius.row,
1247
- backgroundColor: night.color.surfaceElevated,
1248
- overflow: "hidden"
1249
- },
1250
- option: {
1251
- flexDirection: "row",
1252
- alignItems: "center",
1253
- gap: 10,
1254
- paddingHorizontal: 12,
1255
- paddingVertical: 10
1256
- },
1257
- optionLabel: {
1258
- color: night.color.text,
1259
- fontSize: night.font.body,
1260
- fontWeight: "500"
1261
- },
1262
- optionDetail: {
1263
- color: night.color.textSecondary,
1264
- fontSize: night.font.caption
1265
- },
1266
- checkbox: {
1267
- width: 20,
1268
- height: 20,
1269
- borderRadius: 6,
1270
- borderWidth: 1.5,
1271
- borderColor: night.color.textTertiary,
1272
- alignItems: "center",
1273
- justifyContent: "center"
1274
- },
1275
- checkboxOn: {
1276
- backgroundColor: night.color.accent,
1277
- borderColor: night.color.accent
1278
- },
1279
- selectBox: {
1280
- marginHorizontal: 12,
1281
- marginBottom: 12,
1282
- borderRadius: night.radius.row,
1283
- backgroundColor: night.color.surfaceElevated,
1284
- overflow: "hidden"
1285
- },
1286
- selectField: {
1287
- flexDirection: "row",
1288
- alignItems: "center",
1289
- justifyContent: "space-between",
1290
- paddingHorizontal: 12,
1291
- paddingVertical: 11
1292
- },
1293
- selectPlaceholder: {
1294
- color: night.color.textSecondary,
1295
- fontSize: night.font.body
1296
- },
1297
- search: {
1298
- flexDirection: "row",
1299
- alignItems: "center",
1300
- gap: 6,
1301
- paddingHorizontal: 12,
1302
- paddingVertical: 6,
1303
- borderTopWidth: StyleSheet.hairlineWidth,
1304
- borderTopColor: night.color.separator
1305
- },
1306
- searchInput: {
1307
- flex: 1,
1308
- color: night.color.text,
1309
- fontSize: night.font.caption,
1310
- paddingVertical: 4
1311
- },
1312
- sliderRow: {
1313
- flexDirection: "row",
1314
- alignItems: "center",
1315
- gap: 8
1316
- },
1317
- stepBtn: {
1318
- width: 28,
1319
- height: 28,
1320
- borderRadius: 14,
1321
- backgroundColor: night.color.fill,
1322
- alignItems: "center",
1323
- justifyContent: "center"
1324
- },
1325
- stepText: {
1326
- color: night.color.text,
1327
- fontSize: 16,
1328
- fontWeight: "600"
1329
- },
1330
- trackHit: {
1331
- flex: 1,
1332
- height: 36,
1333
- justifyContent: "center"
1334
- },
1335
- track: {
1336
- height: 6,
1337
- borderRadius: 3,
1338
- backgroundColor: night.color.fillTertiary,
1339
- justifyContent: "center"
1340
- },
1341
- fill: {
1342
- height: 6,
1343
- borderRadius: 3,
1344
- backgroundColor: night.color.accent
1345
- },
1346
- thumb: {
1347
- position: "absolute",
1348
- width: 20,
1349
- height: 20,
1350
- borderRadius: 10,
1351
- backgroundColor: night.color.knob,
1352
- marginLeft: -10,
1353
- shadowColor: "#000",
1354
- shadowOpacity: 0.35,
1355
- shadowRadius: 3,
1356
- shadowOffset: {
1357
- width: 0,
1358
- height: 1
1359
- }
1360
- },
1361
- sliderValue: {
1362
- width: 64,
1363
- textAlign: "right",
1364
- color: night.color.text,
1365
- fontSize: night.font.caption,
1366
- fontWeight: "600"
1367
- },
1368
- inputRow: {
1369
- flexDirection: "row",
1370
- alignItems: "center",
1371
- gap: 8,
1372
- paddingBottom: 12
1373
- },
1374
- input: {
1375
- flex: 1,
1376
- height: 38,
1377
- paddingHorizontal: 12,
1378
- borderRadius: night.radius.row,
1379
- backgroundColor: night.color.surfaceElevated,
1380
- color: night.color.text,
1381
- fontSize: night.font.body
1382
- },
1383
- fieldRow: {
1384
- flexDirection: "row",
1385
- alignItems: "center",
1386
- justifyContent: "space-between",
1387
- gap: 10,
1388
- paddingVertical: 6
1389
- },
1390
- fieldCol: {
1391
- paddingVertical: 6,
1392
- gap: 6
1393
- },
1394
- fieldLabel: {
1395
- color: night.color.textSecondary,
1396
- fontSize: night.font.caption,
1397
- width: 110
1398
- },
1399
- fieldInput: {
1400
- flex: 1,
1401
- height: 34,
1402
- paddingHorizontal: 10,
1403
- borderRadius: night.radius.segment,
1404
- backgroundColor: night.color.surfaceElevated,
1405
- color: night.color.text,
1406
- fontSize: night.font.caption
1407
- },
1408
- confirmTitle: {
1409
- color: night.color.text,
1410
- fontSize: night.font.row,
1411
- fontWeight: "600",
1412
- paddingHorizontal: 12,
1413
- paddingTop: 12
1414
- },
1415
- confirmChange: {
1416
- color: night.color.text,
1417
- fontSize: night.font.body,
1418
- lineHeight: 19,
1419
- paddingHorizontal: 12,
1420
- paddingTop: 6,
1421
- paddingBottom: 6
1422
- },
1423
- consequence: {
1424
- color: night.color.warning,
1425
- fontSize: night.font.caption,
1426
- paddingHorizontal: 12
1427
- },
1428
- claim: {
1429
- gap: 6,
1430
- paddingHorizontal: 2
1431
- },
1432
- claimText: {
1433
- color: night.color.text,
1434
- fontSize: night.font.row,
1435
- lineHeight: 22
1436
- },
1437
- cite: {
1438
- color: night.color.accent,
1439
- fontSize: night.font.caption,
1440
- fontWeight: "700"
1441
- },
1442
- verified: {
1443
- color: night.color.accent,
1444
- fontSize: night.font.caption,
1445
- fontWeight: "600"
1446
- },
1447
- citeBox: {
1448
- padding: 10,
1449
- borderRadius: night.radius.row,
1450
- backgroundColor: night.color.surface,
1451
- borderWidth: StyleSheet.hairlineWidth,
1452
- borderColor: night.color.border,
1453
- gap: 2
1454
- },
1455
- citeLabel: {
1456
- color: night.color.text,
1457
- fontSize: night.font.caption,
1458
- fontWeight: "600"
1459
- },
1460
- citeDetail: {
1461
- color: night.color.textSecondary,
1462
- fontSize: night.font.caption,
1463
- fontFamily: "Menlo"
1464
- },
1465
- verifyBtn: {
1466
- alignSelf: "flex-start",
1467
- flexDirection: "row",
1468
- alignItems: "center",
1469
- gap: 5,
1470
- paddingHorizontal: 10,
1471
- paddingVertical: 5,
1472
- borderRadius: night.radius.chip,
1473
- backgroundColor: night.color.accentSoft
1474
- },
1475
- verifyText: {
1476
- color: night.color.accent,
1477
- fontSize: night.font.micro,
1478
- fontWeight: "700"
1479
- },
1480
- detailsBody: {
1481
- color: night.color.textSecondary,
1482
- fontSize: night.font.caption,
1483
- lineHeight: 18,
1484
- paddingHorizontal: 12,
1485
- paddingBottom: 12
1486
- },
1487
- tabsWrap: {
1488
- gap: 8
1489
- },
1490
- tabBar: {
1491
- flexDirection: "row",
1492
- gap: 6
1493
- },
1494
- tab: {
1495
- paddingHorizontal: 12,
1496
- paddingVertical: 6,
1497
- borderRadius: night.radius.badge,
1498
- backgroundColor: night.color.fill
1499
- },
1500
- tabOn: {
1501
- backgroundColor: night.color.accentSoft
1502
- },
1503
- tabText: {
1504
- color: night.color.textSecondary,
1505
- fontSize: night.font.caption,
1506
- fontWeight: "600"
1507
- },
1508
- tabTextOn: {
1509
- color: night.color.accent
1510
- },
1511
- tlRow: {
1512
- flexDirection: "row",
1513
- gap: 10,
1514
- paddingHorizontal: 12,
1515
- paddingVertical: 4,
1516
- alignItems: "flex-start"
1517
- },
1518
- tlAt: {
1519
- width: 46,
1520
- color: night.color.textTertiary,
1521
- fontSize: night.font.micro,
1522
- fontFamily: "Menlo",
1523
- paddingTop: 3
1524
- },
1525
- tlLine: {
1526
- width: 12,
1527
- alignItems: "center"
1528
- },
1529
- tlDot: {
1530
- width: 8,
1531
- height: 8,
1532
- borderRadius: 4,
1533
- marginTop: 5
1534
- },
1535
- tlStem: {
1536
- width: 1,
1537
- flex: 1,
1538
- minHeight: 18,
1539
- backgroundColor: night.color.separator,
1540
- marginTop: 2
1541
- },
1542
- tlSource: {
1543
- color: night.color.textTertiary,
1544
- fontSize: 9,
1545
- fontWeight: "700",
1546
- letterSpacing: 0.6
1547
- },
1548
- sparkHead: {
1549
- flexDirection: "row",
1550
- alignItems: "center",
1551
- justifyContent: "space-between",
1552
- paddingHorizontal: 12,
1553
- paddingTop: 8
1554
- },
1555
- sparkCurrent: {
1556
- color: night.color.text,
1557
- fontSize: 22,
1558
- fontWeight: "700"
1559
- },
1560
- sparkUnit: {
1561
- color: night.color.textSecondary,
1562
- fontSize: night.font.caption,
1563
- fontWeight: "500"
1564
- },
1565
- spark: {
1566
- flexDirection: "row",
1567
- alignItems: "flex-end",
1568
- gap: 2,
1569
- paddingHorizontal: 12,
1570
- paddingTop: 6,
1571
- paddingBottom: 6
1572
- },
1573
- sparkBar: {
1574
- flex: 1,
1575
- borderRadius: 1
1576
- },
1577
- live: {
1578
- flexDirection: "row",
1579
- alignItems: "center",
1580
- gap: 5,
1581
- paddingHorizontal: 8,
1582
- paddingVertical: 3,
1583
- borderRadius: night.radius.badge,
1584
- backgroundColor: night.color.dangerSoft
1585
- },
1586
- liveDot: {
1587
- width: 6,
1588
- height: 6,
1589
- borderRadius: 3,
1590
- backgroundColor: night.color.danger
1591
- },
1592
- liveText: {
1593
- color: night.color.danger,
1594
- fontSize: 9,
1595
- fontWeight: "800",
1596
- letterSpacing: 0.8
1597
- },
1598
- cmpHead: {
1599
- flexDirection: "row",
1600
- paddingHorizontal: 12,
1601
- paddingVertical: 6,
1602
- backgroundColor: night.color.fill,
1603
- gap: 8
1604
- },
1605
- cmpCol: {
1606
- flex: 1,
1607
- color: night.color.textTertiary,
1608
- fontSize: night.font.micro,
1609
- fontWeight: "700",
1610
- letterSpacing: 0.6,
1611
- textTransform: "uppercase"
1612
- },
1613
- cmpRow: {
1614
- flexDirection: "row",
1615
- paddingHorizontal: 12,
1616
- paddingVertical: 8,
1617
- gap: 8,
1618
- alignItems: "flex-start"
1619
- },
1620
- cmpDiff: {
1621
- backgroundColor: night.color.fill
1622
- },
1623
- cmpKey: {
1624
- width: 90,
1625
- color: night.color.textSecondary,
1626
- fontSize: night.font.caption
1627
- },
1628
- cmpVal: {
1629
- flex: 1,
1630
- color: night.color.text,
1631
- fontSize: night.font.caption,
1632
- fontFamily: "Menlo"
1633
- },
1634
- cardImage: {
1635
- width: "100%",
1636
- height: 140,
1637
- backgroundColor: night.color.fill
1638
- },
1639
- cardText: {
1640
- paddingHorizontal: 12,
1641
- paddingTop: 10,
1642
- paddingBottom: 4,
1643
- gap: 4
1644
- },
1645
- cardTitle: {
1646
- color: night.color.text,
1647
- fontSize: night.font.row,
1648
- fontWeight: "600"
1649
- },
1650
- fact: {
1651
- flexDirection: "row",
1652
- justifyContent: "space-between",
1653
- gap: 8
1654
- },
1655
- factLabel: {
1656
- color: night.color.textSecondary,
1657
- fontSize: night.font.caption
1658
- },
1659
- factValue: {
1660
- color: night.color.text,
1661
- fontSize: night.font.caption,
1662
- fontWeight: "500"
1663
- },
1664
- carouselTitle: {
1665
- color: night.color.text,
1666
- fontSize: night.font.caption,
1667
- fontWeight: "600",
1668
- paddingBottom: 8
1669
- },
1670
- carousel: {
1671
- gap: 8,
1672
- paddingRight: 8
1673
- },
1674
- carouselCard: {
1675
- width: 224,
1676
- borderRadius: night.radius.card,
1677
- borderWidth: StyleSheet.hairlineWidth,
1678
- borderColor: night.color.border,
1679
- backgroundColor: night.color.surface,
1680
- overflow: "hidden"
1681
- },
1682
- shot: {
1683
- width: "100%",
1684
- height: 220,
1685
- backgroundColor: night.color.fill
1686
- },
1687
- shotBig: {
1688
- height: 520
1689
- },
1690
- progress: {
1691
- height: 4,
1692
- backgroundColor: night.color.fill,
1693
- marginHorizontal: 12,
1694
- marginTop: 6,
1695
- marginBottom: 8,
1696
- borderRadius: 2,
1697
- overflow: "hidden"
1698
- },
1699
- progressFill: {
1700
- height: 4,
1701
- backgroundColor: night.color.accent
1702
- },
1703
- step: {
1704
- flexDirection: "row",
1705
- alignItems: "center",
1706
- gap: 10,
1707
- paddingHorizontal: 12,
1708
- paddingVertical: 9
1709
- },
1710
- stepMark: {
1711
- width: 20,
1712
- height: 20,
1713
- borderRadius: 10,
1714
- backgroundColor: night.color.fillTertiary,
1715
- alignItems: "center",
1716
- justifyContent: "center"
1717
- },
1718
- stepDone: {
1719
- backgroundColor: night.color.accent
1720
- },
1721
- stepFailed: {
1722
- backgroundColor: night.color.danger
1723
- },
1724
- stepRunning: {
1725
- backgroundColor: night.color.info
1726
- },
1727
- stepNum: {
1728
- color: night.color.text,
1729
- fontSize: night.font.micro,
1730
- fontWeight: "700"
1731
- },
1732
- checkpoint: {
1733
- alignSelf: "flex-start",
1734
- flexDirection: "row",
1735
- alignItems: "center",
1736
- gap: 8,
1737
- paddingHorizontal: 12,
1738
- paddingVertical: 7,
1739
- borderRadius: night.radius.chip,
1740
- backgroundColor: night.color.fill
1741
- },
1742
- cpFlag: {
1743
- width: 8,
1744
- height: 8,
1745
- borderRadius: 2,
1746
- backgroundColor: night.color.info
1747
- },
1748
- cpText: {
1749
- color: night.color.textSecondary,
1750
- fontSize: night.font.caption
1751
- },
1752
- cpRestore: {
1753
- color: night.color.accent,
1754
- fontSize: night.font.caption,
1755
- fontWeight: "600"
1756
- },
1757
- taskHead: {
1758
- flexDirection: "row",
1759
- alignItems: "center",
1760
- justifyContent: "space-between",
1761
- gap: 8,
1762
- paddingHorizontal: 12,
1763
- paddingTop: 12
1764
- },
1765
- banner: {
1766
- flexDirection: "row",
1767
- alignItems: "center",
1768
- gap: 8,
1769
- paddingLeft: 12,
1770
- paddingRight: 4,
1771
- paddingVertical: 4,
1772
- borderRadius: night.radius.row,
1773
- borderWidth: StyleSheet.hairlineWidth
1774
- },
1775
- bannerText: {
1776
- flex: 1,
1777
- fontSize: night.font.caption,
1778
- fontWeight: "600"
1779
- },
1780
- fileIcon: {
1781
- width: 40,
1782
- height: 40,
1783
- borderRadius: 8,
1784
- backgroundColor: night.color.fill,
1785
- alignItems: "center",
1786
- justifyContent: "center"
1787
- },
1788
- fileExt: {
1789
- color: night.color.textSecondary,
1790
- fontSize: 10,
1791
- fontWeight: "800"
1792
- }
1793
- });
1794
- //# sourceMappingURL=ExtraBlocks.js.map
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"}});