@page-speed/agent-everywhere 0.1.0 → 0.2.0

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/index.d.cts CHANGED
@@ -1091,8 +1091,27 @@ interface PromptInputProps {
1091
1091
  inputClassName?: string;
1092
1092
  /** Variant styling */
1093
1093
  variant?: 'default' | 'minimal' | 'bordered';
1094
+ /**
1095
+ * Minimum number of visible text rows. Default 1 (grows as the user types).
1096
+ */
1097
+ minRows?: number;
1098
+ /**
1099
+ * Maximum number of visible text rows before the textarea scrolls internally
1100
+ * instead of growing further. Default 6.
1101
+ */
1102
+ maxRows?: number;
1094
1103
  }
1095
- declare const PromptInput: react.ForwardRefExoticComponent<PromptInputProps & react.RefAttributes<HTMLInputElement>>;
1104
+ /**
1105
+ * Conversational prompt input.
1106
+ *
1107
+ * Behaves like a standard AI chat input: it is a multi-line, auto-growing
1108
+ * textarea where **Enter submits** and **Shift+Enter inserts a newline**. The
1109
+ * textarea grows with content up to `maxRows`, then scrolls internally.
1110
+ *
1111
+ * (Previously this was a single-line `<input>`, which made Shift+Enter a no-op
1112
+ * and prevented multi-line messages entirely.)
1113
+ */
1114
+ declare const PromptInput: react.ForwardRefExoticComponent<PromptInputProps & react.RefAttributes<HTMLTextAreaElement>>;
1096
1115
 
1097
1116
  interface MultimodalInputProps {
1098
1117
  /** Current input value */
package/dist/index.d.ts CHANGED
@@ -1091,8 +1091,27 @@ interface PromptInputProps {
1091
1091
  inputClassName?: string;
1092
1092
  /** Variant styling */
1093
1093
  variant?: 'default' | 'minimal' | 'bordered';
1094
+ /**
1095
+ * Minimum number of visible text rows. Default 1 (grows as the user types).
1096
+ */
1097
+ minRows?: number;
1098
+ /**
1099
+ * Maximum number of visible text rows before the textarea scrolls internally
1100
+ * instead of growing further. Default 6.
1101
+ */
1102
+ maxRows?: number;
1094
1103
  }
1095
- declare const PromptInput: react.ForwardRefExoticComponent<PromptInputProps & react.RefAttributes<HTMLInputElement>>;
1104
+ /**
1105
+ * Conversational prompt input.
1106
+ *
1107
+ * Behaves like a standard AI chat input: it is a multi-line, auto-growing
1108
+ * textarea where **Enter submits** and **Shift+Enter inserts a newline**. The
1109
+ * textarea grows with content up to `maxRows`, then scrolls internally.
1110
+ *
1111
+ * (Previously this was a single-line `<input>`, which made Shift+Enter a no-op
1112
+ * and prevented multi-line messages entirely.)
1113
+ */
1114
+ declare const PromptInput: react.ForwardRefExoticComponent<PromptInputProps & react.RefAttributes<HTMLTextAreaElement>>;
1096
1115
 
1097
1116
  interface MultimodalInputProps {
1098
1117
  /** Current input value */
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { clsx } from 'clsx';
3
3
  import { twMerge } from 'tailwind-merge';
4
4
  import * as React4 from 'react';
5
- import { createContext, forwardRef, useCallback, useRef, useState, useEffect, useReducer, useMemo, useContext } from 'react';
5
+ import { createContext, forwardRef, useRef, useImperativeHandle, useCallback, useLayoutEffect, useState, useEffect, useReducer, useMemo, useContext } from 'react';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
  import { AnimatePresence, motion } from 'motion/react';
8
8
  import { SendIcon, PaperclipIcon, FileTextIcon, MicIcon, ImageIcon, XIcon, SearchIcon, UploadIcon, FileIcon, UserCircleIcon, CheckIcon, SparklesIcon, BookmarkIcon, InfoIcon, CheckCircle2Icon, AlertTriangleIcon, LightbulbIcon, BrainIcon, ChevronDownIcon, ZapIcon, CopyIcon, ThumbsUpIcon, ThumbsDownIcon, BotIcon, UserIcon, DownloadIcon, MinusIcon, TrendingDownIcon, TrendingUpIcon, ChevronUpIcon, ArrowUpDownIcon, LinkIcon, PlayIcon, ExternalLinkIcon, WandIcon, LayoutGridIcon, Grid3X3Icon, ArrowUpRightIcon, ShuffleIcon, SkipForwardIcon, ChevronLeftIcon, ChevronRightIcon, XCircleIcon, HelpCircleIcon, Minimize2Icon, Maximize2Icon, RotateCcwIcon, MessageSquareIcon, GripVerticalIcon, PanelLeftOpenIcon, PanelLeftCloseIcon, CheckCircleIcon, AlertCircleIcon, MoreHorizontalIcon, ArrowLeftIcon, MoreVerticalIcon, Loader2Icon, ArrowRightIcon, AlignLeftIcon, ListIcon, HashIcon, TypeIcon, ClockIcon, CoinsIcon, ActivityIcon, ArrowUpIcon, ArrowDownIcon } from 'lucide-react';
@@ -1056,23 +1056,6 @@ function StatusBadge({
1056
1056
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-[10px]", children: displayLabel })
1057
1057
  ] });
1058
1058
  }
