@alivault/pico 0.10.2 → 0.11.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.
@@ -1,8 +1,8 @@
1
1
  import { i as __toESM } from "../_runtime.mjs";
2
- import { $ as require_react, A as TabsTab, B as Input, C as MenuPositioner, D as MenuGroupLabel, E as MenuItem, F as DialogPopup, H as useRender, I as DialogDescription$1, L as DialogClose, M as DialogTitle$1, N as DialogRoot, O as MenuGroup, P as DialogPortal$1, Q as require_jsx_runtime, R as DialogBackdrop, S as MenuRoot, T as MenuPopup, V as Button, Y as mergeProps, _ as AccordionItem$1, a as ContextMenuRoot, b as MenuTrigger, c as CollapsibleRoot, d as PopoverPortal, f as PopoverTrigger$1, g as AccordionHeader, h as AccordionTrigger$1, i as ContextMenuTrigger$1, j as TabsRoot, k as TabsList$1, l as PopoverPopup, m as AccordionPanel, n as ToggleGroup, o as CollapsiblePanel, p as PopoverRoot, r as Toggle, s as CollapsibleTrigger$1, t as AlertDialogRoot, u as PopoverPositioner, v as AccordionRoot, w as MenuPortal, x as MenuSubmenuRoot, y as MenuSubmenuTrigger, z as Separator } from "../_libs/@base-ui/react+[...].mjs";
2
+ import { $ as require_react, A as TabsTab, B as Input, C as MenuPositioner, D as MenuGroupLabel, E as MenuItem, F as DialogPopup, H as useRender, I as DialogDescription$1, L as DialogClose$1, M as DialogTitle$1, N as DialogRoot, O as MenuGroup, P as DialogPortal$1, Q as require_jsx_runtime, R as DialogBackdrop, S as MenuRoot, T as MenuPopup, V as Button, Y as mergeProps, _ as AccordionItem$1, a as ContextMenuRoot, b as MenuTrigger, c as CollapsibleRoot, d as PopoverPortal, f as PopoverTrigger$1, g as AccordionHeader, h as AccordionTrigger$1, i as ContextMenuTrigger$1, j as TabsRoot, k as TabsList$1, l as PopoverPopup, m as AccordionPanel, n as ToggleGroup, o as CollapsiblePanel, p as PopoverRoot, r as Toggle, s as CollapsibleTrigger$1, t as AlertDialogRoot, u as PopoverPositioner, v as AccordionRoot, w as MenuPortal, x as MenuSubmenuRoot, y as MenuSubmenuTrigger, z as Separator } from "../_libs/@base-ui/react+[...].mjs";
3
3
  import { t as cva } from "../_libs/class-variance-authority+clsx.mjs";
4
4
  import { A as ExternalLink, B as ChevronRight, C as ImagePlus, D as Folder, E as GitCommitHorizontal, F as Command, G as ArrowUpRight, H as Check, J as ArrowDown, L as ChevronsUpDown, M as EllipsisVertical, N as Download, O as FolderPlus, P as Copy, R as ChevronsDownUp, T as GitBranch, U as ArrowUp, V as ChevronDown, W as ArrowUpToLine, _ as OctagonX, a as TriangleAlert, b as ListStart, c as SquarePen, d as Plus, f as PanelRight, h as PanelLeftClose, i as Undo2, j as Ellipsis, k as FileDiff, l as Settings2, m as PanelLeftOpen, n as WandSparkles, o as Tag, p as PanelLeft, q as ArrowLeft, r as Upload, s as Square, t as X, u as Search, v as Minimize2, w as GitPullRequestArrow, x as ListEnd, y as Maximize2 } from "../_libs/lucide-react.mjs";
