@photon-ai/pho-ui 4.11.0 → 4.12.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.
Files changed (48) hide show
  1. package/dist/chunks/animated-height-zr7BmFY1.js +56 -0
  2. package/dist/chunks/animated-height-zr7BmFY1.js.map +1 -0
  3. package/dist/chunks/basic-page-CJ11ekjH.js +2217 -0
  4. package/dist/chunks/basic-page-CJ11ekjH.js.map +1 -0
  5. package/dist/chunks/{chat-B0WIgEyM.js → chat-CU3XVm99.js} +2 -2
  6. package/dist/chunks/{chat-B0WIgEyM.js.map → chat-CU3XVm99.js.map} +1 -1
  7. package/dist/chunks/{checkbox-CLPmblNA.js → checkbox-CwvoEJhd.js} +2 -2
  8. package/dist/chunks/{checkbox-CLPmblNA.js.map → checkbox-CwvoEJhd.js.map} +1 -1
  9. package/dist/chunks/choice-card-_Ocs0iUj.js +17 -0
  10. package/dist/chunks/choice-card-_Ocs0iUj.js.map +1 -0
  11. package/dist/chunks/{command-iYvU6Mhf.js → command-D5g49VqR.js} +3 -3
  12. package/dist/chunks/{command-iYvU6Mhf.js.map → command-D5g49VqR.js.map} +1 -1
  13. package/dist/chunks/{data-table-B1dmrN6r.js → data-table-Ce_c6T73.js} +3 -3
  14. package/dist/chunks/{data-table-B1dmrN6r.js.map → data-table-Ce_c6T73.js.map} +1 -1
  15. package/dist/chunks/{dialog-MPvem7yV.js → dialog-ChS0tdHa.js} +120 -116
  16. package/dist/chunks/dialog-ChS0tdHa.js.map +1 -0
  17. package/dist/chunks/{filter-bar-B-oYYBsU.js → filter-bar-CMkvhvgL.js} +2 -2
  18. package/dist/chunks/{filter-bar-B-oYYBsU.js.map → filter-bar-CMkvhvgL.js.map} +1 -1
  19. package/dist/chunks/{input-DjvZoF8v.js → input-fFWvPJOf.js} +2 -1
  20. package/dist/chunks/{input-DjvZoF8v.js.map → input-fFWvPJOf.js.map} +1 -1
  21. package/dist/components/chat.js +1 -1
  22. package/dist/components/checkbox.js +1 -1
  23. package/dist/components/command.js +1 -1
  24. package/dist/components/data-table.js +1 -1
  25. package/dist/components/dialog.js +1 -1
  26. package/dist/components/field.js +34 -29
  27. package/dist/components/field.js.map +1 -1
  28. package/dist/components/filter-bar.js +1 -1
  29. package/dist/components/input.js +1 -1
  30. package/dist/components/radio-group.js +64 -59
  31. package/dist/components/radio-group.js.map +1 -1
  32. package/dist/index.js +6 -6
  33. package/dist/sections/basic-page.js +2 -2
  34. package/dist/src/components/dialog/dialog.d.ts +9 -1
  35. package/dist/src/components/field/field.d.ts +11 -1
  36. package/dist/src/components/radio-group/radio-card.d.ts +11 -4
  37. package/dist/src/sections/basic-page/basic-page.d.ts +145 -15
  38. package/dist/src/sections/basic-page/index.d.ts +1 -1
  39. package/dist/src/utils/animated-height.d.ts +16 -7
  40. package/dist/src/utils/choice-card.d.ts +8 -1
  41. package/package.json +1 -1
  42. package/dist/chunks/animated-height-I44sUq0n.js +0 -48
  43. package/dist/chunks/animated-height-I44sUq0n.js.map +0 -1
  44. package/dist/chunks/basic-page-B5FsORRi.js +0 -1885
  45. package/dist/chunks/basic-page-B5FsORRi.js.map +0 -1
  46. package/dist/chunks/choice-card-BVNP1NB6.js +0 -17
  47. package/dist/chunks/choice-card-BVNP1NB6.js.map +0 -1
  48. package/dist/chunks/dialog-MPvem7yV.js.map +0 -1
@@ -4,7 +4,7 @@ import { n as oe } from "./link-provider-DXzDQ08N.js";
4
4
  import { FADE_SWAP as K, PRESS_SCALE_ROW as se, SPRING_PRESS as le, TRAVEL_LINEAR as ce } from "../motion.js";
5
5
  import { a as z } from "./button-C9VqBBIr.js";
6
6
  import { t as I } from "./createReactComponent-BqCmnqfX.js";
7
- import { t as de } from "./input-DjvZoF8v.js";
7
+ import { t as de } from "./input-fFWvPJOf.js";
8
8
  import { n as B } from "./avatar-BkmGDIqf.js";
9
9
  import { t as ue } from "./IconSearch-BKAHkLyX.js";
10
10
  import { t as C } from "./scroll-area-DSwD9th7.js";
@@ -616,4 +616,4 @@ export {
616
616
  wt as t
617
617
  };
618
618
 
