bleam 0.0.13 → 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.
package/dist/elements.cjs CHANGED
@@ -1,10 +1,63 @@
1
1
  const require_chunk = require('./chunk-CUT6urMc.cjs');
2
2
  const require_native_runtime = require('./native-runtime-CsXnXkQn.cjs');
3
+ let react = require("react");
4
+ react = require_chunk.__toESM(react);
3
5
  let react_native = require("react-native");
4
6
  react_native = require_chunk.__toESM(react_native);
5
7
  let react_jsx_runtime = require("react/jsx-runtime");
6
8
  react_jsx_runtime = require_chunk.__toESM(react_jsx_runtime);
7
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
8
61
  //#region src/elements/shared.ts
9
62
  function textFromChildren(children) {
10
63
  if (typeof children === "string" || typeof children === "number") return String(children);
@@ -246,7 +299,7 @@ const glassCornerRadius = {
246
299
  regular: 10,
247
300
  large: 12
248
301
  };
249
- function resolveStyle(style, state) {
302
+ function resolveStyle$2(style, state) {
250
303
  return typeof style === "function" ? style(state) : style;
251
304
  }
252
305
  function ButtonContent({ icon, label, labelStyle, loading, size, variant }) {
@@ -261,9 +314,9 @@ function ButtonContent({ icon, label, labelStyle, loading, size, variant }) {
261
314
  }) : null, label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
262
315
  numberOfLines: 1,
263
316
  style: [
264
- styles.label,
317
+ styles$3.label,
265
318
  labelSizeStyles[size],
266
- variant ? labelVariantStyles[variant] : styles.glassLabel,
319
+ variant ? labelVariantStyles[variant] : styles$3.glassLabel,
267
320
  labelStyle
268
321
  ],
269
322
  children: label
@@ -277,10 +330,10 @@ function Button({ accessibilityRole = "button", accessibilityState, activeOpacit
277
330
  accessibilityState: buttonAccessibilityState(accessibilityState, disabled, loading),
278
331
  disabled: inactive,
279
332
  style: (state) => [
280
- styles.button,
333
+ styles$3.button,
281
334
  sizeStyles[size],
282
335
  buttonVariantStyles[variant],
283
- resolveStyle(style, state),
336
+ resolveStyle$2(style, state),
284
337
  { opacity: buttonOpacity({
285
338
  ...state,
286
339
  disabled,
@@ -290,7 +343,7 @@ function Button({ accessibilityRole = "button", accessibilityState, activeOpacit
290
343
  ],
291
344
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
292
345
  pointerEvents: "none",
293
- style: styles.content,
346
+ style: styles$3.content,
294
347
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ButtonContent, {
295
348
  icon,
296
349
  label,
@@ -310,10 +363,10 @@ function GlassButton({ accessibilityRole = "button", accessibilityState, activeO
310
363
  accessibilityState: buttonAccessibilityState(accessibilityState, disabled, loading),
311
364
  disabled: inactive,
312
365
  style: (state) => [
313
- styles.button,
366
+ styles$3.button,
314
367
  sizeStyles[size],
315
- styles.glassButton,
316
- resolveStyle(style, state),
368
+ styles$3.glassButton,
369
+ resolveStyle$2(style, state),
317
370
  { opacity: buttonOpacity({
318
371
  ...state,
319
372
  disabled,
@@ -323,7 +376,7 @@ function GlassButton({ accessibilityRole = "button", accessibilityState, activeO
323
376
  ],
324
377
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
325
378
  pointerEvents: "none",
326
- style: styles.glassBackground,
379
+ style: styles$3.glassBackground,
327
380
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GlassView, {
328
381
  glassEffectStyle,
329
382
  glassStyle: {
@@ -331,12 +384,12 @@ function GlassButton({ accessibilityRole = "button", accessibilityState, activeO
331
384
  ...glassStyle
332
385
  },
333
386
  isInteractive: false,
334
- style: styles.glass,
387
+ style: styles$3.glass,
335
388
  tintColor
336
389
  })
337
390
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
338
391
  pointerEvents: "none",
339
- style: styles.content,
392
+ style: styles$3.content,
340
393
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ButtonContent, {
341
394
  icon,
342
395
  label,
@@ -347,7 +400,7 @@ function GlassButton({ accessibilityRole = "button", accessibilityState, activeO
347
400
  })]
348
401
  });
349
402
  }
350
- const styles = react_native.StyleSheet.create({
403
+ const styles$3 = react_native.StyleSheet.create({
351
404
  button: {
352
405
  alignItems: "center",
353
406
  borderRadius: 10,
@@ -382,6 +435,242 @@ const labelVariantStyles = react_native.StyleSheet.create({
382
435
  plain: { color: (0, react_native.PlatformColor)("systemBlue") }
383
436
  });
384
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
+
385
674
  //#endregion
386
675
  //#region src/elements/glass-container.tsx
387
676
  const GlassContainer = require_native_runtime.ensureNativeScript().defineUIKitContainer({
@@ -443,61 +732,300 @@ const Label = require_native_runtime.ensureNativeScript().defineUIKitView({
443
732
  });
444
733
 
445
734
  //#endregion
446
- //#region src/elements/symbol.tsx
447
- function symbolWeight(weight) {
448
- switch (weight) {
449
- case "ultraLight": return UIImageSymbolWeight.UltraLight;
450
- case "thin": return UIImageSymbolWeight.Thin;
451
- case "light": return UIImageSymbolWeight.Light;
452
- case "medium": return UIImageSymbolWeight.Medium;
453
- case "semibold": return UIImageSymbolWeight.Semibold;
454
- case "bold": return UIImageSymbolWeight.Bold;
455
- case "heavy": return UIImageSymbolWeight.Heavy;
456
- case "black": return UIImageSymbolWeight.Black;
457
- default: return UIImageSymbolWeight.Regular;
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
458
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;
459
828
  }
460
- function symbolScale(scale) {
461
- if (scale === "small") return UIImageSymbolScale.Small;
462
- if (scale === "large") return UIImageSymbolScale.Large;
463
- return UIImageSymbolScale.Medium;
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
+ });
464
867
  }
465
- function symbolConfiguration(props, style) {
466
- const size = props.size ?? style?.fontSize ?? 17;
467
- return UIImageSymbolConfiguration.configurationWithPointSizeWeightScale(size, symbolWeight(props.weight), symbolScale(props.scale));
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
+ });
468
874
  }
469
- function symbolImage(name, configuration) {
470
- if (configuration) return UIImage.systemImageNamedWithConfiguration(name, configuration);
471
- return UIImage.systemImageNamed(name);
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
+ });
472
881
  }
473
- const SFSymbol = require_native_runtime.ensureNativeScript().defineUIKitView({
474
- name: "Symbol",
475
- layout: {
476
- sizing: "intrinsic",
477
- defaultSize: {
478
- width: 17,
479
- height: 17
480
- }
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
481
968
  },
482
- create() {
483
- const imageView = UIImageView.new();
484
- imageView.contentMode = UIViewContentMode.ScaleAspectFit;
485
- return imageView;
969
+ header: { gap: 8 },
970
+ body: { gap: 8 },
971
+ footer: {
972
+ alignItems: "center",
973
+ flexDirection: "row",
974
+ gap: 8,
975
+ justifyContent: "space-between"
486
976
  },
487
- update(imageView, props, _previousProps, ctx) {
488
- const style = styleFromProps(props.style);
489
- const configuration = symbolConfiguration(props, style);
490
- imageView.image = symbolImage(props.symbol, configuration);
491
- imageView.tintColor = colorFromStyle(props.color) ?? colorFromStyle(style?.tintColor) ?? colorFromStyle(style?.color) ?? UIColor.labelColor;
492
- ctx?.invalidateLayout();
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
493
999
  }
494
1000
  });
495
1001
 
496
1002
  //#endregion
497
1003
  exports.BlurView = BlurView;
498
1004
  exports.Button = Button;
1005
+ exports.Conversation = Conversation;
1006
+ exports.ConversationContent = ConversationContent;
1007
+ exports.ConversationEmptyState = ConversationEmptyState;
1008
+ exports.ConversationScrollButton = ConversationScrollButton;
499
1009
  exports.GlassButton = GlassButton;
500
1010
  exports.GlassContainer = GlassContainer;
501
1011
  exports.GlassView = GlassView;
502
1012
  exports.Label = Label;
503
- exports.Symbol = SFSymbol;
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;