5
- import { $ as normalizeThemeFamily, A as Tooltip$1, C as SESSION_DONE_SOUND_ENABLED_STORAGE_KEY, Ct as themeFamilyDescription, D as THEME_FAMILIES, Dt as themeFamilySupportsColorMode, E as THEME_COLOR_MODE_STORAGE_KEY, Et as themeFamilyLabel, F as appliedThemeClass, H as createInitialSessionState, I as appliedThemeClassColorMode, K as flattenTree, N as TooltipTrigger, O as THEME_STORAGE_KEY, Ot as thinkingSummaryText, P as VIEWER_CONTEXT_STORAGE_KEY, Q as normalizeThemeColorMode, R as buildItemsFromSync, S as SESSION_DONE_DESKTOP_NOTIFICATIONS_ENABLED_STORAGE_KEY, St as themeColorModeLabel, T as Spinner, Tt as themeFamilyKeywords, V as createContextId, X as normalizeSessionSelectionKeys, Y as normalizePromptImage, Z as normalizeStoredDirectoryList, _ as RIGHT_SIDEBAR_HISTORY_HEIGHT_STORAGE_KEY, _t as rememberStoredPromptDraft, a as COLLAPSED_DIRECTORIES_STORAGE_KEY, at as readStoredCollapsedDirectories, b as RIGHT_SIDEBAR_WIDTHS_STORAGE_KEY, bt as sameContextUsage, c as Kbd, ct as readStoredPinnedSessionKeys, d as PICO_DIFF_SHIKI_THEMES, dt as readStoredRightSidebarOpen, et as previewUrlForImage, f as PICO_SHIKI_VARIABLE_DEFAULTS, ft as readStoredSessionDoneDesktopNotificationsEnabled, g as RIGHT_SIDEBAR_FILE_TREE_WIDTH_STORAGE_KEY, gt as readStoredThemeColorMode, h as RIGHT_SIDEBAR_ACTIVE_TAB_STORAGE_KEY, ht as readStoredTheme, i as CENTER_MESSAGES_STORAGE_KEY, it as readStoredCenterMessages, j as TooltipContent, k as TitleTooltip, l as KeyboardShortcutContent, lt as readStoredPromptDraft, m as RECENT_DIRECTORIES_STORAGE_KEY, mt as readStoredSidebarDirectories, n as APPLIED_THEME_STORAGE_KEY, nt as promptDraftKeyMatchesOwner, o as DRAFT_DIRECTORY_STORAGE_KEY, ot as readStoredDraftDirectory, p as PINNED_SESSIONS_STORAGE_KEY, pt as readStoredSessionDoneSoundEnabled, q as getSessionTitle, r as AUTO_SCROLL_ENABLED_STORAGE_KEY, rt as readStoredAutoScrollEnabled, s as HIDE_TOOL_BLOCKS_STORAGE_KEY, st as readStoredHideToolBlocks, tt as promptDraftKey, ut as readStoredRecentDirectories, v as RIGHT_SIDEBAR_HISTORY_TAB_STORAGE_KEY, vt as safeLocalStorageGetItem, w as SIDEBAR_DIRECTORIES_STORAGE_KEY, wt as themeFamilyFixedMode, x as Route, xt as sessionListEntryKey, y as RIGHT_SIDEBAR_OPEN_STORAGE_KEY, yt as safeLocalStorageSetItem, z as cn } from "./routes-CHNxptm_.mjs";
5
+ import { $ as normalizeThemeFamily, A as Tooltip$1, C as SESSION_DONE_SOUND_ENABLED_STORAGE_KEY, Ct as themeFamilyDescription, D as THEME_FAMILIES, Dt as themeFamilySupportsColorMode, E as THEME_COLOR_MODE_STORAGE_KEY, Et as themeFamilyLabel, F as appliedThemeClass, H as createInitialSessionState, I as appliedThemeClassColorMode, K as flattenTree, N as TooltipTrigger, O as THEME_STORAGE_KEY, Ot as thinkingSummaryText, P as VIEWER_CONTEXT_STORAGE_KEY, Q as normalizeThemeColorMode, R as buildItemsFromSync, S as SESSION_DONE_DESKTOP_NOTIFICATIONS_ENABLED_STORAGE_KEY, St as themeColorModeLabel, T as Spinner, Tt as themeFamilyKeywords, V as createContextId, X as normalizeSessionSelectionKeys, Y as normalizePromptImage, Z as normalizeStoredDirectoryList, _ as RIGHT_SIDEBAR_HISTORY_HEIGHT_STORAGE_KEY, _t as rememberStoredPromptDraft, a as COLLAPSED_DIRECTORIES_STORAGE_KEY, at as readStoredCollapsedDirectories, b as RIGHT_SIDEBAR_WIDTHS_STORAGE_KEY, bt as sameContextUsage, c as Kbd, ct as readStoredPinnedSessionKeys, d as PICO_DIFF_SHIKI_THEMES, dt as readStoredRightSidebarOpen, et as previewUrlForImage, f as PICO_SHIKI_VARIABLE_DEFAULTS, ft as readStoredSessionDoneDesktopNotificationsEnabled, g as RIGHT_SIDEBAR_FILE_TREE_WIDTH_STORAGE_KEY, gt as readStoredThemeColorMode, h as RIGHT_SIDEBAR_ACTIVE_TAB_STORAGE_KEY, ht as readStoredTheme, i as CENTER_MESSAGES_STORAGE_KEY, it as readStoredCenterMessages, j as TooltipContent, k as TitleTooltip, l as KeyboardShortcutContent, lt as readStoredPromptDraft, m as RECENT_DIRECTORIES_STORAGE_KEY, mt as readStoredSidebarDirectories, n as APPLIED_THEME_STORAGE_KEY, nt as promptDraftKeyMatchesOwner, o as DRAFT_DIRECTORY_STORAGE_KEY, ot as readStoredDraftDirectory, p as PINNED_SESSIONS_STORAGE_KEY, pt as readStoredSessionDoneSoundEnabled, q as getSessionTitle, r as AUTO_SCROLL_ENABLED_STORAGE_KEY, rt as readStoredAutoScrollEnabled, s as HIDE_TOOL_BLOCKS_STORAGE_KEY, st as readStoredHideToolBlocks, tt as promptDraftKey, ut as readStoredRecentDirectories, v as RIGHT_SIDEBAR_HISTORY_TAB_STORAGE_KEY, vt as safeLocalStorageGetItem, w as SIDEBAR_DIRECTORIES_STORAGE_KEY, wt as themeFamilyFixedMode, x as Route, xt as sessionListEntryKey, y as RIGHT_SIDEBAR_OPEN_STORAGE_KEY, yt as safeLocalStorageSetItem, z as cn } from "./routes-D3Hu5M6D.mjs";
6
6
  import { i as useQuery, n as useIsMutating, o as useQueryClient, r as useIsFetching, t as useMutation } from "../_libs/tanstack__react-query.mjs";
7
7
  import { t as useHotkeys } from "../_libs/tanstack__react-hotkeys.mjs";
8
8
  import { a as matchesKeyboardEvent, i as batch, o as formatForDisplay, r as createStore } from "../_libs/@tanstack/hotkeys+[...].mjs";
@@ -22,7 +22,7 @@ import { t as remarkGfm } from "../_libs/remark-gfm.mjs";
22
22
  import { a as getBuiltInSpriteSheet, i as getBuiltInFileIconColor, n as FileTree, r as createFileTreeIconResolver, t as useFileTree } from "../_libs/@pierre/trees+[...].mjs";
23
23
  import { a as closestCenter, c as useDraggable, d as useSensors, f as CSS$1, i as PointerSensor, n as DragOverlay, t as DndContext, u as useSensor } from "../_libs/@dnd-kit/core+[...].mjs";
24
24
  import { a as verticalListSortingStrategy, i as useSortable, n as arrayMove, r as horizontalListSortingStrategy, t as SortableContext } from "../_libs/dnd-kit__sortable.mjs";
25
- //#region node_modules/.nitro/vite/services/ssr/assets/routes-CELGJtcT.js
25
+ //#region node_modules/.nitro/vite/services/ssr/assets/routes-DGf2MDLT.js
26
26
  var import_react = /* @__PURE__ */ __toESM(require_react());
27
27
  var import_jsx_runtime = require_jsx_runtime();
28
28
  var MOBILE_BREAKPOINT = 768;
@@ -75,7 +75,7 @@ function parseCssLengthToPixels$1(value, fallback) {
75
75
  if (trimmedValue.endsWith("rem")) return numericValue * (typeof window === "undefined" ? 16 : Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize) || 16);
