bleam 0.0.12 → 0.0.14

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 (57) hide show
  1. package/dist/ai.cjs +5 -4
  2. package/dist/ai.js +4 -3
  3. package/dist/app-storage-D8W4n8ey.cjs +39 -0
  4. package/dist/app-storage-Isi5Bo0R.js +34 -0
  5. package/dist/cli.cjs +149 -23
  6. package/dist/cli.d.cts +13 -0
  7. package/dist/cli.d.ts +13 -0
  8. package/dist/cli.js +149 -23
  9. package/dist/elements-DX_YUveu.d.ts +341 -0
  10. package/dist/elements-gEI8YGl1.d.cts +341 -0
  11. package/dist/elements.cjs +1031 -0
  12. package/dist/elements.d.cts +2 -0
  13. package/dist/elements.d.ts +2 -0
  14. package/dist/elements.js +999 -0
  15. package/dist/{files-BXVkPrPN.js → files-DErLhzCB.js} +5 -11
  16. package/dist/{files-DxaQ-Nv0.cjs → files-lMk-CpL_.cjs} +5 -11
  17. package/dist/files.cjs +1 -1
  18. package/dist/files.js +1 -1
  19. package/dist/schema.cjs +1 -1
  20. package/dist/schema.d.cts +1 -1
  21. package/dist/schema.d.ts +1 -1
  22. package/dist/schema.js +1 -1
  23. package/dist/secrets.cjs +146 -0
  24. package/dist/secrets.d.cts +14 -0
  25. package/dist/secrets.d.ts +14 -0
  26. package/dist/secrets.js +142 -0
  27. package/dist/{state-LssDgpff.cjs → state-Bm9GiRnU.cjs} +61 -47
  28. package/dist/{state-Dh3HLixb.js → state-D8Firo9w.js} +60 -41
  29. package/dist/state.cjs +3 -2
  30. package/dist/state.d.cts +1 -1
  31. package/dist/state.d.ts +1 -1
  32. package/dist/state.js +3 -2
  33. package/dist/window.d.cts +1 -1
  34. package/dist/window.d.ts +1 -1
  35. package/package.json +14 -11
  36. package/templates/basic/app/index.tsx +7 -129
  37. package/templates/foundation-models/app/index.tsx +100 -41
  38. package/templates/image-generation/app/index.tsx +2 -2
  39. package/templates/native/ios/Podfile.lock +6 -0
  40. package/templates/native/modules/bleam-runtime/ios/AIModule.swift +7 -8
  41. package/templates/native/package.json +6 -1
  42. package/templates/native/yarn.lock +5392 -3749
  43. package/templates/state/app/index.tsx +2 -2
  44. package/templates/text-generation/app/index.tsx +4 -4
  45. package/templates/updates/README.md +1 -1
  46. package/dist/native-sqlite-xcGdamRD.js +0 -64
  47. package/dist/native-sqlite-yQLD5s9i.cjs +0 -66
  48. package/dist/ui-1WepaMS4.d.cts +0 -92
  49. package/dist/ui-D7bRLYee.d.ts +0 -92
  50. package/dist/ui.cjs +0 -364
  51. package/dist/ui.d.cts +0 -2
  52. package/dist/ui.d.ts +0 -2
  53. package/dist/ui.js +0 -357
  54. /package/dist/{schema-B5BfdswF.js → schema-B7ELMpuI.js} +0 -0
  55. /package/dist/{schema-BnVZOXfu.cjs → schema-B7SLUBLN.cjs} +0 -0
  56. /package/dist/{schema-D5eImHxu.d.cts → schema-BWsDPc6c.d.cts} +0 -0
  57. /package/dist/{schema-SSjokbtw.d.ts → schema-DsXZBnvc.d.ts} +0 -0