619
- //# sourceMappingURL=chat-B0WIgEyM.js.map
619
+ //# sourceMappingURL=chat-CU3XVm99.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-B0WIgEyM.js","names":["__iconNode","__iconNode","__iconNode"],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowLeft.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowUp.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconUser.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconUsers.mjs","../../src/components/chat/chat.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M5 12l14 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M5 12l6 6\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M5 12l6 -6\", \"key\": \"svg-2\" }]];\nconst IconArrowLeft = createReactComponent(\"outline\", \"arrow-left\", \"ArrowLeft\", __iconNode);\n\nexport { __iconNode, IconArrowLeft as default };\n//# sourceMappingURL=IconArrowLeft.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M12 5l0 14\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M18 11l-6 -6\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M6 11l6 -6\", \"key\": \"svg-2\" }]];\nconst IconArrowUp = createReactComponent(\"outline\", \"arrow-up\", \"ArrowUp\", __iconNode);\n\nexport { __iconNode, IconArrowUp as default };\n//# sourceMappingURL=IconArrowUp.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2\", \"key\": \"svg-1\" }]];\nconst IconUser = createReactComponent(\"outline\", \"user\", \"User\", __iconNode);\n\nexport { __iconNode, IconUser as default };\n//# sourceMappingURL=IconUser.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M5 7a4 4 0 1 0 8 0a4 4 0 1 0 -8 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M3 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M16 3.13a4 4 0 0 1 0 7.75\", \"key\": \"svg-2\" }], [\"path\", { \"d\": \"M21 21v-2a4 4 0 0 0 -3 -3.85\", \"key\": \"svg-3\" }]];\nconst IconUsers = createReactComponent(\"outline\", \"users\", \"Users\", __iconNode);\n\nexport { __iconNode, IconUsers as default };\n//# sourceMappingURL=IconUsers.mjs.map\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type AnchorHTMLAttributes,\n type ButtonHTMLAttributes,\n type CSSProperties,\n type ComponentProps,\n type ComponentType,\n type FormEvent,\n type KeyboardEvent,\n type PointerEvent,\n type ReactNode,\n type Ref,\n type RefObject,\n} from \"react\";\nimport {\n IconArrowLeft,\n IconArrowUp,\n IconSearch,\n IconUser,\n IconUsers,\n} from \"@tabler/icons-react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\nimport {\n BLUR_PX,\n FADE_SWAP,\n PRESS_SCALE_ROW,\n SPRING_PRESS,\n TRAVEL_LINEAR,\n} from \"../../motion\";\nimport { Avatar } from \"../avatar\";\nimport { Button } from \"../button\";\nimport { Input, type InputProps } from \"../input\";\nimport { ScrollArea } from \"../scroll-area\";\nimport { Skeleton } from \"../skeleton\";\nimport { StatusView, type StatusViewProps } from \"../status-view\";\nimport { cn } from \"../../utils/cn\";\nimport { useLinkComponent } from \"../../utils/link-provider\";\n\n/**\n * Chat — an inbox in one card: the conversations down the left, the open\n * thread on the right with its messages scrolling up from the composer.\n * It composes the smaller parts (`Message` rows of `Bubble`s in a\n * `ScrollArea`, an `Input` for search, `Button`s to send and go back) the\n * way `Sidebar` composes a rail: rows that press, one active, links\n * through the host's `LinkProvider`.\n *\n * Two layouts. `default` seats both panes side by side — the divider\n * between them drags so either pane can grow, each down to a min width.\n * `compact` shows one at a time — the list, then the thread with a way\n * back — for a narrow column or a phone. Opening a conversation pushes\n * the thread in from the right; back pops the list in from the left, a\n * short drift on `TRAVEL_LINEAR` with a `FADE_SWAP` fade. `auto` is\n * compact only while the frame is narrower than 42rem (a container\n * query, so it follows the card, not the viewport). Which pane is up is\n * `pane`, controlled or not; opening a conversation moves to the thread,\n * the header's back button returns.\n *\n * Presentational, like every Pho part: the page fetches, formats times,\n * and decides who is who. The thread stays pinned to its newest message\n * while the reader is at the bottom, and keeps its place when earlier\n * pages arrive above.\n */\n\nexport type ChatLayout = \"default\" | \"compact\" | \"auto\";\nexport type ChatPane = \"list\" | \"thread\";\n/** Push is 1 (thread from the right); pop is −1 (list from the left). */\nexport type ChatPaneDirection = 1 | -1;\n\n/** Same chrome as `BasicPage.Card` and `LogList` — one card surface. */\nconst CHAT_SURFACE = \"rounded-base border border-pho-secondary bg-pho-primary\";\n\n// Below this frame width `auto` is compact: the `@2xl` container variant\n// (42rem) in the class strings below. Those variants are spelled out in\n// full on purpose — Tailwind finds utilities by scanning source text, so\n// a variant built from a variable (`${AUTO_WIDE}` before the colon) never\n// reached a consumer's CSS and `auto` stayed single-pane at every width.\n// chat.test.tsx keeps it that way.\n/** `42rem` in px at the 16px root — `frameWidth` is measured in px. */\nconst AUTO_WIDE_PX = 672;\n/**\n * Compact pane travel — a short drift, the same scale as `BAR_RISE_PX`,\n * not a full-width slide.\n */\nconst PANE_TRAVEL_PX = 24;\n/** Outgoing pane drift — same distance as BasicPage `BACK_LABEL_LEAVE_X`. */\nconst PANE_LEAVE_PX = 8;\n\n/** Search (`p-3` + sm Input) is the pane top-bar height; Header matches it. */\nconst TOP_BAR = \"min-h-[61px]\";\n\n/**\n * Wide layouts start the list at 273 — the measured inbox column, not\n * `w-80`. It will not go below `min-w-64` (256); the thread will not go\n * below `min-w-80` (320).\n */\nconst LIST_WIDTH_PX = 273;\nconst LIST_MIN_PX = 256;\nconst THREAD_MIN_PX = 320;\nconst SPLIT_STEP_PX = 16;\n\nfunction clampListWidth(width: number, rootWidth: number) {\n const next = Math.max(LIST_MIN_PX, width);\n if (rootWidth <= 0) return Number.isFinite(next) ? next : LIST_MIN_PX;\n return Math.min(next, Math.max(LIST_MIN_PX, rootWidth - THREAD_MIN_PX));\n}\n\ninterface ChatContextValue {\n layout: ChatLayout;\n pane: ChatPane;\n setPane: (pane: ChatPane) => void;\n /** Latest list ↔ thread step: 1 push, −1 pop. */\n direction: ChatPaneDirection;\n /** One pane at a time — compact, or `auto` once the frame measures narrow. */\n swap: boolean;\n /** True after the first list ↔ thread step — later remounts still push. */\n swapped: boolean;\n listWidth: number;\n frameWidth: number;\n resizeList: (width: number) => void;\n rootRef: RefObject<HTMLDivElement | null>;\n}\n\nconst ChatContext = createContext<ChatContextValue | null>(null);\n\nfunction useChat(part: string): ChatContextValue {\n const ctx = useContext(ChatContext);\n if (ctx == null) {\n throw new Error(`Chat.${part} must be used inside Chat.Root`);\n }\n return ctx;\n}\n\n// React 18 warns that useLayoutEffect does nothing on the server; fall\n// back to useEffect there so SSR'd docs stay quiet.\nconst useIsoLayoutEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nfunction paneDirectionFor(pane: ChatPane): ChatPaneDirection {\n return pane === \"thread\" ? 1 : -1;\n}\n\n/**\n * Compact (and `auto` once the frame measures narrower than 42rem) mounts\n * one pane at a time so `AnimatePresence` can push/pop. `frameWidth` 0 is\n * the unmeasured / SSR frame — treat it as wide so both panes render and\n * nothing flashes.\n */\nfunction isPaneSwap(layout: ChatLayout, frameWidth: number) {\n return (\n layout === \"compact\" ||\n (layout === \"auto\" && frameWidth > 0 && frameWidth < AUTO_WIDE_PX)\n );\n}\n\n/**\n * The compact pane swap — incoming travels `PANE_TRAVEL_PX` on\n * `TRAVEL_LINEAR`, fades and breathes `BLUR_PX` on `FADE_SWAP`; outgoing\n * drifts `PANE_LEAVE_PX` the other way. Under reduced motion: opacity\n * only, and instant.\n */\nexport function paneSwapMotion(\n direction: ChatPaneDirection,\n reduceMotion?: boolean | null,\n) {\n if (reduceMotion) {\n return {\n initial: { opacity: 0 },\n animate: { opacity: 1 },\n exit: { opacity: 0 },\n transition: { duration: 0 },\n };\n }\n return {\n initial: {\n x: direction * PANE_TRAVEL_PX,\n opacity: 0,\n filter: `blur(${BLUR_PX}px)`,\n },\n animate: { x: 0, opacity: 1, filter: \"blur(0px)\" },\n exit: {\n x: -direction * PANE_LEAVE_PX,\n opacity: 0,\n filter: `blur(${BLUR_PX}px)`,\n },\n transition: { x: TRAVEL_LINEAR, opacity: FADE_SWAP, filter: FADE_SWAP },\n };\n}\n\nfunction paneSwapVariants(reduceMotion: boolean | null) {\n return {\n enter: (direction: ChatPaneDirection) =>\n paneSwapMotion(direction, reduceMotion).initial,\n rest: (direction: ChatPaneDirection) =>\n paneSwapMotion(direction, reduceMotion).animate,\n leave: (direction: ChatPaneDirection) =>\n paneSwapMotion(direction, reduceMotion).exit,\n };\n}\n\n/**\n * DOM handlers whose React signatures clash with Motion's gesture props.\n * Same omit list as `Button` — swap panes and conversation rows render\n * through `motion.*`.\n */\ntype MotionHandlerConflicts =\n | \"onAnimationStart\"\n | \"onAnimationEnd\"\n | \"onAnimationIteration\"\n | \"onDrag\"\n | \"onDragStart\"\n | \"onDragEnd\"\n | \"onDragEnter\"\n | \"onDragExit\"\n | \"onDragLeave\"\n | \"onDragOver\"\n | \"onDrop\";\n\ntype SwapPaneProps = {\n show: boolean;\n swapped: boolean;\n direction: ChatPaneDirection;\n reduceMotion: boolean | null;\n children?: ReactNode;\n} & (\n | ({ as: \"aside\" } & Omit<\n ComponentProps<\"aside\">,\n \"children\" | MotionHandlerConflicts\n >)\n | ({ as: \"section\" } & Omit<\n ComponentProps<\"section\">,\n \"children\" | MotionHandlerConflicts\n >)\n);\n\ntype SwapMotionProps = {\n custom: ChatPaneDirection;\n variants: ReturnType<typeof paneSwapVariants>;\n initial: \"enter\";\n animate: \"rest\";\n exit: \"leave\";\n transition: ReturnType<typeof paneSwapMotion>[\"transition\"];\n};\n\n/**\n * The compact face — Root's `AnimatePresence` keys list vs thread. `custom`\n * on that presence feeds this step's push/pop into the exiting face.\n */\nfunction SwapPane({\n as,\n show,\n swapped,\n direction,\n reduceMotion,\n children,\n ...props\n}: SwapPaneProps) {\n const swap = paneSwapMotion(direction, reduceMotion);\n const motionProps: SwapMotionProps = {\n custom: direction,\n variants: paneSwapVariants(reduceMotion),\n initial: \"enter\",\n animate: \"rest\",\n exit: \"leave\",\n transition: swap.transition,\n };\n // Skip the first paint only before any pane change — a Thread that\n // remounts (host `key`) on the way in still pushes.\n return (\n <AnimatePresence\n initial={!swapped && show ? false : undefined}\n mode=\"popLayout\"\n custom={direction}\n >\n {show ? (\n as === \"aside\" ? (\n <motion.aside key=\"list\" {...props} {...motionProps}>\n {children}\n </motion.aside>\n ) : (\n <motion.section key=\"thread\" {...props} {...motionProps}>\n {children}\n </motion.section>\n )\n ) : null}\n </AnimatePresence>\n );\n}\n\n/* --------------------------------- root --------------------------------- */\n\nexport interface ChatRootProps extends ComponentProps<\"div\"> {\n /**\n * `default` shows both panes; `compact` one at a time; `auto` is\n * compact while the frame is narrower than 42rem.\n * @default \"default\"\n */\n layout?: ChatLayout;\n /** The pane that is up in a compact layout. Pair with `onPaneChange`. */\n pane?: ChatPane;\n /** Initial pane when uncontrolled. @default \"list\" */\n defaultPane?: ChatPane;\n /** Called with the next pane — a row opened a thread, back was pressed. */\n onPaneChange?: (pane: ChatPane) => void;\n ref?: Ref<HTMLDivElement>;\n}\n\n/**\n * The card. Give it a height (`h-[32rem]`, or `min-h-0 flex-1` in a\n * column that fills the page); the panes scroll inside it.\n */\nfunction Root({\n layout = \"default\",\n pane: paneProp,\n defaultPane = \"list\",\n onPaneChange,\n className,\n style,\n ref,\n ...props\n}: ChatRootProps) {\n const [uncontrolledPane, setUncontrolledPane] = useState(defaultPane);\n const [listWidth, setListWidth] = useState(LIST_WIDTH_PX);\n const [frameWidth, setFrameWidth] = useState(0);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const controlled = paneProp !== undefined;\n const pane = controlled ? paneProp : uncontrolledPane;\n const [direction, setDirection] = useState<ChatPaneDirection>(() =>\n paneDirectionFor(pane),\n );\n const [swapped, setSwapped] = useState(false);\n const prevPaneRef = useRef(pane);\n // Keep this render's direction aligned with `pane` so a controlled\n // update and a `setPane` call both push/pop on the same frame.\n let renderedDirection = direction;\n let renderedSwapped = swapped;\n if (prevPaneRef.current !== pane) {\n renderedDirection = paneDirectionFor(pane);\n renderedSwapped = true;\n prevPaneRef.current = pane;\n if (renderedDirection !== direction) setDirection(renderedDirection);\n if (!swapped) setSwapped(true);\n }\n const setPane = useCallback(\n (next: ChatPane) => {\n setDirection(paneDirectionFor(next));\n if (!controlled) setUncontrolledPane(next);\n onPaneChange?.(next);\n },\n [controlled, onPaneChange],\n );\n const resizeList = useCallback((width: number) => {\n setListWidth(clampListWidth(width, rootRef.current?.clientWidth ?? 0));\n }, []);\n const swap = isPaneSwap(layout, frameWidth);\n useIsoLayoutEffect(() => {\n const root = rootRef.current;\n if (!root || typeof ResizeObserver === \"undefined\") return;\n const tighten = () => {\n const frame = root.clientWidth;\n setFrameWidth(frame);\n setListWidth((current) => clampListWidth(current, frame));\n };\n tighten();\n const observer = new ResizeObserver(tighten);\n observer.observe(root);\n return () => observer.disconnect();\n }, []);\n const value = useMemo(\n () => ({\n layout,\n pane,\n setPane,\n direction: renderedDirection,\n swap,\n swapped: renderedSwapped,\n listWidth,\n frameWidth,\n resizeList,\n rootRef,\n }),\n [\n layout,\n pane,\n setPane,\n renderedDirection,\n swap,\n renderedSwapped,\n listWidth,\n frameWidth,\n resizeList,\n ],\n );\n return (\n <ChatContext.Provider value={value}>\n <div\n ref={(node) => {\n rootRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) {\n (ref as { current: HTMLDivElement | null }).current = node;\n }\n }}\n data-chat=\"\"\n data-basic-page-card=\"\"\n data-layout={layout}\n data-pane={pane}\n style={\n {\n ...style,\n \"--chat-list-width\": `${listWidth}px`,\n } as CSSProperties\n }\n className={cn(\n CHAT_SURFACE,\n \"@container relative flex min-h-0 min-w-0 overflow-hidden\",\n className,\n )}\n {...props}\n />\n </ChatContext.Provider>\n );\n}\n\n/* --------------------------------- list --------------------------------- */\n\n/** The left pane — search above, conversations below, on the page wash. */\nfunction List({\n className,\n children,\n id: idProp,\n ...props\n}: ComponentProps<\"aside\">) {\n const { layout, pane, direction, swap, swapped } = useChat(\"List\");\n const reduceMotion = useReducedMotion();\n const uid = useId();\n const listId = idProp ?? uid;\n const listClass = cn(\n \"border-pho-secondary bg-pho-page relative z-10 flex min-h-0 shrink-0 flex-col\",\n layout === \"default\" && \"min-w-64 w-[var(--chat-list-width)] border-r\",\n layout === \"compact\" && \"w-full\",\n layout === \"auto\" &&\n cn(\n \"w-full @2xl:min-w-64 @2xl:w-[var(--chat-list-width)] @2xl:border-r\",\n !swap && pane === \"thread\" && \"@max-2xl:hidden\",\n ),\n className,\n );\n const body = (\n <>\n {children}\n {layout !== \"compact\" && <Splitter controlsId={listId} />}\n </>\n );\n const rest = {\n id: listId,\n \"aria-label\": \"Conversations\",\n \"data-chat-list\": \"\",\n className: listClass,\n ...props,\n };\n if (!swap) {\n return <aside {...rest}>{body}</aside>;\n }\n return (\n <SwapPane\n as=\"aside\"\n show={pane === \"list\"}\n swapped={swapped}\n direction={direction}\n reduceMotion={reduceMotion}\n {...rest}\n >\n {body}\n </SwapPane>\n );\n}\n\n/**\n * The drag between the panes — a focusable separator. Hidden in\n * `compact`, and in `auto` while the frame is narrow.\n */\nfunction Splitter({ controlsId }: { controlsId: string }) {\n const { layout, listWidth, frameWidth, resizeList, rootRef } =\n useChat(\"Splitter\");\n const drag = useRef<{ x: number; width: number } | null>(null);\n\n const onPointerDown = (event: PointerEvent<HTMLDivElement>) => {\n if (event.button !== 0) return;\n event.currentTarget.setPointerCapture?.(event.pointerId);\n drag.current = { x: event.clientX, width: listWidth };\n };\n\n const onPointerMove = (event: PointerEvent<HTMLDivElement>) => {\n const start = drag.current;\n if (start == null) return;\n const root = rootRef.current;\n const rtl = root != null && getComputedStyle(root).direction === \"rtl\";\n const delta = (event.clientX - start.x) * (rtl ? -1 : 1);\n resizeList(start.width + delta);\n };\n\n const onPointerUp = () => {\n drag.current = null;\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const root = rootRef.current;\n const rtl = root != null && getComputedStyle(root).direction === \"rtl\";\n const shrink = rtl ? \"ArrowRight\" : \"ArrowLeft\";\n const grow = rtl ? \"ArrowLeft\" : \"ArrowRight\";\n const step = event.shiftKey ? SPLIT_STEP_PX * 2 : SPLIT_STEP_PX;\n if (event.key === shrink) {\n event.preventDefault();\n resizeList(listWidth - step);\n } else if (event.key === grow) {\n event.preventDefault();\n resizeList(listWidth + step);\n } else if (event.key === \"Home\") {\n event.preventDefault();\n resizeList(LIST_MIN_PX);\n } else if (event.key === \"End\") {\n event.preventDefault();\n const frame = root?.clientWidth ?? 0;\n if (frame > 0) resizeList(frame - THREAD_MIN_PX);\n }\n };\n\n const valueMax =\n frameWidth > 0\n ? Math.max(LIST_MIN_PX, frameWidth - THREAD_MIN_PX)\n : listWidth;\n\n return (\n <div\n // WAI-ARIA window splitter: a focusable separator with a value. An\n // `hr` can neither take focus nor carry the value attributes.\n // oxlint-disable-next-line jsx-a11y/prefer-tag-over-role\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label=\"Resize conversation list\"\n aria-controls={controlsId}\n aria-valuenow={listWidth}\n aria-valuemin={LIST_MIN_PX}\n aria-valuemax={valueMax}\n aria-valuetext={`${listWidth} pixels`}\n tabIndex={0}\n data-chat-splitter=\"\"\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n onKeyDown={onKeyDown}\n className={cn(\n \"absolute inset-y-0 -right-3 z-10 w-6 cursor-col-resize touch-none select-none\",\n \"outline-pho-brand focus-visible:outline-2 focus-visible:-outline-offset-2\",\n \"after:absolute after:inset-y-0 after:left-1/2 after:w-px after:-translate-x-1/2 after:bg-transparent\",\n \"[@media(hover:hover)]:hover:after:bg-pho-brand focus-visible:after:bg-pho-brand\",\n layout === \"auto\" && \"@max-2xl:hidden\",\n )}\n />\n );\n}\n\nexport interface ChatSearchProps extends Omit<\n InputProps,\n \"size\" | \"icon\" | \"label\" | \"hint\" | \"labelTrailing\"\n> {}\n\n/** The search row pinned over the conversations — an `sm` `Input`. */\nfunction Search({\n className,\n placeholder = \"Search\",\n ...props\n}: ChatSearchProps) {\n return (\n <div data-chat-search=\"\" className={cn(\"p-3\", TOP_BAR, className)}>\n <Input\n size=\"sm\"\n icon={IconSearch}\n placeholder={placeholder}\n aria-label=\"Search conversations\"\n autoComplete=\"off\"\n spellCheck={false}\n {...props}\n />\n </div>\n );\n}\n\n/**\n * The scrolling part of the list. Put a `ConversationList` in it — or a\n * `ConversationsLoading`, an `Empty` — and anything that belongs after\n * the rows (a load-older button).\n */\nfunction Conversations({\n className,\n children,\n ...props\n}: ComponentProps<\"div\">) {\n return (\n <div\n data-chat-conversations=\"\"\n className={cn(\"flex min-h-0 flex-1 flex-col\", className)}\n {...props}\n >\n <ScrollArea.Root className=\"min-h-0 flex-1\">\n <ScrollArea.Viewport>\n <ScrollArea.Content\n // Base UI sets `minWidth: fit-content` on Content; a long\n // title must truncate, not widen the pane.\n style={{ minWidth: 0 }}\n // Same horizontal rail as Sidebar sm (`px-3`): the selected\n // chip sits in the page wash instead of kissing the aside.\n className=\"flex min-h-full flex-col px-3 py-1\"\n >\n {children}\n </ScrollArea.Content>\n </ScrollArea.Viewport>\n <ScrollArea.Scrollbar>\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n </ScrollArea.Root>\n </div>\n );\n}\n\n/** The rows. */\nfunction ConversationList({ className, ...props }: ComponentProps<\"ul\">) {\n return (\n <ul\n data-chat-conversation-list=\"\"\n // list-none/m-0/p-0 shield the rows from host prose styles.\n className={cn(\"m-0 flex list-none flex-col gap-0.5 *:m-0\", className)}\n {...props}\n />\n );\n}\n\n/* ------------------------------ conversation ---------------------------- */\n\n/**\n * DOM handlers whose React signatures clash with Motion's gesture props.\n * Same omit list as `Button` — rows render through `motion.*`.\n */\ninterface ConversationBaseProps {\n /** Who — a number, a name, the members of a group. */\n title: ReactNode;\n /** When — the page's relative time (`2d ago`), trailing. */\n time?: ReactNode;\n /** The latest message, one truncated line. */\n preview?: ReactNode;\n /** Replace the default avatar (a person, or people for a `group`). */\n avatar?: ReactNode;\n /** A group conversation — the default avatar shows people. */\n group?: boolean;\n /** The open conversation. */\n active?: boolean;\n className?: string;\n}\n\nexport interface ChatConversationLinkProps\n extends\n ConversationBaseProps,\n Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n keyof ConversationBaseProps | MotionHandlerConflicts\n > {\n /** Destination — rendered through the host's `LinkProvider`. */\n href: string;\n}\n\nexport interface ChatConversationButtonProps\n extends\n ConversationBaseProps,\n Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n keyof ConversationBaseProps | MotionHandlerConflicts\n > {\n href?: undefined;\n}\n\nexport type ChatConversationProps =\n ChatConversationLinkProps | ChatConversationButtonProps;\n\n/** The row at rest, on hover, and while open — one pointer target. */\nconst CONVERSATION_ROW =\n \"outline-pho-brand rounded-base flex w-full cursor-pointer items-center gap-3 px-2 py-2.5 text-left transition-colors focus-visible:outline-2 focus-visible:-outline-offset-1\";\n/**\n * Open row — same chip as `Sidebar.Item` current (`aria-current=page`).\n * Weight lives on the title span, not here: time and preview stay Regular.\n */\nconst CONVERSATION_ROW_ACTIVE =\n \"bg-pho-primary text-pho-primary ring-pho-secondary ring-1 ring-inset *:data-icon:text-pho-primary\";\nconst CONVERSATION_ROW_INACTIVE = \"hover:bg-pho-ghost-hover\";\n\nconst CONVERSATION_PRESS = {\n initial: false as const,\n whileTap: { scale: PRESS_SCALE_ROW },\n transition: SPRING_PRESS,\n};\n\n/**\n * One conversation — a link when `href` is given (through the host's\n * `LinkProvider`), otherwise a button. Opening it in a compact layout\n * brings the thread up.\n */\nfunction Conversation({\n title,\n time,\n preview,\n avatar,\n group,\n active,\n className,\n href,\n onClick,\n ...rest\n}: ChatConversationProps) {\n const { layout, setPane } = useChat(\"Conversation\");\n const Link = useLinkComponent();\n // Same bridge as `Sidebar.Item` — host `LinkProvider` + Motion press.\n const MotionLink = useMemo(\n () =>\n motion.create(Link as unknown as ComponentType<Record<string, unknown>>),\n [Link],\n );\n const rowClass = cn(\n CONVERSATION_ROW,\n active ? CONVERSATION_ROW_ACTIVE : CONVERSATION_ROW_INACTIVE,\n className,\n );\n const open = () => {\n if (layout !== \"default\") setPane(\"thread\");\n };\n const body = (\n <>\n {avatar ?? (\n <Avatar.Root size=\"sm\">\n <Avatar.Fallback>\n {group ? (\n <IconUsers className=\"size-4\" aria-hidden />\n ) : (\n <IconUser className=\"size-4\" aria-hidden />\n )}\n </Avatar.Fallback>\n </Avatar.Root>\n )}\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-pho-primary min-w-0 truncate text-base font-medium\">\n {title}\n </span>\n {time != null && (\n <span className=\"text-pho-description shrink-0 text-xs font-normal whitespace-nowrap tabular-nums\">\n {time}\n </span>\n )}\n </span>\n {preview != null && (\n <span className=\"text-pho-description mt-0.5 block min-w-0 truncate text-xs font-normal\">\n {preview}\n </span>\n )}\n </span>\n </>\n );\n\n if (href !== undefined) {\n return (\n <li>\n <MotionLink\n href={href}\n aria-current={active ? \"page\" : undefined}\n {...(rest as AnchorHTMLAttributes<HTMLAnchorElement>)}\n onClick={(event: React.MouseEvent<HTMLAnchorElement>) => {\n (onClick as AnchorHTMLAttributes<HTMLAnchorElement>[\"onClick\"])?.(\n event,\n );\n if (!event.defaultPrevented) open();\n }}\n className={rowClass}\n {...CONVERSATION_PRESS}\n >\n {body}\n </MotionLink>\n </li>\n );\n }\n\n return (\n <li>\n <motion.button\n type=\"button\"\n aria-current={active ? \"true\" : undefined}\n {...(rest as Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n MotionHandlerConflicts\n >)}\n onClick={(event) => {\n (onClick as ButtonHTMLAttributes<HTMLButtonElement>[\"onClick\"])?.(\n event,\n );\n if (!event.defaultPrevented) open();\n }}\n className={rowClass}\n {...CONVERSATION_PRESS}\n >\n {body}\n </motion.button>\n </li>\n );\n}\n\n/* -------------------------------- thread -------------------------------- */\n\n/** The right pane — header, messages, and the docked footer, on the card. */\nfunction Thread({ className, children, ...props }: ComponentProps<\"section\">) {\n const { layout, pane, direction, swap, swapped } = useChat(\"Thread\");\n const reduceMotion = useReducedMotion();\n const threadClass = cn(\n \"bg-pho-primary flex min-h-0 flex-1 flex-col\",\n layout === \"default\" && \"min-w-80\",\n layout === \"compact\" && \"min-w-0\",\n layout === \"auto\" && \"min-w-0 @2xl:min-w-80\",\n !swap && layout === \"auto\" && pane === \"list\" && \"@max-2xl:hidden\",\n className,\n );\n if (!swap) {\n return (\n <section\n aria-label=\"Conversation\"\n data-chat-thread=\"\"\n className={threadClass}\n {...props}\n >\n {children}\n </section>\n );\n }\n return (\n <SwapPane\n as=\"section\"\n show={pane === \"thread\"}\n swapped={swapped}\n direction={direction}\n reduceMotion={reduceMotion}\n aria-label=\"Conversation\"\n data-chat-thread=\"\"\n className={threadClass}\n {...props}\n >\n {children}\n </SwapPane>\n );\n}\n\nexport interface ChatHeaderProps extends ComponentProps<\"header\"> {\n /** The other side's avatar — an `Avatar.Root`. */\n avatar?: ReactNode;\n /** Controls at the trailing edge — a details button, a menu. */\n actions?: ReactNode;\n /** The back button's accessible name. @default \"Back to conversations\" */\n backLabel?: string;\n}\n\n/**\n * Who the thread is with. Children are a `Title` and a `Description`.\n * In a compact layout a back button leads the row; `auto` shows it only\n * while the frame is narrow.\n */\nfunction Header({\n avatar,\n actions,\n backLabel = \"Back to conversations\",\n className,\n children,\n ...props\n}: ChatHeaderProps) {\n const { layout, setPane } = useChat(\"Header\");\n return (\n <header\n data-chat-header=\"\"\n className={cn(\n \"flex shrink-0 items-center gap-3 px-4 py-1.5\",\n TOP_BAR,\n className,\n )}\n {...props}\n >\n {layout !== \"default\" && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"circle\"\n svgOnly\n aria-label={backLabel}\n data-chat-back=\"\"\n className={cn(\"-ml-1 shrink-0\", layout === \"auto\" && \"@2xl:hidden\")}\n onClick={() => setPane(\"list\")}\n >\n <IconArrowLeft />\n </Button>\n )}\n {avatar}\n <div className=\"flex min-w-0 flex-1 flex-col\">{children}</div>\n {actions != null && (\n <div className=\"flex shrink-0 items-center gap-1\">{actions}</div>\n )}\n </header>\n );\n}\n\n/** The other side's name. Inline extras (a copy button, a badge) sit after it. */\nfunction Title({ className, children, ...props }: ComponentProps<\"h2\">) {\n return (\n <h2\n data-chat-title=\"\"\n className={cn(\n \"text-pho-primary m-0 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5 overflow-visible text-base font-medium\",\n className,\n )}\n {...props}\n >\n {children}\n </h2>\n );\n}\n\n/** One line under the title — from whom, a status. */\nfunction Description({ className, ...props }: ComponentProps<\"p\">) {\n return (\n <p\n data-chat-description=\"\"\n className={cn(\n \"text-pho-description m-0 min-w-0 truncate text-xs\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/* ------------------------------- messages ------------------------------- */\n\n/** Within this many px of the bottom the pane counts as pinned. */\nconst PIN_SLACK_PX = 40;\n\nexport interface ChatMessagesProps extends ComponentProps<\"div\"> {\n /** Earlier pages exist — a button at the top asks for them. */\n hasEarlier?: boolean;\n /** The earlier page is on its way. */\n loadingEarlier?: boolean;\n /** Ask for the page before the first message shown. */\n onLoadEarlier?: () => void;\n /** The button's label. @default \"Load earlier messages\" */\n earlierLabel?: ReactNode;\n}\n\n/**\n * The messages, oldest to newest, on the thread surface. The pane starts at\n * the bottom and stays there as messages arrive unless the reader has\n * scrolled up; an earlier page keeps what they were reading in place.\n * Children are `Message` rows and `Divider`s.\n */\nfunction Messages({\n hasEarlier = false,\n loadingEarlier = false,\n onLoadEarlier,\n earlierLabel = \"Load earlier messages\",\n className,\n children,\n ...props\n}: ChatMessagesProps) {\n const viewportRef = useRef<HTMLDivElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const pinned = useRef(true);\n const anchor = useRef<{ height: number; top: number } | null>(null);\n\n useIsoLayoutEffect(() => {\n const viewport = viewportRef.current;\n const content = contentRef.current;\n if (!viewport || !content) return;\n const settle = () => {\n const kept = anchor.current;\n if (kept) {\n anchor.current = null;\n viewport.scrollTop = viewport.scrollHeight - kept.height + kept.top;\n return;\n }\n if (pinned.current) viewport.scrollTop = viewport.scrollHeight;\n };\n settle();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(settle);\n observer.observe(content);\n observer.observe(viewport);\n return () => observer.disconnect();\n }, []);\n\n const onScroll = () => {\n const viewport = viewportRef.current;\n if (!viewport) return;\n pinned.current =\n viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight <\n PIN_SLACK_PX;\n };\n\n const loadEarlier = () => {\n const viewport = viewportRef.current;\n if (viewport) {\n anchor.current = {\n height: viewport.scrollHeight,\n top: viewport.scrollTop,\n };\n }\n pinned.current = false;\n onLoadEarlier?.();\n };\n\n return (\n <div\n data-chat-messages=\"\"\n className={cn(\n // Bubbles' focus and selected rings offset against the thread.\n \"flex min-h-0 flex-1 flex-col [--pho-bubble-backdrop:var(--background-color-pho-primary)]\",\n className,\n )}\n {...props}\n >\n <ScrollArea.Root className=\"min-h-0 flex-1\">\n <ScrollArea.Viewport ref={viewportRef} onScroll={onScroll}>\n <ScrollArea.Content\n ref={contentRef}\n style={{ minWidth: 0 }}\n className=\"flex min-h-full flex-col gap-1 p-4\"\n >\n {hasEarlier && (\n <div className=\"flex justify-center\">\n <Button\n variant=\"outlined\"\n size=\"sm\"\n loading={loadingEarlier}\n onClick={loadEarlier}\n >\n {earlierLabel}\n </Button>\n </div>\n )}\n {children}\n </ScrollArea.Content>\n </ScrollArea.Viewport>\n <ScrollArea.Scrollbar>\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n </ScrollArea.Root>\n </div>\n );\n}\n\n/** A centered caption in the thread — the day, \"Unread\". */\nfunction Divider({ className, children, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n data-chat-divider=\"\"\n className={cn(\"text-pho-description py-1 text-center text-xs\", className)}\n {...props}\n >\n {children}\n </div>\n );\n}\n\n/* -------------------------------- footer -------------------------------- */\n\n/** The docked bar under the messages — usually a `Composer`. */\nfunction Footer({ className, ...props }: ComponentProps<\"footer\">) {\n return (\n <footer\n data-chat-footer=\"\"\n className={cn(\"shrink-0 px-4 py-3\", className)}\n {...props}\n />\n );\n}\n\n/** The draft box grows with the text up to this, then scrolls. */\nconst COMPOSER_MAX_HEIGHT_PX = 200;\n\nexport interface ChatComposerProps extends Omit<\n ComponentProps<\"form\">,\n \"onSubmit\" | \"prefix\" | \"children\"\n> {\n /** The draft. */\n value: string;\n onValueChange: (value: string) => void;\n /** Enter, or the send button. Not called while `sending` or with nothing to send. */\n onSend: () => void;\n placeholder?: string;\n /** The send is in flight — the button spins, the box waits. */\n sending?: boolean;\n disabled?: boolean;\n /**\n * There is something to send besides text (an attachment). By default\n * the send button wakes when the draft has a non-blank character.\n */\n canSend?: boolean;\n /** Controls at the start of the bottom row — an add-attachment button. */\n prefix?: ReactNode;\n /** A quiet line between `prefix` and the send button — a count, a size. */\n meta?: ReactNode;\n /** The send button's accessible name. @default \"Send\" */\n sendLabel?: string;\n /** Above the text — attachment thumbnails. */\n children?: ReactNode;\n /** The `<textarea>`. */\n textareaRef?: Ref<HTMLTextAreaElement>;\n}\n\n/**\n * The message box: text that grows with the draft, Enter to send and\n * Shift+Enter for a new line, one round send button. Attachments are the\n * page's: put their thumbnails in `children`, the button that adds them\n * in `prefix`, and flip `canSend` when they alone should send.\n */\nfunction Composer({\n value,\n onValueChange,\n onSend,\n placeholder = \"Message\",\n sending = false,\n disabled = false,\n canSend,\n prefix,\n meta,\n sendLabel = \"Send\",\n children,\n textareaRef,\n className,\n ...props\n}: ChatComposerProps) {\n const innerRef = useRef<HTMLTextAreaElement | null>(null);\n const ready = !sending && !disabled && (canSend ?? value.trim().length > 0);\n\n useIsoLayoutEffect(() => {\n const element = innerRef.current;\n if (!element) return;\n element.style.height = \"0px\";\n element.style.height = `${Math.min(element.scrollHeight, COMPOSER_MAX_HEIGHT_PX)}px`;\n }, [value]);\n\n const submit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (ready) onSend();\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (\n event.key === \"Enter\" &&\n !event.shiftKey &&\n !event.nativeEvent.isComposing\n ) {\n event.preventDefault();\n if (ready) onSend();\n }\n };\n\n return (\n <form\n aria-label=\"Message composer\"\n data-chat-composer=\"\"\n onSubmit={submit}\n className={cn(\n // The field surface, as `Input`: hairline at rest, brand ring while\n // anything inside has focus.\n \"rounded-base bg-pho-primary ring-pho-primary focus-within:ring-pho-brand ring-1 transition-shadow duration-100 ease-linear ring-inset focus-within:ring-2\",\n disabled && \"opacity-50\",\n className,\n )}\n {...props}\n >\n {children}\n <textarea\n ref={(node) => {\n innerRef.current = node;\n if (typeof textareaRef === \"function\") textareaRef(node);\n else if (textareaRef) {\n (textareaRef as { current: HTMLTextAreaElement | null }).current =\n node;\n }\n }}\n value={value}\n onChange={(event) => onValueChange(event.target.value)}\n onKeyDown={onKeyDown}\n rows={1}\n placeholder={placeholder}\n aria-label=\"Message\"\n disabled={disabled}\n // In flight the box holds its text but stays focusable — `disabled`\n // would drop focus mid-send; `ready` already blocks a second send.\n readOnly={sending}\n className=\"text-pho-primary placeholder:text-pho-placeholder m-0 block w-full resize-none bg-transparent px-4 pt-3 pb-1 text-base outline-none disabled:cursor-not-allowed\"\n />\n <div className=\"flex items-center gap-2 px-2 pb-2\">\n {prefix}\n <p className=\"text-pho-description m-0 min-w-0 flex-1 truncate text-xs\">\n {meta}\n </p>\n <Button\n type=\"submit\"\n size=\"sm\"\n shape=\"circle\"\n svgOnly\n aria-label={sendLabel}\n disabled={!ready}\n loading={sending}\n >\n <IconArrowUp />\n </Button>\n </div>\n </form>\n );\n}\n\n/* --------------------------------- states ------------------------------- */\n\nexport interface ChatEmptyProps extends StatusViewProps {}\n\n/**\n * The standing-in view for either pane — no conversations, no thread\n * chosen, nothing said yet. `StatusView` at card size, centered in\n * whatever room the pane has.\n */\nfunction Empty({ className, size = \"sm\", ...props }: ChatEmptyProps) {\n return (\n <div\n data-chat-empty=\"\"\n className={cn(\n \"flex flex-1 flex-col items-center justify-center px-6 py-8\",\n className,\n )}\n >\n <StatusView size={size} {...props} />\n </div>\n );\n}\n\n/** Bones in the shape of conversation rows — avatar, who, when, preview. */\nfunction ConversationsLoading({ rows = 5 }: { rows?: number }) {\n return (\n <div\n aria-hidden\n data-chat-conversations-loading=\"\"\n className=\"flex flex-col gap-0.5\"\n >\n {Array.from({ length: rows }, (_, row) => (\n <div key={row} className=\"flex items-center gap-3 px-2 py-2.5\">\n <Skeleton className=\"size-8 shrink-0 rounded-full\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <Skeleton className=\"h-3.5 w-32\" />\n <Skeleton className=\"h-2.5 w-8\" />\n </div>\n <Skeleton className=\"mt-2 h-2.5 w-44\" />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\n/** Bones in a thread's shape — theirs left, ours right. */\nfunction MessagesLoading() {\n return (\n <div\n aria-hidden\n data-chat-messages-loading=\"\"\n className=\"flex flex-col gap-3\"\n >\n <Skeleton className=\"rounded-base h-10 w-1/2 self-start\" />\n <Skeleton className=\"rounded-base h-10 w-2/5 self-end\" />\n <Skeleton className=\"rounded-base h-16 w-3/5 self-start\" />\n </div>\n );\n}\n\n/**\n * The composed inbox. Assemble the two panes and fill them:\n *\n * ```tsx\n * <Chat.Root layout=\"auto\" className=\"h-[32rem]\">\n * <Chat.List>\n * <Chat.Search value={query} onChange={…} />\n * <Chat.Conversations>\n * <Chat.ConversationList>\n * <Chat.Conversation title=\"+1 (315) 997-8332\" time=\"2d ago\" preview=\"…\" active />\n * </Chat.ConversationList>\n * </Chat.Conversations>\n * </Chat.List>\n * <Chat.Thread>\n * <Chat.Header avatar={<Avatar.Root size=\"md\">…</Avatar.Root>}>\n * <Chat.Title>+1 (315) 997-8332</Chat.Title>\n * <Chat.Description>From …</Chat.Description>\n * </Chat.Header>\n * <Chat.Messages>\n * <Chat.Divider>September 12</Chat.Divider>\n * <Message.Root>…</Message.Root>\n * </Chat.Messages>\n * <Chat.Footer>\n * <Chat.Composer value={draft} onValueChange={setDraft} onSend={send} />\n * </Chat.Footer>\n * </Chat.Thread>\n * </Chat.Root>\n * ```\n */\nexport const Chat = {\n Root,\n List,\n Search,\n Conversations,\n ConversationList,\n Conversation,\n Thread,\n Header,\n Title,\n Description,\n Messages,\n Divider,\n Footer,\n Composer,\n Empty,\n ConversationsLoading,\n MessagesLoading,\n};\n"],"x_google_ignoreList":[0,1,2,3],"mappings":"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"}
1
+ {"version":3,"file":"chat-CU3XVm99.js","names":["__iconNode","__iconNode","__iconNode"],"sources":["../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowLeft.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconArrowUp.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconUser.mjs","../../../../node_modules/.pnpm/@tabler+icons-react@3.46.0_react@19.2.8/node_modules/@tabler/icons-react/dist/esm/icons/IconUsers.mjs","../../src/components/chat/chat.tsx"],"sourcesContent":["/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M5 12l14 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M5 12l6 6\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M5 12l6 -6\", \"key\": \"svg-2\" }]];\nconst IconArrowLeft = createReactComponent(\"outline\", \"arrow-left\", \"ArrowLeft\", __iconNode);\n\nexport { __iconNode, IconArrowLeft as default };\n//# sourceMappingURL=IconArrowLeft.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M12 5l0 14\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M18 11l-6 -6\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M6 11l6 -6\", \"key\": \"svg-2\" }]];\nconst IconArrowUp = createReactComponent(\"outline\", \"arrow-up\", \"ArrowUp\", __iconNode);\n\nexport { __iconNode, IconArrowUp as default };\n//# sourceMappingURL=IconArrowUp.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2\", \"key\": \"svg-1\" }]];\nconst IconUser = createReactComponent(\"outline\", \"user\", \"User\", __iconNode);\n\nexport { __iconNode, IconUser as default };\n//# sourceMappingURL=IconUser.mjs.map\n","/**\n * @license @tabler/icons-react v3.46.0 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M5 7a4 4 0 1 0 8 0a4 4 0 1 0 -8 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M3 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M16 3.13a4 4 0 0 1 0 7.75\", \"key\": \"svg-2\" }], [\"path\", { \"d\": \"M21 21v-2a4 4 0 0 0 -3 -3.85\", \"key\": \"svg-3\" }]];\nconst IconUsers = createReactComponent(\"outline\", \"users\", \"Users\", __iconNode);\n\nexport { __iconNode, IconUsers as default };\n//# sourceMappingURL=IconUsers.mjs.map\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type AnchorHTMLAttributes,\n type ButtonHTMLAttributes,\n type CSSProperties,\n type ComponentProps,\n type ComponentType,\n type FormEvent,\n type KeyboardEvent,\n type PointerEvent,\n type ReactNode,\n type Ref,\n type RefObject,\n} from \"react\";\nimport {\n IconArrowLeft,\n IconArrowUp,\n IconSearch,\n IconUser,\n IconUsers,\n} from \"@tabler/icons-react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"motion/react\";\nimport {\n BLUR_PX,\n FADE_SWAP,\n PRESS_SCALE_ROW,\n SPRING_PRESS,\n TRAVEL_LINEAR,\n} from \"../../motion\";\nimport { Avatar } from \"../avatar\";\nimport { Button } from \"../button\";\nimport { Input, type InputProps } from \"../input\";\nimport { ScrollArea } from \"../scroll-area\";\nimport { Skeleton } from \"../skeleton\";\nimport { StatusView, type StatusViewProps } from \"../status-view\";\nimport { cn } from \"../../utils/cn\";\nimport { useLinkComponent } from \"../../utils/link-provider\";\n\n/**\n * Chat — an inbox in one card: the conversations down the left, the open\n * thread on the right with its messages scrolling up from the composer.\n * It composes the smaller parts (`Message` rows of `Bubble`s in a\n * `ScrollArea`, an `Input` for search, `Button`s to send and go back) the\n * way `Sidebar` composes a rail: rows that press, one active, links\n * through the host's `LinkProvider`.\n *\n * Two layouts. `default` seats both panes side by side — the divider\n * between them drags so either pane can grow, each down to a min width.\n * `compact` shows one at a time — the list, then the thread with a way\n * back — for a narrow column or a phone. Opening a conversation pushes\n * the thread in from the right; back pops the list in from the left, a\n * short drift on `TRAVEL_LINEAR` with a `FADE_SWAP` fade. `auto` is\n * compact only while the frame is narrower than 42rem (a container\n * query, so it follows the card, not the viewport). Which pane is up is\n * `pane`, controlled or not; opening a conversation moves to the thread,\n * the header's back button returns.\n *\n * Presentational, like every Pho part: the page fetches, formats times,\n * and decides who is who. The thread stays pinned to its newest message\n * while the reader is at the bottom, and keeps its place when earlier\n * pages arrive above.\n */\n\nexport type ChatLayout = \"default\" | \"compact\" | \"auto\";\nexport type ChatPane = \"list\" | \"thread\";\n/** Push is 1 (thread from the right); pop is −1 (list from the left). */\nexport type ChatPaneDirection = 1 | -1;\n\n/** Same chrome as `BasicPage.Card` and `LogList` — one card surface. */\nconst CHAT_SURFACE = \"rounded-base border border-pho-secondary bg-pho-primary\";\n\n// Below this frame width `auto` is compact: the `@2xl` container variant\n// (42rem) in the class strings below. Those variants are spelled out in\n// full on purpose — Tailwind finds utilities by scanning source text, so\n// a variant built from a variable (`${AUTO_WIDE}` before the colon) never\n// reached a consumer's CSS and `auto` stayed single-pane at every width.\n// chat.test.tsx keeps it that way.\n/** `42rem` in px at the 16px root — `frameWidth` is measured in px. */\nconst AUTO_WIDE_PX = 672;\n/**\n * Compact pane travel — a short drift, the same scale as `BAR_RISE_PX`,\n * not a full-width slide.\n */\nconst PANE_TRAVEL_PX = 24;\n/** Outgoing pane drift — same distance as BasicPage `BACK_LABEL_LEAVE_X`. */\nconst PANE_LEAVE_PX = 8;\n\n/** Search (`p-3` + sm Input) is the pane top-bar height; Header matches it. */\nconst TOP_BAR = \"min-h-[61px]\";\n\n/**\n * Wide layouts start the list at 273 — the measured inbox column, not\n * `w-80`. It will not go below `min-w-64` (256); the thread will not go\n * below `min-w-80` (320).\n */\nconst LIST_WIDTH_PX = 273;\nconst LIST_MIN_PX = 256;\nconst THREAD_MIN_PX = 320;\nconst SPLIT_STEP_PX = 16;\n\nfunction clampListWidth(width: number, rootWidth: number) {\n const next = Math.max(LIST_MIN_PX, width);\n if (rootWidth <= 0) return Number.isFinite(next) ? next : LIST_MIN_PX;\n return Math.min(next, Math.max(LIST_MIN_PX, rootWidth - THREAD_MIN_PX));\n}\n\ninterface ChatContextValue {\n layout: ChatLayout;\n pane: ChatPane;\n setPane: (pane: ChatPane) => void;\n /** Latest list ↔ thread step: 1 push, −1 pop. */\n direction: ChatPaneDirection;\n /** One pane at a time — compact, or `auto` once the frame measures narrow. */\n swap: boolean;\n /** True after the first list ↔ thread step — later remounts still push. */\n swapped: boolean;\n listWidth: number;\n frameWidth: number;\n resizeList: (width: number) => void;\n rootRef: RefObject<HTMLDivElement | null>;\n}\n\nconst ChatContext = createContext<ChatContextValue | null>(null);\n\nfunction useChat(part: string): ChatContextValue {\n const ctx = useContext(ChatContext);\n if (ctx == null) {\n throw new Error(`Chat.${part} must be used inside Chat.Root`);\n }\n return ctx;\n}\n\n// React 18 warns that useLayoutEffect does nothing on the server; fall\n// back to useEffect there so SSR'd docs stay quiet.\nconst useIsoLayoutEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nfunction paneDirectionFor(pane: ChatPane): ChatPaneDirection {\n return pane === \"thread\" ? 1 : -1;\n}\n\n/**\n * Compact (and `auto` once the frame measures narrower than 42rem) mounts\n * one pane at a time so `AnimatePresence` can push/pop. `frameWidth` 0 is\n * the unmeasured / SSR frame — treat it as wide so both panes render and\n * nothing flashes.\n */\nfunction isPaneSwap(layout: ChatLayout, frameWidth: number) {\n return (\n layout === \"compact\" ||\n (layout === \"auto\" && frameWidth > 0 && frameWidth < AUTO_WIDE_PX)\n );\n}\n\n/**\n * The compact pane swap — incoming travels `PANE_TRAVEL_PX` on\n * `TRAVEL_LINEAR`, fades and breathes `BLUR_PX` on `FADE_SWAP`; outgoing\n * drifts `PANE_LEAVE_PX` the other way. Under reduced motion: opacity\n * only, and instant.\n */\nexport function paneSwapMotion(\n direction: ChatPaneDirection,\n reduceMotion?: boolean | null,\n) {\n if (reduceMotion) {\n return {\n initial: { opacity: 0 },\n animate: { opacity: 1 },\n exit: { opacity: 0 },\n transition: { duration: 0 },\n };\n }\n return {\n initial: {\n x: direction * PANE_TRAVEL_PX,\n opacity: 0,\n filter: `blur(${BLUR_PX}px)`,\n },\n animate: { x: 0, opacity: 1, filter: \"blur(0px)\" },\n exit: {\n x: -direction * PANE_LEAVE_PX,\n opacity: 0,\n filter: `blur(${BLUR_PX}px)`,\n },\n transition: { x: TRAVEL_LINEAR, opacity: FADE_SWAP, filter: FADE_SWAP },\n };\n}\n\nfunction paneSwapVariants(reduceMotion: boolean | null) {\n return {\n enter: (direction: ChatPaneDirection) =>\n paneSwapMotion(direction, reduceMotion).initial,\n rest: (direction: ChatPaneDirection) =>\n paneSwapMotion(direction, reduceMotion).animate,\n leave: (direction: ChatPaneDirection) =>\n paneSwapMotion(direction, reduceMotion).exit,\n };\n}\n\n/**\n * DOM handlers whose React signatures clash with Motion's gesture props.\n * Same omit list as `Button` — swap panes and conversation rows render\n * through `motion.*`.\n */\ntype MotionHandlerConflicts =\n | \"onAnimationStart\"\n | \"onAnimationEnd\"\n | \"onAnimationIteration\"\n | \"onDrag\"\n | \"onDragStart\"\n | \"onDragEnd\"\n | \"onDragEnter\"\n | \"onDragExit\"\n | \"onDragLeave\"\n | \"onDragOver\"\n | \"onDrop\";\n\ntype SwapPaneProps = {\n show: boolean;\n swapped: boolean;\n direction: ChatPaneDirection;\n reduceMotion: boolean | null;\n children?: ReactNode;\n} & (\n | ({ as: \"aside\" } & Omit<\n ComponentProps<\"aside\">,\n \"children\" | MotionHandlerConflicts\n >)\n | ({ as: \"section\" } & Omit<\n ComponentProps<\"section\">,\n \"children\" | MotionHandlerConflicts\n >)\n);\n\ntype SwapMotionProps = {\n custom: ChatPaneDirection;\n variants: ReturnType<typeof paneSwapVariants>;\n initial: \"enter\";\n animate: \"rest\";\n exit: \"leave\";\n transition: ReturnType<typeof paneSwapMotion>[\"transition\"];\n};\n\n/**\n * The compact face — Root's `AnimatePresence` keys list vs thread. `custom`\n * on that presence feeds this step's push/pop into the exiting face.\n */\nfunction SwapPane({\n as,\n show,\n swapped,\n direction,\n reduceMotion,\n children,\n ...props\n}: SwapPaneProps) {\n const swap = paneSwapMotion(direction, reduceMotion);\n const motionProps: SwapMotionProps = {\n custom: direction,\n variants: paneSwapVariants(reduceMotion),\n initial: \"enter\",\n animate: \"rest\",\n exit: \"leave\",\n transition: swap.transition,\n };\n // Skip the first paint only before any pane change — a Thread that\n // remounts (host `key`) on the way in still pushes.\n return (\n <AnimatePresence\n initial={!swapped && show ? false : undefined}\n mode=\"popLayout\"\n custom={direction}\n >\n {show ? (\n as === \"aside\" ? (\n <motion.aside key=\"list\" {...props} {...motionProps}>\n {children}\n </motion.aside>\n ) : (\n <motion.section key=\"thread\" {...props} {...motionProps}>\n {children}\n </motion.section>\n )\n ) : null}\n </AnimatePresence>\n );\n}\n\n/* --------------------------------- root --------------------------------- */\n\nexport interface ChatRootProps extends ComponentProps<\"div\"> {\n /**\n * `default` shows both panes; `compact` one at a time; `auto` is\n * compact while the frame is narrower than 42rem.\n * @default \"default\"\n */\n layout?: ChatLayout;\n /** The pane that is up in a compact layout. Pair with `onPaneChange`. */\n pane?: ChatPane;\n /** Initial pane when uncontrolled. @default \"list\" */\n defaultPane?: ChatPane;\n /** Called with the next pane — a row opened a thread, back was pressed. */\n onPaneChange?: (pane: ChatPane) => void;\n ref?: Ref<HTMLDivElement>;\n}\n\n/**\n * The card. Give it a height (`h-[32rem]`, or `min-h-0 flex-1` in a\n * column that fills the page); the panes scroll inside it.\n */\nfunction Root({\n layout = \"default\",\n pane: paneProp,\n defaultPane = \"list\",\n onPaneChange,\n className,\n style,\n ref,\n ...props\n}: ChatRootProps) {\n const [uncontrolledPane, setUncontrolledPane] = useState(defaultPane);\n const [listWidth, setListWidth] = useState(LIST_WIDTH_PX);\n const [frameWidth, setFrameWidth] = useState(0);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const controlled = paneProp !== undefined;\n const pane = controlled ? paneProp : uncontrolledPane;\n const [direction, setDirection] = useState<ChatPaneDirection>(() =>\n paneDirectionFor(pane),\n );\n const [swapped, setSwapped] = useState(false);\n const prevPaneRef = useRef(pane);\n // Keep this render's direction aligned with `pane` so a controlled\n // update and a `setPane` call both push/pop on the same frame.\n let renderedDirection = direction;\n let renderedSwapped = swapped;\n if (prevPaneRef.current !== pane) {\n renderedDirection = paneDirectionFor(pane);\n renderedSwapped = true;\n prevPaneRef.current = pane;\n if (renderedDirection !== direction) setDirection(renderedDirection);\n if (!swapped) setSwapped(true);\n }\n const setPane = useCallback(\n (next: ChatPane) => {\n setDirection(paneDirectionFor(next));\n if (!controlled) setUncontrolledPane(next);\n onPaneChange?.(next);\n },\n [controlled, onPaneChange],\n );\n const resizeList = useCallback((width: number) => {\n setListWidth(clampListWidth(width, rootRef.current?.clientWidth ?? 0));\n }, []);\n const swap = isPaneSwap(layout, frameWidth);\n useIsoLayoutEffect(() => {\n const root = rootRef.current;\n if (!root || typeof ResizeObserver === \"undefined\") return;\n const tighten = () => {\n const frame = root.clientWidth;\n setFrameWidth(frame);\n setListWidth((current) => clampListWidth(current, frame));\n };\n tighten();\n const observer = new ResizeObserver(tighten);\n observer.observe(root);\n return () => observer.disconnect();\n }, []);\n const value = useMemo(\n () => ({\n layout,\n pane,\n setPane,\n direction: renderedDirection,\n swap,\n swapped: renderedSwapped,\n listWidth,\n frameWidth,\n resizeList,\n rootRef,\n }),\n [\n layout,\n pane,\n setPane,\n renderedDirection,\n swap,\n renderedSwapped,\n listWidth,\n frameWidth,\n resizeList,\n ],\n );\n return (\n <ChatContext.Provider value={value}>\n <div\n ref={(node) => {\n rootRef.current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref) {\n (ref as { current: HTMLDivElement | null }).current = node;\n }\n }}\n data-chat=\"\"\n data-basic-page-card=\"\"\n data-layout={layout}\n data-pane={pane}\n style={\n {\n ...style,\n \"--chat-list-width\": `${listWidth}px`,\n } as CSSProperties\n }\n className={cn(\n CHAT_SURFACE,\n \"@container relative flex min-h-0 min-w-0 overflow-hidden\",\n className,\n )}\n {...props}\n />\n </ChatContext.Provider>\n );\n}\n\n/* --------------------------------- list --------------------------------- */\n\n/** The left pane — search above, conversations below, on the page wash. */\nfunction List({\n className,\n children,\n id: idProp,\n ...props\n}: ComponentProps<\"aside\">) {\n const { layout, pane, direction, swap, swapped } = useChat(\"List\");\n const reduceMotion = useReducedMotion();\n const uid = useId();\n const listId = idProp ?? uid;\n const listClass = cn(\n \"border-pho-secondary bg-pho-page relative z-10 flex min-h-0 shrink-0 flex-col\",\n layout === \"default\" && \"min-w-64 w-[var(--chat-list-width)] border-r\",\n layout === \"compact\" && \"w-full\",\n layout === \"auto\" &&\n cn(\n \"w-full @2xl:min-w-64 @2xl:w-[var(--chat-list-width)] @2xl:border-r\",\n !swap && pane === \"thread\" && \"@max-2xl:hidden\",\n ),\n className,\n );\n const body = (\n <>\n {children}\n {layout !== \"compact\" && <Splitter controlsId={listId} />}\n </>\n );\n const rest = {\n id: listId,\n \"aria-label\": \"Conversations\",\n \"data-chat-list\": \"\",\n className: listClass,\n ...props,\n };\n if (!swap) {\n return <aside {...rest}>{body}</aside>;\n }\n return (\n <SwapPane\n as=\"aside\"\n show={pane === \"list\"}\n swapped={swapped}\n direction={direction}\n reduceMotion={reduceMotion}\n {...rest}\n >\n {body}\n </SwapPane>\n );\n}\n\n/**\n * The drag between the panes — a focusable separator. Hidden in\n * `compact`, and in `auto` while the frame is narrow.\n */\nfunction Splitter({ controlsId }: { controlsId: string }) {\n const { layout, listWidth, frameWidth, resizeList, rootRef } =\n useChat(\"Splitter\");\n const drag = useRef<{ x: number; width: number } | null>(null);\n\n const onPointerDown = (event: PointerEvent<HTMLDivElement>) => {\n if (event.button !== 0) return;\n event.currentTarget.setPointerCapture?.(event.pointerId);\n drag.current = { x: event.clientX, width: listWidth };\n };\n\n const onPointerMove = (event: PointerEvent<HTMLDivElement>) => {\n const start = drag.current;\n if (start == null) return;\n const root = rootRef.current;\n const rtl = root != null && getComputedStyle(root).direction === \"rtl\";\n const delta = (event.clientX - start.x) * (rtl ? -1 : 1);\n resizeList(start.width + delta);\n };\n\n const onPointerUp = () => {\n drag.current = null;\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const root = rootRef.current;\n const rtl = root != null && getComputedStyle(root).direction === \"rtl\";\n const shrink = rtl ? \"ArrowRight\" : \"ArrowLeft\";\n const grow = rtl ? \"ArrowLeft\" : \"ArrowRight\";\n const step = event.shiftKey ? SPLIT_STEP_PX * 2 : SPLIT_STEP_PX;\n if (event.key === shrink) {\n event.preventDefault();\n resizeList(listWidth - step);\n } else if (event.key === grow) {\n event.preventDefault();\n resizeList(listWidth + step);\n } else if (event.key === \"Home\") {\n event.preventDefault();\n resizeList(LIST_MIN_PX);\n } else if (event.key === \"End\") {\n event.preventDefault();\n const frame = root?.clientWidth ?? 0;\n if (frame > 0) resizeList(frame - THREAD_MIN_PX);\n }\n };\n\n const valueMax =\n frameWidth > 0\n ? Math.max(LIST_MIN_PX, frameWidth - THREAD_MIN_PX)\n : listWidth;\n\n return (\n <div\n // WAI-ARIA window splitter: a focusable separator with a value. An\n // `hr` can neither take focus nor carry the value attributes.\n // oxlint-disable-next-line jsx-a11y/prefer-tag-over-role\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label=\"Resize conversation list\"\n aria-controls={controlsId}\n aria-valuenow={listWidth}\n aria-valuemin={LIST_MIN_PX}\n aria-valuemax={valueMax}\n aria-valuetext={`${listWidth} pixels`}\n tabIndex={0}\n data-chat-splitter=\"\"\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerUp}\n onKeyDown={onKeyDown}\n className={cn(\n \"absolute inset-y-0 -right-3 z-10 w-6 cursor-col-resize touch-none select-none\",\n \"outline-pho-brand focus-visible:outline-2 focus-visible:-outline-offset-2\",\n \"after:absolute after:inset-y-0 after:left-1/2 after:w-px after:-translate-x-1/2 after:bg-transparent\",\n \"[@media(hover:hover)]:hover:after:bg-pho-brand focus-visible:after:bg-pho-brand\",\n layout === \"auto\" && \"@max-2xl:hidden\",\n )}\n />\n );\n}\n\nexport interface ChatSearchProps extends Omit<\n InputProps,\n \"size\" | \"icon\" | \"label\" | \"hint\" | \"labelTrailing\"\n> {}\n\n/** The search row pinned over the conversations — an `sm` `Input`. */\nfunction Search({\n className,\n placeholder = \"Search\",\n ...props\n}: ChatSearchProps) {\n return (\n <div data-chat-search=\"\" className={cn(\"p-3\", TOP_BAR, className)}>\n <Input\n size=\"sm\"\n icon={IconSearch}\n placeholder={placeholder}\n aria-label=\"Search conversations\"\n autoComplete=\"off\"\n spellCheck={false}\n {...props}\n />\n </div>\n );\n}\n\n/**\n * The scrolling part of the list. Put a `ConversationList` in it — or a\n * `ConversationsLoading`, an `Empty` — and anything that belongs after\n * the rows (a load-older button).\n */\nfunction Conversations({\n className,\n children,\n ...props\n}: ComponentProps<\"div\">) {\n return (\n <div\n data-chat-conversations=\"\"\n className={cn(\"flex min-h-0 flex-1 flex-col\", className)}\n {...props}\n >\n <ScrollArea.Root className=\"min-h-0 flex-1\">\n <ScrollArea.Viewport>\n <ScrollArea.Content\n // Base UI sets `minWidth: fit-content` on Content; a long\n // title must truncate, not widen the pane.\n style={{ minWidth: 0 }}\n // Same horizontal rail as Sidebar sm (`px-3`): the selected\n // chip sits in the page wash instead of kissing the aside.\n className=\"flex min-h-full flex-col px-3 py-1\"\n >\n {children}\n </ScrollArea.Content>\n </ScrollArea.Viewport>\n <ScrollArea.Scrollbar>\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n </ScrollArea.Root>\n </div>\n );\n}\n\n/** The rows. */\nfunction ConversationList({ className, ...props }: ComponentProps<\"ul\">) {\n return (\n <ul\n data-chat-conversation-list=\"\"\n // list-none/m-0/p-0 shield the rows from host prose styles.\n className={cn(\"m-0 flex list-none flex-col gap-0.5 *:m-0\", className)}\n {...props}\n />\n );\n}\n\n/* ------------------------------ conversation ---------------------------- */\n\n/**\n * DOM handlers whose React signatures clash with Motion's gesture props.\n * Same omit list as `Button` — rows render through `motion.*`.\n */\ninterface ConversationBaseProps {\n /** Who — a number, a name, the members of a group. */\n title: ReactNode;\n /** When — the page's relative time (`2d ago`), trailing. */\n time?: ReactNode;\n /** The latest message, one truncated line. */\n preview?: ReactNode;\n /** Replace the default avatar (a person, or people for a `group`). */\n avatar?: ReactNode;\n /** A group conversation — the default avatar shows people. */\n group?: boolean;\n /** The open conversation. */\n active?: boolean;\n className?: string;\n}\n\nexport interface ChatConversationLinkProps\n extends\n ConversationBaseProps,\n Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n keyof ConversationBaseProps | MotionHandlerConflicts\n > {\n /** Destination — rendered through the host's `LinkProvider`. */\n href: string;\n}\n\nexport interface ChatConversationButtonProps\n extends\n ConversationBaseProps,\n Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n keyof ConversationBaseProps | MotionHandlerConflicts\n > {\n href?: undefined;\n}\n\nexport type ChatConversationProps =\n ChatConversationLinkProps | ChatConversationButtonProps;\n\n/** The row at rest, on hover, and while open — one pointer target. */\nconst CONVERSATION_ROW =\n \"outline-pho-brand rounded-base flex w-full cursor-pointer items-center gap-3 px-2 py-2.5 text-left transition-colors focus-visible:outline-2 focus-visible:-outline-offset-1\";\n/**\n * Open row — same chip as `Sidebar.Item` current (`aria-current=page`).\n * Weight lives on the title span, not here: time and preview stay Regular.\n */\nconst CONVERSATION_ROW_ACTIVE =\n \"bg-pho-primary text-pho-primary ring-pho-secondary ring-1 ring-inset *:data-icon:text-pho-primary\";\nconst CONVERSATION_ROW_INACTIVE = \"hover:bg-pho-ghost-hover\";\n\nconst CONVERSATION_PRESS = {\n initial: false as const,\n whileTap: { scale: PRESS_SCALE_ROW },\n transition: SPRING_PRESS,\n};\n\n/**\n * One conversation — a link when `href` is given (through the host's\n * `LinkProvider`), otherwise a button. Opening it in a compact layout\n * brings the thread up.\n */\nfunction Conversation({\n title,\n time,\n preview,\n avatar,\n group,\n active,\n className,\n href,\n onClick,\n ...rest\n}: ChatConversationProps) {\n const { layout, setPane } = useChat(\"Conversation\");\n const Link = useLinkComponent();\n // Same bridge as `Sidebar.Item` — host `LinkProvider` + Motion press.\n const MotionLink = useMemo(\n () =>\n motion.create(Link as unknown as ComponentType<Record<string, unknown>>),\n [Link],\n );\n const rowClass = cn(\n CONVERSATION_ROW,\n active ? CONVERSATION_ROW_ACTIVE : CONVERSATION_ROW_INACTIVE,\n className,\n );\n const open = () => {\n if (layout !== \"default\") setPane(\"thread\");\n };\n const body = (\n <>\n {avatar ?? (\n <Avatar.Root size=\"sm\">\n <Avatar.Fallback>\n {group ? (\n <IconUsers className=\"size-4\" aria-hidden />\n ) : (\n <IconUser className=\"size-4\" aria-hidden />\n )}\n </Avatar.Fallback>\n </Avatar.Root>\n )}\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-pho-primary min-w-0 truncate text-base font-medium\">\n {title}\n </span>\n {time != null && (\n <span className=\"text-pho-description shrink-0 text-xs font-normal whitespace-nowrap tabular-nums\">\n {time}\n </span>\n )}\n </span>\n {preview != null && (\n <span className=\"text-pho-description mt-0.5 block min-w-0 truncate text-xs font-normal\">\n {preview}\n </span>\n )}\n </span>\n </>\n );\n\n if (href !== undefined) {\n return (\n <li>\n <MotionLink\n href={href}\n aria-current={active ? \"page\" : undefined}\n {...(rest as AnchorHTMLAttributes<HTMLAnchorElement>)}\n onClick={(event: React.MouseEvent<HTMLAnchorElement>) => {\n (onClick as AnchorHTMLAttributes<HTMLAnchorElement>[\"onClick\"])?.(\n event,\n );\n if (!event.defaultPrevented) open();\n }}\n className={rowClass}\n {...CONVERSATION_PRESS}\n >\n {body}\n </MotionLink>\n </li>\n );\n }\n\n return (\n <li>\n <motion.button\n type=\"button\"\n aria-current={active ? \"true\" : undefined}\n {...(rest as Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n MotionHandlerConflicts\n >)}\n onClick={(event) => {\n (onClick as ButtonHTMLAttributes<HTMLButtonElement>[\"onClick\"])?.(\n event,\n );\n if (!event.defaultPrevented) open();\n }}\n className={rowClass}\n {...CONVERSATION_PRESS}\n >\n {body}\n </motion.button>\n </li>\n );\n}\n\n/* -------------------------------- thread -------------------------------- */\n\n/** The right pane — header, messages, and the docked footer, on the card. */\nfunction Thread({ className, children, ...props }: ComponentProps<\"section\">) {\n const { layout, pane, direction, swap, swapped } = useChat(\"Thread\");\n const reduceMotion = useReducedMotion();\n const threadClass = cn(\n \"bg-pho-primary flex min-h-0 flex-1 flex-col\",\n layout === \"default\" && \"min-w-80\",\n layout === \"compact\" && \"min-w-0\",\n layout === \"auto\" && \"min-w-0 @2xl:min-w-80\",\n !swap && layout === \"auto\" && pane === \"list\" && \"@max-2xl:hidden\",\n className,\n );\n if (!swap) {\n return (\n <section\n aria-label=\"Conversation\"\n data-chat-thread=\"\"\n className={threadClass}\n {...props}\n >\n {children}\n </section>\n );\n }\n return (\n <SwapPane\n as=\"section\"\n show={pane === \"thread\"}\n swapped={swapped}\n direction={direction}\n reduceMotion={reduceMotion}\n aria-label=\"Conversation\"\n data-chat-thread=\"\"\n className={threadClass}\n {...props}\n >\n {children}\n </SwapPane>\n );\n}\n\nexport interface ChatHeaderProps extends ComponentProps<\"header\"> {\n /** The other side's avatar — an `Avatar.Root`. */\n avatar?: ReactNode;\n /** Controls at the trailing edge — a details button, a menu. */\n actions?: ReactNode;\n /** The back button's accessible name. @default \"Back to conversations\" */\n backLabel?: string;\n}\n\n/**\n * Who the thread is with. Children are a `Title` and a `Description`.\n * In a compact layout a back button leads the row; `auto` shows it only\n * while the frame is narrow.\n */\nfunction Header({\n avatar,\n actions,\n backLabel = \"Back to conversations\",\n className,\n children,\n ...props\n}: ChatHeaderProps) {\n const { layout, setPane } = useChat(\"Header\");\n return (\n <header\n data-chat-header=\"\"\n className={cn(\n \"flex shrink-0 items-center gap-3 px-4 py-1.5\",\n TOP_BAR,\n className,\n )}\n {...props}\n >\n {layout !== \"default\" && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"circle\"\n svgOnly\n aria-label={backLabel}\n data-chat-back=\"\"\n className={cn(\"-ml-1 shrink-0\", layout === \"auto\" && \"@2xl:hidden\")}\n onClick={() => setPane(\"list\")}\n >\n <IconArrowLeft />\n </Button>\n )}\n {avatar}\n <div className=\"flex min-w-0 flex-1 flex-col\">{children}</div>\n {actions != null && (\n <div className=\"flex shrink-0 items-center gap-1\">{actions}</div>\n )}\n </header>\n );\n}\n\n/** The other side's name. Inline extras (a copy button, a badge) sit after it. */\nfunction Title({ className, children, ...props }: ComponentProps<\"h2\">) {\n return (\n <h2\n data-chat-title=\"\"\n className={cn(\n \"text-pho-primary m-0 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5 overflow-visible text-base font-medium\",\n className,\n )}\n {...props}\n >\n {children}\n </h2>\n );\n}\n\n/** One line under the title — from whom, a status. */\nfunction Description({ className, ...props }: ComponentProps<\"p\">) {\n return (\n <p\n data-chat-description=\"\"\n className={cn(\n \"text-pho-description m-0 min-w-0 truncate text-xs\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/* ------------------------------- messages ------------------------------- */\n\n/** Within this many px of the bottom the pane counts as pinned. */\nconst PIN_SLACK_PX = 40;\n\nexport interface ChatMessagesProps extends ComponentProps<\"div\"> {\n /** Earlier pages exist — a button at the top asks for them. */\n hasEarlier?: boolean;\n /** The earlier page is on its way. */\n loadingEarlier?: boolean;\n /** Ask for the page before the first message shown. */\n onLoadEarlier?: () => void;\n /** The button's label. @default \"Load earlier messages\" */\n earlierLabel?: ReactNode;\n}\n\n/**\n * The messages, oldest to newest, on the thread surface. The pane starts at\n * the bottom and stays there as messages arrive unless the reader has\n * scrolled up; an earlier page keeps what they were reading in place.\n * Children are `Message` rows and `Divider`s.\n */\nfunction Messages({\n hasEarlier = false,\n loadingEarlier = false,\n onLoadEarlier,\n earlierLabel = \"Load earlier messages\",\n className,\n children,\n ...props\n}: ChatMessagesProps) {\n const viewportRef = useRef<HTMLDivElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const pinned = useRef(true);\n const anchor = useRef<{ height: number; top: number } | null>(null);\n\n useIsoLayoutEffect(() => {\n const viewport = viewportRef.current;\n const content = contentRef.current;\n if (!viewport || !content) return;\n const settle = () => {\n const kept = anchor.current;\n if (kept) {\n anchor.current = null;\n viewport.scrollTop = viewport.scrollHeight - kept.height + kept.top;\n return;\n }\n if (pinned.current) viewport.scrollTop = viewport.scrollHeight;\n };\n settle();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(settle);\n observer.observe(content);\n observer.observe(viewport);\n return () => observer.disconnect();\n }, []);\n\n const onScroll = () => {\n const viewport = viewportRef.current;\n if (!viewport) return;\n pinned.current =\n viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight <\n PIN_SLACK_PX;\n };\n\n const loadEarlier = () => {\n const viewport = viewportRef.current;\n if (viewport) {\n anchor.current = {\n height: viewport.scrollHeight,\n top: viewport.scrollTop,\n };\n }\n pinned.current = false;\n onLoadEarlier?.();\n };\n\n return (\n <div\n data-chat-messages=\"\"\n className={cn(\n // Bubbles' focus and selected rings offset against the thread.\n \"flex min-h-0 flex-1 flex-col [--pho-bubble-backdrop:var(--background-color-pho-primary)]\",\n className,\n )}\n {...props}\n >\n <ScrollArea.Root className=\"min-h-0 flex-1\">\n <ScrollArea.Viewport ref={viewportRef} onScroll={onScroll}>\n <ScrollArea.Content\n ref={contentRef}\n style={{ minWidth: 0 }}\n className=\"flex min-h-full flex-col gap-1 p-4\"\n >\n {hasEarlier && (\n <div className=\"flex justify-center\">\n <Button\n variant=\"outlined\"\n size=\"sm\"\n loading={loadingEarlier}\n onClick={loadEarlier}\n >\n {earlierLabel}\n </Button>\n </div>\n )}\n {children}\n </ScrollArea.Content>\n </ScrollArea.Viewport>\n <ScrollArea.Scrollbar>\n <ScrollArea.Thumb />\n </ScrollArea.Scrollbar>\n </ScrollArea.Root>\n </div>\n );\n}\n\n/** A centered caption in the thread — the day, \"Unread\". */\nfunction Divider({ className, children, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n data-chat-divider=\"\"\n className={cn(\"text-pho-description py-1 text-center text-xs\", className)}\n {...props}\n >\n {children}\n </div>\n );\n}\n\n/* -------------------------------- footer -------------------------------- */\n\n/** The docked bar under the messages — usually a `Composer`. */\nfunction Footer({ className, ...props }: ComponentProps<\"footer\">) {\n return (\n <footer\n data-chat-footer=\"\"\n className={cn(\"shrink-0 px-4 py-3\", className)}\n {...props}\n />\n );\n}\n\n/** The draft box grows with the text up to this, then scrolls. */\nconst COMPOSER_MAX_HEIGHT_PX = 200;\n\nexport interface ChatComposerProps extends Omit<\n ComponentProps<\"form\">,\n \"onSubmit\" | \"prefix\" | \"children\"\n> {\n /** The draft. */\n value: string;\n onValueChange: (value: string) => void;\n /** Enter, or the send button. Not called while `sending` or with nothing to send. */\n onSend: () => void;\n placeholder?: string;\n /** The send is in flight — the button spins, the box waits. */\n sending?: boolean;\n disabled?: boolean;\n /**\n * There is something to send besides text (an attachment). By default\n * the send button wakes when the draft has a non-blank character.\n */\n canSend?: boolean;\n /** Controls at the start of the bottom row — an add-attachment button. */\n prefix?: ReactNode;\n /** A quiet line between `prefix` and the send button — a count, a size. */\n meta?: ReactNode;\n /** The send button's accessible name. @default \"Send\" */\n sendLabel?: string;\n /** Above the text — attachment thumbnails. */\n children?: ReactNode;\n /** The `<textarea>`. */\n textareaRef?: Ref<HTMLTextAreaElement>;\n}\n\n/**\n * The message box: text that grows with the draft, Enter to send and\n * Shift+Enter for a new line, one round send button. Attachments are the\n * page's: put their thumbnails in `children`, the button that adds them\n * in `prefix`, and flip `canSend` when they alone should send.\n */\nfunction Composer({\n value,\n onValueChange,\n onSend,\n placeholder = \"Message\",\n sending = false,\n disabled = false,\n canSend,\n prefix,\n meta,\n sendLabel = \"Send\",\n children,\n textareaRef,\n className,\n ...props\n}: ChatComposerProps) {\n const innerRef = useRef<HTMLTextAreaElement | null>(null);\n const ready = !sending && !disabled && (canSend ?? value.trim().length > 0);\n\n useIsoLayoutEffect(() => {\n const element = innerRef.current;\n if (!element) return;\n element.style.height = \"0px\";\n element.style.height = `${Math.min(element.scrollHeight, COMPOSER_MAX_HEIGHT_PX)}px`;\n }, [value]);\n\n const submit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (ready) onSend();\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (\n event.key === \"Enter\" &&\n !event.shiftKey &&\n !event.nativeEvent.isComposing\n ) {\n event.preventDefault();\n if (ready) onSend();\n }\n };\n\n return (\n <form\n aria-label=\"Message composer\"\n data-chat-composer=\"\"\n onSubmit={submit}\n className={cn(\n // The field surface, as `Input`: hairline at rest, brand ring while\n // anything inside has focus.\n \"rounded-base bg-pho-primary ring-pho-primary focus-within:ring-pho-brand ring-1 transition-shadow duration-100 ease-linear ring-inset focus-within:ring-2\",\n disabled && \"opacity-50\",\n className,\n )}\n {...props}\n >\n {children}\n <textarea\n ref={(node) => {\n innerRef.current = node;\n if (typeof textareaRef === \"function\") textareaRef(node);\n else if (textareaRef) {\n (textareaRef as { current: HTMLTextAreaElement | null }).current =\n node;\n }\n }}\n value={value}\n onChange={(event) => onValueChange(event.target.value)}\n onKeyDown={onKeyDown}\n rows={1}\n placeholder={placeholder}\n aria-label=\"Message\"\n disabled={disabled}\n // In flight the box holds its text but stays focusable — `disabled`\n // would drop focus mid-send; `ready` already blocks a second send.\n readOnly={sending}\n className=\"text-pho-primary placeholder:text-pho-placeholder m-0 block w-full resize-none bg-transparent px-4 pt-3 pb-1 text-base outline-none disabled:cursor-not-allowed\"\n />\n <div className=\"flex items-center gap-2 px-2 pb-2\">\n {prefix}\n <p className=\"text-pho-description m-0 min-w-0 flex-1 truncate text-xs\">\n {meta}\n </p>\n <Button\n type=\"submit\"\n size=\"sm\"\n shape=\"circle\"\n svgOnly\n aria-label={sendLabel}\n disabled={!ready}\n loading={sending}\n >\n <IconArrowUp />\n </Button>\n </div>\n </form>\n );\n}\n\n/* --------------------------------- states ------------------------------- */\n\nexport interface ChatEmptyProps extends StatusViewProps {}\n\n/**\n * The standing-in view for either pane — no conversations, no thread\n * chosen, nothing said yet. `StatusView` at card size, centered in\n * whatever room the pane has.\n */\nfunction Empty({ className, size = \"sm\", ...props }: ChatEmptyProps) {\n return (\n <div\n data-chat-empty=\"\"\n className={cn(\n \"flex flex-1 flex-col items-center justify-center px-6 py-8\",\n className,\n )}\n >\n <StatusView size={size} {...props} />\n </div>\n );\n}\n\n/** Bones in the shape of conversation rows — avatar, who, when, preview. */\nfunction ConversationsLoading({ rows = 5 }: { rows?: number }) {\n return (\n <div\n aria-hidden\n data-chat-conversations-loading=\"\"\n className=\"flex flex-col gap-0.5\"\n >\n {Array.from({ length: rows }, (_, row) => (\n <div key={row} className=\"flex items-center gap-3 px-2 py-2.5\">\n <Skeleton className=\"size-8 shrink-0 rounded-full\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between gap-2\">\n <Skeleton className=\"h-3.5 w-32\" />\n <Skeleton className=\"h-2.5 w-8\" />\n </div>\n <Skeleton className=\"mt-2 h-2.5 w-44\" />\n </div>\n </div>\n ))}\n </div>\n );\n}\n\n/** Bones in a thread's shape — theirs left, ours right. */\nfunction MessagesLoading() {\n return (\n <div\n aria-hidden\n data-chat-messages-loading=\"\"\n className=\"flex flex-col gap-3\"\n >\n <Skeleton className=\"rounded-base h-10 w-1/2 self-start\" />\n <Skeleton className=\"rounded-base h-10 w-2/5 self-end\" />\n <Skeleton className=\"rounded-base h-16 w-3/5 self-start\" />\n </div>\n );\n}\n\n/**\n * The composed inbox. Assemble the two panes and fill them:\n *\n * ```tsx\n * <Chat.Root layout=\"auto\" className=\"h-[32rem]\">\n * <Chat.List>\n * <Chat.Search value={query} onChange={…} />\n * <Chat.Conversations>\n * <Chat.ConversationList>\n * <Chat.Conversation title=\"+1 (315) 997-8332\" time=\"2d ago\" preview=\"…\" active />\n * </Chat.ConversationList>\n * </Chat.Conversations>\n * </Chat.List>\n * <Chat.Thread>\n * <Chat.Header avatar={<Avatar.Root size=\"md\">…</Avatar.Root>}>\n * <Chat.Title>+1 (315) 997-8332</Chat.Title>\n * <Chat.Description>From …</Chat.Description>\n * </Chat.Header>\n * <Chat.Messages>\n * <Chat.Divider>September 12</Chat.Divider>\n * <Message.Root>…</Message.Root>\n * </Chat.Messages>\n * <Chat.Footer>\n * <Chat.Composer value={draft} onValueChange={setDraft} onSend={send} />\n * </Chat.Footer>\n * </Chat.Thread>\n * </Chat.Root>\n * ```\n */\nexport const Chat = {\n Root,\n List,\n Search,\n Conversations,\n ConversationList,\n Conversation,\n Thread,\n Header,\n Title,\n Description,\n Messages,\n Divider,\n Footer,\n Composer,\n Empty,\n ConversationsLoading,\n MessagesLoading,\n};\n"],"x_google_ignoreList":[0,1,2,3],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { t } from "./cn-ChIgwEl3.js";
3
3
  import { r as b } from "./use-press-pulse-IbNstUT0.js";
4
- import { n as f, r as x, t as v } from "./choice-card-BVNP1NB6.js";
4
+ import { n as f, r as x, t as v } from "./choice-card-_Ocs0iUj.js";
5
5
  import "react";
6
6
  import { jsx as e, jsxs as p } from "react/jsx-runtime";
7
7
  import { motion as m } from "motion/react";
@@ -130,4 +130,4 @@ export {
130
130
  O as t
131
131
  };
132
132
 
133
- //# sourceMappingURL=checkbox-CLPmblNA.js.map
133
+ //# sourceMappingURL=checkbox-CwvoEJhd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox-CLPmblNA.js","names":[],"sources":["../../src/components/checkbox/check-glyph.tsx","../../src/components/checkbox/checkbox.tsx","../../src/components/checkbox/checkbox-group.tsx","../../src/components/checkbox/checkbox-card.tsx"],"sourcesContent":["import { motion } from \"motion/react\";\n\n// Tabler's IconCheck / IconMinus paths, redrawn as a single animatable\n// `motion.path` — same 24×24 outline geometry, round caps/joins. Tabler\n// draws at stroke 2 for a 24px icon; the box shows this one at 12–14px,\n// where 2 thins to a hair, so it strokes at 3 and reads with the same\n// weight the icons around it have.\nconst CHECK_PATH = \"M5 12l5 5l10 -10\";\nconst MINUS_PATH = \"M5 12l14 0\";\n\nconst DRAW_TRANSITION = { duration: 0.22, ease: \"easeOut\" } as const;\n\n/**\n * The checkbox glyph, stroked on rather than popped in solid — same\n * considered-motion spirit as Button's press/wake effects. Re-keyed per\n * state (check vs. dash) so every appearance draws fresh from empty instead\n * of resuming a stroke left mid-way by whatever the glyph showed before.\n */\nexport function DrawnCheckGlyph({\n indeterminate,\n className,\n}: {\n indeterminate?: boolean;\n className?: string;\n}) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={3}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <motion.path\n key={indeterminate ? \"minus\" : \"check\"}\n d={indeterminate ? MINUS_PATH : CHECK_PATH}\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n transition={DRAW_TRANSITION}\n />\n </svg>\n );\n}\n","import { type ComponentProps, type ReactNode } from \"react\";\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { motion } from \"motion/react\";\nimport { DrawnCheckGlyph } from \"./check-glyph\";\nimport { cn } from \"../../utils/cn\";\nimport { usePressPulse } from \"../../utils/use-press-pulse\";\n\nexport type CheckboxSize = \"sm\" | \"md\";\n\nconst BOX: Record<CheckboxSize, string> = { sm: \"size-4\", md: \"size-5\" };\nconst ICON: Record<CheckboxSize, string> = { sm: \"size-3\", md: \"size-3.5\" };\n\nexport interface CheckboxProps extends Omit<\n ComponentProps<typeof BaseCheckbox.Root>,\n \"className\"\n> {\n className?: string;\n /** Text rendered beside the box; the whole row toggles the checkbox. */\n label?: ReactNode;\n /** Size variant. @default \"md\" */\n size?: CheckboxSize;\n}\n\n/**\n * Checkbox built on Base UI `Checkbox`. Supports checked, unchecked, and\n * `indeterminate` states; pass `label` for a clickable text row, or omit it\n * and provide an `aria-label`. For a set of related options that submit\n * together, wrap them in `CheckboxGroup`.\n *\n * Animation is the Effect Button family scaled to a toggle, kept restrained:\n * a quick shallow press pulse on pointer-down (always plays out), the\n * fill/stroke easing between states, and the glyph popping in.\n */\nexport function Checkbox({\n className,\n label,\n size = \"md\",\n disabled,\n indeterminate,\n ...props\n}: CheckboxProps) {\n const { motionProps } = usePressPulse({\n scale: 0.94,\n disabled: Boolean(disabled),\n });\n // With a label, the whole row is the hit target — press-trigger from there\n // (pointerdown bubbles up from the label text too) so the box still\n // animates when the text, not the box itself, is what's clicked.\n const { onPointerDown, ...boxMotionProps } = motionProps;\n\n const box = (\n <BaseCheckbox.Root\n disabled={disabled}\n indeterminate={indeterminate}\n render={\n <motion.span\n {...boxMotionProps}\n onPointerDown={label ? undefined : onPointerDown}\n />\n }\n className={cn(\n // Flat field surface with the input-strength ring; the glyph only shows\n // on the brand-solid checked fill, so it must be on-brand (not white —\n // brand-solid is white in dark mode).\n \"group/cb outline-pho-brand bg-pho-primary ring-pho-primary text-pho-on-brand flex shrink-0 cursor-pointer items-center justify-center rounded-sm ring-1 ring-inset focus-visible:outline-2 focus-visible:outline-offset-2\",\n // Fill and stroke ease between states (stroke dissolves into the\n // fill on tick). Transform stays out — Motion owns the press pulse.\n \"transition-[background-color,box-shadow,color,outline-color] duration-150 ease-out\",\n // group-hover covers hovering the label text, not just the box itself.\n \"hover:bg-pho-primary-hover hover:ring-pho-ink group-hover:bg-pho-primary-hover group-hover:ring-pho-ink\",\n \"data-[checked]:bg-pho-brand-solid data-[checked]:ring-transparent\",\n \"data-[indeterminate]:bg-pho-brand-solid data-[indeterminate]:ring-transparent\",\n \"data-[checked]:hover:bg-pho-brand-solid-hover data-[checked]:group-hover:bg-pho-brand-solid-hover\",\n \"data-[indeterminate]:hover:bg-pho-brand-solid-hover data-[indeterminate]:group-hover:bg-pho-brand-solid-hover\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n BOX[size],\n className,\n )}\n {...props}\n >\n {/* The glyph draws itself on (see DrawnCheckGlyph) — no separate\n pop-in needed. A quick fade covers the exit, since an unmount\n can't play the stroke backwards. */}\n <BaseCheckbox.Indicator\n className={cn(\n \"flex items-center justify-center transition-opacity duration-100 ease-out\",\n \"data-[ending-style]:opacity-0\",\n )}\n >\n <DrawnCheckGlyph indeterminate={indeterminate} className={ICON[size]} />\n </BaseCheckbox.Indicator>\n </BaseCheckbox.Root>\n );\n\n if (!label) return box;\n return (\n <label\n className=\"group flex cursor-pointer items-center gap-2 select-none\"\n onPointerDown={onPointerDown}\n >\n {box}\n <span className=\"text-pho-secondary text-base\">{label}</span>\n </label>\n );\n}\n\nCheckbox.displayName = \"Checkbox\";\n","import { type ComponentProps } from \"react\";\nimport { CheckboxGroup as BaseCheckboxGroup } from \"@base-ui/react/checkbox-group\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface CheckboxGroupProps extends Omit<\n ComponentProps<typeof BaseCheckboxGroup>,\n \"className\"\n> {\n className?: string;\n}\n\n/**\n * Groups related `Checkbox`es and tracks their values as one. Built on Base UI\n * `CheckboxGroup` — supports a parent \"select all\" checkbox via `allValues`.\n * Control with `value` / `onValueChange` or leave uncontrolled with\n * `defaultValue`.\n */\nexport function CheckboxGroup({ className, ...props }: CheckboxGroupProps) {\n return (\n <BaseCheckboxGroup\n className={cn(\"flex flex-col gap-3\", className)}\n {...props}\n />\n );\n}\n\nCheckboxGroup.displayName = \"CheckboxGroup\";\n","import { type ComponentProps, type ReactNode } from \"react\";\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { motion } from \"motion/react\";\nimport { DrawnCheckGlyph } from \"./check-glyph\";\nimport { cn } from \"../../utils/cn\";\nimport { usePressPulse } from \"../../utils/use-press-pulse\";\nimport {\n CHOICE_CARD_BASE,\n CHOICE_CARD_WITH_ICON,\n CHOICE_CARD_PRESS_SCALE,\n CHOICE_CARD_PRESS_TRANSITION,\n} from \"../../utils/choice-card\";\n\nexport interface CheckboxCardProps extends Omit<\n ComponentProps<typeof BaseCheckbox.Root>,\n \"className\" | \"title\"\n> {\n className?: string;\n /** Tile heading. */\n title: ReactNode;\n /** Supporting copy shown below the title. */\n description?: ReactNode;\n /** Glyph stacked above the title. When set, it replaces the checkbox box. */\n icon?: ReactNode;\n}\n\nfunction CardCopy({\n title,\n description,\n}: {\n title: ReactNode;\n description?: ReactNode;\n}) {\n return (\n <span className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"text-pho-primary block font-medium\">{title}</span>\n {description ? (\n <span className=\"text-pho-description block\">{description}</span>\n ) : null}\n </span>\n );\n}\n\n/**\n * A `Checkbox` styled as a bordered, selectable tile — title, optional\n * description, and either a stacked icon above them or the checkbox box at\n * the end of the title row. The tile is a\n * `<label>` around the control so clicks (including on the icon/title) are a\n * trusted activation of the hidden input Base UI renders beside the root.\n */\nexport function CheckboxCard({\n className,\n title,\n description,\n icon,\n disabled,\n indeterminate,\n ...props\n}: CheckboxCardProps) {\n const { motionProps } = usePressPulse({\n scale: CHOICE_CARD_PRESS_SCALE,\n disabled: Boolean(disabled),\n transition: CHOICE_CARD_PRESS_TRANSITION,\n });\n const hasIcon = icon != null;\n\n return (\n <motion.label\n {...motionProps}\n className={cn(\n CHOICE_CARD_BASE,\n hasIcon && CHOICE_CARD_WITH_ICON,\n className,\n )}\n data-disabled={disabled ? \"\" : undefined}\n >\n {hasIcon ? (\n <span\n aria-hidden\n className=\"text-pho-secondary flex size-6 shrink-0 items-center justify-center [&>svg]:size-6\"\n >\n {icon}\n </span>\n ) : null}\n <CardCopy title={title} description={description} />\n {/* The box sits at the end of the title row, centered on the title's\n line and the same half step from the right edge, square in the\n corner; with an icon it is the hidden control the label\n activates. */}\n <BaseCheckbox.Root\n disabled={disabled}\n indeterminate={indeterminate}\n className={\n hasIcon\n ? \"sr-only\"\n : cn(\n \"bg-pho-primary ring-pho-primary text-pho-on-brand mt-0.5 mr-0.5 flex size-4 shrink-0 items-center justify-center rounded-sm ring-1 ring-inset\",\n \"group-hover:bg-pho-primary-hover group-hover:ring-pho-ink transition-[background-color,box-shadow,color] duration-150 ease-out\",\n \"data-[checked]:bg-pho-brand-solid data-[checked]:group-hover:bg-pho-brand-solid-hover data-[checked]:ring-transparent\",\n \"data-[indeterminate]:bg-pho-brand-solid data-[indeterminate]:group-hover:bg-pho-brand-solid-hover data-[indeterminate]:ring-transparent\",\n )\n }\n {...props}\n >\n {hasIcon ? null : (\n <BaseCheckbox.Indicator\n className={cn(\n \"flex items-center justify-center transition-opacity duration-100 ease-out\",\n \"data-[ending-style]:opacity-0\",\n )}\n >\n <DrawnCheckGlyph\n indeterminate={indeterminate}\n className=\"size-2.5\"\n />\n </BaseCheckbox.Indicator>\n )}\n </BaseCheckbox.Root>\n </motion.label>\n );\n}\n\nCheckboxCard.displayName = \"CheckboxCard\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"checkbox-CwvoEJhd.js","names":[],"sources":["../../src/components/checkbox/check-glyph.tsx","../../src/components/checkbox/checkbox.tsx","../../src/components/checkbox/checkbox-group.tsx","../../src/components/checkbox/checkbox-card.tsx"],"sourcesContent":["import { motion } from \"motion/react\";\n\n// Tabler's IconCheck / IconMinus paths, redrawn as a single animatable\n// `motion.path` — same 24×24 outline geometry, round caps/joins. Tabler\n// draws at stroke 2 for a 24px icon; the box shows this one at 12–14px,\n// where 2 thins to a hair, so it strokes at 3 and reads with the same\n// weight the icons around it have.\nconst CHECK_PATH = \"M5 12l5 5l10 -10\";\nconst MINUS_PATH = \"M5 12l14 0\";\n\nconst DRAW_TRANSITION = { duration: 0.22, ease: \"easeOut\" } as const;\n\n/**\n * The checkbox glyph, stroked on rather than popped in solid — same\n * considered-motion spirit as Button's press/wake effects. Re-keyed per\n * state (check vs. dash) so every appearance draws fresh from empty instead\n * of resuming a stroke left mid-way by whatever the glyph showed before.\n */\nexport function DrawnCheckGlyph({\n indeterminate,\n className,\n}: {\n indeterminate?: boolean;\n className?: string;\n}) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={3}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <motion.path\n key={indeterminate ? \"minus\" : \"check\"}\n d={indeterminate ? MINUS_PATH : CHECK_PATH}\n initial={{ pathLength: 0 }}\n animate={{ pathLength: 1 }}\n transition={DRAW_TRANSITION}\n />\n </svg>\n );\n}\n","import { type ComponentProps, type ReactNode } from \"react\";\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { motion } from \"motion/react\";\nimport { DrawnCheckGlyph } from \"./check-glyph\";\nimport { cn } from \"../../utils/cn\";\nimport { usePressPulse } from \"../../utils/use-press-pulse\";\n\nexport type CheckboxSize = \"sm\" | \"md\";\n\nconst BOX: Record<CheckboxSize, string> = { sm: \"size-4\", md: \"size-5\" };\nconst ICON: Record<CheckboxSize, string> = { sm: \"size-3\", md: \"size-3.5\" };\n\nexport interface CheckboxProps extends Omit<\n ComponentProps<typeof BaseCheckbox.Root>,\n \"className\"\n> {\n className?: string;\n /** Text rendered beside the box; the whole row toggles the checkbox. */\n label?: ReactNode;\n /** Size variant. @default \"md\" */\n size?: CheckboxSize;\n}\n\n/**\n * Checkbox built on Base UI `Checkbox`. Supports checked, unchecked, and\n * `indeterminate` states; pass `label` for a clickable text row, or omit it\n * and provide an `aria-label`. For a set of related options that submit\n * together, wrap them in `CheckboxGroup`.\n *\n * Animation is the Effect Button family scaled to a toggle, kept restrained:\n * a quick shallow press pulse on pointer-down (always plays out), the\n * fill/stroke easing between states, and the glyph popping in.\n */\nexport function Checkbox({\n className,\n label,\n size = \"md\",\n disabled,\n indeterminate,\n ...props\n}: CheckboxProps) {\n const { motionProps } = usePressPulse({\n scale: 0.94,\n disabled: Boolean(disabled),\n });\n // With a label, the whole row is the hit target — press-trigger from there\n // (pointerdown bubbles up from the label text too) so the box still\n // animates when the text, not the box itself, is what's clicked.\n const { onPointerDown, ...boxMotionProps } = motionProps;\n\n const box = (\n <BaseCheckbox.Root\n disabled={disabled}\n indeterminate={indeterminate}\n render={\n <motion.span\n {...boxMotionProps}\n onPointerDown={label ? undefined : onPointerDown}\n />\n }\n className={cn(\n // Flat field surface with the input-strength ring; the glyph only shows\n // on the brand-solid checked fill, so it must be on-brand (not white —\n // brand-solid is white in dark mode).\n \"group/cb outline-pho-brand bg-pho-primary ring-pho-primary text-pho-on-brand flex shrink-0 cursor-pointer items-center justify-center rounded-sm ring-1 ring-inset focus-visible:outline-2 focus-visible:outline-offset-2\",\n // Fill and stroke ease between states (stroke dissolves into the\n // fill on tick). Transform stays out — Motion owns the press pulse.\n \"transition-[background-color,box-shadow,color,outline-color] duration-150 ease-out\",\n // group-hover covers hovering the label text, not just the box itself.\n \"hover:bg-pho-primary-hover hover:ring-pho-ink group-hover:bg-pho-primary-hover group-hover:ring-pho-ink\",\n \"data-[checked]:bg-pho-brand-solid data-[checked]:ring-transparent\",\n \"data-[indeterminate]:bg-pho-brand-solid data-[indeterminate]:ring-transparent\",\n \"data-[checked]:hover:bg-pho-brand-solid-hover data-[checked]:group-hover:bg-pho-brand-solid-hover\",\n \"data-[indeterminate]:hover:bg-pho-brand-solid-hover data-[indeterminate]:group-hover:bg-pho-brand-solid-hover\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n BOX[size],\n className,\n )}\n {...props}\n >\n {/* The glyph draws itself on (see DrawnCheckGlyph) — no separate\n pop-in needed. A quick fade covers the exit, since an unmount\n can't play the stroke backwards. */}\n <BaseCheckbox.Indicator\n className={cn(\n \"flex items-center justify-center transition-opacity duration-100 ease-out\",\n \"data-[ending-style]:opacity-0\",\n )}\n >\n <DrawnCheckGlyph indeterminate={indeterminate} className={ICON[size]} />\n </BaseCheckbox.Indicator>\n </BaseCheckbox.Root>\n );\n\n if (!label) return box;\n return (\n <label\n className=\"group flex cursor-pointer items-center gap-2 select-none\"\n onPointerDown={onPointerDown}\n >\n {box}\n <span className=\"text-pho-secondary text-base\">{label}</span>\n </label>\n );\n}\n\nCheckbox.displayName = \"Checkbox\";\n","import { type ComponentProps } from \"react\";\nimport { CheckboxGroup as BaseCheckboxGroup } from \"@base-ui/react/checkbox-group\";\nimport { cn } from \"../../utils/cn\";\n\nexport interface CheckboxGroupProps extends Omit<\n ComponentProps<typeof BaseCheckboxGroup>,\n \"className\"\n> {\n className?: string;\n}\n\n/**\n * Groups related `Checkbox`es and tracks their values as one. Built on Base UI\n * `CheckboxGroup` — supports a parent \"select all\" checkbox via `allValues`.\n * Control with `value` / `onValueChange` or leave uncontrolled with\n * `defaultValue`.\n */\nexport function CheckboxGroup({ className, ...props }: CheckboxGroupProps) {\n return (\n <BaseCheckboxGroup\n className={cn(\"flex flex-col gap-3\", className)}\n {...props}\n />\n );\n}\n\nCheckboxGroup.displayName = \"CheckboxGroup\";\n","import { type ComponentProps, type ReactNode } from \"react\";\nimport { Checkbox as BaseCheckbox } from \"@base-ui/react/checkbox\";\nimport { motion } from \"motion/react\";\nimport { DrawnCheckGlyph } from \"./check-glyph\";\nimport { cn } from \"../../utils/cn\";\nimport { usePressPulse } from \"../../utils/use-press-pulse\";\nimport {\n CHOICE_CARD_BASE,\n CHOICE_CARD_WITH_ICON,\n CHOICE_CARD_PRESS_SCALE,\n CHOICE_CARD_PRESS_TRANSITION,\n} from \"../../utils/choice-card\";\n\nexport interface CheckboxCardProps extends Omit<\n ComponentProps<typeof BaseCheckbox.Root>,\n \"className\" | \"title\"\n> {\n className?: string;\n /** Tile heading. */\n title: ReactNode;\n /** Supporting copy shown below the title. */\n description?: ReactNode;\n /** Glyph stacked above the title. When set, it replaces the checkbox box. */\n icon?: ReactNode;\n}\n\nfunction CardCopy({\n title,\n description,\n}: {\n title: ReactNode;\n description?: ReactNode;\n}) {\n return (\n <span className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"text-pho-primary block font-medium\">{title}</span>\n {description ? (\n <span className=\"text-pho-description block\">{description}</span>\n ) : null}\n </span>\n );\n}\n\n/**\n * A `Checkbox` styled as a bordered, selectable tile — title, optional\n * description, and either a stacked icon above them or the checkbox box at\n * the end of the title row. The tile is a\n * `<label>` around the control so clicks (including on the icon/title) are a\n * trusted activation of the hidden input Base UI renders beside the root.\n */\nexport function CheckboxCard({\n className,\n title,\n description,\n icon,\n disabled,\n indeterminate,\n ...props\n}: CheckboxCardProps) {\n const { motionProps } = usePressPulse({\n scale: CHOICE_CARD_PRESS_SCALE,\n disabled: Boolean(disabled),\n transition: CHOICE_CARD_PRESS_TRANSITION,\n });\n const hasIcon = icon != null;\n\n return (\n <motion.label\n {...motionProps}\n className={cn(\n CHOICE_CARD_BASE,\n hasIcon && CHOICE_CARD_WITH_ICON,\n className,\n )}\n data-disabled={disabled ? \"\" : undefined}\n >\n {hasIcon ? (\n <span\n aria-hidden\n className=\"text-pho-secondary flex size-6 shrink-0 items-center justify-center [&>svg]:size-6\"\n >\n {icon}\n </span>\n ) : null}\n <CardCopy title={title} description={description} />\n {/* The box sits at the end of the title row, centered on the title's\n line and the same half step from the right edge, square in the\n corner; with an icon it is the hidden control the label\n activates. */}\n <BaseCheckbox.Root\n disabled={disabled}\n indeterminate={indeterminate}\n className={\n hasIcon\n ? \"sr-only\"\n : cn(\n \"bg-pho-primary ring-pho-primary text-pho-on-brand mt-0.5 mr-0.5 flex size-4 shrink-0 items-center justify-center rounded-sm ring-1 ring-inset\",\n \"group-hover:bg-pho-primary-hover group-hover:ring-pho-ink transition-[background-color,box-shadow,color] duration-150 ease-out\",\n \"data-[checked]:bg-pho-brand-solid data-[checked]:group-hover:bg-pho-brand-solid-hover data-[checked]:ring-transparent\",\n \"data-[indeterminate]:bg-pho-brand-solid data-[indeterminate]:group-hover:bg-pho-brand-solid-hover data-[indeterminate]:ring-transparent\",\n )\n }\n {...props}\n >\n {hasIcon ? null : (\n <BaseCheckbox.Indicator\n className={cn(\n \"flex items-center justify-center transition-opacity duration-100 ease-out\",\n \"data-[ending-style]:opacity-0\",\n )}\n >\n <DrawnCheckGlyph\n indeterminate={indeterminate}\n className=\"size-2.5\"\n />\n </BaseCheckbox.Indicator>\n )}\n </BaseCheckbox.Root>\n </motion.label>\n );\n}\n\nCheckboxCard.displayName = \"CheckboxCard\";\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { n as a } from "./use-press-pulse-IbNstUT0.js";
3
+ var r = "group outline-pho-brand flex flex-1 cursor-pointer items-start gap-2.5 rounded-base px-[var(--choice-card-inset,0.75rem)] py-[calc(var(--choice-card-inset,0.75rem)*0.75)] text-base text-pho-secondary ring-1 ring-pho-primary ring-inset transition-[box-shadow,background-color] duration-150 ease-out select-none hover:bg-pho-ghost-hover data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[disabled]:hover:bg-transparent data-[checked]:ring-2 data-[checked]:ring-pho-brand has-[[data-checked]]:ring-2 has-[[data-checked]]:ring-pho-brand focus-visible:outline-2 focus-visible:outline-offset-2 has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2", s = "flex-col gap-1.5", o = 0.98, i = a, t = {
4
+ type: "spring",
5
+ stiffness: 500,
6
+ damping: 30,
7
+ mass: 0.5
8
+ };
9
+ export {
10
+ t as a,
11
+ s as i,
12
+ o as n,
13
+ i as r,
14
+ r as t
15
+ };
16
+
17
+ //# sourceMappingURL=choice-card-_Ocs0iUj.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"choice-card-_Ocs0iUj.js","names":[],"sources":["../../src/utils/choice-card.ts"],"sourcesContent":["import type { Transition } from \"motion/react\";\nimport { CONTROL_PRESS_SPRING } from \"./use-press-pulse\";\n\n/**\n * Shared surface for `RadioCard` / `CheckboxCard` — a bordered, selectable\n * tile. Applied to the radio/checkbox root itself so the whole tile is the\n * hit target. Hover fills (`bg-pho-ghost-hover`); selected uses the brand\n * ring. Press feedback lives on this surface (see `usePressPulse`).\n *\n * The side padding is `--choice-card-inset`, 12px unless the page says\n * otherwise, and the padding above and below is three quarters of it: a\n * `BasicPage.Stack` sets it to the page's text edge (20px), so tiles\n * standing on the page as its surfaces reach the column's edge as a card\n * does and start their words on the headings' line; a card, sheet or\n * callout sets it back, so tiles inside one stay compact.\n */\nexport const CHOICE_CARD_BASE =\n \"group outline-pho-brand flex flex-1 cursor-pointer items-start gap-2.5 rounded-base px-[var(--choice-card-inset,0.75rem)] py-[calc(var(--choice-card-inset,0.75rem)*0.75)] text-base text-pho-secondary ring-1 ring-pho-primary ring-inset transition-[box-shadow,background-color] duration-150 ease-out select-none hover:bg-pho-ghost-hover data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[disabled]:hover:bg-transparent data-[checked]:ring-2 data-[checked]:ring-pho-brand has-[[data-checked]]:ring-2 has-[[data-checked]]:ring-pho-brand focus-visible:outline-2 focus-visible:outline-offset-2 has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2\";\n\n/** Stacked icon above the copy — tighter than the checkbox/radio row gap. */\nexport const CHOICE_CARD_WITH_ICON = \"flex-col gap-1.5\";\n\n/** Same press as Select's default trigger — field-sized, not Button's whileTap. */\nexport const CHOICE_CARD_PRESS_SCALE = 0.98;\nexport const CHOICE_CARD_PRESS_TRANSITION: Transition = CONTROL_PRESS_SPRING;\n\n/** Selection pop for a radio dot / checkbox glyph — quick and slightly bouncy. */\nexport const CHOICE_INDICATOR_POP_TRANSITION: Transition = {\n type: \"spring\",\n stiffness: 500,\n damping: 30,\n mass: 0.5,\n};\n"],"mappings":";;AAgBA,IAAa,IACX,qqBAGW,IAAwB,oBAGxB,IAA0B,MAC1B,IAA2C,GAG3C,IAA8C;AAAA,EACzD,MAAM;AAAA,EACN,WAAW;AAAA,EACX,SAAS;AAAA,EACT,MAAM;AACR"}
@@ -4,8 +4,8 @@ import { t as m } from "./resolve-variant-CcD8iG5l.js";
4
4
  import { SPRING_SETTLE as P } from "../motion.js";
5
5
  import { t as j } from "./IconArrowUpRight-DGgKzQwV.js";
6
6
  import { t as V } from "./IconChevronLeft-CSWMKQ4C.js";
7
- import { t as Z } from "./animated-height-I44sUq0n.js";
8
- import { t as u } from "./dialog-MPvem7yV.js";
7
+ import { t as Z } from "./animated-height-zr7BmFY1.js";
8
+ import { t as u } from "./dialog-ChS0tdHa.js";
9
9
  import { useEffect as $, useId as z, useLayoutEffect as A, useRef as F } from "react";
10
10
  import { Fragment as E, jsx as t, jsxs as d } from "react/jsx-runtime";
11
11
  import { LayoutGroup as H, motion as g, useReducedMotion as B } from "motion/react";
@@ -222,4 +222,4 @@ export {
222
222
  ye as t
223
223
  };
224
224
 
225
- //# sourceMappingURL=command-iYvU6Mhf.js.map
225
+ //# sourceMappingURL=command-D5g49VqR.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"command-iYvU6Mhf.js","names":[],"sources":["../../src/components/command/command.tsx"],"sourcesContent":["import {\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n type ComponentProps,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { IconArrowUpRight, IconChevronLeft } from \"@tabler/icons-react\";\nimport { SPRING_SETTLE } from \"../../motion\";\nimport { Command as CommandPrimitive, useCommandState } from \"cmdk\";\nimport { LayoutGroup, motion, useReducedMotion } from \"motion/react\";\nimport { AnimatedHeight } from \"../../utils/animated-height\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveVariant, type VariantMap } from \"../../utils/resolve-variant\";\nimport { Dialog as PhoDialog } from \"../dialog\";\n\n/**\n * Spring for row moves (FLIP / shared-layout) — same feel as\n * `AnimatedHeight`: quick and critically damped, so rows glide to their new\n * slot without overshooting into neighbours.\n */\nconst ROW_MOVE_SPRING = SPRING_SETTLE;\n\nfunction Root({\n // Filtering is yours by default: filter in render (state above the\n // palette) so the rows' FLIP diff can glide survivors to their slots.\n // cmdk's built-in matcher reorders DOM imperatively — invisible to the\n // layout pass — so it is opt-in: pass `shouldFilter` to hand matching\n // and ranking back to cmdk at the cost of the animation.\n shouldFilter = false,\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive>) {\n // Namespace row layoutIds per palette instance — the docs page mounts the\n // inline demo and the dialog demo at once, with identical item values.\n const layoutNamespace = useId();\n return (\n <CommandPrimitive\n className={cn(\n \"bg-pho-primary text-pho-primary flex w-full flex-col overflow-hidden outline-none\",\n className,\n )}\n shouldFilter={shouldFilter}\n {...props}\n >\n <LayoutGroup id={layoutNamespace}>{children}</LayoutGroup>\n </CommandPrimitive>\n );\n}\n\n/**\n * The input row — a bottom hairline separates it from the list. Position\n * leading icons absolutely and pad the input (`pl-9`), mirroring\n * `Autocomplete.InputGroup`.\n */\nfunction InputGroup({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\n \"border-pho-secondary relative flex items-center border-b\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** SSR-safe layout effect (same pattern cmdk uses internally). */\nconst useIsomorphicLayoutEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === \"function\") ref(value);\n else if (ref) ref.current = value;\n}\n\nfunction Input({\n className,\n value,\n ref: consumerRef,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Input>) {\n const inputRef = useRef<HTMLInputElement>(null);\n const search = useCommandState((state) => state.search);\n\n // cmdk stays uncontrolled here on purpose. Its controlled path syncs the\n // `value` prop into the search store through a passive effect — one painted\n // frame late — so on that stale frame the old row is still \"selected\" while\n // the list has already reflowed, and the selection pill visibly rides it\n // before snapping to the re-selected first row. Uncontrolled keystrokes\n // update search + first-row selection synchronously (pre-paint), killing\n // that frame in both directions (typing and clearing).\n //\n // The consumer-facing API is still controlled: external `value` changes\n // (programmatic reset, initial query) are replayed through the native input\n // path below so store, display, and selection take the same sync route.\n useIsomorphicLayoutEffect(() => {\n const input = inputRef.current;\n if (value == null || input == null || value === search) return;\n const setNativeValue = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n \"value\",\n )?.set;\n setNativeValue?.call(input, value);\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n }, [value, search]);\n\n return (\n <CommandPrimitive.Input\n className={cn(\n // Borderless inside the palette surface — the InputGroup hairline\n // carries the edge. display-xs (18px) keeps iOS from zooming in.\n \"text-pho-primary placeholder:text-pho-placeholder text-display-xs w-full bg-transparent px-3 py-3 outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n ref={(node) => {\n inputRef.current = node;\n assignRef(consumerRef, node);\n }}\n />\n );\n}\n\nfunction List({\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive.List>) {\n return (\n // Same spring as the onboarding / invite Card shell — list height glides\n // when idle ↔ search (or filter) changes instead of jumping.\n <AnimatedHeight>\n {/* The scroller is a motion element with layoutScroll so the rows'\n FLIP projections account for its scroll offset — without it,\n scrolling reads as a layout change and every row glides to\n compensate. scroll-py keeps a breath above and below the row\n being scrolled into view. */}\n <motion.div\n layoutScroll\n className=\"max-h-[min(24rem,60vh)] scroll-py-1 overflow-y-auto overscroll-contain\"\n >\n <CommandPrimitive.List\n className={cn(\"relative isolate p-1\", className)}\n {...props}\n >\n {children}\n </CommandPrimitive.List>\n </motion.div>\n </AnimatedHeight>\n );\n}\n\nfunction Empty({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n className={cn(\n \"text-pho-description px-2.5 py-6 text-center text-base\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Group({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n className={cn(\n // cmdk renders the `heading` prop in a [cmdk-group-heading] wrapper —\n // typography mirrors `Autocomplete.GroupLabel`.\n \"[&_[cmdk-group-heading]]:text-pho-secondary [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Row layout mode:\n * - `item` / `subitem` / `subsubitem` — idle hierarchy (icon column + indent)\n * - `result` — flat search hit (breadcrumb + trailing scope)\n */\nexport type CommandItemLevel = \"item\" | \"subitem\" | \"subsubitem\" | \"result\";\nexport type CommandItemSize = \"sm\" | \"md\";\n\nconst ITEM_SIZES = {\n sm: {\n classes: \"gap-1.5 py-1 pr-2 text-sm\",\n description: \"Compact rows for filter lists and dense pickers\",\n },\n md: {\n classes: \"gap-2 py-2 pr-2.5 text-base\",\n description: \"Default palette row\",\n },\n} as const satisfies VariantMap;\n\nconst ITEM_TITLE_SIZES = {\n sm: { classes: \"text-sm\", description: \"Compact row title\" },\n md: { classes: \"text-md\", description: \"Default row title\" },\n} as const satisfies VariantMap;\n\nconst ITEM_ICON_SIZES = {\n sm: {\n classes: \"size-3.5 [&>svg]:size-3.5\",\n description: \"Compact leading glyph\",\n },\n md: {\n classes: \"size-4 [&>svg]:size-4\",\n description: \"Default leading glyph\",\n },\n} as const satisfies VariantMap;\n\ntype ItemPrimitiveProps = ComponentProps<typeof CommandPrimitive.Item>;\n\nexport interface CommandItemProps extends Omit<\n ItemPrimitiveProps,\n \"children\" | \"title\"\n> {\n /**\n * Row depth / mode in the palette:\n * - `item` — page / top destination (icon + title)\n * - `subitem` — section under an item (label aligns with the item title)\n * - `subsubitem` — row under a section (one step deeper)\n * - `result` — flat search hit (`title` + `path` crumbs + `scope`)\n */\n level?: CommandItemLevel;\n /**\n * Leading glyph. On idle `item` rows (and reserved for sub-levels). On\n * `result` rows, pass the resolved icon (self → parent → grandparent).\n */\n icon?: ReactNode;\n /**\n * When `level=\"result\"`, force the icon column so labels align across the\n * list even if this row's `icon` is empty. Set true when any sibling result\n * has an icon; omit when the whole result set is icon-less.\n */\n iconSlot?: boolean;\n /**\n * Row density. `sm` tightens padding and type for chip popovers\n * (Filter Bar options). Palette destinations stay `md`.\n * @default \"md\"\n */\n size?: CommandItemSize;\n /** Primary label. Prefer this over free-form children for the shared layout. */\n title?: ReactNode;\n /**\n * Ancestors after `title` for `level=\"result\"` — parent → page\n * (e.g. `[\"Agent profile\", \"Settings\"]` → `Name < Agent profile < Settings`).\n */\n path?: ReactNode[];\n /**\n * Trailing scope for `level=\"result\"` — `Project` vs `Personal`, not a nav group.\n */\n scope?: ReactNode;\n /** Shows a trailing external-link glyph (opens outside the app). */\n external?: boolean;\n /**\n * Free-form content. When `title` is set, rendered after the label stack.\n * When `title` is omitted, becomes the row body (legacy / simple items).\n */\n children?: ReactNode;\n}\n\n/** Leading icon column — `size-4` at `md`, tighter at `sm`. */\nfunction ItemIcon({\n className,\n size = \"md\",\n ...props\n}: ComponentProps<\"span\"> & { size?: CommandItemSize }) {\n return (\n <span\n className={cn(\n \"text-pho-secondary flex shrink-0 items-center justify-center\",\n resolveVariant(ITEM_ICON_SIZES, size),\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Primary label — medium + primary ink on `item` rows. */\nfunction ItemTitle({\n className,\n level = \"item\",\n size = \"md\",\n ...props\n}: ComponentProps<\"span\"> & {\n level?: CommandItemLevel;\n size?: CommandItemSize;\n}) {\n return (\n <span\n className={cn(\n \"block truncate\",\n resolveVariant(ITEM_TITLE_SIZES, size),\n level === \"item\" && \"text-pho-primary\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * One selectable row. Idle palettes use `level` + `icon` / `title`\n * (item → subitem → subsubitem). Searching uses `level=\"result\"` with `path`\n * crumbs and a trailing `scope` (Project / Personal). No description line —\n * match via `keywords` / aliases instead.\n */\nfunction ExternalGlyph() {\n return (\n <IconArrowUpRight\n aria-hidden\n className=\"text-pho-description size-4 shrink-0\"\n />\n );\n}\n\nfunction Item({\n className,\n level = \"item\",\n size = \"md\",\n icon,\n iconSlot,\n title,\n path,\n scope,\n external,\n children,\n value,\n ...props\n}: CommandItemProps) {\n const reduceMotion = useReducedMotion();\n // cmdk registers `value.trim()` and exposes the selected one as\n // `state.value` — mirrors cmdk's own `data-selected` computation.\n const trimmedValue = typeof value === \"string\" ? value.trim() : \"\";\n const selectedValue = useCommandState((state) => state.value);\n const isSelected = trimmedValue !== \"\" && selectedValue === trimmedValue;\n const structured = title != null;\n const isResult = level === \"result\";\n // Reserve the icon column when the row has an icon, or when the list asks\n // for alignment (`iconSlot`) even if this row's glyph is empty.\n const showResultIcon = isResult && (icon != null || iconSlot);\n\n const row = (\n <CommandPrimitive.Item\n data-level={level}\n data-size={size}\n value={value}\n className={cn(\n \"text-pho-secondary flex cursor-pointer items-center rounded-[calc(var(--radius-base)-4px)] outline-none select-none\",\n resolveVariant(ITEM_SIZES, size),\n // subsubitem steps in; item/subitem share the base gutter.\n level === \"subsubitem\" ? \"pl-6\" : \"pl-2\",\n // Secondary at rest; selection lifts to primary ink (Menu idiom).\n // The wash lands with it instantly — stepping through rows is a\n // snap, not a flight.\n \"data-[selected=true]:text-pho-primary data-[selected=true]:bg-pho-ghost-hover\",\n \"data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50\",\n className,\n )}\n {...props}\n >\n {structured && isResult ? (\n <>\n {showResultIcon ? (\n <ItemIcon size={size} aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n ) : null}\n {/* Same title size as idle ItemTitle so row height matches. */}\n <span\n className={cn(\n \"flex min-w-0 flex-1 items-center gap-1 overflow-hidden\",\n resolveVariant(ITEM_TITLE_SIZES, size),\n )}\n >\n <span className=\"text-pho-primary truncate\">{title}</span>\n {(path ?? []).map((segment, index) => (\n <span\n key={index}\n className=\"text-pho-description flex shrink-0 items-center gap-0.5\"\n >\n <IconChevronLeft aria-hidden className=\"size-4 shrink-0\" />\n {segment}\n </span>\n ))}\n </span>\n {scope != null && scope !== \"\" ? (\n <span className=\"text-pho-description shrink-0 text-xs\">\n {scope}\n </span>\n ) : null}\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : structured ? (\n <>\n {/* Icon column always reserved so subitem labels share the item title edge. */}\n <ItemIcon size={size} aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n <span className=\"min-w-0 flex-1\">\n <ItemTitle level={level} size={size}>\n {title}\n </ItemTitle>\n </span>\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : (\n children\n )}\n </CommandPrimitive.Item>\n );\n\n if (reduceMotion) return row;\n\n return (\n // FLIP wrapper: rows that stay mounted glide when neighbours enter or\n // leave, and a row remounting elsewhere with the same `value` (idle group\n // ↔ flat search result) inherits the old bounds via its layoutId and\n // slides to the new slot — the iOS list-diff feel. Rows without a match\n // simply appear / disappear so the whole list never swarms.\n //\n // The selected row is the exception: it skips the travel and appears at\n // its final slot immediately, so the selection wash is never sitting on\n // empty space waiting for its row to fly in.\n <motion.div\n layout=\"position\"\n layoutId={typeof value === \"string\" ? value : undefined}\n initial={false}\n transition={isSelected ? { duration: 0 } : ROW_MOVE_SPRING}\n >\n {row}\n </motion.div>\n );\n}\n\nfunction Separator({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n className={cn(\n \"-mx-1 my-1 h-px bg-[var(--border-color-pho-secondary)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Loading({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Loading>) {\n return (\n <CommandPrimitive.Loading\n className={cn(\"text-pho-description px-2.5 py-1.5 text-base\", className)}\n {...props}\n />\n );\n}\n\ntype DialogRootProps = ComponentProps<typeof PhoDialog.Root>;\n\ninterface CommandDialogProps extends ComponentProps<typeof CommandPrimitive> {\n /** Controlled dialog state — pass straight through to `Dialog.Root`. */\n open?: DialogRootProps[\"open\"];\n onOpenChange?: DialogRootProps[\"onOpenChange\"];\n /** Accessible name for the palette (dialog and command menu). */\n label?: string;\n /** Extra classes for the dialog panel (not the command root). */\n className?: string;\n}\n\n/**\n * A command palette in a modal — Pho's `Dialog` overlay (Base UI) around a\n * `Command.Root`, raised above center. We deliberately skip cmdk's own\n * `Command.Dialog` (Radix) so overlays stay on one primitive stack.\n *\n * List height springs via `AnimatedHeight` (same feel as the Card shell on\n * onboarding / invite) — the input row stays put while results resize.\n */\nfunction Dialog({\n open,\n onOpenChange,\n label,\n className,\n children,\n ...props\n}: CommandDialogProps) {\n return (\n <PhoDialog.Root open={open} onOpenChange={onOpenChange}>\n <PhoDialog.Portal>\n <PhoDialog.Backdrop />\n <PhoDialog.Popup\n aria-label={label}\n // Palette sits above center so the list grows downward from a\n // stable top edge instead of jumping around it.\n className={cn(\n \"top-[max(4rem,18vh)] max-w-xl translate-y-0 overflow-hidden p-0\",\n className,\n )}\n >\n {/* The popup is position: fixed; layout animations inside a fixed\n element need a layoutRoot to project against, or their\n measurements drift with the page scroll. */}\n <motion.div layoutRoot>\n <Root label={label} {...props}>\n {children}\n </Root>\n </motion.div>\n </PhoDialog.Popup>\n </PhoDialog.Portal>\n </PhoDialog.Root>\n );\n}\n\n/**\n * Command menu built on `cmdk` — a filterable list of actions driven from a\n * single input, keyboard-first. Compose inline (`Command.Root`) or as a\n * ⌘K-style modal palette (`Command.Dialog`, which owns the overlay).\n * Filtering is yours by default — filter in render so the rows' diff can\n * glide; pass `shouldFilter` to hand matching and ranking to cmdk (its\n * imperative reorder skips the animation).\n *\n * Rows share one layout via `Command.Item` `level` — idle\n * `item` → `subitem` → `subsubitem`, or flat `result` while searching.\n */\nexport const Command = {\n Root,\n InputGroup,\n Input,\n List,\n Empty,\n Group,\n Item,\n ItemIcon,\n ItemTitle,\n Separator,\n Loading,\n Dialog,\n};\n\n/** Re-export of cmdk's state selector hook (search, value, filtered counts). */\nexport { useCommandState };\n"],"mappings":"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"}
1
+ {"version":3,"file":"command-D5g49VqR.js","names":[],"sources":["../../src/components/command/command.tsx"],"sourcesContent":["import {\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n type ComponentProps,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { IconArrowUpRight, IconChevronLeft } from \"@tabler/icons-react\";\nimport { SPRING_SETTLE } from \"../../motion\";\nimport { Command as CommandPrimitive, useCommandState } from \"cmdk\";\nimport { LayoutGroup, motion, useReducedMotion } from \"motion/react\";\nimport { AnimatedHeight } from \"../../utils/animated-height\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveVariant, type VariantMap } from \"../../utils/resolve-variant\";\nimport { Dialog as PhoDialog } from \"../dialog\";\n\n/**\n * Spring for row moves (FLIP / shared-layout) — same feel as\n * `AnimatedHeight`: quick and critically damped, so rows glide to their new\n * slot without overshooting into neighbours.\n */\nconst ROW_MOVE_SPRING = SPRING_SETTLE;\n\nfunction Root({\n // Filtering is yours by default: filter in render (state above the\n // palette) so the rows' FLIP diff can glide survivors to their slots.\n // cmdk's built-in matcher reorders DOM imperatively — invisible to the\n // layout pass — so it is opt-in: pass `shouldFilter` to hand matching\n // and ranking back to cmdk at the cost of the animation.\n shouldFilter = false,\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive>) {\n // Namespace row layoutIds per palette instance — the docs page mounts the\n // inline demo and the dialog demo at once, with identical item values.\n const layoutNamespace = useId();\n return (\n <CommandPrimitive\n className={cn(\n \"bg-pho-primary text-pho-primary flex w-full flex-col overflow-hidden outline-none\",\n className,\n )}\n shouldFilter={shouldFilter}\n {...props}\n >\n <LayoutGroup id={layoutNamespace}>{children}</LayoutGroup>\n </CommandPrimitive>\n );\n}\n\n/**\n * The input row — a bottom hairline separates it from the list. Position\n * leading icons absolutely and pad the input (`pl-9`), mirroring\n * `Autocomplete.InputGroup`.\n */\nfunction InputGroup({ className, ...props }: ComponentProps<\"div\">) {\n return (\n <div\n className={cn(\n \"border-pho-secondary relative flex items-center border-b\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** SSR-safe layout effect (same pattern cmdk uses internally). */\nconst useIsomorphicLayoutEffect =\n typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nfunction assignRef<T>(ref: Ref<T> | undefined, value: T | null) {\n if (typeof ref === \"function\") ref(value);\n else if (ref) ref.current = value;\n}\n\nfunction Input({\n className,\n value,\n ref: consumerRef,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Input>) {\n const inputRef = useRef<HTMLInputElement>(null);\n const search = useCommandState((state) => state.search);\n\n // cmdk stays uncontrolled here on purpose. Its controlled path syncs the\n // `value` prop into the search store through a passive effect — one painted\n // frame late — so on that stale frame the old row is still \"selected\" while\n // the list has already reflowed, and the selection pill visibly rides it\n // before snapping to the re-selected first row. Uncontrolled keystrokes\n // update search + first-row selection synchronously (pre-paint), killing\n // that frame in both directions (typing and clearing).\n //\n // The consumer-facing API is still controlled: external `value` changes\n // (programmatic reset, initial query) are replayed through the native input\n // path below so store, display, and selection take the same sync route.\n useIsomorphicLayoutEffect(() => {\n const input = inputRef.current;\n if (value == null || input == null || value === search) return;\n const setNativeValue = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n \"value\",\n )?.set;\n setNativeValue?.call(input, value);\n input.dispatchEvent(new Event(\"input\", { bubbles: true }));\n }, [value, search]);\n\n return (\n <CommandPrimitive.Input\n className={cn(\n // Borderless inside the palette surface — the InputGroup hairline\n // carries the edge. display-xs (18px) keeps iOS from zooming in.\n \"text-pho-primary placeholder:text-pho-placeholder text-display-xs w-full bg-transparent px-3 py-3 outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n ref={(node) => {\n inputRef.current = node;\n assignRef(consumerRef, node);\n }}\n />\n );\n}\n\nfunction List({\n className,\n children,\n ...props\n}: ComponentProps<typeof CommandPrimitive.List>) {\n return (\n // Same spring as the onboarding / invite Card shell — list height glides\n // when idle ↔ search (or filter) changes instead of jumping.\n <AnimatedHeight>\n {/* The scroller is a motion element with layoutScroll so the rows'\n FLIP projections account for its scroll offset — without it,\n scrolling reads as a layout change and every row glides to\n compensate. scroll-py keeps a breath above and below the row\n being scrolled into view. */}\n <motion.div\n layoutScroll\n className=\"max-h-[min(24rem,60vh)] scroll-py-1 overflow-y-auto overscroll-contain\"\n >\n <CommandPrimitive.List\n className={cn(\"relative isolate p-1\", className)}\n {...props}\n >\n {children}\n </CommandPrimitive.List>\n </motion.div>\n </AnimatedHeight>\n );\n}\n\nfunction Empty({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Empty>) {\n return (\n <CommandPrimitive.Empty\n className={cn(\n \"text-pho-description px-2.5 py-6 text-center text-base\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Group({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Group>) {\n return (\n <CommandPrimitive.Group\n className={cn(\n // cmdk renders the `heading` prop in a [cmdk-group-heading] wrapper —\n // typography mirrors `Autocomplete.GroupLabel`.\n \"[&_[cmdk-group-heading]]:text-pho-secondary [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Row layout mode:\n * - `item` / `subitem` / `subsubitem` — idle hierarchy (icon column + indent)\n * - `result` — flat search hit (breadcrumb + trailing scope)\n */\nexport type CommandItemLevel = \"item\" | \"subitem\" | \"subsubitem\" | \"result\";\nexport type CommandItemSize = \"sm\" | \"md\";\n\nconst ITEM_SIZES = {\n sm: {\n classes: \"gap-1.5 py-1 pr-2 text-sm\",\n description: \"Compact rows for filter lists and dense pickers\",\n },\n md: {\n classes: \"gap-2 py-2 pr-2.5 text-base\",\n description: \"Default palette row\",\n },\n} as const satisfies VariantMap;\n\nconst ITEM_TITLE_SIZES = {\n sm: { classes: \"text-sm\", description: \"Compact row title\" },\n md: { classes: \"text-md\", description: \"Default row title\" },\n} as const satisfies VariantMap;\n\nconst ITEM_ICON_SIZES = {\n sm: {\n classes: \"size-3.5 [&>svg]:size-3.5\",\n description: \"Compact leading glyph\",\n },\n md: {\n classes: \"size-4 [&>svg]:size-4\",\n description: \"Default leading glyph\",\n },\n} as const satisfies VariantMap;\n\ntype ItemPrimitiveProps = ComponentProps<typeof CommandPrimitive.Item>;\n\nexport interface CommandItemProps extends Omit<\n ItemPrimitiveProps,\n \"children\" | \"title\"\n> {\n /**\n * Row depth / mode in the palette:\n * - `item` — page / top destination (icon + title)\n * - `subitem` — section under an item (label aligns with the item title)\n * - `subsubitem` — row under a section (one step deeper)\n * - `result` — flat search hit (`title` + `path` crumbs + `scope`)\n */\n level?: CommandItemLevel;\n /**\n * Leading glyph. On idle `item` rows (and reserved for sub-levels). On\n * `result` rows, pass the resolved icon (self → parent → grandparent).\n */\n icon?: ReactNode;\n /**\n * When `level=\"result\"`, force the icon column so labels align across the\n * list even if this row's `icon` is empty. Set true when any sibling result\n * has an icon; omit when the whole result set is icon-less.\n */\n iconSlot?: boolean;\n /**\n * Row density. `sm` tightens padding and type for chip popovers\n * (Filter Bar options). Palette destinations stay `md`.\n * @default \"md\"\n */\n size?: CommandItemSize;\n /** Primary label. Prefer this over free-form children for the shared layout. */\n title?: ReactNode;\n /**\n * Ancestors after `title` for `level=\"result\"` — parent → page\n * (e.g. `[\"Agent profile\", \"Settings\"]` → `Name < Agent profile < Settings`).\n */\n path?: ReactNode[];\n /**\n * Trailing scope for `level=\"result\"` — `Project` vs `Personal`, not a nav group.\n */\n scope?: ReactNode;\n /** Shows a trailing external-link glyph (opens outside the app). */\n external?: boolean;\n /**\n * Free-form content. When `title` is set, rendered after the label stack.\n * When `title` is omitted, becomes the row body (legacy / simple items).\n */\n children?: ReactNode;\n}\n\n/** Leading icon column — `size-4` at `md`, tighter at `sm`. */\nfunction ItemIcon({\n className,\n size = \"md\",\n ...props\n}: ComponentProps<\"span\"> & { size?: CommandItemSize }) {\n return (\n <span\n className={cn(\n \"text-pho-secondary flex shrink-0 items-center justify-center\",\n resolveVariant(ITEM_ICON_SIZES, size),\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Primary label — medium + primary ink on `item` rows. */\nfunction ItemTitle({\n className,\n level = \"item\",\n size = \"md\",\n ...props\n}: ComponentProps<\"span\"> & {\n level?: CommandItemLevel;\n size?: CommandItemSize;\n}) {\n return (\n <span\n className={cn(\n \"block truncate\",\n resolveVariant(ITEM_TITLE_SIZES, size),\n level === \"item\" && \"text-pho-primary\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * One selectable row. Idle palettes use `level` + `icon` / `title`\n * (item → subitem → subsubitem). Searching uses `level=\"result\"` with `path`\n * crumbs and a trailing `scope` (Project / Personal). No description line —\n * match via `keywords` / aliases instead.\n */\nfunction ExternalGlyph() {\n return (\n <IconArrowUpRight\n aria-hidden\n className=\"text-pho-description size-4 shrink-0\"\n />\n );\n}\n\nfunction Item({\n className,\n level = \"item\",\n size = \"md\",\n icon,\n iconSlot,\n title,\n path,\n scope,\n external,\n children,\n value,\n ...props\n}: CommandItemProps) {\n const reduceMotion = useReducedMotion();\n // cmdk registers `value.trim()` and exposes the selected one as\n // `state.value` — mirrors cmdk's own `data-selected` computation.\n const trimmedValue = typeof value === \"string\" ? value.trim() : \"\";\n const selectedValue = useCommandState((state) => state.value);\n const isSelected = trimmedValue !== \"\" && selectedValue === trimmedValue;\n const structured = title != null;\n const isResult = level === \"result\";\n // Reserve the icon column when the row has an icon, or when the list asks\n // for alignment (`iconSlot`) even if this row's glyph is empty.\n const showResultIcon = isResult && (icon != null || iconSlot);\n\n const row = (\n <CommandPrimitive.Item\n data-level={level}\n data-size={size}\n value={value}\n className={cn(\n \"text-pho-secondary flex cursor-pointer items-center rounded-[calc(var(--radius-base)-4px)] outline-none select-none\",\n resolveVariant(ITEM_SIZES, size),\n // subsubitem steps in; item/subitem share the base gutter.\n level === \"subsubitem\" ? \"pl-6\" : \"pl-2\",\n // Secondary at rest; selection lifts to primary ink (Menu idiom).\n // The wash lands with it instantly — stepping through rows is a\n // snap, not a flight.\n \"data-[selected=true]:text-pho-primary data-[selected=true]:bg-pho-ghost-hover\",\n \"data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50\",\n className,\n )}\n {...props}\n >\n {structured && isResult ? (\n <>\n {showResultIcon ? (\n <ItemIcon size={size} aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n ) : null}\n {/* Same title size as idle ItemTitle so row height matches. */}\n <span\n className={cn(\n \"flex min-w-0 flex-1 items-center gap-1 overflow-hidden\",\n resolveVariant(ITEM_TITLE_SIZES, size),\n )}\n >\n <span className=\"text-pho-primary truncate\">{title}</span>\n {(path ?? []).map((segment, index) => (\n <span\n key={index}\n className=\"text-pho-description flex shrink-0 items-center gap-0.5\"\n >\n <IconChevronLeft aria-hidden className=\"size-4 shrink-0\" />\n {segment}\n </span>\n ))}\n </span>\n {scope != null && scope !== \"\" ? (\n <span className=\"text-pho-description shrink-0 text-xs\">\n {scope}\n </span>\n ) : null}\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : structured ? (\n <>\n {/* Icon column always reserved so subitem labels share the item title edge. */}\n <ItemIcon size={size} aria-hidden={icon == null ? true : undefined}>\n {icon ?? null}\n </ItemIcon>\n <span className=\"min-w-0 flex-1\">\n <ItemTitle level={level} size={size}>\n {title}\n </ItemTitle>\n </span>\n {external ? <ExternalGlyph /> : null}\n {children}\n </>\n ) : (\n children\n )}\n </CommandPrimitive.Item>\n );\n\n if (reduceMotion) return row;\n\n return (\n // FLIP wrapper: rows that stay mounted glide when neighbours enter or\n // leave, and a row remounting elsewhere with the same `value` (idle group\n // ↔ flat search result) inherits the old bounds via its layoutId and\n // slides to the new slot — the iOS list-diff feel. Rows without a match\n // simply appear / disappear so the whole list never swarms.\n //\n // The selected row is the exception: it skips the travel and appears at\n // its final slot immediately, so the selection wash is never sitting on\n // empty space waiting for its row to fly in.\n <motion.div\n layout=\"position\"\n layoutId={typeof value === \"string\" ? value : undefined}\n initial={false}\n transition={isSelected ? { duration: 0 } : ROW_MOVE_SPRING}\n >\n {row}\n </motion.div>\n );\n}\n\nfunction Separator({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Separator>) {\n return (\n <CommandPrimitive.Separator\n className={cn(\n \"-mx-1 my-1 h-px bg-[var(--border-color-pho-secondary)]\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Loading({\n className,\n ...props\n}: ComponentProps<typeof CommandPrimitive.Loading>) {\n return (\n <CommandPrimitive.Loading\n className={cn(\"text-pho-description px-2.5 py-1.5 text-base\", className)}\n {...props}\n />\n );\n}\n\ntype DialogRootProps = ComponentProps<typeof PhoDialog.Root>;\n\ninterface CommandDialogProps extends ComponentProps<typeof CommandPrimitive> {\n /** Controlled dialog state — pass straight through to `Dialog.Root`. */\n open?: DialogRootProps[\"open\"];\n onOpenChange?: DialogRootProps[\"onOpenChange\"];\n /** Accessible name for the palette (dialog and command menu). */\n label?: string;\n /** Extra classes for the dialog panel (not the command root). */\n className?: string;\n}\n\n/**\n * A command palette in a modal — Pho's `Dialog` overlay (Base UI) around a\n * `Command.Root`, raised above center. We deliberately skip cmdk's own\n * `Command.Dialog` (Radix) so overlays stay on one primitive stack.\n *\n * List height springs via `AnimatedHeight` (same feel as the Card shell on\n * onboarding / invite) — the input row stays put while results resize.\n */\nfunction Dialog({\n open,\n onOpenChange,\n label,\n className,\n children,\n ...props\n}: CommandDialogProps) {\n return (\n <PhoDialog.Root open={open} onOpenChange={onOpenChange}>\n <PhoDialog.Portal>\n <PhoDialog.Backdrop />\n <PhoDialog.Popup\n aria-label={label}\n // Palette sits above center so the list grows downward from a\n // stable top edge instead of jumping around it.\n className={cn(\n \"top-[max(4rem,18vh)] max-w-xl translate-y-0 overflow-hidden p-0\",\n className,\n )}\n >\n {/* The popup is position: fixed; layout animations inside a fixed\n element need a layoutRoot to project against, or their\n measurements drift with the page scroll. */}\n <motion.div layoutRoot>\n <Root label={label} {...props}>\n {children}\n </Root>\n </motion.div>\n </PhoDialog.Popup>\n </PhoDialog.Portal>\n </PhoDialog.Root>\n );\n}\n\n/**\n * Command menu built on `cmdk` — a filterable list of actions driven from a\n * single input, keyboard-first. Compose inline (`Command.Root`) or as a\n * ⌘K-style modal palette (`Command.Dialog`, which owns the overlay).\n * Filtering is yours by default — filter in render so the rows' diff can\n * glide; pass `shouldFilter` to hand matching and ranking to cmdk (its\n * imperative reorder skips the animation).\n *\n * Rows share one layout via `Command.Item` `level` — idle\n * `item` → `subitem` → `subsubitem`, or flat `result` while searching.\n */\nexport const Command = {\n Root,\n InputGroup,\n Input,\n List,\n Empty,\n Group,\n Item,\n ItemIcon,\n ItemTitle,\n Separator,\n Loading,\n Dialog,\n};\n\n/** Re-export of cmdk's state selector hook (search, value, filtered counts). */\nexport { useCommandState };\n"],"mappings":"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"}