76
76
  return numericValue;
77
77
  }
78
- function clamp(value, min, max) {
78
+ function clamp$1(value, min, max) {
79
79
  return Math.min(Math.max(value, min), max);
80
80
  }
81
81
  function getResizeSide(element) {
@@ -216,7 +216,7 @@ function useSidebarResize({ enabled = true, expandThreshold = SIDEBAR_EXPAND_DIS
216
216
  collapseSidebar(pointerEvent.clientX);
217
217
  return;
218
218
  }
219
- const nextWidth = clamp(attemptedWidth, minWidthPx, maxWidthPx);
219
+ const nextWidth = clamp$1(attemptedWidth, minWidthPx, maxWidthPx);
220
220
  previewSidebarWidth(dragState, `${Math.round(nextWidth)}px`);
221
221
  };
222
222
  const handlePointerUp = (pointerEvent) => {
@@ -319,7 +319,7 @@ function SheetContent({ className, children, side = "right", showCloseButton = t
319
319
  "data-side": side,
320
320
  className: cn("fixed z-50 flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-ending-style:opacity-0 data-starting-style:opacity-0 data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm", className),
321
321
  ...props,
322
- children: [children, showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogClose, {
322
+ children: [children, showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogClose$1, {
323
323
  "data-slot": "sheet-close",
324
324
  render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
325
325
  variant: "ghost",
@@ -813,6 +813,12 @@ function DialogPortal({ ...props }) {
813
813
  ...props
814
814
  });
815
815
  }
816
+ function DialogClose({ ...props }) {
817
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogClose$1, {
818
+ "data-slot": "dialog-close",
819
+ ...props
820
+ });
821
+ }
816
822
  function DialogOverlay({ className, ...props }) {
817
823
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogBackdrop, {
818
824
  "data-slot": "dialog-overlay",
@@ -825,7 +831,7 @@ function DialogContent({ className, children, showCloseButton = true, ...props }
825
831
  "data-slot": "dialog-content",
826
832
  className: cn("fixed top-1/2 left-1/2 z-50 grid max-h-dvh w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 overflow-y-auto rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-h-[80vh] sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
827
833
  ...props,
828
- children: [children, showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogClose, {
834
+ children: [children, showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogClose$1, {
829
835
  "data-slot": "dialog-close",
830
836
  render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
831
837
  variant: "ghost",
@@ -851,7 +857,7 @@ function DialogFooter({ className, showCloseButton = false, children, ...props }
851
857
  "data-slot": "dialog-footer",
852
858
  className: cn("-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 sm:flex-row sm:justify-end", className),
853
859
  ...props,
854
- children: [children, showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogClose, {
860
+ children: [children, showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogClose$1, {
855
861
  render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, { variant: "outline" }),
856
862
  children: "Close"
857
863
  })]
@@ -1000,13 +1006,13 @@ function dispatchDrawerClosedEvent() {
1000
1006
  window.dispatchEvent(new CustomEvent(PICO_DIALOG_CLOSED_EVENT));
1001
1007
  }, 160);
1002
1008
  }
1003
- function Drawer$1({ shouldScaleBackground = false, open, ...props }) {
1009
+ function Drawer$1({ restorePromptFocusOnClose = true, shouldScaleBackground = false, open, ...props }) {
1004
1010
  const wasOpenRef = import_react.useRef(open === true);
1005
1011
  import_react.useLayoutEffect(() => {
1006
1012
  const nextOpen = open === true;
1007
- if (!nextOpen && wasOpenRef.current) dispatchDrawerClosedEvent();
1013
+ if (!nextOpen && wasOpenRef.current && restorePromptFocusOnClose) dispatchDrawerClosedEvent();
1008
1014
  wasOpenRef.current = nextOpen;
1009
- }, [open]);
1015
+ }, [open, restorePromptFocusOnClose]);
1010
1016
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Drawer.Root, {
1011
1017
  "data-slot": "drawer",
1012
1018
  shouldScaleBackground,
@@ -2851,7 +2857,7 @@ function useAppShellSessionsDialogView({ open, onOpenChange, viewerContextId, cu
2851
2857
  children: [loading && sortedSessionItems.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CommandItem, {
2852
2858
  value: "loading:sessions",
2853
2859
  disabled: true,
2854
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { className: "size-3.5 text-primary" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2860
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { className: "text-primary" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2855
2861
  className: "text-muted-foreground",
2856
2862
  children: "Loading sessions…"
2857
2863
  })]
@@ -2869,7 +2875,7 @@ function useAppShellSessionsDialogView({ open, onOpenChange, viewerContextId, cu
2869
2875
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2870
2876
  className: "mt-0.5 flex size-4 shrink-0 items-center justify-center",
2871
2877
  children: entry.streaming ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
2872
- className: "size-3.5 text-primary",
2878
+ className: "text-primary",
2873
2879
  "aria-label": "Session streaming"
2874
2880
  }) : showUnread ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2875
2881
  className: "size-2 rounded-full bg-primary",
@@ -4639,7 +4645,8 @@ function useTreeBrowsePanelView({ isMobile, treeFilterMode, onTreeFilterModeChan
4639
4645
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
4640
4646
  className: "flex h-6 w-2.5 items-center justify-center",
4641
4647
  children: node.streaming || node.id === treeStreamingEntryId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
4642
- className: "size-3 text-[var(--success)]",
4648
+ size: "xs",
4649
+ className: "text-[var(--success)]",
4643
4650
  "aria-label": "Streaming"
4644
4651
  }) : node.isActivePath ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TreeHierarchyIcon, {
4645
4652
  name: "active-path",
@@ -10325,6 +10332,234 @@ var MarkdownBlock = import_react.memo(function MarkdownBlock({ streaming = false
10325
10332
  })
10326
10333
  });
10327
10334
  });
10335
+ var minScale = 1;
10336
+ var maxScale = 5;
10337
+ var initialTransform = {
10338
+ scale: 1,
10339
+ x: 0,
10340
+ y: 0
10341
+ };
10342
+ function clamp(value, min, max) {
10343
+ return Math.min(max, Math.max(min, value));
10344
+ }
10345
+ function getDistance(first, second) {
10346
+ return Math.hypot(first.x - second.x, first.y - second.y);
10347
+ }
10348
+ function getMidpoint(first, second) {
10349
+ return {
10350
+ x: (first.x + second.x) / 2,
10351
+ y: (first.y + second.y) / 2
10352
+ };
10353
+ }
10354
+ function ImageLightbox({ open, onOpenChange, imageSrc, imageAlt, title, description, emptyState, className }) {
10355
+ const containerRef = import_react.useRef(null);
10356
+ const imageRef = import_react.useRef(null);
10357
+ const activePointersRef = import_react.useRef(/* @__PURE__ */ new Map());
10358
+ const clickStartedOnBackdropRef = import_react.useRef(false);
10359
+ const gestureRef = import_react.useRef(null);
10360
+ const transformRef = import_react.useRef(initialTransform);
10361
+ const [transform, setTransform] = import_react.useState(initialTransform);
10362
+ import_react.useEffect(() => {
10363
+ activePointersRef.current.clear();
10364
+ gestureRef.current = null;
10365
+ transformRef.current = initialTransform;
10366
+ setTransform(initialTransform);
10367
+ }, [imageSrc, open]);
10368
+ function getPointFromEvent(event) {
10369
+ return {
10370
+ x: event.clientX,
10371
+ y: event.clientY
10372
+ };
10373
+ }
10374
+ function getPointRelativeToCenter(point) {
10375
+ const container = containerRef.current;
10376
+ if (!container) return point;
10377
+ const rect = container.getBoundingClientRect();
10378
+ return {
10379
+ x: point.x - rect.left - rect.width / 2,
10380
+ y: point.y - rect.top - rect.height / 2
10381
+ };
10382
+ }
10383
+ function clampTransform(nextTransform) {
10384
+ const nextScale = clamp(nextTransform.scale, minScale, maxScale);
10385
+ if (nextScale <= minScale) return initialTransform;
10386
+ const container = containerRef.current;
10387
+ const image = imageRef.current;
10388
+ if (!container || !image) return {
10389
+ scale: nextScale,
10390
+ x: nextTransform.x,
10391
+ y: nextTransform.y
10392
+ };
10393
+ const maxX = Math.max(0, (image.offsetWidth * nextScale - container.clientWidth) / 2);
10394
+ const maxY = Math.max(0, (image.offsetHeight * nextScale - container.clientHeight) / 2);
10395
+ return {
10396
+ scale: nextScale,
10397
+ x: clamp(nextTransform.x, -maxX, maxX),
10398
+ y: clamp(nextTransform.y, -maxY, maxY)
10399
+ };
10400
+ }
10401
+ function updateTransform(nextTransform) {
10402
+ const clampedTransform = clampTransform(nextTransform);
10403
+ transformRef.current = clampedTransform;
10404
+ setTransform(clampedTransform);
10405
+ }
10406
+ function zoomAroundPoint(nextScale, screenPoint) {
10407
+ const currentTransform = transformRef.current;
10408
+ const relativePoint = getPointRelativeToCenter(screenPoint);
10409
+ const clampedScale = clamp(nextScale, minScale, maxScale);
10410
+ if (clampedScale <= minScale) {
10411
+ updateTransform(initialTransform);
10412
+ return;
10413
+ }
10414
+ const imagePoint = {
10415
+ x: (relativePoint.x - currentTransform.x) / currentTransform.scale,
10416
+ y: (relativePoint.y - currentTransform.y) / currentTransform.scale
10417
+ };
10418
+ updateTransform({
10419
+ scale: clampedScale,
10420
+ x: relativePoint.x - imagePoint.x * clampedScale,
10421
+ y: relativePoint.y - imagePoint.y * clampedScale
10422
+ });
10423
+ }
10424
+ function startPinchGesture() {
10425
+ const pointers = [...activePointersRef.current.values()];
10426
+ const firstPointer = pointers[0];
10427
+ const secondPointer = pointers[1];
10428
+ if (!firstPointer || !secondPointer) return;
10429
+ gestureRef.current = {
10430
+ type: "pinch",
10431
+ startDistance: getDistance(firstPointer, secondPointer),
10432
+ startMidpoint: getMidpoint(firstPointer, secondPointer),
10433
+ startTransform: transformRef.current
10434
+ };
10435
+ }
10436
+ function startPanGesture(pointerId, point) {
10437
+ gestureRef.current = {
10438
+ type: "pan",
10439
+ pointerId,
10440
+ startPoint: point,
10441
+ startTransform: transformRef.current
10442
+ };
10443
+ }
10444
+ function finishPointer(pointerId) {
10445
+ activePointersRef.current.delete(pointerId);
10446
+ const remainingPointer = [...activePointersRef.current.entries()][0];
10447
+ if (activePointersRef.current.size >= 2) startPinchGesture();
10448
+ else if (remainingPointer) startPanGesture(remainingPointer[0], remainingPointer[1]);
10449
+ else gestureRef.current = null;
10450
+ }
10451
+ function handlePointerDown(event) {
10452
+ clickStartedOnBackdropRef.current = event.target === event.currentTarget;
10453
+ if (!imageSrc) return;
10454
+ event.currentTarget.setPointerCapture(event.pointerId);
10455
+ const point = getPointFromEvent(event);
10456
+ activePointersRef.current.set(event.pointerId, point);
10457
+ if (activePointersRef.current.size >= 2) startPinchGesture();
10458
+ else startPanGesture(event.pointerId, point);
10459
+ }
10460
+ function handlePointerMove(event) {
10461
+ if (!activePointersRef.current.has(event.pointerId)) return;
10462
+ const point = getPointFromEvent(event);
10463
+ activePointersRef.current.set(event.pointerId, point);
10464
+ const gesture = gestureRef.current;
10465
+ const pointers = [...activePointersRef.current.values()];
10466
+ if (gesture?.type === "pinch" && pointers.length >= 2) {
10467
+ const firstPointer = pointers[0];
10468
+ const secondPointer = pointers[1];
10469
+ if (!firstPointer || !secondPointer || gesture.startDistance <= 0) return;
10470
+ const nextDistance = getDistance(firstPointer, secondPointer);
10471
+ const nextMidpoint = getMidpoint(firstPointer, secondPointer);
10472
+ const nextScale = gesture.startTransform.scale * (nextDistance / gesture.startDistance);
10473
+ const startRelativeMidpoint = getPointRelativeToCenter(gesture.startMidpoint);
10474
+ const nextRelativeMidpoint = getPointRelativeToCenter(nextMidpoint);
10475
+ const imagePoint = {
10476
+ x: (startRelativeMidpoint.x - gesture.startTransform.x) / gesture.startTransform.scale,
10477
+ y: (startRelativeMidpoint.y - gesture.startTransform.y) / gesture.startTransform.scale
10478
+ };
10479
+ const clampedScale = clamp(nextScale, minScale, maxScale);
10480
+ updateTransform({
10481
+ scale: clampedScale,
10482
+ x: nextRelativeMidpoint.x - imagePoint.x * clampedScale,
10483
+ y: nextRelativeMidpoint.y - imagePoint.y * clampedScale
10484
+ });
10485
+ return;
10486
+ }
10487
+ if (gesture?.type === "pan" && gesture.pointerId === event.pointerId) updateTransform({
10488
+ scale: gesture.startTransform.scale,
10489
+ x: gesture.startTransform.x + point.x - gesture.startPoint.x,
10490
+ y: gesture.startTransform.y + point.y - gesture.startPoint.y
10491
+ });
10492
+ }
10493
+ function handleWheel(event) {
10494
+ if (!imageSrc) return;
10495
+ event.preventDefault();
10496
+ const scaleDelta = Math.exp(-event.deltaY * .0015);
10497
+ zoomAroundPoint(transformRef.current.scale * scaleDelta, getPointFromEvent(event));
10498
+ }
10499
+ function handleDoubleClick(event) {
10500
+ if (!imageSrc) return;
10501
+ if (transformRef.current.scale > minScale) updateTransform(initialTransform);
10502
+ else zoomAroundPoint(2, getPointFromEvent(event));
10503
+ }
10504
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Dialog$1, {
10505
+ open,
10506
+ onOpenChange,
10507
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogContent, {
10508
+ showCloseButton: false,
10509
+ className: cn("top-0 left-0 h-dvh max-h-dvh w-dvw max-w-none translate-x-0 translate-y-0 overflow-hidden rounded-none bg-transparent p-0 shadow-none ring-0 sm:max-h-dvh sm:max-w-none dark:ring-0", className),
10510
+ children: [
10511
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, {
10512
+ className: "sr-only",
10513
+ children: title
10514
+ }),
10515
+ description ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription, {
10516
+ className: "sr-only",
10517
+ children: description
10518
+ }) : null,
10519
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
10520
+ className: "absolute top-4 right-4 z-10 flex items-center gap-2",
10521
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogClose, {
10522
+ render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
10523
+ variant: "ghost",
10524
+ size: "icon",
10525
+ className: "border border-white/15 bg-black/55 text-white hover:bg-black/80 hover:text-white"
10526
+ }),
10527
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
10528
+ className: "sr-only",
10529
+ children: "Close"
10530
+ })]
10531
+ })
10532
+ }),
10533
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
10534
+ ref: containerRef,
10535
+ className: "flex h-full w-full touch-none items-center justify-center overflow-hidden p-4",
10536
+ onPointerDown: handlePointerDown,
10537
+ onPointerMove: handlePointerMove,
10538
+ onPointerUp: (event) => finishPointer(event.pointerId),
10539
+ onPointerCancel: (event) => finishPointer(event.pointerId),
10540
+ onLostPointerCapture: (event) => finishPointer(event.pointerId),
10541
+ onWheel: handleWheel,
10542
+ onDoubleClick: handleDoubleClick,
10543
+ onClick: (event) => {
10544
+ if (clickStartedOnBackdropRef.current && event.target === event.currentTarget) onOpenChange(false);
10545
+ clickStartedOnBackdropRef.current = false;
10546
+ },
10547
+ children: imageSrc ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
10548
+ ref: imageRef,
10549
+ src: imageSrc,
10550
+ alt: imageAlt,
10551
+ draggable: false,
10552
+ className: "block max-h-full max-w-full cursor-grab object-contain active:cursor-grabbing",
10553
+ style: { transform: `translate3d(${transform.x}px, ${transform.y}px, 0) scale(${transform.scale})` }
10554
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
10555
+ className: "rounded-3xl border border-dashed border-border/70 bg-background/95 px-6 py-10 text-sm text-muted-foreground",
10556
+ children: emptyState || "Unable to load the image preview."
10557
+ })
10558
+ })
10559
+ ]
10560
+ })
10561
+ });
10562
+ }
10328
10563
  var PICO_DIFF_THEME_PAIR = {
10329
10564
  light: PICO_DIFF_SHIKI_THEMES.light,
10330
10565
  dark: PICO_DIFF_SHIKI_THEMES.dark
@@ -11767,9 +12002,11 @@ var CompactionBlockCard = import_react.memo(function CompactionBlockCard({ block
11767
12002
  });
11768
12003
  var UserMessageCard = import_react.memo(function UserMessageCard({ item }) {
11769
12004
  const labelText = userMessageLabel(item);
11770
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
12005
+ const [selectedImageIndex, setSelectedImageIndex] = import_react.useState(null);
12006
+ const selectedImage = selectedImageIndex === null ? null : item.images[selectedImageIndex] ?? null;
12007
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
11771
12008
  className: "mr-2 ml-auto w-fit max-w-[80%]",
11772
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
12009
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
11773
12010
  className: "relative rounded-3xl bg-primary px-5 py-2.5 text-primary-foreground before:absolute before:-right-1.75 before:bottom-0 before:h-5.5 before:w-4 before:rounded-bl-[16px_14px] before:bg-primary before:content-[''] after:absolute after:-right-6.5 after:bottom-0 after:h-6.25 after:w-6.5 after:rounded-bl-[10px] after:bg-background after:content-['']",
11774
12011
  children: [
11775
12012
  labelText ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
@@ -11789,14 +12026,31 @@ var UserMessageCard = import_react.memo(function UserMessageCard({ item }) {
11789
12026
  }),
11790
12027
  item.images.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
11791
12028
  className: "mt-3 flex flex-wrap gap-3",
11792
- children: item.images.map((image) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
11793
- src: image.previewUrl,
11794
- alt: "Prompt upload",
11795
- className: "h-28 rounded-lg border object-cover"
11796
- }, promptImageKey(image)))
12029
+ children: item.images.map((image, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
12030
+ type: "button",
12031
+ className: "max-w-full cursor-zoom-in overflow-hidden rounded-lg border border-primary-foreground/20 bg-primary-foreground/10 p-0 transition hover:opacity-90 focus-visible:ring-2 focus-visible:ring-primary-foreground/70 focus-visible:ring-offset-2 focus-visible:ring-offset-primary focus-visible:outline-none",
12032
+ onClick: () => setSelectedImageIndex(index),
12033
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", {
12034
+ src: image.previewUrl,
12035
+ alt: "Prompt upload",
12036
+ className: "block h-28 max-w-full object-cover"
12037
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
12038
+ className: "sr-only",
12039
+ children: "Open prompt upload"
12040
+ })]
12041
+ }, `${promptImageKey(image)}:${index}`))
11797
12042
  }) : null