@@ -0,0 +1,1031 @@
1
+ const require_chunk = require('./chunk-CUT6urMc.cjs');
2
+ const require_native_runtime = require('./native-runtime-CsXnXkQn.cjs');
3
+ let react = require("react");
4
+ react = require_chunk.__toESM(react);
5
+ let react_native = require("react-native");
6
+ react_native = require_chunk.__toESM(react_native);
7
+ let react_jsx_runtime = require("react/jsx-runtime");
8
+ react_jsx_runtime = require_chunk.__toESM(react_jsx_runtime);
9
+
10
+ //#region src/elements/ai-status.ts
11
+ function messageStatusDisplay(status) {
12
+ switch (status) {
13
+ case "queued": return {
14
+ symbol: "clock",
15
+ label: "Queued",
16
+ color: "systemGray"
17
+ };
18
+ case "generating": return {
19
+ symbol: "ellipsis",
20
+ label: "Generating",
21
+ color: "systemBlue"
22
+ };
23
+ case "canceling": return {
24
+ symbol: "xmark.circle",
25
+ label: "Canceling",
26
+ color: "systemOrange"
27
+ };
28
+ case "failed": return {
29
+ symbol: "exclamationmark.triangle",
30
+ label: "Failed",
31
+ color: "systemRed"
32
+ };
33
+ case "canceled": return {
34
+ symbol: "xmark.circle",
35
+ label: "Canceled",
36
+ color: "systemOrange"
37
+ };
38
+ default: return {
39
+ symbol: "checkmark",
40
+ label: "Completed",
41
+ color: "systemGray"
42
+ };
43
+ }
44
+ }
45
+ function promptStatusGenerating(status) {
46
+ return status === "queued" || status === "generating" || status === "canceling";
47
+ }
48
+ function promptStatusSymbol(status, generating) {
49
+ if (generating) return "stop.fill";
50
+ if (status === "failed" || status === "canceled") return "exclamationmark.arrow.triangle.2.circlepath";
51
+ return "arrow.up";
52
+ }
53
+ function promptStatusLabel(status, generating) {
54
+ if (generating) return "Stop generating";
55
+ if (status === "failed") return "Send after failure";
56
+ if (status === "canceled") return "Send after cancellation";
57
+ return "Send message";
58
+ }
59
+
60
+ //#endregion
61
+ //#region src/elements/shared.ts
62
+ function textFromChildren(children) {
63
+ if (typeof children === "string" || typeof children === "number") return String(children);
64
+ if (Array.isArray(children)) return children.filter((child) => typeof child === "string" || typeof child === "number").join("");
65
+ }
66
+ function styleFromProps(style) {
67
+ return react_native.StyleSheet.flatten(style);
68
+ }
69
+ function colorFromHex(hex) {
70
+ const value = hex.trim().replace(/^#/, "");
71
+ const normalized = value.length === 3 ? value.split("").map((part) => `${part}${part}`).join("") : value;
72
+ if (!/^[\da-f]{6}$/i.test(normalized)) return;
73
+ const number = Number.parseInt(normalized, 16);
74
+ const red = (number >> 16 & 255) / 255;
75
+ const green = (number >> 8 & 255) / 255;
76
+ const blue = (number & 255) / 255;
77
+ return UIColor.colorWithRedGreenBlueAlpha(red, green, blue, 1);
78
+ }
79
+ function colorFromStyle(value) {
80
+ if (value == null) return;
81
+ if (typeof value === "string") {
82
+ const hexColor = colorFromHex(value);
83
+ if (hexColor) return hexColor;
84
+ }
85
+ const color = (0, react_native.processColor)(value);
86
+ if (typeof color !== "number") return;
87
+ const alpha = (color >>> 24 & 255) / 255;
88
+ const red = (color >>> 16 & 255) / 255;
89
+ const green = (color >>> 8 & 255) / 255;
90
+ const blue = (color & 255) / 255;
91
+ return UIColor.colorWithRedGreenBlueAlpha(red, green, blue, alpha);
92
+ }
93
+ function fontFromStyle(style) {
94
+ if (typeof style?.fontSize !== "number") return;
95
+ if (style.fontWeight === "700" || style.fontWeight === "bold") return UIFont.boldSystemFontOfSize(style.fontSize);
96
+ return UIFont.systemFontOfSize(style.fontSize);
97
+ }
98
+
99
+ //#endregion
100
+ //#region src/elements/blur-view.tsx
101
+ function blurStyle(intensity, colorScheme) {
102
+ const scheme = colorScheme ?? "auto";
103
+ const level = intensity ?? "regular";
104
+ if (scheme === "light") switch (level) {
105
+ case "ultraThin": return UIBlurEffectStyle.SystemUltraThinMaterialLight;
106
+ case "thin": return UIBlurEffectStyle.SystemThinMaterialLight;
107
+ case "thick": return UIBlurEffectStyle.SystemThickMaterialLight;
108
+ case "chrome": return UIBlurEffectStyle.SystemChromeMaterialLight;
109
+ default: return UIBlurEffectStyle.SystemMaterialLight;
110
+ }
111
+ if (scheme === "dark") switch (level) {
112
+ case "ultraThin": return UIBlurEffectStyle.SystemUltraThinMaterialDark;
113
+ case "thin": return UIBlurEffectStyle.SystemThinMaterialDark;
114
+ case "thick": return UIBlurEffectStyle.SystemThickMaterialDark;
115
+ case "chrome": return UIBlurEffectStyle.SystemChromeMaterialDark;
116
+ default: return UIBlurEffectStyle.SystemMaterialDark;
117
+ }
118
+ switch (level) {
119
+ case "ultraThin": return UIBlurEffectStyle.SystemUltraThinMaterial;
120
+ case "thin": return UIBlurEffectStyle.SystemThinMaterial;
121
+ case "thick": return UIBlurEffectStyle.SystemThickMaterial;
122
+ case "chrome": return UIBlurEffectStyle.SystemChromeMaterial;
123
+ default: return UIBlurEffectStyle.SystemMaterial;
124
+ }
125
+ }
126
+ function createEffectHost(effect) {
127
+ const rootView = UIVisualEffectView.alloc().initWithEffect(effect);
128
+ rootView.backgroundColor = UIColor.clearColor;
129
+ rootView.contentView.backgroundColor = UIColor.clearColor;
130
+ rootView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
131
+ rootView.contentView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
132
+ return {
133
+ rootView,
134
+ childrenView: rootView.contentView
135
+ };
136
+ }
137
+ function applyContainerStyle(view, style) {
138
+ const borderRadius = style?.borderRadius;
139
+ if (typeof borderRadius === "number") view.layer.cornerRadius = borderRadius;
140
+ view.clipsToBounds = style?.overflow === "hidden" || typeof borderRadius === "number";
141
+ }
142
+ function updateBlurEffect(view, props) {
143
+ view.effect = UIBlurEffect.effectWithStyle(blurStyle(props.intensity, props.colorScheme));
144
+ }
145
+ const BlurView = require_native_runtime.ensureNativeScript().defineUIKitContainer({
146
+ name: "BlurView",
147
+ layout: {
148
+ sizing: "fill",
149
+ defaultSize: {
150
+ width: 0,
151
+ height: 0
152
+ }
153
+ },
154
+ create() {
155
+ return createEffectHost(UIBlurEffect.effectWithStyle(UIBlurEffectStyle.SystemMaterial));
156
+ },
157
+ update(view, props, _previousProps, ctx) {
158
+ updateBlurEffect(view.rootView, props);
159
+ applyContainerStyle(view.rootView, styleFromProps(props.style));
160
+ ctx?.invalidateLayout();
161
+ }
162
+ });
163
+
164
+ //#endregion
165
+ //#region src/elements/button-state.ts
166
+ function buttonDisabled(disabled, loading) {
167
+ return disabled || loading;
168
+ }
169
+ function buttonOpacity(options) {
170
+ if (buttonDisabled(options.disabled, options.loading)) return .45;
171
+ if (!options.pressed) return 1;
172
+ return Math.min(1, Math.max(0, options.activeOpacity));
173
+ }
174
+ function buttonAccessibilityState(state, disabled, loading) {
175
+ return {
176
+ ...state,
177
+ disabled: buttonDisabled(disabled, loading),
178
+ busy: loading
179
+ };
180
+ }
181
+
182
+ //#endregion
183
+ //#region src/elements/glass-shared.ts
184
+ function glassStyleValue(style) {
185
+ return typeof style === "object" ? style.style : style ?? "regular";
186
+ }
187
+ function glassEffect(style) {
188
+ if (style === "none") return null;
189
+ return UIGlassEffect.effectWithStyle(style === "clear" ? UIGlassEffectStyle.Clear : UIGlassEffectStyle.Regular);
190
+ }
191
+ function createGlassHost(effect) {
192
+ const rootView = UIVisualEffectView.alloc().initWithEffect(effect);
193
+ const childrenView = UIView.new();
194
+ rootView.backgroundColor = UIColor.clearColor;
195
+ rootView.contentView.backgroundColor = UIColor.clearColor;
196
+ childrenView.backgroundColor = UIColor.clearColor;
197
+ rootView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
198
+ rootView.contentView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
199
+ childrenView.translatesAutoresizingMaskIntoConstraints = false;
200
+ rootView.contentView.addSubview(childrenView);
201
+ const constraints = {
202
+ top: childrenView.topAnchor.constraintEqualToAnchorConstant(rootView.contentView.topAnchor, 0),
203
+ right: rootView.contentView.rightAnchor.constraintEqualToAnchorConstant(childrenView.rightAnchor, 0),
204
+ bottom: rootView.contentView.bottomAnchor.constraintEqualToAnchorConstant(childrenView.bottomAnchor, 0),
205
+ left: childrenView.leftAnchor.constraintEqualToAnchorConstant(rootView.contentView.leftAnchor, 0)
206
+ };
207
+ NSLayoutConstraint.activateConstraints([
208
+ constraints.top,
209
+ constraints.right,
210
+ constraints.bottom,
211
+ constraints.left
212
+ ]);
213
+ return {
214
+ rootView,
215
+ childrenView
216
+ };
217
+ }
218
+ function applyGlassShape(view, style) {
219
+ const radius = typeof style?.cornerRadius === "number" ? style.cornerRadius : 0;
220
+ view.layer.cornerRadius = radius;
221
+ view.contentView.layer.cornerRadius = radius;
222
+ view.layer.cornerCurve = kCACornerCurveContinuous;
223
+ view.contentView.layer.cornerCurve = kCACornerCurveContinuous;
224
+ view.clipsToBounds = radius > 0;
225
+ view.contentView.clipsToBounds = radius > 0;
226
+ view.layer.masksToBounds = radius > 0;
227
+ view.contentView.layer.masksToBounds = radius > 0;
228
+ view.layer.borderWidth = typeof style?.borderWidth === "number" ? style.borderWidth : 0;
229
+ const borderColor = colorFromStyle(style?.borderColor);
230
+ view.layer.borderColor = borderColor?.CGColor ?? null;
231
+ }
232
+ function updateGlassEffect(view, props) {
233
+ const style = glassStyleValue(props.glassEffectStyle);
234
+ const effect = glassEffect(style);
235
+ if (style !== "none") {
236
+ const tintColor = props.tintColor ? colorFromHex(props.tintColor) : void 0;
237
+ const glass = effect;
238
+ glass.interactive = props.isInteractive ?? false;
239
+ if (tintColor) glass.tintColor = tintColor;
240
+ }
241
+ if (typeof props.glassEffectStyle === "object" && props.glassEffectStyle.animate) UIView.animateWithDurationAnimations(props.glassEffectStyle.animationDuration ?? .35, () => {
242
+ view.effect = effect;
243
+ });
244
+ else view.effect = effect;
245
+ }
246
+ function updateGlassContainerEffect(view, spacing) {
247
+ const effect = UIGlassContainerEffect.new();
248
+ effect.spacing = spacing ?? 0;
249
+ view.effect = effect;
250
+ }
251
+
252
+ //#endregion
253
+ //#region src/elements/glass-view.tsx
254
+ const GlassView = require_native_runtime.ensureNativeScript().defineUIKitContainer({
255
+ name: "GlassView",
256
+ layout: {
257
+ sizing: "fill",
258
+ defaultSize: {
259
+ width: 0,
260
+ height: 0
261
+ }
262
+ },
263
+ create() {
264
+ return createGlassHost(glassEffect("regular"));
265
+ },
266
+ update(view, props, _previousProps, ctx) {
267
+ updateGlassEffect(view.rootView, props);
268
+ applyGlassShape(view.rootView, props.glassStyle);
269
+ ctx?.invalidateLayout();
270
+ }
271
+ });
272
+
273
+ //#endregion
274
+ //#region src/elements/button.tsx
275
+ const sizeStyles = {
276
+ small: {
277
+ minHeight: 28,
278
+ minWidth: 28,
279
+ paddingHorizontal: 10
280
+ },
281
+ regular: {
282
+ minHeight: 36,
283
+ minWidth: 36,
284
+ paddingHorizontal: 14
285
+ },
286
+ large: {
287
+ minHeight: 44,
288
+ minWidth: 44,
289
+ paddingHorizontal: 18
290
+ }
291
+ };
292
+ const labelSizeStyles = {
293
+ small: { fontSize: 13 },
294
+ regular: { fontSize: 15 },
295
+ large: { fontSize: 17 }
296
+ };
297
+ const glassCornerRadius = {
298
+ small: 8,
299
+ regular: 10,
300
+ large: 12
301
+ };
302
+ function resolveStyle$2(style, state) {
303
+ return typeof style === "function" ? style(state) : style;
304
+ }
305
+ function ButtonContent({ icon, label, labelStyle, loading, size, variant }) {
306
+ const indicatorColor = variant === "primary" ? "#ffffff" : (0, react_native.PlatformColor)("systemBlue");
307
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.ActivityIndicator, {
308
+ accessibilityElementsHidden: true,
309
+ color: indicatorColor,
310
+ size: "small"
311
+ }) : icon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
312
+ accessibilityElementsHidden: true,
313
+ children: icon
314
+ }) : null, label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
315
+ numberOfLines: 1,
316
+ style: [
317
+ styles$3.label,
318
+ labelSizeStyles[size],
319
+ variant ? labelVariantStyles[variant] : styles$3.glassLabel,
320
+ labelStyle
321
+ ],
322
+ children: label
323
+ }) : null] });
324
+ }
325
+ function Button({ accessibilityRole = "button", accessibilityState, activeOpacity = .2, disabled = false, icon, label, labelStyle, loading = false, size = "regular", style, variant = "primary",...props }) {
326
+ const inactive = buttonDisabled(disabled, loading);
327
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
328
+ ...props,
329
+ accessibilityRole,
330
+ accessibilityState: buttonAccessibilityState(accessibilityState, disabled, loading),
331
+ disabled: inactive,
332
+ style: (state) => [
333
+ styles$3.button,
334
+ sizeStyles[size],
335
+ buttonVariantStyles[variant],
336
+ resolveStyle$2(style, state),
337
+ { opacity: buttonOpacity({
338
+ ...state,
339
+ disabled,
340
+ loading,
341
+ activeOpacity
342
+ }) }
343
+ ],
344
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
345
+ pointerEvents: "none",
346
+ style: styles$3.content,
347
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ButtonContent, {
348
+ icon,
349
+ label,
350
+ labelStyle,
351
+ loading,
352
+ size,
353
+ variant
354
+ })
355
+ })
356
+ });
357
+ }
358
+ function GlassButton({ accessibilityRole = "button", accessibilityState, activeOpacity = .2, disabled = false, glassEffectStyle, glassStyle, icon, label, labelStyle, loading = false, size = "regular", style, tintColor,...props }) {
359
+ const inactive = buttonDisabled(disabled, loading);
360
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.Pressable, {
361
+ ...props,
362
+ accessibilityRole,
363
+ accessibilityState: buttonAccessibilityState(accessibilityState, disabled, loading),
364
+ disabled: inactive,
365
+ style: (state) => [
366
+ styles$3.button,
367
+ sizeStyles[size],
368
+ styles$3.glassButton,
369
+ resolveStyle$2(style, state),
370
+ { opacity: buttonOpacity({
371
+ ...state,
372
+ disabled,
373
+ loading,
374
+ activeOpacity
375
+ }) }
376
+ ],
377
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
378
+ pointerEvents: "none",
379
+ style: styles$3.glassBackground,
380
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GlassView, {
381
+ glassEffectStyle,
382
+ glassStyle: {
383
+ cornerRadius: glassCornerRadius[size],
384
+ ...glassStyle
385
+ },
386
+ isInteractive: false,
387
+ style: styles$3.glass,
388
+ tintColor
389
+ })
390
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
391
+ pointerEvents: "none",
392
+ style: styles$3.content,
393
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ButtonContent, {
394
+ icon,
395
+ label,
396
+ labelStyle,
397
+ loading,
398
+ size
399
+ })
400
+ })]
401
+ });
402
+ }
403
+ const styles$3 = react_native.StyleSheet.create({
404
+ button: {
405
+ alignItems: "center",
406
+ borderRadius: 10,
407
+ justifyContent: "center"
408
+ },
409
+ glassButton: { backgroundColor: "transparent" },
410
+ glass: { flex: 1 },
411
+ glassBackground: {
412
+ bottom: 0,
413
+ left: 0,
414
+ position: "absolute",
415
+ right: 0,
416
+ top: 0
417
+ },
418
+ content: {
419
+ alignItems: "center",
420
+ flexDirection: "row",
421
+ gap: 7,
422
+ justifyContent: "center"
423
+ },
424
+ label: { fontWeight: "600" },
425
+ glassLabel: { color: (0, react_native.PlatformColor)("label") }
426
+ });
427
+ const buttonVariantStyles = react_native.StyleSheet.create({
428
+ primary: { backgroundColor: (0, react_native.PlatformColor)("systemBlue") },
429
+ secondary: { backgroundColor: (0, react_native.PlatformColor)("secondarySystemFill") },
430
+ plain: { backgroundColor: "transparent" }
431
+ });
432
+ const labelVariantStyles = react_native.StyleSheet.create({
433
+ primary: { color: "#ffffff" },
434
+ secondary: { color: (0, react_native.PlatformColor)("label") },
435
+ plain: { color: (0, react_native.PlatformColor)("systemBlue") }
436
+ });
437
+
438
+ //#endregion
439
+ //#region src/elements/symbol.tsx
440
+ function symbolWeight(weight) {
441
+ switch (weight) {
442
+ case "ultraLight": return UIImageSymbolWeight.UltraLight;
443
+ case "thin": return UIImageSymbolWeight.Thin;
444
+ case "light": return UIImageSymbolWeight.Light;
445
+ case "medium": return UIImageSymbolWeight.Medium;
446
+ case "semibold": return UIImageSymbolWeight.Semibold;
447
+ case "bold": return UIImageSymbolWeight.Bold;
448
+ case "heavy": return UIImageSymbolWeight.Heavy;
449
+ case "black": return UIImageSymbolWeight.Black;
450
+ default: return UIImageSymbolWeight.Regular;
451
+ }
452
+ }
453
+ function symbolScale(scale) {
454
+ if (scale === "small") return UIImageSymbolScale.Small;
455
+ if (scale === "large") return UIImageSymbolScale.Large;
456
+ return UIImageSymbolScale.Medium;
457
+ }
458
+ function symbolConfiguration(props, style) {
459
+ const size = props.size ?? style?.fontSize ?? 17;
460
+ return UIImageSymbolConfiguration.configurationWithPointSizeWeightScale(size, symbolWeight(props.weight), symbolScale(props.scale));
461
+ }
462
+ function symbolImage(name, configuration) {
463
+ if (configuration) return UIImage.systemImageNamedWithConfiguration(name, configuration);
464
+ return UIImage.systemImageNamed(name);
465
+ }
466
+ const SFSymbol = require_native_runtime.ensureNativeScript().defineUIKitView({
467
+ name: "SFSymbol",
468
+ layout: {
469
+ sizing: "intrinsic",
470
+ defaultSize: {
471
+ width: 17,
472
+ height: 17
473
+ }
474
+ },
475
+ create() {
476
+ const imageView = UIImageView.new();
477
+ imageView.contentMode = UIViewContentMode.ScaleAspectFit;
478
+ return imageView;
479
+ },
480
+ update(imageView, props, _previousProps, ctx) {
481
+ const style = styleFromProps(props.style);
482
+ const configuration = symbolConfiguration(props, style);
483
+ imageView.image = symbolImage(props.symbol, configuration);
484
+ imageView.tintColor = colorFromStyle(props.color) ?? colorFromStyle(style?.tintColor) ?? colorFromStyle(style?.color) ?? UIColor.labelColor;
485
+ ctx?.invalidateLayout();
486
+ }
487
+ });
488
+
489
+ //#endregion
490
+ //#region src/elements/conversation.tsx
491
+ const ConversationContext = (0, react.createContext)(null);
492
+ const scrollEndThreshold = 48;
493
+ function useConversation() {
494
+ const context = (0, react.useContext)(ConversationContext);
495
+ if (!context) throw new Error("Conversation elements must be rendered inside <Conversation>");
496
+ return context;
497
+ }
498
+ function Conversation({ children, defaultFollowOutput = true, followOutput, onFollowOutputChange, style,...props }) {
499
+ const controlled = followOutput !== void 0;
500
+ const generation = (0, react.useRef)(0);
501
+ const [internalFollowing, setInternalFollowing] = (0, react.useState)(defaultFollowOutput);
502
+ const [isAtBottom, setIsAtBottom] = (0, react.useState)(true);
503
+ const [followGeneration, setFollowGeneration] = (0, react.useState)(0);
504
+ const following = controlled ? followOutput : internalFollowing;
505
+ const setFollowing = (0, react.useCallback)((value) => {
506
+ if (!controlled) setInternalFollowing(value);
507
+ onFollowOutputChange?.(value);
508
+ }, [controlled, onFollowOutputChange]);
509
+ const updateAtBottom = (0, react.useCallback)((value) => {
510
+ setIsAtBottom(value);
511
+ if (following !== value) setFollowing(value);
512
+ }, [following, setFollowing]);
513
+ const requestFollow = (0, react.useCallback)(() => {
514
+ generation.current += 1;
515
+ setFollowGeneration(generation.current);
516
+ setFollowing(true);
517
+ }, [setFollowing]);
518
+ const context = (0, react.useMemo)(() => ({
519
+ followGeneration,
520
+ following,
521
+ isAtBottom,
522
+ updateAtBottom,
523
+ requestFollow
524
+ }), [
525
+ followGeneration,
526
+ following,
527
+ isAtBottom,
528
+ updateAtBottom,
529
+ requestFollow
530
+ ]);
531
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConversationContext.Provider, {
532
+ value: context,
533
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
534
+ ...props,
535
+ style: [styles$2.conversation, style],
536
+ children
537
+ })
538
+ });
539
+ }
540
+ function ConversationContent({ contentContainerStyle, data, keyboardShouldPersistTaps = "handled", onContentSizeChange, onScroll, renderItem, scrollEventThrottle = 16,...props }) {
541
+ const context = useConversation();
542
+ const list = (0, react.useRef)(null);
543
+ const following = (0, react.useRef)(context.following);
544
+ const previousHeight = (0, react.useRef)(0);
545
+ const previousFollowGeneration = (0, react.useRef)(context.followGeneration);
546
+ following.current = context.following;
547
+ (0, react.useEffect)(() => {
548
+ if (context.following && context.followGeneration > previousFollowGeneration.current) {
549
+ previousFollowGeneration.current = context.followGeneration;
550
+ list.current?.scrollToEnd({ animated: true });
551
+ }
552
+ }, [context.followGeneration, context.following]);
553
+ const handleScroll = (0, react.useCallback)((event) => {
554
+ const { contentOffset, contentSize, layoutMeasurement } = event.nativeEvent;
555
+ const distance = contentSize.height - (contentOffset.y + layoutMeasurement.height);
556
+ context.updateAtBottom(distance <= scrollEndThreshold);
557
+ onScroll?.(event);
558
+ }, [context, onScroll]);
559
+ const handleContentSizeChange = (0, react.useCallback)((width, height) => {
560
+ const newFollowRequested = context.followGeneration > previousFollowGeneration.current;
561
+ const shouldScroll = following.current && (previousHeight.current === 0 || height > previousHeight.current || newFollowRequested);
562
+ previousHeight.current = height;
563
+ previousFollowGeneration.current = context.followGeneration;
564
+ if (shouldScroll) list.current?.scrollToEnd({ animated: true });
565
+ onContentSizeChange?.(width, height);
566
+ }, [context.followGeneration, onContentSizeChange]);
567
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.FlatList, {
568
+ ...props,
569
+ data,
570
+ keyboardShouldPersistTaps,
571
+ onContentSizeChange: handleContentSizeChange,
572
+ onScroll: handleScroll,
573
+ ref: list,
574
+ renderItem,
575
+ scrollEventThrottle,
576
+ style: [styles$2.content, props.style],
577
+ contentContainerStyle: [styles$2.contentContainer, contentContainerStyle]
578
+ });
579
+ }
580
+ function ConversationEmptyState({ children, description = "Start a conversation to see messages here.", descriptionStyle, icon, style, title = "No messages yet", titleStyle,...props }) {
581
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
582
+ ...props,
583
+ style: [styles$2.emptyState, style],
584
+ children: [
585
+ icon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
586
+ accessibilityElementsHidden: true,
587
+ style: styles$2.emptyIcon,
588
+ children: icon
589
+ }) : null,
590
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
591
+ style: [styles$2.emptyTitle, titleStyle],
592
+ children: title
593
+ }),
594
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
595
+ style: [styles$2.emptyDescription, descriptionStyle],
596
+ children: description
597
+ }),
598
+ children
599
+ ]
600
+ });
601
+ }
602
+ function ConversationScrollButton({ accessibilityLabel = "Scroll to latest message", activeOpacity = .2, children, onPress, style,...props }) {
603
+ const context = useConversation();
604
+ if (context.isAtBottom) return null;
605
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
606
+ ...props,
607
+ accessibilityLabel,
608
+ accessibilityRole: "button",
609
+ onPress: () => {
610
+ context.requestFollow();
611
+ onPress?.();
612
+ },
613
+ style: (state) => [
614
+ styles$2.scrollButton,
615
+ resolveStyle$1(style, state),
616
+ state.pressed && { opacity: activeOpacity }
617
+ ],
618
+ children: children ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SFSymbol, {
619
+ color: (0, react_native.PlatformColor)("systemBlue"),
620
+ size: 16,
621
+ symbol: "arrow.down"
622
+ })
623
+ });
624
+ }
625
+ function resolveStyle$1(style, state) {
626
+ return typeof style === "function" ? style(state) : style;
627
+ }
628
+ const styles$2 = react_native.StyleSheet.create({
629
+ conversation: {
630
+ flex: 1,
631
+ minHeight: 0,
632
+ position: "relative"
633
+ },
634
+ content: { flex: 1 },
635
+ contentContainer: {
636
+ gap: 16,
637
+ padding: 16
638
+ },
639
+ emptyState: {
640
+ alignItems: "center",
641
+ alignSelf: "center",
642
+ gap: 8,
643
+ justifyContent: "center",
644
+ maxWidth: 320,
645
+ padding: 32
646
+ },
647
+ emptyIcon: { marginBottom: 8 },
648
+ emptyTitle: {
649
+ color: (0, react_native.PlatformColor)("label"),
650
+ fontSize: 17,
651
+ fontWeight: "600",
652
+ textAlign: "center"
653
+ },
654
+ emptyDescription: {
655
+ color: (0, react_native.PlatformColor)("secondaryLabel"),
656
+ fontSize: 15,
657
+ textAlign: "center"
658
+ },
659
+ scrollButton: {
660
+ alignItems: "center",
661
+ backgroundColor: (0, react_native.PlatformColor)("secondarySystemBackground"),
662
+ borderColor: (0, react_native.PlatformColor)("separator"),
663
+ borderRadius: 18,
664
+ borderWidth: react_native.StyleSheet.hairlineWidth,
665
+ bottom: 16,
666
+ height: 36,
667
+ justifyContent: "center",
668
+ position: "absolute",
669
+ right: 16,
670
+ width: 36
671
+ }
672
+ });
673
+
674
+ //#endregion
675
+ //#region src/elements/glass-container.tsx
676
+ const GlassContainer = require_native_runtime.ensureNativeScript().defineUIKitContainer({
677
+ name: "GlassContainer",
678
+ layout: {
679
+ sizing: "fill",
680
+ defaultSize: {
681
+ width: 0,
682
+ height: 0
683
+ }
684
+ },
685
+ create() {
686
+ const host = createGlassHost(UIGlassContainerEffect.new());
687
+ updateGlassContainerEffect(host.rootView, void 0);
688
+ return host;
689
+ },
690
+ update(view, props, _previousProps, ctx) {
691
+ updateGlassContainerEffect(view.rootView, props.spacing);
692
+ applyGlassShape(view.rootView, props.glassStyle);
693
+ ctx?.invalidateLayout();
694
+ }
695
+ });
696
+
697
+ //#endregion
698
+ //#region src/elements/label.tsx
699
+ function labelText(props) {
700
+ return props.text ?? textFromChildren(props.children) ?? "";
701
+ }
702
+ function defaultLabelColor(tone) {
703
+ if (tone === "secondary") return UIColor.secondaryLabelColor;
704
+ if (tone === "tertiary") return UIColor.tertiaryLabelColor;
705
+ return UIColor.labelColor;
706
+ }
707
+ const Label = require_native_runtime.ensureNativeScript().defineUIKitView({
708
+ name: "Label",
709
+ layout: {
710
+ sizing: "intrinsic",
711
+ defaultSize: {
712
+ width: 1,
713
+ height: 24
714
+ }
715
+ },
716
+ create() {
717
+ const label = UILabel.new();
718
+ label.adjustsFontForContentSizeCategory = true;
719
+ return label;
720
+ },
721
+ update(label, props, _previousProps, ctx) {
722
+ const style = styleFromProps(props.style);
723
+ label.text = labelText(props);
724
+ label.textColor = colorFromStyle(style?.color) ?? defaultLabelColor(props.tone);
725
+ label.font = fontFromStyle(style) ?? UIFont.preferredFontForTextStyle(UIFontTextStyleBody);
726
+ label.numberOfLines = props.numberOfLines ?? 0;
727
+ if (style?.textAlign === "center") label.textAlignment = NSTextAlignment.Center;
728
+ else if (style?.textAlign === "right") label.textAlignment = NSTextAlignment.Right;
729
+ else label.textAlignment = NSTextAlignment.Left;
730
+ ctx?.invalidateLayout();
731
+ }
732
+ });
733
+
734
+ //#endregion
735
+ //#region src/elements/message.tsx
736
+ function Message({ children, from = "assistant", style,...props }) {
737
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
738
+ ...props,
739
+ style: [
740
+ styles$1.message,
741
+ from === "user" ? styles$1.userMessage : styles$1.assistantMessage,
742
+ style
743
+ ],
744
+ children
745
+ });
746
+ }
747
+ function MessageContent({ children, style,...props }) {
748
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
749
+ ...props,
750
+ style: [styles$1.content, style],
751
+ children
752
+ });
753
+ }
754
+ function MessageText({ style,...props }) {
755
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
756
+ ...props,
757
+ style: [styles$1.text, style]
758
+ });
759
+ }
760
+ function MessageStatus({ label, showSymbol = true, status, style,...props }) {
761
+ const display = messageStatusDisplay(status);
762
+ const color = (0, react_native.PlatformColor)(display.color);
763
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
764
+ style: styles$1.status,
765
+ children: [showSymbol ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SFSymbol, {
766
+ color,
767
+ size: 12,
768
+ symbol: display.symbol
769
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
770
+ ...props,
771
+ style: [
772
+ styles$1.statusText,
773
+ { color },
774
+ style
775
+ ],
776
+ children: label ?? display.label
777
+ })]
778
+ });
779
+ }
780
+ function MessageActions({ children, style,...props }) {
781
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
782
+ ...props,
783
+ style: [styles$1.actions, style],
784
+ children
785
+ });
786
+ }
787
+ const styles$1 = react_native.StyleSheet.create({
788
+ message: {
789
+ gap: 6,
790
+ maxWidth: "85%"
791
+ },
792
+ userMessage: { alignSelf: "flex-end" },
793
+ assistantMessage: { alignSelf: "stretch" },
794
+ content: {
795
+ backgroundColor: (0, react_native.PlatformColor)("secondarySystemFill"),
796
+ borderRadius: 16,
797
+ paddingHorizontal: 14,
798
+ paddingVertical: 10
799
+ },
800
+ text: {
801
+ color: (0, react_native.PlatformColor)("label"),
802
+ fontSize: 15,
803
+ lineHeight: 21
804
+ },
805
+ status: {
806
+ alignItems: "center",
807
+ flexDirection: "row",
808
+ gap: 5
809
+ },
810
+ statusText: {
811
+ fontSize: 12,
812
+ fontWeight: "500"
813
+ },
814
+ actions: {
815
+ flexDirection: "row",
816
+ flexWrap: "wrap",
817
+ gap: 8
818
+ }
819
+ });
820
+
821
+ //#endregion
822
+ //#region src/elements/prompt-input.tsx
823
+ const PromptInputContext = (0, react.createContext)(null);
824
+ function usePromptInput() {
825
+ const context = (0, react.useContext)(PromptInputContext);
826
+ if (!context) throw new Error("Prompt input elements must be rendered inside <PromptInput>");
827
+ return context;
828
+ }
829
+ function PromptInput({ children, defaultValue = "", disabled = false, onChangeText, onSubmit, status, style, value,...props }) {
830
+ const controlled = value !== void 0;
831
+ const [internalText, setInternalText] = (0, react.useState)(defaultValue);
832
+ const text = controlled ? value : internalText;
833
+ const setText = (0, react.useCallback)((nextText) => {
834
+ if (!controlled) setInternalText(nextText);
835
+ onChangeText?.(nextText);
836
+ }, [controlled, onChangeText]);
837
+ const submit = (0, react.useCallback)(() => {
838
+ if (disabled) return;
839
+ onSubmit?.({ text });
840
+ }, [
841
+ disabled,
842
+ onSubmit,
843
+ text
844
+ ]);
845
+ const context = (0, react.useMemo)(() => ({
846
+ disabled,
847
+ generating: promptStatusGenerating(status),
848
+ setText,
849
+ status,
850
+ submit,
851
+ text
852
+ }), [
853
+ disabled,
854
+ setText,
855
+ status,
856
+ submit,
857
+ text
858
+ ]);
859
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PromptInputContext.Provider, {
860
+ value: context,
861
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
862
+ ...props,
863
+ style: [styles.input, style],
864
+ children
865
+ })
866
+ });
867
+ }
868
+ function PromptInputHeader({ children, style,...props }) {
869
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
870
+ ...props,
871
+ style: [styles.header, style],
872
+ children
873
+ });
874
+ }
875
+ function PromptInputBody({ children, style,...props }) {
876
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
877
+ ...props,
878
+ style: [styles.body, style],
879
+ children
880
+ });
881
+ }
882
+ function PromptInputFooter({ children, style,...props }) {
883
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
884
+ ...props,
885
+ style: [styles.footer, style],
886
+ children
887
+ });
888
+ }
889
+ function PromptInputTools({ children, style,...props }) {
890
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
891
+ ...props,
892
+ style: [styles.tools, style],
893
+ children
894
+ });
895
+ }
896
+ function PromptInputTextarea({ multiline = true, onChangeText, onSubmitEditing, placeholder = "Send a message", placeholderTextColor = (0, react_native.PlatformColor)("placeholderText"), returnKeyType = "send", style, submitOnEnter = !multiline, value,...props }) {
897
+ const context = usePromptInput();
898
+ const text = value !== void 0 ? value : context.text;
899
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.TextInput, {
900
+ ...props,
901
+ editable: !context.disabled && props.editable !== false,
902
+ multiline,
903
+ onChangeText: (nextText) => {
904
+ context.setText(nextText);
905
+ onChangeText?.(nextText);
906
+ },
907
+ onSubmitEditing: (event) => {
908
+ onSubmitEditing?.(event);
909
+ if (submitOnEnter) context.submit();
910
+ },
911
+ placeholder,
912
+ placeholderTextColor,
913
+ returnKeyType,
914
+ style: [styles.textarea, style],
915
+ submitBehavior: multiline && !submitOnEnter ? "newline" : "submit",
916
+ value: text
917
+ });
918
+ }
919
+ function PromptInputSubmit({ accessibilityLabel, accessibilityState, activeOpacity = .2, children, disabled: disabledProp, generating, loading = false, onPress, status, style,...props }) {
920
+ const context = usePromptInput();
921
+ const resolvedStatus = status ?? context.status;
922
+ const resolvedGenerating = generating ?? loading ?? promptStatusGenerating(resolvedStatus);
923
+ const disabled = context.disabled || buttonDisabled(disabledProp === true, loading);
924
+ const resolvedChildren = typeof children === "function" ? children({ generating: resolvedGenerating }) : children;
925
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
926
+ ...props,
927
+ accessibilityLabel: accessibilityLabel ?? promptStatusLabel(resolvedStatus, resolvedGenerating),
928
+ accessibilityRole: "button",
929
+ accessibilityState: {
930
+ ...accessibilityState,
931
+ busy: resolvedGenerating,
932
+ disabled
933
+ },
934
+ disabled,
935
+ onPress: () => {
936
+ if (onPress) onPress({ text: context.text });
937
+ else context.submit();
938
+ },
939
+ style: (state) => [
940
+ styles.submit,
941
+ resolveStyle(style, state),
942
+ { opacity: buttonOpacity({
943
+ ...state,
944
+ disabled,
945
+ loading,
946
+ activeOpacity
947
+ }) }
948
+ ],
949
+ children: resolvedChildren ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SFSymbol, {
950
+ color: "#ffffff",
951
+ size: 16,
952
+ symbol: promptStatusSymbol(resolvedStatus, resolvedGenerating),
953
+ weight: "semibold"
954
+ })
955
+ });
956
+ }
957
+ function resolveStyle(style, state) {
958
+ return typeof style === "function" ? style(state) : style;
959
+ }
960
+ const styles = react_native.StyleSheet.create({
961
+ input: {
962
+ backgroundColor: (0, react_native.PlatformColor)("secondarySystemBackground"),
963
+ borderColor: (0, react_native.PlatformColor)("separator"),
964
+ borderRadius: 18,
965
+ borderWidth: react_native.StyleSheet.hairlineWidth,
966
+ gap: 8,
967
+ padding: 10
968
+ },
969
+ header: { gap: 8 },
970
+ body: { gap: 8 },
971
+ footer: {
972
+ alignItems: "center",
973
+ flexDirection: "row",
974
+ gap: 8,
975
+ justifyContent: "space-between"
976
+ },
977
+ tools: {
978
+ alignItems: "center",
979
+ flexDirection: "row",
980
+ flex: 1,
981
+ flexWrap: "wrap",
982
+ gap: 8
983
+ },
984
+ textarea: {
985
+ color: (0, react_native.PlatformColor)("label"),
986
+ fontSize: 15,
987
+ minHeight: 40,
988
+ padding: 4
989
+ },
990
+ submit: {
991
+ alignItems: "center",
992
+ alignSelf: "flex-end",
993
+ backgroundColor: (0, react_native.PlatformColor)("systemBlue"),
994
+ borderRadius: 18,
995
+ height: 36,
996
+ justifyContent: "center",
997
+ minWidth: 36,
998
+ paddingHorizontal: 9
999
+ }
1000
+ });
1001
+
1002
+ //#endregion
1003
+ exports.BlurView = BlurView;
1004
+ exports.Button = Button;
1005
+ exports.Conversation = Conversation;
1006
+ exports.ConversationContent = ConversationContent;
1007
+ exports.ConversationEmptyState = ConversationEmptyState;
1008
+ exports.ConversationScrollButton = ConversationScrollButton;
1009
+ exports.GlassButton = GlassButton;
1010
+ exports.GlassContainer = GlassContainer;
1011
+ exports.GlassView = GlassView;
1012
+ exports.Label = Label;
1013
+ exports.Message = Message;
1014
+ exports.MessageActions = MessageActions;
1015
+ exports.MessageContent = MessageContent;
1016
+ exports.MessageStatus = MessageStatus;
1017
+ exports.MessageText = MessageText;
1018
+ exports.PromptInput = PromptInput;
1019
+ exports.PromptInputBody = PromptInputBody;
1020
+ exports.PromptInputFooter = PromptInputFooter;
1021
+ exports.PromptInputHeader = PromptInputHeader;
1022
+ exports.PromptInputSubmit = PromptInputSubmit;
1023
+ exports.PromptInputTextarea = PromptInputTextarea;
1024
+ exports.PromptInputTools = PromptInputTools;
1025
+ exports.SFSymbol = SFSymbol;
1026
+ exports.messageStatusDisplay = messageStatusDisplay;
1027
+ exports.promptStatusGenerating = promptStatusGenerating;
1028
+ exports.promptStatusLabel = promptStatusLabel;
1029
+ exports.promptStatusSymbol = promptStatusSymbol;
1030
+ exports.useConversation = useConversation;
1031
+ exports.usePromptInput = usePromptInput;