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.js CHANGED
@@ -1,7 +1,59 @@
1
1
  import { t as ensureNativeScript } from "./native-runtime-C85Nuc4F.js";
2
- import { ActivityIndicator, PlatformColor, Pressable, StyleSheet, Text, View, processColor } from "react-native";
2
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
3
+ import { ActivityIndicator, FlatList, PlatformColor, Pressable, StyleSheet, Text, TextInput, View, processColor } from "react-native";
3
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
5
 
6
+ //#region src/elements/ai-status.ts
7
+ function messageStatusDisplay(status) {
8
+ switch (status) {
9
+ case "queued": return {
10
+ symbol: "clock",
11
+ label: "Queued",
12
+ color: "systemGray"
13
+ };
14
+ case "generating": return {
15
+ symbol: "ellipsis",
16
+ label: "Generating",
17
+ color: "systemBlue"
18
+ };
19
+ case "canceling": return {
20
+ symbol: "xmark.circle",
21
+ label: "Canceling",
22
+ color: "systemOrange"
23
+ };
24
+ case "failed": return {
25
+ symbol: "exclamationmark.triangle",
26
+ label: "Failed",
27
+ color: "systemRed"
28
+ };
29
+ case "canceled": return {
30
+ symbol: "xmark.circle",
31
+ label: "Canceled",
32
+ color: "systemOrange"
33
+ };
34
+ default: return {
35
+ symbol: "checkmark",
36
+ label: "Completed",
37
+ color: "systemGray"
38
+ };
39
+ }
40
+ }
41
+ function promptStatusGenerating(status) {
42
+ return status === "queued" || status === "generating" || status === "canceling";
43
+ }
44
+ function promptStatusSymbol(status, generating) {
45
+ if (generating) return "stop.fill";
46
+ if (status === "failed" || status === "canceled") return "exclamationmark.arrow.triangle.2.circlepath";
47
+ return "arrow.up";
48
+ }
49
+ function promptStatusLabel(status, generating) {
50
+ if (generating) return "Stop generating";
51
+ if (status === "failed") return "Send after failure";
52
+ if (status === "canceled") return "Send after cancellation";
53
+ return "Send message";
54
+ }
55
+
56
+ //#endregion
5
57
  //#region src/elements/shared.ts