11798
12043
  ]
11799
- })
12044
+ }), selectedImage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageLightbox, {
12045
+ open: true,
12046
+ onOpenChange: (open) => {
12047
+ if (!open) setSelectedImageIndex(null);
12048
+ },
12049
+ imageSrc: selectedImage.previewUrl,
12050
+ imageAlt: "Prompt upload",
12051
+ title: "Prompt upload preview",
12052
+ description: "Expanded preview of an image attached to a user message."
12053
+ }) : null]
11800
12054
  });
11801
12055
  });
11802
12056
  function assistantBlockIsVisible({ block, hideThinking, hideToolBlocks }) {
@@ -13178,7 +13432,10 @@ function NewSessionComposerSelectors({ cwd, defaultNewSessionDirectory, director
13178
13432
  className: "truncate",
13179
13433
  children: branchLabel
13180
13434
  }),
13181
- checkoutBranchMutation.isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { className: "size-4 shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, {
13435
+ checkoutBranchMutation.isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
13436
+ size: "md",
13437
+ className: "shrink-0"
13438
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, {
13182
13439
  className: "size-5 shrink-0",
13183
13440
  "aria-hidden": "true"
13184
13441
  })
@@ -14891,7 +15148,7 @@ function ProjectFileIconSprite() {
14891
15148
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
14892
15149
  ref: installTrustedFileIconSprite,
14893
15150
  "aria-hidden": "true",
14894
- className: "pointer-events-none block size-0 overflow-hidden"
15151
+ className: "pointer-events-none absolute size-0 overflow-hidden"
14895
15152
  });
