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