6
58
  function textFromChildren(children) {
7
59
  if (typeof children === "string" || typeof children === "number") return String(children);
@@ -243,7 +295,7 @@ const glassCornerRadius = {
243
295
  regular: 10,
244
296
  large: 12
245
297
  };
246
- function resolveStyle(style, state) {
298
+ function resolveStyle$2(style, state) {
247
299
  return typeof style === "function" ? style(state) : style;
248
300
  }
249
301
  function ButtonContent({ icon, label, labelStyle, loading, size, variant }) {
@@ -258,9 +310,9 @@ function ButtonContent({ icon, label, labelStyle, loading, size, variant }) {
258
310
  }) : null, label ? /* @__PURE__ */ jsx(Text, {
259
311
  numberOfLines: 1,
260
312
  style: [
261
- styles.label,
313
+ styles$3.label,
262
314
  labelSizeStyles[size],
263
- variant ? labelVariantStyles[variant] : styles.glassLabel,
315
+ variant ? labelVariantStyles[variant] : styles$3.glassLabel,
264
316
  labelStyle
265
317
  ],
266
318
  children: label
@@ -274,10 +326,10 @@ function Button({ accessibilityRole = "button", accessibilityState, activeOpacit
274
326
  accessibilityState: buttonAccessibilityState(accessibilityState, disabled, loading),
275
327
  disabled: inactive,
276
328
  style: (state) => [
277
- styles.button,
329
+ styles$3.button,
278
330
  sizeStyles[size],
279
331
  buttonVariantStyles[variant],
280
- resolveStyle(style, state),
332
+ resolveStyle$2(style, state),
281
333
  { opacity: buttonOpacity({
282
334
  ...state,
283
335
  disabled,
@@ -287,7 +339,7 @@ function Button({ accessibilityRole = "button", accessibilityState, activeOpacit
287
339
  ],
288
340
  children: /* @__PURE__ */ jsx(View, {
289
341
  pointerEvents: "none",
290
- style: styles.content,
342
+ style: styles$3.content,
291
343
  children: /* @__PURE__ */ jsx(ButtonContent, {
292
344
  icon,
293
345
  label,
@@ -307,10 +359,10 @@ function GlassButton({ accessibilityRole = "button", accessibilityState, activeO
307
359
  accessibilityState: buttonAccessibilityState(accessibilityState, disabled, loading),
308
360
  disabled: inactive,
309
361
  style: (state) => [
310
- styles.button,
362
+ styles$3.button,
311
363
  sizeStyles[size],
312
- styles.glassButton,
313
- resolveStyle(style, state),
364
+ styles$3.glassButton,
365
+ resolveStyle$2(style, state),
314
366
  { opacity: buttonOpacity({
315
367
  ...state,
316
368
  disabled,
@@ -320,7 +372,7 @@ function GlassButton({ accessibilityRole = "button", accessibilityState, activeO
320
372
  ],
321
373
  children: [/* @__PURE__ */ jsx(View, {
322
374
  pointerEvents: "none",
323
- style: styles.glassBackground,
375
+ style: styles$3.glassBackground,
324
376
  children: /* @__PURE__ */ jsx(GlassView, {
325
377
  glassEffectStyle,
326
378
  glassStyle: {
@@ -328,12 +380,12 @@ function GlassButton({ accessibilityRole = "button", accessibilityState, activeO
328
380
  ...glassStyle
329
381
  },
330
382
  isInteractive: false,
331
- style: styles.glass,
383
+ style: styles$3.glass,
332
384
  tintColor
333
385
  })
334
386
  }), /* @__PURE__ */ jsx(View, {
335
387
  pointerEvents: "none",
336
- style: styles.content,
388
+ style: styles$3.content,
337
389
  children: /* @__PURE__ */ jsx(ButtonContent, {
338
390
  icon,
339
391
  label,
@@ -344,7 +396,7 @@ function GlassButton({ accessibilityRole = "button", accessibilityState, activeO
344
396
  })]
345
397
  });
346
398
  }
347
- const styles = StyleSheet.create({
399
+ const styles$3 = StyleSheet.create({
348
400
  button: {
349
401
  alignItems: "center",
350
402
  borderRadius: 10,
@@ -379,6 +431,242 @@ const labelVariantStyles = StyleSheet.create({
379
431
  plain: { color: PlatformColor("systemBlue") }
380
432
  });
381
433
 
434
+ //#endregion
435
+ //#region src/elements/symbol.tsx
436
+ function symbolWeight(weight) {
437
+ switch (weight) {
438
+ case "ultraLight": return UIImageSymbolWeight.UltraLight;
439
+ case "thin": return UIImageSymbolWeight.Thin;
440
+ case "light": return UIImageSymbolWeight.Light;
441
+ case "medium": return UIImageSymbolWeight.Medium;
442
+ case "semibold": return UIImageSymbolWeight.Semibold;
443
+ case "bold": return UIImageSymbolWeight.Bold;
444
+ case "heavy": return UIImageSymbolWeight.Heavy;
445
+ case "black": return UIImageSymbolWeight.Black;
446
+ default: return UIImageSymbolWeight.Regular;
447
+ }
448
+ }
449
+ function symbolScale(scale) {
450
+ if (scale === "small") return UIImageSymbolScale.Small;
451
+ if (scale === "large") return UIImageSymbolScale.Large;
452
+ return UIImageSymbolScale.Medium;
453
+ }
454
+ function symbolConfiguration(props, style) {
455
+ const size = props.size ?? style?.fontSize ?? 17;
456
+ return UIImageSymbolConfiguration.configurationWithPointSizeWeightScale(size, symbolWeight(props.weight), symbolScale(props.scale));
457
+ }
458
+ function symbolImage(name, configuration) {
459
+ if (configuration) return UIImage.systemImageNamedWithConfiguration(name, configuration);
460
+ return UIImage.systemImageNamed(name);
461
+ }
462
+ const SFSymbol = ensureNativeScript().defineUIKitView({
463
+ name: "SFSymbol",
464
+ layout: {
465
+ sizing: "intrinsic",
466
+ defaultSize: {
467
+ width: 17,
468
+ height: 17
469
+ }
470
+ },
471
+ create() {
472
+ const imageView = UIImageView.new();
473
+ imageView.contentMode = UIViewContentMode.ScaleAspectFit;
474
+ return imageView;
475
+ },
476
+ update(imageView, props, _previousProps, ctx) {
477
+ const style = styleFromProps(props.style);
478
+ const configuration = symbolConfiguration(props, style);
479
+ imageView.image = symbolImage(props.symbol, configuration);
480
+ imageView.tintColor = colorFromStyle(props.color) ?? colorFromStyle(style?.tintColor) ?? colorFromStyle(style?.color) ?? UIColor.labelColor;
481
+ ctx?.invalidateLayout();
482
+ }
483
+ });
484
+
485
+ //#endregion
486
+ //#region src/elements/conversation.tsx
487
+ const ConversationContext = createContext(null);
488
+ const scrollEndThreshold = 48;
489
+ function useConversation() {
490
+ const context = useContext(ConversationContext);
491
+ if (!context) throw new Error("Conversation elements must be rendered inside <Conversation>");
492
+ return context;
493
+ }
494
+ function Conversation({ children, defaultFollowOutput = true, followOutput, onFollowOutputChange, style,...props }) {
495
+ const controlled = followOutput !== void 0;
496
+ const generation = useRef(0);
497
+ const [internalFollowing, setInternalFollowing] = useState(defaultFollowOutput);
498
+ const [isAtBottom, setIsAtBottom] = useState(true);
499
+ const [followGeneration, setFollowGeneration] = useState(0);
500
+ const following = controlled ? followOutput : internalFollowing;
501
+ const setFollowing = useCallback((value) => {
502
+ if (!controlled) setInternalFollowing(value);
503
+ onFollowOutputChange?.(value);
504
+ }, [controlled, onFollowOutputChange]);
505
+ const updateAtBottom = useCallback((value) => {
506
+ setIsAtBottom(value);
507
+ if (following !== value) setFollowing(value);
508
+ }, [following, setFollowing]);
509
+ const requestFollow = useCallback(() => {
510
+ generation.current += 1;
511
+ setFollowGeneration(generation.current);
512
+ setFollowing(true);
513
+ }, [setFollowing]);
514
+ const context = useMemo(() => ({
515
+ followGeneration,
516
+ following,
517
+ isAtBottom,
518
+ updateAtBottom,
519
+ requestFollow
520
+ }), [
521
+ followGeneration,
522
+ following,
523
+ isAtBottom,
524
+ updateAtBottom,
525
+ requestFollow
526
+ ]);
527
+ return /* @__PURE__ */ jsx(ConversationContext.Provider, {
528
+ value: context,
529
+ children: /* @__PURE__ */ jsx(View, {
530
+ ...props,
531
+ style: [styles$2.conversation, style],
532
+ children
533
+ })
534
+ });
535
+ }
536
+ function ConversationContent({ contentContainerStyle, data, keyboardShouldPersistTaps = "handled", onContentSizeChange, onScroll, renderItem, scrollEventThrottle = 16,...props }) {
537
+ const context = useConversation();
538
+ const list = useRef(null);
539
+ const following = useRef(context.following);
540
+ const previousHeight = useRef(0);
541
+ const previousFollowGeneration = useRef(context.followGeneration);
542
+ following.current = context.following;
543
+ useEffect(() => {
544
+ if (context.following && context.followGeneration > previousFollowGeneration.current) {
545
+ previousFollowGeneration.current = context.followGeneration;
546
+ list.current?.scrollToEnd({ animated: true });
547
+ }
548
+ }, [context.followGeneration, context.following]);
549
+ const handleScroll = useCallback((event) => {
550
+ const { contentOffset, contentSize, layoutMeasurement } = event.nativeEvent;
551
+ const distance = contentSize.height - (contentOffset.y + layoutMeasurement.height);
552
+ context.updateAtBottom(distance <= scrollEndThreshold);
553
+ onScroll?.(event);
554
+ }, [context, onScroll]);
555
+ const handleContentSizeChange = useCallback((width, height) => {
556
+ const newFollowRequested = context.followGeneration > previousFollowGeneration.current;
557
+ const shouldScroll = following.current && (previousHeight.current === 0 || height > previousHeight.current || newFollowRequested);
558
+ previousHeight.current = height;
559
+ previousFollowGeneration.current = context.followGeneration;
560
+ if (shouldScroll) list.current?.scrollToEnd({ animated: true });
561
+ onContentSizeChange?.(width, height);
562
+ }, [context.followGeneration, onContentSizeChange]);
563
+ return /* @__PURE__ */ jsx(FlatList, {
564
+ ...props,
565
+ data,
566
+ keyboardShouldPersistTaps,
567
+ onContentSizeChange: handleContentSizeChange,
568
+ onScroll: handleScroll,
569
+ ref: list,
570
+ renderItem,
571
+ scrollEventThrottle,
572
+ style: [styles$2.content, props.style],
573
+ contentContainerStyle: [styles$2.contentContainer, contentContainerStyle]
574
+ });
575
+ }
576
+ function ConversationEmptyState({ children, description = "Start a conversation to see messages here.", descriptionStyle, icon, style, title = "No messages yet", titleStyle,...props }) {
577
+ return /* @__PURE__ */ jsxs(View, {
578
+ ...props,
579
+ style: [styles$2.emptyState, style],
580
+ children: [
581
+ icon ? /* @__PURE__ */ jsx(View, {
582
+ accessibilityElementsHidden: true,
583
+ style: styles$2.emptyIcon,
584
+ children: icon
585
+ }) : null,
586
+ /* @__PURE__ */ jsx(Text, {
587
+ style: [styles$2.emptyTitle, titleStyle],
588
+ children: title
589
+ }),
590
+ /* @__PURE__ */ jsx(Text, {
591
+ style: [styles$2.emptyDescription, descriptionStyle],
592
+ children: description
593
+ }),
594
+ children
595
+ ]
596
+ });
597
+ }
598
+ function ConversationScrollButton({ accessibilityLabel = "Scroll to latest message", activeOpacity = .2, children, onPress, style,...props }) {
599
+ const context = useConversation();
600
+ if (context.isAtBottom) return null;
601
+ return /* @__PURE__ */ jsx(Pressable, {
602
+ ...props,
603
+ accessibilityLabel,
604
+ accessibilityRole: "button",
605
+ onPress: () => {
606
+ context.requestFollow();
607
+ onPress?.();
608
+ },
609
+ style: (state) => [
610
+ styles$2.scrollButton,
611
+ resolveStyle$1(style, state),
612
+ state.pressed && { opacity: activeOpacity }
613
+ ],
614
+ children: children ?? /* @__PURE__ */ jsx(SFSymbol, {
615
+ color: PlatformColor("systemBlue"),
616
+ size: 16,
617
+ symbol: "arrow.down"
618
+ })
619
+ });
620
+ }
621
+ function resolveStyle$1(style, state) {
622
+ return typeof style === "function" ? style(state) : style;
623
+ }
624
+ const styles$2 = StyleSheet.create({
625
+ conversation: {
626
+ flex: 1,
627
+ minHeight: 0,
628
+ position: "relative"
629
+ },
630
+ content: { flex: 1 },
631
+ contentContainer: {
632
+ gap: 16,
633
+ padding: 16
634
+ },
635
+ emptyState: {
636
+ alignItems: "center",
637
+ alignSelf: "center",
638
+ gap: 8,
639
+ justifyContent: "center",
640
+ maxWidth: 320,
641
+ padding: 32
642
+ },
643
+ emptyIcon: { marginBottom: 8 },
644
+ emptyTitle: {
645
+ color: PlatformColor("label"),
646
+ fontSize: 17,
647
+ fontWeight: "600",
648
+ textAlign: "center"
649
+ },
650
+ emptyDescription: {
651
+ color: PlatformColor("secondaryLabel"),
652
+ fontSize: 15,
653
+ textAlign: "center"
654
+ },
655
+ scrollButton: {
656
+ alignItems: "center",
657
+ backgroundColor: PlatformColor("secondarySystemBackground"),
658
+ borderColor: PlatformColor("separator"),
659
+ borderRadius: 18,
660
+ borderWidth: StyleSheet.hairlineWidth,
661
+ bottom: 16,
662
+ height: 36,
663
+ justifyContent: "center",
664
+ position: "absolute",
665
+ right: 16,
666
+ width: 36
667
+ }
668
+ });
669
+
382
670
  //#endregion
383
671
  //#region src/elements/glass-container.tsx
384
672
  const GlassContainer = ensureNativeScript().defineUIKitContainer({
@@ -440,55 +728,272 @@ const Label = ensureNativeScript().defineUIKitView({
440
728
  });
441
729
 
442
730
  //#endregion
443
- //#region src/elements/symbol.tsx
444
- function symbolWeight(weight) {
445
- switch (weight) {
446
- case "ultraLight": return UIImageSymbolWeight.UltraLight;
447
- case "thin": return UIImageSymbolWeight.Thin;
448
- case "light": return UIImageSymbolWeight.Light;
449
- case "medium": return UIImageSymbolWeight.Medium;
450
- case "semibold": return UIImageSymbolWeight.Semibold;
451
- case "bold": return UIImageSymbolWeight.Bold;
452
- case "heavy": return UIImageSymbolWeight.Heavy;
453
- case "black": return UIImageSymbolWeight.Black;
454
- default: return UIImageSymbolWeight.Regular;
731
+ //#region src/elements/message.tsx
732
+ function Message({ children, from = "assistant", style,...props }) {
733
+ return /* @__PURE__ */ jsx(View, {
734
+ ...props,
735
+ style: [
736
+ styles$1.message,
737
+ from === "user" ? styles$1.userMessage : styles$1.assistantMessage,
738
+ style
739
+ ],
740
+ children
741
+ });
742
+ }
743
+ function MessageContent({ children, style,...props }) {
744
+ return /* @__PURE__ */ jsx(View, {
745
+ ...props,
746
+ style: [styles$1.content, style],
747
+ children
748
+ });
749
+ }
750
+ function MessageText({ style,...props }) {
751
+ return /* @__PURE__ */ jsx(Text, {
752
+ ...props,
753
+ style: [styles$1.text, style]
754
+ });
755
+ }
756
+ function MessageStatus({ label, showSymbol = true, status, style,...props }) {
757
+ const display = messageStatusDisplay(status);
758
+ const color = PlatformColor(display.color);
759
+ return /* @__PURE__ */ jsxs(View, {
760
+ style: styles$1.status,
761
+ children: [showSymbol ? /* @__PURE__ */ jsx(SFSymbol, {
762
+ color,
763
+ size: 12,
764
+ symbol: display.symbol
765
+ }) : null, /* @__PURE__ */ jsx(Text, {
766
+ ...props,
767
+ style: [
768
+ styles$1.statusText,
769
+ { color },
770
+ style
771
+ ],
772
+ children: label ?? display.label
773
+ })]
774
+ });
775
+ }
776
+ function MessageActions({ children, style,...props }) {
777
+ return /* @__PURE__ */ jsx(View, {
778
+ ...props,
779
+ style: [styles$1.actions, style],
780
+ children
781
+ });
782
+ }
783
+ const styles$1 = StyleSheet.create({
784
+ message: {
785
+ gap: 6,
786
+ maxWidth: "85%"
787
+ },
788
+ userMessage: { alignSelf: "flex-end" },
789
+ assistantMessage: { alignSelf: "stretch" },
790
+ content: {
791
+ backgroundColor: PlatformColor("secondarySystemFill"),
792
+ borderRadius: 16,
793
+ paddingHorizontal: 14,
794
+ paddingVertical: 10
795
+ },
796
+ text: {
797
+ color: PlatformColor("label"),
798
+ fontSize: 15,
799
+ lineHeight: 21
800
+ },
801
+ status: {
802
+ alignItems: "center",
803
+ flexDirection: "row",
804
+ gap: 5
805
+ },
806
+ statusText: {
807
+ fontSize: 12,
808
+ fontWeight: "500"
809
+ },
810
+ actions: {
811
+ flexDirection: "row",
812
+ flexWrap: "wrap",
813
+ gap: 8
455
814
  }
815
+ });
816
+
817
+ //#endregion
818
+ //#region src/elements/prompt-input.tsx
819
+ const PromptInputContext = createContext(null);
820
+ function usePromptInput() {
821
+ const context = useContext(PromptInputContext);
822
+ if (!context) throw new Error("Prompt input elements must be rendered inside <PromptInput>");
823
+ return context;
456
824
  }
457
- function symbolScale(scale) {
458
- if (scale === "small") return UIImageSymbolScale.Small;
459
- if (scale === "large") return UIImageSymbolScale.Large;
460
- return UIImageSymbolScale.Medium;
825
+ function PromptInput({ children, defaultValue = "", disabled = false, onChangeText, onSubmit, status, style, value,...props }) {
826
+ const controlled = value !== void 0;
827
+ const [internalText, setInternalText] = useState(defaultValue);
828
+ const text = controlled ? value : internalText;
829
+ const setText = useCallback((nextText) => {
830
+ if (!controlled) setInternalText(nextText);
831
+ onChangeText?.(nextText);
832
+ }, [controlled, onChangeText]);
833
+ const submit = useCallback(() => {
834
+ if (disabled) return;
835
+ onSubmit?.({ text });
836
+ }, [
837
+ disabled,
838
+ onSubmit,
839
+ text
840
+ ]);
841
+ const context = useMemo(() => ({
842
+ disabled,
843
+ generating: promptStatusGenerating(status),
844
+ setText,
845
+ status,
846
+ submit,
847
+ text
848
+ }), [
849
+ disabled,
850
+ setText,
851
+ status,
852
+ submit,
853
+ text
854
+ ]);
855
+ return /* @__PURE__ */ jsx(PromptInputContext.Provider, {
856
+ value: context,
857
+ children: /* @__PURE__ */ jsx(View, {
858
+ ...props,
859
+ style: [styles.input, style],
860
+ children
861
+ })
862
+ });
461
863
  }
462
- function symbolConfiguration(props, style) {
463
- const size = props.size ?? style?.fontSize ?? 17;
464
- return UIImageSymbolConfiguration.configurationWithPointSizeWeightScale(size, symbolWeight(props.weight), symbolScale(props.scale));
864
+ function PromptInputHeader({ children, style,...props }) {
865
+ return /* @__PURE__ */ jsx(View, {
866
+ ...props,
867
+ style: [styles.header, style],
868
+ children
869
+ });
465
870
  }
466
- function symbolImage(name, configuration) {
467
- if (configuration) return UIImage.systemImageNamedWithConfiguration(name, configuration);
468
- return UIImage.systemImageNamed(name);
871
+ function PromptInputBody({ children, style,...props }) {
872
+ return /* @__PURE__ */ jsx(View, {
873
+ ...props,
874
+ style: [styles.body, style],
875
+ children
876
+ });
469
877
  }
470
- const SFSymbol = ensureNativeScript().defineUIKitView({
471
- name: "Symbol",
472
- layout: {
473
- sizing: "intrinsic",
474
- defaultSize: {
475
- width: 17,
476
- height: 17
477
- }
878
+ function PromptInputFooter({ children, style,...props }) {
879
+ return /* @__PURE__ */ jsx(View, {
880
+ ...props,
881
+ style: [styles.footer, style],
882
+ children
883
+ });
884
+ }
885
+ function PromptInputTools({ children, style,...props }) {
886
+ return /* @__PURE__ */ jsx(View, {
887
+ ...props,
888
+ style: [styles.tools, style],
889
+ children
890
+ });
891
+ }
892
+ function PromptInputTextarea({ multiline = true, onChangeText, onSubmitEditing, placeholder = "Send a message", placeholderTextColor = PlatformColor("placeholderText"), returnKeyType = "send", style, submitOnEnter = !multiline, value,...props }) {
893
+ const context = usePromptInput();
894
+ const text = value !== void 0 ? value : context.text;
895
+ return /* @__PURE__ */ jsx(TextInput, {
896
+ ...props,
897
+ editable: !context.disabled && props.editable !== false,
898
+ multiline,
899
+ onChangeText: (nextText) => {
900
+ context.setText(nextText);
901
+ onChangeText?.(nextText);
902
+ },
903
+ onSubmitEditing: (event) => {
904
+ onSubmitEditing?.(event);
905
+ if (submitOnEnter) context.submit();
906
+ },
907
+ placeholder,
908
+ placeholderTextColor,
909
+ returnKeyType,
910
+ style: [styles.textarea, style],
911
+ submitBehavior: multiline && !submitOnEnter ? "newline" : "submit",
912
+ value: text
913
+ });
914
+ }
915
+ function PromptInputSubmit({ accessibilityLabel, accessibilityState, activeOpacity = .2, children, disabled: disabledProp, generating, loading = false, onPress, status, style,...props }) {
916
+ const context = usePromptInput();
917
+ const resolvedStatus = status ?? context.status;
918
+ const resolvedGenerating = generating ?? loading ?? promptStatusGenerating(resolvedStatus);
919
+ const disabled = context.disabled || buttonDisabled(disabledProp === true, loading);
920
+ const resolvedChildren = typeof children === "function" ? children({ generating: resolvedGenerating }) : children;
921
+ return /* @__PURE__ */ jsx(Pressable, {
922
+ ...props,
923
+ accessibilityLabel: accessibilityLabel ?? promptStatusLabel(resolvedStatus, resolvedGenerating),
924
+ accessibilityRole: "button",
925
+ accessibilityState: {
926
+ ...accessibilityState,
927
+ busy: resolvedGenerating,
928
+ disabled
929
+ },
930
+ disabled,
931
+ onPress: () => {
932
+ if (onPress) onPress({ text: context.text });
933
+ else context.submit();
934
+ },
935
+ style: (state) => [
936
+ styles.submit,
937
+ resolveStyle(style, state),
938
+ { opacity: buttonOpacity({
939
+ ...state,
940
+ disabled,
941
+ loading,
942
+ activeOpacity
943
+ }) }
944
+ ],
945
+ children: resolvedChildren ?? /* @__PURE__ */ jsx(SFSymbol, {
946
+ color: "#ffffff",
947
+ size: 16,
948
+ symbol: promptStatusSymbol(resolvedStatus, resolvedGenerating),
949
+ weight: "semibold"
950
+ })
951
+ });
952
+ }
953
+ function resolveStyle(style, state) {
954
+ return typeof style === "function" ? style(state) : style;
955
+ }
956
+ const styles = StyleSheet.create({
957
+ input: {
958
+ backgroundColor: PlatformColor("secondarySystemBackground"),
959
+ borderColor: PlatformColor("separator"),
960
+ borderRadius: 18,
961
+ borderWidth: StyleSheet.hairlineWidth,
962
+ gap: 8,
963
+ padding: 10
478
964
  },
479
- create() {
480
- const imageView = UIImageView.new();
481
- imageView.contentMode = UIViewContentMode.ScaleAspectFit;
482
- return imageView;
965
+ header: { gap: 8 },
966
+ body: { gap: 8 },
967
+ footer: {
968
+ alignItems: "center",
969
+ flexDirection: "row",
970
+ gap: 8,
971
+ justifyContent: "space-between"
483
972
  },
484
- update(imageView, props, _previousProps, ctx) {
485
- const style = styleFromProps(props.style);
486
- const configuration = symbolConfiguration(props, style);
487
- imageView.image = symbolImage(props.symbol, configuration);
488
- imageView.tintColor = colorFromStyle(props.color) ?? colorFromStyle(style?.tintColor) ?? colorFromStyle(style?.color) ?? UIColor.labelColor;
489
- ctx?.invalidateLayout();
973
+ tools: {
974
+ alignItems: "center",
975
+ flexDirection: "row",
976
+ flex: 1,
977
+ flexWrap: "wrap",
978
+ gap: 8
979
+ },
980
+ textarea: {
981
+ color: PlatformColor("label"),
982
+ fontSize: 15,
983
+ minHeight: 40,
984
+ padding: 4
985
+ },
986
+ submit: {
987
+ alignItems: "center",
988
+ alignSelf: "flex-end",
989
+ backgroundColor: PlatformColor("systemBlue"),
990
+ borderRadius: 18,
991
+ height: 36,
992
+ justifyContent: "center",
993
+ minWidth: 36,
994
+ paddingHorizontal: 9
490
995
  }
491
996
  });
492
997
 
493
998
  //#endregion
494
- export { BlurView, Button, GlassButton, GlassContainer, GlassView, Label, SFSymbol as Symbol };
999
+ export { BlurView, Button, Conversation, ConversationContent, ConversationEmptyState, ConversationScrollButton, GlassButton, GlassContainer, GlassView, Label, Message, MessageActions, MessageContent, MessageStatus, MessageText, PromptInput, PromptInputBody, PromptInputFooter, PromptInputHeader, PromptInputSubmit, PromptInputTextarea, PromptInputTools, SFSymbol, messageStatusDisplay, promptStatusGenerating, promptStatusLabel, promptStatusSymbol, useConversation, usePromptInput };