@pactor-app/ui 1.21.0 → 1.22.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.
@@ -2,7 +2,7 @@ import {
2
2
  Icon,
3
3
  Menu,
4
4
  Sidebar
5
- } from "./chunk-7WB4TS55.js";
5
+ } from "./chunk-44DAGWXZ.js";
6
6
  import {
7
7
  Alert,
8
8
  AlertDescription,
@@ -1611,6 +1611,7 @@ function Command2({
1611
1611
  import { useRenderer as useRenderer5 } from "@pactor-app/runtime";
1612
1612
  import { ArrowUp } from "lucide-react";
1613
1613
  import {
1614
+ isValidElement,
1614
1615
  useRef as useRef3,
1615
1616
  useState as useState10
1616
1617
  } from "react";
@@ -1625,6 +1626,7 @@ function ChatInput({
1625
1626
  toolbarEnd,
1626
1627
  header,
1627
1628
  footer,
1629
+ field,
1628
1630
  onChange,
1629
1631
  onSubmit,
1630
1632
  className,
@@ -1635,6 +1637,8 @@ function ChatInput({
1635
1637
  const [draft, setDraft] = useState10("");
1636
1638
  const text = controlled ? value : draft;
1637
1639
  const canSubmit = !disabled && text.trim() !== "";
1640
+ const customField = field !== void 0 && field !== null;
1641
+ const renderSlot = (slot) => isValidElement(slot) || typeof slot !== "object" || slot === null ? slot : renderChildren([slot]);
1638
1642
  const composingRef = useRef3(false);
1639
1643
  const handleChange = (next) => {
1640
1644
  if (!controlled) {
@@ -1670,8 +1674,8 @@ function ChatInput({
1670
1674
  ),
1671
1675
  style,
1672
1676
  children: [
1673
- header ? /* @__PURE__ */ jsx26("div", { className: "px-3 pt-3", children: renderChildren([header]) }) : null,
1674
- /* @__PURE__ */ jsx26(
1677
+ header ? /* @__PURE__ */ jsx26("div", { className: "px-3 pt-3", children: renderSlot(header) }) : null,
1678
+ customField ? field : /* @__PURE__ */ jsx26(
1675
1679
  Textarea,
1676
1680
  {
1677
1681
  value: text,
@@ -1686,9 +1690,9 @@ function ChatInput({
1686
1690
  }
1687
1691
  ),
1688
1692
  toolbarStart || toolbarEnd || !hideSend ? /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-1 px-2 pb-2", children: [
1689
- toolbarStart ? renderChildren([toolbarStart]) : null,
1693
+ toolbarStart ? renderSlot(toolbarStart) : null,
1690
1694
  /* @__PURE__ */ jsx26("span", { className: "flex-1" }),
1691
- toolbarEnd ? renderChildren([toolbarEnd]) : null,
1695
+ toolbarEnd ? renderSlot(toolbarEnd) : null,
1692
1696
  hideSend ? null : /* @__PURE__ */ jsx26(
1693
1697
  Button,
1694
1698
  {
@@ -1702,7 +1706,7 @@ function ChatInput({
1702
1706
  }
1703
1707
  )
1704
1708
  ] }) : null,
1705
- footer ? /* @__PURE__ */ jsx26("div", { className: "border-t border-border px-3 py-2", children: renderChildren([footer]) }) : null
1709
+ footer ? /* @__PURE__ */ jsx26("div", { className: "border-t border-border px-3 py-2", children: renderSlot(footer) }) : null
1706
1710
  ]
1707
1711
  }
1708
1712
  );
@@ -2138,7 +2142,8 @@ function DatePicker(props) {
2138
2142
  onSelect: handleRangeDaySelect,
2139
2143
  modifiers: rangeModifiers,
2140
2144
  modifiersClassNames: rangeModifierClassNames,
2141
- locale: dfLocale
2145
+ locale: dfLocale,
2146
+ showOutsideDays: false
2142
2147
  }
2143
2148
  )
2144
2149
  }
@@ -2152,7 +2157,8 @@ function DatePicker(props) {
2152
2157
  onSelect: handleRangeDaySelect,
2153
2158
  modifiers: rangeModifiers,
2154
2159
  modifiersClassNames: rangeModifierClassNames,
2155
- locale: dfLocale
2160
+ locale: dfLocale,
2161
+ showOutsideDays: false
2156
2162
  }
2157
2163
  ) })
2158
2164
  ] }) : /* @__PURE__ */ jsx31(
@@ -7557,7 +7563,14 @@ function ArtifactTreeRow({
7557
7563
  className: "flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm hover:bg-accent",
7558
7564
  onClick: () => setOpen((value) => !value),
7559
7565
  children: [
7560
- /* @__PURE__ */ jsx113("span", { className: "inline-flex transition-transform data-[open=true]:rotate-90", "data-open": open, children: /* @__PURE__ */ jsx113(Icon, { name: "chevron-right", size: 12 }) }),
7566
+ /* @__PURE__ */ jsx113(
7567
+ "span",
7568
+ {
7569
+ className: "inline-flex transition-transform data-[open=true]:rotate-90",
7570
+ "data-open": open,
7571
+ children: /* @__PURE__ */ jsx113(Icon, { name: "chevron-right", size: 12 })
7572
+ }
7573
+ ),
7561
7574
  /* @__PURE__ */ jsx113(Icon, { name: "folder", size: 13 }),
7562
7575
  /* @__PURE__ */ jsx113("span", { className: "min-w-0 flex-1 truncate", children: node.name })
7563
7576
  ]
@@ -7689,6 +7702,7 @@ function ArtifactPanel({
7689
7702
  icon: "download",
7690
7703
  variant: "text",
7691
7704
  tooltip: "\u4E0B\u8F7D\u4EA7\u7269",
7705
+ className: "px-2",
7692
7706
  onClick: () => onDownload ? onDownload(artifact) : void downloadArtifact(artifact)
7693
7707
  }
7694
7708
  ) : null,
@@ -7698,11 +7712,12 @@ function ArtifactPanel({
7698
7712
  icon: "x",
7699
7713
  variant: "text",
7700
7714
  tooltip: "\u6536\u8D77\u4EA7\u7269\u533A",
7715
+ className: "px-2",
7701
7716
  onClick: () => onClose?.()
7702
7717
  }
7703
7718
  )
7704
7719
  ] }),
7705
- /* @__PURE__ */ jsx113("div", { className: "min-h-0 flex-1 overflow-auto p-4", children: view === "list" && artifacts !== void 0 ? /* @__PURE__ */ jsx113(
7720
+ /* @__PURE__ */ jsx113("div", { className: "scrollbar-subtle min-h-0 flex-1 overflow-auto p-4", children: view === "list" && artifacts !== void 0 ? /* @__PURE__ */ jsx113(
7706
7721
  ArtifactListView,
7707
7722
  {
7708
7723
  nodes: buildArtifactTree(artifacts),
@@ -7873,7 +7888,7 @@ function Thinking({
7873
7888
  {
7874
7889
  "data-slot": "thinking",
7875
7890
  "data-status": status,
7876
- className: cn("w-full overflow-hidden rounded-md border border-border bg-muted/50", className),
7891
+ className: cn("w-full", className),
7877
7892
  style,
7878
7893
  children: [
7879
7894
  /* @__PURE__ */ jsxs82(
@@ -7882,12 +7897,12 @@ function Thinking({
7882
7897
  type: "button",
7883
7898
  "data-slot": "thinking-trigger",
7884
7899
  "aria-expanded": isExpanded,
7885
- className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm",
7900
+ className: "flex w-full cursor-pointer items-center gap-2 py-1 text-left text-sm",
7886
7901
  onClick: toggle,
7887
7902
  children: [
7888
7903
  /* @__PURE__ */ jsx118("span", { className: cn("text-muted-foreground", status === "thinking" && "animate-pulse motion-reduce:animate-none"), children: /* @__PURE__ */ jsx118(Icon, { name: "brain", size: "sm" }) }),
7889
- /* @__PURE__ */ jsx118("span", { "data-slot": "thinking-title", className: "flex-1 text-muted-foreground", children: resolvedTitle }),
7890
- /* @__PURE__ */ jsx118(Icon, { name: isExpanded ? "chevron-down" : "chevron-right", size: "sm" })
7904
+ /* @__PURE__ */ jsx118("span", { "data-slot": "thinking-title", className: "text-muted-foreground", children: resolvedTitle }),
7905
+ /* @__PURE__ */ jsx118("span", { className: "text-muted-foreground", children: /* @__PURE__ */ jsx118(Icon, { name: isExpanded ? "chevron-down" : "chevron-right", size: "sm" }) })
7891
7906
  ]
7892
7907
  }
7893
7908
  ),
@@ -7895,7 +7910,7 @@ function Thinking({
7895
7910
  "div",
7896
7911
  {
7897
7912
  "data-slot": "thinking-content",
7898
- className: "border-t border-border px-3 py-2 text-sm whitespace-pre-wrap text-muted-foreground",
7913
+ className: "py-1 pl-6 text-sm whitespace-pre-wrap text-muted-foreground",
7899
7914
  children: content
7900
7915
  }
7901
7916
  ) : null
@@ -7906,7 +7921,7 @@ function Thinking({
7906
7921
 
7907
7922
  // src/components/chat/ToolCall/index.tsx
7908
7923
  import { useState as useState40 } from "react";
7909
- import { jsx as jsx119, jsxs as jsxs83 } from "react/jsx-runtime";
7924
+ import { Fragment as Fragment11, jsx as jsx119, jsxs as jsxs83 } from "react/jsx-runtime";
7910
7925
  var statusIcon3 = {
7911
7926
  running: { icon: "loader-circle", className: "text-info", spin: true },
7912
7927
  done: { icon: "circle-check", className: "text-success" },
@@ -7925,42 +7940,51 @@ function ToolCall({ name, params, status = "done", result, durationMs, defaultEx
7925
7940
  const [expanded, setExpanded] = useState40(defaultExpanded ?? status === "running");
7926
7941
  const meta = statusIcon3[status];
7927
7942
  const paramsText = renderValue(params);
7943
+ const hasDetail = Boolean(paramsText) || Boolean(result);
7944
+ const headerInner = /* @__PURE__ */ jsxs83(Fragment11, { children: [
7945
+ /* @__PURE__ */ jsx119("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ jsx119(Icon, { name: "terminal", size: "sm" }) }),
7946
+ /* @__PURE__ */ jsx119("span", { "data-slot": "tool-call-name", className: "min-w-0 truncate font-medium", children: name ?? "\u5DE5\u5177\u8C03\u7528" }),
7947
+ /* @__PURE__ */ jsx119("span", { className: cn("shrink-0", meta.className, meta.spin && "animate-spin motion-reduce:animate-none"), children: /* @__PURE__ */ jsx119(Icon, { name: meta.icon, size: "sm" }) }),
7948
+ durationMs !== void 0 ? /* @__PURE__ */ jsxs83("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
7949
+ (durationMs / 1e3).toFixed(1),
7950
+ "s"
7951
+ ] }) : null,
7952
+ hasDetail ? /* @__PURE__ */ jsx119("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ jsx119(Icon, { name: expanded ? "chevron-down" : "chevron-right", size: "sm" }) }) : null
7953
+ ] });
7928
7954
  return /* @__PURE__ */ jsxs83(
7929
7955
  "div",
7930
7956
  {
7931
7957
  "data-slot": "tool-call",
7932
7958
  "data-status": status,
7933
- className: cn("w-full overflow-hidden rounded-md border border-border", className),
7959
+ className: cn("w-full", className),
7934
7960
  style,
7935
7961
  children: [
7936
- /* @__PURE__ */ jsxs83(
7962
+ hasDetail ? /* @__PURE__ */ jsx119(
7937
7963
  "button",
7938
7964
  {
7939
7965
  type: "button",
7940
7966
  "data-slot": "tool-call-trigger",
7941
7967
  "aria-expanded": expanded,
7942
- className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm",
7968
+ className: "flex w-full cursor-pointer items-center gap-2 py-1 text-left text-sm",
7943
7969
  onClick: () => setExpanded((value) => !value),
7944
- children: [
7945
- /* @__PURE__ */ jsx119("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ jsx119(Icon, { name: "terminal", size: "sm" }) }),
7946
- /* @__PURE__ */ jsx119("span", { "data-slot": "tool-call-name", className: "min-w-0 flex-1 truncate font-medium", children: name ?? "\u5DE5\u5177\u8C03\u7528" }),
7947
- /* @__PURE__ */ jsx119("span", { className: cn("shrink-0", meta.className, meta.spin && "animate-spin motion-reduce:animate-none"), children: /* @__PURE__ */ jsx119(Icon, { name: meta.icon, size: "sm" }) }),
7948
- durationMs !== void 0 ? /* @__PURE__ */ jsxs83("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
7949
- (durationMs / 1e3).toFixed(1),
7950
- "s"
7951
- ] }) : null,
7952
- /* @__PURE__ */ jsx119(Icon, { name: expanded ? "chevron-down" : "chevron-right", size: "sm" })
7953
- ]
7970
+ children: headerInner
7971
+ }
7972
+ ) : /* @__PURE__ */ jsx119(
7973
+ "div",
7974
+ {
7975
+ "data-slot": "tool-call-trigger",
7976
+ className: "flex w-full items-center gap-2 py-1 text-left text-sm",
7977
+ children: headerInner
7954
7978
  }
7955
7979
  ),
7956
- expanded ? /* @__PURE__ */ jsxs83("div", { "data-slot": "tool-call-body", className: "flex flex-col gap-2 border-t border-border px-3 py-2", children: [
7980
+ hasDetail && expanded ? /* @__PURE__ */ jsxs83("div", { "data-slot": "tool-call-body", className: "flex flex-col gap-2 py-1 pl-6", children: [
7957
7981
  paramsText ? /* @__PURE__ */ jsxs83("div", { children: [
7958
7982
  /* @__PURE__ */ jsx119("div", { className: "text-xs font-medium text-muted-foreground", children: "\u53C2\u6570" }),
7959
- /* @__PURE__ */ jsx119("pre", { "data-slot": "tool-call-params", className: "mt-1 overflow-x-auto rounded-sm bg-muted p-2 text-xs whitespace-pre-wrap", children: paramsText })
7983
+ /* @__PURE__ */ jsx119("pre", { "data-slot": "tool-call-params", className: "mt-1 overflow-x-auto text-xs whitespace-pre-wrap text-muted-foreground", children: paramsText })
7960
7984
  ] }) : null,
7961
7985
  result ? /* @__PURE__ */ jsxs83("div", { children: [
7962
7986
  /* @__PURE__ */ jsx119("div", { className: "text-xs font-medium text-muted-foreground", children: "\u7ED3\u679C" }),
7963
- /* @__PURE__ */ jsx119("pre", { "data-slot": "tool-call-result", className: "mt-1 overflow-x-auto rounded-sm bg-muted p-2 text-xs whitespace-pre-wrap", children: result })
7987
+ /* @__PURE__ */ jsx119("pre", { "data-slot": "tool-call-result", className: "mt-1 overflow-x-auto text-xs whitespace-pre-wrap text-muted-foreground", children: result })
7964
7988
  ] }) : null
7965
7989
  ] }) : null
7966
7990
  ]
@@ -7970,12 +7994,26 @@ function ToolCall({ name, params, status = "done", result, durationMs, defaultEx
7970
7994
 
7971
7995
  // src/components/chat/ChatMessage/index.tsx
7972
7996
  import { jsx as jsx120, jsxs as jsxs84 } from "react/jsx-runtime";
7973
- function PartView({ part, role }) {
7997
+ function PartView({
7998
+ part,
7999
+ role,
8000
+ onOpenArtifacts
8001
+ }) {
8002
+ if (role === "system" && (part.type === "text" || part.type === "markdown")) {
8003
+ return /* @__PURE__ */ jsx120(
8004
+ "div",
8005
+ {
8006
+ "data-slot": "chat-message-system-part",
8007
+ className: "w-full text-center text-xs text-muted-foreground",
8008
+ children: part.type === "markdown" ? /* @__PURE__ */ jsx120(MarkdownDslComponent, { content: part.content }) : part.content
8009
+ }
8010
+ );
8011
+ }
7974
8012
  switch (part.type) {
7975
8013
  case "text":
7976
8014
  return /* @__PURE__ */ jsx120(Bubble2, { align: role === "user" ? "end" : "start", variant: role === "user" ? "default" : "muted", children: /* @__PURE__ */ jsx120("span", { className: "text-sm whitespace-pre-wrap", children: part.content }) });
7977
8015
  case "markdown":
7978
- return /* @__PURE__ */ jsx120(Bubble2, { align: role === "user" ? "end" : "start", variant: role === "user" ? "default" : "ghost", children: /* @__PURE__ */ jsx120(MarkdownDslComponent, { content: part.content, className: "text-sm" }) });
8016
+ return /* @__PURE__ */ jsx120(Bubble2, { align: role === "user" ? "end" : "start", variant: role === "user" ? "default" : "ghost", children: /* @__PURE__ */ jsx120(MarkdownDslComponent, { content: part.content }) });
7979
8017
  case "thinking":
7980
8018
  return /* @__PURE__ */ jsx120(Thinking, { content: part.content, status: part.status ?? "done" });
7981
8019
  case "tool-call":
@@ -7983,10 +8021,31 @@ function PartView({ part, role }) {
7983
8021
  case "tool-result":
7984
8022
  return /* @__PURE__ */ jsx120("pre", { "data-slot": "chat-message-tool-result", className: "overflow-x-auto rounded-md bg-muted p-2 text-xs whitespace-pre-wrap", children: part.content });
7985
8023
  case "status":
7986
- return /* @__PURE__ */ jsxs84("div", { "data-slot": "chat-message-status", className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
8024
+ return /* @__PURE__ */ jsxs84("div", { "data-slot": "chat-message-status", className: "flex w-fit items-center gap-1.5 text-muted-foreground", children: [
7987
8025
  /* @__PURE__ */ jsx120(Icon, { name: "clock", size: "sm" }),
7988
8026
  part.text
7989
8027
  ] });
8028
+ case "artifacts": {
8029
+ const artifactsClass = "flex w-fit items-center gap-1.5 text-muted-foreground";
8030
+ const label = `\u5DF2\u751F\u6210 ${part.count} \u4E2A\u4EA7\u7269`;
8031
+ return onOpenArtifacts ? /* @__PURE__ */ jsxs84(
8032
+ "button",
8033
+ {
8034
+ type: "button",
8035
+ "data-slot": "chat-message-artifacts",
8036
+ className: cn(artifactsClass, "cursor-pointer hover:text-foreground"),
8037
+ onClick: onOpenArtifacts,
8038
+ children: [
8039
+ /* @__PURE__ */ jsx120(Icon, { name: "package", size: "sm" }),
8040
+ label,
8041
+ /* @__PURE__ */ jsx120(Icon, { name: "chevron-right", size: 12 })
8042
+ ]
8043
+ }
8044
+ ) : /* @__PURE__ */ jsxs84("div", { "data-slot": "chat-message-artifacts", className: artifactsClass, children: [
8045
+ /* @__PURE__ */ jsx120(Icon, { name: "package", size: "sm" }),
8046
+ label
8047
+ ] });
8048
+ }
7990
8049
  case "error":
7991
8050
  return /* @__PURE__ */ jsxs84("div", { "data-slot": "chat-message-error", className: "flex items-center gap-1.5 text-sm text-destructive", children: [
7992
8051
  /* @__PURE__ */ jsx120(Icon, { name: "circle-alert", size: "sm" }),
@@ -7996,19 +8055,31 @@ function PartView({ part, role }) {
7996
8055
  return null;
7997
8056
  }
7998
8057
  }
8058
+ var ACTION_ICON_BY_NAME = {
8059
+ copy: "copy",
8060
+ retry: "rotate-ccw",
8061
+ regenerate: "refresh-ccw",
8062
+ edit: "pencil",
8063
+ like: "thumbs-up",
8064
+ dislike: "thumbs-down",
8065
+ share: "share",
8066
+ delete: "trash"
8067
+ };
7999
8068
  function ChatMessage({
8000
8069
  role = "assistant",
8001
8070
  parts = [],
8002
8071
  status = "completed",
8003
8072
  agent,
8004
8073
  time,
8005
- showSender = true,
8074
+ showSender = false,
8006
8075
  actions = [],
8007
8076
  onAction,
8077
+ onOpenArtifacts,
8008
8078
  className,
8009
8079
  style
8010
8080
  }) {
8011
8081
  const isUser = role === "user";
8082
+ const isSystem = role === "system";
8012
8083
  const senderName = isUser ? "\u6211" : agent?.name ?? "\u52A9\u624B";
8013
8084
  return /* @__PURE__ */ jsxs84(
8014
8085
  "div",
@@ -8016,10 +8087,16 @@ function ChatMessage({
8016
8087
  "data-slot": "chat-message",
8017
8088
  "data-role": role,
8018
8089
  "data-status": status,
8019
- className: cn("flex w-full flex-col gap-1.5", isUser && "items-end", className),
8090
+ className: cn(
8091
+ "flex w-full flex-col gap-1.5",
8092
+ isUser && "items-end",
8093
+ // system 居中弱提示(参考 @pactor-app/chat MessageBubble)
8094
+ isSystem && "items-center text-muted-foreground",
8095
+ className
8096
+ ),
8020
8097
  style,
8021
8098
  children: [
8022
- showSender && role !== "system" ? /* @__PURE__ */ jsx120(
8099
+ showSender ? /* @__PURE__ */ jsx120(
8023
8100
  Sender,
8024
8101
  {
8025
8102
  name: senderName,
@@ -8028,35 +8105,454 @@ function ChatMessage({
8028
8105
  align: isUser ? "end" : "start"
8029
8106
  }
8030
8107
  ) : null,
8031
- /* @__PURE__ */ jsxs84("div", { className: cn("flex min-w-0 w-full max-w-full flex-col gap-2", isUser && "items-end"), children: [
8032
- parts.map((part, index) => /* @__PURE__ */ jsx120(PartView, { part, role }, index)),
8108
+ /* @__PURE__ */ jsxs84("div", { className: cn("flex min-w-0 w-full max-w-full flex-col gap-2", isUser && "items-end", isSystem && "items-center"), children: [
8109
+ parts.map((part, index) => /* @__PURE__ */ jsx120(PartView, { part, role, onOpenArtifacts }, index)),
8033
8110
  status === "streaming" ? /* @__PURE__ */ jsx120(StreamingText, { content: "", streaming: true }) : null
8034
8111
  ] }),
8035
- actions.length > 0 && (status === "completed" || status === "error") ? /* @__PURE__ */ jsx120("div", { "data-slot": "chat-message-actions", className: "flex items-center gap-1", children: actions.map((action) => /* @__PURE__ */ jsxs84(
8036
- "button",
8037
- {
8038
- type: "button",
8039
- "data-slot": "chat-message-action",
8040
- "data-action": action.name,
8041
- className: "flex items-center gap-1 rounded-sm px-1.5 py-0.5 text-xs text-muted-foreground hover:bg-accent hover:text-foreground",
8042
- onClick: () => onAction?.(action.name),
8043
- children: [
8044
- action.icon ? /* @__PURE__ */ jsx120(Icon, { name: action.icon, size: "sm" }) : null,
8045
- action.label ?? action.name
8046
- ]
8047
- },
8048
- action.name
8049
- )) }) : null
8112
+ actions.length > 0 && (status === "completed" || status === "error") ? /* @__PURE__ */ jsx120("div", { "data-slot": "chat-message-actions", className: "flex items-center gap-1 mt-2", children: actions.map((action) => {
8113
+ const label = action.label ?? action.name;
8114
+ const iconName = action.icon ?? ACTION_ICON_BY_NAME[action.name];
8115
+ if (iconName) {
8116
+ return /* @__PURE__ */ jsx120(Tooltip2, { content: label, side: "top", children: /* @__PURE__ */ jsx120(
8117
+ "button",
8118
+ {
8119
+ type: "button",
8120
+ "data-slot": "chat-message-action",
8121
+ "data-action": action.name,
8122
+ "aria-label": label,
8123
+ className: "flex cursor-pointer items-center rounded-sm p-1 text-muted-foreground hover:bg-accent hover:text-foreground",
8124
+ onClick: () => onAction?.(action.name),
8125
+ children: /* @__PURE__ */ jsx120(Icon, { name: iconName, size: "sm" })
8126
+ }
8127
+ ) }, action.name);
8128
+ }
8129
+ return /* @__PURE__ */ jsx120(
8130
+ "button",
8131
+ {
8132
+ type: "button",
8133
+ "data-slot": "chat-message-action",
8134
+ "data-action": action.name,
8135
+ className: "flex items-center cursor-pointer gap-1 rounded-sm px-1.5 py-0.5 text-xs text-muted-foreground hover:bg-accent hover:text-foreground",
8136
+ onClick: () => onAction?.(action.name),
8137
+ children: label
8138
+ },
8139
+ action.name
8140
+ );
8141
+ }) }) : null
8050
8142
  ]
8051
8143
  }
8052
8144
  );
8053
8145
  }
8054
8146
 
8055
8147
  // src/components/chat/ChatPage/index.tsx
8056
- import { useState as useState42 } from "react";
8148
+ import { useRenderer as useRenderer18 } from "@pactor-app/runtime";
8149
+ import { isValidElement as isValidElement2, useState as useState44 } from "react";
8150
+
8151
+ // src/components/chat/Composer/index.tsx
8152
+ import {
8153
+ useRef as useRef9,
8154
+ useState as useState42
8155
+ } from "react";
8156
+
8157
+ // src/components/chat/Composer/mention-input.tsx
8158
+ import {
8159
+ forwardRef,
8160
+ useEffect as useEffect34,
8161
+ useImperativeHandle,
8162
+ useRef as useRef8,
8163
+ useState as useState41
8164
+ } from "react";
8165
+ import { renderToStaticMarkup } from "react-dom/server";
8166
+ import { Fragment as Fragment12, jsx as jsx121, jsxs as jsxs85 } from "react/jsx-runtime";
8167
+ var NBSP = "\xA0";
8168
+ var CHIP_ATTR = "data-mention-chip";
8169
+ function escapeRegExp(text) {
8170
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8171
+ }
8172
+ function isChipElement(node) {
8173
+ return node instanceof HTMLElement && node.hasAttribute(CHIP_ATTR);
8174
+ }
8175
+ function serializeNode(node) {
8176
+ let out = "";
8177
+ node.childNodes.forEach((child) => {
8178
+ if (child.nodeType === Node.TEXT_NODE) {
8179
+ out += (child.textContent ?? "").replace(/\u00A0/g, " ");
8180
+ } else if (isChipElement(child)) {
8181
+ out += `${child.dataset["trigger"] ?? ""}${child.dataset["label"] ?? ""}`;
8182
+ } else if (child instanceof HTMLBRElement) {
8183
+ out += "\n";
8184
+ } else if (child instanceof HTMLElement) {
8185
+ const inner = serializeNode(child).replace(/\n$/, "");
8186
+ out += (out === "" || out.endsWith("\n") ? "" : "\n") + inner + "\n";
8187
+ }
8188
+ });
8189
+ return out;
8190
+ }
8191
+ function collectChips(field) {
8192
+ return Array.from(field.querySelectorAll(`[${CHIP_ATTR}]`)).map((el) => ({
8193
+ id: el.dataset["id"] ?? "",
8194
+ label: el.dataset["label"] ?? "",
8195
+ trigger: el.dataset["trigger"] ?? ""
8196
+ }));
8197
+ }
8198
+ function detectActiveMention(field, sources) {
8199
+ const selection = window.getSelection();
8200
+ if (!selection || selection.rangeCount === 0 || !selection.isCollapsed) {
8201
+ return null;
8202
+ }
8203
+ const anchor = selection.anchorNode;
8204
+ if (!anchor || anchor.nodeType !== Node.TEXT_NODE || !field.contains(anchor)) {
8205
+ return null;
8206
+ }
8207
+ const caretOffset = selection.anchorOffset;
8208
+ const beforeCaret = (anchor.textContent ?? "").slice(0, caretOffset);
8209
+ for (const source of sources) {
8210
+ const trigger = source.trigger;
8211
+ const match = new RegExp(
8212
+ `(?:^|\\s)${escapeRegExp(trigger)}([^\\s${escapeRegExp(trigger)}]*)$`
8213
+ ).exec(beforeCaret);
8214
+ if (match) {
8215
+ const query = match[1] ?? "";
8216
+ return {
8217
+ source,
8218
+ query,
8219
+ node: anchor,
8220
+ triggerStart: caretOffset - query.length - trigger.length,
8221
+ caretOffset
8222
+ };
8223
+ }
8224
+ }
8225
+ return null;
8226
+ }
8227
+ function chipIcon(item, source) {
8228
+ return item.icon ?? source.icon ?? (source.trigger === "@" ? "user" : "file-text");
8229
+ }
8230
+ var MentionInput = forwardRef(
8231
+ function MentionInput2({
8232
+ value,
8233
+ placeholder,
8234
+ disabled,
8235
+ sources,
8236
+ chips,
8237
+ onChipsChange,
8238
+ onChange,
8239
+ onSubmit,
8240
+ className,
8241
+ style
8242
+ }, ref) {
8243
+ const fieldRef = useRef8(null);
8244
+ const [menu, setMenu] = useState41(null);
8245
+ const [empty, setEmpty] = useState41(true);
8246
+ const suppressSyncRef = useRef8(false);
8247
+ const composingRef = useRef8(false);
8248
+ const emitChips = () => {
8249
+ if (suppressSyncRef.current || !fieldRef.current) {
8250
+ return;
8251
+ }
8252
+ onChipsChange?.(collectChips(fieldRef.current));
8253
+ };
8254
+ const serialize = () => fieldRef.current ? serializeNode(fieldRef.current).replace(/\n$/, "") : "";
8255
+ const buildChipElement = (item, source) => {
8256
+ const chip = document.createElement("span");
8257
+ chip.setAttribute(CHIP_ATTR, "");
8258
+ chip.dataset["id"] = item.id;
8259
+ chip.dataset["label"] = item.label;
8260
+ chip.dataset["trigger"] = item.trigger ?? source.trigger;
8261
+ chip.contentEditable = "false";
8262
+ chip.className = "mx-0.5 inline-flex items-center gap-1 rounded-md bg-muted px-1.5 py-0.5 align-middle text-xs text-foreground";
8263
+ const iconMarkup = renderToStaticMarkup(
8264
+ /* @__PURE__ */ jsx121(Icon, { name: chipIcon(item, source), size: 12 })
8265
+ );
8266
+ const label = document.createElement("span");
8267
+ label.textContent = item.label;
8268
+ chip.innerHTML = iconMarkup;
8269
+ chip.appendChild(label);
8270
+ return chip;
8271
+ };
8272
+ const insertChipElement = (item, source, replace) => {
8273
+ const field = fieldRef.current;
8274
+ if (!field) {
8275
+ return;
8276
+ }
8277
+ const chip = buildChipElement(item, source);
8278
+ let caretNode;
8279
+ if (replace) {
8280
+ const { node, start, end } = replace;
8281
+ const text = node.textContent ?? "";
8282
+ node.textContent = text.slice(0, start);
8283
+ caretNode = document.createTextNode(`${NBSP}${text.slice(end)}`);
8284
+ node.after(chip, caretNode);
8285
+ } else {
8286
+ caretNode = document.createTextNode(NBSP);
8287
+ const selection2 = window.getSelection();
8288
+ if (selection2 && selection2.rangeCount > 0 && selection2.anchorNode !== null && field.contains(selection2.anchorNode)) {
8289
+ const range = selection2.getRangeAt(0);
8290
+ range.deleteContents();
8291
+ range.insertNode(caretNode);
8292
+ range.insertNode(chip);
8293
+ } else {
8294
+ field.append(chip, caretNode);
8295
+ }
8296
+ }
8297
+ const selection = window.getSelection();
8298
+ if (selection) {
8299
+ const range = document.createRange();
8300
+ range.setStart(caretNode, 1);
8301
+ range.collapse(true);
8302
+ selection.removeAllRanges();
8303
+ selection.addRange(range);
8304
+ }
8305
+ setEmpty(false);
8306
+ onChange?.(serialize());
8307
+ emitChips();
8308
+ };
8309
+ useImperativeHandle(ref, () => ({
8310
+ insertChip: (item, source) => {
8311
+ fieldRef.current?.focus();
8312
+ insertChipElement(item, source);
8313
+ },
8314
+ focus: () => fieldRef.current?.focus()
8315
+ }));
8316
+ useEffect34(() => {
8317
+ const field = fieldRef.current;
8318
+ if (field && value === "" && serializeNode(field).trim() !== "") {
8319
+ suppressSyncRef.current = true;
8320
+ field.innerHTML = "";
8321
+ setEmpty(true);
8322
+ setMenu(null);
8323
+ suppressSyncRef.current = false;
8324
+ }
8325
+ }, [value]);
8326
+ useEffect34(() => {
8327
+ const field = fieldRef.current;
8328
+ if (!field) {
8329
+ return;
8330
+ }
8331
+ const keep = new Set(chips.map((chip) => `${chip.trigger}:${chip.id}`));
8332
+ const stale = Array.from(field.querySelectorAll(`[${CHIP_ATTR}]`)).filter(
8333
+ (el) => !keep.has(
8334
+ `${el.dataset["trigger"]}:${el.dataset["id"]}`
8335
+ )
8336
+ );
8337
+ if (stale.length > 0) {
8338
+ suppressSyncRef.current = true;
8339
+ stale.forEach((el) => el.remove());
8340
+ suppressSyncRef.current = false;
8341
+ setEmpty(serializeNode(field).trim() === "");
8342
+ }
8343
+ }, [chips]);
8344
+ const closeMenu = () => setMenu(null);
8345
+ const filteredItems = (state) => state.query ? state.source.items.filter((item) => item.label.includes(state.query)) : state.source.items;
8346
+ const refreshMenu = () => {
8347
+ const field = fieldRef.current;
8348
+ if (!field) {
8349
+ return;
8350
+ }
8351
+ const active = detectActiveMention(field, sources);
8352
+ if (!active) {
8353
+ setMenu(null);
8354
+ return;
8355
+ }
8356
+ const range = document.createRange();
8357
+ range.setStart(active.node, active.triggerStart);
8358
+ range.setEnd(active.node, active.caretOffset);
8359
+ const rect = typeof range.getBoundingClientRect === "function" ? range.getBoundingClientRect() : field.getBoundingClientRect();
8360
+ setMenu((prev) => ({
8361
+ source: active.source,
8362
+ query: active.query,
8363
+ left: rect.left,
8364
+ top: rect.top,
8365
+ // 过滤结果变化后候选下标钳制在有效范围内(DSL 每次渲染产出新
8366
+ // props 对象,source 按 trigger 比较而非引用)
8367
+ activeIndex: Math.min(
8368
+ prev?.source.trigger === active.source.trigger ? prev.activeIndex : 0,
8369
+ Math.max(filteredItems({ source: active.source, query: active.query, left: 0, top: 0, activeIndex: 0 }).length - 1, 0)
8370
+ )
8371
+ }));
8372
+ };
8373
+ const selectMenuItem = (item) => {
8374
+ const field = fieldRef.current;
8375
+ if (!field || !menu) {
8376
+ return;
8377
+ }
8378
+ const active = detectActiveMention(field, sources);
8379
+ insertChipElement(
8380
+ { ...item, trigger: item.trigger ?? menu.source.trigger },
8381
+ menu.source,
8382
+ active && active.source.trigger === menu.source.trigger ? { node: active.node, start: active.triggerStart, end: active.caretOffset } : void 0
8383
+ );
8384
+ setMenu(null);
8385
+ };
8386
+ const handleInput = () => {
8387
+ const field = fieldRef.current;
8388
+ if (!field) {
8389
+ return;
8390
+ }
8391
+ if ((field.textContent ?? "") === "" && field.querySelector(`[${CHIP_ATTR}]`) === null) {
8392
+ field.innerHTML = "";
8393
+ }
8394
+ setEmpty(serializeNode(field).trim() === "");
8395
+ onChange?.(serialize());
8396
+ refreshMenu();
8397
+ };
8398
+ const handleKeyDown = (event) => {
8399
+ if (menu) {
8400
+ const items = filteredItems(menu);
8401
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
8402
+ event.preventDefault();
8403
+ if (items.length > 0) {
8404
+ const delta = event.key === "ArrowDown" ? 1 : -1;
8405
+ setMenu({
8406
+ ...menu,
8407
+ activeIndex: (menu.activeIndex + delta + items.length) % items.length
8408
+ });
8409
+ }
8410
+ return;
8411
+ }
8412
+ if (event.key === "Enter" && !composingRef.current && !event.nativeEvent.isComposing) {
8413
+ event.preventDefault();
8414
+ const item = items[Math.min(menu.activeIndex, items.length - 1)];
8415
+ if (item) {
8416
+ selectMenuItem(item);
8417
+ } else {
8418
+ closeMenu();
8419
+ }
8420
+ return;
8421
+ }
8422
+ if (event.key === "Escape") {
8423
+ event.preventDefault();
8424
+ closeMenu();
8425
+ return;
8426
+ }
8427
+ }
8428
+ if (event.key === "Enter" && !event.shiftKey && !composingRef.current && !event.nativeEvent.isComposing) {
8429
+ event.preventDefault();
8430
+ const text = serialize();
8431
+ if (text.trim() !== "" && !disabled) {
8432
+ onSubmit?.(text);
8433
+ }
8434
+ return;
8435
+ }
8436
+ if (event.key === "Backspace") {
8437
+ const selection = window.getSelection();
8438
+ const field = fieldRef.current;
8439
+ if (!selection || !selection.isCollapsed || !field) {
8440
+ return;
8441
+ }
8442
+ let chip = null;
8443
+ const anchor = selection.anchorNode;
8444
+ if (anchor === field && selection.anchorOffset > 0) {
8445
+ const before = field.childNodes[selection.anchorOffset - 1];
8446
+ if (isChipElement(before)) {
8447
+ chip = before;
8448
+ }
8449
+ } else if (anchor?.nodeType === Node.TEXT_NODE && selection.anchorOffset === 0) {
8450
+ if (isChipElement(anchor.previousSibling)) {
8451
+ chip = anchor.previousSibling;
8452
+ }
8453
+ }
8454
+ if (chip) {
8455
+ event.preventDefault();
8456
+ chip.remove();
8457
+ onChange?.(serialize());
8458
+ emitChips();
8459
+ setEmpty(serializeNode(field).trim() === "");
8460
+ }
8461
+ }
8462
+ };
8463
+ const menuItems = menu ? filteredItems(menu) : [];
8464
+ const activeIndex = Math.min(menu?.activeIndex ?? 0, Math.max(menuItems.length - 1, 0));
8465
+ return /* @__PURE__ */ jsxs85("div", { className: "relative", children: [
8466
+ /* @__PURE__ */ jsx121(
8467
+ "div",
8468
+ {
8469
+ ref: fieldRef,
8470
+ "data-slot": "mention-input",
8471
+ role: "textbox",
8472
+ "aria-multiline": "true",
8473
+ "aria-placeholder": placeholder,
8474
+ contentEditable: !disabled,
8475
+ suppressContentEditableWarning: true,
8476
+ className: cn(
8477
+ "min-h-[60px] w-full px-4 pt-3 pb-1 text-sm whitespace-pre-wrap break-words outline-none",
8478
+ className
8479
+ ),
8480
+ style,
8481
+ onInput: handleInput,
8482
+ onKeyDown: handleKeyDown,
8483
+ onCompositionStart: () => {
8484
+ composingRef.current = true;
8485
+ },
8486
+ onCompositionEnd: () => {
8487
+ composingRef.current = false;
8488
+ },
8489
+ onPaste: (event) => {
8490
+ event.preventDefault();
8491
+ const text = event.clipboardData?.getData("text/plain") ?? "";
8492
+ if (text) {
8493
+ document.execCommand("insertText", false, text);
8494
+ }
8495
+ }
8496
+ }
8497
+ ),
8498
+ empty && placeholder !== void 0 ? /* @__PURE__ */ jsx121("span", { className: "pointer-events-none absolute top-3 left-4 text-sm text-muted-foreground", children: placeholder }) : null,
8499
+ menu ? /* @__PURE__ */ jsxs85(Fragment12, { children: [
8500
+ /* @__PURE__ */ jsx121(
8501
+ "div",
8502
+ {
8503
+ className: "fixed inset-0 z-40",
8504
+ onMouseDown: (event) => {
8505
+ event.preventDefault();
8506
+ closeMenu();
8507
+ }
8508
+ }
8509
+ ),
8510
+ /* @__PURE__ */ jsxs85(
8511
+ "div",
8512
+ {
8513
+ "data-slot": "mention-menu",
8514
+ role: "listbox",
8515
+ className: "scrollbar-subtle fixed z-50 max-h-72 w-64 overflow-y-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md",
8516
+ style: {
8517
+ left: menu.left,
8518
+ bottom: typeof window === "undefined" ? void 0 : window.innerHeight - menu.top + 6
8519
+ },
8520
+ children: [
8521
+ /* @__PURE__ */ jsx121("div", { className: "px-2 py-1 text-xs text-muted-foreground", children: menu.source.label }),
8522
+ menuItems.length === 0 ? /* @__PURE__ */ jsx121("div", { className: "px-2 py-2 text-xs text-muted-foreground", children: "\u65E0\u5339\u914D\u9879" }) : menuItems.map((item, index) => /* @__PURE__ */ jsxs85(
8523
+ "button",
8524
+ {
8525
+ type: "button",
8526
+ role: "option",
8527
+ "aria-selected": index === activeIndex,
8528
+ className: cn(
8529
+ "flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm",
8530
+ index === activeIndex ? "bg-accent" : "hover:bg-accent"
8531
+ ),
8532
+ onMouseDown: (event) => {
8533
+ event.preventDefault();
8534
+ selectMenuItem(item);
8535
+ },
8536
+ children: [
8537
+ /* @__PURE__ */ jsx121(Icon, { name: chipIcon(item, menu.source), size: "sm" }),
8538
+ /* @__PURE__ */ jsx121("span", { className: "min-w-0 flex-1 truncate", children: item.label })
8539
+ ]
8540
+ },
8541
+ item.id
8542
+ ))
8543
+ ]
8544
+ }
8545
+ )
8546
+ ] }) : null
8547
+ ] });
8548
+ }
8549
+ );
8057
8550
 
8058
8551
  // src/components/chat/Composer/index.tsx
8059
- import { jsx as jsx121, jsxs as jsxs85 } from "react/jsx-runtime";
8552
+ import { Fragment as Fragment13, jsx as jsx122, jsxs as jsxs86 } from "react/jsx-runtime";
8553
+ var toolButtonClass3 = "flex cursor-pointer items-center rounded-md p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground";
8554
+ var popoverPanelClass = "absolute bottom-full left-0 z-50 mb-2 max-h-72 w-64 overflow-y-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md";
8555
+ var popoverItemClass = "flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm hover:bg-accent";
8060
8556
  function Composer({
8061
8557
  value,
8062
8558
  placeholder,
@@ -8066,33 +8562,236 @@ function Composer({
8066
8562
  attachments = [],
8067
8563
  onRemoveAttachment,
8068
8564
  onRetryAttachment,
8565
+ onAttachFiles,
8069
8566
  onChange,
8070
8567
  onSubmit,
8568
+ models,
8569
+ model,
8570
+ onModelChange,
8571
+ contexts,
8572
+ contextItems,
8573
+ onContextItemsChange,
8574
+ footer,
8071
8575
  className,
8072
8576
  style
8073
8577
  }) {
8074
- return /* @__PURE__ */ jsxs85("div", { "data-slot": "composer", className: cn("flex w-full flex-col gap-2", className), style, children: [
8075
- attachments.length > 0 ? /* @__PURE__ */ jsx121(Attachment, { items: attachments, onRemove: onRemoveAttachment, onRetry: onRetryAttachment }) : null,
8076
- /* @__PURE__ */ jsx121(
8077
- ChatInput,
8578
+ const textControlled = value !== void 0;
8579
+ const [innerText, setInnerText] = useState42("");
8580
+ const text = textControlled ? value : innerText;
8581
+ const [dragOver, setDragOver] = useState42(false);
8582
+ const [plusOpen, setPlusOpen] = useState42(false);
8583
+ const [modelOpen, setModelOpen] = useState42(false);
8584
+ const fileInputRef = useRef9(null);
8585
+ const mentionRef = useRef9(null);
8586
+ const sources = contexts ?? [];
8587
+ const rich = sources.length > 0;
8588
+ const plusSources = sources.filter((s) => s.trigger === "+");
8589
+ const plusEnabled = plusSources.length > 0;
8590
+ const modelEnabled = models !== void 0 && models.length > 0;
8591
+ const currentModel = models?.find((m) => m.value === model) ?? models?.[0];
8592
+ const chips = contextItems ?? [];
8593
+ const closePopovers = () => {
8594
+ setPlusOpen(false);
8595
+ setModelOpen(false);
8596
+ };
8597
+ const handleChange = (next) => {
8598
+ if (!textControlled) {
8599
+ setInnerText(next);
8600
+ }
8601
+ onChange?.(next);
8602
+ };
8603
+ const handleSubmit = (submitted) => {
8604
+ onSubmit?.(submitted);
8605
+ if (!textControlled) {
8606
+ setInnerText("");
8607
+ }
8608
+ closePopovers();
8609
+ };
8610
+ const selectContext = (item, source) => {
8611
+ if (rich) {
8612
+ mentionRef.current?.insertChip(item, source);
8613
+ } else {
8614
+ const chip = { ...item, trigger: item.trigger ?? source.trigger };
8615
+ const duplicated = chips.some(
8616
+ (existing) => existing.id === chip.id && existing.trigger === chip.trigger
8617
+ );
8618
+ if (!duplicated) {
8619
+ onContextItemsChange?.([...chips, chip]);
8620
+ }
8621
+ }
8622
+ closePopovers();
8623
+ };
8624
+ const emitFiles = (files) => {
8625
+ if (files.length > 0 && onAttachFiles) {
8626
+ onAttachFiles(files);
8627
+ }
8628
+ };
8629
+ const handleDrop = (event) => {
8630
+ if (!onAttachFiles) {
8631
+ return;
8632
+ }
8633
+ event.preventDefault();
8634
+ setDragOver(false);
8635
+ emitFiles(Array.from(event.dataTransfer?.files ?? []));
8636
+ };
8637
+ const toolbarStart = plusEnabled || onAttachFiles ? /* @__PURE__ */ jsxs86(Fragment13, { children: [
8638
+ plusEnabled ? /* @__PURE__ */ jsx122(
8639
+ "button",
8078
8640
  {
8079
- value,
8080
- placeholder,
8081
- disabled: disabled || loading,
8082
- rows,
8083
- onChange,
8084
- onSubmit
8641
+ type: "button",
8642
+ "aria-label": "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
8643
+ title: "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
8644
+ className: toolButtonClass3,
8645
+ onClick: () => {
8646
+ setPlusOpen((prev) => !prev);
8647
+ setModelOpen(false);
8648
+ },
8649
+ children: /* @__PURE__ */ jsx122(Icon, { name: "plus", size: "sm" })
8085
8650
  }
8086
- )
8087
- ] });
8651
+ ) : null,
8652
+ onAttachFiles ? /* @__PURE__ */ jsx122(
8653
+ "button",
8654
+ {
8655
+ type: "button",
8656
+ "aria-label": "\u6DFB\u52A0\u9644\u4EF6",
8657
+ title: "\u6DFB\u52A0\u9644\u4EF6",
8658
+ className: toolButtonClass3,
8659
+ onClick: () => fileInputRef.current?.click(),
8660
+ children: /* @__PURE__ */ jsx122(Icon, { name: "paperclip", size: "sm" })
8661
+ }
8662
+ ) : null
8663
+ ] }) : void 0;
8664
+ const toolbarEnd = modelEnabled ? /* @__PURE__ */ jsxs86(
8665
+ "button",
8666
+ {
8667
+ type: "button",
8668
+ "aria-label": "\u9009\u62E9\u6A21\u578B",
8669
+ title: "\u9009\u62E9\u6A21\u578B",
8670
+ className: "flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-foreground",
8671
+ onClick: () => {
8672
+ setModelOpen((prev) => !prev);
8673
+ setPlusOpen(false);
8674
+ },
8675
+ children: [
8676
+ currentModel?.label,
8677
+ /* @__PURE__ */ jsx122(Icon, { name: "chevrons-up-down", size: 12 })
8678
+ ]
8679
+ }
8680
+ ) : void 0;
8681
+ const activePopover = plusOpen ? "plus" : modelOpen ? "model" : null;
8682
+ return /* @__PURE__ */ jsxs86(
8683
+ "div",
8684
+ {
8685
+ "data-slot": "composer",
8686
+ className: cn("relative flex w-full flex-col gap-2", className),
8687
+ style,
8688
+ onDragOver: (event) => {
8689
+ if (onAttachFiles) {
8690
+ event.preventDefault();
8691
+ setDragOver(true);
8692
+ }
8693
+ },
8694
+ onDragLeave: () => setDragOver(false),
8695
+ onDrop: handleDrop,
8696
+ onPaste: (event) => {
8697
+ const files = Array.from(event.clipboardData?.files ?? []);
8698
+ if (files.length > 0 && onAttachFiles) {
8699
+ event.preventDefault();
8700
+ emitFiles(files);
8701
+ }
8702
+ },
8703
+ children: [
8704
+ attachments.length > 0 ? /* @__PURE__ */ jsx122(Attachment, { items: attachments, onRemove: onRemoveAttachment, onRetry: onRetryAttachment }) : null,
8705
+ /* @__PURE__ */ jsx122("div", { className: cn(dragOver && "rounded-xl ring-2 ring-ring/50"), children: /* @__PURE__ */ jsx122(
8706
+ ChatInput,
8707
+ {
8708
+ value: text,
8709
+ placeholder,
8710
+ disabled: disabled || loading,
8711
+ rows,
8712
+ toolbarStart,
8713
+ toolbarEnd,
8714
+ footer,
8715
+ field: rich ? /* @__PURE__ */ jsx122(
8716
+ MentionInput,
8717
+ {
8718
+ ref: mentionRef,
8719
+ value: text,
8720
+ placeholder,
8721
+ disabled: disabled || loading,
8722
+ sources,
8723
+ chips,
8724
+ onChipsChange: onContextItemsChange,
8725
+ onChange: handleChange,
8726
+ onSubmit: handleSubmit
8727
+ }
8728
+ ) : void 0,
8729
+ onChange: handleChange,
8730
+ onSubmit: handleSubmit
8731
+ }
8732
+ ) }),
8733
+ onAttachFiles ? /* @__PURE__ */ jsx122(
8734
+ "input",
8735
+ {
8736
+ ref: fileInputRef,
8737
+ type: "file",
8738
+ multiple: true,
8739
+ hidden: true,
8740
+ onChange: (event) => {
8741
+ emitFiles(Array.from(event.target.files ?? []));
8742
+ event.target.value = "";
8743
+ }
8744
+ }
8745
+ ) : null,
8746
+ activePopover !== null ? /* @__PURE__ */ jsxs86(Fragment13, { children: [
8747
+ /* @__PURE__ */ jsx122("div", { className: "fixed inset-0 z-40", onClick: closePopovers }),
8748
+ activePopover === "model" ? /* @__PURE__ */ jsx122("div", { "data-slot": "composer-model-popover", className: cn(popoverPanelClass, "right-0 left-auto w-48"), role: "listbox", children: models.map((option) => /* @__PURE__ */ jsxs86(
8749
+ "button",
8750
+ {
8751
+ type: "button",
8752
+ role: "option",
8753
+ "aria-selected": option.value === currentModel?.value,
8754
+ className: popoverItemClass,
8755
+ onClick: () => {
8756
+ onModelChange?.(option.value);
8757
+ closePopovers();
8758
+ },
8759
+ children: [
8760
+ /* @__PURE__ */ jsx122("span", { className: "min-w-0 flex-1 truncate", children: option.label }),
8761
+ option.value === currentModel?.value ? /* @__PURE__ */ jsx122(Icon, { name: "check", size: 14 }) : null
8762
+ ]
8763
+ },
8764
+ option.value
8765
+ )) }) : /* @__PURE__ */ jsx122("div", { "data-slot": "composer-context-popover", className: popoverPanelClass, role: "listbox", children: plusSources.map(
8766
+ (source) => source.items.length === 0 ? null : /* @__PURE__ */ jsxs86("div", { children: [
8767
+ /* @__PURE__ */ jsx122("div", { className: "px-2 py-1 text-xs text-muted-foreground", children: source.label }),
8768
+ source.items.map((item) => /* @__PURE__ */ jsxs86(
8769
+ "button",
8770
+ {
8771
+ type: "button",
8772
+ className: popoverItemClass,
8773
+ onClick: () => selectContext(item, source),
8774
+ children: [
8775
+ /* @__PURE__ */ jsx122(Icon, { name: item.icon ?? source.icon ?? "file-text", size: "sm" }),
8776
+ /* @__PURE__ */ jsx122("span", { className: "min-w-0 flex-1 truncate", children: item.label })
8777
+ ]
8778
+ },
8779
+ item.id
8780
+ ))
8781
+ ] }, source.trigger)
8782
+ ) })
8783
+ ] }) : null
8784
+ ]
8785
+ }
8786
+ );
8088
8787
  }
8089
8788
 
8090
8789
  // src/components/chat/ConversationList/index.tsx
8091
- import { useMemo as useMemo6, useState as useState41 } from "react";
8092
- import { jsx as jsx122, jsxs as jsxs86 } from "react/jsx-runtime";
8790
+ import { useMemo as useMemo6, useState as useState43 } from "react";
8791
+ import { jsx as jsx123, jsxs as jsxs87 } from "react/jsx-runtime";
8093
8792
  function ConversationList({ items = [], activeId, searchable, onSelect, onDelete, className, style }) {
8094
- const [innerActive, setInnerActive] = useState41();
8095
- const [keyword, setKeyword] = useState41("");
8793
+ const [innerActive, setInnerActive] = useState43();
8794
+ const [keyword, setKeyword] = useState43("");
8096
8795
  const active = activeId ?? innerActive;
8097
8796
  const filtered = useMemo6(() => {
8098
8797
  const query = keyword.trim().toLowerCase();
@@ -8107,10 +8806,10 @@ function ConversationList({ items = [], activeId, searchable, onSelect, onDelete
8107
8806
  }
8108
8807
  onSelect?.(id);
8109
8808
  };
8110
- return /* @__PURE__ */ jsxs86("div", { "data-slot": "conversation-list", className: cn("flex w-full flex-col gap-1", className), style, children: [
8111
- searchable ? /* @__PURE__ */ jsxs86("div", { className: "relative mb-1", children: [
8112
- /* @__PURE__ */ jsx122("span", { className: "absolute top-1/2 left-2 -translate-y-1/2 text-muted-foreground", children: /* @__PURE__ */ jsx122(Icon, { name: "search", size: "sm" }) }),
8113
- /* @__PURE__ */ jsx122(
8809
+ return /* @__PURE__ */ jsxs87("div", { "data-slot": "conversation-list", className: cn("flex w-full flex-col gap-1", className), style, children: [
8810
+ searchable ? /* @__PURE__ */ jsxs87("div", { className: "relative mb-1", children: [
8811
+ /* @__PURE__ */ jsx123("span", { className: "absolute top-1/2 left-2 -translate-y-1/2 text-muted-foreground", children: /* @__PURE__ */ jsx123(Icon, { name: "search", size: "sm" }) }),
8812
+ /* @__PURE__ */ jsx123(
8114
8813
  "input",
8115
8814
  {
8116
8815
  "data-slot": "conversation-list-search",
@@ -8121,7 +8820,7 @@ function ConversationList({ items = [], activeId, searchable, onSelect, onDelete
8121
8820
  }
8122
8821
  )
8123
8822
  ] }) : null,
8124
- filtered.map((item) => /* @__PURE__ */ jsxs86(
8823
+ filtered.map((item) => /* @__PURE__ */ jsxs87(
8125
8824
  "div",
8126
8825
  {
8127
8826
  "data-slot": "conversation-list-item",
@@ -8132,12 +8831,12 @@ function ConversationList({ items = [], activeId, searchable, onSelect, onDelete
8132
8831
  ),
8133
8832
  onClick: () => select(item.id),
8134
8833
  children: [
8135
- /* @__PURE__ */ jsxs86("div", { className: "min-w-0 flex-1", children: [
8136
- /* @__PURE__ */ jsx122("div", { className: cn("truncate text-sm", item.id === active && "font-medium"), children: item.title }),
8137
- item.description ? /* @__PURE__ */ jsx122("div", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null
8834
+ /* @__PURE__ */ jsxs87("div", { className: "min-w-0 flex-1", children: [
8835
+ /* @__PURE__ */ jsx123("div", { className: cn("truncate text-sm", item.id === active && "font-medium"), children: item.title }),
8836
+ item.description ? /* @__PURE__ */ jsx123("div", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null
8138
8837
  ] }),
8139
- item.time ? /* @__PURE__ */ jsx122("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.time }) : null,
8140
- onDelete ? /* @__PURE__ */ jsx122(
8838
+ item.time ? /* @__PURE__ */ jsx123("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.time }) : null,
8839
+ onDelete ? /* @__PURE__ */ jsx123(
8141
8840
  "button",
8142
8841
  {
8143
8842
  type: "button",
@@ -8148,41 +8847,42 @@ function ConversationList({ items = [], activeId, searchable, onSelect, onDelete
8148
8847
  event.stopPropagation();
8149
8848
  onDelete(item.id);
8150
8849
  },
8151
- children: /* @__PURE__ */ jsx122(Icon, { name: "trash-2", size: "sm" })
8850
+ children: /* @__PURE__ */ jsx123(Icon, { name: "trash-2", size: "sm" })
8152
8851
  }
8153
8852
  ) : null
8154
8853
  ]
8155
8854
  },
8156
8855
  item.id
8157
8856
  )),
8158
- filtered.length === 0 ? /* @__PURE__ */ jsx122("div", { className: "px-2 py-4 text-center text-sm text-muted-foreground", children: "\u65E0\u5339\u914D\u4F1A\u8BDD" }) : null
8857
+ filtered.length === 0 ? /* @__PURE__ */ jsx123("div", { className: "px-2 py-4 text-center text-sm text-muted-foreground", children: "\u65E0\u5339\u914D\u4F1A\u8BDD" }) : null
8159
8858
  ] });
8160
8859
  }
8161
8860
 
8162
8861
  // src/components/chat/MessageList/index.tsx
8163
- import { useEffect as useEffect34, useRef as useRef8 } from "react";
8164
- import { jsx as jsx123 } from "react/jsx-runtime";
8165
- function MessageList({ messages = [], autoScroll = true, onAction, className, style }) {
8166
- const listRef = useRef8(null);
8167
- useEffect34(() => {
8862
+ import { useEffect as useEffect35, useRef as useRef10 } from "react";
8863
+ import { jsx as jsx124 } from "react/jsx-runtime";
8864
+ function MessageList({ messages = [], autoScroll = true, onAction, onOpenArtifacts, className, style }) {
8865
+ const listRef = useRef10(null);
8866
+ useEffect35(() => {
8168
8867
  if (!autoScroll) return;
8169
8868
  const el = listRef.current;
8170
8869
  if (el) {
8171
8870
  el.scrollTop = el.scrollHeight;
8172
8871
  }
8173
8872
  }, [messages, autoScroll]);
8174
- return /* @__PURE__ */ jsx123(
8873
+ return /* @__PURE__ */ jsx124(
8175
8874
  "div",
8176
8875
  {
8177
8876
  ref: listRef,
8178
8877
  "data-slot": "message-list",
8179
8878
  className: cn("flex w-full flex-col gap-4 overflow-y-auto", className),
8180
8879
  style,
8181
- children: messages.map((message, index) => /* @__PURE__ */ jsx123(
8880
+ children: messages.map((message, index) => /* @__PURE__ */ jsx124(
8182
8881
  ChatMessage,
8183
8882
  {
8184
8883
  ...message,
8185
- onAction: (action) => onAction?.({ id: message.id, action })
8884
+ onAction: (action) => onAction?.({ id: message.id, action }),
8885
+ onOpenArtifacts: onOpenArtifacts ? () => onOpenArtifacts({ id: message.id }) : void 0
8186
8886
  },
8187
8887
  message.id ?? index
8188
8888
  ))
@@ -8191,9 +8891,9 @@ function MessageList({ messages = [], autoScroll = true, onAction, className, st
8191
8891
  }
8192
8892
 
8193
8893
  // src/components/chat/Prompt/index.tsx
8194
- import { jsx as jsx124, jsxs as jsxs87 } from "react/jsx-runtime";
8894
+ import { jsx as jsx125, jsxs as jsxs88 } from "react/jsx-runtime";
8195
8895
  function Prompt({ title, description, icon, value, disabled, onSelect, className, style }) {
8196
- return /* @__PURE__ */ jsxs87(
8896
+ return /* @__PURE__ */ jsxs88(
8197
8897
  "button",
8198
8898
  {
8199
8899
  type: "button",
@@ -8206,10 +8906,10 @@ function Prompt({ title, description, icon, value, disabled, onSelect, className
8206
8906
  style,
8207
8907
  onClick: () => onSelect?.(value ?? title ?? ""),
8208
8908
  children: [
8209
- icon ? /* @__PURE__ */ jsx124("span", { className: "mt-0.5 shrink-0 text-primary", children: /* @__PURE__ */ jsx124(Icon, { name: icon, size: "sm" }) }) : null,
8210
- /* @__PURE__ */ jsxs87("span", { className: "min-w-0", children: [
8211
- /* @__PURE__ */ jsx124("span", { "data-slot": "prompt-title", className: "block text-sm font-medium", children: title }),
8212
- description ? /* @__PURE__ */ jsx124("span", { "data-slot": "prompt-description", className: "mt-0.5 block text-xs text-muted-foreground", children: description }) : null
8909
+ icon ? /* @__PURE__ */ jsx125("span", { className: "mt-0.5 shrink-0 text-primary", children: /* @__PURE__ */ jsx125(Icon, { name: icon, size: "sm" }) }) : null,
8910
+ /* @__PURE__ */ jsxs88("span", { className: "min-w-0", children: [
8911
+ /* @__PURE__ */ jsx125("span", { "data-slot": "prompt-title", className: "block text-sm font-medium", children: title }),
8912
+ description ? /* @__PURE__ */ jsx125("span", { "data-slot": "prompt-description", className: "mt-0.5 block text-xs text-muted-foreground", children: description }) : null
8213
8913
  ] })
8214
8914
  ]
8215
8915
  }
@@ -8217,7 +8917,7 @@ function Prompt({ title, description, icon, value, disabled, onSelect, className
8217
8917
  }
8218
8918
 
8219
8919
  // src/components/chat/Welcome/index.tsx
8220
- import { jsx as jsx125, jsxs as jsxs88 } from "react/jsx-runtime";
8920
+ import { jsx as jsx126, jsxs as jsxs89 } from "react/jsx-runtime";
8221
8921
  function Welcome({
8222
8922
  title = "\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u4F60\uFF1F",
8223
8923
  description,
@@ -8227,19 +8927,19 @@ function Welcome({
8227
8927
  className,
8228
8928
  style
8229
8929
  }) {
8230
- return /* @__PURE__ */ jsxs88(
8930
+ return /* @__PURE__ */ jsxs89(
8231
8931
  "div",
8232
8932
  {
8233
8933
  "data-slot": "welcome",
8234
8934
  className: cn("flex w-full flex-col items-center gap-4 py-10 text-center", className),
8235
8935
  style,
8236
8936
  children: [
8237
- /* @__PURE__ */ jsx125("span", { "data-slot": "welcome-icon", className: "text-primary", children: /* @__PURE__ */ jsx125(Icon, { name: icon, size: "lg" }) }),
8238
- /* @__PURE__ */ jsxs88("div", { children: [
8239
- /* @__PURE__ */ jsx125("div", { "data-slot": "welcome-title", className: "text-xl font-semibold", children: title }),
8240
- description ? /* @__PURE__ */ jsx125("div", { "data-slot": "welcome-description", className: "mt-1 text-sm text-muted-foreground", children: description }) : null
8937
+ /* @__PURE__ */ jsx126("span", { "data-slot": "welcome-icon", className: "text-primary", children: /* @__PURE__ */ jsx126(Icon, { name: icon, size: "lg" }) }),
8938
+ /* @__PURE__ */ jsxs89("div", { children: [
8939
+ /* @__PURE__ */ jsx126("div", { "data-slot": "welcome-title", className: "text-xl font-semibold", children: title }),
8940
+ description ? /* @__PURE__ */ jsx126("div", { "data-slot": "welcome-description", className: "mt-1 text-sm text-muted-foreground", children: description }) : null
8241
8941
  ] }),
8242
- prompts.length > 0 ? /* @__PURE__ */ jsx125("div", { "data-slot": "welcome-prompts", className: "grid w-full max-w-xl grid-cols-1 gap-3 text-left sm:grid-cols-2", children: prompts.map((item, index) => /* @__PURE__ */ jsx125(
8942
+ prompts.length > 0 ? /* @__PURE__ */ jsx126("div", { "data-slot": "welcome-prompts", className: "grid w-full max-w-xl grid-cols-1 gap-3 text-left sm:grid-cols-2", children: prompts.map((item, index) => /* @__PURE__ */ jsx126(
8243
8943
  Prompt,
8244
8944
  {
8245
8945
  title: item.title,
@@ -8256,7 +8956,7 @@ function Welcome({
8256
8956
  }
8257
8957
 
8258
8958
  // src/components/chat/ChatPage/index.tsx
8259
- import { jsx as jsx126, jsxs as jsxs89 } from "react/jsx-runtime";
8959
+ import { jsx as jsx127, jsxs as jsxs90 } from "react/jsx-runtime";
8260
8960
  function ChatPage({
8261
8961
  brand,
8262
8962
  menuItems = [],
@@ -8282,12 +8982,26 @@ function ChatPage({
8282
8982
  defaultFooterSectionCollapsed = false,
8283
8983
  onFooterSectionToggle,
8284
8984
  conversationTitle,
8985
+ conversationHeaderAction,
8986
+ onConversationHeaderAction,
8285
8987
  messages = [],
8286
8988
  sending,
8287
8989
  composerPlaceholder,
8288
8990
  welcome,
8289
8991
  onSend,
8290
8992
  onMessageAction,
8993
+ models,
8994
+ model,
8995
+ onModelChange,
8996
+ contexts,
8997
+ contextItems,
8998
+ onContextItemsChange,
8999
+ attachments,
9000
+ onAttachFiles,
9001
+ onRemoveAttachment,
9002
+ onRetryAttachment,
9003
+ composerFooter,
9004
+ composerBottom,
8291
9005
  artifactTitle = "\u4EA7\u7269",
8292
9006
  artifacts = [],
8293
9007
  activeArtifactId,
@@ -8298,20 +9012,22 @@ function ChatPage({
8298
9012
  artifactViewers,
8299
9013
  onDownloadArtifact,
8300
9014
  artifactOpen,
8301
- defaultArtifactOpen = true,
9015
+ defaultArtifactOpen = false,
8302
9016
  onArtifactOpenChange,
8303
9017
  className,
8304
9018
  style
8305
9019
  }) {
8306
9020
  const controlled = artifactOpen !== void 0;
8307
- const [innerOpen, setInnerOpen] = useState42(defaultArtifactOpen);
9021
+ const [innerOpen, setInnerOpen] = useState44(defaultArtifactOpen);
8308
9022
  const open = controlled ? artifactOpen === true : innerOpen;
8309
9023
  const setOpen = (next) => {
8310
9024
  if (!controlled) setInnerOpen(next);
8311
9025
  onArtifactOpenChange?.(next);
8312
9026
  };
9027
+ const { renderChildren } = useRenderer18();
9028
+ const renderSlot = (slot) => isValidElement2(slot) || typeof slot !== "object" || slot === null ? slot : renderChildren([slot]);
8313
9029
  const convCollControlled = conversationSectionCollapsed !== void 0;
8314
- const [convCollapsedInner, setConvCollapsedInner] = useState42(
9030
+ const [convCollapsedInner, setConvCollapsedInner] = useState44(
8315
9031
  defaultConversationSectionCollapsed
8316
9032
  );
8317
9033
  const convCollapsed = convCollControlled ? conversationSectionCollapsed === true : convCollapsedInner;
@@ -8321,7 +9037,7 @@ function ChatPage({
8321
9037
  onConversationSectionToggle?.(next);
8322
9038
  };
8323
9039
  const footerCollControlled = footerSectionCollapsed !== void 0;
8324
- const [footerCollapsedInner, setFooterCollapsedInner] = useState42(
9040
+ const [footerCollapsedInner, setFooterCollapsedInner] = useState44(
8325
9041
  defaultFooterSectionCollapsed
8326
9042
  );
8327
9043
  const footerCollapsed = footerCollControlled ? footerSectionCollapsed === true : footerCollapsedInner;
@@ -8331,7 +9047,7 @@ function ChatPage({
8331
9047
  onFooterSectionToggle?.(next);
8332
9048
  };
8333
9049
  const railVisible = railItems.length > 0 || railFooterItems.length > 0;
8334
- const railButton = (item) => /* @__PURE__ */ jsx126(Tooltip2, { content: item.label, side: "right", children: /* @__PURE__ */ jsx126(
9050
+ const railButton = (item) => /* @__PURE__ */ jsx127(Tooltip2, { content: item.label, side: "right", children: /* @__PURE__ */ jsx127(
8335
9051
  Button2,
8336
9052
  {
8337
9053
  icon: item.icon,
@@ -8339,17 +9055,25 @@ function ChatPage({
8339
9055
  onClick: () => onMenuSelect?.(item.key)
8340
9056
  }
8341
9057
  ) }, item.key);
8342
- const chatArea = /* @__PURE__ */ jsxs89("div", { "data-slot": "chat-page-conversation", className: "flex h-full min-w-0 flex-1 flex-col", children: [
8343
- /* @__PURE__ */ jsxs89(
9058
+ const chatArea = /* @__PURE__ */ jsxs90("div", { "data-slot": "chat-page-conversation", className: "flex h-full min-w-0 flex-1 flex-col", children: [
9059
+ /* @__PURE__ */ jsxs90(
8344
9060
  "div",
8345
9061
  {
8346
9062
  className: "flex shrink-0 items-center justify-between border-b border-border px-4 py-2.5",
8347
9063
  children: [
8348
- /* @__PURE__ */ jsx126(Text, { text: conversationTitle, strong: true }),
8349
- /* @__PURE__ */ jsx126(Tooltip2, { content: artifactTitle, side: "bottom", children: /* @__PURE__ */ jsx126(
9064
+ /* @__PURE__ */ jsx127(Text, { text: conversationTitle, strong: true }),
9065
+ conversationHeaderAction ? /* @__PURE__ */ jsx127(Tooltip2, { content: conversationHeaderAction.tooltip ?? conversationHeaderAction.label, side: "bottom", children: /* @__PURE__ */ jsx127(
9066
+ Button2,
9067
+ {
9068
+ text: conversationHeaderAction.label,
9069
+ icon: conversationHeaderAction.icon,
9070
+ variant: "text",
9071
+ onClick: () => onConversationHeaderAction?.()
9072
+ }
9073
+ ) }) : /* @__PURE__ */ jsx127(Tooltip2, { content: open ? "\u6536\u8D77\u4EA7\u7269\u533A" : artifactTitle, side: "bottom", children: /* @__PURE__ */ jsx127(
8350
9074
  Button2,
8351
9075
  {
8352
- icon: "panel-right-open",
9076
+ icon: open ? "panel-right-close" : "panel-right-open",
8353
9077
  variant: "text",
8354
9078
  onClick: () => setOpen(!open)
8355
9079
  }
@@ -8357,40 +9081,63 @@ function ChatPage({
8357
9081
  ]
8358
9082
  }
8359
9083
  ),
8360
- messages.length === 0 ? /* @__PURE__ */ jsx126(
8361
- Welcome,
8362
- {
8363
- title: welcome?.title,
8364
- description: welcome?.description,
8365
- prompts: welcome?.prompts,
8366
- style: { flex: 1 },
8367
- onSelect: (value) => onSend?.(value)
8368
- }
8369
- ) : /* @__PURE__ */ jsx126(
8370
- MessageList,
8371
- {
8372
- messages,
8373
- style: { flex: 1, minHeight: 0, padding: 16 },
8374
- onAction: onMessageAction
8375
- }
8376
- ),
8377
- /* @__PURE__ */ jsx126(
8378
- Composer,
9084
+ /* @__PURE__ */ jsxs90(
9085
+ "div",
8379
9086
  {
8380
- placeholder: composerPlaceholder,
8381
- loading: sending,
8382
- style: { padding: 16, borderTop: "1px solid var(--border)", flexShrink: 0 },
8383
- onSubmit: (text) => onSend?.(text)
9087
+ "data-slot": "chat-page-conversation-body",
9088
+ className: "mx-auto flex min-h-0 w-[61.8cqw] max-w-full flex-1 flex-col",
9089
+ children: [
9090
+ messages.length === 0 ? /* @__PURE__ */ jsx127(
9091
+ Welcome,
9092
+ {
9093
+ title: welcome?.title,
9094
+ description: welcome?.description,
9095
+ prompts: welcome?.prompts,
9096
+ style: { flex: 1 },
9097
+ onSelect: (value) => onSend?.(value)
9098
+ }
9099
+ ) : /* @__PURE__ */ jsx127(
9100
+ MessageList,
9101
+ {
9102
+ messages,
9103
+ className: "scrollbar-subtle",
9104
+ style: { flex: 1, minHeight: 0, padding: 16 },
9105
+ onAction: onMessageAction,
9106
+ onOpenArtifacts: () => setOpen(true)
9107
+ }
9108
+ ),
9109
+ /* @__PURE__ */ jsx127(
9110
+ Composer,
9111
+ {
9112
+ placeholder: composerPlaceholder,
9113
+ loading: sending,
9114
+ models,
9115
+ model,
9116
+ contexts,
9117
+ contextItems,
9118
+ attachments,
9119
+ footer: composerFooter,
9120
+ style: { padding: 16, paddingBottom: composerBottom ? 8 : 16, flexShrink: 0 },
9121
+ onModelChange,
9122
+ onContextItemsChange,
9123
+ onAttachFiles,
9124
+ onRemoveAttachment,
9125
+ onRetryAttachment,
9126
+ onSubmit: (text) => onSend?.(text)
9127
+ }
9128
+ ),
9129
+ composerBottom ? /* @__PURE__ */ jsx127("div", { "data-slot": "chat-page-composer-bottom", className: "shrink-0 px-4 pb-2 text-center", children: renderSlot(composerBottom) }) : null
9130
+ ]
8384
9131
  }
8385
9132
  )
8386
9133
  ] });
8387
9134
  const activeArtifact = artifacts.find((item) => item.id === activeArtifactId) ?? (activeArtifactId === void 0 || activeArtifactId === "" ? artifacts[artifacts.length - 1] : void 0);
8388
- const artifactPanel = /* @__PURE__ */ jsx126(
9135
+ const artifactPanel = /* @__PURE__ */ jsx127(
8389
9136
  "div",
8390
9137
  {
8391
9138
  "data-slot": "chat-page-artifact",
8392
9139
  className: "flex h-full min-w-0 flex-col border-l border-border bg-muted",
8393
- children: /* @__PURE__ */ jsx126(
9140
+ children: /* @__PURE__ */ jsx127(
8394
9141
  ArtifactPanel,
8395
9142
  {
8396
9143
  artifact: activeArtifact,
@@ -8408,37 +9155,37 @@ function ChatPage({
8408
9155
  )
8409
9156
  }
8410
9157
  );
8411
- return /* @__PURE__ */ jsxs89(
9158
+ return /* @__PURE__ */ jsxs90(
8412
9159
  "div",
8413
9160
  {
8414
9161
  "data-slot": "chat-page",
8415
9162
  className: cn("flex w-full overflow-hidden", className),
8416
9163
  style: { height: "100vh", ...style },
8417
9164
  children: [
8418
- railVisible ? /* @__PURE__ */ jsxs89(
9165
+ railVisible ? /* @__PURE__ */ jsxs90(
8419
9166
  "div",
8420
9167
  {
8421
9168
  "data-slot": "chat-page-rail",
8422
9169
  className: "flex h-full w-[52px] shrink-0 flex-col items-center gap-1 border-r border-border py-2.5",
8423
9170
  children: [
8424
9171
  railItems.map(railButton),
8425
- /* @__PURE__ */ jsx126("div", { className: "flex-1" }),
9172
+ /* @__PURE__ */ jsx127("div", { className: "flex-1" }),
8426
9173
  railFooterItems.map(railButton)
8427
9174
  ]
8428
9175
  }
8429
9176
  ) : null,
8430
- /* @__PURE__ */ jsxs89(
9177
+ /* @__PURE__ */ jsxs90(
8431
9178
  "div",
8432
9179
  {
8433
9180
  "data-slot": "chat-page-menu",
8434
- className: "flex h-full w-[264px] shrink-0 flex-col gap-2 overflow-auto border-r border-border px-2 py-3",
9181
+ className: "flex h-full w-[264px] shrink-0 flex-col gap-2 overflow-hidden border-r border-border px-2 py-3",
8435
9182
  children: [
8436
- brand ? /* @__PURE__ */ jsxs89("div", { className: "flex items-center justify-between px-2", children: [
8437
- /* @__PURE__ */ jsxs89("div", { className: "flex flex-col gap-0.5", children: [
8438
- /* @__PURE__ */ jsx126(Text, { text: brand.title, strong: true, size: "large" }),
8439
- brand.version !== void 0 ? /* @__PURE__ */ jsx126(Text, { text: brand.version, type: "secondary", size: "small" }) : null
9183
+ brand ? /* @__PURE__ */ jsxs90("div", { className: "flex shrink-0 items-center justify-between px-2", children: [
9184
+ /* @__PURE__ */ jsxs90("div", { className: "flex flex-col gap-0.5", children: [
9185
+ /* @__PURE__ */ jsx127(Text, { text: brand.title, strong: true, size: "large" }),
9186
+ brand.version !== void 0 ? /* @__PURE__ */ jsx127(Text, { text: brand.version, type: "secondary", size: "small" }) : null
8440
9187
  ] }),
8441
- menuAction ? /* @__PURE__ */ jsx126(
9188
+ menuAction ? /* @__PURE__ */ jsx127(
8442
9189
  Button2,
8443
9190
  {
8444
9191
  text: menuAction.label,
@@ -8448,24 +9195,24 @@ function ChatPage({
8448
9195
  }
8449
9196
  ) : null
8450
9197
  ] }) : null,
8451
- /* @__PURE__ */ jsx126(
9198
+ /* @__PURE__ */ jsx127("div", { className: "scrollbar-subtle max-h-[40%] min-h-0 shrink-0 overflow-y-auto", children: /* @__PURE__ */ jsx127(
8452
9199
  Menu,
8453
9200
  {
8454
9201
  items: menuItems,
8455
9202
  selectedKey: activeMenuKey,
8456
9203
  onSelect: (key) => onMenuSelect?.(key)
8457
9204
  }
8458
- ),
8459
- conversationSectionTitle !== void 0 ? /* @__PURE__ */ jsxs89(
9205
+ ) }),
9206
+ conversationSectionTitle !== void 0 ? /* @__PURE__ */ jsxs90(
8460
9207
  "button",
8461
9208
  {
8462
9209
  type: "button",
8463
9210
  "data-slot": "chat-page-section-toggle",
8464
9211
  "aria-expanded": !convCollapsed,
8465
- className: "flex w-full cursor-pointer items-center justify-between px-2 pt-2",
9212
+ className: "flex w-full shrink-0 cursor-pointer items-center justify-between px-2 pt-2",
8466
9213
  onClick: toggleConvSection,
8467
9214
  children: [
8468
- /* @__PURE__ */ jsx126(
9215
+ /* @__PURE__ */ jsx127(
8469
9216
  Text,
8470
9217
  {
8471
9218
  text: `${conversationSectionTitle} (${conversations.length})`,
@@ -8474,48 +9221,50 @@ function ChatPage({
8474
9221
  strong: true
8475
9222
  }
8476
9223
  ),
8477
- /* @__PURE__ */ jsx126(Icon, { name: convCollapsed ? "chevron-right" : "chevron-down", size: 14 })
9224
+ /* @__PURE__ */ jsx127(Icon, { name: convCollapsed ? "chevron-right" : "chevron-down", size: 14 })
8478
9225
  ]
8479
9226
  }
8480
9227
  ) : null,
8481
- !convCollapsed ? /* @__PURE__ */ jsx126(
8482
- ConversationList,
8483
- {
8484
- items: conversations,
8485
- activeId: activeConversationId,
8486
- onSelect: (id) => onSelectConversation?.(id),
8487
- onDelete: (id) => onDeleteConversation?.(id)
8488
- }
8489
- ) : null,
8490
- !convCollapsed && moreLabel !== void 0 ? /* @__PURE__ */ jsx126("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx126(Button2, { text: `${moreLabel} >>`, variant: "link", size: "small", onClick: () => onMore?.() }) }) : null,
8491
- footerSectionTitle !== void 0 ? /* @__PURE__ */ jsxs89(
9228
+ !convCollapsed ? /* @__PURE__ */ jsxs90("div", { "data-slot": "chat-page-section-body", className: "scrollbar-subtle flex min-h-0 flex-1 flex-col overflow-y-auto", children: [
9229
+ /* @__PURE__ */ jsx127(
9230
+ ConversationList,
9231
+ {
9232
+ items: conversations,
9233
+ activeId: activeConversationId,
9234
+ onSelect: (id) => onSelectConversation?.(id),
9235
+ onDelete: (id) => onDeleteConversation?.(id)
9236
+ }
9237
+ ),
9238
+ moreLabel !== void 0 ? /* @__PURE__ */ jsx127("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx127(Button2, { text: `${moreLabel} >>`, variant: "link", size: "small", onClick: () => onMore?.() }) }) : null
9239
+ ] }) : null,
9240
+ footerSectionTitle !== void 0 ? /* @__PURE__ */ jsxs90(
8492
9241
  "button",
8493
9242
  {
8494
9243
  type: "button",
8495
9244
  "data-slot": "chat-page-section-toggle",
8496
9245
  "aria-expanded": !footerCollapsed,
8497
- className: "flex w-full cursor-pointer items-center justify-between px-2 pt-2",
9246
+ className: "flex w-full shrink-0 cursor-pointer items-center justify-between px-2 pt-2",
8498
9247
  onClick: toggleFooterSection,
8499
9248
  children: [
8500
- /* @__PURE__ */ jsx126(Text, { text: footerSectionTitle, type: "secondary", className: "text-sm", strong: true }),
8501
- /* @__PURE__ */ jsx126(Icon, { name: footerCollapsed ? "chevron-right" : "chevron-down", size: 14 })
9249
+ /* @__PURE__ */ jsx127(Text, { text: footerSectionTitle, type: "secondary", className: "text-sm", strong: true }),
9250
+ /* @__PURE__ */ jsx127(Icon, { name: footerCollapsed ? "chevron-right" : "chevron-down", size: 14 })
8502
9251
  ]
8503
9252
  }
8504
9253
  ) : null,
8505
- !footerCollapsed && footerItems.length > 0 ? /* @__PURE__ */ jsx126(
9254
+ !footerCollapsed && footerItems.length > 0 ? /* @__PURE__ */ jsx127("div", { "data-slot": "chat-page-section-body", className: "scrollbar-subtle min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx127(
8506
9255
  Menu,
8507
9256
  {
8508
9257
  items: footerItems,
8509
9258
  onSelect: (key) => onMenuSelect?.(key)
8510
9259
  }
8511
- ) : null
9260
+ ) }) : null
8512
9261
  ]
8513
9262
  }
8514
9263
  ),
8515
- /* @__PURE__ */ jsx126("div", { className: "h-full min-w-0 flex-1", children: open ? /* @__PURE__ */ jsxs89(PanelGroup, { orientation: "horizontal", style: { width: "100%", height: "100%" }, children: [
8516
- /* @__PURE__ */ jsx126(Panel, { defaultSize: "62%", children: chatArea }),
8517
- /* @__PURE__ */ jsx126(ResizableHandle, { withHandle: true }),
8518
- /* @__PURE__ */ jsx126(Panel, { defaultSize: "38%", minSize: "320px", maxSize: "760px", children: artifactPanel })
9264
+ /* @__PURE__ */ jsx127("div", { className: "@container h-full min-w-0 flex-1", children: open ? /* @__PURE__ */ jsxs90(PanelGroup, { orientation: "horizontal", style: { width: "100%", height: "100%" }, children: [
9265
+ /* @__PURE__ */ jsx127(Panel, { defaultSize: "62%", children: chatArea }),
9266
+ /* @__PURE__ */ jsx127(ResizableHandle, { withHandle: true }),
9267
+ /* @__PURE__ */ jsx127(Panel, { defaultSize: "38%", minSize: "380px", maxSize: "760px", children: artifactPanel })
8519
9268
  ] }) : chatArea })
8520
9269
  ]
8521
9270
  }
@@ -8523,10 +9272,10 @@ function ChatPage({
8523
9272
  }
8524
9273
 
8525
9274
  // src/components/chat/Citation/index.tsx
8526
- import { jsx as jsx127, jsxs as jsxs90 } from "react/jsx-runtime";
9275
+ import { jsx as jsx128, jsxs as jsxs91 } from "react/jsx-runtime";
8527
9276
  function Citation({ items = [], start = 1, className, style }) {
8528
- return /* @__PURE__ */ jsx127("span", { "data-slot": "citation", className: cn("inline-flex gap-1 align-super", className), style, children: items.map((item, index) => /* @__PURE__ */ jsxs90(HoverCard, { children: [
8529
- /* @__PURE__ */ jsxs90(
9277
+ return /* @__PURE__ */ jsx128("span", { "data-slot": "citation", className: cn("inline-flex gap-1 align-super", className), style, children: items.map((item, index) => /* @__PURE__ */ jsxs91(HoverCard, { children: [
9278
+ /* @__PURE__ */ jsxs91(
8530
9279
  HoverCardTrigger,
8531
9280
  {
8532
9281
  "data-slot": "citation-marker",
@@ -8538,10 +9287,10 @@ function Citation({ items = [], start = 1, className, style }) {
8538
9287
  ]
8539
9288
  }
8540
9289
  ),
8541
- /* @__PURE__ */ jsxs90(HoverCardContent, { "data-slot": "citation-card", className: "w-72", children: [
8542
- /* @__PURE__ */ jsx127("div", { className: "text-sm font-medium", children: item.title }),
8543
- item.snippet ? /* @__PURE__ */ jsx127("div", { className: "mt-1 line-clamp-3 text-xs text-muted-foreground", children: item.snippet }) : null,
8544
- item.url ? /* @__PURE__ */ jsx127(
9290
+ /* @__PURE__ */ jsxs91(HoverCardContent, { "data-slot": "citation-card", className: "w-72", children: [
9291
+ /* @__PURE__ */ jsx128("div", { className: "text-sm font-medium", children: item.title }),
9292
+ item.snippet ? /* @__PURE__ */ jsx128("div", { className: "mt-1 line-clamp-3 text-xs text-muted-foreground", children: item.snippet }) : null,
9293
+ item.url ? /* @__PURE__ */ jsx128(
8545
9294
  "a",
8546
9295
  {
8547
9296
  href: item.url,
@@ -8556,13 +9305,13 @@ function Citation({ items = [], start = 1, className, style }) {
8556
9305
  }
8557
9306
 
8558
9307
  // src/components/chat/Suggestion/index.tsx
8559
- import { jsx as jsx128, jsxs as jsxs91 } from "react/jsx-runtime";
9308
+ import { jsx as jsx129, jsxs as jsxs92 } from "react/jsx-runtime";
8560
9309
  function normalize(item) {
8561
9310
  if (typeof item === "string") return { label: item, value: item };
8562
9311
  return { label: item.label, value: item.value ?? item.label, icon: item.icon };
8563
9312
  }
8564
9313
  function Suggestion({ items = [], justify = "start", onSelect, className, style }) {
8565
- return /* @__PURE__ */ jsx128(
9314
+ return /* @__PURE__ */ jsx129(
8566
9315
  "div",
8567
9316
  {
8568
9317
  "data-slot": "suggestion",
@@ -8570,7 +9319,7 @@ function Suggestion({ items = [], justify = "start", onSelect, className, style
8570
9319
  style,
8571
9320
  children: items.map((item, index) => {
8572
9321
  const { label, value, icon } = normalize(item);
8573
- return /* @__PURE__ */ jsxs91(
9322
+ return /* @__PURE__ */ jsxs92(
8574
9323
  "button",
8575
9324
  {
8576
9325
  type: "button",
@@ -8579,7 +9328,7 @@ function Suggestion({ items = [], justify = "start", onSelect, className, style
8579
9328
  className: "flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-sm transition-colors hover:bg-accent",
8580
9329
  onClick: () => onSelect?.(value),
8581
9330
  children: [
8582
- icon ? /* @__PURE__ */ jsx128(Icon, { name: icon, size: "sm" }) : null,
9331
+ icon ? /* @__PURE__ */ jsx129(Icon, { name: icon, size: "sm" }) : null,
8583
9332
  label
8584
9333
  ]
8585
9334
  },
@@ -8591,7 +9340,7 @@ function Suggestion({ items = [], justify = "start", onSelect, className, style
8591
9340
  }
8592
9341
 
8593
9342
  // src/components/chart/EChartBase/index.tsx
8594
- import { useEffect as useEffect35, useRef as useRef9, useState as useState43 } from "react";
9343
+ import { useEffect as useEffect36, useRef as useRef11, useState as useState45 } from "react";
8595
9344
 
8596
9345
  // src/components/chart/echarts-modules.ts
8597
9346
  import * as echarts from "echarts/core";
@@ -8643,7 +9392,7 @@ echarts.use([
8643
9392
  ]);
8644
9393
 
8645
9394
  // src/components/chart/EChartBase/index.tsx
8646
- import { jsx as jsx129 } from "react/jsx-runtime";
9395
+ import { jsx as jsx130 } from "react/jsx-runtime";
8647
9396
  function EChartBase({
8648
9397
  option,
8649
9398
  height = 256,
@@ -8652,12 +9401,12 @@ function EChartBase({
8652
9401
  style,
8653
9402
  slot
8654
9403
  }) {
8655
- const hostRef = useRef9(null);
8656
- const chartRef = useRef9(null);
8657
- const onSelectRef = useRef9(onSelect);
9404
+ const hostRef = useRef11(null);
9405
+ const chartRef = useRef11(null);
9406
+ const onSelectRef = useRef11(onSelect);
8658
9407
  onSelectRef.current = onSelect;
8659
- const [failed, setFailed] = useState43(false);
8660
- useEffect35(() => {
9408
+ const [failed, setFailed] = useState45(false);
9409
+ useEffect36(() => {
8661
9410
  const host = hostRef.current;
8662
9411
  if (!host) return;
8663
9412
  let chart = null;
@@ -8684,14 +9433,14 @@ function EChartBase({
8684
9433
  chartRef.current = null;
8685
9434
  };
8686
9435
  }, []);
8687
- useEffect35(() => {
9436
+ useEffect36(() => {
8688
9437
  try {
8689
9438
  chartRef.current?.setOption(option, { notMerge: true });
8690
9439
  } catch {
8691
9440
  }
8692
9441
  }, [option]);
8693
9442
  if (failed) {
8694
- return /* @__PURE__ */ jsx129(
9443
+ return /* @__PURE__ */ jsx130(
8695
9444
  "div",
8696
9445
  {
8697
9446
  "data-slot": "chart-fallback",
@@ -8704,7 +9453,7 @@ function EChartBase({
8704
9453
  }
8705
9454
  );
8706
9455
  }
8707
- return /* @__PURE__ */ jsx129(
9456
+ return /* @__PURE__ */ jsx130(
8708
9457
  "div",
8709
9458
  {
8710
9459
  ref: hostRef,
@@ -9238,7 +9987,7 @@ function getChartTheme() {
9238
9987
  }
9239
9988
 
9240
9989
  // src/components/chart/AreaChart/index.tsx
9241
- import { jsx as jsx130 } from "react/jsx-runtime";
9990
+ import { jsx as jsx131 } from "react/jsx-runtime";
9242
9991
  function AreaChart({
9243
9992
  data = [],
9244
9993
  xKey,
@@ -9256,7 +10005,7 @@ function AreaChart({
9256
10005
  { data, xKey, yKeys, stacked, fillOpacity, colors, title },
9257
10006
  getChartTheme()
9258
10007
  );
9259
- return /* @__PURE__ */ jsx130(
10008
+ return /* @__PURE__ */ jsx131(
9260
10009
  EChartBase,
9261
10010
  {
9262
10011
  slot: "area-chart",
@@ -9270,7 +10019,7 @@ function AreaChart({
9270
10019
  }
9271
10020
 
9272
10021
  // src/components/chart/BarChart/index.tsx
9273
- import { jsx as jsx131 } from "react/jsx-runtime";
10022
+ import { jsx as jsx132 } from "react/jsx-runtime";
9274
10023
  function BarChart2({
9275
10024
  data = [],
9276
10025
  yKey,
@@ -9287,7 +10036,7 @@ function BarChart2({
9287
10036
  { data, yKey, yKeys: xKeys, stacked, colors, title },
9288
10037
  getChartTheme()
9289
10038
  );
9290
- return /* @__PURE__ */ jsx131(
10039
+ return /* @__PURE__ */ jsx132(
9291
10040
  EChartBase,
9292
10041
  {
9293
10042
  slot: "bar-chart",
@@ -9301,7 +10050,7 @@ function BarChart2({
9301
10050
  }
9302
10051
 
9303
10052
  // src/components/chart/BubbleChart/index.tsx
9304
- import { jsx as jsx132 } from "react/jsx-runtime";
10053
+ import { jsx as jsx133 } from "react/jsx-runtime";
9305
10054
  function BubbleChart({
9306
10055
  data = [],
9307
10056
  xKey,
@@ -9319,7 +10068,7 @@ function BubbleChart({
9319
10068
  { data, xKey, yKey, sizeKey, seriesKey, colors, title },
9320
10069
  getChartTheme()
9321
10070
  );
9322
- return /* @__PURE__ */ jsx132(
10071
+ return /* @__PURE__ */ jsx133(
9323
10072
  EChartBase,
9324
10073
  {
9325
10074
  slot: "bubble-chart",
@@ -9333,7 +10082,7 @@ function BubbleChart({
9333
10082
  }
9334
10083
 
9335
10084
  // src/components/chart/ColumnChart/index.tsx
9336
- import { jsx as jsx133 } from "react/jsx-runtime";
10085
+ import { jsx as jsx134 } from "react/jsx-runtime";
9337
10086
  function ColumnChart({
9338
10087
  data = [],
9339
10088
  xKey,
@@ -9350,7 +10099,7 @@ function ColumnChart({
9350
10099
  { data, xKey, yKeys, stacked, colors, title },
9351
10100
  getChartTheme()
9352
10101
  );
9353
- return /* @__PURE__ */ jsx133(
10102
+ return /* @__PURE__ */ jsx134(
9354
10103
  EChartBase,
9355
10104
  {
9356
10105
  slot: "column-chart",
@@ -9364,7 +10113,7 @@ function ColumnChart({
9364
10113
  }
9365
10114
 
9366
10115
  // src/components/chart/ComposedChart/index.tsx
9367
- import { jsx as jsx134 } from "react/jsx-runtime";
10116
+ import { jsx as jsx135 } from "react/jsx-runtime";
9368
10117
  function ComposedChart({
9369
10118
  data = [],
9370
10119
  xKey,
@@ -9380,7 +10129,7 @@ function ComposedChart({
9380
10129
  { data, xKey, series, colors, title },
9381
10130
  getChartTheme()
9382
10131
  );
9383
- return /* @__PURE__ */ jsx134(
10132
+ return /* @__PURE__ */ jsx135(
9384
10133
  EChartBase,
9385
10134
  {
9386
10135
  slot: "composed-chart",
@@ -9394,7 +10143,7 @@ function ComposedChart({
9394
10143
  }
9395
10144
 
9396
10145
  // src/components/chart/DonutChart/index.tsx
9397
- import { jsx as jsx135 } from "react/jsx-runtime";
10146
+ import { jsx as jsx136 } from "react/jsx-runtime";
9398
10147
  function DonutChart({
9399
10148
  data = [],
9400
10149
  nameKey,
@@ -9426,7 +10175,7 @@ function DonutChart({
9426
10175
  },
9427
10176
  getChartTheme()
9428
10177
  );
9429
- return /* @__PURE__ */ jsx135(
10178
+ return /* @__PURE__ */ jsx136(
9430
10179
  EChartBase,
9431
10180
  {
9432
10181
  slot: "donut-chart",
@@ -9440,7 +10189,7 @@ function DonutChart({
9440
10189
  }
9441
10190
 
9442
10191
  // src/components/chart/FunnelChart/index.tsx
9443
- import { jsx as jsx136 } from "react/jsx-runtime";
10192
+ import { jsx as jsx137 } from "react/jsx-runtime";
9444
10193
  function FunnelChart2({
9445
10194
  data = [],
9446
10195
  nameKey,
@@ -9457,7 +10206,7 @@ function FunnelChart2({
9457
10206
  { data, nameKey, valueKey, sort, colors, title },
9458
10207
  getChartTheme()
9459
10208
  );
9460
- return /* @__PURE__ */ jsx136(
10209
+ return /* @__PURE__ */ jsx137(
9461
10210
  EChartBase,
9462
10211
  {
9463
10212
  slot: "funnel-chart",
@@ -9471,7 +10220,7 @@ function FunnelChart2({
9471
10220
  }
9472
10221
 
9473
10222
  // src/components/chart/GaugeChart/index.tsx
9474
- import { jsx as jsx137 } from "react/jsx-runtime";
10223
+ import { jsx as jsx138 } from "react/jsx-runtime";
9475
10224
  function GaugeChart2({
9476
10225
  value = 0,
9477
10226
  min,
@@ -9488,7 +10237,7 @@ function GaugeChart2({
9488
10237
  { value, min, max, thresholds, unit, title },
9489
10238
  getChartTheme()
9490
10239
  );
9491
- return /* @__PURE__ */ jsx137(
10240
+ return /* @__PURE__ */ jsx138(
9492
10241
  EChartBase,
9493
10242
  {
9494
10243
  slot: "gauge-chart",
@@ -9502,7 +10251,7 @@ function GaugeChart2({
9502
10251
  }
9503
10252
 
9504
10253
  // src/components/chart/Heatmap/index.tsx
9505
- import { jsx as jsx138 } from "react/jsx-runtime";
10254
+ import { jsx as jsx139 } from "react/jsx-runtime";
9506
10255
  function Heatmap({
9507
10256
  data = [],
9508
10257
  xKey,
@@ -9518,7 +10267,7 @@ function Heatmap({
9518
10267
  { data, xKey, yKey, valueKey, title },
9519
10268
  getChartTheme()
9520
10269
  );
9521
- return /* @__PURE__ */ jsx138(
10270
+ return /* @__PURE__ */ jsx139(
9522
10271
  EChartBase,
9523
10272
  {
9524
10273
  slot: "heatmap",
@@ -9532,7 +10281,7 @@ function Heatmap({
9532
10281
  }
9533
10282
 
9534
10283
  // src/components/chart/LineChart/index.tsx
9535
- import { jsx as jsx139 } from "react/jsx-runtime";
10284
+ import { jsx as jsx140 } from "react/jsx-runtime";
9536
10285
  function LineChart2({
9537
10286
  data = [],
9538
10287
  xKey,
@@ -9551,7 +10300,7 @@ function LineChart2({
9551
10300
  { data, xKey, yKeys, smooth, showArea, stacked, colors, title },
9552
10301
  getChartTheme()
9553
10302
  );
9554
- return /* @__PURE__ */ jsx139(
10303
+ return /* @__PURE__ */ jsx140(
9555
10304
  EChartBase,
9556
10305
  {
9557
10306
  slot: "line-chart",
@@ -9565,8 +10314,8 @@ function LineChart2({
9565
10314
  }
9566
10315
 
9567
10316
  // src/components/chart/MapChart/index.tsx
9568
- import { useEffect as useEffect36, useState as useState44 } from "react";
9569
- import { jsx as jsx140 } from "react/jsx-runtime";
10317
+ import { useEffect as useEffect37, useState as useState46 } from "react";
10318
+ import { jsx as jsx141 } from "react/jsx-runtime";
9570
10319
  var fetchedMaps = /* @__PURE__ */ new Set();
9571
10320
  function hasRegisteredMap(mapName) {
9572
10321
  try {
@@ -9588,7 +10337,7 @@ function MapChart2({
9588
10337
  className,
9589
10338
  style
9590
10339
  }) {
9591
- const [loadState, setLoadState] = useState44(
10340
+ const [loadState, setLoadState] = useState46(
9592
10341
  () => geoJson || !geoJsonUrl || hasRegisteredMap(mapName) ? "idle" : "loading"
9593
10342
  );
9594
10343
  if (geoJson) {
@@ -9597,7 +10346,7 @@ function MapChart2({
9597
10346
  } catch {
9598
10347
  }
9599
10348
  }
9600
- useEffect36(() => {
10349
+ useEffect37(() => {
9601
10350
  if (geoJson || !geoJsonUrl || hasRegisteredMap(mapName) || fetchedMaps.has(mapName)) {
9602
10351
  setLoadState("idle");
9603
10352
  return;
@@ -9622,7 +10371,7 @@ function MapChart2({
9622
10371
  };
9623
10372
  }, [geoJson, geoJsonUrl, mapName]);
9624
10373
  if (geoJsonUrl && !geoJson && loadState === "loading") {
9625
- return /* @__PURE__ */ jsx140(
10374
+ return /* @__PURE__ */ jsx141(
9626
10375
  "div",
9627
10376
  {
9628
10377
  "data-slot": "map-chart-loading",
@@ -9632,7 +10381,7 @@ function MapChart2({
9632
10381
  );
9633
10382
  }
9634
10383
  if (!geoJson && loadState === "error") {
9635
- return /* @__PURE__ */ jsx140(
10384
+ return /* @__PURE__ */ jsx141(
9636
10385
  Empty2,
9637
10386
  {
9638
10387
  title: "\u5730\u56FE\u52A0\u8F7D\u5931\u8D25",
@@ -9644,7 +10393,7 @@ function MapChart2({
9644
10393
  }
9645
10394
  if (!geoJson && !hasRegisteredMap(mapName)) {
9646
10395
  console.warn(`[MapChart] \u5730\u56FE "${mapName}" \u672A\u6CE8\u518C\uFF1A\u8BF7\u4F20\u5165 geoJson / geoJsonUrl\uFF0C\u6216\u5728\u5E94\u7528\u542F\u52A8\u65F6 echarts.registerMap`);
9647
- return /* @__PURE__ */ jsx140(
10396
+ return /* @__PURE__ */ jsx141(
9648
10397
  Empty2,
9649
10398
  {
9650
10399
  title: "\u5730\u56FE\u672A\u6CE8\u518C",
@@ -9655,7 +10404,7 @@ function MapChart2({
9655
10404
  );
9656
10405
  }
9657
10406
  const option = buildMapOption({ mapName, data, nameKey, valueKey, title }, getChartTheme());
9658
- return /* @__PURE__ */ jsx140(
10407
+ return /* @__PURE__ */ jsx141(
9659
10408
  EChartBase,
9660
10409
  {
9661
10410
  slot: "map-chart",
@@ -9670,7 +10419,7 @@ function MapChart2({
9670
10419
 
9671
10420
  // src/components/chart/MetricCard/index.tsx
9672
10421
  import { ArrowDownRight, ArrowUpRight } from "lucide-react";
9673
- import { jsx as jsx141, jsxs as jsxs92 } from "react/jsx-runtime";
10422
+ import { jsx as jsx142, jsxs as jsxs93 } from "react/jsx-runtime";
9674
10423
  function MetricCard({
9675
10424
  title,
9676
10425
  value,
@@ -9683,15 +10432,15 @@ function MetricCard({
9683
10432
  }) {
9684
10433
  const showTrend = typeof trend === "number" && trend !== 0;
9685
10434
  const rising = (trend ?? 0) > 0;
9686
- return /* @__PURE__ */ jsxs92(
10435
+ return /* @__PURE__ */ jsxs93(
9687
10436
  "div",
9688
10437
  {
9689
10438
  "data-slot": "metric-card",
9690
10439
  className: cn("rounded-lg border bg-card p-4 text-card-foreground shadow-sm", className),
9691
10440
  style,
9692
10441
  children: [
9693
- title ? /* @__PURE__ */ jsx141("div", { "data-slot": "metric-card-title", className: "text-sm text-muted-foreground", children: title }) : null,
9694
- /* @__PURE__ */ jsxs92(
10442
+ title ? /* @__PURE__ */ jsx142("div", { "data-slot": "metric-card-title", className: "text-sm text-muted-foreground", children: title }) : null,
10443
+ /* @__PURE__ */ jsxs93(
9695
10444
  "div",
9696
10445
  {
9697
10446
  "data-slot": "metric-card-value",
@@ -9703,7 +10452,7 @@ function MetricCard({
9703
10452
  ]
9704
10453
  }
9705
10454
  ),
9706
- showTrend ? /* @__PURE__ */ jsxs92(
10455
+ showTrend ? /* @__PURE__ */ jsxs93(
9707
10456
  "div",
9708
10457
  {
9709
10458
  "data-slot": "metric-card-trend",
@@ -9713,10 +10462,10 @@ function MetricCard({
9713
10462
  rising ? "text-success" : "text-destructive"
9714
10463
  ),
9715
10464
  children: [
9716
- rising ? /* @__PURE__ */ jsx141(ArrowUpRight, { className: "size-4" }) : /* @__PURE__ */ jsx141(ArrowDownRight, { className: "size-4" }),
10465
+ rising ? /* @__PURE__ */ jsx142(ArrowUpRight, { className: "size-4" }) : /* @__PURE__ */ jsx142(ArrowDownRight, { className: "size-4" }),
9717
10466
  Math.abs(trend ?? 0),
9718
10467
  "%",
9719
- trendLabel ? /* @__PURE__ */ jsx141("span", { className: "ml-1 text-muted-foreground", children: trendLabel }) : null
10468
+ trendLabel ? /* @__PURE__ */ jsx142("span", { className: "ml-1 text-muted-foreground", children: trendLabel }) : null
9720
10469
  ]
9721
10470
  }
9722
10471
  ) : null
@@ -9726,7 +10475,7 @@ function MetricCard({
9726
10475
  }
9727
10476
 
9728
10477
  // src/components/chart/PieChart/index.tsx
9729
- import { jsx as jsx142 } from "react/jsx-runtime";
10478
+ import { jsx as jsx143 } from "react/jsx-runtime";
9730
10479
  function PieChart2({
9731
10480
  data = [],
9732
10481
  nameKey,
@@ -9743,7 +10492,7 @@ function PieChart2({
9743
10492
  { data, nameKey, valueKey, showLabel, colors, title },
9744
10493
  getChartTheme()
9745
10494
  );
9746
- return /* @__PURE__ */ jsx142(
10495
+ return /* @__PURE__ */ jsx143(
9747
10496
  EChartBase,
9748
10497
  {
9749
10498
  slot: "pie-chart",
@@ -9757,7 +10506,7 @@ function PieChart2({
9757
10506
  }
9758
10507
 
9759
10508
  // src/components/chart/RadarChart/index.tsx
9760
- import { jsx as jsx143 } from "react/jsx-runtime";
10509
+ import { jsx as jsx144 } from "react/jsx-runtime";
9761
10510
  function RadarChart2({
9762
10511
  data = [],
9763
10512
  indicatorKey,
@@ -9773,7 +10522,7 @@ function RadarChart2({
9773
10522
  { data, indicatorKey, yKeys, colors, title },
9774
10523
  getChartTheme()
9775
10524
  );
9776
- return /* @__PURE__ */ jsx143(
10525
+ return /* @__PURE__ */ jsx144(
9777
10526
  EChartBase,
9778
10527
  {
9779
10528
  slot: "radar-chart",
@@ -9787,7 +10536,7 @@ function RadarChart2({
9787
10536
  }
9788
10537
 
9789
10538
  // src/components/chart/SankeyChart/index.tsx
9790
- import { jsx as jsx144 } from "react/jsx-runtime";
10539
+ import { jsx as jsx145 } from "react/jsx-runtime";
9791
10540
  function SankeyChart2({
9792
10541
  nodes = [],
9793
10542
  links = [],
@@ -9798,7 +10547,7 @@ function SankeyChart2({
9798
10547
  style
9799
10548
  }) {
9800
10549
  const option = buildSankeyOption({ nodes, links, title }, getChartTheme());
9801
- return /* @__PURE__ */ jsx144(
10550
+ return /* @__PURE__ */ jsx145(
9802
10551
  EChartBase,
9803
10552
  {
9804
10553
  slot: "sankey-chart",
@@ -9812,7 +10561,7 @@ function SankeyChart2({
9812
10561
  }
9813
10562
 
9814
10563
  // src/components/chart/ScatterChart/index.tsx
9815
- import { jsx as jsx145 } from "react/jsx-runtime";
10564
+ import { jsx as jsx146 } from "react/jsx-runtime";
9816
10565
  function ScatterChart2({
9817
10566
  data = [],
9818
10567
  xKey,
@@ -9829,7 +10578,7 @@ function ScatterChart2({
9829
10578
  { data, xKey, yKey, seriesKey, colors, title },
9830
10579
  getChartTheme()
9831
10580
  );
9832
- return /* @__PURE__ */ jsx145(
10581
+ return /* @__PURE__ */ jsx146(
9833
10582
  EChartBase,
9834
10583
  {
9835
10584
  slot: "scatter-chart",
@@ -9843,7 +10592,7 @@ function ScatterChart2({
9843
10592
  }
9844
10593
 
9845
10594
  // src/components/chart/TreeChart/index.tsx
9846
- import { jsx as jsx146 } from "react/jsx-runtime";
10595
+ import { jsx as jsx147 } from "react/jsx-runtime";
9847
10596
  function TreeChart2({
9848
10597
  data = [],
9849
10598
  title,
@@ -9859,7 +10608,7 @@ function TreeChart2({
9859
10608
  { data, title, orient, edgeShape, initialTreeDepth },
9860
10609
  getChartTheme()
9861
10610
  );
9862
- return /* @__PURE__ */ jsx146(
10611
+ return /* @__PURE__ */ jsx147(
9863
10612
  EChartBase,
9864
10613
  {
9865
10614
  slot: "tree-chart",