@particle-academy/react-fancy 5.46.0 → 5.48.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/CHANGELOG.md CHANGED
@@ -11,6 +11,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [5.48.0] - 2026-10-19
15
+
16
+ ### Added
17
+
18
+ - **Tab completes in `PromptInput`'s `/` and `@` menus**, as Enter does: the
19
+ highlighted command or mention goes in. Only while a menu is open; with no
20
+ menu, Tab moves focus as before. **Nothing to do.**
21
+
22
+ ## [5.47.0] - 2026-10-19
23
+
24
+ ### Added
25
+
26
+ - **`FauxClient` `applyZoom={false}`**: the frame shows the zoom controls and
27
+ keeps the zoom state, but leaves the zooming to the content. A viewer that
28
+ fits itself to its box (a slide viewer) only re-fits under a scaled frame, so
29
+ it ended up the same size with its own buttons enlarged; it now reads the zoom
30
+ and magnifies itself. **Nothing to do:** it defaults to `true`.
31
+
14
32
  ## [5.46.0] - 2026-10-19
15
33
 
16
34
  ### Added
@@ -24,6 +24,7 @@ var FauxClient = react.forwardRef(
24
24
  maxZoom = 4,
25
25
  onFullscreenChange,
26
26
  fill = false,
27
+ applyZoom = true,
27
28
  className,
28
29
  barClassName,
29
30
  bodyClassName,
@@ -83,8 +84,9 @@ var FauxClient = react.forwardRef(
83
84
  };
84
85
  const isBrowser = variant === "browser";
85
86
  const isDevice = variant === "device";
86
- const effective = fit * zoom;
87
- const zoomed = zoom !== 1;
87
+ const appliedZoom = applyZoom ? zoom : 1;
88
+ const effective = fit * appliedZoom;
89
+ const zoomed = appliedZoom !== 1;
88
90
  const hasControls = showZoom || showFullscreen;
89
91
  const controlsBar = hasControls ? /* @__PURE__ */ jsxRuntime.jsxs(
90
92
  "div",
@@ -225,7 +227,7 @@ var FauxClient = react.forwardRef(
225
227
  {
226
228
  "data-react-fancy-faux-client-content": "",
227
229
  className: chunkZU5Q77OT_cjs.cn((fill || fullscreen) && "h-full"),
228
- style: zoomed ? { zoom: String(zoom) } : void 0,
230
+ style: zoomed ? { zoom: String(appliedZoom) } : void 0,
229
231
  children
230
232
  }
231
233
  )
@@ -278,5 +280,5 @@ function ExitFullscreenIcon() {
278
280
  }
279
281
 
280
282
  exports.FauxClient = FauxClient;
281
- //# sourceMappingURL=chunk-S3WWYBL4.cjs.map
282
- //# sourceMappingURL=chunk-S3WWYBL4.cjs.map
283
+ //# sourceMappingURL=chunk-DUOZSOSB.cjs.map
284
+ //# sourceMappingURL=chunk-DUOZSOSB.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/FauxClient/FauxClient.tsx"],"names":["forwardRef","useRef","useState","useControllableState","useLayoutEffect","useEffect","useCallback","jsxs","cn","Fragment","jsx"],"mappings":"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","file":"chunk-DUOZSOSB.cjs","sourcesContent":["import { forwardRef, useCallback, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useControllableState } from \"../../hooks/use-controllable-state\";\nimport type { FauxClientProps } from \"./FauxClient.types\";\n\nconst DOT_COLORS = [\"bg-rose-300\", \"bg-amber-300\", \"bg-green-300\"];\n\n/** One click of the zoom bar. Matches `ImageViewer`, so the kit zooms one way. */\nconst ZOOM_STEP = 1.25;\n\nconst clamp = (n: number, min: number, max: number) => Math.min(max, Math.max(min, n));\n\n/**\n * A frame that mimics a browser window or device, rendering **real UI** inside.\n * With a logical `width` + `scale=\"fit\"` it renders a full-size page/app and\n * scales it down to fit any container (live thumbnails, device mockups) — the\n * content is real and interactive, just zoomed.\n *\n * Omit `width` for chrome around natural-size content (e.g. a code/preview card).\n *\n * `controls` adds a zoom bar and a full-screen button, for content that has to be\n * READ rather than glanced at: a slide or a sheet shrunk to fit a panel.\n */\nexport const FauxClient = forwardRef<HTMLDivElement, FauxClientProps>(\n (\n {\n variant = \"browser\",\n url,\n meta,\n dots = true,\n width,\n scale = \"fit\",\n controls = false,\n zoom: controlledZoom,\n defaultZoom = 1,\n onZoomChange,\n minZoom = 0.5,\n maxZoom = 4,\n onFullscreenChange,\n fill = false,\n applyZoom = true,\n className,\n barClassName,\n bodyClassName,\n children,\n ...rest\n },\n ref,\n ) => {\n const scaled = typeof width === \"number\";\n const rootRef = useRef<HTMLDivElement | null>(null);\n const viewportRef = useRef<HTMLDivElement>(null);\n const stageRef = useRef<HTMLDivElement>(null);\n const [fit, setFit] = useState(typeof scale === \"number\" ? scale : 1);\n const [naturalHeight, setNaturalHeight] = useState<number | undefined>(undefined);\n\n const showZoom = controls === true || (typeof controls === \"object\" && controls.zoom !== false);\n const showFullscreen = controls === true || (typeof controls === \"object\" && controls.fullscreen !== false);\n const [zoom, setZoom] = useControllableState(controlledZoom, defaultZoom, onZoomChange);\n const [fullscreen, setFullscreen] = useState(false);\n\n useLayoutEffect(() => {\n if (!scaled) return;\n const viewport = viewportRef.current;\n const stage = stageRef.current;\n if (!viewport || !stage) return;\n if (typeof ResizeObserver === \"undefined\") return;\n\n const measure = () => {\n const avail = viewport.clientWidth;\n setFit(scale === \"fit\" ? (width && width > 0 ? avail / width : 1) : scale);\n // offsetHeight is the pre-transform layout height (CSS transforms don't affect it).\n setNaturalHeight(stage.offsetHeight);\n };\n\n measure();\n const ro = new ResizeObserver(measure);\n ro.observe(viewport);\n ro.observe(stage);\n return () => ro.disconnect();\n }, [scaled, scale, width]);\n\n // Full screen is the browser's state, not ours: follow it, so Esc and the\n // browser's own exit leave the button telling the truth.\n useEffect(() => {\n if (!showFullscreen || typeof document === \"undefined\") return;\n const sync = () => {\n const on = document.fullscreenElement != null && document.fullscreenElement === rootRef.current;\n setFullscreen(on);\n onFullscreenChange?.(on);\n };\n document.addEventListener(\"fullscreenchange\", sync);\n return () => document.removeEventListener(\"fullscreenchange\", sync);\n }, [showFullscreen, onFullscreenChange]);\n\n const toggleFullscreen = useCallback(() => {\n const el = rootRef.current;\n if (!el || typeof document === \"undefined\") return;\n if (document.fullscreenElement === el) void document.exitFullscreen?.();\n else void el.requestFullscreen?.();\n }, []);\n\n const zoomBy = (factor: number) => {\n // Rounded so ten clicks in and ten out land back on 100%, not 99.99%.\n setZoom(clamp(Math.round(zoom * factor * 100) / 100, minZoom, maxZoom));\n };\n\n const setRefs = (el: HTMLDivElement | null) => {\n rootRef.current = el;\n if (typeof ref === \"function\") ref(el);\n else if (ref) ref.current = el;\n };\n\n const isBrowser = variant === \"browser\";\n const isDevice = variant === \"device\";\n // The zoom the FRAME applies: none when the content zooms itself.\n const appliedZoom = applyZoom ? zoom : 1;\n const effective = fit * appliedZoom;\n const zoomed = appliedZoom !== 1;\n const hasControls = showZoom || showFullscreen;\n\n /*\n * Out of the way until wanted: hidden, and revealed when the pointer is over\n * the frame or focus is inside it (keyboard). Always shown where there is no\n * hover to reveal it (touch), or it could never be reached.\n *\n * In the browser chrome it sits in the address bar, inline. On a device or a\n * bare frame there is no chrome, so it floats top-right as a slim strip: the\n * bottom corners belong to the content (a slide viewer's page count lives\n * there).\n */\n const controlsBar = hasControls ? (\n <div\n data-react-fancy-faux-client-controls=\"\"\n className={cn(\n \"pointer-events-auto flex shrink-0 items-center gap-px opacity-0 transition-opacity duration-150\",\n \"group-hover/faux-client:opacity-100 focus-within:opacity-100 [@media(hover:none)]:opacity-100\",\n isBrowser\n ? \"-my-1 text-zinc-400 dark:text-zinc-500\"\n : \"rounded-full bg-zinc-900/60 px-1 py-0.5 text-white/80 shadow-sm backdrop-blur-sm\",\n )}\n >\n {showZoom && (\n <>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-out=\"\"\n aria-label=\"Zoom out\"\n title=\"Zoom out\"\n disabled={zoom <= minZoom}\n onClick={() => zoomBy(1 / ZOOM_STEP)}\n className={controlButton(isBrowser)}\n >\n <ZoomOutIcon />\n </button>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-reset=\"\"\n aria-label=\"Reset zoom\"\n title=\"Reset zoom\"\n onClick={() => setZoom(1)}\n className={cn(controlButton(isBrowser), \"w-auto min-w-[2.25rem] px-1 font-sans text-[10.5px] tabular-nums\")}\n >\n {Math.round(zoom * 100)}%\n </button>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-in=\"\"\n aria-label=\"Zoom in\"\n title=\"Zoom in\"\n disabled={zoom >= maxZoom}\n onClick={() => zoomBy(ZOOM_STEP)}\n className={controlButton(isBrowser)}\n >\n <ZoomInIcon />\n </button>\n </>\n )}\n {showFullscreen && (\n <button\n type=\"button\"\n data-react-fancy-faux-client-fullscreen=\"\"\n aria-label={fullscreen ? \"Exit full screen\" : \"Full screen\"}\n aria-pressed={fullscreen}\n title={fullscreen ? \"Exit full screen\" : \"Full screen\"}\n onClick={toggleFullscreen}\n className={controlButton(isBrowser)}\n >\n {fullscreen ? <ExitFullscreenIcon /> : <FullscreenIcon />}\n </button>\n )}\n </div>\n ) : null;\n\n return (\n <div\n ref={setRefs}\n data-react-fancy-faux-client=\"\"\n data-fullscreen={showFullscreen ? String(fullscreen) : undefined}\n className={cn(\n \"group/faux-client relative overflow-hidden bg-white dark:bg-zinc-900\",\n isBrowser && \"rounded-2xl border border-zinc-200 shadow-xl dark:border-zinc-800\",\n isDevice && \"rounded-[2rem] border-[10px] border-zinc-800 shadow-2xl dark:border-zinc-700\",\n variant === \"bare\" && \"rounded-lg border border-zinc-200 dark:border-zinc-800\",\n // Fill (or full screen): the frame takes its parent's height and its\n // body takes whatever the chrome leaves.\n (fill || fullscreen) && \"flex flex-col\",\n fill && \"h-full\",\n fullscreen && \"rounded-none\",\n className,\n )}\n {...rest}\n >\n {isBrowser && (\n <div\n className={cn(\n \"flex items-center gap-2 border-b border-zinc-200 bg-zinc-50 px-3.5 py-2.5 font-mono text-[11.5px] text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-400\",\n barClassName,\n )}\n >\n {dots && (\n <div className=\"mr-1.5 flex gap-[5px]\">\n {DOT_COLORS.map((color, i) => (\n <span key={i} className={cn(\"h-[9px] w-[9px] rounded-full\", color)} />\n ))}\n </div>\n )}\n {url != null && <span className=\"min-w-0 flex-1 truncate\">{url}</span>}\n {meta != null && <span className=\"shrink-0 text-zinc-400 dark:text-zinc-500\">{meta}</span>}\n {hasControls && <div className={cn(url == null && meta == null && \"ml-auto\")}>{controlsBar}</div>}\n </div>\n )}\n\n <div\n ref={viewportRef}\n className={cn(\n \"relative\",\n // Zoomed in, the content is bigger than the frame: scroll to it.\n zoomed ? \"overflow-auto\" : \"overflow-hidden\",\n (fill || fullscreen) && \"min-h-0 flex-1\",\n bodyClassName,\n )}\n // The frame keeps its FIT height whatever the zoom; zooming scrolls.\n style={scaled && !fullscreen && naturalHeight !== undefined ? { height: naturalHeight * fit } : undefined}\n >\n {scaled ? (\n // A sizer the size of the zoomed content, so the scrollbars are right.\n <div\n style={\n naturalHeight !== undefined && width !== undefined\n ? { width: width * effective, height: naturalHeight * effective, position: \"relative\" }\n : undefined\n }\n >\n <div\n ref={stageRef}\n data-react-fancy-faux-client-content=\"\"\n className=\"absolute left-0 top-0 origin-top-left\"\n style={{ width, transform: `scale(${effective})` }}\n >\n {children}\n </div>\n </div>\n ) : (\n <div\n data-react-fancy-faux-client-content=\"\"\n className={cn((fill || fullscreen) && \"h-full\")}\n // CSS `zoom` rather than a transform: it changes layout size, so the\n // content reflows and the viewport scrolls to all of it.\n style={zoomed ? { zoom: String(appliedZoom) } : undefined}\n >\n {children}\n </div>\n )}\n </div>\n\n {hasControls && !isBrowser && (\n <div className=\"pointer-events-none absolute right-2 top-2 z-10\">{controlsBar}</div>\n )}\n </div>\n );\n },\n);\n\nFauxClient.displayName = \"FauxClient\";\n\n/** Ghost icon buttons: no box of their own, so the bar reads as part of the frame. */\nfunction controlButton(inBar: boolean): string {\n return cn(\n \"flex h-6 w-6 items-center justify-center rounded-full transition-colors disabled:pointer-events-none disabled:opacity-30\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50\",\n inBar\n ? \"hover:bg-zinc-900/5 hover:text-zinc-700 dark:hover:bg-white/10 dark:hover:text-zinc-200\"\n : \"hover:bg-white/15 hover:text-white\",\n );\n}\n\nfunction ZoomOutIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n <path d=\"M8 11h6\" />\n </svg>\n );\n}\n\nfunction ZoomInIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n <path d=\"M8 11h6\" />\n <path d=\"M11 8v6\" />\n </svg>\n );\n}\n\n/** Inline, like `Input`'s reveal icons: a frame should not need an icon set configured. */\nfunction FullscreenIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3\" />\n <path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" />\n <path d=\"M3 16v3a2 2 0 0 0 2 2h3\" />\n <path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" />\n </svg>\n );\n}\n\nfunction ExitFullscreenIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3\" />\n <path d=\"M21 8h-3a2 2 0 0 1-2-2V3\" />\n <path d=\"M3 16h3a2 2 0 0 1 2 2v3\" />\n <path d=\"M16 21v-3a2 2 0 0 1 2-2h3\" />\n </svg>\n );\n}\n"]}
@@ -190,7 +190,7 @@ function PromptInput({
190
190
  setPicker((p) => p ? { ...p, cursor: Math.max(0, p.cursor - 1) } : p);
191
191
  return;
192
192
  }
193
- if (e.key === "Enter" && !e.metaKey && !e.ctrlKey && items.length > 0) {
193
+ if ((e.key === "Enter" && !e.metaKey && !e.ctrlKey || e.key === "Tab" && !e.shiftKey) && items.length > 0) {
194
194
  e.preventDefault();
195
195
  insertChoice(picker.cursor);
196
196
  return;
@@ -481,5 +481,5 @@ function fmtSize(b) {
481
481
  }
482
482
 
483
483
  export { PromptInput, browserPlatformHints, detectPlatform, modifierKeyLabel };
484
- //# sourceMappingURL=chunk-JZCAMPIA.js.map
485
- //# sourceMappingURL=chunk-JZCAMPIA.js.map
484
+ //# sourceMappingURL=chunk-QSAYIYEB.js.map
485
+ //# sourceMappingURL=chunk-QSAYIYEB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/platform.ts","../src/components/PromptInput/PromptInput.tsx"],"names":[],"mappings":";;;;;;;;;AA2CA,IAAM,0CAA0B,IAAI,GAAA,CAAI,CAAC,OAAA,EAAS,KAAA,EAAO,QAAQ,CAAC,CAAA;AAOlE,IAAM,eAAA,GAAkB,4CAAA;AAGjB,SAAS,eAAe,KAAA,EAA6C;AAC1E,EAAA,IAAI,CAAC,OAAO,OAAO,SAAA;AAEnB,EAAA,MAAM,MAAA,GAAS,MAAM,aAAA,EAAe,QAAA;AACpC,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,CAAO,SAAS,CAAA,EAAG;AAInD,IAAA,OAAO,uBAAA,CAAwB,IAAI,MAAA,CAAO,IAAA,GAAO,WAAA,EAAa,IAAI,OAAA,GAAU,SAAA;AAAA,EAC9E;AAEA,EAAA,KAAA,MAAW,SAAS,CAAC,KAAA,CAAM,QAAA,EAAU,KAAA,CAAM,SAAS,CAAA,EAAG;AACrD,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,gBAAgB,IAAA,CAAK,KAAK,GAAG,OAAO,OAAA;AAAA,EACvE;AAEA,EAAA,OAAO,SAAA;AACT;AASO,SAAS,iBAAiB,QAAA,EAAuC;AACtE,EAAA,OAAO,QAAA,KAAa,UAAU,QAAA,GAAM,MAAA;AACtC;AAGO,SAAS,oBAAA,GAA6C;AAC3D,EAAA,IAAI,OAAO,SAAA,KAAc,WAAA,EAAa,OAAO,IAAA;AAC7C,EAAA,OAAO,SAAA;AACT;AC0FA,IAAM,qBAAA,GAAgD;AAAA,EACpD,KAAA,EAAO,SAAA;AAAA,EACP,IAAA,EAAM,SAAA;AAAA,EACN,MAAA,EAAQ;AACV,CAAA;AAEO,SAAS,WAAA,CAAY;AAAA,EAC1B,YAAA;AAAA,EACA,WAAW,EAAC;AAAA,EACZ,WAAW,EAAC;AAAA,EACZ,QAAA,GAAW,IAAA;AAAA,EACX,QAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA,GAAgB,CAAA;AAAA,EAChB,YAAA;AAAA,EACA,SAAA,GAAY,GAAA;AAAA,EACZ,UAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA,GAAc,KAAA;AAAA,EACd,YAAA,GAAe,EAAA;AAAA,EACf,kBAAA;AAAA,EACA,eAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA,GAAe,OAAA;AAAA,EACf,UAAA,GAAa,OAAA;AAAA,EACb,UAAA;AAAA,EACA,KAAA,GAAQ,QAAA;AAAA,EACR,WAAA,GAAc,IAAA;AAAA,EACd,WAAA,GAAc,GAAA;AAAA,EACd,GAAG;AACL,CAAA,EAAqB;AACnB,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,EAAE,CAAA;AAEnC,EAAA,MAAM,MAAA,GAAS,mBAAmB,MAAA,IAAa,WAAA;AAC/C,EAAA,MAAM,SAAA,GAAY,OAAgC,IAAI,CAAA;AACtD,EAAA,MAAM,QAAQ,cAAA,CAAe;AAAA,IAC3B,cAAA;AAAA,IACA,WAAA;AAAA,IACA,YAAA;AAAA,IACA,kBAAA;AAAA,IACA,UAAA,EAAY,eAAA;AAAA,IACZ,QAAA,EAAU,KAAA;AAAA,IACV;AAAA,GACD,CAAA;AACD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,QAAA,CAA6B,EAAE,CAAA;AACrE,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAKzB,IAAI,CAAA;AACP,EAAA,MAAM,KAAA,GAAQ,OAA4B,IAAI,CAAA;AAC9C,EAAA,MAAM,OAAA,GAAU,OAAyB,IAAI,CAAA;AAC7C,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAS,KAAK,CAAA;AAE9C,EAAA,MAAM,SAAS,YAAA,IAAgB,qBAAA;AAY/B,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,SAAwB,SAAS,CAAA;AACjE,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAA,EAAU;AACd,IAAA,WAAA,CAAY,cAAA,CAAe,oBAAA,EAAsB,CAAC,CAAA;AAAA,EACpD,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AACb,EAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,QAAA,IAAY,QAAQ,CAAA;AAEpD,EAAA,MAAM,mBAAA,GACJ,WAAA,IACA,CAAA,mDAAA,EAAsD,MAAM,CAAA,eAAA,CAAA;AAI9D,EAAA,MAAM,WAAA,GAAc,OAAA;AAAA,IAClB,MACE,IAAA,CAAK,IAAA,CAAA,CAAM,MAAA,GAAS,MAAM,MAAA,CAAO,IAAI,CAAA,GAAI,IAAA,EAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,aAAa,CAAC,CAAA;AAAA,IACpF,CAAC,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,aAAa;AAAA,GACrC;AACA,EAAA,MAAM,MAAA,GAAA,CAAU,cAAc,CAAA,IAAK,WAAA;AACnC,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,SAAS,YAAY,CAAA;AAC/C,EAAA,MAAM,aACJ,KAAA,KAAU,QAAA,GACN,OACA,KAAA,KAAU,YAAA,GACR,QAAQ,WAAA,GACN,IAAA,GACA,KAAA,IAAS,WAAA,GACP,SACA,OAAA,GACJ,KAAA,GAAQ,MACN,IAAA,GACA,KAAA,GAAQ,OACN,SAAA,GACA,MAAA;AACZ,EAAA,MAAM,UAAA,GACJ,eAAe,IAAA,GACX,SAAA,GACA,eAAe,SAAA,GACb,SAAA,GACA,UAAA,KAAe,MAAA,GACb,SAAA,GACA,SAAA;AAEV,EAAA,MAAM,YAAA,GAAe,OAAA;AAAA,IACnB,MACE,MAAA,EAAQ,IAAA,KAAS,KAAA,GACb,QAAA,CAAS,MAAA;AAAA,MAAO,CAAC,CAAA,KACf,CAAA,CAAE,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,WAAA,EAAY,CAAE,UAAA,CAAW,MAAA,CAAO,KAAA,CAAM,aAAa;AAAA,QAErE,EAAC;AAAA,IACP,CAAC,QAAQ,QAAQ;AAAA,GACnB;AACA,EAAA,MAAM,gBAAA,GAAmB,OAAA;AAAA,IACvB,MACE,MAAA,EAAQ,IAAA,KAAS,SAAA,GACb,QAAA,CAAS,MAAA;AAAA,MAAO,CAAC,CAAA,KACf,CAAA,CAAE,IAAA,CAAK,WAAA,GAAc,QAAA,CAAS,MAAA,CAAO,KAAA,CAAM,WAAA,EAAa;AAAA,QAE1D,EAAC;AAAA,IACP,CAAC,QAAQ,QAAQ;AAAA,GACnB;AACA,EAAA,MAAM,KAAA,GACJ,QAAQ,IAAA,KAAS,KAAA,GACb,eACA,MAAA,EAAQ,IAAA,KAAS,SAAA,GACf,gBAAA,GACA,EAAC;AAET,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,KAAK,KAAA,CAAM,OAAA;AACjB,IAAA,IAAI,CAAC,EAAA,EAAI;AACT,IAAA,EAAA,CAAG,MAAM,MAAA,GAAS,MAAA;AAClB,IAAA,EAAA,CAAG,MAAM,MAAA,GAAS,IAAA,CAAK,IAAI,SAAA,EAAW,EAAA,CAAG,YAAY,CAAA,GAAI,IAAA;AAAA,EAC3D,CAAA,EAAG,CAAC,IAAA,EAAM,SAAS,CAAC,CAAA;AAEpB,EAAA,MAAM,UAAA,GAAa,CAAC,IAAA,EAAc,KAAA,KAAkB;AAClD,IAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,IAAA,IAAI,UAAA,GAAa,EAAA;AACjB,IAAA,IAAI,WAAA,GAAwC,IAAA;AAC5C,IAAA,KAAA,IAAS,CAAA,GAAI,KAAA,GAAQ,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AACnC,MAAA,MAAM,EAAA,GAAK,KAAK,CAAC,CAAA;AACjB,MAAA,IAAI,OAAO,GAAA,EAAK;AACd,QAAA,WAAA,GAAc,SAAA;AACd,QAAA,UAAA,GAAa,CAAA;AACb,QAAA;AAAA,MACF;AACA,MAAA,IAAI,EAAA,KAAO,GAAA,KAAQ,CAAA,KAAM,CAAA,IAAK,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,IAAK,EAAE,CAAA,CAAA,EAAI;AAC3D,QAAA,WAAA,GAAc,KAAA;AACd,QAAA,UAAA,GAAa,CAAA;AACb,QAAA;AAAA,MACF;AACA,MAAA,IAAI,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,EAAG;AAAA,IACrB;AACA,IAAA,IAAI,WAAA,KAAgB,IAAA,IAAQ,UAAA,IAAc,CAAA,EAAG;AAC3C,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,UAAA,GAAa,GAAG,KAAK,CAAA;AAC9C,MAAA,SAAA,CAAU,EAAE,MAAM,WAAA,EAAa,KAAA,EAAO,YAAY,KAAA,EAAO,MAAA,EAAQ,GAAG,CAAA;AAAA,IACtE,CAAA,MAAO;AACL,MAAA,SAAA,CAAU,IAAI,CAAA;AAAA,IAChB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,YAAA,GAAe,CAAC,CAAA,KAAc;AAClC,IAAA,IAAI,CAAC,MAAA,IAAU,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AACnC,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,CAAC,CAAA,IAAK,MAAM,CAAC,CAAA;AAClC,IAAA,MAAM,MAAA,GACJ,OAAO,IAAA,KAAS,KAAA,GACX,OAAqB,IAAA,GAAO,GAAA,GAC7B,CAAA,CAAA,EAAK,MAAA,CAAyB,EAAE,CAAA,CAAA,CAAA;AACtC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,OAAO,KAAK,CAAA;AACzC,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,CAAM,MAAA,CAAO,QAAQ,CAAA,GAAI,MAAA,CAAO,MAAM,MAAM,CAAA;AAC/D,IAAA,MAAM,IAAA,GAAO,SAAS,MAAA,GAAS,KAAA;AAC/B,IAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,IAAA,SAAA,CAAU,IAAI,CAAA;AACd,IAAA,IAAI,MAAA,EAAQ;AAEV,MAAA,SAAA,CAAU,SAAS,QAAA,CAAS,IAAA,EAAM,MAAA,CAAO,MAAA,GAAS,OAAO,MAAM,CAAA;AAC/D,MAAA;AAAA,IACF;AACA,IAAA,qBAAA,CAAsB,MAAM;AAC1B,MAAA,MAAM,KAAK,KAAA,CAAM,OAAA;AACjB,MAAA,IAAI,CAAC,EAAA,EAAI;AACT,MAAA,EAAA,CAAG,KAAA,EAAM;AACT,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,MAAA,GAAS,MAAA,CAAO,MAAA;AACnC,MAAA,EAAA,CAAG,iBAAA,CAAkB,KAAK,GAAG,CAAA;AAAA,IAC/B,CAAC,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,SAAS,MAAM;AAEnB,IAAA,IAAI,CAAC,IAAA,CAAK,IAAA,EAAK,IAAK,WAAA,CAAY,WAAW,CAAA,EAAG;AAE9C,IAAA,IAAI,MAAA,EAAQ;AAGV,MAAA,MAAM,eAAmC,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA,CAAE,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,QAC5E,IAAI,KAAA,CAAM,EAAA;AAAA,QACV,IAAA,EAAM,MAAM,IAAA,CAAK,IAAA;AAAA,QACjB,KAAA,EAAO,MAAM,IAAA,CAAK,IAAA;AAAA,QAClB,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,IAAA,EAAM,MAAM,IAAA,CAAK;AAAA,OACnB,CAAE,CAAA;AACF,MAAA,QAAA,CAAS,KAAA,CAAM,OAAO,IAAI,CAAA,EAAG,CAAC,GAAG,WAAA,EAAa,GAAG,YAAY,CAAC,CAAA;AAC9D,MAAA,KAAA,CAAM,KAAA,EAAM;AAAA,IACd,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,MAAM,WAAW,CAAA;AAAA,IAC5B;AACA,IAAA,OAAA,CAAQ,EAAE,CAAA;AACV,IAAA,cAAA,CAAe,EAAE,CAAA;AACjB,IAAA,SAAA,CAAU,IAAI,CAAA;AAAA,EAChB,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAwC;AACzD,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAI,CAAA,CAAE,QAAQ,WAAA,EAAa;AACzB,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,SAAA;AAAA,UAAU,CAAC,CAAA,KACT,CAAA,GAAI,EAAE,GAAG,GAAG,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,SAAS,CAAA,EAAG,CAAA,CAAE,MAAA,GAAS,CAAC,GAAE,GAAI;AAAA,SACnE;AACA,QAAA;AAAA,MACF;AACA,MAAA,IAAI,CAAA,CAAE,QAAQ,SAAA,EAAW;AACvB,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,SAAA,CAAU,CAAC,CAAA,KAAO,CAAA,GAAI,EAAE,GAAG,CAAA,EAAG,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA,KAAM,CAAE,CAAA;AACtE,QAAA;AAAA,MACF;AAIA,MAAA,IAAA,CAAM,EAAE,GAAA,KAAQ,OAAA,IAAW,CAAC,CAAA,CAAE,WAAW,CAAC,CAAA,CAAE,OAAA,IAAa,CAAA,CAAE,QAAQ,KAAA,IAAS,CAAC,EAAE,QAAA,KAAc,KAAA,CAAM,SAAS,CAAA,EAAG;AAC7G,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,YAAA,CAAa,OAAO,MAAM,CAAA;AAC1B,QAAA;AAAA,MACF;AACA,MAAA,IAAI,CAAA,CAAE,QAAQ,QAAA,EAAU;AACtB,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,SAAA,CAAU,IAAI,CAAA;AACd,QAAA;AAAA,MACF;AAAA,IACF;AACA,IAAA,IAAI,EAAE,GAAA,KAAQ,OAAA,KAAY,CAAA,CAAE,OAAA,IAAW,EAAE,OAAA,CAAA,EAAU;AACjD,MAAA,CAAA,CAAE,cAAA,EAAe;AACjB,MAAA,MAAA,EAAO;AAAA,IACT;AAAA,EACF,CAAA;AASA,EAAA,MAAM,MAAA,GAAS,CAAC,IAAA,KAAmC;AACjD,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,IAAA,IAAQ,EAAE,CAAA;AACnC,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AAExB,IAAA,cAAA,CAAe,CAAC,GAAA,KAAQ;AAAA,MACtB,GAAG,GAAA;AAAA,MACH,GAAG,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QACnB,EAAA,EAAI,OAAO,UAAA,EAAW;AAAA,QACtB,MAAM,CAAA,CAAE,IAAA;AAAA,QACR,OAAO,CAAA,CAAE,IAAA;AAAA,QACT,IAAA,EAAM,CAAA;AAAA,QACN,MAAM,CAAA,CAAE;AAAA,OACV,CAAE;AAAA,KACH,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,MAAA,GAAS,CAAC,CAAA,KAAuC;AACrD,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,WAAA,CAAY,KAAK,CAAA;AACjB,IAAA,MAAA,CAAO,CAAA,CAAE,aAAa,KAAK,CAAA;AAAA,EAC7B,CAAA;AAeA,EAAA,MAAM,OAAA,GAAU,CAAC,CAAA,KAAiD;AAChE,IAAA,MAAM,OAAO,CAAA,CAAE,aAAA;AACf,IAAA,MAAM,QAAQ,KAAA,CAAM,IAAA,CAAK,IAAA,EAAM,KAAA,IAAS,EAAE,CAAA;AAE1C,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,IAAA,CAAM,IAAA,EAAM,QAAQ,YAAY,CAAA,IAAK,QAAQ,EAAA,EAAI;AAEtE,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,MAAA,CAAO,KAAK,CAAA;AAAA,EACd,CAAA;AAEA,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MAIE,GAAG,IAAA;AAAA,MAKJ,+BAAA,EAA8B,EAAA;AAAA,MAC9B,oCAAA,EAAoC,WAAW,MAAA,GAAS,MAAA;AAAA,MACxD,UAAA,EAAY,CAAC,CAAA,KAAM;AACjB,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,WAAA,CAAY,IAAI,CAAA;AAAA,MAClB,CAAA;AAAA,MACA,WAAA,EAAa,MAAM,WAAA,CAAY,KAAK,CAAA;AAAA,MACpC,MAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,iEAAA;AAAA,QACA,WACI,gFAAA,GACA,sCAAA;AAAA,QACJ;AAAA,OACF;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,UAAA,oBACC,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+CAAA,EACZ,QAAA,EAAA,UAAA,EACH,CAAA;AAAA,QAED,WAAA,CAAY,MAAA,GAAS,CAAA,oBACpB,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,gFAAA,EACZ,QAAA,EAAA,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,qBAChB,IAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YAEC,SAAA,EAAU,kGAAA;AAAA,YAEV,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,QAAK,IAAA,EAAK,WAAA,EAAY,IAAA,EAAK,IAAA,EAAK,WAAU,eAAA,EAAgB,CAAA;AAAA,8BAC3D,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,WAAA,EAAa,YAAE,IAAA,EAAK,CAAA;AAAA,kCACnC,MAAA,EAAA,EAAK,SAAA,EAAU,iBAAiB,QAAA,EAAA,OAAA,CAAQ,CAAA,CAAE,KAAK,CAAA,EAAE,CAAA;AAAA,8BAClD,GAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,OAAA,EAAS,MACP,cAAA,CAAe,CAAC,GAAA,KAAQ,GAAA,CAAI,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,CAAA,CAAE,EAAE,CAAC,CAAA;AAAA,kBAE1D,SAAA,EAAU,8BAAA;AAAA,kBACV,YAAA,EAAW,mBAAA;AAAA,kBACZ,QAAA,EAAA;AAAA;AAAA;AAED;AAAA,WAAA;AAAA,UAdK,CAAA,CAAE;AAAA,SAgBV,CAAA,EACH,CAAA;AAAA,wBAGF,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,UAAA,EACZ,QAAA,EAAA;AAAA,UAAA,MAAA,mBACC,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,4BAAA,GAAA;AAAA,cAAC,iBAAA;AAAA,cAAA;AAAA,gBACC,GAAA,EAAK,SAAA;AAAA,gBACL,KAAA,EAAO,IAAA;AAAA,gBACP,OAAO,KAAA,CAAM,KAAA;AAAA,gBACb,QAAA,EAAU,CAAC,IAAA,EAAM,KAAA,KAAU;AACzB,kBAAA,UAAA,CAAW,MAAM,KAAK,CAAA;AACtB,kBAAA,KAAA,CAAM,MAAM,IAAI,CAAA;AAAA,gBAClB,CAAA;AAAA,gBACA,QAAA,EAAU,MAAA;AAAA,gBACV,SAAA,EAAU,WAAA;AAAA,gBACV,SAAA;AAAA,gBACA,SAAS,KAAA,CAAM,WAAA;AAAA,gBACf,eAAe,KAAA,CAAM,aAAA;AAAA,gBACrB,WAAA,EAAa,mBAAA;AAAA,gBACb,QAAA,EAAU,KAAA;AAAA,gBACV,SAAA;AAAA,gBACA,oBAAA,EAAqB,4CAAA;AAAA,gBACrB,SAAA,EAAW,EAAA;AAAA,kBACT,8DAAA;AAAA,kBACA,eAAA,EAAiB;AAAA;AACnB;AAAA,aACF;AAAA,YACC,KAAA,CAAM,OAAA;AAAA,YACN,eAAe,cAAA,oBACd,GAAA;AAAA,cAAC,gBAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAM,cAAA;AAAA,gBACN,KAAA,EAAO,MAAM,QAAA,CAAS,IAAI,EAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI;AAAA;AAAA;AAC/C,WAAA,EAEJ,CAAA,mBAEA,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,GAAA,EAAK,KAAA;AAAA,cACL,KAAA,EAAO,IAAA;AAAA,cACP,QAAA,EAAU,CAAC,CAAA,KAAM,UAAA,CAAW,EAAE,MAAA,CAAO,KAAA,EAAO,CAAA,CAAE,MAAA,CAAO,cAAc,CAAA;AAAA,cACnE,SAAA;AAAA,cACA,OAAA;AAAA,cACA,WAAA,EAAa,mBAAA;AAAA,cACb,UAAA,EAAY,KAAA;AAAA,cACZ,SAAA,EAAU,wHAAA;AAAA,cACV,IAAA,EAAM;AAAA;AAAA,WACR;AAAA,UAGD,UAAU,KAAA,CAAM,MAAA,GAAS,qBACxB,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,uJAAA,EACb,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,sJAAA,EACZ,QAAA,EAAA;AAAA,cAAA,MAAA,CAAO,IAAA,KAAS,QAAQ,UAAA,GAAa,SAAA;AAAA,cAAU,QAAA;AAAA,cAAI,KAAA,CAAM;AAAA,aAAA,EAC5D,CAAA;AAAA,4BACA,GAAA,CAAC,QAAG,SAAA,EAAU,0BAAA,EACX,gBAAM,GAAA,CAAI,CAAC,MAAM,CAAA,KAAM;AACtB,cAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,MAAA;AAC5B,cAAA,IAAI,MAAA,CAAO,SAAS,KAAA,EAAO;AACzB,gBAAA,MAAM,CAAA,GAAI,IAAA;AACV,gBAAA,uBACE,IAAA;AAAA,kBAAC,IAAA;AAAA,kBAAA;AAAA,oBAEC,WAAA,EAAa,CAAC,CAAA,KAAM;AAClB,sBAAA,CAAA,CAAE,cAAA,EAAe;AACjB,sBAAA,YAAA,CAAa,CAAC,CAAA;AAAA,oBAChB,CAAA;AAAA,oBACA,YAAA,EAAc,MACZ,SAAA,CAAU,CAAC,CAAA,KAAO,CAAA,GAAI,EAAE,GAAG,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAE,GAAI,CAAE,CAAA;AAAA,oBAEhD,SAAA,EAAW,CAAA,uCAAA,EACT,MAAA,GACI,qCAAA,GACA,yCACN,CAAA,CAAA;AAAA,oBAEA,QAAA,EAAA;AAAA,sCAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4DAAA,EACZ,QAAA,EAAA,CAAA,CAAE,IAAA,EACL,CAAA;AAAA,sCACA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2BAAA,EAA6B,YAAE,IAAA,EAAK;AAAA;AAAA,mBAAA;AAAA,kBAjB9C,CAAA,CAAE;AAAA,iBAkBT;AAAA,cAEJ;AACA,cAAA,MAAM,CAAA,GAAI,IAAA;AACV,cAAA,uBACE,IAAA;AAAA,gBAAC,IAAA;AAAA,gBAAA;AAAA,kBAEC,WAAA,EAAa,CAAC,CAAA,KAAM;AAClB,oBAAA,CAAA,CAAE,cAAA,EAAe;AACjB,oBAAA,YAAA,CAAa,CAAC,CAAA;AAAA,kBAChB,CAAA;AAAA,kBACA,YAAA,EAAc,MACZ,SAAA,CAAU,CAAC,CAAA,KAAO,CAAA,GAAI,EAAE,GAAG,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAE,GAAI,CAAE,CAAA;AAAA,kBAEhD,SAAA,EAAW,CAAA,+DAAA,EACT,MAAA,GACI,qCAAA,GACA,yCACN,CAAA,CAAA;AAAA,kBAEA,QAAA,EAAA;AAAA,oCAAA,GAAA;AAAA,sBAAC,MAAA;AAAA,sBAAA;AAAA,wBACC,SAAA,EAAU,sBAAA;AAAA,wBACV,OAAO,EAAE,eAAA,EAAiB,OAAO,CAAA,CAAE,IAAI,KAAK,SAAA;AAAU;AAAA,qBACxD;AAAA,oCACA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,aAAA,EAAe,YAAE,IAAA,EAAK,CAAA;AAAA,oCACtC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,4DAAA,EACb,YAAE,IAAA,EACL;AAAA;AAAA,iBAAA;AAAA,gBArBK,CAAA,CAAE;AAAA,eAsBT;AAAA,YAEJ,CAAC,CAAA,EACH;AAAA,WAAA,EACF;AAAA,SAAA,EAEJ,CAAA;AAAA,wBAEA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mHAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,OAAA,EAAA,EAAQ,OAAA,EAAS,YAAA,KAAiB,MAAA,GAAS,0CAAqC,2BAAA,EAC/E,QAAA,kBAAA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,OAAA;AAAA,cACR,IAAA,EAAK,IAAA;AAAA,cACL,IAAA,EAAK,WAAA;AAAA,cACL,SAAA,EAAU,UAAA;AAAA,cACV,sCAAA,EAAqC,EAAA;AAAA,cAErC,YAAA,EAAY,YAAA,KAAiB,MAAA,GAAS,cAAA,GAAiB,MAAA;AAAA,cACvD,OAAA,EAAS,MAAM,OAAA,CAAQ,OAAA,EAAS,KAAA,EAAM;AAAA,cAErC,QAAA,EAAA,YAAA,KAAiB,SAAS,IAAA,GAAO;AAAA;AAAA,WACpC,EACF,CAAA;AAAA,0BAaA,GAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,GAAA,EAAK,OAAA;AAAA,cACL,IAAA,EAAK,MAAA;AAAA,cACL,QAAA,EAAQ,IAAA;AAAA,cACR,SAAA,EAAU,QAAA;AAAA,cACV,QAAA,EAAU,CAAC,CAAA,KAAM;AACf,gBAAA,MAAA,CAAO,CAAA,CAAE,OAAO,KAAK,CAAA;AAErB,gBAAA,CAAA,CAAE,OAAO,KAAA,GAAQ,EAAA;AAAA,cACnB;AAAA;AAAA,WACF;AAAA,UACC,eAAe,IAAA,oBACd,IAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,qCAAA,EAAoC,EAAA;AAAA,cACpC,YAAA,EAAY,UAAA;AAAA,cACZ,SAAA,EAAU,wDAAA;AAAA,cAEV,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,6EAAA,EACb,QAAA,kBAAA,GAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAU,oCAAA;AAAA,oBACV,KAAA,EAAO,EAAE,KAAA,EAAO,CAAA,EAAG,QAAQ,GAAG,CAAA,CAAA,CAAA,EAAK,iBAAiB,UAAA;AAAW;AAAA,iBACjE,EACF,CAAA;AAAA,gCACA,IAAA,CAAC,UAAK,SAAA,EAAU,uBAAA,EAAwB,OAAO,EAAE,KAAA,EAAO,YAAW,EAChE,QAAA,EAAA;AAAA,kBAAA,SAAA,CAAU,MAAM,CAAA;AAAA,kBAAE,KAAA;AAAA,kBAAI,UAAU,YAAY;AAAA,iBAAA,EAC/C;AAAA;AAAA;AAAA,WACF;AAAA,0BAEF,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0CAAA,EAEZ,QAAA,EAAA;AAAA,YAAA,QAAA,IAAY,eAAe,MAAA,oBAC1B,IAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAU,4CAAA;AAAA,gBACV,oCAAA,EAAoC,MAAA,KAAW,QAAA,GAAM,OAAA,GAAU,SAAA;AAAA,gBAE/D,QAAA,EAAA;AAAA,kCAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mJAAA,EACZ,QAAA,EAAA,MAAA,EACH,CAAA;AAAA,kBAAO,GAAA;AAAA,kBAAI,GAAA;AAAA,kBACT,GAAA;AAAA,kCACF,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mJAAA,EAAoJ,QAAA,EAAA,OAAA,EAEnK,CAAA;AAAA,kBAAO,GAAA;AAAA,kBAAI;AAAA;AAAA;AAAA,aAEb;AAAA,YAED,eAAe,MAAA,mBACd,GAAA,CAAC,WAAQ,OAAA,EAAS,CAAA,UAAA,EAAU,MAAM,CAAA,MAAA,CAAA,EAChC,QAAA,kBAAA,GAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,KAAA,EAAM,QAAA;AAAA,gBACN,IAAA,EAAK,IAAA;AAAA,gBACL,IAAA,EAAK,UAAA;AAAA,gBACL,SAAA,EAAU,UAAA;AAAA,gBACV,oCAAA,EAAmC,EAAA;AAAA,gBACnC,YAAA,EAAW,MAAA;AAAA,gBACX,OAAA,EAAS;AAAA;AAAA,eAEb,CAAA,mBAEA,GAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,KAAA,EAAM,QAAA;AAAA,gBACN,IAAA,EAAK,IAAA;AAAA,gBACL,YAAA,EAAa,aAAA;AAAA,gBACb,SAAA,EAAU,UAAA;AAAA,gBACV,oCAAA,EAAmC,EAAA;AAAA,gBACnC,OAAA,EAAS,MAAA;AAAA,gBACV,QAAA,EAAA;AAAA;AAAA;AAED,WAAA,EAEJ;AAAA,SAAA,EACF;AAAA;AAAA;AAAA,GACF;AAEJ;AAEA,SAAS,UAAU,CAAA,EAAmB;AACpC,EAAA,IAAI,CAAA,GAAI,GAAA,EAAM,OAAO,CAAA,EAAG,CAAC,CAAA,CAAA;AACzB,EAAA,OAAO,CAAA,EAAA,CAAI,CAAA,GAAI,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA;AACjC;AAEA,SAAS,QAAQ,CAAA,EAAmB;AAClC,EAAA,IAAI,CAAA,GAAI,IAAA,EAAM,OAAO,CAAA,EAAG,CAAC,CAAA,EAAA,CAAA;AACzB,EAAA,IAAI,CAAA,GAAI,OAAO,IAAA,EAAM,OAAO,IAAI,CAAA,GAAI,IAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,GAAA,CAAA;AACpD,EAAA,OAAO,IAAI,CAAA,GAAI,IAAA,GAAO,IAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,GAAA,CAAA;AACxC","file":"chunk-QSAYIYEB.js","sourcesContent":["/**\n * Which modifier key the user actually has.\n *\n * This exists because a keyboard hint is a CLAIM about the reader's hardware.\n * `⌘ + Enter to send` on Windows or Linux names a key that is not on the\n * keyboard, and a reader who cannot act on a hint learns to ignore hints — so\n * the cost is not one wrong glyph, it is the credibility of every hint beside\n * it. (Reported from a real Electron app running on Linux, where the glyph had\n * no font behind it either and rendered as tofu.)\n *\n * Two deliberate choices:\n *\n * 1. **The platform is an ARGUMENT, never a global read.** `detectPlatform`\n * takes the hints; `modifierKeyLabel` takes the verdict. Both branches are\n * therefore reachable from one machine, which is the only way a test can\n * cover the platform you are not sitting at. A function that reads\n * `navigator` internally can only ever be tested on the developer's own OS.\n * 2. **`generic` is the fallback, and that is not arbitrary.** Every Fancy\n * surface that submits on a modifier accepts `metaKey || ctrlKey`, so\n * `Ctrl` is a TRUE label on an Apple keyboard while `⌘` is a FALSE one\n * everywhere else. The honest default is the one that is pressable on all\n * of them.\n */\nexport type FancyPlatform = \"apple\" | \"generic\";\n\n/**\n * The parts of `navigator` the detection reads — nothing more, so a caller can\n * hand it a literal (a test, an Electron main process forwarding `process.platform`,\n * a server with a stored preference).\n */\nexport interface PlatformHints {\n /** `navigator.userAgentData` — the modern, non-spoofed answer where it exists. */\n userAgentData?: { platform?: string } | null;\n /** `navigator.platform` — deprecated, still the most reliable legacy signal. */\n platform?: string | null;\n /** `navigator.userAgent` — last resort. */\n userAgent?: string | null;\n}\n\n/**\n * `userAgentData.platform` is a short enumerated token (\"macOS\", \"Windows\",\n * \"Linux\", \"Android\", \"iOS\"), so it is matched exactly rather than by substring.\n */\nconst APPLE_UA_DATA_PLATFORMS = new Set([\"macos\", \"ios\", \"ipados\"]);\n\n/**\n * Legacy `platform` / `userAgent` are free text. iPadOS reports `MacIntel`, and\n * iOS user agents say \"like Mac OS X\" — both are Apple, so a Mac match is\n * correct for them too.\n */\nconst APPLE_FREE_TEXT = /\\b(mac|macintosh|iphone|ipad|ipod|darwin)/i;\n\n/** Resolve a platform from navigator-shaped hints. Unknown or absent ⇒ `generic`. */\nexport function detectPlatform(hints?: PlatformHints | null): FancyPlatform {\n if (!hints) return \"generic\";\n\n const uaData = hints.userAgentData?.platform;\n if (typeof uaData === \"string\" && uaData.length > 0) {\n // When the browser gives an enumerated answer, TRUST IT and stop. Falling\n // through to the free-text test would let a Windows UA string containing\n // the word \"Mac\" (a font name, a device model) overturn it.\n return APPLE_UA_DATA_PLATFORMS.has(uaData.trim().toLowerCase()) ? \"apple\" : \"generic\";\n }\n\n for (const value of [hints.platform, hints.userAgent]) {\n if (typeof value === \"string\" && APPLE_FREE_TEXT.test(value)) return \"apple\";\n }\n\n return \"generic\";\n}\n\n/**\n * The modifier key to NAME for a platform.\n *\n * `⌘` is emitted for `apple` and nothing else. A test enumerates the platform\n * values and counts that no other one can produce it, because a hint that names\n * the wrong key is worse than no hint.\n */\nexport function modifierKeyLabel(platform: FancyPlatform): \"⌘\" | \"Ctrl\" {\n return platform === \"apple\" ? \"⌘\" : \"Ctrl\";\n}\n\n/** SSR-safe read of the live browser hints. `null` off a browser. */\nexport function browserPlatformHints(): PlatformHints | null {\n if (typeof navigator === \"undefined\") return null;\n return navigator as PlatformHints;\n}\n","import {\n useEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button\";\nimport { Icon } from \"../Icon\";\nimport { Tooltip } from \"../Tooltip\";\nimport {\n InlinePasteEditor,\n PastedFilesInput,\n useInlinePaste,\n type ComposerPasteClassNames,\n type ComposerPastePreview,\n type InlinePasteEditorHandle,\n} from \"../PastePills\";\nimport {\n browserPlatformHints,\n detectPlatform,\n modifierKeyLabel,\n type FancyPlatform,\n} from \"../../utils/platform\";\n\n/**\n * PromptInput — the chat composer every AI app rebuilds. Auto-growing\n * multi-line input with:\n *\n * • slash-command picker (`/` triggers a filtered command palette,\n * ↑/↓ navigate, Enter inserts)\n * • mention picker (`@` triggers, filtered against `mentions`)\n * • drop-to-attach (drag files anywhere on the surface), paste-to-attach\n * (a pasted screenshot becomes an attachment) + chip bar\n * • submit on ⌘/Ctrl+Enter (plain Enter inserts a newline)\n * • live token-budget meter (green → amber → red as headroom drops)\n *\n * Wire it up:\n *\n * <PromptInput\n * budgetTokens={32000}\n * commands={[{ name: \"/rewrite\", hint: \"rewrite the selection\" }]}\n * mentions={[{ id: \"ada\", name: \"Ada\", kind: \"person\" }]}\n * onSubmit={(text, attachments) => sendToAgent(text, attachments)}\n * />\n */\nexport type PromptCmd = { name: string; hint: string };\nexport type PromptMention = {\n id: string;\n name: string;\n kind: \"agent\" | \"file\" | \"person\" | string;\n};\nexport type PromptAttachment = {\n id: string;\n name: string;\n bytes: number;\n /**\n * The file the user actually attached.\n *\n * Optional because an attachment restored from a server has no File — but for\n * anything the user dropped or picked it is always present. Without it a host\n * can render a chip and nothing else: no POST, no FormData, no send-to-model.\n */\n file?: File;\n /** MIME type. Hosts branch on this to decide whether a file can be sent as-is. */\n type?: string;\n};\n\n/**\n * `...rest` reaches the root surface, so a consumer or a bridge can tag the\n * composer with its own `data-*` handle. The component named every prop it\n * used and had no rest spread, which means a `data-handle` put on it was\n * DROPPED — silently, since React discards unknown props and the component\n * still renders perfectly. That is issue #22 all over again, and the contract\n * calls it out: \"Each interactive element has a stable identity. Agents never\n * guess DOM.\"\n */\nexport interface PromptInputProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"onSubmit\" | \"className\"> {\n /** Extra classes on the root surface. MERGED, never replaced. */\n className?: string;\n /** Token budget for the meter. */\n budgetTokens: number;\n /** Slash-commands. Names must start with `/`. */\n commands?: PromptCmd[];\n /** @-mentions. */\n mentions?: PromptMention[];\n /** Show the keyboard hint (\"Ctrl + Enter to send\", \"⌘ + Enter\" on a Mac). */\n showHint?: boolean;\n /**\n * Which modifier the hint and the default placeholder NAME. Omit it and the\n * component reads the platform after mount, which is the right answer for an\n * ordinary web app.\n *\n * Pass it when the host knows better than `navigator` does — an Electron\n * renderer forwarding `process.platform`, a remote session where the\n * keyboard is not the one running the browser, or a test that needs the\n * branch it is not sitting on. The pressed keys are unaffected either way:\n * submit is `⌘/Ctrl+Enter` on every platform, so this only decides which\n * true key gets named.\n */\n platform?: FancyPlatform;\n /** Called on ⌘/Ctrl+Enter or send button. */\n onSubmit: (text: string, attachments: PromptAttachment[]) => void;\n /**\n * Placeholder text. Defaults to a hint naming the modifier THIS platform\n * actually has, so leaving it unset is the better option — a hardcoded\n * placeholder is the other place a `⌘` ends up in front of a Windows user.\n */\n placeholder?: string;\n /** Rough estimator: chars-per-token. Defaults to 4. */\n charsPerToken?: number;\n /** Color → CSS chip mapping for mention kinds. */\n mentionColor?: Record<string, string>;\n /** Optional max textarea height in px. Defaults to 280. */\n maxHeight?: number;\n /**\n * Rendered INSIDE the rounded shell, ABOVE the attachments bar and\n * textarea. Use this slot for a drawer of tools/files/prompts/etc. so\n * the drawer and composer share one visual panel. See {@link ChatDrawer}.\n */\n aboveInput?: ReactNode;\n /**\n * Hold a paste of at least this many characters as a pill IN the message,\n * where it was pasted: on a line of its own, its full text put back in place\n * when clicked, and expanded where it sits when sent. Omit it and paste is\n * unchanged. Setting this (or `pasteImages`) swaps the textarea for an inline\n * editor that keeps the `/` and `@` pickers and the send key.\n */\n pasteThreshold?: number;\n /**\n * A pasted image becomes an inline `Pasted image N` pill AND reaches\n * `onSubmit`'s attachments, with its File, in message order; the text marks\n * where it sat as `[Pasted image N]`. Without it a pasted image is an\n * ordinary attachment chip, as before.\n */\n pasteImages?: boolean;\n /** Characters of a held paste shown at EACH end of its hover preview. Default 20. */\n previewChars?: number;\n /** Replace the paste pills' hover popover content. */\n renderPastePreview?: (preview: ComposerPastePreview) => ReactNode;\n /** Restyle the paste pills, their popover and the inline editor. Merged onto the defaults. */\n pasteClassNames?: ComposerPasteClassNames;\n /**\n * Submit pasted images with an enclosing `<form>`, under this field name: a\n * hidden `<input type=\"file\" multiple>` holds the images still in the message,\n * in message order. Needs `pasteImages`. They reach `onSubmit` either way.\n */\n pasteFilesName?: string;\n /** `\"icon\"`: an icon-only attach button whose tooltip says what it does. Default `\"label\"`. */\n attachButton?: \"label\" | \"icon\";\n /**\n * `\"icon\"`: a compact icon send button whose tooltip carries the shortcut —\n * replacing the inline `Ctrl + Enter to send` hint. Default `\"label\"`.\n */\n sendButton?: \"label\" | \"icon\";\n /**\n * Tokens already used — the caller's REAL value, e.g. an agent's context\n * usage. The meter shows this plus the estimate for the draft. Without it the\n * meter estimates the draft alone, as before.\n */\n usedTokens?: number;\n /**\n * `\"always\"` (default) — as before. `\"near-limit\"` — hidden until usage passes\n * `meterShowAt`, muted until `meterWarnAt`, warning colour past that.\n * `\"hidden\"` — never shown.\n */\n meter?: \"always\" | \"near-limit\" | \"hidden\";\n /** Fraction of `budgetTokens` at which a `\"near-limit\"` meter appears. Default 0.75. */\n meterShowAt?: number;\n /** Fraction of `budgetTokens` past which a `\"near-limit\"` meter takes the warning colour. Default 0.9. */\n meterWarnAt?: number;\n}\n\nconst DEFAULT_MENTION_COLOR: Record<string, string> = {\n agent: \"#a855f7\",\n file: \"#10b981\",\n person: \"#3b82f6\",\n};\n\nexport function PromptInput({\n budgetTokens,\n commands = [],\n mentions = [],\n showHint = true,\n platform,\n onSubmit,\n placeholder,\n charsPerToken = 4,\n mentionColor,\n maxHeight = 280,\n aboveInput,\n className,\n pasteThreshold,\n pasteImages = false,\n previewChars = 20,\n renderPastePreview,\n pasteClassNames,\n pasteFilesName,\n attachButton = \"label\",\n sendButton = \"label\",\n usedTokens,\n meter = \"always\",\n meterShowAt = 0.75,\n meterWarnAt = 0.9,\n ...rest\n}: PromptInputProps) {\n const [text, setText] = useState(\"\");\n /** Inline pills need an editor that can hold them; a textarea cannot. */\n const inline = pasteThreshold !== undefined || pasteImages;\n const editorRef = useRef<InlinePasteEditorHandle>(null);\n const paste = useInlinePaste({\n pasteThreshold,\n pasteImages,\n previewChars,\n renderPastePreview,\n classNames: pasteClassNames,\n disabled: false,\n editorRef,\n });\n const [attachments, setAttachments] = useState<PromptAttachment[]>([]);\n const [picker, setPicker] = useState<null | {\n kind: \"cmd\" | \"mention\";\n start: number;\n query: string;\n cursor: number;\n }>(null);\n const taRef = useRef<HTMLTextAreaElement>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const [dragOver, setDragOver] = useState(false);\n\n const colors = mentionColor ?? DEFAULT_MENTION_COLOR;\n\n /**\n * Resolved AFTER mount, never during render.\n *\n * `navigator` read during render disagrees with the server's HTML and\n * hydration patches it — so the fix for a wrong label would have introduced a\n * hydration mismatch instead. The first paint names `Ctrl`, which is\n * pressable on every platform including a Mac, and an Apple client swaps to\n * `⌘` on the next tick. A prop, when given, wins outright and no detection\n * runs at all.\n */\n const [detected, setDetected] = useState<FancyPlatform>(\"generic\");\n useEffect(() => {\n if (platform) return;\n setDetected(detectPlatform(browserPlatformHints()));\n }, [platform]);\n const modKey = modifierKeyLabel(platform ?? detected);\n\n const resolvedPlaceholder =\n placeholder ??\n `Ask anything. Type / for commands, @ for mentions. ${modKey}+Enter to send.`;\n\n // Estimated from what will actually be SENT — pills expanded — so a held\n // paste counts for its text, not for the few characters of its marker.\n const draftTokens = useMemo(\n () =>\n Math.ceil((inline ? paste.expand(text) : text).length / Math.max(1, charsPerToken)),\n [text, inline, paste, charsPerToken],\n );\n const tokens = (usedTokens ?? 0) + draftTokens;\n const ratio = Math.min(1, tokens / budgetTokens);\n const meterLevel: \"ok\" | \"caution\" | \"warn\" | \"muted\" | null =\n meter === \"hidden\"\n ? null\n : meter === \"near-limit\"\n ? ratio < meterShowAt\n ? null\n : ratio >= meterWarnAt\n ? \"warn\"\n : \"muted\"\n : ratio < 0.6\n ? \"ok\"\n : ratio < 0.85\n ? \"caution\"\n : \"warn\";\n const meterColor =\n meterLevel === \"ok\"\n ? \"#10b981\"\n : meterLevel === \"caution\"\n ? \"#f59e0b\"\n : meterLevel === \"warn\"\n ? \"#ef4444\"\n : \"#a1a1aa\";\n\n const filteredCmds = useMemo(\n () =>\n picker?.kind === \"cmd\"\n ? commands.filter((c) =>\n c.name.slice(1).toLowerCase().startsWith(picker.query.toLowerCase()),\n )\n : [],\n [picker, commands],\n );\n const filteredMentions = useMemo(\n () =>\n picker?.kind === \"mention\"\n ? mentions.filter((m) =>\n m.name.toLowerCase().includes(picker.query.toLowerCase()),\n )\n : [],\n [picker, mentions],\n );\n const items: Array<PromptCmd | PromptMention> =\n picker?.kind === \"cmd\"\n ? filteredCmds\n : picker?.kind === \"mention\"\n ? filteredMentions\n : [];\n\n useEffect(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.style.height = \"auto\";\n ta.style.height = Math.min(maxHeight, ta.scrollHeight) + \"px\";\n }, [text, maxHeight]);\n\n const updateText = (next: string, caret: number) => {\n setText(next);\n let triggerIdx = -1;\n let triggerKind: \"cmd\" | \"mention\" | null = null;\n for (let i = caret - 1; i >= 0; i--) {\n const ch = next[i];\n if (ch === \"@\") {\n triggerKind = \"mention\";\n triggerIdx = i;\n break;\n }\n if (ch === \"/\" && (i === 0 || /\\s/.test(next[i - 1] ?? \"\"))) {\n triggerKind = \"cmd\";\n triggerIdx = i;\n break;\n }\n if (/\\s/.test(ch)) break;\n }\n if (triggerKind !== null && triggerIdx >= 0) {\n const query = next.slice(triggerIdx + 1, caret);\n setPicker({ kind: triggerKind, start: triggerIdx, query, cursor: 0 });\n } else {\n setPicker(null);\n }\n };\n\n const insertChoice = (i: number) => {\n if (!picker || items.length === 0) return;\n const choice = items[i] ?? items[0];\n const insert =\n picker.kind === \"cmd\"\n ? (choice as PromptCmd).name + \" \"\n : `@${(choice as PromptMention).id} `;\n const before = text.slice(0, picker.start);\n const after = text.slice(picker.start + 1 + picker.query.length);\n const next = before + insert + after;\n setText(next);\n setPicker(null);\n if (inline) {\n // The editor rebuilds from the value and puts the caret back itself.\n editorRef.current?.setValue(next, before.length + insert.length);\n return;\n }\n requestAnimationFrame(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.focus();\n const pos = before.length + insert.length;\n ta.setSelectionRange(pos, pos);\n });\n };\n\n const submit = () => {\n // A message that is only a paste counts: its marker is in `text`.\n if (!text.trim() && attachments.length === 0) return;\n\n if (inline) {\n // Every pill goes out where it sits; pasted images join the attachments\n // in message order, with their Files, so a host sends them like any other.\n const pastedImages: PromptAttachment[] = paste.imagesIn(text).map((image) => ({\n id: image.id,\n name: image.file.name,\n bytes: image.file.size,\n file: image.file,\n type: image.file.type,\n }));\n onSubmit(paste.expand(text), [...attachments, ...pastedImages]);\n paste.clear();\n } else {\n onSubmit(text, attachments);\n }\n setText(\"\");\n setAttachments([]);\n setPicker(null);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (picker) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setPicker((p) =>\n p ? { ...p, cursor: Math.min(items.length - 1, p.cursor + 1) } : p,\n );\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setPicker((p) => (p ? { ...p, cursor: Math.max(0, p.cursor - 1) } : p));\n return;\n }\n // Tab completes, as Enter does: the autocomplete key people expect from a\n // shell or Claude Code. Only while a menu is open; otherwise Tab moves\n // focus as usual.\n if (((e.key === \"Enter\" && !e.metaKey && !e.ctrlKey) || (e.key === \"Tab\" && !e.shiftKey)) && items.length > 0) {\n e.preventDefault();\n insertChoice(picker.cursor);\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n setPicker(null);\n return;\n }\n }\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n submit();\n }\n };\n\n /**\n * Build attachments from a FileList, KEEPING the File.\n *\n * Shared by the drop handler and the picker so the two cannot drift — the\n * picker being a second, subtly different copy of this is exactly how one of\n * them would end up dropping the File again.\n */\n const attach = (list: FileList | File[] | null) => {\n const files = Array.from(list ?? []);\n if (files.length === 0) return;\n\n setAttachments((cur) => [\n ...cur,\n ...files.map((f) => ({\n id: crypto.randomUUID(),\n name: f.name,\n bytes: f.size,\n file: f,\n type: f.type,\n })),\n ]);\n };\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setDragOver(false);\n attach(e.dataTransfer.files);\n };\n\n /**\n * Paste a screenshot, get an attachment.\n *\n * There was no paste handler at all, so a pasted image did nothing — no chip,\n * no error — and a host that had swapped its own paste-capable textarea for\n * this component lost the feature without noticing.\n *\n * Files attach only when the clipboard carries NO plain text. Word, Excel and\n * most editors put a picture of the selection beside the text; attaching that\n * would turn every pasted sentence into a screenshot of the sentence. A pure\n * image paste has nothing for the browser to insert, so the default is\n * prevented only then, and a text paste is never touched.\n */\n const onPaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const data = e.clipboardData;\n const files = Array.from(data?.files ?? []);\n\n if (files.length === 0 || (data?.getData(\"text/plain\") ?? \"\") !== \"\") return;\n\n e.preventDefault();\n attach(files);\n };\n\n return (\n <div\n // Spread FIRST so an internal handler or data attribute cannot be\n // clobbered from outside, and so a missing one fails loudly here rather\n // than at a consumer's selector. `className` is merged below instead.\n {...rest}\n // The component had no root handle at all, so an agent reading the\n // composer had to guess at classes. The drag state is on it too: a bridge\n // that wants to know whether a drop is in flight should not have to infer\n // it from Tailwind colours.\n data-react-fancy-prompt-input=\"\"\n data-react-fancy-prompt-input-drag={dragOver ? \"over\" : \"idle\"}\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}\n className={cn(\n \"relative rounded-md border bg-white transition dark:bg-zinc-900\",\n dragOver\n ? \"border-violet-400 bg-violet-50/50 dark:border-violet-600 dark:bg-violet-950/30\"\n : \"border-zinc-200 dark:border-zinc-800\",\n className,\n )}\n >\n {aboveInput && (\n <div className=\"border-b border-zinc-200 dark:border-zinc-800\">\n {aboveInput}\n </div>\n )}\n {attachments.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 border-b border-zinc-200 px-3 py-2 dark:border-zinc-800\">\n {attachments.map((a) => (\n <span\n key={a.id}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-zinc-100 px-2 py-0.5 text-[11px] dark:bg-zinc-800\"\n >\n <Icon name=\"paperclip\" size=\"xs\" className=\"text-zinc-400\" />\n <span className=\"font-mono\">{a.name}</span>\n <span className=\"text-zinc-400\">{fmtSize(a.bytes)}</span>\n <button\n onClick={() =>\n setAttachments((cur) => cur.filter((x) => x.id !== a.id))\n }\n className=\"opacity-50 hover:opacity-100\"\n aria-label=\"Remove attachment\"\n >\n ×\n </button>\n </span>\n ))}\n </div>\n )}\n\n <div className=\"relative\">\n {inline ? (\n <>\n <InlinePasteEditor\n ref={editorRef}\n value={text}\n known={paste.known}\n onChange={(next, caret) => {\n updateText(next, caret);\n paste.prune(next);\n }}\n onSubmit={submit}\n submitKey=\"mod-enter\"\n onKeyDown={onKeyDown}\n onPaste={paste.decidePaste}\n onHostsChange={paste.onHostsChange}\n placeholder={resolvedPlaceholder}\n disabled={false}\n maxHeight={maxHeight}\n placeholderClassName=\"left-3 top-2.5 text-[14px] leading-relaxed\"\n className={cn(\n \"block min-h-[5.5rem] px-3 py-2.5 text-[14px] leading-relaxed\",\n pasteClassNames?.input,\n )}\n />\n {paste.portals}\n {pasteImages && pasteFilesName && (\n <PastedFilesInput\n name={pasteFilesName}\n files={paste.imagesIn(text).map((i) => i.file)}\n />\n )}\n </>\n ) : (\n <textarea\n ref={taRef}\n value={text}\n onChange={(e) => updateText(e.target.value, e.target.selectionStart)}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n placeholder={resolvedPlaceholder}\n spellCheck={false}\n className=\"block w-full resize-none bg-transparent px-3 py-2.5 text-[14px] leading-relaxed outline-none placeholder:text-zinc-400\"\n rows={3}\n />\n )}\n\n {picker && items.length > 0 && (\n <div className=\"absolute bottom-full left-2 z-10 mb-1 w-72 overflow-hidden rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900\">\n <div className=\"border-b border-zinc-100 bg-zinc-50 px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950\">\n {picker.kind === \"cmd\" ? \"Commands\" : \"Mention\"} · {items.length}\n </div>\n <ul className=\"max-h-56 overflow-y-auto\">\n {items.map((item, i) => {\n const active = i === picker.cursor;\n if (picker.kind === \"cmd\") {\n const c = item as PromptCmd;\n return (\n <li\n key={c.name}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`cursor-pointer px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <div className=\"font-mono font-medium text-violet-700 dark:text-violet-300\">\n {c.name}\n </div>\n <div className=\"text-[11px] text-zinc-500\">{c.hint}</div>\n </li>\n );\n }\n const m = item as PromptMention;\n return (\n <li\n key={m.id}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`flex cursor-pointer items-center gap-2 px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <span\n className=\"h-2 w-2 rounded-full\"\n style={{ backgroundColor: colors[m.kind] ?? \"#71717a\" }}\n />\n <span className=\"font-medium\">{m.name}</span>\n <span className=\"ml-auto text-[10px] uppercase tracking-wider text-zinc-400\">\n {m.kind}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n\n <div className=\"flex items-center gap-2 border-t border-zinc-200 bg-zinc-50/60 px-3 py-2 dark:border-zinc-800 dark:bg-zinc-900/40\">\n <Tooltip content={attachButton === \"icon\" ? \"Attach files — or drop them here\" : \"Drop files here, or click\"}>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n icon=\"paperclip\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-attach=\"\"\n // An icon alone has no name; the tooltip is not one a screen reader reads.\n aria-label={attachButton === \"icon\" ? \"Attach files\" : undefined}\n onClick={() => fileRef.current?.click()}\n >\n {attachButton === \"icon\" ? null : \"attach\"}\n </Button>\n </Tooltip>\n {/*\n The button above shipped with a no-op onClick and a tooltip reading\n \"Drop files here, or click\" — an affordance that lied. Drop-only also\n meant keyboard and touch users could not attach at all.\n\n It then shipped with a literal paperclip EMOJI as its icon, which\n needs a COLOUR\n EMOJI FONT — not merely broad coverage — so a lean container renders a\n tofu box where the affordance should be. `icon=\"paperclip\"` draws an\n SVG from the kit's own icon layer, which is the same reason the rest of\n the suite does not hand-roll iconography.\n */}\n <input\n ref={fileRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n attach(e.target.files);\n // Let the same file be picked twice in a row.\n e.target.value = \"\";\n }}\n />\n {meterLevel !== null && (\n <div\n data-react-fancy-prompt-input-meter=\"\"\n data-level={meterLevel}\n className=\"ml-2 flex min-w-0 items-center gap-1.5 overflow-hidden\"\n >\n <div className=\"h-1.5 w-24 shrink overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-700\">\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${ratio * 100}%`, backgroundColor: meterColor }}\n />\n </div>\n <span className=\"font-mono text-[11px]\" style={{ color: meterColor }}>\n {fmtTokens(tokens)} / {fmtTokens(budgetTokens)}\n </span>\n </div>\n )}\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {/* With an icon send button the shortcut lives in its tooltip instead. */}\n {showHint && sendButton !== \"icon\" && (\n <span\n className=\"hidden text-[10px] text-zinc-500 sm:inline\"\n data-react-fancy-prompt-input-hint={modKey === \"⌘\" ? \"apple\" : \"generic\"}\n >\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n {modKey}\n </kbd>{\" \"}\n +{\" \"}\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n Enter\n </kbd>{\" \"}\n to send\n </span>\n )}\n {sendButton === \"icon\" ? (\n <Tooltip content={`Send · ${modKey}+Enter`}>\n <Button\n color=\"violet\"\n size=\"sm\"\n icon=\"arrow-up\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-send=\"\"\n aria-label=\"Send\"\n onClick={submit}\n />\n </Tooltip>\n ) : (\n <Button\n color=\"violet\"\n size=\"sm\"\n iconTrailing=\"arrow-right\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-send=\"\"\n onClick={submit}\n >\n send\n </Button>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction fmtTokens(n: number): string {\n if (n < 1000) return `${n}`;\n return `${(n / 1000).toFixed(1)}k`;\n}\n\nfunction fmtSize(b: number): string {\n if (b < 1024) return `${b} B`;\n if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)} KB`;\n return `${(b / 1024 / 1024).toFixed(1)} MB`;\n}\n"]}
@@ -192,7 +192,7 @@ function PromptInput({
192
192
  setPicker((p) => p ? { ...p, cursor: Math.max(0, p.cursor - 1) } : p);
193
193
  return;
194
194
  }
195
- if (e.key === "Enter" && !e.metaKey && !e.ctrlKey && items.length > 0) {
195
+ if ((e.key === "Enter" && !e.metaKey && !e.ctrlKey || e.key === "Tab" && !e.shiftKey) && items.length > 0) {
196
196
  e.preventDefault();
197
197
  insertChoice(picker.cursor);
198
198
  return;
@@ -486,5 +486,5 @@ exports.PromptInput = PromptInput;
486
486
  exports.browserPlatformHints = browserPlatformHints;
487
487
  exports.detectPlatform = detectPlatform;
488
488
  exports.modifierKeyLabel = modifierKeyLabel;
489
- //# sourceMappingURL=chunk-Z3FIU77M.cjs.map
490
- //# sourceMappingURL=chunk-Z3FIU77M.cjs.map
489
+ //# sourceMappingURL=chunk-RBEQLBKI.cjs.map
490
+ //# sourceMappingURL=chunk-RBEQLBKI.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/platform.ts","../src/components/PromptInput/PromptInput.tsx"],"names":["useState","useRef","useInlinePaste","useEffect","useMemo","jsxs","cn","jsx","Icon","Fragment","InlinePasteEditor","PastedFilesInput","Tooltip","Button"],"mappings":"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","file":"chunk-RBEQLBKI.cjs","sourcesContent":["/**\n * Which modifier key the user actually has.\n *\n * This exists because a keyboard hint is a CLAIM about the reader's hardware.\n * `⌘ + Enter to send` on Windows or Linux names a key that is not on the\n * keyboard, and a reader who cannot act on a hint learns to ignore hints — so\n * the cost is not one wrong glyph, it is the credibility of every hint beside\n * it. (Reported from a real Electron app running on Linux, where the glyph had\n * no font behind it either and rendered as tofu.)\n *\n * Two deliberate choices:\n *\n * 1. **The platform is an ARGUMENT, never a global read.** `detectPlatform`\n * takes the hints; `modifierKeyLabel` takes the verdict. Both branches are\n * therefore reachable from one machine, which is the only way a test can\n * cover the platform you are not sitting at. A function that reads\n * `navigator` internally can only ever be tested on the developer's own OS.\n * 2. **`generic` is the fallback, and that is not arbitrary.** Every Fancy\n * surface that submits on a modifier accepts `metaKey || ctrlKey`, so\n * `Ctrl` is a TRUE label on an Apple keyboard while `⌘` is a FALSE one\n * everywhere else. The honest default is the one that is pressable on all\n * of them.\n */\nexport type FancyPlatform = \"apple\" | \"generic\";\n\n/**\n * The parts of `navigator` the detection reads — nothing more, so a caller can\n * hand it a literal (a test, an Electron main process forwarding `process.platform`,\n * a server with a stored preference).\n */\nexport interface PlatformHints {\n /** `navigator.userAgentData` — the modern, non-spoofed answer where it exists. */\n userAgentData?: { platform?: string } | null;\n /** `navigator.platform` — deprecated, still the most reliable legacy signal. */\n platform?: string | null;\n /** `navigator.userAgent` — last resort. */\n userAgent?: string | null;\n}\n\n/**\n * `userAgentData.platform` is a short enumerated token (\"macOS\", \"Windows\",\n * \"Linux\", \"Android\", \"iOS\"), so it is matched exactly rather than by substring.\n */\nconst APPLE_UA_DATA_PLATFORMS = new Set([\"macos\", \"ios\", \"ipados\"]);\n\n/**\n * Legacy `platform` / `userAgent` are free text. iPadOS reports `MacIntel`, and\n * iOS user agents say \"like Mac OS X\" — both are Apple, so a Mac match is\n * correct for them too.\n */\nconst APPLE_FREE_TEXT = /\\b(mac|macintosh|iphone|ipad|ipod|darwin)/i;\n\n/** Resolve a platform from navigator-shaped hints. Unknown or absent ⇒ `generic`. */\nexport function detectPlatform(hints?: PlatformHints | null): FancyPlatform {\n if (!hints) return \"generic\";\n\n const uaData = hints.userAgentData?.platform;\n if (typeof uaData === \"string\" && uaData.length > 0) {\n // When the browser gives an enumerated answer, TRUST IT and stop. Falling\n // through to the free-text test would let a Windows UA string containing\n // the word \"Mac\" (a font name, a device model) overturn it.\n return APPLE_UA_DATA_PLATFORMS.has(uaData.trim().toLowerCase()) ? \"apple\" : \"generic\";\n }\n\n for (const value of [hints.platform, hints.userAgent]) {\n if (typeof value === \"string\" && APPLE_FREE_TEXT.test(value)) return \"apple\";\n }\n\n return \"generic\";\n}\n\n/**\n * The modifier key to NAME for a platform.\n *\n * `⌘` is emitted for `apple` and nothing else. A test enumerates the platform\n * values and counts that no other one can produce it, because a hint that names\n * the wrong key is worse than no hint.\n */\nexport function modifierKeyLabel(platform: FancyPlatform): \"⌘\" | \"Ctrl\" {\n return platform === \"apple\" ? \"⌘\" : \"Ctrl\";\n}\n\n/** SSR-safe read of the live browser hints. `null` off a browser. */\nexport function browserPlatformHints(): PlatformHints | null {\n if (typeof navigator === \"undefined\") return null;\n return navigator as PlatformHints;\n}\n","import {\n useEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button\";\nimport { Icon } from \"../Icon\";\nimport { Tooltip } from \"../Tooltip\";\nimport {\n InlinePasteEditor,\n PastedFilesInput,\n useInlinePaste,\n type ComposerPasteClassNames,\n type ComposerPastePreview,\n type InlinePasteEditorHandle,\n} from \"../PastePills\";\nimport {\n browserPlatformHints,\n detectPlatform,\n modifierKeyLabel,\n type FancyPlatform,\n} from \"../../utils/platform\";\n\n/**\n * PromptInput — the chat composer every AI app rebuilds. Auto-growing\n * multi-line input with:\n *\n * • slash-command picker (`/` triggers a filtered command palette,\n * ↑/↓ navigate, Enter inserts)\n * • mention picker (`@` triggers, filtered against `mentions`)\n * • drop-to-attach (drag files anywhere on the surface), paste-to-attach\n * (a pasted screenshot becomes an attachment) + chip bar\n * • submit on ⌘/Ctrl+Enter (plain Enter inserts a newline)\n * • live token-budget meter (green → amber → red as headroom drops)\n *\n * Wire it up:\n *\n * <PromptInput\n * budgetTokens={32000}\n * commands={[{ name: \"/rewrite\", hint: \"rewrite the selection\" }]}\n * mentions={[{ id: \"ada\", name: \"Ada\", kind: \"person\" }]}\n * onSubmit={(text, attachments) => sendToAgent(text, attachments)}\n * />\n */\nexport type PromptCmd = { name: string; hint: string };\nexport type PromptMention = {\n id: string;\n name: string;\n kind: \"agent\" | \"file\" | \"person\" | string;\n};\nexport type PromptAttachment = {\n id: string;\n name: string;\n bytes: number;\n /**\n * The file the user actually attached.\n *\n * Optional because an attachment restored from a server has no File — but for\n * anything the user dropped or picked it is always present. Without it a host\n * can render a chip and nothing else: no POST, no FormData, no send-to-model.\n */\n file?: File;\n /** MIME type. Hosts branch on this to decide whether a file can be sent as-is. */\n type?: string;\n};\n\n/**\n * `...rest` reaches the root surface, so a consumer or a bridge can tag the\n * composer with its own `data-*` handle. The component named every prop it\n * used and had no rest spread, which means a `data-handle` put on it was\n * DROPPED — silently, since React discards unknown props and the component\n * still renders perfectly. That is issue #22 all over again, and the contract\n * calls it out: \"Each interactive element has a stable identity. Agents never\n * guess DOM.\"\n */\nexport interface PromptInputProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"onSubmit\" | \"className\"> {\n /** Extra classes on the root surface. MERGED, never replaced. */\n className?: string;\n /** Token budget for the meter. */\n budgetTokens: number;\n /** Slash-commands. Names must start with `/`. */\n commands?: PromptCmd[];\n /** @-mentions. */\n mentions?: PromptMention[];\n /** Show the keyboard hint (\"Ctrl + Enter to send\", \"⌘ + Enter\" on a Mac). */\n showHint?: boolean;\n /**\n * Which modifier the hint and the default placeholder NAME. Omit it and the\n * component reads the platform after mount, which is the right answer for an\n * ordinary web app.\n *\n * Pass it when the host knows better than `navigator` does — an Electron\n * renderer forwarding `process.platform`, a remote session where the\n * keyboard is not the one running the browser, or a test that needs the\n * branch it is not sitting on. The pressed keys are unaffected either way:\n * submit is `⌘/Ctrl+Enter` on every platform, so this only decides which\n * true key gets named.\n */\n platform?: FancyPlatform;\n /** Called on ⌘/Ctrl+Enter or send button. */\n onSubmit: (text: string, attachments: PromptAttachment[]) => void;\n /**\n * Placeholder text. Defaults to a hint naming the modifier THIS platform\n * actually has, so leaving it unset is the better option — a hardcoded\n * placeholder is the other place a `⌘` ends up in front of a Windows user.\n */\n placeholder?: string;\n /** Rough estimator: chars-per-token. Defaults to 4. */\n charsPerToken?: number;\n /** Color → CSS chip mapping for mention kinds. */\n mentionColor?: Record<string, string>;\n /** Optional max textarea height in px. Defaults to 280. */\n maxHeight?: number;\n /**\n * Rendered INSIDE the rounded shell, ABOVE the attachments bar and\n * textarea. Use this slot for a drawer of tools/files/prompts/etc. so\n * the drawer and composer share one visual panel. See {@link ChatDrawer}.\n */\n aboveInput?: ReactNode;\n /**\n * Hold a paste of at least this many characters as a pill IN the message,\n * where it was pasted: on a line of its own, its full text put back in place\n * when clicked, and expanded where it sits when sent. Omit it and paste is\n * unchanged. Setting this (or `pasteImages`) swaps the textarea for an inline\n * editor that keeps the `/` and `@` pickers and the send key.\n */\n pasteThreshold?: number;\n /**\n * A pasted image becomes an inline `Pasted image N` pill AND reaches\n * `onSubmit`'s attachments, with its File, in message order; the text marks\n * where it sat as `[Pasted image N]`. Without it a pasted image is an\n * ordinary attachment chip, as before.\n */\n pasteImages?: boolean;\n /** Characters of a held paste shown at EACH end of its hover preview. Default 20. */\n previewChars?: number;\n /** Replace the paste pills' hover popover content. */\n renderPastePreview?: (preview: ComposerPastePreview) => ReactNode;\n /** Restyle the paste pills, their popover and the inline editor. Merged onto the defaults. */\n pasteClassNames?: ComposerPasteClassNames;\n /**\n * Submit pasted images with an enclosing `<form>`, under this field name: a\n * hidden `<input type=\"file\" multiple>` holds the images still in the message,\n * in message order. Needs `pasteImages`. They reach `onSubmit` either way.\n */\n pasteFilesName?: string;\n /** `\"icon\"`: an icon-only attach button whose tooltip says what it does. Default `\"label\"`. */\n attachButton?: \"label\" | \"icon\";\n /**\n * `\"icon\"`: a compact icon send button whose tooltip carries the shortcut —\n * replacing the inline `Ctrl + Enter to send` hint. Default `\"label\"`.\n */\n sendButton?: \"label\" | \"icon\";\n /**\n * Tokens already used — the caller's REAL value, e.g. an agent's context\n * usage. The meter shows this plus the estimate for the draft. Without it the\n * meter estimates the draft alone, as before.\n */\n usedTokens?: number;\n /**\n * `\"always\"` (default) — as before. `\"near-limit\"` — hidden until usage passes\n * `meterShowAt`, muted until `meterWarnAt`, warning colour past that.\n * `\"hidden\"` — never shown.\n */\n meter?: \"always\" | \"near-limit\" | \"hidden\";\n /** Fraction of `budgetTokens` at which a `\"near-limit\"` meter appears. Default 0.75. */\n meterShowAt?: number;\n /** Fraction of `budgetTokens` past which a `\"near-limit\"` meter takes the warning colour. Default 0.9. */\n meterWarnAt?: number;\n}\n\nconst DEFAULT_MENTION_COLOR: Record<string, string> = {\n agent: \"#a855f7\",\n file: \"#10b981\",\n person: \"#3b82f6\",\n};\n\nexport function PromptInput({\n budgetTokens,\n commands = [],\n mentions = [],\n showHint = true,\n platform,\n onSubmit,\n placeholder,\n charsPerToken = 4,\n mentionColor,\n maxHeight = 280,\n aboveInput,\n className,\n pasteThreshold,\n pasteImages = false,\n previewChars = 20,\n renderPastePreview,\n pasteClassNames,\n pasteFilesName,\n attachButton = \"label\",\n sendButton = \"label\",\n usedTokens,\n meter = \"always\",\n meterShowAt = 0.75,\n meterWarnAt = 0.9,\n ...rest\n}: PromptInputProps) {\n const [text, setText] = useState(\"\");\n /** Inline pills need an editor that can hold them; a textarea cannot. */\n const inline = pasteThreshold !== undefined || pasteImages;\n const editorRef = useRef<InlinePasteEditorHandle>(null);\n const paste = useInlinePaste({\n pasteThreshold,\n pasteImages,\n previewChars,\n renderPastePreview,\n classNames: pasteClassNames,\n disabled: false,\n editorRef,\n });\n const [attachments, setAttachments] = useState<PromptAttachment[]>([]);\n const [picker, setPicker] = useState<null | {\n kind: \"cmd\" | \"mention\";\n start: number;\n query: string;\n cursor: number;\n }>(null);\n const taRef = useRef<HTMLTextAreaElement>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const [dragOver, setDragOver] = useState(false);\n\n const colors = mentionColor ?? DEFAULT_MENTION_COLOR;\n\n /**\n * Resolved AFTER mount, never during render.\n *\n * `navigator` read during render disagrees with the server's HTML and\n * hydration patches it — so the fix for a wrong label would have introduced a\n * hydration mismatch instead. The first paint names `Ctrl`, which is\n * pressable on every platform including a Mac, and an Apple client swaps to\n * `⌘` on the next tick. A prop, when given, wins outright and no detection\n * runs at all.\n */\n const [detected, setDetected] = useState<FancyPlatform>(\"generic\");\n useEffect(() => {\n if (platform) return;\n setDetected(detectPlatform(browserPlatformHints()));\n }, [platform]);\n const modKey = modifierKeyLabel(platform ?? detected);\n\n const resolvedPlaceholder =\n placeholder ??\n `Ask anything. Type / for commands, @ for mentions. ${modKey}+Enter to send.`;\n\n // Estimated from what will actually be SENT — pills expanded — so a held\n // paste counts for its text, not for the few characters of its marker.\n const draftTokens = useMemo(\n () =>\n Math.ceil((inline ? paste.expand(text) : text).length / Math.max(1, charsPerToken)),\n [text, inline, paste, charsPerToken],\n );\n const tokens = (usedTokens ?? 0) + draftTokens;\n const ratio = Math.min(1, tokens / budgetTokens);\n const meterLevel: \"ok\" | \"caution\" | \"warn\" | \"muted\" | null =\n meter === \"hidden\"\n ? null\n : meter === \"near-limit\"\n ? ratio < meterShowAt\n ? null\n : ratio >= meterWarnAt\n ? \"warn\"\n : \"muted\"\n : ratio < 0.6\n ? \"ok\"\n : ratio < 0.85\n ? \"caution\"\n : \"warn\";\n const meterColor =\n meterLevel === \"ok\"\n ? \"#10b981\"\n : meterLevel === \"caution\"\n ? \"#f59e0b\"\n : meterLevel === \"warn\"\n ? \"#ef4444\"\n : \"#a1a1aa\";\n\n const filteredCmds = useMemo(\n () =>\n picker?.kind === \"cmd\"\n ? commands.filter((c) =>\n c.name.slice(1).toLowerCase().startsWith(picker.query.toLowerCase()),\n )\n : [],\n [picker, commands],\n );\n const filteredMentions = useMemo(\n () =>\n picker?.kind === \"mention\"\n ? mentions.filter((m) =>\n m.name.toLowerCase().includes(picker.query.toLowerCase()),\n )\n : [],\n [picker, mentions],\n );\n const items: Array<PromptCmd | PromptMention> =\n picker?.kind === \"cmd\"\n ? filteredCmds\n : picker?.kind === \"mention\"\n ? filteredMentions\n : [];\n\n useEffect(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.style.height = \"auto\";\n ta.style.height = Math.min(maxHeight, ta.scrollHeight) + \"px\";\n }, [text, maxHeight]);\n\n const updateText = (next: string, caret: number) => {\n setText(next);\n let triggerIdx = -1;\n let triggerKind: \"cmd\" | \"mention\" | null = null;\n for (let i = caret - 1; i >= 0; i--) {\n const ch = next[i];\n if (ch === \"@\") {\n triggerKind = \"mention\";\n triggerIdx = i;\n break;\n }\n if (ch === \"/\" && (i === 0 || /\\s/.test(next[i - 1] ?? \"\"))) {\n triggerKind = \"cmd\";\n triggerIdx = i;\n break;\n }\n if (/\\s/.test(ch)) break;\n }\n if (triggerKind !== null && triggerIdx >= 0) {\n const query = next.slice(triggerIdx + 1, caret);\n setPicker({ kind: triggerKind, start: triggerIdx, query, cursor: 0 });\n } else {\n setPicker(null);\n }\n };\n\n const insertChoice = (i: number) => {\n if (!picker || items.length === 0) return;\n const choice = items[i] ?? items[0];\n const insert =\n picker.kind === \"cmd\"\n ? (choice as PromptCmd).name + \" \"\n : `@${(choice as PromptMention).id} `;\n const before = text.slice(0, picker.start);\n const after = text.slice(picker.start + 1 + picker.query.length);\n const next = before + insert + after;\n setText(next);\n setPicker(null);\n if (inline) {\n // The editor rebuilds from the value and puts the caret back itself.\n editorRef.current?.setValue(next, before.length + insert.length);\n return;\n }\n requestAnimationFrame(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.focus();\n const pos = before.length + insert.length;\n ta.setSelectionRange(pos, pos);\n });\n };\n\n const submit = () => {\n // A message that is only a paste counts: its marker is in `text`.\n if (!text.trim() && attachments.length === 0) return;\n\n if (inline) {\n // Every pill goes out where it sits; pasted images join the attachments\n // in message order, with their Files, so a host sends them like any other.\n const pastedImages: PromptAttachment[] = paste.imagesIn(text).map((image) => ({\n id: image.id,\n name: image.file.name,\n bytes: image.file.size,\n file: image.file,\n type: image.file.type,\n }));\n onSubmit(paste.expand(text), [...attachments, ...pastedImages]);\n paste.clear();\n } else {\n onSubmit(text, attachments);\n }\n setText(\"\");\n setAttachments([]);\n setPicker(null);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (picker) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setPicker((p) =>\n p ? { ...p, cursor: Math.min(items.length - 1, p.cursor + 1) } : p,\n );\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setPicker((p) => (p ? { ...p, cursor: Math.max(0, p.cursor - 1) } : p));\n return;\n }\n // Tab completes, as Enter does: the autocomplete key people expect from a\n // shell or Claude Code. Only while a menu is open; otherwise Tab moves\n // focus as usual.\n if (((e.key === \"Enter\" && !e.metaKey && !e.ctrlKey) || (e.key === \"Tab\" && !e.shiftKey)) && items.length > 0) {\n e.preventDefault();\n insertChoice(picker.cursor);\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n setPicker(null);\n return;\n }\n }\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n submit();\n }\n };\n\n /**\n * Build attachments from a FileList, KEEPING the File.\n *\n * Shared by the drop handler and the picker so the two cannot drift — the\n * picker being a second, subtly different copy of this is exactly how one of\n * them would end up dropping the File again.\n */\n const attach = (list: FileList | File[] | null) => {\n const files = Array.from(list ?? []);\n if (files.length === 0) return;\n\n setAttachments((cur) => [\n ...cur,\n ...files.map((f) => ({\n id: crypto.randomUUID(),\n name: f.name,\n bytes: f.size,\n file: f,\n type: f.type,\n })),\n ]);\n };\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setDragOver(false);\n attach(e.dataTransfer.files);\n };\n\n /**\n * Paste a screenshot, get an attachment.\n *\n * There was no paste handler at all, so a pasted image did nothing — no chip,\n * no error — and a host that had swapped its own paste-capable textarea for\n * this component lost the feature without noticing.\n *\n * Files attach only when the clipboard carries NO plain text. Word, Excel and\n * most editors put a picture of the selection beside the text; attaching that\n * would turn every pasted sentence into a screenshot of the sentence. A pure\n * image paste has nothing for the browser to insert, so the default is\n * prevented only then, and a text paste is never touched.\n */\n const onPaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const data = e.clipboardData;\n const files = Array.from(data?.files ?? []);\n\n if (files.length === 0 || (data?.getData(\"text/plain\") ?? \"\") !== \"\") return;\n\n e.preventDefault();\n attach(files);\n };\n\n return (\n <div\n // Spread FIRST so an internal handler or data attribute cannot be\n // clobbered from outside, and so a missing one fails loudly here rather\n // than at a consumer's selector. `className` is merged below instead.\n {...rest}\n // The component had no root handle at all, so an agent reading the\n // composer had to guess at classes. The drag state is on it too: a bridge\n // that wants to know whether a drop is in flight should not have to infer\n // it from Tailwind colours.\n data-react-fancy-prompt-input=\"\"\n data-react-fancy-prompt-input-drag={dragOver ? \"over\" : \"idle\"}\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}\n className={cn(\n \"relative rounded-md border bg-white transition dark:bg-zinc-900\",\n dragOver\n ? \"border-violet-400 bg-violet-50/50 dark:border-violet-600 dark:bg-violet-950/30\"\n : \"border-zinc-200 dark:border-zinc-800\",\n className,\n )}\n >\n {aboveInput && (\n <div className=\"border-b border-zinc-200 dark:border-zinc-800\">\n {aboveInput}\n </div>\n )}\n {attachments.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 border-b border-zinc-200 px-3 py-2 dark:border-zinc-800\">\n {attachments.map((a) => (\n <span\n key={a.id}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-zinc-100 px-2 py-0.5 text-[11px] dark:bg-zinc-800\"\n >\n <Icon name=\"paperclip\" size=\"xs\" className=\"text-zinc-400\" />\n <span className=\"font-mono\">{a.name}</span>\n <span className=\"text-zinc-400\">{fmtSize(a.bytes)}</span>\n <button\n onClick={() =>\n setAttachments((cur) => cur.filter((x) => x.id !== a.id))\n }\n className=\"opacity-50 hover:opacity-100\"\n aria-label=\"Remove attachment\"\n >\n ×\n </button>\n </span>\n ))}\n </div>\n )}\n\n <div className=\"relative\">\n {inline ? (\n <>\n <InlinePasteEditor\n ref={editorRef}\n value={text}\n known={paste.known}\n onChange={(next, caret) => {\n updateText(next, caret);\n paste.prune(next);\n }}\n onSubmit={submit}\n submitKey=\"mod-enter\"\n onKeyDown={onKeyDown}\n onPaste={paste.decidePaste}\n onHostsChange={paste.onHostsChange}\n placeholder={resolvedPlaceholder}\n disabled={false}\n maxHeight={maxHeight}\n placeholderClassName=\"left-3 top-2.5 text-[14px] leading-relaxed\"\n className={cn(\n \"block min-h-[5.5rem] px-3 py-2.5 text-[14px] leading-relaxed\",\n pasteClassNames?.input,\n )}\n />\n {paste.portals}\n {pasteImages && pasteFilesName && (\n <PastedFilesInput\n name={pasteFilesName}\n files={paste.imagesIn(text).map((i) => i.file)}\n />\n )}\n </>\n ) : (\n <textarea\n ref={taRef}\n value={text}\n onChange={(e) => updateText(e.target.value, e.target.selectionStart)}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n placeholder={resolvedPlaceholder}\n spellCheck={false}\n className=\"block w-full resize-none bg-transparent px-3 py-2.5 text-[14px] leading-relaxed outline-none placeholder:text-zinc-400\"\n rows={3}\n />\n )}\n\n {picker && items.length > 0 && (\n <div className=\"absolute bottom-full left-2 z-10 mb-1 w-72 overflow-hidden rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900\">\n <div className=\"border-b border-zinc-100 bg-zinc-50 px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950\">\n {picker.kind === \"cmd\" ? \"Commands\" : \"Mention\"} · {items.length}\n </div>\n <ul className=\"max-h-56 overflow-y-auto\">\n {items.map((item, i) => {\n const active = i === picker.cursor;\n if (picker.kind === \"cmd\") {\n const c = item as PromptCmd;\n return (\n <li\n key={c.name}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`cursor-pointer px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <div className=\"font-mono font-medium text-violet-700 dark:text-violet-300\">\n {c.name}\n </div>\n <div className=\"text-[11px] text-zinc-500\">{c.hint}</div>\n </li>\n );\n }\n const m = item as PromptMention;\n return (\n <li\n key={m.id}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`flex cursor-pointer items-center gap-2 px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <span\n className=\"h-2 w-2 rounded-full\"\n style={{ backgroundColor: colors[m.kind] ?? \"#71717a\" }}\n />\n <span className=\"font-medium\">{m.name}</span>\n <span className=\"ml-auto text-[10px] uppercase tracking-wider text-zinc-400\">\n {m.kind}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n\n <div className=\"flex items-center gap-2 border-t border-zinc-200 bg-zinc-50/60 px-3 py-2 dark:border-zinc-800 dark:bg-zinc-900/40\">\n <Tooltip content={attachButton === \"icon\" ? \"Attach files — or drop them here\" : \"Drop files here, or click\"}>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n icon=\"paperclip\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-attach=\"\"\n // An icon alone has no name; the tooltip is not one a screen reader reads.\n aria-label={attachButton === \"icon\" ? \"Attach files\" : undefined}\n onClick={() => fileRef.current?.click()}\n >\n {attachButton === \"icon\" ? null : \"attach\"}\n </Button>\n </Tooltip>\n {/*\n The button above shipped with a no-op onClick and a tooltip reading\n \"Drop files here, or click\" — an affordance that lied. Drop-only also\n meant keyboard and touch users could not attach at all.\n\n It then shipped with a literal paperclip EMOJI as its icon, which\n needs a COLOUR\n EMOJI FONT — not merely broad coverage — so a lean container renders a\n tofu box where the affordance should be. `icon=\"paperclip\"` draws an\n SVG from the kit's own icon layer, which is the same reason the rest of\n the suite does not hand-roll iconography.\n */}\n <input\n ref={fileRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n attach(e.target.files);\n // Let the same file be picked twice in a row.\n e.target.value = \"\";\n }}\n />\n {meterLevel !== null && (\n <div\n data-react-fancy-prompt-input-meter=\"\"\n data-level={meterLevel}\n className=\"ml-2 flex min-w-0 items-center gap-1.5 overflow-hidden\"\n >\n <div className=\"h-1.5 w-24 shrink overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-700\">\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${ratio * 100}%`, backgroundColor: meterColor }}\n />\n </div>\n <span className=\"font-mono text-[11px]\" style={{ color: meterColor }}>\n {fmtTokens(tokens)} / {fmtTokens(budgetTokens)}\n </span>\n </div>\n )}\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {/* With an icon send button the shortcut lives in its tooltip instead. */}\n {showHint && sendButton !== \"icon\" && (\n <span\n className=\"hidden text-[10px] text-zinc-500 sm:inline\"\n data-react-fancy-prompt-input-hint={modKey === \"⌘\" ? \"apple\" : \"generic\"}\n >\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n {modKey}\n </kbd>{\" \"}\n +{\" \"}\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n Enter\n </kbd>{\" \"}\n to send\n </span>\n )}\n {sendButton === \"icon\" ? (\n <Tooltip content={`Send · ${modKey}+Enter`}>\n <Button\n color=\"violet\"\n size=\"sm\"\n icon=\"arrow-up\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-send=\"\"\n aria-label=\"Send\"\n onClick={submit}\n />\n </Tooltip>\n ) : (\n <Button\n color=\"violet\"\n size=\"sm\"\n iconTrailing=\"arrow-right\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-send=\"\"\n onClick={submit}\n >\n send\n </Button>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction fmtTokens(n: number): string {\n if (n < 1000) return `${n}`;\n return `${(n / 1000).toFixed(1)}k`;\n}\n\nfunction fmtSize(b: number): string {\n if (b < 1024) return `${b} B`;\n if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)} KB`;\n return `${(b / 1024 / 1024).toFixed(1)} MB`;\n}\n"]}
@@ -22,6 +22,7 @@ var FauxClient = forwardRef(
22
22
  maxZoom = 4,
23
23
  onFullscreenChange,
24
24
  fill = false,
25
+ applyZoom = true,
25
26
  className,
26
27
  barClassName,
27
28
  bodyClassName,
@@ -81,8 +82,9 @@ var FauxClient = forwardRef(
81
82
  };
82
83
  const isBrowser = variant === "browser";
83
84
  const isDevice = variant === "device";
84
- const effective = fit * zoom;
85
- const zoomed = zoom !== 1;
85
+ const appliedZoom = applyZoom ? zoom : 1;
86
+ const effective = fit * appliedZoom;
87
+ const zoomed = appliedZoom !== 1;
86
88
  const hasControls = showZoom || showFullscreen;
87
89
  const controlsBar = hasControls ? /* @__PURE__ */ jsxs(
88
90
  "div",
@@ -223,7 +225,7 @@ var FauxClient = forwardRef(
223
225
  {
224
226
  "data-react-fancy-faux-client-content": "",
225
227
  className: cn((fill || fullscreen) && "h-full"),
226
- style: zoomed ? { zoom: String(zoom) } : void 0,
228
+ style: zoomed ? { zoom: String(appliedZoom) } : void 0,
227
229
  children
228
230
  }
229
231
  )
@@ -276,5 +278,5 @@ function ExitFullscreenIcon() {
276
278
  }
277
279
 
278
280
  export { FauxClient };
279
- //# sourceMappingURL=chunk-A5ENSMZP.js.map
280
- //# sourceMappingURL=chunk-A5ENSMZP.js.map
281
+ //# sourceMappingURL=chunk-XWXV6HSK.js.map
282
+ //# sourceMappingURL=chunk-XWXV6HSK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/FauxClient/FauxClient.tsx"],"names":[],"mappings":"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","file":"chunk-XWXV6HSK.js","sourcesContent":["import { forwardRef, useCallback, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useControllableState } from \"../../hooks/use-controllable-state\";\nimport type { FauxClientProps } from \"./FauxClient.types\";\n\nconst DOT_COLORS = [\"bg-rose-300\", \"bg-amber-300\", \"bg-green-300\"];\n\n/** One click of the zoom bar. Matches `ImageViewer`, so the kit zooms one way. */\nconst ZOOM_STEP = 1.25;\n\nconst clamp = (n: number, min: number, max: number) => Math.min(max, Math.max(min, n));\n\n/**\n * A frame that mimics a browser window or device, rendering **real UI** inside.\n * With a logical `width` + `scale=\"fit\"` it renders a full-size page/app and\n * scales it down to fit any container (live thumbnails, device mockups) — the\n * content is real and interactive, just zoomed.\n *\n * Omit `width` for chrome around natural-size content (e.g. a code/preview card).\n *\n * `controls` adds a zoom bar and a full-screen button, for content that has to be\n * READ rather than glanced at: a slide or a sheet shrunk to fit a panel.\n */\nexport const FauxClient = forwardRef<HTMLDivElement, FauxClientProps>(\n (\n {\n variant = \"browser\",\n url,\n meta,\n dots = true,\n width,\n scale = \"fit\",\n controls = false,\n zoom: controlledZoom,\n defaultZoom = 1,\n onZoomChange,\n minZoom = 0.5,\n maxZoom = 4,\n onFullscreenChange,\n fill = false,\n applyZoom = true,\n className,\n barClassName,\n bodyClassName,\n children,\n ...rest\n },\n ref,\n ) => {\n const scaled = typeof width === \"number\";\n const rootRef = useRef<HTMLDivElement | null>(null);\n const viewportRef = useRef<HTMLDivElement>(null);\n const stageRef = useRef<HTMLDivElement>(null);\n const [fit, setFit] = useState(typeof scale === \"number\" ? scale : 1);\n const [naturalHeight, setNaturalHeight] = useState<number | undefined>(undefined);\n\n const showZoom = controls === true || (typeof controls === \"object\" && controls.zoom !== false);\n const showFullscreen = controls === true || (typeof controls === \"object\" && controls.fullscreen !== false);\n const [zoom, setZoom] = useControllableState(controlledZoom, defaultZoom, onZoomChange);\n const [fullscreen, setFullscreen] = useState(false);\n\n useLayoutEffect(() => {\n if (!scaled) return;\n const viewport = viewportRef.current;\n const stage = stageRef.current;\n if (!viewport || !stage) return;\n if (typeof ResizeObserver === \"undefined\") return;\n\n const measure = () => {\n const avail = viewport.clientWidth;\n setFit(scale === \"fit\" ? (width && width > 0 ? avail / width : 1) : scale);\n // offsetHeight is the pre-transform layout height (CSS transforms don't affect it).\n setNaturalHeight(stage.offsetHeight);\n };\n\n measure();\n const ro = new ResizeObserver(measure);\n ro.observe(viewport);\n ro.observe(stage);\n return () => ro.disconnect();\n }, [scaled, scale, width]);\n\n // Full screen is the browser's state, not ours: follow it, so Esc and the\n // browser's own exit leave the button telling the truth.\n useEffect(() => {\n if (!showFullscreen || typeof document === \"undefined\") return;\n const sync = () => {\n const on = document.fullscreenElement != null && document.fullscreenElement === rootRef.current;\n setFullscreen(on);\n onFullscreenChange?.(on);\n };\n document.addEventListener(\"fullscreenchange\", sync);\n return () => document.removeEventListener(\"fullscreenchange\", sync);\n }, [showFullscreen, onFullscreenChange]);\n\n const toggleFullscreen = useCallback(() => {\n const el = rootRef.current;\n if (!el || typeof document === \"undefined\") return;\n if (document.fullscreenElement === el) void document.exitFullscreen?.();\n else void el.requestFullscreen?.();\n }, []);\n\n const zoomBy = (factor: number) => {\n // Rounded so ten clicks in and ten out land back on 100%, not 99.99%.\n setZoom(clamp(Math.round(zoom * factor * 100) / 100, minZoom, maxZoom));\n };\n\n const setRefs = (el: HTMLDivElement | null) => {\n rootRef.current = el;\n if (typeof ref === \"function\") ref(el);\n else if (ref) ref.current = el;\n };\n\n const isBrowser = variant === \"browser\";\n const isDevice = variant === \"device\";\n // The zoom the FRAME applies: none when the content zooms itself.\n const appliedZoom = applyZoom ? zoom : 1;\n const effective = fit * appliedZoom;\n const zoomed = appliedZoom !== 1;\n const hasControls = showZoom || showFullscreen;\n\n /*\n * Out of the way until wanted: hidden, and revealed when the pointer is over\n * the frame or focus is inside it (keyboard). Always shown where there is no\n * hover to reveal it (touch), or it could never be reached.\n *\n * In the browser chrome it sits in the address bar, inline. On a device or a\n * bare frame there is no chrome, so it floats top-right as a slim strip: the\n * bottom corners belong to the content (a slide viewer's page count lives\n * there).\n */\n const controlsBar = hasControls ? (\n <div\n data-react-fancy-faux-client-controls=\"\"\n className={cn(\n \"pointer-events-auto flex shrink-0 items-center gap-px opacity-0 transition-opacity duration-150\",\n \"group-hover/faux-client:opacity-100 focus-within:opacity-100 [@media(hover:none)]:opacity-100\",\n isBrowser\n ? \"-my-1 text-zinc-400 dark:text-zinc-500\"\n : \"rounded-full bg-zinc-900/60 px-1 py-0.5 text-white/80 shadow-sm backdrop-blur-sm\",\n )}\n >\n {showZoom && (\n <>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-out=\"\"\n aria-label=\"Zoom out\"\n title=\"Zoom out\"\n disabled={zoom <= minZoom}\n onClick={() => zoomBy(1 / ZOOM_STEP)}\n className={controlButton(isBrowser)}\n >\n <ZoomOutIcon />\n </button>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-reset=\"\"\n aria-label=\"Reset zoom\"\n title=\"Reset zoom\"\n onClick={() => setZoom(1)}\n className={cn(controlButton(isBrowser), \"w-auto min-w-[2.25rem] px-1 font-sans text-[10.5px] tabular-nums\")}\n >\n {Math.round(zoom * 100)}%\n </button>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-in=\"\"\n aria-label=\"Zoom in\"\n title=\"Zoom in\"\n disabled={zoom >= maxZoom}\n onClick={() => zoomBy(ZOOM_STEP)}\n className={controlButton(isBrowser)}\n >\n <ZoomInIcon />\n </button>\n </>\n )}\n {showFullscreen && (\n <button\n type=\"button\"\n data-react-fancy-faux-client-fullscreen=\"\"\n aria-label={fullscreen ? \"Exit full screen\" : \"Full screen\"}\n aria-pressed={fullscreen}\n title={fullscreen ? \"Exit full screen\" : \"Full screen\"}\n onClick={toggleFullscreen}\n className={controlButton(isBrowser)}\n >\n {fullscreen ? <ExitFullscreenIcon /> : <FullscreenIcon />}\n </button>\n )}\n </div>\n ) : null;\n\n return (\n <div\n ref={setRefs}\n data-react-fancy-faux-client=\"\"\n data-fullscreen={showFullscreen ? String(fullscreen) : undefined}\n className={cn(\n \"group/faux-client relative overflow-hidden bg-white dark:bg-zinc-900\",\n isBrowser && \"rounded-2xl border border-zinc-200 shadow-xl dark:border-zinc-800\",\n isDevice && \"rounded-[2rem] border-[10px] border-zinc-800 shadow-2xl dark:border-zinc-700\",\n variant === \"bare\" && \"rounded-lg border border-zinc-200 dark:border-zinc-800\",\n // Fill (or full screen): the frame takes its parent's height and its\n // body takes whatever the chrome leaves.\n (fill || fullscreen) && \"flex flex-col\",\n fill && \"h-full\",\n fullscreen && \"rounded-none\",\n className,\n )}\n {...rest}\n >\n {isBrowser && (\n <div\n className={cn(\n \"flex items-center gap-2 border-b border-zinc-200 bg-zinc-50 px-3.5 py-2.5 font-mono text-[11.5px] text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-400\",\n barClassName,\n )}\n >\n {dots && (\n <div className=\"mr-1.5 flex gap-[5px]\">\n {DOT_COLORS.map((color, i) => (\n <span key={i} className={cn(\"h-[9px] w-[9px] rounded-full\", color)} />\n ))}\n </div>\n )}\n {url != null && <span className=\"min-w-0 flex-1 truncate\">{url}</span>}\n {meta != null && <span className=\"shrink-0 text-zinc-400 dark:text-zinc-500\">{meta}</span>}\n {hasControls && <div className={cn(url == null && meta == null && \"ml-auto\")}>{controlsBar}</div>}\n </div>\n )}\n\n <div\n ref={viewportRef}\n className={cn(\n \"relative\",\n // Zoomed in, the content is bigger than the frame: scroll to it.\n zoomed ? \"overflow-auto\" : \"overflow-hidden\",\n (fill || fullscreen) && \"min-h-0 flex-1\",\n bodyClassName,\n )}\n // The frame keeps its FIT height whatever the zoom; zooming scrolls.\n style={scaled && !fullscreen && naturalHeight !== undefined ? { height: naturalHeight * fit } : undefined}\n >\n {scaled ? (\n // A sizer the size of the zoomed content, so the scrollbars are right.\n <div\n style={\n naturalHeight !== undefined && width !== undefined\n ? { width: width * effective, height: naturalHeight * effective, position: \"relative\" }\n : undefined\n }\n >\n <div\n ref={stageRef}\n data-react-fancy-faux-client-content=\"\"\n className=\"absolute left-0 top-0 origin-top-left\"\n style={{ width, transform: `scale(${effective})` }}\n >\n {children}\n </div>\n </div>\n ) : (\n <div\n data-react-fancy-faux-client-content=\"\"\n className={cn((fill || fullscreen) && \"h-full\")}\n // CSS `zoom` rather than a transform: it changes layout size, so the\n // content reflows and the viewport scrolls to all of it.\n style={zoomed ? { zoom: String(appliedZoom) } : undefined}\n >\n {children}\n </div>\n )}\n </div>\n\n {hasControls && !isBrowser && (\n <div className=\"pointer-events-none absolute right-2 top-2 z-10\">{controlsBar}</div>\n )}\n </div>\n );\n },\n);\n\nFauxClient.displayName = \"FauxClient\";\n\n/** Ghost icon buttons: no box of their own, so the bar reads as part of the frame. */\nfunction controlButton(inBar: boolean): string {\n return cn(\n \"flex h-6 w-6 items-center justify-center rounded-full transition-colors disabled:pointer-events-none disabled:opacity-30\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50\",\n inBar\n ? \"hover:bg-zinc-900/5 hover:text-zinc-700 dark:hover:bg-white/10 dark:hover:text-zinc-200\"\n : \"hover:bg-white/15 hover:text-white\",\n );\n}\n\nfunction ZoomOutIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n <path d=\"M8 11h6\" />\n </svg>\n );\n}\n\nfunction ZoomInIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n <path d=\"M8 11h6\" />\n <path d=\"M11 8v6\" />\n </svg>\n );\n}\n\n/** Inline, like `Input`'s reveal icons: a frame should not need an icon set configured. */\nfunction FullscreenIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3\" />\n <path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" />\n <path d=\"M3 16v3a2 2 0 0 0 2 2h3\" />\n <path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" />\n </svg>\n );\n}\n\nfunction ExitFullscreenIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3\" />\n <path d=\"M21 8h-3a2 2 0 0 1-2-2V3\" />\n <path d=\"M3 16h3a2 2 0 0 1 2 2v3\" />\n <path d=\"M16 21v-3a2 2 0 0 1 2-2h3\" />\n </svg>\n );\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkS3WWYBL4_cjs = require('./chunk-S3WWYBL4.cjs');
3
+ var chunkDUOZSOSB_cjs = require('./chunk-DUOZSOSB.cjs');
4
4
  require('./chunk-SNHU2AI4.cjs');
5
5
  require('./chunk-ZU5Q77OT.cjs');
6
6
 
@@ -8,7 +8,7 @@ require('./chunk-ZU5Q77OT.cjs');
8
8
 
9
9
  Object.defineProperty(exports, "FauxClient", {
10
10
  enumerable: true,
11
- get: function () { return chunkS3WWYBL4_cjs.FauxClient; }
11
+ get: function () { return chunkDUOZSOSB_cjs.FauxClient; }
12
12
  });
13
13
  //# sourceMappingURL=faux-client.cjs.map
14
14
  //# sourceMappingURL=faux-client.cjs.map
@@ -47,6 +47,13 @@ interface FauxClientProps extends Omit<HTMLAttributes<HTMLDivElement>, "children
47
47
  * rather than to what is in it. Default `false`.
48
48
  */
49
49
  fill?: boolean;
50
+ /**
51
+ * `false`: the frame shows the zoom controls and keeps the zoom state, but
52
+ * does not scale the content; the content reads `zoom` (via `onZoomChange` or
53
+ * a controlled `zoom`) and zooms itself. For content that fits itself to its
54
+ * box (a slide viewer), which a scaled frame only re-fits. Default `true`.
55
+ */
56
+ applyZoom?: boolean;
50
57
  className?: string;
51
58
  /** Class for the browser bar. */
52
59
  barClassName?: string;
@@ -47,6 +47,13 @@ interface FauxClientProps extends Omit<HTMLAttributes<HTMLDivElement>, "children
47
47
  * rather than to what is in it. Default `false`.
48
48
  */
49
49
  fill?: boolean;
50
+ /**
51
+ * `false`: the frame shows the zoom controls and keeps the zoom state, but
52
+ * does not scale the content; the content reads `zoom` (via `onZoomChange` or
53
+ * a controlled `zoom`) and zooms itself. For content that fits itself to its
54
+ * box (a slide viewer), which a scaled frame only re-fits. Default `true`.
55
+ */
56
+ applyZoom?: boolean;
50
57
  className?: string;
51
58
  /** Class for the browser bar. */
52
59
  barClassName?: string;
@@ -1,4 +1,4 @@
1
- export { FauxClient } from './chunk-A5ENSMZP.js';
1
+ export { FauxClient } from './chunk-XWXV6HSK.js';
2
2
  import './chunk-EDYAXGUM.js';
3
3
  import './chunk-MMW2JGKZ.js';
4
4
  //# sourceMappingURL=faux-client.js.map
package/dist/index.cjs CHANGED
@@ -33,7 +33,7 @@ var chunkLLA33GKC_cjs = require('./chunk-LLA33GKC.cjs');
33
33
  var chunkWKNVZUWZ_cjs = require('./chunk-WKNVZUWZ.cjs');
34
34
  var chunkPFEFKLUV_cjs = require('./chunk-PFEFKLUV.cjs');
35
35
  var chunkRWOH2ADL_cjs = require('./chunk-RWOH2ADL.cjs');
36
- var chunkZ3FIU77M_cjs = require('./chunk-Z3FIU77M.cjs');
36
+ var chunkRBEQLBKI_cjs = require('./chunk-RBEQLBKI.cjs');
37
37
  var chunkWKAEAGMT_cjs = require('./chunk-WKAEAGMT.cjs');
38
38
  var chunkAE53RKWR_cjs = require('./chunk-AE53RKWR.cjs');
39
39
  var chunkGBGJWAXZ_cjs = require('./chunk-GBGJWAXZ.cjs');
@@ -61,7 +61,7 @@ var chunkZMD3PIYF_cjs = require('./chunk-ZMD3PIYF.cjs');
61
61
  var chunkTH7VP4CL_cjs = require('./chunk-TH7VP4CL.cjs');
62
62
  var chunkV35A6B7A_cjs = require('./chunk-V35A6B7A.cjs');
63
63
  var chunkRPVCMW64_cjs = require('./chunk-RPVCMW64.cjs');
64
- var chunkS3WWYBL4_cjs = require('./chunk-S3WWYBL4.cjs');
64
+ var chunkDUOZSOSB_cjs = require('./chunk-DUOZSOSB.cjs');
65
65
  var chunkT45XK5GN_cjs = require('./chunk-T45XK5GN.cjs');
66
66
  var chunkVKXNCYLE_cjs = require('./chunk-VKXNCYLE.cjs');
67
67
  var chunkOOZCJLEF_cjs = require('./chunk-OOZCJLEF.cjs');
@@ -259,19 +259,19 @@ Object.defineProperty(exports, "Progress", {
259
259
  });
260
260
  Object.defineProperty(exports, "PromptInput", {
261
261
  enumerable: true,
262
- get: function () { return chunkZ3FIU77M_cjs.PromptInput; }
262
+ get: function () { return chunkRBEQLBKI_cjs.PromptInput; }
263
263
  });
264
264
  Object.defineProperty(exports, "browserPlatformHints", {
265
265
  enumerable: true,
266
- get: function () { return chunkZ3FIU77M_cjs.browserPlatformHints; }
266
+ get: function () { return chunkRBEQLBKI_cjs.browserPlatformHints; }
267
267
  });
268
268
  Object.defineProperty(exports, "detectPlatform", {
269
269
  enumerable: true,
270
- get: function () { return chunkZ3FIU77M_cjs.detectPlatform; }
270
+ get: function () { return chunkRBEQLBKI_cjs.detectPlatform; }
271
271
  });
272
272
  Object.defineProperty(exports, "modifierKeyLabel", {
273
273
  enumerable: true,
274
- get: function () { return chunkZ3FIU77M_cjs.modifierKeyLabel; }
274
+ get: function () { return chunkRBEQLBKI_cjs.modifierKeyLabel; }
275
275
  });
276
276
  Object.defineProperty(exports, "PullQuote", {
277
277
  enumerable: true,
@@ -467,7 +467,7 @@ Object.defineProperty(exports, "useMenu", {
467
467
  });
468
468
  Object.defineProperty(exports, "FauxClient", {
469
469
  enumerable: true,
470
- get: function () { return chunkS3WWYBL4_cjs.FauxClient; }
470
+ get: function () { return chunkDUOZSOSB_cjs.FauxClient; }
471
471
  });
472
472
  Object.defineProperty(exports, "FileBrowser", {
473
473
  enumerable: true,
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ export { Pillbox } from './chunk-FSRPZYZZ.js';
31
31
  export { Popover, usePopover } from './chunk-6KXAFP2T.js';
32
32
  export { Profile } from './chunk-KQQA7JBC.js';
33
33
  export { Progress } from './chunk-P7PKK5BO.js';
34
- export { PromptInput, browserPlatformHints, detectPlatform, modifierKeyLabel } from './chunk-JZCAMPIA.js';
34
+ export { PromptInput, browserPlatformHints, detectPlatform, modifierKeyLabel } from './chunk-QSAYIYEB.js';
35
35
  export { PullQuote } from './chunk-NDUEPDNS.js';
36
36
  export { QrCode, encodeQr, selectMode } from './chunk-RLE5WYY6.js';
37
37
  export { MobileMenu, useMobileMenu } from './chunk-P7F32HIH.js';
@@ -59,7 +59,7 @@ export { MediaViewer, resolveMediaType } from './chunk-KO2HLNBB.js';
59
59
  export { VideoViewer } from './chunk-VOGI7GX3.js';
60
60
  export { PdfViewer } from './chunk-SOYORSLZ.js';
61
61
  export { Menu, useMenu } from './chunk-RA2VOQ46.js';
62
- export { FauxClient } from './chunk-A5ENSMZP.js';
62
+ export { FauxClient } from './chunk-XWXV6HSK.js';
63
63
  export { FileBrowser, FileBrowserNewFolder, useFileBrowser, validateFolderName } from './chunk-2KAJ4L7C.js';
64
64
  export { FileUpload, useFileUpload } from './chunk-W6RDAZJC.js';
65
65
  export { Grid } from './chunk-TM3RTWKI.js';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkZ3FIU77M_cjs = require('./chunk-Z3FIU77M.cjs');
3
+ var chunkRBEQLBKI_cjs = require('./chunk-RBEQLBKI.cjs');
4
4
  require('./chunk-AIA5UNQ5.cjs');
5
5
  require('./chunk-MSRYJETY.cjs');
6
6
  require('./chunk-X7H75WVP.cjs');
@@ -18,7 +18,7 @@ require('./chunk-ZU5Q77OT.cjs');
18
18
 
19
19
  Object.defineProperty(exports, "PromptInput", {
20
20
  enumerable: true,
21
- get: function () { return chunkZ3FIU77M_cjs.PromptInput; }
21
+ get: function () { return chunkRBEQLBKI_cjs.PromptInput; }
22
22
  });
23
23
  //# sourceMappingURL=prompt-input.cjs.map
24
24
  //# sourceMappingURL=prompt-input.cjs.map
@@ -1,4 +1,4 @@
1
- export { PromptInput } from './chunk-JZCAMPIA.js';
1
+ export { PromptInput } from './chunk-QSAYIYEB.js';
2
2
  import './chunk-TJ66S5K6.js';
3
3
  import './chunk-KYZNCVRD.js';
4
4
  import './chunk-CF5KRDN4.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/react-fancy",
3
- "version": "5.46.0",
3
+ "version": "5.48.0",
4
4
  "description": "React UI component library for Human+ UX — controlled, agent-bridgeable primitives",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/FauxClient/FauxClient.tsx"],"names":[],"mappings":";;;;;AAKA,IAAM,UAAA,GAAa,CAAC,aAAA,EAAe,cAAA,EAAgB,cAAc,CAAA;AAGjE,IAAM,SAAA,GAAY,IAAA;AAElB,IAAM,KAAA,GAAQ,CAAC,CAAA,EAAW,GAAA,EAAa,GAAA,KAAgB,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,CAAC,CAAC,CAAA;AAa9E,IAAM,UAAA,GAAa,UAAA;AAAA,EACxB,CACE;AAAA,IACE,OAAA,GAAU,SAAA;AAAA,IACV,GAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA,GAAO,IAAA;AAAA,IACP,KAAA;AAAA,IACA,KAAA,GAAQ,KAAA;AAAA,IACR,QAAA,GAAW,KAAA;AAAA,IACX,IAAA,EAAM,cAAA;AAAA,IACN,WAAA,GAAc,CAAA;AAAA,IACd,YAAA;AAAA,IACA,OAAA,GAAU,GAAA;AAAA,IACV,OAAA,GAAU,CAAA;AAAA,IACV,kBAAA;AAAA,IACA,IAAA,GAAO,KAAA;AAAA,IACP,SAAA;AAAA,IACA,YAAA;AAAA,IACA,aAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,MAAA,GAAS,OAAO,KAAA,KAAU,QAAA;AAChC,IAAA,MAAM,OAAA,GAAU,OAA8B,IAAI,CAAA;AAClD,IAAA,MAAM,WAAA,GAAc,OAAuB,IAAI,CAAA;AAC/C,IAAA,MAAM,QAAA,GAAW,OAAuB,IAAI,CAAA;AAC5C,IAAA,MAAM,CAAC,KAAK,MAAM,CAAA,GAAI,SAAS,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,CAAC,CAAA;AACpE,IAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAA6B,MAAS,CAAA;AAEhF,IAAA,MAAM,WAAW,QAAA,KAAa,IAAA,IAAS,OAAO,QAAA,KAAa,QAAA,IAAY,SAAS,IAAA,KAAS,KAAA;AACzF,IAAA,MAAM,iBAAiB,QAAA,KAAa,IAAA,IAAS,OAAO,QAAA,KAAa,QAAA,IAAY,SAAS,UAAA,KAAe,KAAA;AACrG,IAAA,MAAM,CAAC,IAAA,EAAM,OAAO,IAAI,oBAAA,CAAqB,cAAA,EAAgB,aAAa,YAAY,CAAA;AACtF,IAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAS,KAAK,CAAA;AAElD,IAAA,eAAA,CAAgB,MAAM;AACpB,MAAA,IAAI,CAAC,MAAA,EAAQ;AACb,MAAA,MAAM,WAAW,WAAA,CAAY,OAAA;AAC7B,MAAA,MAAM,QAAQ,QAAA,CAAS,OAAA;AACvB,MAAA,IAAI,CAAC,QAAA,IAAY,CAAC,KAAA,EAAO;AACzB,MAAA,IAAI,OAAO,mBAAmB,WAAA,EAAa;AAE3C,MAAA,MAAM,UAAU,MAAM;AACpB,QAAA,MAAM,QAAQ,QAAA,CAAS,WAAA;AACvB,QAAA,MAAA,CAAO,KAAA,KAAU,QAAS,KAAA,IAAS,KAAA,GAAQ,IAAI,KAAA,GAAQ,KAAA,GAAQ,IAAK,KAAK,CAAA;AAEzE,QAAA,gBAAA,CAAiB,MAAM,YAAY,CAAA;AAAA,MACrC,CAAA;AAEA,MAAA,OAAA,EAAQ;AACR,MAAA,MAAM,EAAA,GAAK,IAAI,cAAA,CAAe,OAAO,CAAA;AACrC,MAAA,EAAA,CAAG,QAAQ,QAAQ,CAAA;AACnB,MAAA,EAAA,CAAG,QAAQ,KAAK,CAAA;AAChB,MAAA,OAAO,MAAM,GAAG,UAAA,EAAW;AAAA,IAC7B,CAAA,EAAG,CAAC,MAAA,EAAQ,KAAA,EAAO,KAAK,CAAC,CAAA;AAIzB,IAAA,SAAA,CAAU,MAAM;AACd,MAAA,IAAI,CAAC,cAAA,IAAkB,OAAO,QAAA,KAAa,WAAA,EAAa;AACxD,MAAA,MAAM,OAAO,MAAM;AACjB,QAAA,MAAM,KAAK,QAAA,CAAS,iBAAA,IAAqB,IAAA,IAAQ,QAAA,CAAS,sBAAsB,OAAA,CAAQ,OAAA;AACxF,QAAA,aAAA,CAAc,EAAE,CAAA;AAChB,QAAA,kBAAA,GAAqB,EAAE,CAAA;AAAA,MACzB,CAAA;AACA,MAAA,QAAA,CAAS,gBAAA,CAAiB,oBAAoB,IAAI,CAAA;AAClD,MAAA,OAAO,MAAM,QAAA,CAAS,mBAAA,CAAoB,kBAAA,EAAoB,IAAI,CAAA;AAAA,IACpE,CAAA,EAAG,CAAC,cAAA,EAAgB,kBAAkB,CAAC,CAAA;AAEvC,IAAA,MAAM,gBAAA,GAAmB,YAAY,MAAM;AACzC,MAAA,MAAM,KAAK,OAAA,CAAQ,OAAA;AACnB,MAAA,IAAI,CAAC,EAAA,IAAM,OAAO,QAAA,KAAa,WAAA,EAAa;AAC5C,MAAA,IAAI,QAAA,CAAS,iBAAA,KAAsB,EAAA,EAAI,KAAK,SAAS,cAAA,IAAiB;AAAA,WACjE,KAAK,GAAG,iBAAA,IAAoB;AAAA,IACnC,CAAA,EAAG,EAAE,CAAA;AAEL,IAAA,MAAM,MAAA,GAAS,CAAC,MAAA,KAAmB;AAEjC,MAAA,OAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,IAAA,GAAO,MAAA,GAAS,GAAG,CAAA,GAAI,GAAA,EAAK,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,IACxE,CAAA;AAEA,IAAA,MAAM,OAAA,GAAU,CAAC,EAAA,KAA8B;AAC7C,MAAA,OAAA,CAAQ,OAAA,GAAU,EAAA;AAClB,MAAA,IAAI,OAAO,GAAA,KAAQ,UAAA,EAAY,GAAA,CAAI,EAAE,CAAA;AAAA,WAAA,IAC5B,GAAA,MAAS,OAAA,GAAU,EAAA;AAAA,IAC9B,CAAA;AAEA,IAAA,MAAM,YAAY,OAAA,KAAY,SAAA;AAC9B,IAAA,MAAM,WAAW,OAAA,KAAY,QAAA;AAC7B,IAAA,MAAM,YAAY,GAAA,GAAM,IAAA;AACxB,IAAA,MAAM,SAAS,IAAA,KAAS,CAAA;AACxB,IAAA,MAAM,cAAc,QAAA,IAAY,cAAA;AAYhC,IAAA,MAAM,cAAc,WAAA,mBAClB,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,uCAAA,EAAsC,EAAA;AAAA,QACtC,SAAA,EAAW,EAAA;AAAA,UACT,iGAAA;AAAA,UACA,+FAAA;AAAA,UACA,YACI,wCAAA,GACA;AAAA,SACN;AAAA,QAEC,QAAA,EAAA;AAAA,UAAA,QAAA,oBACC,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,4BAAA,GAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,uCAAA,EAAsC,EAAA;AAAA,gBACtC,YAAA,EAAW,UAAA;AAAA,gBACX,KAAA,EAAM,UAAA;AAAA,gBACN,UAAU,IAAA,IAAQ,OAAA;AAAA,gBAClB,OAAA,EAAS,MAAM,MAAA,CAAO,CAAA,GAAI,SAAS,CAAA;AAAA,gBACnC,SAAA,EAAW,cAAc,SAAS,CAAA;AAAA,gBAElC,8BAAC,WAAA,EAAA,EAAY;AAAA;AAAA,aACf;AAAA,4BACA,IAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,yCAAA,EAAwC,EAAA;AAAA,gBACxC,YAAA,EAAW,YAAA;AAAA,gBACX,KAAA,EAAM,YAAA;AAAA,gBACN,OAAA,EAAS,MAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,gBACxB,SAAA,EAAW,EAAA,CAAG,aAAA,CAAc,SAAS,GAAG,kEAAkE,CAAA;AAAA,gBAEzG,QAAA,EAAA;AAAA,kBAAA,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AAAA,kBAAE;AAAA;AAAA;AAAA,aAC1B;AAAA,4BACA,GAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,sCAAA,EAAqC,EAAA;AAAA,gBACrC,YAAA,EAAW,SAAA;AAAA,gBACX,KAAA,EAAM,SAAA;AAAA,gBACN,UAAU,IAAA,IAAQ,OAAA;AAAA,gBAClB,OAAA,EAAS,MAAM,MAAA,CAAO,SAAS,CAAA;AAAA,gBAC/B,SAAA,EAAW,cAAc,SAAS,CAAA;AAAA,gBAElC,8BAAC,UAAA,EAAA,EAAW;AAAA;AAAA;AACd,WAAA,EACF,CAAA;AAAA,UAED,cAAA,oBACC,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,yCAAA,EAAwC,EAAA;AAAA,cACxC,YAAA,EAAY,aAAa,kBAAA,GAAqB,aAAA;AAAA,cAC9C,cAAA,EAAc,UAAA;AAAA,cACd,KAAA,EAAO,aAAa,kBAAA,GAAqB,aAAA;AAAA,cACzC,OAAA,EAAS,gBAAA;AAAA,cACT,SAAA,EAAW,cAAc,SAAS,CAAA;AAAA,cAEjC,QAAA,EAAA,UAAA,mBAAa,GAAA,CAAC,kBAAA,EAAA,EAAmB,CAAA,uBAAM,cAAA,EAAA,EAAe;AAAA;AAAA;AACzD;AAAA;AAAA,KAEJ,GACE,IAAA;AAEJ,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,OAAA;AAAA,QACL,8BAAA,EAA6B,EAAA;AAAA,QAC7B,iBAAA,EAAiB,cAAA,GAAiB,MAAA,CAAO,UAAU,CAAA,GAAI,MAAA;AAAA,QACvD,SAAA,EAAW,EAAA;AAAA,UACT,sEAAA;AAAA,UACA,SAAA,IAAa,mEAAA;AAAA,UACb,QAAA,IAAY,8EAAA;AAAA,UACZ,YAAY,MAAA,IAAU,wDAAA;AAAA;AAAA;AAAA,UAAA,CAGrB,QAAQ,UAAA,KAAe,eAAA;AAAA,UACxB,IAAA,IAAQ,QAAA;AAAA,UACR,UAAA,IAAc,cAAA;AAAA,UACd;AAAA,SACF;AAAA,QACC,GAAG,IAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,SAAA,oBACC,IAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,EAAA;AAAA,gBACT,0KAAA;AAAA,gBACA;AAAA,eACF;AAAA,cAEC,QAAA,EAAA;AAAA,gBAAA,IAAA,wBACE,KAAA,EAAA,EAAI,SAAA,EAAU,yBACZ,QAAA,EAAA,UAAA,CAAW,GAAA,CAAI,CAAC,KAAA,EAAO,CAAA,qBACtB,GAAA,CAAC,MAAA,EAAA,EAAa,WAAW,EAAA,CAAG,8BAAA,EAAgC,KAAK,CAAA,EAAA,EAAtD,CAAyD,CACrE,CAAA,EACH,CAAA;AAAA,gBAED,OAAO,IAAA,oBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2BAA2B,QAAA,EAAA,GAAA,EAAI,CAAA;AAAA,gBAC9D,QAAQ,IAAA,oBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,6CAA6C,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,gBAClF,WAAA,oBAAe,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,GAAA,IAAO,IAAA,IAAQ,IAAA,IAAQ,IAAA,IAAQ,SAAS,CAAA,EAAI,QAAA,EAAA,WAAA,EAAY;AAAA;AAAA;AAAA,WAC7F;AAAA,0BAGF,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,GAAA,EAAK,WAAA;AAAA,cACL,SAAA,EAAW,EAAA;AAAA,gBACT,UAAA;AAAA;AAAA,gBAEA,SAAS,eAAA,GAAkB,iBAAA;AAAA,gBAAA,CAC1B,QAAQ,UAAA,KAAe,gBAAA;AAAA,gBACxB;AAAA,eACF;AAAA,cAEA,KAAA,EAAO,MAAA,IAAU,CAAC,UAAA,IAAc,aAAA,KAAkB,SAAY,EAAE,MAAA,EAAQ,aAAA,GAAgB,GAAA,EAAI,GAAI,MAAA;AAAA,cAE/F,QAAA,EAAA,MAAA;AAAA;AAAA,gCAEC,GAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,KAAA,EACE,aAAA,KAAkB,MAAA,IAAa,KAAA,KAAU,SACrC,EAAE,KAAA,EAAO,KAAA,GAAQ,SAAA,EAAW,MAAA,EAAQ,aAAA,GAAgB,SAAA,EAAW,QAAA,EAAU,YAAW,GACpF,MAAA;AAAA,oBAGN,QAAA,kBAAA,GAAA;AAAA,sBAAC,KAAA;AAAA,sBAAA;AAAA,wBACC,GAAA,EAAK,QAAA;AAAA,wBACL,sCAAA,EAAqC,EAAA;AAAA,wBACrC,SAAA,EAAU,uCAAA;AAAA,wBACV,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,CAAA,MAAA,EAAS,SAAS,CAAA,CAAA,CAAA,EAAI;AAAA,wBAEhD;AAAA;AAAA;AACH;AAAA;AACF,kCAEA,GAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,sCAAA,EAAqC,EAAA;AAAA,kBACrC,SAAA,EAAW,EAAA,CAAA,CAAI,IAAA,IAAQ,UAAA,KAAe,QAAQ,CAAA;AAAA,kBAG9C,OAAO,MAAA,GAAS,EAAE,MAAM,MAAA,CAAO,IAAI,GAAE,GAAI,MAAA;AAAA,kBAExC;AAAA;AAAA;AACH;AAAA,WAEJ;AAAA,UAEC,eAAe,CAAC,SAAA,wBACd,KAAA,EAAA,EAAI,SAAA,EAAU,mDAAmD,QAAA,EAAA,WAAA,EAAY;AAAA;AAAA;AAAA,KAElF;AAAA,EAEJ;AACF;AAEA,UAAA,CAAW,WAAA,GAAc,YAAA;AAGzB,SAAS,cAAc,KAAA,EAAwB;AAC7C,EAAA,OAAO,EAAA;AAAA,IACL,0HAAA;AAAA,IACA,gFAAA;AAAA,IACA,QACI,yFAAA,GACA;AAAA,GACN;AACF;AAEA,SAAS,WAAA,GAAc;AACrB,EAAA,4BACG,KAAA,EAAA,EAAI,KAAA,EAAM,MAAK,MAAA,EAAO,IAAA,EAAK,SAAQ,WAAA,EAAY,IAAA,EAAK,QAAO,MAAA,EAAO,cAAA,EAAe,aAAY,GAAA,EAAI,aAAA,EAAc,SAAQ,cAAA,EAAe,OAAA,EAAQ,eAAY,MAAA,EACzJ,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,YAAO,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,GAAE,GAAA,EAAI,CAAA;AAAA,oBAC9B,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,gBAAA,EAAiB,CAAA;AAAA,oBACzB,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,SAAA,EAAU;AAAA,GAAA,EACpB,CAAA;AAEJ;AAEA,SAAS,UAAA,GAAa;AACpB,EAAA,4BACG,KAAA,EAAA,EAAI,KAAA,EAAM,MAAK,MAAA,EAAO,IAAA,EAAK,SAAQ,WAAA,EAAY,IAAA,EAAK,QAAO,MAAA,EAAO,cAAA,EAAe,aAAY,GAAA,EAAI,aAAA,EAAc,SAAQ,cAAA,EAAe,OAAA,EAAQ,eAAY,MAAA,EACzJ,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,YAAO,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,GAAE,GAAA,EAAI,CAAA;AAAA,oBAC9B,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,gBAAA,EAAiB,CAAA;AAAA,oBACzB,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,SAAA,EAAU,CAAA;AAAA,oBAClB,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,SAAA,EAAU;AAAA,GAAA,EACpB,CAAA;AAEJ;AAGA,SAAS,cAAA,GAAiB;AACxB,EAAA,4BACG,KAAA,EAAA,EAAI,KAAA,EAAM,MAAK,MAAA,EAAO,IAAA,EAAK,SAAQ,WAAA,EAAY,IAAA,EAAK,QAAO,MAAA,EAAO,cAAA,EAAe,aAAY,GAAA,EAAI,aAAA,EAAc,SAAQ,cAAA,EAAe,OAAA,EAAQ,eAAY,MAAA,EACzJ,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,wBAAA,EAAyB,CAAA;AAAA,oBACjC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,0BAAA,EAA2B,CAAA;AAAA,oBACnC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,yBAAA,EAA0B,CAAA;AAAA,oBAClC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,2BAAA,EAA4B;AAAA,GAAA,EACtC,CAAA;AAEJ;AAEA,SAAS,kBAAA,GAAqB;AAC5B,EAAA,4BACG,KAAA,EAAA,EAAI,KAAA,EAAM,MAAK,MAAA,EAAO,IAAA,EAAK,SAAQ,WAAA,EAAY,IAAA,EAAK,QAAO,MAAA,EAAO,cAAA,EAAe,aAAY,GAAA,EAAI,aAAA,EAAc,SAAQ,cAAA,EAAe,OAAA,EAAQ,eAAY,MAAA,EACzJ,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,wBAAA,EAAyB,CAAA;AAAA,oBACjC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,0BAAA,EAA2B,CAAA;AAAA,oBACnC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,yBAAA,EAA0B,CAAA;AAAA,oBAClC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,2BAAA,EAA4B;AAAA,GAAA,EACtC,CAAA;AAEJ","file":"chunk-A5ENSMZP.js","sourcesContent":["import { forwardRef, useCallback, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useControllableState } from \"../../hooks/use-controllable-state\";\nimport type { FauxClientProps } from \"./FauxClient.types\";\n\nconst DOT_COLORS = [\"bg-rose-300\", \"bg-amber-300\", \"bg-green-300\"];\n\n/** One click of the zoom bar. Matches `ImageViewer`, so the kit zooms one way. */\nconst ZOOM_STEP = 1.25;\n\nconst clamp = (n: number, min: number, max: number) => Math.min(max, Math.max(min, n));\n\n/**\n * A frame that mimics a browser window or device, rendering **real UI** inside.\n * With a logical `width` + `scale=\"fit\"` it renders a full-size page/app and\n * scales it down to fit any container (live thumbnails, device mockups) — the\n * content is real and interactive, just zoomed.\n *\n * Omit `width` for chrome around natural-size content (e.g. a code/preview card).\n *\n * `controls` adds a zoom bar and a full-screen button, for content that has to be\n * READ rather than glanced at: a slide or a sheet shrunk to fit a panel.\n */\nexport const FauxClient = forwardRef<HTMLDivElement, FauxClientProps>(\n (\n {\n variant = \"browser\",\n url,\n meta,\n dots = true,\n width,\n scale = \"fit\",\n controls = false,\n zoom: controlledZoom,\n defaultZoom = 1,\n onZoomChange,\n minZoom = 0.5,\n maxZoom = 4,\n onFullscreenChange,\n fill = false,\n className,\n barClassName,\n bodyClassName,\n children,\n ...rest\n },\n ref,\n ) => {\n const scaled = typeof width === \"number\";\n const rootRef = useRef<HTMLDivElement | null>(null);\n const viewportRef = useRef<HTMLDivElement>(null);\n const stageRef = useRef<HTMLDivElement>(null);\n const [fit, setFit] = useState(typeof scale === \"number\" ? scale : 1);\n const [naturalHeight, setNaturalHeight] = useState<number | undefined>(undefined);\n\n const showZoom = controls === true || (typeof controls === \"object\" && controls.zoom !== false);\n const showFullscreen = controls === true || (typeof controls === \"object\" && controls.fullscreen !== false);\n const [zoom, setZoom] = useControllableState(controlledZoom, defaultZoom, onZoomChange);\n const [fullscreen, setFullscreen] = useState(false);\n\n useLayoutEffect(() => {\n if (!scaled) return;\n const viewport = viewportRef.current;\n const stage = stageRef.current;\n if (!viewport || !stage) return;\n if (typeof ResizeObserver === \"undefined\") return;\n\n const measure = () => {\n const avail = viewport.clientWidth;\n setFit(scale === \"fit\" ? (width && width > 0 ? avail / width : 1) : scale);\n // offsetHeight is the pre-transform layout height (CSS transforms don't affect it).\n setNaturalHeight(stage.offsetHeight);\n };\n\n measure();\n const ro = new ResizeObserver(measure);\n ro.observe(viewport);\n ro.observe(stage);\n return () => ro.disconnect();\n }, [scaled, scale, width]);\n\n // Full screen is the browser's state, not ours: follow it, so Esc and the\n // browser's own exit leave the button telling the truth.\n useEffect(() => {\n if (!showFullscreen || typeof document === \"undefined\") return;\n const sync = () => {\n const on = document.fullscreenElement != null && document.fullscreenElement === rootRef.current;\n setFullscreen(on);\n onFullscreenChange?.(on);\n };\n document.addEventListener(\"fullscreenchange\", sync);\n return () => document.removeEventListener(\"fullscreenchange\", sync);\n }, [showFullscreen, onFullscreenChange]);\n\n const toggleFullscreen = useCallback(() => {\n const el = rootRef.current;\n if (!el || typeof document === \"undefined\") return;\n if (document.fullscreenElement === el) void document.exitFullscreen?.();\n else void el.requestFullscreen?.();\n }, []);\n\n const zoomBy = (factor: number) => {\n // Rounded so ten clicks in and ten out land back on 100%, not 99.99%.\n setZoom(clamp(Math.round(zoom * factor * 100) / 100, minZoom, maxZoom));\n };\n\n const setRefs = (el: HTMLDivElement | null) => {\n rootRef.current = el;\n if (typeof ref === \"function\") ref(el);\n else if (ref) ref.current = el;\n };\n\n const isBrowser = variant === \"browser\";\n const isDevice = variant === \"device\";\n const effective = fit * zoom;\n const zoomed = zoom !== 1;\n const hasControls = showZoom || showFullscreen;\n\n /*\n * Out of the way until wanted: hidden, and revealed when the pointer is over\n * the frame or focus is inside it (keyboard). Always shown where there is no\n * hover to reveal it (touch), or it could never be reached.\n *\n * In the browser chrome it sits in the address bar, inline. On a device or a\n * bare frame there is no chrome, so it floats top-right as a slim strip: the\n * bottom corners belong to the content (a slide viewer's page count lives\n * there).\n */\n const controlsBar = hasControls ? (\n <div\n data-react-fancy-faux-client-controls=\"\"\n className={cn(\n \"pointer-events-auto flex shrink-0 items-center gap-px opacity-0 transition-opacity duration-150\",\n \"group-hover/faux-client:opacity-100 focus-within:opacity-100 [@media(hover:none)]:opacity-100\",\n isBrowser\n ? \"-my-1 text-zinc-400 dark:text-zinc-500\"\n : \"rounded-full bg-zinc-900/60 px-1 py-0.5 text-white/80 shadow-sm backdrop-blur-sm\",\n )}\n >\n {showZoom && (\n <>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-out=\"\"\n aria-label=\"Zoom out\"\n title=\"Zoom out\"\n disabled={zoom <= minZoom}\n onClick={() => zoomBy(1 / ZOOM_STEP)}\n className={controlButton(isBrowser)}\n >\n <ZoomOutIcon />\n </button>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-reset=\"\"\n aria-label=\"Reset zoom\"\n title=\"Reset zoom\"\n onClick={() => setZoom(1)}\n className={cn(controlButton(isBrowser), \"w-auto min-w-[2.25rem] px-1 font-sans text-[10.5px] tabular-nums\")}\n >\n {Math.round(zoom * 100)}%\n </button>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-in=\"\"\n aria-label=\"Zoom in\"\n title=\"Zoom in\"\n disabled={zoom >= maxZoom}\n onClick={() => zoomBy(ZOOM_STEP)}\n className={controlButton(isBrowser)}\n >\n <ZoomInIcon />\n </button>\n </>\n )}\n {showFullscreen && (\n <button\n type=\"button\"\n data-react-fancy-faux-client-fullscreen=\"\"\n aria-label={fullscreen ? \"Exit full screen\" : \"Full screen\"}\n aria-pressed={fullscreen}\n title={fullscreen ? \"Exit full screen\" : \"Full screen\"}\n onClick={toggleFullscreen}\n className={controlButton(isBrowser)}\n >\n {fullscreen ? <ExitFullscreenIcon /> : <FullscreenIcon />}\n </button>\n )}\n </div>\n ) : null;\n\n return (\n <div\n ref={setRefs}\n data-react-fancy-faux-client=\"\"\n data-fullscreen={showFullscreen ? String(fullscreen) : undefined}\n className={cn(\n \"group/faux-client relative overflow-hidden bg-white dark:bg-zinc-900\",\n isBrowser && \"rounded-2xl border border-zinc-200 shadow-xl dark:border-zinc-800\",\n isDevice && \"rounded-[2rem] border-[10px] border-zinc-800 shadow-2xl dark:border-zinc-700\",\n variant === \"bare\" && \"rounded-lg border border-zinc-200 dark:border-zinc-800\",\n // Fill (or full screen): the frame takes its parent's height and its\n // body takes whatever the chrome leaves.\n (fill || fullscreen) && \"flex flex-col\",\n fill && \"h-full\",\n fullscreen && \"rounded-none\",\n className,\n )}\n {...rest}\n >\n {isBrowser && (\n <div\n className={cn(\n \"flex items-center gap-2 border-b border-zinc-200 bg-zinc-50 px-3.5 py-2.5 font-mono text-[11.5px] text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-400\",\n barClassName,\n )}\n >\n {dots && (\n <div className=\"mr-1.5 flex gap-[5px]\">\n {DOT_COLORS.map((color, i) => (\n <span key={i} className={cn(\"h-[9px] w-[9px] rounded-full\", color)} />\n ))}\n </div>\n )}\n {url != null && <span className=\"min-w-0 flex-1 truncate\">{url}</span>}\n {meta != null && <span className=\"shrink-0 text-zinc-400 dark:text-zinc-500\">{meta}</span>}\n {hasControls && <div className={cn(url == null && meta == null && \"ml-auto\")}>{controlsBar}</div>}\n </div>\n )}\n\n <div\n ref={viewportRef}\n className={cn(\n \"relative\",\n // Zoomed in, the content is bigger than the frame: scroll to it.\n zoomed ? \"overflow-auto\" : \"overflow-hidden\",\n (fill || fullscreen) && \"min-h-0 flex-1\",\n bodyClassName,\n )}\n // The frame keeps its FIT height whatever the zoom; zooming scrolls.\n style={scaled && !fullscreen && naturalHeight !== undefined ? { height: naturalHeight * fit } : undefined}\n >\n {scaled ? (\n // A sizer the size of the zoomed content, so the scrollbars are right.\n <div\n style={\n naturalHeight !== undefined && width !== undefined\n ? { width: width * effective, height: naturalHeight * effective, position: \"relative\" }\n : undefined\n }\n >\n <div\n ref={stageRef}\n data-react-fancy-faux-client-content=\"\"\n className=\"absolute left-0 top-0 origin-top-left\"\n style={{ width, transform: `scale(${effective})` }}\n >\n {children}\n </div>\n </div>\n ) : (\n <div\n data-react-fancy-faux-client-content=\"\"\n className={cn((fill || fullscreen) && \"h-full\")}\n // CSS `zoom` rather than a transform: it changes layout size, so the\n // content reflows and the viewport scrolls to all of it.\n style={zoomed ? { zoom: String(zoom) } : undefined}\n >\n {children}\n </div>\n )}\n </div>\n\n {hasControls && !isBrowser && (\n <div className=\"pointer-events-none absolute right-2 top-2 z-10\">{controlsBar}</div>\n )}\n </div>\n );\n },\n);\n\nFauxClient.displayName = \"FauxClient\";\n\n/** Ghost icon buttons: no box of their own, so the bar reads as part of the frame. */\nfunction controlButton(inBar: boolean): string {\n return cn(\n \"flex h-6 w-6 items-center justify-center rounded-full transition-colors disabled:pointer-events-none disabled:opacity-30\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50\",\n inBar\n ? \"hover:bg-zinc-900/5 hover:text-zinc-700 dark:hover:bg-white/10 dark:hover:text-zinc-200\"\n : \"hover:bg-white/15 hover:text-white\",\n );\n}\n\nfunction ZoomOutIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n <path d=\"M8 11h6\" />\n </svg>\n );\n}\n\nfunction ZoomInIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n <path d=\"M8 11h6\" />\n <path d=\"M11 8v6\" />\n </svg>\n );\n}\n\n/** Inline, like `Input`'s reveal icons: a frame should not need an icon set configured. */\nfunction FullscreenIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3\" />\n <path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" />\n <path d=\"M3 16v3a2 2 0 0 0 2 2h3\" />\n <path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" />\n </svg>\n );\n}\n\nfunction ExitFullscreenIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3\" />\n <path d=\"M21 8h-3a2 2 0 0 1-2-2V3\" />\n <path d=\"M3 16h3a2 2 0 0 1 2 2v3\" />\n <path d=\"M16 21v-3a2 2 0 0 1 2-2h3\" />\n </svg>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/platform.ts","../src/components/PromptInput/PromptInput.tsx"],"names":[],"mappings":"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","file":"chunk-JZCAMPIA.js","sourcesContent":["/**\n * Which modifier key the user actually has.\n *\n * This exists because a keyboard hint is a CLAIM about the reader's hardware.\n * `⌘ + Enter to send` on Windows or Linux names a key that is not on the\n * keyboard, and a reader who cannot act on a hint learns to ignore hints — so\n * the cost is not one wrong glyph, it is the credibility of every hint beside\n * it. (Reported from a real Electron app running on Linux, where the glyph had\n * no font behind it either and rendered as tofu.)\n *\n * Two deliberate choices:\n *\n * 1. **The platform is an ARGUMENT, never a global read.** `detectPlatform`\n * takes the hints; `modifierKeyLabel` takes the verdict. Both branches are\n * therefore reachable from one machine, which is the only way a test can\n * cover the platform you are not sitting at. A function that reads\n * `navigator` internally can only ever be tested on the developer's own OS.\n * 2. **`generic` is the fallback, and that is not arbitrary.** Every Fancy\n * surface that submits on a modifier accepts `metaKey || ctrlKey`, so\n * `Ctrl` is a TRUE label on an Apple keyboard while `⌘` is a FALSE one\n * everywhere else. The honest default is the one that is pressable on all\n * of them.\n */\nexport type FancyPlatform = \"apple\" | \"generic\";\n\n/**\n * The parts of `navigator` the detection reads — nothing more, so a caller can\n * hand it a literal (a test, an Electron main process forwarding `process.platform`,\n * a server with a stored preference).\n */\nexport interface PlatformHints {\n /** `navigator.userAgentData` — the modern, non-spoofed answer where it exists. */\n userAgentData?: { platform?: string } | null;\n /** `navigator.platform` — deprecated, still the most reliable legacy signal. */\n platform?: string | null;\n /** `navigator.userAgent` — last resort. */\n userAgent?: string | null;\n}\n\n/**\n * `userAgentData.platform` is a short enumerated token (\"macOS\", \"Windows\",\n * \"Linux\", \"Android\", \"iOS\"), so it is matched exactly rather than by substring.\n */\nconst APPLE_UA_DATA_PLATFORMS = new Set([\"macos\", \"ios\", \"ipados\"]);\n\n/**\n * Legacy `platform` / `userAgent` are free text. iPadOS reports `MacIntel`, and\n * iOS user agents say \"like Mac OS X\" — both are Apple, so a Mac match is\n * correct for them too.\n */\nconst APPLE_FREE_TEXT = /\\b(mac|macintosh|iphone|ipad|ipod|darwin)/i;\n\n/** Resolve a platform from navigator-shaped hints. Unknown or absent ⇒ `generic`. */\nexport function detectPlatform(hints?: PlatformHints | null): FancyPlatform {\n if (!hints) return \"generic\";\n\n const uaData = hints.userAgentData?.platform;\n if (typeof uaData === \"string\" && uaData.length > 0) {\n // When the browser gives an enumerated answer, TRUST IT and stop. Falling\n // through to the free-text test would let a Windows UA string containing\n // the word \"Mac\" (a font name, a device model) overturn it.\n return APPLE_UA_DATA_PLATFORMS.has(uaData.trim().toLowerCase()) ? \"apple\" : \"generic\";\n }\n\n for (const value of [hints.platform, hints.userAgent]) {\n if (typeof value === \"string\" && APPLE_FREE_TEXT.test(value)) return \"apple\";\n }\n\n return \"generic\";\n}\n\n/**\n * The modifier key to NAME for a platform.\n *\n * `⌘` is emitted for `apple` and nothing else. A test enumerates the platform\n * values and counts that no other one can produce it, because a hint that names\n * the wrong key is worse than no hint.\n */\nexport function modifierKeyLabel(platform: FancyPlatform): \"⌘\" | \"Ctrl\" {\n return platform === \"apple\" ? \"⌘\" : \"Ctrl\";\n}\n\n/** SSR-safe read of the live browser hints. `null` off a browser. */\nexport function browserPlatformHints(): PlatformHints | null {\n if (typeof navigator === \"undefined\") return null;\n return navigator as PlatformHints;\n}\n","import {\n useEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button\";\nimport { Icon } from \"../Icon\";\nimport { Tooltip } from \"../Tooltip\";\nimport {\n InlinePasteEditor,\n PastedFilesInput,\n useInlinePaste,\n type ComposerPasteClassNames,\n type ComposerPastePreview,\n type InlinePasteEditorHandle,\n} from \"../PastePills\";\nimport {\n browserPlatformHints,\n detectPlatform,\n modifierKeyLabel,\n type FancyPlatform,\n} from \"../../utils/platform\";\n\n/**\n * PromptInput — the chat composer every AI app rebuilds. Auto-growing\n * multi-line input with:\n *\n * • slash-command picker (`/` triggers a filtered command palette,\n * ↑/↓ navigate, Enter inserts)\n * • mention picker (`@` triggers, filtered against `mentions`)\n * • drop-to-attach (drag files anywhere on the surface), paste-to-attach\n * (a pasted screenshot becomes an attachment) + chip bar\n * • submit on ⌘/Ctrl+Enter (plain Enter inserts a newline)\n * • live token-budget meter (green → amber → red as headroom drops)\n *\n * Wire it up:\n *\n * <PromptInput\n * budgetTokens={32000}\n * commands={[{ name: \"/rewrite\", hint: \"rewrite the selection\" }]}\n * mentions={[{ id: \"ada\", name: \"Ada\", kind: \"person\" }]}\n * onSubmit={(text, attachments) => sendToAgent(text, attachments)}\n * />\n */\nexport type PromptCmd = { name: string; hint: string };\nexport type PromptMention = {\n id: string;\n name: string;\n kind: \"agent\" | \"file\" | \"person\" | string;\n};\nexport type PromptAttachment = {\n id: string;\n name: string;\n bytes: number;\n /**\n * The file the user actually attached.\n *\n * Optional because an attachment restored from a server has no File — but for\n * anything the user dropped or picked it is always present. Without it a host\n * can render a chip and nothing else: no POST, no FormData, no send-to-model.\n */\n file?: File;\n /** MIME type. Hosts branch on this to decide whether a file can be sent as-is. */\n type?: string;\n};\n\n/**\n * `...rest` reaches the root surface, so a consumer or a bridge can tag the\n * composer with its own `data-*` handle. The component named every prop it\n * used and had no rest spread, which means a `data-handle` put on it was\n * DROPPED — silently, since React discards unknown props and the component\n * still renders perfectly. That is issue #22 all over again, and the contract\n * calls it out: \"Each interactive element has a stable identity. Agents never\n * guess DOM.\"\n */\nexport interface PromptInputProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"onSubmit\" | \"className\"> {\n /** Extra classes on the root surface. MERGED, never replaced. */\n className?: string;\n /** Token budget for the meter. */\n budgetTokens: number;\n /** Slash-commands. Names must start with `/`. */\n commands?: PromptCmd[];\n /** @-mentions. */\n mentions?: PromptMention[];\n /** Show the keyboard hint (\"Ctrl + Enter to send\", \"⌘ + Enter\" on a Mac). */\n showHint?: boolean;\n /**\n * Which modifier the hint and the default placeholder NAME. Omit it and the\n * component reads the platform after mount, which is the right answer for an\n * ordinary web app.\n *\n * Pass it when the host knows better than `navigator` does — an Electron\n * renderer forwarding `process.platform`, a remote session where the\n * keyboard is not the one running the browser, or a test that needs the\n * branch it is not sitting on. The pressed keys are unaffected either way:\n * submit is `⌘/Ctrl+Enter` on every platform, so this only decides which\n * true key gets named.\n */\n platform?: FancyPlatform;\n /** Called on ⌘/Ctrl+Enter or send button. */\n onSubmit: (text: string, attachments: PromptAttachment[]) => void;\n /**\n * Placeholder text. Defaults to a hint naming the modifier THIS platform\n * actually has, so leaving it unset is the better option — a hardcoded\n * placeholder is the other place a `⌘` ends up in front of a Windows user.\n */\n placeholder?: string;\n /** Rough estimator: chars-per-token. Defaults to 4. */\n charsPerToken?: number;\n /** Color → CSS chip mapping for mention kinds. */\n mentionColor?: Record<string, string>;\n /** Optional max textarea height in px. Defaults to 280. */\n maxHeight?: number;\n /**\n * Rendered INSIDE the rounded shell, ABOVE the attachments bar and\n * textarea. Use this slot for a drawer of tools/files/prompts/etc. so\n * the drawer and composer share one visual panel. See {@link ChatDrawer}.\n */\n aboveInput?: ReactNode;\n /**\n * Hold a paste of at least this many characters as a pill IN the message,\n * where it was pasted: on a line of its own, its full text put back in place\n * when clicked, and expanded where it sits when sent. Omit it and paste is\n * unchanged. Setting this (or `pasteImages`) swaps the textarea for an inline\n * editor that keeps the `/` and `@` pickers and the send key.\n */\n pasteThreshold?: number;\n /**\n * A pasted image becomes an inline `Pasted image N` pill AND reaches\n * `onSubmit`'s attachments, with its File, in message order; the text marks\n * where it sat as `[Pasted image N]`. Without it a pasted image is an\n * ordinary attachment chip, as before.\n */\n pasteImages?: boolean;\n /** Characters of a held paste shown at EACH end of its hover preview. Default 20. */\n previewChars?: number;\n /** Replace the paste pills' hover popover content. */\n renderPastePreview?: (preview: ComposerPastePreview) => ReactNode;\n /** Restyle the paste pills, their popover and the inline editor. Merged onto the defaults. */\n pasteClassNames?: ComposerPasteClassNames;\n /**\n * Submit pasted images with an enclosing `<form>`, under this field name: a\n * hidden `<input type=\"file\" multiple>` holds the images still in the message,\n * in message order. Needs `pasteImages`. They reach `onSubmit` either way.\n */\n pasteFilesName?: string;\n /** `\"icon\"`: an icon-only attach button whose tooltip says what it does. Default `\"label\"`. */\n attachButton?: \"label\" | \"icon\";\n /**\n * `\"icon\"`: a compact icon send button whose tooltip carries the shortcut —\n * replacing the inline `Ctrl + Enter to send` hint. Default `\"label\"`.\n */\n sendButton?: \"label\" | \"icon\";\n /**\n * Tokens already used — the caller's REAL value, e.g. an agent's context\n * usage. The meter shows this plus the estimate for the draft. Without it the\n * meter estimates the draft alone, as before.\n */\n usedTokens?: number;\n /**\n * `\"always\"` (default) — as before. `\"near-limit\"` — hidden until usage passes\n * `meterShowAt`, muted until `meterWarnAt`, warning colour past that.\n * `\"hidden\"` — never shown.\n */\n meter?: \"always\" | \"near-limit\" | \"hidden\";\n /** Fraction of `budgetTokens` at which a `\"near-limit\"` meter appears. Default 0.75. */\n meterShowAt?: number;\n /** Fraction of `budgetTokens` past which a `\"near-limit\"` meter takes the warning colour. Default 0.9. */\n meterWarnAt?: number;\n}\n\nconst DEFAULT_MENTION_COLOR: Record<string, string> = {\n agent: \"#a855f7\",\n file: \"#10b981\",\n person: \"#3b82f6\",\n};\n\nexport function PromptInput({\n budgetTokens,\n commands = [],\n mentions = [],\n showHint = true,\n platform,\n onSubmit,\n placeholder,\n charsPerToken = 4,\n mentionColor,\n maxHeight = 280,\n aboveInput,\n className,\n pasteThreshold,\n pasteImages = false,\n previewChars = 20,\n renderPastePreview,\n pasteClassNames,\n pasteFilesName,\n attachButton = \"label\",\n sendButton = \"label\",\n usedTokens,\n meter = \"always\",\n meterShowAt = 0.75,\n meterWarnAt = 0.9,\n ...rest\n}: PromptInputProps) {\n const [text, setText] = useState(\"\");\n /** Inline pills need an editor that can hold them; a textarea cannot. */\n const inline = pasteThreshold !== undefined || pasteImages;\n const editorRef = useRef<InlinePasteEditorHandle>(null);\n const paste = useInlinePaste({\n pasteThreshold,\n pasteImages,\n previewChars,\n renderPastePreview,\n classNames: pasteClassNames,\n disabled: false,\n editorRef,\n });\n const [attachments, setAttachments] = useState<PromptAttachment[]>([]);\n const [picker, setPicker] = useState<null | {\n kind: \"cmd\" | \"mention\";\n start: number;\n query: string;\n cursor: number;\n }>(null);\n const taRef = useRef<HTMLTextAreaElement>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const [dragOver, setDragOver] = useState(false);\n\n const colors = mentionColor ?? DEFAULT_MENTION_COLOR;\n\n /**\n * Resolved AFTER mount, never during render.\n *\n * `navigator` read during render disagrees with the server's HTML and\n * hydration patches it — so the fix for a wrong label would have introduced a\n * hydration mismatch instead. The first paint names `Ctrl`, which is\n * pressable on every platform including a Mac, and an Apple client swaps to\n * `⌘` on the next tick. A prop, when given, wins outright and no detection\n * runs at all.\n */\n const [detected, setDetected] = useState<FancyPlatform>(\"generic\");\n useEffect(() => {\n if (platform) return;\n setDetected(detectPlatform(browserPlatformHints()));\n }, [platform]);\n const modKey = modifierKeyLabel(platform ?? detected);\n\n const resolvedPlaceholder =\n placeholder ??\n `Ask anything. Type / for commands, @ for mentions. ${modKey}+Enter to send.`;\n\n // Estimated from what will actually be SENT — pills expanded — so a held\n // paste counts for its text, not for the few characters of its marker.\n const draftTokens = useMemo(\n () =>\n Math.ceil((inline ? paste.expand(text) : text).length / Math.max(1, charsPerToken)),\n [text, inline, paste, charsPerToken],\n );\n const tokens = (usedTokens ?? 0) + draftTokens;\n const ratio = Math.min(1, tokens / budgetTokens);\n const meterLevel: \"ok\" | \"caution\" | \"warn\" | \"muted\" | null =\n meter === \"hidden\"\n ? null\n : meter === \"near-limit\"\n ? ratio < meterShowAt\n ? null\n : ratio >= meterWarnAt\n ? \"warn\"\n : \"muted\"\n : ratio < 0.6\n ? \"ok\"\n : ratio < 0.85\n ? \"caution\"\n : \"warn\";\n const meterColor =\n meterLevel === \"ok\"\n ? \"#10b981\"\n : meterLevel === \"caution\"\n ? \"#f59e0b\"\n : meterLevel === \"warn\"\n ? \"#ef4444\"\n : \"#a1a1aa\";\n\n const filteredCmds = useMemo(\n () =>\n picker?.kind === \"cmd\"\n ? commands.filter((c) =>\n c.name.slice(1).toLowerCase().startsWith(picker.query.toLowerCase()),\n )\n : [],\n [picker, commands],\n );\n const filteredMentions = useMemo(\n () =>\n picker?.kind === \"mention\"\n ? mentions.filter((m) =>\n m.name.toLowerCase().includes(picker.query.toLowerCase()),\n )\n : [],\n [picker, mentions],\n );\n const items: Array<PromptCmd | PromptMention> =\n picker?.kind === \"cmd\"\n ? filteredCmds\n : picker?.kind === \"mention\"\n ? filteredMentions\n : [];\n\n useEffect(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.style.height = \"auto\";\n ta.style.height = Math.min(maxHeight, ta.scrollHeight) + \"px\";\n }, [text, maxHeight]);\n\n const updateText = (next: string, caret: number) => {\n setText(next);\n let triggerIdx = -1;\n let triggerKind: \"cmd\" | \"mention\" | null = null;\n for (let i = caret - 1; i >= 0; i--) {\n const ch = next[i];\n if (ch === \"@\") {\n triggerKind = \"mention\";\n triggerIdx = i;\n break;\n }\n if (ch === \"/\" && (i === 0 || /\\s/.test(next[i - 1] ?? \"\"))) {\n triggerKind = \"cmd\";\n triggerIdx = i;\n break;\n }\n if (/\\s/.test(ch)) break;\n }\n if (triggerKind !== null && triggerIdx >= 0) {\n const query = next.slice(triggerIdx + 1, caret);\n setPicker({ kind: triggerKind, start: triggerIdx, query, cursor: 0 });\n } else {\n setPicker(null);\n }\n };\n\n const insertChoice = (i: number) => {\n if (!picker || items.length === 0) return;\n const choice = items[i] ?? items[0];\n const insert =\n picker.kind === \"cmd\"\n ? (choice as PromptCmd).name + \" \"\n : `@${(choice as PromptMention).id} `;\n const before = text.slice(0, picker.start);\n const after = text.slice(picker.start + 1 + picker.query.length);\n const next = before + insert + after;\n setText(next);\n setPicker(null);\n if (inline) {\n // The editor rebuilds from the value and puts the caret back itself.\n editorRef.current?.setValue(next, before.length + insert.length);\n return;\n }\n requestAnimationFrame(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.focus();\n const pos = before.length + insert.length;\n ta.setSelectionRange(pos, pos);\n });\n };\n\n const submit = () => {\n // A message that is only a paste counts: its marker is in `text`.\n if (!text.trim() && attachments.length === 0) return;\n\n if (inline) {\n // Every pill goes out where it sits; pasted images join the attachments\n // in message order, with their Files, so a host sends them like any other.\n const pastedImages: PromptAttachment[] = paste.imagesIn(text).map((image) => ({\n id: image.id,\n name: image.file.name,\n bytes: image.file.size,\n file: image.file,\n type: image.file.type,\n }));\n onSubmit(paste.expand(text), [...attachments, ...pastedImages]);\n paste.clear();\n } else {\n onSubmit(text, attachments);\n }\n setText(\"\");\n setAttachments([]);\n setPicker(null);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (picker) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setPicker((p) =>\n p ? { ...p, cursor: Math.min(items.length - 1, p.cursor + 1) } : p,\n );\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setPicker((p) => (p ? { ...p, cursor: Math.max(0, p.cursor - 1) } : p));\n return;\n }\n if (e.key === \"Enter\" && !e.metaKey && !e.ctrlKey && items.length > 0) {\n e.preventDefault();\n insertChoice(picker.cursor);\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n setPicker(null);\n return;\n }\n }\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n submit();\n }\n };\n\n /**\n * Build attachments from a FileList, KEEPING the File.\n *\n * Shared by the drop handler and the picker so the two cannot drift — the\n * picker being a second, subtly different copy of this is exactly how one of\n * them would end up dropping the File again.\n */\n const attach = (list: FileList | File[] | null) => {\n const files = Array.from(list ?? []);\n if (files.length === 0) return;\n\n setAttachments((cur) => [\n ...cur,\n ...files.map((f) => ({\n id: crypto.randomUUID(),\n name: f.name,\n bytes: f.size,\n file: f,\n type: f.type,\n })),\n ]);\n };\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setDragOver(false);\n attach(e.dataTransfer.files);\n };\n\n /**\n * Paste a screenshot, get an attachment.\n *\n * There was no paste handler at all, so a pasted image did nothing — no chip,\n * no error — and a host that had swapped its own paste-capable textarea for\n * this component lost the feature without noticing.\n *\n * Files attach only when the clipboard carries NO plain text. Word, Excel and\n * most editors put a picture of the selection beside the text; attaching that\n * would turn every pasted sentence into a screenshot of the sentence. A pure\n * image paste has nothing for the browser to insert, so the default is\n * prevented only then, and a text paste is never touched.\n */\n const onPaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const data = e.clipboardData;\n const files = Array.from(data?.files ?? []);\n\n if (files.length === 0 || (data?.getData(\"text/plain\") ?? \"\") !== \"\") return;\n\n e.preventDefault();\n attach(files);\n };\n\n return (\n <div\n // Spread FIRST so an internal handler or data attribute cannot be\n // clobbered from outside, and so a missing one fails loudly here rather\n // than at a consumer's selector. `className` is merged below instead.\n {...rest}\n // The component had no root handle at all, so an agent reading the\n // composer had to guess at classes. The drag state is on it too: a bridge\n // that wants to know whether a drop is in flight should not have to infer\n // it from Tailwind colours.\n data-react-fancy-prompt-input=\"\"\n data-react-fancy-prompt-input-drag={dragOver ? \"over\" : \"idle\"}\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}\n className={cn(\n \"relative rounded-md border bg-white transition dark:bg-zinc-900\",\n dragOver\n ? \"border-violet-400 bg-violet-50/50 dark:border-violet-600 dark:bg-violet-950/30\"\n : \"border-zinc-200 dark:border-zinc-800\",\n className,\n )}\n >\n {aboveInput && (\n <div className=\"border-b border-zinc-200 dark:border-zinc-800\">\n {aboveInput}\n </div>\n )}\n {attachments.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 border-b border-zinc-200 px-3 py-2 dark:border-zinc-800\">\n {attachments.map((a) => (\n <span\n key={a.id}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-zinc-100 px-2 py-0.5 text-[11px] dark:bg-zinc-800\"\n >\n <Icon name=\"paperclip\" size=\"xs\" className=\"text-zinc-400\" />\n <span className=\"font-mono\">{a.name}</span>\n <span className=\"text-zinc-400\">{fmtSize(a.bytes)}</span>\n <button\n onClick={() =>\n setAttachments((cur) => cur.filter((x) => x.id !== a.id))\n }\n className=\"opacity-50 hover:opacity-100\"\n aria-label=\"Remove attachment\"\n >\n ×\n </button>\n </span>\n ))}\n </div>\n )}\n\n <div className=\"relative\">\n {inline ? (\n <>\n <InlinePasteEditor\n ref={editorRef}\n value={text}\n known={paste.known}\n onChange={(next, caret) => {\n updateText(next, caret);\n paste.prune(next);\n }}\n onSubmit={submit}\n submitKey=\"mod-enter\"\n onKeyDown={onKeyDown}\n onPaste={paste.decidePaste}\n onHostsChange={paste.onHostsChange}\n placeholder={resolvedPlaceholder}\n disabled={false}\n maxHeight={maxHeight}\n placeholderClassName=\"left-3 top-2.5 text-[14px] leading-relaxed\"\n className={cn(\n \"block min-h-[5.5rem] px-3 py-2.5 text-[14px] leading-relaxed\",\n pasteClassNames?.input,\n )}\n />\n {paste.portals}\n {pasteImages && pasteFilesName && (\n <PastedFilesInput\n name={pasteFilesName}\n files={paste.imagesIn(text).map((i) => i.file)}\n />\n )}\n </>\n ) : (\n <textarea\n ref={taRef}\n value={text}\n onChange={(e) => updateText(e.target.value, e.target.selectionStart)}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n placeholder={resolvedPlaceholder}\n spellCheck={false}\n className=\"block w-full resize-none bg-transparent px-3 py-2.5 text-[14px] leading-relaxed outline-none placeholder:text-zinc-400\"\n rows={3}\n />\n )}\n\n {picker && items.length > 0 && (\n <div className=\"absolute bottom-full left-2 z-10 mb-1 w-72 overflow-hidden rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900\">\n <div className=\"border-b border-zinc-100 bg-zinc-50 px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950\">\n {picker.kind === \"cmd\" ? \"Commands\" : \"Mention\"} · {items.length}\n </div>\n <ul className=\"max-h-56 overflow-y-auto\">\n {items.map((item, i) => {\n const active = i === picker.cursor;\n if (picker.kind === \"cmd\") {\n const c = item as PromptCmd;\n return (\n <li\n key={c.name}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`cursor-pointer px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <div className=\"font-mono font-medium text-violet-700 dark:text-violet-300\">\n {c.name}\n </div>\n <div className=\"text-[11px] text-zinc-500\">{c.hint}</div>\n </li>\n );\n }\n const m = item as PromptMention;\n return (\n <li\n key={m.id}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`flex cursor-pointer items-center gap-2 px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <span\n className=\"h-2 w-2 rounded-full\"\n style={{ backgroundColor: colors[m.kind] ?? \"#71717a\" }}\n />\n <span className=\"font-medium\">{m.name}</span>\n <span className=\"ml-auto text-[10px] uppercase tracking-wider text-zinc-400\">\n {m.kind}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n\n <div className=\"flex items-center gap-2 border-t border-zinc-200 bg-zinc-50/60 px-3 py-2 dark:border-zinc-800 dark:bg-zinc-900/40\">\n <Tooltip content={attachButton === \"icon\" ? \"Attach files — or drop them here\" : \"Drop files here, or click\"}>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n icon=\"paperclip\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-attach=\"\"\n // An icon alone has no name; the tooltip is not one a screen reader reads.\n aria-label={attachButton === \"icon\" ? \"Attach files\" : undefined}\n onClick={() => fileRef.current?.click()}\n >\n {attachButton === \"icon\" ? null : \"attach\"}\n </Button>\n </Tooltip>\n {/*\n The button above shipped with a no-op onClick and a tooltip reading\n \"Drop files here, or click\" — an affordance that lied. Drop-only also\n meant keyboard and touch users could not attach at all.\n\n It then shipped with a literal paperclip EMOJI as its icon, which\n needs a COLOUR\n EMOJI FONT — not merely broad coverage — so a lean container renders a\n tofu box where the affordance should be. `icon=\"paperclip\"` draws an\n SVG from the kit's own icon layer, which is the same reason the rest of\n the suite does not hand-roll iconography.\n */}\n <input\n ref={fileRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n attach(e.target.files);\n // Let the same file be picked twice in a row.\n e.target.value = \"\";\n }}\n />\n {meterLevel !== null && (\n <div\n data-react-fancy-prompt-input-meter=\"\"\n data-level={meterLevel}\n className=\"ml-2 flex min-w-0 items-center gap-1.5 overflow-hidden\"\n >\n <div className=\"h-1.5 w-24 shrink overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-700\">\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${ratio * 100}%`, backgroundColor: meterColor }}\n />\n </div>\n <span className=\"font-mono text-[11px]\" style={{ color: meterColor }}>\n {fmtTokens(tokens)} / {fmtTokens(budgetTokens)}\n </span>\n </div>\n )}\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {/* With an icon send button the shortcut lives in its tooltip instead. */}\n {showHint && sendButton !== \"icon\" && (\n <span\n className=\"hidden text-[10px] text-zinc-500 sm:inline\"\n data-react-fancy-prompt-input-hint={modKey === \"⌘\" ? \"apple\" : \"generic\"}\n >\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n {modKey}\n </kbd>{\" \"}\n +{\" \"}\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n Enter\n </kbd>{\" \"}\n to send\n </span>\n )}\n {sendButton === \"icon\" ? (\n <Tooltip content={`Send · ${modKey}+Enter`}>\n <Button\n color=\"violet\"\n size=\"sm\"\n icon=\"arrow-up\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-send=\"\"\n aria-label=\"Send\"\n onClick={submit}\n />\n </Tooltip>\n ) : (\n <Button\n color=\"violet\"\n size=\"sm\"\n iconTrailing=\"arrow-right\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-send=\"\"\n onClick={submit}\n >\n send\n </Button>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction fmtTokens(n: number): string {\n if (n < 1000) return `${n}`;\n return `${(n / 1000).toFixed(1)}k`;\n}\n\nfunction fmtSize(b: number): string {\n if (b < 1024) return `${b} B`;\n if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)} KB`;\n return `${(b / 1024 / 1024).toFixed(1)} MB`;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/FauxClient/FauxClient.tsx"],"names":["forwardRef","useRef","useState","useControllableState","useLayoutEffect","useEffect","useCallback","jsxs","cn","Fragment","jsx"],"mappings":"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","file":"chunk-S3WWYBL4.cjs","sourcesContent":["import { forwardRef, useCallback, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useControllableState } from \"../../hooks/use-controllable-state\";\nimport type { FauxClientProps } from \"./FauxClient.types\";\n\nconst DOT_COLORS = [\"bg-rose-300\", \"bg-amber-300\", \"bg-green-300\"];\n\n/** One click of the zoom bar. Matches `ImageViewer`, so the kit zooms one way. */\nconst ZOOM_STEP = 1.25;\n\nconst clamp = (n: number, min: number, max: number) => Math.min(max, Math.max(min, n));\n\n/**\n * A frame that mimics a browser window or device, rendering **real UI** inside.\n * With a logical `width` + `scale=\"fit\"` it renders a full-size page/app and\n * scales it down to fit any container (live thumbnails, device mockups) — the\n * content is real and interactive, just zoomed.\n *\n * Omit `width` for chrome around natural-size content (e.g. a code/preview card).\n *\n * `controls` adds a zoom bar and a full-screen button, for content that has to be\n * READ rather than glanced at: a slide or a sheet shrunk to fit a panel.\n */\nexport const FauxClient = forwardRef<HTMLDivElement, FauxClientProps>(\n (\n {\n variant = \"browser\",\n url,\n meta,\n dots = true,\n width,\n scale = \"fit\",\n controls = false,\n zoom: controlledZoom,\n defaultZoom = 1,\n onZoomChange,\n minZoom = 0.5,\n maxZoom = 4,\n onFullscreenChange,\n fill = false,\n className,\n barClassName,\n bodyClassName,\n children,\n ...rest\n },\n ref,\n ) => {\n const scaled = typeof width === \"number\";\n const rootRef = useRef<HTMLDivElement | null>(null);\n const viewportRef = useRef<HTMLDivElement>(null);\n const stageRef = useRef<HTMLDivElement>(null);\n const [fit, setFit] = useState(typeof scale === \"number\" ? scale : 1);\n const [naturalHeight, setNaturalHeight] = useState<number | undefined>(undefined);\n\n const showZoom = controls === true || (typeof controls === \"object\" && controls.zoom !== false);\n const showFullscreen = controls === true || (typeof controls === \"object\" && controls.fullscreen !== false);\n const [zoom, setZoom] = useControllableState(controlledZoom, defaultZoom, onZoomChange);\n const [fullscreen, setFullscreen] = useState(false);\n\n useLayoutEffect(() => {\n if (!scaled) return;\n const viewport = viewportRef.current;\n const stage = stageRef.current;\n if (!viewport || !stage) return;\n if (typeof ResizeObserver === \"undefined\") return;\n\n const measure = () => {\n const avail = viewport.clientWidth;\n setFit(scale === \"fit\" ? (width && width > 0 ? avail / width : 1) : scale);\n // offsetHeight is the pre-transform layout height (CSS transforms don't affect it).\n setNaturalHeight(stage.offsetHeight);\n };\n\n measure();\n const ro = new ResizeObserver(measure);\n ro.observe(viewport);\n ro.observe(stage);\n return () => ro.disconnect();\n }, [scaled, scale, width]);\n\n // Full screen is the browser's state, not ours: follow it, so Esc and the\n // browser's own exit leave the button telling the truth.\n useEffect(() => {\n if (!showFullscreen || typeof document === \"undefined\") return;\n const sync = () => {\n const on = document.fullscreenElement != null && document.fullscreenElement === rootRef.current;\n setFullscreen(on);\n onFullscreenChange?.(on);\n };\n document.addEventListener(\"fullscreenchange\", sync);\n return () => document.removeEventListener(\"fullscreenchange\", sync);\n }, [showFullscreen, onFullscreenChange]);\n\n const toggleFullscreen = useCallback(() => {\n const el = rootRef.current;\n if (!el || typeof document === \"undefined\") return;\n if (document.fullscreenElement === el) void document.exitFullscreen?.();\n else void el.requestFullscreen?.();\n }, []);\n\n const zoomBy = (factor: number) => {\n // Rounded so ten clicks in and ten out land back on 100%, not 99.99%.\n setZoom(clamp(Math.round(zoom * factor * 100) / 100, minZoom, maxZoom));\n };\n\n const setRefs = (el: HTMLDivElement | null) => {\n rootRef.current = el;\n if (typeof ref === \"function\") ref(el);\n else if (ref) ref.current = el;\n };\n\n const isBrowser = variant === \"browser\";\n const isDevice = variant === \"device\";\n const effective = fit * zoom;\n const zoomed = zoom !== 1;\n const hasControls = showZoom || showFullscreen;\n\n /*\n * Out of the way until wanted: hidden, and revealed when the pointer is over\n * the frame or focus is inside it (keyboard). Always shown where there is no\n * hover to reveal it (touch), or it could never be reached.\n *\n * In the browser chrome it sits in the address bar, inline. On a device or a\n * bare frame there is no chrome, so it floats top-right as a slim strip: the\n * bottom corners belong to the content (a slide viewer's page count lives\n * there).\n */\n const controlsBar = hasControls ? (\n <div\n data-react-fancy-faux-client-controls=\"\"\n className={cn(\n \"pointer-events-auto flex shrink-0 items-center gap-px opacity-0 transition-opacity duration-150\",\n \"group-hover/faux-client:opacity-100 focus-within:opacity-100 [@media(hover:none)]:opacity-100\",\n isBrowser\n ? \"-my-1 text-zinc-400 dark:text-zinc-500\"\n : \"rounded-full bg-zinc-900/60 px-1 py-0.5 text-white/80 shadow-sm backdrop-blur-sm\",\n )}\n >\n {showZoom && (\n <>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-out=\"\"\n aria-label=\"Zoom out\"\n title=\"Zoom out\"\n disabled={zoom <= minZoom}\n onClick={() => zoomBy(1 / ZOOM_STEP)}\n className={controlButton(isBrowser)}\n >\n <ZoomOutIcon />\n </button>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-reset=\"\"\n aria-label=\"Reset zoom\"\n title=\"Reset zoom\"\n onClick={() => setZoom(1)}\n className={cn(controlButton(isBrowser), \"w-auto min-w-[2.25rem] px-1 font-sans text-[10.5px] tabular-nums\")}\n >\n {Math.round(zoom * 100)}%\n </button>\n <button\n type=\"button\"\n data-react-fancy-faux-client-zoom-in=\"\"\n aria-label=\"Zoom in\"\n title=\"Zoom in\"\n disabled={zoom >= maxZoom}\n onClick={() => zoomBy(ZOOM_STEP)}\n className={controlButton(isBrowser)}\n >\n <ZoomInIcon />\n </button>\n </>\n )}\n {showFullscreen && (\n <button\n type=\"button\"\n data-react-fancy-faux-client-fullscreen=\"\"\n aria-label={fullscreen ? \"Exit full screen\" : \"Full screen\"}\n aria-pressed={fullscreen}\n title={fullscreen ? \"Exit full screen\" : \"Full screen\"}\n onClick={toggleFullscreen}\n className={controlButton(isBrowser)}\n >\n {fullscreen ? <ExitFullscreenIcon /> : <FullscreenIcon />}\n </button>\n )}\n </div>\n ) : null;\n\n return (\n <div\n ref={setRefs}\n data-react-fancy-faux-client=\"\"\n data-fullscreen={showFullscreen ? String(fullscreen) : undefined}\n className={cn(\n \"group/faux-client relative overflow-hidden bg-white dark:bg-zinc-900\",\n isBrowser && \"rounded-2xl border border-zinc-200 shadow-xl dark:border-zinc-800\",\n isDevice && \"rounded-[2rem] border-[10px] border-zinc-800 shadow-2xl dark:border-zinc-700\",\n variant === \"bare\" && \"rounded-lg border border-zinc-200 dark:border-zinc-800\",\n // Fill (or full screen): the frame takes its parent's height and its\n // body takes whatever the chrome leaves.\n (fill || fullscreen) && \"flex flex-col\",\n fill && \"h-full\",\n fullscreen && \"rounded-none\",\n className,\n )}\n {...rest}\n >\n {isBrowser && (\n <div\n className={cn(\n \"flex items-center gap-2 border-b border-zinc-200 bg-zinc-50 px-3.5 py-2.5 font-mono text-[11.5px] text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-400\",\n barClassName,\n )}\n >\n {dots && (\n <div className=\"mr-1.5 flex gap-[5px]\">\n {DOT_COLORS.map((color, i) => (\n <span key={i} className={cn(\"h-[9px] w-[9px] rounded-full\", color)} />\n ))}\n </div>\n )}\n {url != null && <span className=\"min-w-0 flex-1 truncate\">{url}</span>}\n {meta != null && <span className=\"shrink-0 text-zinc-400 dark:text-zinc-500\">{meta}</span>}\n {hasControls && <div className={cn(url == null && meta == null && \"ml-auto\")}>{controlsBar}</div>}\n </div>\n )}\n\n <div\n ref={viewportRef}\n className={cn(\n \"relative\",\n // Zoomed in, the content is bigger than the frame: scroll to it.\n zoomed ? \"overflow-auto\" : \"overflow-hidden\",\n (fill || fullscreen) && \"min-h-0 flex-1\",\n bodyClassName,\n )}\n // The frame keeps its FIT height whatever the zoom; zooming scrolls.\n style={scaled && !fullscreen && naturalHeight !== undefined ? { height: naturalHeight * fit } : undefined}\n >\n {scaled ? (\n // A sizer the size of the zoomed content, so the scrollbars are right.\n <div\n style={\n naturalHeight !== undefined && width !== undefined\n ? { width: width * effective, height: naturalHeight * effective, position: \"relative\" }\n : undefined\n }\n >\n <div\n ref={stageRef}\n data-react-fancy-faux-client-content=\"\"\n className=\"absolute left-0 top-0 origin-top-left\"\n style={{ width, transform: `scale(${effective})` }}\n >\n {children}\n </div>\n </div>\n ) : (\n <div\n data-react-fancy-faux-client-content=\"\"\n className={cn((fill || fullscreen) && \"h-full\")}\n // CSS `zoom` rather than a transform: it changes layout size, so the\n // content reflows and the viewport scrolls to all of it.\n style={zoomed ? { zoom: String(zoom) } : undefined}\n >\n {children}\n </div>\n )}\n </div>\n\n {hasControls && !isBrowser && (\n <div className=\"pointer-events-none absolute right-2 top-2 z-10\">{controlsBar}</div>\n )}\n </div>\n );\n },\n);\n\nFauxClient.displayName = \"FauxClient\";\n\n/** Ghost icon buttons: no box of their own, so the bar reads as part of the frame. */\nfunction controlButton(inBar: boolean): string {\n return cn(\n \"flex h-6 w-6 items-center justify-center rounded-full transition-colors disabled:pointer-events-none disabled:opacity-30\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-500/50\",\n inBar\n ? \"hover:bg-zinc-900/5 hover:text-zinc-700 dark:hover:bg-white/10 dark:hover:text-zinc-200\"\n : \"hover:bg-white/15 hover:text-white\",\n );\n}\n\nfunction ZoomOutIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n <path d=\"M8 11h6\" />\n </svg>\n );\n}\n\nfunction ZoomInIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n <path d=\"M8 11h6\" />\n <path d=\"M11 8v6\" />\n </svg>\n );\n}\n\n/** Inline, like `Input`'s reveal icons: a frame should not need an icon set configured. */\nfunction FullscreenIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3\" />\n <path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" />\n <path d=\"M3 16v3a2 2 0 0 0 2 2h3\" />\n <path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" />\n </svg>\n );\n}\n\nfunction ExitFullscreenIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3\" />\n <path d=\"M21 8h-3a2 2 0 0 1-2-2V3\" />\n <path d=\"M3 16h3a2 2 0 0 1 2 2v3\" />\n <path d=\"M16 21v-3a2 2 0 0 1 2-2h3\" />\n </svg>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/platform.ts","../src/components/PromptInput/PromptInput.tsx"],"names":["useState","useRef","useInlinePaste","useEffect","useMemo","jsxs","cn","jsx","Icon","Fragment","InlinePasteEditor","PastedFilesInput","Tooltip","Button"],"mappings":"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","file":"chunk-Z3FIU77M.cjs","sourcesContent":["/**\n * Which modifier key the user actually has.\n *\n * This exists because a keyboard hint is a CLAIM about the reader's hardware.\n * `⌘ + Enter to send` on Windows or Linux names a key that is not on the\n * keyboard, and a reader who cannot act on a hint learns to ignore hints — so\n * the cost is not one wrong glyph, it is the credibility of every hint beside\n * it. (Reported from a real Electron app running on Linux, where the glyph had\n * no font behind it either and rendered as tofu.)\n *\n * Two deliberate choices:\n *\n * 1. **The platform is an ARGUMENT, never a global read.** `detectPlatform`\n * takes the hints; `modifierKeyLabel` takes the verdict. Both branches are\n * therefore reachable from one machine, which is the only way a test can\n * cover the platform you are not sitting at. A function that reads\n * `navigator` internally can only ever be tested on the developer's own OS.\n * 2. **`generic` is the fallback, and that is not arbitrary.** Every Fancy\n * surface that submits on a modifier accepts `metaKey || ctrlKey`, so\n * `Ctrl` is a TRUE label on an Apple keyboard while `⌘` is a FALSE one\n * everywhere else. The honest default is the one that is pressable on all\n * of them.\n */\nexport type FancyPlatform = \"apple\" | \"generic\";\n\n/**\n * The parts of `navigator` the detection reads — nothing more, so a caller can\n * hand it a literal (a test, an Electron main process forwarding `process.platform`,\n * a server with a stored preference).\n */\nexport interface PlatformHints {\n /** `navigator.userAgentData` — the modern, non-spoofed answer where it exists. */\n userAgentData?: { platform?: string } | null;\n /** `navigator.platform` — deprecated, still the most reliable legacy signal. */\n platform?: string | null;\n /** `navigator.userAgent` — last resort. */\n userAgent?: string | null;\n}\n\n/**\n * `userAgentData.platform` is a short enumerated token (\"macOS\", \"Windows\",\n * \"Linux\", \"Android\", \"iOS\"), so it is matched exactly rather than by substring.\n */\nconst APPLE_UA_DATA_PLATFORMS = new Set([\"macos\", \"ios\", \"ipados\"]);\n\n/**\n * Legacy `platform` / `userAgent` are free text. iPadOS reports `MacIntel`, and\n * iOS user agents say \"like Mac OS X\" — both are Apple, so a Mac match is\n * correct for them too.\n */\nconst APPLE_FREE_TEXT = /\\b(mac|macintosh|iphone|ipad|ipod|darwin)/i;\n\n/** Resolve a platform from navigator-shaped hints. Unknown or absent ⇒ `generic`. */\nexport function detectPlatform(hints?: PlatformHints | null): FancyPlatform {\n if (!hints) return \"generic\";\n\n const uaData = hints.userAgentData?.platform;\n if (typeof uaData === \"string\" && uaData.length > 0) {\n // When the browser gives an enumerated answer, TRUST IT and stop. Falling\n // through to the free-text test would let a Windows UA string containing\n // the word \"Mac\" (a font name, a device model) overturn it.\n return APPLE_UA_DATA_PLATFORMS.has(uaData.trim().toLowerCase()) ? \"apple\" : \"generic\";\n }\n\n for (const value of [hints.platform, hints.userAgent]) {\n if (typeof value === \"string\" && APPLE_FREE_TEXT.test(value)) return \"apple\";\n }\n\n return \"generic\";\n}\n\n/**\n * The modifier key to NAME for a platform.\n *\n * `⌘` is emitted for `apple` and nothing else. A test enumerates the platform\n * values and counts that no other one can produce it, because a hint that names\n * the wrong key is worse than no hint.\n */\nexport function modifierKeyLabel(platform: FancyPlatform): \"⌘\" | \"Ctrl\" {\n return platform === \"apple\" ? \"⌘\" : \"Ctrl\";\n}\n\n/** SSR-safe read of the live browser hints. `null` off a browser. */\nexport function browserPlatformHints(): PlatformHints | null {\n if (typeof navigator === \"undefined\") return null;\n return navigator as PlatformHints;\n}\n","import {\n useEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button\";\nimport { Icon } from \"../Icon\";\nimport { Tooltip } from \"../Tooltip\";\nimport {\n InlinePasteEditor,\n PastedFilesInput,\n useInlinePaste,\n type ComposerPasteClassNames,\n type ComposerPastePreview,\n type InlinePasteEditorHandle,\n} from \"../PastePills\";\nimport {\n browserPlatformHints,\n detectPlatform,\n modifierKeyLabel,\n type FancyPlatform,\n} from \"../../utils/platform\";\n\n/**\n * PromptInput — the chat composer every AI app rebuilds. Auto-growing\n * multi-line input with:\n *\n * • slash-command picker (`/` triggers a filtered command palette,\n * ↑/↓ navigate, Enter inserts)\n * • mention picker (`@` triggers, filtered against `mentions`)\n * • drop-to-attach (drag files anywhere on the surface), paste-to-attach\n * (a pasted screenshot becomes an attachment) + chip bar\n * • submit on ⌘/Ctrl+Enter (plain Enter inserts a newline)\n * • live token-budget meter (green → amber → red as headroom drops)\n *\n * Wire it up:\n *\n * <PromptInput\n * budgetTokens={32000}\n * commands={[{ name: \"/rewrite\", hint: \"rewrite the selection\" }]}\n * mentions={[{ id: \"ada\", name: \"Ada\", kind: \"person\" }]}\n * onSubmit={(text, attachments) => sendToAgent(text, attachments)}\n * />\n */\nexport type PromptCmd = { name: string; hint: string };\nexport type PromptMention = {\n id: string;\n name: string;\n kind: \"agent\" | \"file\" | \"person\" | string;\n};\nexport type PromptAttachment = {\n id: string;\n name: string;\n bytes: number;\n /**\n * The file the user actually attached.\n *\n * Optional because an attachment restored from a server has no File — but for\n * anything the user dropped or picked it is always present. Without it a host\n * can render a chip and nothing else: no POST, no FormData, no send-to-model.\n */\n file?: File;\n /** MIME type. Hosts branch on this to decide whether a file can be sent as-is. */\n type?: string;\n};\n\n/**\n * `...rest` reaches the root surface, so a consumer or a bridge can tag the\n * composer with its own `data-*` handle. The component named every prop it\n * used and had no rest spread, which means a `data-handle` put on it was\n * DROPPED — silently, since React discards unknown props and the component\n * still renders perfectly. That is issue #22 all over again, and the contract\n * calls it out: \"Each interactive element has a stable identity. Agents never\n * guess DOM.\"\n */\nexport interface PromptInputProps\n extends Omit<HTMLAttributes<HTMLDivElement>, \"onSubmit\" | \"className\"> {\n /** Extra classes on the root surface. MERGED, never replaced. */\n className?: string;\n /** Token budget for the meter. */\n budgetTokens: number;\n /** Slash-commands. Names must start with `/`. */\n commands?: PromptCmd[];\n /** @-mentions. */\n mentions?: PromptMention[];\n /** Show the keyboard hint (\"Ctrl + Enter to send\", \"⌘ + Enter\" on a Mac). */\n showHint?: boolean;\n /**\n * Which modifier the hint and the default placeholder NAME. Omit it and the\n * component reads the platform after mount, which is the right answer for an\n * ordinary web app.\n *\n * Pass it when the host knows better than `navigator` does — an Electron\n * renderer forwarding `process.platform`, a remote session where the\n * keyboard is not the one running the browser, or a test that needs the\n * branch it is not sitting on. The pressed keys are unaffected either way:\n * submit is `⌘/Ctrl+Enter` on every platform, so this only decides which\n * true key gets named.\n */\n platform?: FancyPlatform;\n /** Called on ⌘/Ctrl+Enter or send button. */\n onSubmit: (text: string, attachments: PromptAttachment[]) => void;\n /**\n * Placeholder text. Defaults to a hint naming the modifier THIS platform\n * actually has, so leaving it unset is the better option — a hardcoded\n * placeholder is the other place a `⌘` ends up in front of a Windows user.\n */\n placeholder?: string;\n /** Rough estimator: chars-per-token. Defaults to 4. */\n charsPerToken?: number;\n /** Color → CSS chip mapping for mention kinds. */\n mentionColor?: Record<string, string>;\n /** Optional max textarea height in px. Defaults to 280. */\n maxHeight?: number;\n /**\n * Rendered INSIDE the rounded shell, ABOVE the attachments bar and\n * textarea. Use this slot for a drawer of tools/files/prompts/etc. so\n * the drawer and composer share one visual panel. See {@link ChatDrawer}.\n */\n aboveInput?: ReactNode;\n /**\n * Hold a paste of at least this many characters as a pill IN the message,\n * where it was pasted: on a line of its own, its full text put back in place\n * when clicked, and expanded where it sits when sent. Omit it and paste is\n * unchanged. Setting this (or `pasteImages`) swaps the textarea for an inline\n * editor that keeps the `/` and `@` pickers and the send key.\n */\n pasteThreshold?: number;\n /**\n * A pasted image becomes an inline `Pasted image N` pill AND reaches\n * `onSubmit`'s attachments, with its File, in message order; the text marks\n * where it sat as `[Pasted image N]`. Without it a pasted image is an\n * ordinary attachment chip, as before.\n */\n pasteImages?: boolean;\n /** Characters of a held paste shown at EACH end of its hover preview. Default 20. */\n previewChars?: number;\n /** Replace the paste pills' hover popover content. */\n renderPastePreview?: (preview: ComposerPastePreview) => ReactNode;\n /** Restyle the paste pills, their popover and the inline editor. Merged onto the defaults. */\n pasteClassNames?: ComposerPasteClassNames;\n /**\n * Submit pasted images with an enclosing `<form>`, under this field name: a\n * hidden `<input type=\"file\" multiple>` holds the images still in the message,\n * in message order. Needs `pasteImages`. They reach `onSubmit` either way.\n */\n pasteFilesName?: string;\n /** `\"icon\"`: an icon-only attach button whose tooltip says what it does. Default `\"label\"`. */\n attachButton?: \"label\" | \"icon\";\n /**\n * `\"icon\"`: a compact icon send button whose tooltip carries the shortcut —\n * replacing the inline `Ctrl + Enter to send` hint. Default `\"label\"`.\n */\n sendButton?: \"label\" | \"icon\";\n /**\n * Tokens already used — the caller's REAL value, e.g. an agent's context\n * usage. The meter shows this plus the estimate for the draft. Without it the\n * meter estimates the draft alone, as before.\n */\n usedTokens?: number;\n /**\n * `\"always\"` (default) — as before. `\"near-limit\"` — hidden until usage passes\n * `meterShowAt`, muted until `meterWarnAt`, warning colour past that.\n * `\"hidden\"` — never shown.\n */\n meter?: \"always\" | \"near-limit\" | \"hidden\";\n /** Fraction of `budgetTokens` at which a `\"near-limit\"` meter appears. Default 0.75. */\n meterShowAt?: number;\n /** Fraction of `budgetTokens` past which a `\"near-limit\"` meter takes the warning colour. Default 0.9. */\n meterWarnAt?: number;\n}\n\nconst DEFAULT_MENTION_COLOR: Record<string, string> = {\n agent: \"#a855f7\",\n file: \"#10b981\",\n person: \"#3b82f6\",\n};\n\nexport function PromptInput({\n budgetTokens,\n commands = [],\n mentions = [],\n showHint = true,\n platform,\n onSubmit,\n placeholder,\n charsPerToken = 4,\n mentionColor,\n maxHeight = 280,\n aboveInput,\n className,\n pasteThreshold,\n pasteImages = false,\n previewChars = 20,\n renderPastePreview,\n pasteClassNames,\n pasteFilesName,\n attachButton = \"label\",\n sendButton = \"label\",\n usedTokens,\n meter = \"always\",\n meterShowAt = 0.75,\n meterWarnAt = 0.9,\n ...rest\n}: PromptInputProps) {\n const [text, setText] = useState(\"\");\n /** Inline pills need an editor that can hold them; a textarea cannot. */\n const inline = pasteThreshold !== undefined || pasteImages;\n const editorRef = useRef<InlinePasteEditorHandle>(null);\n const paste = useInlinePaste({\n pasteThreshold,\n pasteImages,\n previewChars,\n renderPastePreview,\n classNames: pasteClassNames,\n disabled: false,\n editorRef,\n });\n const [attachments, setAttachments] = useState<PromptAttachment[]>([]);\n const [picker, setPicker] = useState<null | {\n kind: \"cmd\" | \"mention\";\n start: number;\n query: string;\n cursor: number;\n }>(null);\n const taRef = useRef<HTMLTextAreaElement>(null);\n const fileRef = useRef<HTMLInputElement>(null);\n const [dragOver, setDragOver] = useState(false);\n\n const colors = mentionColor ?? DEFAULT_MENTION_COLOR;\n\n /**\n * Resolved AFTER mount, never during render.\n *\n * `navigator` read during render disagrees with the server's HTML and\n * hydration patches it — so the fix for a wrong label would have introduced a\n * hydration mismatch instead. The first paint names `Ctrl`, which is\n * pressable on every platform including a Mac, and an Apple client swaps to\n * `⌘` on the next tick. A prop, when given, wins outright and no detection\n * runs at all.\n */\n const [detected, setDetected] = useState<FancyPlatform>(\"generic\");\n useEffect(() => {\n if (platform) return;\n setDetected(detectPlatform(browserPlatformHints()));\n }, [platform]);\n const modKey = modifierKeyLabel(platform ?? detected);\n\n const resolvedPlaceholder =\n placeholder ??\n `Ask anything. Type / for commands, @ for mentions. ${modKey}+Enter to send.`;\n\n // Estimated from what will actually be SENT — pills expanded — so a held\n // paste counts for its text, not for the few characters of its marker.\n const draftTokens = useMemo(\n () =>\n Math.ceil((inline ? paste.expand(text) : text).length / Math.max(1, charsPerToken)),\n [text, inline, paste, charsPerToken],\n );\n const tokens = (usedTokens ?? 0) + draftTokens;\n const ratio = Math.min(1, tokens / budgetTokens);\n const meterLevel: \"ok\" | \"caution\" | \"warn\" | \"muted\" | null =\n meter === \"hidden\"\n ? null\n : meter === \"near-limit\"\n ? ratio < meterShowAt\n ? null\n : ratio >= meterWarnAt\n ? \"warn\"\n : \"muted\"\n : ratio < 0.6\n ? \"ok\"\n : ratio < 0.85\n ? \"caution\"\n : \"warn\";\n const meterColor =\n meterLevel === \"ok\"\n ? \"#10b981\"\n : meterLevel === \"caution\"\n ? \"#f59e0b\"\n : meterLevel === \"warn\"\n ? \"#ef4444\"\n : \"#a1a1aa\";\n\n const filteredCmds = useMemo(\n () =>\n picker?.kind === \"cmd\"\n ? commands.filter((c) =>\n c.name.slice(1).toLowerCase().startsWith(picker.query.toLowerCase()),\n )\n : [],\n [picker, commands],\n );\n const filteredMentions = useMemo(\n () =>\n picker?.kind === \"mention\"\n ? mentions.filter((m) =>\n m.name.toLowerCase().includes(picker.query.toLowerCase()),\n )\n : [],\n [picker, mentions],\n );\n const items: Array<PromptCmd | PromptMention> =\n picker?.kind === \"cmd\"\n ? filteredCmds\n : picker?.kind === \"mention\"\n ? filteredMentions\n : [];\n\n useEffect(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.style.height = \"auto\";\n ta.style.height = Math.min(maxHeight, ta.scrollHeight) + \"px\";\n }, [text, maxHeight]);\n\n const updateText = (next: string, caret: number) => {\n setText(next);\n let triggerIdx = -1;\n let triggerKind: \"cmd\" | \"mention\" | null = null;\n for (let i = caret - 1; i >= 0; i--) {\n const ch = next[i];\n if (ch === \"@\") {\n triggerKind = \"mention\";\n triggerIdx = i;\n break;\n }\n if (ch === \"/\" && (i === 0 || /\\s/.test(next[i - 1] ?? \"\"))) {\n triggerKind = \"cmd\";\n triggerIdx = i;\n break;\n }\n if (/\\s/.test(ch)) break;\n }\n if (triggerKind !== null && triggerIdx >= 0) {\n const query = next.slice(triggerIdx + 1, caret);\n setPicker({ kind: triggerKind, start: triggerIdx, query, cursor: 0 });\n } else {\n setPicker(null);\n }\n };\n\n const insertChoice = (i: number) => {\n if (!picker || items.length === 0) return;\n const choice = items[i] ?? items[0];\n const insert =\n picker.kind === \"cmd\"\n ? (choice as PromptCmd).name + \" \"\n : `@${(choice as PromptMention).id} `;\n const before = text.slice(0, picker.start);\n const after = text.slice(picker.start + 1 + picker.query.length);\n const next = before + insert + after;\n setText(next);\n setPicker(null);\n if (inline) {\n // The editor rebuilds from the value and puts the caret back itself.\n editorRef.current?.setValue(next, before.length + insert.length);\n return;\n }\n requestAnimationFrame(() => {\n const ta = taRef.current;\n if (!ta) return;\n ta.focus();\n const pos = before.length + insert.length;\n ta.setSelectionRange(pos, pos);\n });\n };\n\n const submit = () => {\n // A message that is only a paste counts: its marker is in `text`.\n if (!text.trim() && attachments.length === 0) return;\n\n if (inline) {\n // Every pill goes out where it sits; pasted images join the attachments\n // in message order, with their Files, so a host sends them like any other.\n const pastedImages: PromptAttachment[] = paste.imagesIn(text).map((image) => ({\n id: image.id,\n name: image.file.name,\n bytes: image.file.size,\n file: image.file,\n type: image.file.type,\n }));\n onSubmit(paste.expand(text), [...attachments, ...pastedImages]);\n paste.clear();\n } else {\n onSubmit(text, attachments);\n }\n setText(\"\");\n setAttachments([]);\n setPicker(null);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (picker) {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setPicker((p) =>\n p ? { ...p, cursor: Math.min(items.length - 1, p.cursor + 1) } : p,\n );\n return;\n }\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setPicker((p) => (p ? { ...p, cursor: Math.max(0, p.cursor - 1) } : p));\n return;\n }\n if (e.key === \"Enter\" && !e.metaKey && !e.ctrlKey && items.length > 0) {\n e.preventDefault();\n insertChoice(picker.cursor);\n return;\n }\n if (e.key === \"Escape\") {\n e.preventDefault();\n setPicker(null);\n return;\n }\n }\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n submit();\n }\n };\n\n /**\n * Build attachments from a FileList, KEEPING the File.\n *\n * Shared by the drop handler and the picker so the two cannot drift — the\n * picker being a second, subtly different copy of this is exactly how one of\n * them would end up dropping the File again.\n */\n const attach = (list: FileList | File[] | null) => {\n const files = Array.from(list ?? []);\n if (files.length === 0) return;\n\n setAttachments((cur) => [\n ...cur,\n ...files.map((f) => ({\n id: crypto.randomUUID(),\n name: f.name,\n bytes: f.size,\n file: f,\n type: f.type,\n })),\n ]);\n };\n\n const onDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n setDragOver(false);\n attach(e.dataTransfer.files);\n };\n\n /**\n * Paste a screenshot, get an attachment.\n *\n * There was no paste handler at all, so a pasted image did nothing — no chip,\n * no error — and a host that had swapped its own paste-capable textarea for\n * this component lost the feature without noticing.\n *\n * Files attach only when the clipboard carries NO plain text. Word, Excel and\n * most editors put a picture of the selection beside the text; attaching that\n * would turn every pasted sentence into a screenshot of the sentence. A pure\n * image paste has nothing for the browser to insert, so the default is\n * prevented only then, and a text paste is never touched.\n */\n const onPaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const data = e.clipboardData;\n const files = Array.from(data?.files ?? []);\n\n if (files.length === 0 || (data?.getData(\"text/plain\") ?? \"\") !== \"\") return;\n\n e.preventDefault();\n attach(files);\n };\n\n return (\n <div\n // Spread FIRST so an internal handler or data attribute cannot be\n // clobbered from outside, and so a missing one fails loudly here rather\n // than at a consumer's selector. `className` is merged below instead.\n {...rest}\n // The component had no root handle at all, so an agent reading the\n // composer had to guess at classes. The drag state is on it too: a bridge\n // that wants to know whether a drop is in flight should not have to infer\n // it from Tailwind colours.\n data-react-fancy-prompt-input=\"\"\n data-react-fancy-prompt-input-drag={dragOver ? \"over\" : \"idle\"}\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}\n className={cn(\n \"relative rounded-md border bg-white transition dark:bg-zinc-900\",\n dragOver\n ? \"border-violet-400 bg-violet-50/50 dark:border-violet-600 dark:bg-violet-950/30\"\n : \"border-zinc-200 dark:border-zinc-800\",\n className,\n )}\n >\n {aboveInput && (\n <div className=\"border-b border-zinc-200 dark:border-zinc-800\">\n {aboveInput}\n </div>\n )}\n {attachments.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 border-b border-zinc-200 px-3 py-2 dark:border-zinc-800\">\n {attachments.map((a) => (\n <span\n key={a.id}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-zinc-100 px-2 py-0.5 text-[11px] dark:bg-zinc-800\"\n >\n <Icon name=\"paperclip\" size=\"xs\" className=\"text-zinc-400\" />\n <span className=\"font-mono\">{a.name}</span>\n <span className=\"text-zinc-400\">{fmtSize(a.bytes)}</span>\n <button\n onClick={() =>\n setAttachments((cur) => cur.filter((x) => x.id !== a.id))\n }\n className=\"opacity-50 hover:opacity-100\"\n aria-label=\"Remove attachment\"\n >\n ×\n </button>\n </span>\n ))}\n </div>\n )}\n\n <div className=\"relative\">\n {inline ? (\n <>\n <InlinePasteEditor\n ref={editorRef}\n value={text}\n known={paste.known}\n onChange={(next, caret) => {\n updateText(next, caret);\n paste.prune(next);\n }}\n onSubmit={submit}\n submitKey=\"mod-enter\"\n onKeyDown={onKeyDown}\n onPaste={paste.decidePaste}\n onHostsChange={paste.onHostsChange}\n placeholder={resolvedPlaceholder}\n disabled={false}\n maxHeight={maxHeight}\n placeholderClassName=\"left-3 top-2.5 text-[14px] leading-relaxed\"\n className={cn(\n \"block min-h-[5.5rem] px-3 py-2.5 text-[14px] leading-relaxed\",\n pasteClassNames?.input,\n )}\n />\n {paste.portals}\n {pasteImages && pasteFilesName && (\n <PastedFilesInput\n name={pasteFilesName}\n files={paste.imagesIn(text).map((i) => i.file)}\n />\n )}\n </>\n ) : (\n <textarea\n ref={taRef}\n value={text}\n onChange={(e) => updateText(e.target.value, e.target.selectionStart)}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n placeholder={resolvedPlaceholder}\n spellCheck={false}\n className=\"block w-full resize-none bg-transparent px-3 py-2.5 text-[14px] leading-relaxed outline-none placeholder:text-zinc-400\"\n rows={3}\n />\n )}\n\n {picker && items.length > 0 && (\n <div className=\"absolute bottom-full left-2 z-10 mb-1 w-72 overflow-hidden rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900\">\n <div className=\"border-b border-zinc-100 bg-zinc-50 px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950\">\n {picker.kind === \"cmd\" ? \"Commands\" : \"Mention\"} · {items.length}\n </div>\n <ul className=\"max-h-56 overflow-y-auto\">\n {items.map((item, i) => {\n const active = i === picker.cursor;\n if (picker.kind === \"cmd\") {\n const c = item as PromptCmd;\n return (\n <li\n key={c.name}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`cursor-pointer px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <div className=\"font-mono font-medium text-violet-700 dark:text-violet-300\">\n {c.name}\n </div>\n <div className=\"text-[11px] text-zinc-500\">{c.hint}</div>\n </li>\n );\n }\n const m = item as PromptMention;\n return (\n <li\n key={m.id}\n onMouseDown={(e) => {\n e.preventDefault();\n insertChoice(i);\n }}\n onMouseEnter={() =>\n setPicker((p) => (p ? { ...p, cursor: i } : p))\n }\n className={`flex cursor-pointer items-center gap-2 px-2 py-1.5 text-[12px] ${\n active\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\"\n }`}\n >\n <span\n className=\"h-2 w-2 rounded-full\"\n style={{ backgroundColor: colors[m.kind] ?? \"#71717a\" }}\n />\n <span className=\"font-medium\">{m.name}</span>\n <span className=\"ml-auto text-[10px] uppercase tracking-wider text-zinc-400\">\n {m.kind}\n </span>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n\n <div className=\"flex items-center gap-2 border-t border-zinc-200 bg-zinc-50/60 px-3 py-2 dark:border-zinc-800 dark:bg-zinc-900/40\">\n <Tooltip content={attachButton === \"icon\" ? \"Attach files — or drop them here\" : \"Drop files here, or click\"}>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n icon=\"paperclip\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-attach=\"\"\n // An icon alone has no name; the tooltip is not one a screen reader reads.\n aria-label={attachButton === \"icon\" ? \"Attach files\" : undefined}\n onClick={() => fileRef.current?.click()}\n >\n {attachButton === \"icon\" ? null : \"attach\"}\n </Button>\n </Tooltip>\n {/*\n The button above shipped with a no-op onClick and a tooltip reading\n \"Drop files here, or click\" — an affordance that lied. Drop-only also\n meant keyboard and touch users could not attach at all.\n\n It then shipped with a literal paperclip EMOJI as its icon, which\n needs a COLOUR\n EMOJI FONT — not merely broad coverage — so a lean container renders a\n tofu box where the affordance should be. `icon=\"paperclip\"` draws an\n SVG from the kit's own icon layer, which is the same reason the rest of\n the suite does not hand-roll iconography.\n */}\n <input\n ref={fileRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n attach(e.target.files);\n // Let the same file be picked twice in a row.\n e.target.value = \"\";\n }}\n />\n {meterLevel !== null && (\n <div\n data-react-fancy-prompt-input-meter=\"\"\n data-level={meterLevel}\n className=\"ml-2 flex min-w-0 items-center gap-1.5 overflow-hidden\"\n >\n <div className=\"h-1.5 w-24 shrink overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-700\">\n <div\n className=\"h-full rounded-full transition-all\"\n style={{ width: `${ratio * 100}%`, backgroundColor: meterColor }}\n />\n </div>\n <span className=\"font-mono text-[11px]\" style={{ color: meterColor }}>\n {fmtTokens(tokens)} / {fmtTokens(budgetTokens)}\n </span>\n </div>\n )}\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {/* With an icon send button the shortcut lives in its tooltip instead. */}\n {showHint && sendButton !== \"icon\" && (\n <span\n className=\"hidden text-[10px] text-zinc-500 sm:inline\"\n data-react-fancy-prompt-input-hint={modKey === \"⌘\" ? \"apple\" : \"generic\"}\n >\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n {modKey}\n </kbd>{\" \"}\n +{\" \"}\n <kbd className=\"rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300\">\n Enter\n </kbd>{\" \"}\n to send\n </span>\n )}\n {sendButton === \"icon\" ? (\n <Tooltip content={`Send · ${modKey}+Enter`}>\n <Button\n color=\"violet\"\n size=\"sm\"\n icon=\"arrow-up\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-send=\"\"\n aria-label=\"Send\"\n onClick={submit}\n />\n </Tooltip>\n ) : (\n <Button\n color=\"violet\"\n size=\"sm\"\n iconTrailing=\"arrow-right\"\n className=\"shrink-0\"\n data-react-fancy-prompt-input-send=\"\"\n onClick={submit}\n >\n send\n </Button>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction fmtTokens(n: number): string {\n if (n < 1000) return `${n}`;\n return `${(n / 1000).toFixed(1)}k`;\n}\n\nfunction fmtSize(b: number): string {\n if (b < 1024) return `${b} B`;\n if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)} KB`;\n return `${(b / 1024 / 1024).toFixed(1)} MB`;\n}\n"]}