UNPKG

@liveblocks/react-ui

Version:

A set of React pre-built components for the Liveblocks products. Liveblocks is the all-in-one toolkit to build collaborative products like Figma, Notion, and more.

189 lines (186 loc) 6.84 kB
import { jsx, jsxs } from 'react/jsx-runtime'; import { kInternal } from '@liveblocks/core'; import { useMemo, useCallback, forwardRef, Children } from 'react'; import '../_private/index.js'; import '../icons/index.js'; import { useOverrides } from '../overrides.js'; import { useAiToolInvocationContext } from '../primitives/AiMessage/contexts.js'; import { Root as CollapsibleRoot, Trigger as CollapsibleTrigger, Content as CollapsibleContent } from '../primitives/Collapsible/index.js'; import { cn } from '../utils/cn.js'; import { useSemiControllableState } from '../utils/use-controllable-state.js'; import { CodeBlock } from './internal/CodeBlock.js'; import { Button } from './internal/Button.js'; import { ChevronRightIcon } from '../icons/ChevronRight.js'; import { CheckCircleFillIcon } from '../icons/CheckCircleFill.js'; import { CrossCircleFillIcon } from '../icons/CrossCircleFill.js'; import { MinusCircleIcon } from '../icons/MinusCircle.js'; import { SpinnerIcon } from '../icons/Spinner.js'; function AiToolIcon({ className, ...props }) { return /* @__PURE__ */ jsx("div", { className: cn("lb-ai-tool-icon", className), ...props }); } function AiToolInspector({ className, ...props }) { const { args, partialArgs, result } = useAiToolInvocationContext(); return /* @__PURE__ */ jsxs("div", { className: cn("lb-ai-tool-inspector", className), ...props, children: [ /* @__PURE__ */ jsx(CodeBlock, { title: "Arguments", code: JSON.stringify(args ?? partialArgs, null, 2) }), result !== void 0 ? /* @__PURE__ */ jsx(CodeBlock, { title: "Result", code: JSON.stringify(result, null, 2) }) : null ] }); } function AiToolConfirmation({ children, variant = "default", confirm, cancel, overrides, className, ...props }) { const { stage, args, respond, name, invocationId } = useAiToolInvocationContext(); const $ = useOverrides(overrides); const enabled = stage === "executing"; const context = useMemo(() => ({ name, invocationId }), [name, invocationId]); const onConfirmClick = useCallback(async () => { if (enabled) { const result = await confirm(args, context); respond(result ?? void 0); } }, [enabled, args, confirm, respond, context]); const onCancelClick = useCallback(async () => { if (enabled) { if (cancel === void 0) { respond({ cancel: true }); } else { const result = await cancel(args, context); respond(result ?? void 0); } } }, [enabled, args, cancel, respond, context]); if (stage === "executed" && !children) { return null; } return /* @__PURE__ */ jsxs("div", { className: cn("lb-ai-tool-confirmation", className), ...props, children: [ children ? /* @__PURE__ */ jsx("div", { className: "lb-ai-tool-confirmation-content", children }) : null, stage !== "executed" && /* @__PURE__ */ jsx("div", { className: "lb-ai-tool-confirmation-footer", children: /* @__PURE__ */ jsxs("div", { className: "lb-ai-tool-confirmation-actions", children: [ /* @__PURE__ */ jsx(Button, { disabled: !enabled, onClick: onCancelClick, variant: "secondary", children: $.AI_TOOL_CONFIRMATION_CANCEL }), /* @__PURE__ */ jsx(Button, { disabled: !enabled, onClick: onConfirmClick, variant: variant === "destructive" ? "destructive" : "primary", children: $.AI_TOOL_CONFIRMATION_CONFIRM }) ] }) }) ] }); } function prettifyString(string) { return string.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim().toLowerCase().replace(/^\w/, (character) => character.toUpperCase()); } const AiTool = Object.assign( forwardRef( ({ children, title, icon, collapsible, collapsed, onCollapsedChange, className, ...props }, forwardedRef) => { const { stage, result, name, [kInternal]: { execute } } = useAiToolInvocationContext(); const [semiControlledCollapsed, onSemiControlledCollapsed] = useSemiControllableState(collapsed ?? false, onCollapsedChange); const hasContent = Children.count(children) > 0; const isCollapsible = hasContent ? collapsible ?? true : false; const resolvedTitle = useMemo(() => { return title ?? prettifyString(name); }, [title, name]); const handleCollapsibleOpenChange = useCallback( (open) => { onSemiControlledCollapsed(!open); }, [onSemiControlledCollapsed] ); return /* @__PURE__ */ jsxs(CollapsibleRoot, { ref: forwardedRef, className: cn("lb-collapsible lb-ai-tool", className), ...props, open: hasContent ? !semiControlledCollapsed : false, onOpenChange: handleCollapsibleOpenChange, disabled: !isCollapsible, "data-result": result?.type, "data-stage": stage, children: [ /* @__PURE__ */ jsxs(CollapsibleTrigger, { className: "lb-collapsible-trigger lb-ai-tool-header", children: [ icon ? /* @__PURE__ */ jsx("div", { className: "lb-ai-tool-header-icon-container", children: icon }) : null, /* @__PURE__ */ jsx("span", { className: "lb-ai-tool-header-title", children: resolvedTitle }), isCollapsible ? /* @__PURE__ */ jsx("span", { className: "lb-collapsible-chevron lb-icon-container", children: /* @__PURE__ */ jsx(ChevronRightIcon, {}) }) : null, /* @__PURE__ */ jsx("div", { className: "lb-ai-tool-header-status", children: stage === "executed" ? result.type === "success" ? /* @__PURE__ */ jsx(CheckCircleFillIcon, {}) : result.type === "error" ? /* @__PURE__ */ jsx(CrossCircleFillIcon, {}) : result.type === "cancelled" ? /* @__PURE__ */ jsx(MinusCircleIcon, {}) : null : execute !== void 0 ? /* @__PURE__ */ jsx(SpinnerIcon, {}) : null }) ] }), hasContent ? /* @__PURE__ */ jsx(CollapsibleContent, { className: "lb-collapsible-content lb-ai-tool-content-container", children: /* @__PURE__ */ jsx("div", { className: "lb-ai-tool-content", children }) }) : null ] }); } ), { Icon: AiToolIcon, Inspector: AiToolInspector, Confirmation: AiToolConfirmation } ); export { AiTool }; //# sourceMappingURL=AiTool.js.map