14896
15153
  }
14897
15154
  function ProjectFileTypeIcon({ path }) {
@@ -15314,6 +15571,7 @@ function ProjectOpenFileDialog({ open, onOpenChange, paths, onOpenFile }) {
15314
15571
  if (isMobile) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Drawer$1, {
15315
15572
  open,
15316
15573
  onOpenChange,
15574
+ restorePromptFocusOnClose: false,
15317
15575
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerContent, {
15318
15576
  className: "max-h-[90svh] overflow-hidden",
15319
15577
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DrawerHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DrawerTitle, { children: "Open Files" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DrawerDescription, { children: "Search project files to open." })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
@@ -15601,9 +15859,9 @@ function CommitDiffViewerTabOverlay({ active, tab }) {
15601
15859
  tabCount: 1
15602
15860
  });
15603
15861
  }
15604
- function RightSidebarTabStrip({ activeCommitDiffKey = "", activeFilePath, activeTab, commitDiffTabs = EMPTY_COMMIT_DIFF_TABS, filePreviewPath = "", fileTabs = EMPTY_RIGHT_SIDEBAR_FILE_TABS$1, onActiveCommitDiffChange, onActiveFileChange, onActiveTabChange, onCloseAllCommitDiffs, onCloseAllFiles, onCloseCommitDiff, onCloseCommitDiffsToRight, onCloseFile, onCloseFilesToRight, onCloseOtherCommitDiffs, onCloseOtherFiles, onOpenFileDialog, onReorderCommitDiffs, onReorderFiles, showHistory = false, showReview = false }) {
15605
- const renderTab = ({ label, value }) => {
15606
- const active = activeTab === value;
15862
+ function RightSidebarTabStrip({ activeCommitDiffKey = "", activeFilePath, activeTab, commitDiffTabs = EMPTY_COMMIT_DIFF_TABS, filePreviewPath = "", fileTabs = EMPTY_RIGHT_SIDEBAR_FILE_TABS$1, onActiveCommitDiffChange, onActiveFileChange, onActiveTabChange, onCloseAllCommitDiffs, onCloseAllFiles, onCloseCommitDiff, onCloseCommitDiffsToRight, onCloseFile, onCloseFilesToRight, onCloseOtherCommitDiffs, onCloseOtherFiles, onOpenFileDialog, onReorderCommitDiffs, onReorderFiles, showFiles = false, showHistory = false, showReview = false }) {
15863
+ const renderTab = ({ active: activeOverride, label, value }) => {
15864
+ const active = activeOverride ?? activeTab === value;
15607
15865
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
15608
15866
  type: "button",
15609
15867
  "aria-pressed": active,
@@ -15675,7 +15933,8 @@ function RightSidebarTabStrip({ activeCommitDiffKey = "", activeFilePath, active
15675
15933
  label: "History",
15676
15934
  value: "history"
15677
15935
  }) : null,
15678
- !hasOpenFiles ? renderTab({
15936
+ !hasOpenFiles || showFiles ? renderTab({
15937
+ active: activeTab === "files" && (!hasOpenFiles || !activeFilePath),
15679
15938
  label: "Files",
15680
15939
  value: "files"
15681
15940
  }) : null,
@@ -15999,7 +16258,7 @@ function GitBranchLocalGroup({ branches, branchesPending, checkoutPending, onSwi
15999
16258
  children: [branchesPending && branches.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CommandItem, {
16000
16259
  value: "loading:branches",
16001
16260
  disabled: true,
16002
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { className: "size-3.5 text-primary" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
16261
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { className: "text-primary" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
16003
16262
  className: "text-muted-foreground",
16004
16263
  children: "Loading branches…"
16005
16264
  })]
@@ -16552,7 +16811,10 @@ function GitPanelToolbar({ viewerContextId, cwd, active }) {
16552
16811
  onBranchClick: () => {
16553
16812
  setBranchDialogOpen(true);
16554
16813
  }
16555
- }), active && refreshing ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { className: "size-3 shrink-0 text-primary" }) : null]
16814
+ }), active && refreshing ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
16815
+ size: "xs",
16816
+ className: "shrink-0 text-primary"
16817
+ }) : null]
16556
16818
  }),
16557
16819
  showCommitAction || showPushAction || showForcePushAction || showPullAction ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
16558
16820
  className: "flex flex-wrap items-center justify-end gap-2",
@@ -16695,7 +16957,7 @@ function AlertDialogAction({ className, ...props }) {
16695
16957
  });
