@buoy-gg/ask-buoy 7.0.33

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 (184) hide show
  1. package/LICENSE +58 -0
  2. package/README.md +50 -0
  3. package/lib/commonjs/blocks/AskBlocks.js +338 -0
  4. package/lib/commonjs/blocks/AskBlocks.js.map +1 -0
  5. package/lib/commonjs/blocks/BlockRenderer.js +250 -0
  6. package/lib/commonjs/blocks/BlockRenderer.js.map +1 -0
  7. package/lib/commonjs/blocks/ChromePrototypes.js +514 -0
  8. package/lib/commonjs/blocks/ChromePrototypes.js.map +1 -0
  9. package/lib/commonjs/blocks/DataBlocks.js +545 -0
  10. package/lib/commonjs/blocks/DataBlocks.js.map +1 -0
  11. package/lib/commonjs/blocks/ExtraBlocks.js +1821 -0
  12. package/lib/commonjs/blocks/ExtraBlocks.js.map +1 -0
  13. package/lib/commonjs/blocks/MediaBlocks.js +140 -0
  14. package/lib/commonjs/blocks/MediaBlocks.js.map +1 -0
  15. package/lib/commonjs/blocks/ReceiptBlocks.js +596 -0
  16. package/lib/commonjs/blocks/ReceiptBlocks.js.map +1 -0
  17. package/lib/commonjs/blocks/context.js +42 -0
  18. package/lib/commonjs/blocks/context.js.map +1 -0
  19. package/lib/commonjs/blocks/icons.js +96 -0
  20. package/lib/commonjs/blocks/icons.js.map +1 -0
  21. package/lib/commonjs/blocks/index.js +95 -0
  22. package/lib/commonjs/blocks/index.js.map +1 -0
  23. package/lib/commonjs/blocks/primitives.js +312 -0
  24. package/lib/commonjs/blocks/primitives.js.map +1 -0
  25. package/lib/commonjs/blocks/primitivesIndex.js +56 -0
  26. package/lib/commonjs/blocks/primitivesIndex.js.map +1 -0
  27. package/lib/commonjs/components/ApprovalCard.js +140 -0
  28. package/lib/commonjs/components/ApprovalCard.js.map +1 -0
  29. package/lib/commonjs/components/AskBuoyHeader.js +127 -0
  30. package/lib/commonjs/components/AskBuoyHeader.js.map +1 -0
  31. package/lib/commonjs/components/AskBuoyIcon.js +19 -0
  32. package/lib/commonjs/components/AskBuoyIcon.js.map +1 -0
  33. package/lib/commonjs/components/AskBuoyModal.js +322 -0
  34. package/lib/commonjs/components/AskBuoyModal.js.map +1 -0
  35. package/lib/commonjs/components/ChangesBar.js +211 -0
  36. package/lib/commonjs/components/ChangesBar.js.map +1 -0
  37. package/lib/commonjs/components/Composer.js +175 -0
  38. package/lib/commonjs/components/Composer.js.map +1 -0
  39. package/lib/commonjs/components/EmptyState.js +154 -0
  40. package/lib/commonjs/components/EmptyState.js.map +1 -0
  41. package/lib/commonjs/components/Markdown.js +252 -0
  42. package/lib/commonjs/components/Markdown.js.map +1 -0
  43. package/lib/commonjs/components/MessageList.js +648 -0
  44. package/lib/commonjs/components/MessageList.js.map +1 -0
  45. package/lib/commonjs/components/TypingDots.js +63 -0
  46. package/lib/commonjs/components/TypingDots.js.map +1 -0
  47. package/lib/commonjs/index.js +205 -0
  48. package/lib/commonjs/index.js.map +1 -0
  49. package/lib/commonjs/package.json +1 -0
  50. package/lib/commonjs/preset.js +90 -0
  51. package/lib/commonjs/preset.js.map +1 -0
  52. package/lib/commonjs/store/askBuoyStore.js +279 -0
  53. package/lib/commonjs/store/askBuoyStore.js.map +1 -0
  54. package/lib/commonjs/store/useAskBuoy.js +299 -0
  55. package/lib/commonjs/store/useAskBuoy.js.map +1 -0
  56. package/lib/commonjs/sync/askBuoySyncAdapter.js +119 -0
  57. package/lib/commonjs/sync/askBuoySyncAdapter.js.map +1 -0
  58. package/lib/commonjs/sync/askBuoySyncAdapter.test.js +136 -0
  59. package/lib/commonjs/sync/askBuoySyncAdapter.test.js.map +1 -0
  60. package/lib/commonjs/sync/wire.js +58 -0
  61. package/lib/commonjs/sync/wire.js.map +1 -0
  62. package/lib/commonjs/types.js +6 -0
  63. package/lib/commonjs/types.js.map +1 -0
  64. package/lib/module/blocks/AskBlocks.js +331 -0
  65. package/lib/module/blocks/AskBlocks.js.map +1 -0
  66. package/lib/module/blocks/BlockRenderer.js +245 -0
  67. package/lib/module/blocks/BlockRenderer.js.map +1 -0
  68. package/lib/module/blocks/ChromePrototypes.js +503 -0
  69. package/lib/module/blocks/ChromePrototypes.js.map +1 -0
  70. package/lib/module/blocks/DataBlocks.js +532 -0
  71. package/lib/module/blocks/DataBlocks.js.map +1 -0
  72. package/lib/module/blocks/ExtraBlocks.js +1794 -0
  73. package/lib/module/blocks/ExtraBlocks.js.map +1 -0
  74. package/lib/module/blocks/MediaBlocks.js +135 -0
  75. package/lib/module/blocks/MediaBlocks.js.map +1 -0
  76. package/lib/module/blocks/ReceiptBlocks.js +584 -0
  77. package/lib/module/blocks/ReceiptBlocks.js.map +1 -0
  78. package/lib/module/blocks/context.js +35 -0
  79. package/lib/module/blocks/context.js.map +1 -0
  80. package/lib/module/blocks/icons.js +91 -0
  81. package/lib/module/blocks/icons.js.map +1 -0
  82. package/lib/module/blocks/index.js +8 -0
  83. package/lib/module/blocks/index.js.map +1 -0
  84. package/lib/module/blocks/primitives.js +301 -0
  85. package/lib/module/blocks/primitives.js.map +1 -0
  86. package/lib/module/blocks/primitivesIndex.js +5 -0
  87. package/lib/module/blocks/primitivesIndex.js.map +1 -0
  88. package/lib/module/components/ApprovalCard.js +135 -0
  89. package/lib/module/components/ApprovalCard.js.map +1 -0
  90. package/lib/module/components/AskBuoyHeader.js +124 -0
  91. package/lib/module/components/AskBuoyHeader.js.map +1 -0
  92. package/lib/module/components/AskBuoyIcon.js +8 -0
  93. package/lib/module/components/AskBuoyIcon.js.map +1 -0
  94. package/lib/module/components/AskBuoyModal.js +317 -0
  95. package/lib/module/components/AskBuoyModal.js.map +1 -0
  96. package/lib/module/components/ChangesBar.js +206 -0
  97. package/lib/module/components/ChangesBar.js.map +1 -0
  98. package/lib/module/components/Composer.js +170 -0
  99. package/lib/module/components/Composer.js.map +1 -0
  100. package/lib/module/components/EmptyState.js +149 -0
  101. package/lib/module/components/EmptyState.js.map +1 -0
  102. package/lib/module/components/Markdown.js +246 -0
  103. package/lib/module/components/Markdown.js.map +1 -0
  104. package/lib/module/components/MessageList.js +642 -0
  105. package/lib/module/components/MessageList.js.map +1 -0
  106. package/lib/module/components/TypingDots.js +58 -0
  107. package/lib/module/components/TypingDots.js.map +1 -0
  108. package/lib/module/index.js +29 -0
  109. package/lib/module/index.js.map +1 -0
  110. package/lib/module/preset.js +73 -0
  111. package/lib/module/preset.js.map +1 -0
  112. package/lib/module/store/askBuoyStore.js +275 -0
  113. package/lib/module/store/askBuoyStore.js.map +1 -0
  114. package/lib/module/store/useAskBuoy.js +293 -0
  115. package/lib/module/store/useAskBuoy.js.map +1 -0
  116. package/lib/module/sync/askBuoySyncAdapter.js +114 -0
  117. package/lib/module/sync/askBuoySyncAdapter.js.map +1 -0
  118. package/lib/module/sync/askBuoySyncAdapter.test.js +135 -0
  119. package/lib/module/sync/askBuoySyncAdapter.test.js.map +1 -0
  120. package/lib/module/sync/wire.js +47 -0
  121. package/lib/module/sync/wire.js.map +1 -0
  122. package/lib/module/types.js +4 -0
  123. package/lib/module/types.js.map +1 -0
  124. package/lib/typescript/blocks/AskBlocks.d.ts +11 -0
  125. package/lib/typescript/blocks/AskBlocks.d.ts.map +1 -0
  126. package/lib/typescript/blocks/BlockRenderer.d.ts +5 -0
  127. package/lib/typescript/blocks/BlockRenderer.d.ts.map +1 -0
  128. package/lib/typescript/blocks/ChromePrototypes.d.ts +27 -0
  129. package/lib/typescript/blocks/ChromePrototypes.d.ts.map +1 -0
  130. package/lib/typescript/blocks/DataBlocks.d.ts +29 -0
  131. package/lib/typescript/blocks/DataBlocks.d.ts.map +1 -0
  132. package/lib/typescript/blocks/ExtraBlocks.d.ts +69 -0
  133. package/lib/typescript/blocks/ExtraBlocks.d.ts.map +1 -0
  134. package/lib/typescript/blocks/MediaBlocks.d.ts +5 -0
  135. package/lib/typescript/blocks/MediaBlocks.d.ts.map +1 -0
  136. package/lib/typescript/blocks/ReceiptBlocks.d.ts +27 -0
  137. package/lib/typescript/blocks/ReceiptBlocks.d.ts.map +1 -0
  138. package/lib/typescript/blocks/context.d.ts +35 -0
  139. package/lib/typescript/blocks/context.d.ts.map +1 -0
  140. package/lib/typescript/blocks/icons.d.ts +6 -0
  141. package/lib/typescript/blocks/icons.d.ts.map +1 -0
  142. package/lib/typescript/blocks/index.d.ts +6 -0
  143. package/lib/typescript/blocks/index.d.ts.map +1 -0
  144. package/lib/typescript/blocks/primitives.d.ts +85 -0
  145. package/lib/typescript/blocks/primitives.d.ts.map +1 -0
  146. package/lib/typescript/blocks/primitivesIndex.d.ts +3 -0
  147. package/lib/typescript/blocks/primitivesIndex.d.ts.map +1 -0
  148. package/lib/typescript/components/ApprovalCard.d.ts +7 -0
  149. package/lib/typescript/components/ApprovalCard.d.ts.map +1 -0
  150. package/lib/typescript/components/AskBuoyHeader.d.ts +14 -0
  151. package/lib/typescript/components/AskBuoyHeader.d.ts.map +1 -0
  152. package/lib/typescript/components/AskBuoyIcon.d.ts +6 -0
  153. package/lib/typescript/components/AskBuoyIcon.d.ts.map +1 -0
  154. package/lib/typescript/components/AskBuoyModal.d.ts +13 -0
  155. package/lib/typescript/components/AskBuoyModal.d.ts.map +1 -0
  156. package/lib/typescript/components/ChangesBar.d.ts +9 -0
  157. package/lib/typescript/components/ChangesBar.d.ts.map +1 -0
  158. package/lib/typescript/components/Composer.d.ts +9 -0
  159. package/lib/typescript/components/Composer.d.ts.map +1 -0
  160. package/lib/typescript/components/EmptyState.d.ts +6 -0
  161. package/lib/typescript/components/EmptyState.d.ts.map +1 -0
  162. package/lib/typescript/components/Markdown.d.ts +23 -0
  163. package/lib/typescript/components/Markdown.d.ts.map +1 -0
  164. package/lib/typescript/components/MessageList.d.ts +18 -0
  165. package/lib/typescript/components/MessageList.d.ts.map +1 -0
  166. package/lib/typescript/components/TypingDots.d.ts +2 -0
  167. package/lib/typescript/components/TypingDots.d.ts.map +1 -0
  168. package/lib/typescript/index.d.ts +28 -0
  169. package/lib/typescript/index.d.ts.map +1 -0
  170. package/lib/typescript/preset.d.ts +61 -0
  171. package/lib/typescript/preset.d.ts.map +1 -0
  172. package/lib/typescript/store/askBuoyStore.d.ts +124 -0
  173. package/lib/typescript/store/askBuoyStore.d.ts.map +1 -0
  174. package/lib/typescript/store/useAskBuoy.d.ts +22 -0
  175. package/lib/typescript/store/useAskBuoy.d.ts.map +1 -0
  176. package/lib/typescript/sync/askBuoySyncAdapter.d.ts +73 -0
  177. package/lib/typescript/sync/askBuoySyncAdapter.d.ts.map +1 -0
  178. package/lib/typescript/sync/askBuoySyncAdapter.test.d.ts +2 -0
  179. package/lib/typescript/sync/askBuoySyncAdapter.test.d.ts.map +1 -0
  180. package/lib/typescript/sync/wire.d.ts +17 -0
  181. package/lib/typescript/sync/wire.d.ts.map +1 -0
  182. package/lib/typescript/types.d.ts +119 -0
  183. package/lib/typescript/types.d.ts.map +1 -0
  184. package/package.json +83 -0
@@ -0,0 +1,1794 @@
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