1059
- var Input = React4.forwardRef(
1060
- ({ className, type, ...props }, ref) => {
1061
- return /* @__PURE__ */ jsx(
1062
- "input",
1063
- {
1064
- type,
1065
- className: cn(
1066
- "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1067
- className
1068
- ),
1069
- ref,
1070
- ...props
1071
- }
1072
- );
1073
- }
1074
- );
1075
- Input.displayName = "Input";
1076
1059
  var buttonVariants = cva(
1077
1060
  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1078
1061
  {
@@ -1112,6 +1095,8 @@ var Button = React4.forwardRef(
1112
1095
  }
1113
1096
  );
1114
1097
  Button.displayName = "Button";
1098
+ var LINE_HEIGHT_PX = 20;
1099
+ var VERTICAL_PADDING_PX = 8;
1115
1100
  var PromptInput = forwardRef(
1116
1101
  ({
1117
1102
  value,
@@ -1127,11 +1112,28 @@ var PromptInput = forwardRef(
1127
1112
  rightActions,
1128
1113
  className,
1129
1114
  inputClassName,
1130
- variant = "default"
1115
+ variant = "default",
1116
+ minRows = 1,
1117
+ maxRows = 6
1131
1118
  }, ref) => {
1119
+ const textareaRef = useRef(null);
1120
+ useImperativeHandle(ref, () => textareaRef.current);
1121
+ const resize = useCallback(() => {
1122
+ const el = textareaRef.current;
1123
+ if (!el) return;
1124
+ el.style.height = "auto";
1125
+ const maxHeight = maxRows * LINE_HEIGHT_PX + VERTICAL_PADDING_PX;
1126
+ const minHeight = minRows * LINE_HEIGHT_PX + VERTICAL_PADDING_PX;
1127
+ const next = Math.min(Math.max(el.scrollHeight, minHeight), maxHeight);
1128
+ el.style.height = `${next}px`;
1129
+ el.style.overflowY = el.scrollHeight > maxHeight ? "auto" : "hidden";
1130
+ }, [maxRows, minRows]);
1131
+ useLayoutEffect(() => {
1132
+ resize();
1133
+ }, [value, resize]);
1132
1134
  const handleSubmit = useCallback(
1133
1135
  (e) => {
1134
- e.preventDefault();
1136
+ e?.preventDefault();
1135
1137
  if (!value.trim() || disabled || loading) return;
1136
1138
  onSubmit();
1137
1139
  },
@@ -1141,7 +1143,7 @@ var PromptInput = forwardRef(
1141
1143
  (e) => {
1142
1144
  if (e.key === "Enter" && !e.shiftKey) {
1143
1145
  e.preventDefault();
1144
- handleSubmit(e);
1146
+ handleSubmit();
1145
1147
  }
1146
1148
  },
1147
1149
  [handleSubmit]
@@ -1152,48 +1154,65 @@ var PromptInput = forwardRef(
1152
1154
  bordered: "border rounded-lg px-3 py-2.5"
1153
1155
  };
1154
1156
  const inputVariantStyles = {
1155
- default: "h-9 border-0 bg-transparent shadow-none focus-visible:ring-0",
1156
- minimal: "h-8 border-0 bg-transparent shadow-none focus-visible:ring-0 px-0",
1157
- bordered: "h-9 border-0 bg-muted/50 shadow-none focus-visible:ring-0"
1157
+ default: "bg-transparent",
1158
+ minimal: "bg-transparent px-0",
1159
+ bordered: "bg-muted/50"
1158
1160
  };
1161
+ return /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, className: cn(variantStyles[variant], className), children: /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-2", children: [
1162
+ leftActions,
1163
+ /* @__PURE__ */ jsx(
1164
+ "textarea",
1165
+ {
1166
+ ref: textareaRef,
1167
+ value,
1168
+ onChange: (e) => onChange(e.target.value),
1169
+ onKeyDown: handleKeyDown,
1170
+ placeholder,
1171
+ disabled: disabled || loading,
1172
+ autoFocus,
1173
+ rows: minRows,
1174
+ className: cn(
1175
+ "flex-1 resize-none border-0 px-0 py-1 text-sm leading-5 shadow-none",
1176
+ "placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0",
1177
+ "disabled:cursor-not-allowed disabled:opacity-50",
1178
+ inputVariantStyles[variant],
1179
+ inputClassName
1180
+ )
1181
+ }
1182
+ ),
1183
+ rightActions,
1184
+ showSendButton && /* @__PURE__ */ jsx(
1185
+ Button,
1186
+ {
1187
+ type: "submit",
1188
+ size: "sm",
1189
+ variant: variant === "minimal" ? "ghost" : "outline",
1190
+ disabled: !value.trim() || disabled || loading,
1191
+ className: "size-8 shrink-0 p-0",
1192
+ children: sendButtonContent || /* @__PURE__ */ jsx(SendIcon, { className: "size-4" })
1193
+ }
1194
+ )
1195
+ ] }) });
1196
+ }
1197
+ );
1198
+ PromptInput.displayName = "PromptInput";
1199
+ var Input = React4.forwardRef(
1200
+ ({ className, type, ...props }, ref) => {
1159
1201
  return /* @__PURE__ */ jsx(
1160
- "form",
1202
+ "input",
1161
1203
  {
1162
- onSubmit: handleSubmit,
1163
- className: cn(variantStyles[variant], className),
1164
- children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1165
- leftActions,
1166
- /* @__PURE__ */ jsx(
1167
- Input,
1168
- {
1169
- ref,
1170
- value,
1171
- onChange: (e) => onChange(e.target.value),
1172
- onKeyDown: handleKeyDown,
1173
- placeholder,
1174
- disabled: disabled || loading,
1175
- autoFocus,
1176
- className: cn("flex-1 text-sm", inputVariantStyles[variant], inputClassName)
1177
- }
1178
- ),
1179
- rightActions,
1180
- showSendButton && /* @__PURE__ */ jsx(
1181
- Button,
1182
- {
1183
- type: "submit",
1184
- size: "sm",
1185
- variant: variant === "minimal" ? "ghost" : "outline",
1186
- disabled: !value.trim() || disabled || loading,
1187
- className: "size-8 shrink-0 p-0",
1188
- children: sendButtonContent || /* @__PURE__ */ jsx(SendIcon, { className: "size-4" })
1189
- }
1190
- )
1191
- ] })
1204
+ type,
1205
+ className: cn(
1206
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1207
+ className
1208
+ ),
1209
+ ref,
1210
+ ...props
1192
1211
  }
1193
1212
  );
1194
1213
  }
1195
1214
  );
1196
- PromptInput.displayName = "PromptInput";
1215
+ Input.displayName = "Input";
1197
1216
  var attachmentIcons = {
1198
1217
  image: ImageIcon,
1199
1218
  audio: MicIcon,
@@ -6227,7 +6246,7 @@ function FloatingWidget({
6227
6246
  children,
6228
6247
  isLoading && /* @__PURE__ */ jsx(TypingIndicator, { size: "sm" })
6229
6248
  ] }) }),
6230
- quickReplies && /* @__PURE__ */ jsx("div", { className: "flex gap-1.5 overflow-x-auto px-4 pb-2", children: quickReplies }),
6249
+ quickReplies && /* @__PURE__ */ jsx("div", { className: "max-h-[40%] shrink-0 overflow-y-auto border-t bg-muted/30 px-4 py-2", children: quickReplies }),
6231
6250
  input,
6232
6251
  footer && /* @__PURE__ */ jsx("div", { className: "border-t px-4 py-1.5", children: /* @__PURE__ */ jsx("p", { className: "text-center text-[10px] text-muted-foreground", children: footer }) })
6233
6252
  ]