16696
16958
  }
16697
16959
  function AlertDialogCancel({ className, variant = "outline", size = "default", ...props }) {
16698
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogClose, {
16960
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogClose$1, {
16699
16961
  "data-slot": "alert-dialog-cancel",
16700
16962
  className: cn(className),
16701
16963
  render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
@@ -17128,7 +17390,7 @@ function GitCommitActionsMenu({ disabled, busy, canCopyMessage, onViewDiff, onCo
17128
17390
  "aria-label": "Commit actions",
17129
17391
  disabled: disabled || busy
17130
17392
  }),
17131
- children: busy ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { className: "size-3" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Ellipsis, {})
17393
+ children: busy ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: "xs" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Ellipsis, {})
17132
17394
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownMenuContent, {
17133
17395
  align: "end",
17134
17396
  className: "w-64",
@@ -18122,7 +18384,7 @@ function GitCommitsSection({ viewerContextId, cwd, active, onOpenCommitDiff, onR
18122
18384
  role: "status",
18123
18385
  "aria-label": "Loading more commits",
18124
18386
  className: "inline-flex items-center gap-2 px-1 text-xs text-muted-foreground",
18125
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { className: "size-3" }), "Loading more commits…"]
18387
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: "xs" }), "Loading more commits…"]
18126
18388
  }) : null
18127
18389
  }) : null]
18128
18390
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GitSectionNote, {
@@ -19585,9 +19847,9 @@ function RightSidebar({ viewerContextId, cwd, active, activeFilePath = "", activ
19585
19847
  setHistoryAsTabState(value);
19586
19848
  storeHistoryAsTab(value);
19587
19849
  };
19588
- const previewMode = isMobile ? "inline" : "external";
19850
+ const previewMode = "external";
19589
19851
  const panelHasCardChrome = showToolbar && !isMobile;
19590
- const currentFilePath = previewMode === "inline" ? localState.inlineActiveFilePath : activeFilePath;
19852
+ const currentFilePath = activeFilePath;
19591
19853
  const hasOpenFileTabs = fileTabs.length > 0;
19592
19854
  const activeCommitDiffTab = localState.commitDiffTabs.find((tab) => tab.key === localState.activeCommitDiffKey) ?? localState.commitDiffTabs[0];
19593
19855
  const fileDialogPaths = useQuery({
@@ -19602,13 +19864,6 @@ function RightSidebar({ viewerContextId, cwd, active, activeFilePath = "", activ
19602
19864
  const openFile = (path, options) => {
19603
19865
  if (!path) return;
19604
19866
  setActiveTab("files");
19605
- if (previewMode === "inline") {
19606
- dispatchLocal({
19607
- type: "set-inline-active-file",
19608
- path
19609
- });
19610
- return;
19611
- }
19612
19867
  onOpenFile?.(path, options);
19613
19868
  onActiveFileChange?.(path);
19614
19869
  };
@@ -19654,6 +19909,10 @@ function RightSidebar({ viewerContextId, cwd, active, activeFilePath = "", activ
19654
19909
  keys
19655
19910
  });
19656
19911
  };
19912
+ const handleTabStripActiveTabChange = (tab) => {
19913
+ if (isMobile && tab === "files") onActiveFileChange?.("");
19914
+ setActiveTab(tab);
19915
+ };
19657
19916
  import_react.useEffect(() => {
19658
19917
  dispatchLocal({
19659
19918
  type: "reset-navigation",
@@ -19686,7 +19945,7 @@ function RightSidebar({ viewerContextId, cwd, active, activeFilePath = "", activ
19686
19945
  key
19687
19946
  }),
19688
19947
  onActiveFileChange,
19689
- onActiveTabChange: setActiveTab,
19948
+ onActiveTabChange: handleTabStripActiveTabChange,
19690
19949
  onCloseAllCommitDiffs: closeAllCommitDiffs,
19691
19950
  onCloseAllFiles,
19692
19951
  onCloseCommitDiff: closeCommitDiff,
@@ -19703,6 +19962,7 @@ function RightSidebar({ viewerContextId, cwd, active, activeFilePath = "", activ
19703
19962
  },
19704
19963
  onReorderCommitDiffs: reorderCommitDiffs,
19705
19964
  onReorderFiles,
19965
+ showFiles: isMobile && hasOpenFileTabs,
19706
19966
  showHistory: historyAsTab,
19707
19967
  showReview: true
19708
19968
  }),
@@ -19750,7 +20010,25 @@ function RightSidebar({ viewerContextId, cwd, active, activeFilePath = "", activ
19750
20010
  }),
19751
20011
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
19752
20012
  className: activeTab === "files" ? "min-h-0 flex-1 overflow-hidden" : "hidden",
19753
- children: previewMode === "external" && hasOpenFileTabs ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20013
+ children: isMobile ? currentFilePath ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20014
+ className: "flex h-full min-h-0 min-w-0 flex-col overflow-hidden",
20015
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FilePathBreadcrumb, { path: currentFilePath }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
20016
+ className: "min-h-0 min-w-0 flex-1 overflow-hidden",
20017
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectFileContent, {
20018
+ viewerContextId,
20019
+ cwd: normalizedCwd,
20020
+ active: active && activeTab === "files",
20021
+ path: currentFilePath
20022
+ })
20023
+ })]
20024
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProjectFilesWorkspace, {
20025
+ viewerContextId,
20026
+ cwd: normalizedCwd,
20027
+ active: active && activeTab === "files",
20028
+ activeFilePath: currentFilePath,
20029
+ onOpenFile: openFile,
20030
+ previewMode
20031
+ }) : hasOpenFileTabs ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
19754
20032
  className: "flex h-full min-h-0 min-w-0 flex-col overflow-hidden",
19755
20033
  children: [currentFilePath ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FilePathBreadcrumb, {
19756
20034
  path: currentFilePath,
@@ -19780,12 +20058,6 @@ function RightSidebar({ viewerContextId, cwd, active, activeFilePath = "", activ
19780
20058
  cwd: normalizedCwd,
19781
20059
  active: active && activeTab === "files",
19782
20060
  activeFilePath: currentFilePath,
19783
- onCloseFile: () => {
19784
- dispatchLocal({
19785
- type: "set-inline-active-file",
19786
- path: ""
19787
- });
19788
- },
19789
20061
  onOpenFile: openFile,
19790
20062
  previewMode
19791
20063
  })
@@ -20410,7 +20682,7 @@ var AppShellSessionHeader = import_react.memo(function AppShellSessionHeader({ a
20410
20682
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
20411
20683
  className: "flex max-w-full min-w-0 items-center justify-center gap-1.5",
20412
20684
  children: [!isSessionViewLoading && sessionHeaderState.sessionStreaming ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
20413
- className: "size-3.5 shrink-0",
20685
+ className: "shrink-0",
20414
20686
  "aria-label": "Session streaming"
20415
20687
  }) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
20416
20688
  title: displaySessionTitle,
@@ -20903,10 +21175,7 @@ function SidebarSessionItem({ entryKey, directorySessionsStore, activeSessionSto
20903
21175
  },
20904
21176
  children: [entry.streaming ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20905
21177
  className: "absolute top-2.5 left-2 flex size-4 items-center justify-center",
20906
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {
20907
- className: "size-3.5",
20908
- "aria-label": "Session streaming"
20909
- })
21178
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { "aria-label": "Session streaming" })
20910
21179
  }) : showUnread ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
20911
21180
  className: "absolute top-2.5 left-2 flex size-4 items-center justify-center",
20912
21181
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
@@ -21083,7 +21352,7 @@ var DirectorySessionGroup = import_react.memo(function DirectorySessionGroup({ d
21083
21352
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DirectoryPathLabel, { path: directory })
21084
21353
  }),
21085
21354
  !searchActive && !overlay ? collapsed ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, { className: "size-4 shrink-0 opacity-0 transition-opacity group-hover/directory-label:opacity-100 group-focus-visible/directory-label:opacity-100" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, { className: "size-4 shrink-0 opacity-0 transition-opacity group-hover/directory-label:opacity-100 group-focus-visible/directory-label:opacity-100" }) : null,
21086
- showHeaderLoadingSpinner ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { className: "size-3.5 shrink-0" }) : null
21355
+ showHeaderLoadingSpinner ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { className: "shrink-0" }) : null
21087
21356
  ]
21088
21357
  }),
21089
21358
  onCreateSessionInDirectory && !overlay && !isMobile ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TitleTooltip, {
@@ -22648,6 +22917,7 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
22648
22917
  const awaitingFirstTurnAssistantOutputSignatureRef = import_react.useRef(null);
22649
22918
  const sessionSnapshot = usePromptMutationSessionSnapshot(sessionStore);
22650
22919
  const sessionStreamingRef = import_react.useRef(sessionSnapshot.streaming);
22920
+ const flushPendingDraftPromptRef = import_react.useRef(async () => false);
22651
22921
  import_react.useEffect(() => {
22652
22922
  draftSessionLoadingOwnerKeyRef.current = draftSessionLoadingOwnerKey;
22653
22923
  }, [draftSessionLoadingOwnerKey]);
@@ -22794,6 +23064,11 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
22794
23064
  setDraftSessionLoadingOwnerKey(ownerKey);
22795
23065
  try {
22796
23066
  await createSessionRequest({ cwd: nextCwd });
23067
+ if (draftSessionLoadingOwnerKeyRef.current === ownerKey) {
23068
+ draftSessionLoadingOwnerKeyRef.current = null;
23069
+ setDraftSessionLoadingOwnerKey((current) => current === ownerKey ? null : current);
23070
+ }
23071
+ if (pendingDraftPromptRef.current?.ownerKey === ownerKey) flushPendingDraftPromptRef.current(ownerKey);
22797
23072
  return true;
22798
23073
  } catch (error) {
22799
23074
  if (draftSessionLoadingOwnerKeyRef.current === ownerKey) draftSessionLoadingOwnerKeyRef.current = null;
@@ -23059,6 +23334,7 @@ function useAppShellPromptMutations({ viewerContextId, activeSessionId, defaultN
23059
23334
  setPendingDraftPrompt,
23060
23335
  submitPrompt
23061
23336
  ]);
23337
+ flushPendingDraftPromptRef.current = flushPendingDraftPrompt;
23062
23338
  import_react.useEffect(() => {
23063
23339
  if (!draftSessionLoadingOwnerKey) return;
23064
23340
  const currentSessionState = sessionStateRef.current;
@@ -25272,7 +25548,11 @@ function useAppShellSessionWorkspaceView({ viewerContextId, sessionId, onSelectS
25272
25548
  if (!path) return;
25273
25549
  batch(() => {
25274
25550
  setGitPanelOpen(true);
25275
- openRightSidebarFile(rightSidebarStore, path, options);
25551
+ if (isMobile) setCurrentTab("git");
25552
+ openRightSidebarFile(rightSidebarStore, path, {
25553
+ ...options,
25554
+ pin: isMobile || options?.pin
25555
+ });
25276
25556
  });
25277
25557
  };
25278
25558
  const closeFileViewTab = (path) => {