@pactor-app/ui 1.21.0 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -502,6 +502,7 @@ var ICONS = {
502
502
  "file-text": import_lucide_react2.FileText,
503
503
  "panel-left": import_lucide_react2.PanelLeft,
504
504
  "panel-right-open": import_lucide_react2.PanelRightOpen,
505
+ "panel-right-close": import_lucide_react2.PanelRightClose,
505
506
  square: import_lucide_react2.Square,
506
507
  history: import_lucide_react2.History,
507
508
  "rotate-ccw": import_lucide_react2.RotateCcw,
@@ -3069,6 +3070,7 @@ function ChatInput({
3069
3070
  toolbarEnd,
3070
3071
  header,
3071
3072
  footer,
3073
+ field,
3072
3074
  onChange,
3073
3075
  onSubmit,
3074
3076
  className,
@@ -3079,6 +3081,8 @@ function ChatInput({
3079
3081
  const [draft, setDraft] = (0, import_react14.useState)("");
3080
3082
  const text = controlled ? value : draft;
3081
3083
  const canSubmit = !disabled && text.trim() !== "";
3084
+ const customField = field !== void 0 && field !== null;
3085
+ const renderSlot = (slot) => (0, import_react14.isValidElement)(slot) || typeof slot !== "object" || slot === null ? slot : renderChildren([slot]);
3082
3086
  const composingRef = (0, import_react14.useRef)(false);
3083
3087
  const handleChange = (next) => {
3084
3088
  if (!controlled) {
@@ -3114,8 +3118,8 @@ function ChatInput({
3114
3118
  ),
3115
3119
  style,
3116
3120
  children: [
3117
- header ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "px-3 pt-3", children: renderChildren([header]) }) : null,
3118
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3121
+ header ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "px-3 pt-3", children: renderSlot(header) }) : null,
3122
+ customField ? field : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3119
3123
  Textarea,
3120
3124
  {
3121
3125
  value: text,
@@ -3130,9 +3134,9 @@ function ChatInput({
3130
3134
  }
3131
3135
  ),
3132
3136
  toolbarStart || toolbarEnd || !hideSend ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-1 px-2 pb-2", children: [
3133
- toolbarStart ? renderChildren([toolbarStart]) : null,
3137
+ toolbarStart ? renderSlot(toolbarStart) : null,
3134
3138
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "flex-1" }),
3135
- toolbarEnd ? renderChildren([toolbarEnd]) : null,
3139
+ toolbarEnd ? renderSlot(toolbarEnd) : null,
3136
3140
  hideSend ? null : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3137
3141
  Button,
3138
3142
  {
@@ -3146,7 +3150,7 @@ function ChatInput({
3146
3150
  }
3147
3151
  )
3148
3152
  ] }) : null,
3149
- footer ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "border-t border-border px-3 py-2", children: renderChildren([footer]) }) : null
3153
+ footer ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "border-t border-border px-3 py-2", children: renderSlot(footer) }) : null
3150
3154
  ]
3151
3155
  }
3152
3156
  );
@@ -3698,7 +3702,8 @@ function DatePicker(props) {
3698
3702
  onSelect: handleRangeDaySelect,
3699
3703
  modifiers: rangeModifiers,
3700
3704
  modifiersClassNames: rangeModifierClassNames,
3701
- locale: dfLocale
3705
+ locale: dfLocale,
3706
+ showOutsideDays: false
3702
3707
  }
3703
3708
  )
3704
3709
  }
@@ -3712,7 +3717,8 @@ function DatePicker(props) {
3712
3717
  onSelect: handleRangeDaySelect,
3713
3718
  modifiers: rangeModifiers,
3714
3719
  modifiersClassNames: rangeModifierClassNames,
3715
- locale: dfLocale
3720
+ locale: dfLocale,
3721
+ showOutsideDays: false
3716
3722
  }
3717
3723
  ) })
3718
3724
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
@@ -11774,7 +11780,14 @@ function ArtifactTreeRow({
11774
11780
  className: "flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm hover:bg-accent",
11775
11781
  onClick: () => setOpen((value) => !value),
11776
11782
  children: [
11777
- /* @__PURE__ */ (0, import_jsx_runtime170.jsx)("span", { className: "inline-flex transition-transform data-[open=true]:rotate-90", "data-open": open, children: /* @__PURE__ */ (0, import_jsx_runtime170.jsx)(Icon, { name: "chevron-right", size: 12 }) }),
11783
+ /* @__PURE__ */ (0, import_jsx_runtime170.jsx)(
11784
+ "span",
11785
+ {
11786
+ className: "inline-flex transition-transform data-[open=true]:rotate-90",
11787
+ "data-open": open,
11788
+ children: /* @__PURE__ */ (0, import_jsx_runtime170.jsx)(Icon, { name: "chevron-right", size: 12 })
11789
+ }
11790
+ ),
11778
11791
  /* @__PURE__ */ (0, import_jsx_runtime170.jsx)(Icon, { name: "folder", size: 13 }),
11779
11792
  /* @__PURE__ */ (0, import_jsx_runtime170.jsx)("span", { className: "min-w-0 flex-1 truncate", children: node.name })
11780
11793
  ]
@@ -11906,6 +11919,7 @@ function ArtifactPanel({
11906
11919
  icon: "download",
11907
11920
  variant: "text",
11908
11921
  tooltip: "\u4E0B\u8F7D\u4EA7\u7269",
11922
+ className: "px-2",
11909
11923
  onClick: () => onDownload ? onDownload(artifact) : void downloadArtifact(artifact)
11910
11924
  }
11911
11925
  ) : null,
@@ -11915,11 +11929,12 @@ function ArtifactPanel({
11915
11929
  icon: "x",
11916
11930
  variant: "text",
11917
11931
  tooltip: "\u6536\u8D77\u4EA7\u7269\u533A",
11932
+ className: "px-2",
11918
11933
  onClick: () => onClose?.()
11919
11934
  }
11920
11935
  )
11921
11936
  ] }),
11922
- /* @__PURE__ */ (0, import_jsx_runtime170.jsx)("div", { className: "min-h-0 flex-1 overflow-auto p-4", children: view === "list" && artifacts !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime170.jsx)(
11937
+ /* @__PURE__ */ (0, import_jsx_runtime170.jsx)("div", { className: "scrollbar-subtle min-h-0 flex-1 overflow-auto p-4", children: view === "list" && artifacts !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime170.jsx)(
11923
11938
  ArtifactListView,
11924
11939
  {
11925
11940
  nodes: buildArtifactTree(artifacts),
@@ -12177,7 +12192,7 @@ function Thinking({
12177
12192
  {
12178
12193
  "data-slot": "thinking",
12179
12194
  "data-status": status,
12180
- className: cn("w-full overflow-hidden rounded-md border border-border bg-muted/50", className),
12195
+ className: cn("w-full", className),
12181
12196
  style,
12182
12197
  children: [
12183
12198
  /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)(
@@ -12186,12 +12201,12 @@ function Thinking({
12186
12201
  type: "button",
12187
12202
  "data-slot": "thinking-trigger",
12188
12203
  "aria-expanded": isExpanded,
12189
- className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm",
12204
+ className: "flex w-full cursor-pointer items-center gap-2 py-1 text-left text-sm",
12190
12205
  onClick: toggle,
12191
12206
  children: [
12192
12207
  /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: cn("text-muted-foreground", status === "thinking" && "animate-pulse motion-reduce:animate-none"), children: /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(Icon, { name: "brain", size: "sm" }) }),
12193
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { "data-slot": "thinking-title", className: "flex-1 text-muted-foreground", children: resolvedTitle }),
12194
- /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(Icon, { name: isExpanded ? "chevron-down" : "chevron-right", size: "sm" })
12208
+ /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { "data-slot": "thinking-title", className: "text-muted-foreground", children: resolvedTitle }),
12209
+ /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(Icon, { name: isExpanded ? "chevron-down" : "chevron-right", size: "sm" }) })
12195
12210
  ]
12196
12211
  }
12197
12212
  ),
@@ -12199,7 +12214,7 @@ function Thinking({
12199
12214
  "div",
12200
12215
  {
12201
12216
  "data-slot": "thinking-content",
12202
- className: "border-t border-border px-3 py-2 text-sm whitespace-pre-wrap text-muted-foreground",
12217
+ className: "py-1 pl-6 text-sm whitespace-pre-wrap text-muted-foreground",
12203
12218
  children: content
12204
12219
  }
12205
12220
  ) : null
@@ -12229,42 +12244,51 @@ function ToolCall({ name, params, status = "done", result, durationMs, defaultEx
12229
12244
  const [expanded, setExpanded] = (0, import_react62.useState)(defaultExpanded ?? status === "running");
12230
12245
  const meta = statusIcon3[status];
12231
12246
  const paramsText = renderValue(params);
12247
+ const hasDetail = Boolean(paramsText) || Boolean(result);
12248
+ const headerInner = /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)(import_jsx_runtime177.Fragment, { children: [
12249
+ /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: "terminal", size: "sm" }) }),
12250
+ /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { "data-slot": "tool-call-name", className: "min-w-0 truncate font-medium", children: name ?? "\u5DE5\u5177\u8C03\u7528" }),
12251
+ /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: cn("shrink-0", meta.className, meta.spin && "animate-spin motion-reduce:animate-none"), children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: meta.icon, size: "sm" }) }),
12252
+ durationMs !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
12253
+ (durationMs / 1e3).toFixed(1),
12254
+ "s"
12255
+ ] }) : null,
12256
+ hasDetail ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: expanded ? "chevron-down" : "chevron-right", size: "sm" }) }) : null
12257
+ ] });
12232
12258
  return /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)(
12233
12259
  "div",
12234
12260
  {
12235
12261
  "data-slot": "tool-call",
12236
12262
  "data-status": status,
12237
- className: cn("w-full overflow-hidden rounded-md border border-border", className),
12263
+ className: cn("w-full", className),
12238
12264
  style,
12239
12265
  children: [
12240
- /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)(
12266
+ hasDetail ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
12241
12267
  "button",
12242
12268
  {
12243
12269
  type: "button",
12244
12270
  "data-slot": "tool-call-trigger",
12245
12271
  "aria-expanded": expanded,
12246
- className: "flex w-full items-center gap-2 px-3 py-2 text-left text-sm",
12272
+ className: "flex w-full cursor-pointer items-center gap-2 py-1 text-left text-sm",
12247
12273
  onClick: () => setExpanded((value) => !value),
12248
- children: [
12249
- /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: "terminal", size: "sm" }) }),
12250
- /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { "data-slot": "tool-call-name", className: "min-w-0 flex-1 truncate font-medium", children: name ?? "\u5DE5\u5177\u8C03\u7528" }),
12251
- /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: cn("shrink-0", meta.className, meta.spin && "animate-spin motion-reduce:animate-none"), children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: meta.icon, size: "sm" }) }),
12252
- durationMs !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
12253
- (durationMs / 1e3).toFixed(1),
12254
- "s"
12255
- ] }) : null,
12256
- /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: expanded ? "chevron-down" : "chevron-right", size: "sm" })
12257
- ]
12274
+ children: headerInner
12275
+ }
12276
+ ) : /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
12277
+ "div",
12278
+ {
12279
+ "data-slot": "tool-call-trigger",
12280
+ className: "flex w-full items-center gap-2 py-1 text-left text-sm",
12281
+ children: headerInner
12258
12282
  }
12259
12283
  ),
12260
- expanded ? /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("div", { "data-slot": "tool-call-body", className: "flex flex-col gap-2 border-t border-border px-3 py-2", children: [
12284
+ hasDetail && expanded ? /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("div", { "data-slot": "tool-call-body", className: "flex flex-col gap-2 py-1 pl-6", children: [
12261
12285
  paramsText ? /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("div", { children: [
12262
12286
  /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("div", { className: "text-xs font-medium text-muted-foreground", children: "\u53C2\u6570" }),
12263
- /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("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 })
12287
+ /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("pre", { "data-slot": "tool-call-params", className: "mt-1 overflow-x-auto text-xs whitespace-pre-wrap text-muted-foreground", children: paramsText })
12264
12288
  ] }) : null,
12265
12289
  result ? /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("div", { children: [
12266
12290
  /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("div", { className: "text-xs font-medium text-muted-foreground", children: "\u7ED3\u679C" }),
12267
- /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("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 })
12291
+ /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("pre", { "data-slot": "tool-call-result", className: "mt-1 overflow-x-auto text-xs whitespace-pre-wrap text-muted-foreground", children: result })
12268
12292
  ] }) : null
12269
12293
  ] }) : null
12270
12294
  ]
@@ -12274,12 +12298,26 @@ function ToolCall({ name, params, status = "done", result, durationMs, defaultEx
12274
12298
 
12275
12299
  // src/components/chat/ChatMessage/index.tsx
12276
12300
  var import_jsx_runtime178 = require("react/jsx-runtime");
12277
- function PartView({ part, role }) {
12301
+ function PartView({
12302
+ part,
12303
+ role,
12304
+ onOpenArtifacts
12305
+ }) {
12306
+ if (role === "system" && (part.type === "text" || part.type === "markdown")) {
12307
+ return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
12308
+ "div",
12309
+ {
12310
+ "data-slot": "chat-message-system-part",
12311
+ className: "w-full text-center text-xs text-muted-foreground",
12312
+ children: part.type === "markdown" ? /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(import_markdown2.MarkdownDslComponent, { content: part.content }) : part.content
12313
+ }
12314
+ );
12315
+ }
12278
12316
  switch (part.type) {
12279
12317
  case "text":
12280
12318
  return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Bubble2, { align: role === "user" ? "end" : "start", variant: role === "user" ? "default" : "muted", children: /* @__PURE__ */ (0, import_jsx_runtime178.jsx)("span", { className: "text-sm whitespace-pre-wrap", children: part.content }) });
12281
12319
  case "markdown":
12282
- return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Bubble2, { align: role === "user" ? "end" : "start", variant: role === "user" ? "default" : "ghost", children: /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(import_markdown2.MarkdownDslComponent, { content: part.content, className: "text-sm" }) });
12320
+ return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Bubble2, { align: role === "user" ? "end" : "start", variant: role === "user" ? "default" : "ghost", children: /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(import_markdown2.MarkdownDslComponent, { content: part.content }) });
12283
12321
  case "thinking":
12284
12322
  return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Thinking, { content: part.content, status: part.status ?? "done" });
12285
12323
  case "tool-call":
@@ -12287,10 +12325,31 @@ function PartView({ part, role }) {
12287
12325
  case "tool-result":
12288
12326
  return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)("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 });
12289
12327
  case "status":
12290
- return /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)("div", { "data-slot": "chat-message-status", className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
12328
+ return /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)("div", { "data-slot": "chat-message-status", className: "flex w-fit items-center gap-1.5 text-muted-foreground", children: [
12291
12329
  /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Icon, { name: "clock", size: "sm" }),
12292
12330
  part.text
12293
12331
  ] });
12332
+ case "artifacts": {
12333
+ const artifactsClass = "flex w-fit items-center gap-1.5 text-muted-foreground";
12334
+ const label = `\u5DF2\u751F\u6210 ${part.count} \u4E2A\u4EA7\u7269`;
12335
+ return onOpenArtifacts ? /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)(
12336
+ "button",
12337
+ {
12338
+ type: "button",
12339
+ "data-slot": "chat-message-artifacts",
12340
+ className: cn(artifactsClass, "cursor-pointer hover:text-foreground"),
12341
+ onClick: onOpenArtifacts,
12342
+ children: [
12343
+ /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Icon, { name: "package", size: "sm" }),
12344
+ label,
12345
+ /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Icon, { name: "chevron-right", size: 12 })
12346
+ ]
12347
+ }
12348
+ ) : /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)("div", { "data-slot": "chat-message-artifacts", className: artifactsClass, children: [
12349
+ /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Icon, { name: "package", size: "sm" }),
12350
+ label
12351
+ ] });
12352
+ }
12294
12353
  case "error":
12295
12354
  return /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)("div", { "data-slot": "chat-message-error", className: "flex items-center gap-1.5 text-sm text-destructive", children: [
12296
12355
  /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Icon, { name: "circle-alert", size: "sm" }),
@@ -12300,19 +12359,31 @@ function PartView({ part, role }) {
12300
12359
  return null;
12301
12360
  }
12302
12361
  }
12362
+ var ACTION_ICON_BY_NAME = {
12363
+ copy: "copy",
12364
+ retry: "rotate-ccw",
12365
+ regenerate: "refresh-ccw",
12366
+ edit: "pencil",
12367
+ like: "thumbs-up",
12368
+ dislike: "thumbs-down",
12369
+ share: "share",
12370
+ delete: "trash"
12371
+ };
12303
12372
  function ChatMessage({
12304
12373
  role = "assistant",
12305
12374
  parts = [],
12306
12375
  status = "completed",
12307
12376
  agent,
12308
12377
  time,
12309
- showSender = true,
12378
+ showSender = false,
12310
12379
  actions = [],
12311
12380
  onAction,
12381
+ onOpenArtifacts,
12312
12382
  className,
12313
12383
  style
12314
12384
  }) {
12315
12385
  const isUser = role === "user";
12386
+ const isSystem = role === "system";
12316
12387
  const senderName = isUser ? "\u6211" : agent?.name ?? "\u52A9\u624B";
12317
12388
  return /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)(
12318
12389
  "div",
@@ -12320,10 +12391,16 @@ function ChatMessage({
12320
12391
  "data-slot": "chat-message",
12321
12392
  "data-role": role,
12322
12393
  "data-status": status,
12323
- className: cn("flex w-full flex-col gap-1.5", isUser && "items-end", className),
12394
+ className: cn(
12395
+ "flex w-full flex-col gap-1.5",
12396
+ isUser && "items-end",
12397
+ // system 居中弱提示(参考 @pactor-app/chat MessageBubble)
12398
+ isSystem && "items-center text-muted-foreground",
12399
+ className
12400
+ ),
12324
12401
  style,
12325
12402
  children: [
12326
- showSender && role !== "system" ? /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
12403
+ showSender ? /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
12327
12404
  Sender,
12328
12405
  {
12329
12406
  name: senderName,
@@ -12332,35 +12409,445 @@ function ChatMessage({
12332
12409
  align: isUser ? "end" : "start"
12333
12410
  }
12334
12411
  ) : null,
12335
- /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)("div", { className: cn("flex min-w-0 w-full max-w-full flex-col gap-2", isUser && "items-end"), children: [
12336
- parts.map((part, index) => /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(PartView, { part, role }, index)),
12412
+ /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)("div", { className: cn("flex min-w-0 w-full max-w-full flex-col gap-2", isUser && "items-end", isSystem && "items-center"), children: [
12413
+ parts.map((part, index) => /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(PartView, { part, role, onOpenArtifacts }, index)),
12337
12414
  status === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(StreamingText, { content: "", streaming: true }) : null
12338
12415
  ] }),
12339
- actions.length > 0 && (status === "completed" || status === "error") ? /* @__PURE__ */ (0, import_jsx_runtime178.jsx)("div", { "data-slot": "chat-message-actions", className: "flex items-center gap-1", children: actions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)(
12340
- "button",
12341
- {
12342
- type: "button",
12343
- "data-slot": "chat-message-action",
12344
- "data-action": action.name,
12345
- 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",
12346
- onClick: () => onAction?.(action.name),
12347
- children: [
12348
- action.icon ? /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Icon, { name: action.icon, size: "sm" }) : null,
12349
- action.label ?? action.name
12350
- ]
12351
- },
12352
- action.name
12353
- )) }) : null
12416
+ actions.length > 0 && (status === "completed" || status === "error") ? /* @__PURE__ */ (0, import_jsx_runtime178.jsx)("div", { "data-slot": "chat-message-actions", className: "flex items-center gap-1 mt-2", children: actions.map((action) => {
12417
+ const label = action.label ?? action.name;
12418
+ const iconName = action.icon ?? ACTION_ICON_BY_NAME[action.name];
12419
+ if (iconName) {
12420
+ return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Tooltip2, { content: label, side: "top", children: /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
12421
+ "button",
12422
+ {
12423
+ type: "button",
12424
+ "data-slot": "chat-message-action",
12425
+ "data-action": action.name,
12426
+ "aria-label": label,
12427
+ className: "flex cursor-pointer items-center rounded-sm p-1 text-muted-foreground hover:bg-accent hover:text-foreground",
12428
+ onClick: () => onAction?.(action.name),
12429
+ children: /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(Icon, { name: iconName, size: "sm" })
12430
+ }
12431
+ ) }, action.name);
12432
+ }
12433
+ return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
12434
+ "button",
12435
+ {
12436
+ type: "button",
12437
+ "data-slot": "chat-message-action",
12438
+ "data-action": action.name,
12439
+ 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",
12440
+ onClick: () => onAction?.(action.name),
12441
+ children: label
12442
+ },
12443
+ action.name
12444
+ );
12445
+ }) }) : null
12354
12446
  ]
12355
12447
  }
12356
12448
  );
12357
12449
  }
12358
12450
 
12359
12451
  // src/components/chat/ChatPage/index.tsx
12360
- var import_react65 = require("react");
12452
+ var import_runtime26 = require("@pactor-app/runtime");
12453
+ var import_react67 = require("react");
12361
12454
 
12362
12455
  // src/components/chat/Composer/index.tsx
12456
+ var import_react64 = require("react");
12457
+
12458
+ // src/components/chat/Composer/mention-input.tsx
12459
+ var import_react63 = require("react");
12460
+ var import_server = require("react-dom/server");
12363
12461
  var import_jsx_runtime179 = require("react/jsx-runtime");
12462
+ var NBSP = "\xA0";
12463
+ var CHIP_ATTR = "data-mention-chip";
12464
+ function escapeRegExp(text) {
12465
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12466
+ }
12467
+ function isChipElement(node) {
12468
+ return node instanceof HTMLElement && node.hasAttribute(CHIP_ATTR);
12469
+ }
12470
+ function serializeNode(node) {
12471
+ let out = "";
12472
+ node.childNodes.forEach((child) => {
12473
+ if (child.nodeType === Node.TEXT_NODE) {
12474
+ out += (child.textContent ?? "").replace(/\u00A0/g, " ");
12475
+ } else if (isChipElement(child)) {
12476
+ out += `${child.dataset["trigger"] ?? ""}${child.dataset["label"] ?? ""}`;
12477
+ } else if (child instanceof HTMLBRElement) {
12478
+ out += "\n";
12479
+ } else if (child instanceof HTMLElement) {
12480
+ const inner = serializeNode(child).replace(/\n$/, "");
12481
+ out += (out === "" || out.endsWith("\n") ? "" : "\n") + inner + "\n";
12482
+ }
12483
+ });
12484
+ return out;
12485
+ }
12486
+ function collectChips(field) {
12487
+ return Array.from(field.querySelectorAll(`[${CHIP_ATTR}]`)).map((el) => ({
12488
+ id: el.dataset["id"] ?? "",
12489
+ label: el.dataset["label"] ?? "",
12490
+ trigger: el.dataset["trigger"] ?? ""
12491
+ }));
12492
+ }
12493
+ function detectActiveMention(field, sources) {
12494
+ const selection = window.getSelection();
12495
+ if (!selection || selection.rangeCount === 0 || !selection.isCollapsed) {
12496
+ return null;
12497
+ }
12498
+ const anchor = selection.anchorNode;
12499
+ if (!anchor || anchor.nodeType !== Node.TEXT_NODE || !field.contains(anchor)) {
12500
+ return null;
12501
+ }
12502
+ const caretOffset = selection.anchorOffset;
12503
+ const beforeCaret = (anchor.textContent ?? "").slice(0, caretOffset);
12504
+ for (const source of sources) {
12505
+ const trigger = source.trigger;
12506
+ const match = new RegExp(
12507
+ `(?:^|\\s)${escapeRegExp(trigger)}([^\\s${escapeRegExp(trigger)}]*)$`
12508
+ ).exec(beforeCaret);
12509
+ if (match) {
12510
+ const query = match[1] ?? "";
12511
+ return {
12512
+ source,
12513
+ query,
12514
+ node: anchor,
12515
+ triggerStart: caretOffset - query.length - trigger.length,
12516
+ caretOffset
12517
+ };
12518
+ }
12519
+ }
12520
+ return null;
12521
+ }
12522
+ function chipIcon(item, source) {
12523
+ return item.icon ?? source.icon ?? (source.trigger === "@" ? "user" : "file-text");
12524
+ }
12525
+ var MentionInput = (0, import_react63.forwardRef)(
12526
+ function MentionInput2({
12527
+ value,
12528
+ placeholder,
12529
+ disabled,
12530
+ sources,
12531
+ chips,
12532
+ onChipsChange,
12533
+ onChange,
12534
+ onSubmit,
12535
+ className,
12536
+ style
12537
+ }, ref) {
12538
+ const fieldRef = (0, import_react63.useRef)(null);
12539
+ const [menu, setMenu] = (0, import_react63.useState)(null);
12540
+ const [empty, setEmpty] = (0, import_react63.useState)(true);
12541
+ const suppressSyncRef = (0, import_react63.useRef)(false);
12542
+ const composingRef = (0, import_react63.useRef)(false);
12543
+ const emitChips = () => {
12544
+ if (suppressSyncRef.current || !fieldRef.current) {
12545
+ return;
12546
+ }
12547
+ onChipsChange?.(collectChips(fieldRef.current));
12548
+ };
12549
+ const serialize = () => fieldRef.current ? serializeNode(fieldRef.current).replace(/\n$/, "") : "";
12550
+ const buildChipElement = (item, source) => {
12551
+ const chip = document.createElement("span");
12552
+ chip.setAttribute(CHIP_ATTR, "");
12553
+ chip.dataset["id"] = item.id;
12554
+ chip.dataset["label"] = item.label;
12555
+ chip.dataset["trigger"] = item.trigger ?? source.trigger;
12556
+ chip.contentEditable = "false";
12557
+ 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";
12558
+ const iconMarkup = (0, import_server.renderToStaticMarkup)(
12559
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(Icon, { name: chipIcon(item, source), size: 12 })
12560
+ );
12561
+ const label = document.createElement("span");
12562
+ label.textContent = item.label;
12563
+ chip.innerHTML = iconMarkup;
12564
+ chip.appendChild(label);
12565
+ return chip;
12566
+ };
12567
+ const insertChipElement = (item, source, replace) => {
12568
+ const field = fieldRef.current;
12569
+ if (!field) {
12570
+ return;
12571
+ }
12572
+ const chip = buildChipElement(item, source);
12573
+ let caretNode;
12574
+ if (replace) {
12575
+ const { node, start, end } = replace;
12576
+ const text = node.textContent ?? "";
12577
+ node.textContent = text.slice(0, start);
12578
+ caretNode = document.createTextNode(`${NBSP}${text.slice(end)}`);
12579
+ node.after(chip, caretNode);
12580
+ } else {
12581
+ caretNode = document.createTextNode(NBSP);
12582
+ const selection2 = window.getSelection();
12583
+ if (selection2 && selection2.rangeCount > 0 && selection2.anchorNode !== null && field.contains(selection2.anchorNode)) {
12584
+ const range = selection2.getRangeAt(0);
12585
+ range.deleteContents();
12586
+ range.insertNode(caretNode);
12587
+ range.insertNode(chip);
12588
+ } else {
12589
+ field.append(chip, caretNode);
12590
+ }
12591
+ }
12592
+ const selection = window.getSelection();
12593
+ if (selection) {
12594
+ const range = document.createRange();
12595
+ range.setStart(caretNode, 1);
12596
+ range.collapse(true);
12597
+ selection.removeAllRanges();
12598
+ selection.addRange(range);
12599
+ }
12600
+ setEmpty(false);
12601
+ onChange?.(serialize());
12602
+ emitChips();
12603
+ };
12604
+ (0, import_react63.useImperativeHandle)(ref, () => ({
12605
+ insertChip: (item, source) => {
12606
+ fieldRef.current?.focus();
12607
+ insertChipElement(item, source);
12608
+ },
12609
+ focus: () => fieldRef.current?.focus()
12610
+ }));
12611
+ (0, import_react63.useEffect)(() => {
12612
+ const field = fieldRef.current;
12613
+ if (field && value === "" && serializeNode(field).trim() !== "") {
12614
+ suppressSyncRef.current = true;
12615
+ field.innerHTML = "";
12616
+ setEmpty(true);
12617
+ setMenu(null);
12618
+ suppressSyncRef.current = false;
12619
+ }
12620
+ }, [value]);
12621
+ (0, import_react63.useEffect)(() => {
12622
+ const field = fieldRef.current;
12623
+ if (!field) {
12624
+ return;
12625
+ }
12626
+ const keep = new Set(chips.map((chip) => `${chip.trigger}:${chip.id}`));
12627
+ const stale = Array.from(field.querySelectorAll(`[${CHIP_ATTR}]`)).filter(
12628
+ (el) => !keep.has(
12629
+ `${el.dataset["trigger"]}:${el.dataset["id"]}`
12630
+ )
12631
+ );
12632
+ if (stale.length > 0) {
12633
+ suppressSyncRef.current = true;
12634
+ stale.forEach((el) => el.remove());
12635
+ suppressSyncRef.current = false;
12636
+ setEmpty(serializeNode(field).trim() === "");
12637
+ }
12638
+ }, [chips]);
12639
+ const closeMenu = () => setMenu(null);
12640
+ const filteredItems = (state) => state.query ? state.source.items.filter((item) => item.label.includes(state.query)) : state.source.items;
12641
+ const refreshMenu = () => {
12642
+ const field = fieldRef.current;
12643
+ if (!field) {
12644
+ return;
12645
+ }
12646
+ const active = detectActiveMention(field, sources);
12647
+ if (!active) {
12648
+ setMenu(null);
12649
+ return;
12650
+ }
12651
+ const range = document.createRange();
12652
+ range.setStart(active.node, active.triggerStart);
12653
+ range.setEnd(active.node, active.caretOffset);
12654
+ const rect = typeof range.getBoundingClientRect === "function" ? range.getBoundingClientRect() : field.getBoundingClientRect();
12655
+ setMenu((prev) => ({
12656
+ source: active.source,
12657
+ query: active.query,
12658
+ left: rect.left,
12659
+ top: rect.top,
12660
+ // 过滤结果变化后候选下标钳制在有效范围内(DSL 每次渲染产出新
12661
+ // props 对象,source 按 trigger 比较而非引用)
12662
+ activeIndex: Math.min(
12663
+ prev?.source.trigger === active.source.trigger ? prev.activeIndex : 0,
12664
+ Math.max(filteredItems({ source: active.source, query: active.query, left: 0, top: 0, activeIndex: 0 }).length - 1, 0)
12665
+ )
12666
+ }));
12667
+ };
12668
+ const selectMenuItem = (item) => {
12669
+ const field = fieldRef.current;
12670
+ if (!field || !menu) {
12671
+ return;
12672
+ }
12673
+ const active = detectActiveMention(field, sources);
12674
+ insertChipElement(
12675
+ { ...item, trigger: item.trigger ?? menu.source.trigger },
12676
+ menu.source,
12677
+ active && active.source.trigger === menu.source.trigger ? { node: active.node, start: active.triggerStart, end: active.caretOffset } : void 0
12678
+ );
12679
+ setMenu(null);
12680
+ };
12681
+ const handleInput = () => {
12682
+ const field = fieldRef.current;
12683
+ if (!field) {
12684
+ return;
12685
+ }
12686
+ if ((field.textContent ?? "") === "" && field.querySelector(`[${CHIP_ATTR}]`) === null) {
12687
+ field.innerHTML = "";
12688
+ }
12689
+ setEmpty(serializeNode(field).trim() === "");
12690
+ onChange?.(serialize());
12691
+ refreshMenu();
12692
+ };
12693
+ const handleKeyDown = (event) => {
12694
+ if (menu) {
12695
+ const items = filteredItems(menu);
12696
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
12697
+ event.preventDefault();
12698
+ if (items.length > 0) {
12699
+ const delta = event.key === "ArrowDown" ? 1 : -1;
12700
+ setMenu({
12701
+ ...menu,
12702
+ activeIndex: (menu.activeIndex + delta + items.length) % items.length
12703
+ });
12704
+ }
12705
+ return;
12706
+ }
12707
+ if (event.key === "Enter" && !composingRef.current && !event.nativeEvent.isComposing) {
12708
+ event.preventDefault();
12709
+ const item = items[Math.min(menu.activeIndex, items.length - 1)];
12710
+ if (item) {
12711
+ selectMenuItem(item);
12712
+ } else {
12713
+ closeMenu();
12714
+ }
12715
+ return;
12716
+ }
12717
+ if (event.key === "Escape") {
12718
+ event.preventDefault();
12719
+ closeMenu();
12720
+ return;
12721
+ }
12722
+ }
12723
+ if (event.key === "Enter" && !event.shiftKey && !composingRef.current && !event.nativeEvent.isComposing) {
12724
+ event.preventDefault();
12725
+ const text = serialize();
12726
+ if (text.trim() !== "" && !disabled) {
12727
+ onSubmit?.(text);
12728
+ }
12729
+ return;
12730
+ }
12731
+ if (event.key === "Backspace") {
12732
+ const selection = window.getSelection();
12733
+ const field = fieldRef.current;
12734
+ if (!selection || !selection.isCollapsed || !field) {
12735
+ return;
12736
+ }
12737
+ let chip = null;
12738
+ const anchor = selection.anchorNode;
12739
+ if (anchor === field && selection.anchorOffset > 0) {
12740
+ const before = field.childNodes[selection.anchorOffset - 1];
12741
+ if (isChipElement(before)) {
12742
+ chip = before;
12743
+ }
12744
+ } else if (anchor?.nodeType === Node.TEXT_NODE && selection.anchorOffset === 0) {
12745
+ if (isChipElement(anchor.previousSibling)) {
12746
+ chip = anchor.previousSibling;
12747
+ }
12748
+ }
12749
+ if (chip) {
12750
+ event.preventDefault();
12751
+ chip.remove();
12752
+ onChange?.(serialize());
12753
+ emitChips();
12754
+ setEmpty(serializeNode(field).trim() === "");
12755
+ }
12756
+ }
12757
+ };
12758
+ const menuItems = menu ? filteredItems(menu) : [];
12759
+ const activeIndex = Math.min(menu?.activeIndex ?? 0, Math.max(menuItems.length - 1, 0));
12760
+ return /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)("div", { className: "relative", children: [
12761
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(
12762
+ "div",
12763
+ {
12764
+ ref: fieldRef,
12765
+ "data-slot": "mention-input",
12766
+ role: "textbox",
12767
+ "aria-multiline": "true",
12768
+ "aria-placeholder": placeholder,
12769
+ contentEditable: !disabled,
12770
+ suppressContentEditableWarning: true,
12771
+ className: cn(
12772
+ "min-h-[60px] w-full px-4 pt-3 pb-1 text-sm whitespace-pre-wrap break-words outline-none",
12773
+ className
12774
+ ),
12775
+ style,
12776
+ onInput: handleInput,
12777
+ onKeyDown: handleKeyDown,
12778
+ onCompositionStart: () => {
12779
+ composingRef.current = true;
12780
+ },
12781
+ onCompositionEnd: () => {
12782
+ composingRef.current = false;
12783
+ },
12784
+ onPaste: (event) => {
12785
+ event.preventDefault();
12786
+ const text = event.clipboardData?.getData("text/plain") ?? "";
12787
+ if (text) {
12788
+ document.execCommand("insertText", false, text);
12789
+ }
12790
+ }
12791
+ }
12792
+ ),
12793
+ empty && placeholder !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime179.jsx)("span", { className: "pointer-events-none absolute top-3 left-4 text-sm text-muted-foreground", children: placeholder }) : null,
12794
+ menu ? /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(import_jsx_runtime179.Fragment, { children: [
12795
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(
12796
+ "div",
12797
+ {
12798
+ className: "fixed inset-0 z-40",
12799
+ onMouseDown: (event) => {
12800
+ event.preventDefault();
12801
+ closeMenu();
12802
+ }
12803
+ }
12804
+ ),
12805
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(
12806
+ "div",
12807
+ {
12808
+ "data-slot": "mention-menu",
12809
+ role: "listbox",
12810
+ 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",
12811
+ style: {
12812
+ left: menu.left,
12813
+ bottom: typeof window === "undefined" ? void 0 : window.innerHeight - menu.top + 6
12814
+ },
12815
+ children: [
12816
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsx)("div", { className: "px-2 py-1 text-xs text-muted-foreground", children: menu.source.label }),
12817
+ menuItems.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime179.jsx)("div", { className: "px-2 py-2 text-xs text-muted-foreground", children: "\u65E0\u5339\u914D\u9879" }) : menuItems.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(
12818
+ "button",
12819
+ {
12820
+ type: "button",
12821
+ role: "option",
12822
+ "aria-selected": index === activeIndex,
12823
+ className: cn(
12824
+ "flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm",
12825
+ index === activeIndex ? "bg-accent" : "hover:bg-accent"
12826
+ ),
12827
+ onMouseDown: (event) => {
12828
+ event.preventDefault();
12829
+ selectMenuItem(item);
12830
+ },
12831
+ children: [
12832
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(Icon, { name: chipIcon(item, menu.source), size: "sm" }),
12833
+ /* @__PURE__ */ (0, import_jsx_runtime179.jsx)("span", { className: "min-w-0 flex-1 truncate", children: item.label })
12834
+ ]
12835
+ },
12836
+ item.id
12837
+ ))
12838
+ ]
12839
+ }
12840
+ )
12841
+ ] }) : null
12842
+ ] });
12843
+ }
12844
+ );
12845
+
12846
+ // src/components/chat/Composer/index.tsx
12847
+ var import_jsx_runtime180 = require("react/jsx-runtime");
12848
+ var toolButtonClass3 = "flex cursor-pointer items-center rounded-md p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground";
12849
+ 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";
12850
+ 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";
12364
12851
  function Composer({
12365
12852
  value,
12366
12853
  placeholder,
@@ -12370,35 +12857,238 @@ function Composer({
12370
12857
  attachments = [],
12371
12858
  onRemoveAttachment,
12372
12859
  onRetryAttachment,
12860
+ onAttachFiles,
12373
12861
  onChange,
12374
12862
  onSubmit,
12863
+ models,
12864
+ model,
12865
+ onModelChange,
12866
+ contexts,
12867
+ contextItems,
12868
+ onContextItemsChange,
12869
+ footer,
12375
12870
  className,
12376
12871
  style
12377
12872
  }) {
12378
- return /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)("div", { "data-slot": "composer", className: cn("flex w-full flex-col gap-2", className), style, children: [
12379
- attachments.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(Attachment, { items: attachments, onRemove: onRemoveAttachment, onRetry: onRetryAttachment }) : null,
12380
- /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(
12381
- ChatInput,
12873
+ const textControlled = value !== void 0;
12874
+ const [innerText, setInnerText] = (0, import_react64.useState)("");
12875
+ const text = textControlled ? value : innerText;
12876
+ const [dragOver, setDragOver] = (0, import_react64.useState)(false);
12877
+ const [plusOpen, setPlusOpen] = (0, import_react64.useState)(false);
12878
+ const [modelOpen, setModelOpen] = (0, import_react64.useState)(false);
12879
+ const fileInputRef = (0, import_react64.useRef)(null);
12880
+ const mentionRef = (0, import_react64.useRef)(null);
12881
+ const sources = contexts ?? [];
12882
+ const rich = sources.length > 0;
12883
+ const plusSources = sources.filter((s) => s.trigger === "+");
12884
+ const plusEnabled = plusSources.length > 0;
12885
+ const modelEnabled = models !== void 0 && models.length > 0;
12886
+ const currentModel = models?.find((m) => m.value === model) ?? models?.[0];
12887
+ const chips = contextItems ?? [];
12888
+ const closePopovers = () => {
12889
+ setPlusOpen(false);
12890
+ setModelOpen(false);
12891
+ };
12892
+ const handleChange = (next) => {
12893
+ if (!textControlled) {
12894
+ setInnerText(next);
12895
+ }
12896
+ onChange?.(next);
12897
+ };
12898
+ const handleSubmit = (submitted) => {
12899
+ onSubmit?.(submitted);
12900
+ if (!textControlled) {
12901
+ setInnerText("");
12902
+ }
12903
+ closePopovers();
12904
+ };
12905
+ const selectContext = (item, source) => {
12906
+ if (rich) {
12907
+ mentionRef.current?.insertChip(item, source);
12908
+ } else {
12909
+ const chip = { ...item, trigger: item.trigger ?? source.trigger };
12910
+ const duplicated = chips.some(
12911
+ (existing) => existing.id === chip.id && existing.trigger === chip.trigger
12912
+ );
12913
+ if (!duplicated) {
12914
+ onContextItemsChange?.([...chips, chip]);
12915
+ }
12916
+ }
12917
+ closePopovers();
12918
+ };
12919
+ const emitFiles = (files) => {
12920
+ if (files.length > 0 && onAttachFiles) {
12921
+ onAttachFiles(files);
12922
+ }
12923
+ };
12924
+ const handleDrop = (event) => {
12925
+ if (!onAttachFiles) {
12926
+ return;
12927
+ }
12928
+ event.preventDefault();
12929
+ setDragOver(false);
12930
+ emitFiles(Array.from(event.dataTransfer?.files ?? []));
12931
+ };
12932
+ const toolbarStart = plusEnabled || onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(import_jsx_runtime180.Fragment, { children: [
12933
+ plusEnabled ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
12934
+ "button",
12382
12935
  {
12383
- value,
12384
- placeholder,
12385
- disabled: disabled || loading,
12386
- rows,
12387
- onChange,
12388
- onSubmit
12936
+ type: "button",
12937
+ "aria-label": "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
12938
+ title: "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
12939
+ className: toolButtonClass3,
12940
+ onClick: () => {
12941
+ setPlusOpen((prev) => !prev);
12942
+ setModelOpen(false);
12943
+ },
12944
+ children: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(Icon, { name: "plus", size: "sm" })
12389
12945
  }
12390
- )
12391
- ] });
12946
+ ) : null,
12947
+ onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
12948
+ "button",
12949
+ {
12950
+ type: "button",
12951
+ "aria-label": "\u6DFB\u52A0\u9644\u4EF6",
12952
+ title: "\u6DFB\u52A0\u9644\u4EF6",
12953
+ className: toolButtonClass3,
12954
+ onClick: () => fileInputRef.current?.click(),
12955
+ children: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(Icon, { name: "paperclip", size: "sm" })
12956
+ }
12957
+ ) : null
12958
+ ] }) : void 0;
12959
+ const toolbarEnd = modelEnabled ? /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
12960
+ "button",
12961
+ {
12962
+ type: "button",
12963
+ "aria-label": "\u9009\u62E9\u6A21\u578B",
12964
+ title: "\u9009\u62E9\u6A21\u578B",
12965
+ 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",
12966
+ onClick: () => {
12967
+ setModelOpen((prev) => !prev);
12968
+ setPlusOpen(false);
12969
+ },
12970
+ children: [
12971
+ currentModel?.label,
12972
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(Icon, { name: "chevrons-up-down", size: 12 })
12973
+ ]
12974
+ }
12975
+ ) : void 0;
12976
+ const activePopover = plusOpen ? "plus" : modelOpen ? "model" : null;
12977
+ return /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
12978
+ "div",
12979
+ {
12980
+ "data-slot": "composer",
12981
+ className: cn("relative flex w-full flex-col gap-2", className),
12982
+ style,
12983
+ onDragOver: (event) => {
12984
+ if (onAttachFiles) {
12985
+ event.preventDefault();
12986
+ setDragOver(true);
12987
+ }
12988
+ },
12989
+ onDragLeave: () => setDragOver(false),
12990
+ onDrop: handleDrop,
12991
+ onPaste: (event) => {
12992
+ const files = Array.from(event.clipboardData?.files ?? []);
12993
+ if (files.length > 0 && onAttachFiles) {
12994
+ event.preventDefault();
12995
+ emitFiles(files);
12996
+ }
12997
+ },
12998
+ children: [
12999
+ attachments.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(Attachment, { items: attachments, onRemove: onRemoveAttachment, onRetry: onRetryAttachment }) : null,
13000
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { className: cn(dragOver && "rounded-xl ring-2 ring-ring/50"), children: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
13001
+ ChatInput,
13002
+ {
13003
+ value: text,
13004
+ placeholder,
13005
+ disabled: disabled || loading,
13006
+ rows,
13007
+ toolbarStart,
13008
+ toolbarEnd,
13009
+ footer,
13010
+ field: rich ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
13011
+ MentionInput,
13012
+ {
13013
+ ref: mentionRef,
13014
+ value: text,
13015
+ placeholder,
13016
+ disabled: disabled || loading,
13017
+ sources,
13018
+ chips,
13019
+ onChipsChange: onContextItemsChange,
13020
+ onChange: handleChange,
13021
+ onSubmit: handleSubmit
13022
+ }
13023
+ ) : void 0,
13024
+ onChange: handleChange,
13025
+ onSubmit: handleSubmit
13026
+ }
13027
+ ) }),
13028
+ onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
13029
+ "input",
13030
+ {
13031
+ ref: fileInputRef,
13032
+ type: "file",
13033
+ multiple: true,
13034
+ hidden: true,
13035
+ onChange: (event) => {
13036
+ emitFiles(Array.from(event.target.files ?? []));
13037
+ event.target.value = "";
13038
+ }
13039
+ }
13040
+ ) : null,
13041
+ activePopover !== null ? /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(import_jsx_runtime180.Fragment, { children: [
13042
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { className: "fixed inset-0 z-40", onClick: closePopovers }),
13043
+ activePopover === "model" ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { "data-slot": "composer-model-popover", className: cn(popoverPanelClass, "right-0 left-auto w-48"), role: "listbox", children: models.map((option) => /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
13044
+ "button",
13045
+ {
13046
+ type: "button",
13047
+ role: "option",
13048
+ "aria-selected": option.value === currentModel?.value,
13049
+ className: popoverItemClass,
13050
+ onClick: () => {
13051
+ onModelChange?.(option.value);
13052
+ closePopovers();
13053
+ },
13054
+ children: [
13055
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("span", { className: "min-w-0 flex-1 truncate", children: option.label }),
13056
+ option.value === currentModel?.value ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(Icon, { name: "check", size: 14 }) : null
13057
+ ]
13058
+ },
13059
+ option.value
13060
+ )) }) : /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { "data-slot": "composer-context-popover", className: popoverPanelClass, role: "listbox", children: plusSources.map(
13061
+ (source) => source.items.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)("div", { children: [
13062
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { className: "px-2 py-1 text-xs text-muted-foreground", children: source.label }),
13063
+ source.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
13064
+ "button",
13065
+ {
13066
+ type: "button",
13067
+ className: popoverItemClass,
13068
+ onClick: () => selectContext(item, source),
13069
+ children: [
13070
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(Icon, { name: item.icon ?? source.icon ?? "file-text", size: "sm" }),
13071
+ /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("span", { className: "min-w-0 flex-1 truncate", children: item.label })
13072
+ ]
13073
+ },
13074
+ item.id
13075
+ ))
13076
+ ] }, source.trigger)
13077
+ ) })
13078
+ ] }) : null
13079
+ ]
13080
+ }
13081
+ );
12392
13082
  }
12393
13083
 
12394
13084
  // src/components/chat/ConversationList/index.tsx
12395
- var import_react63 = require("react");
12396
- var import_jsx_runtime180 = require("react/jsx-runtime");
13085
+ var import_react65 = require("react");
13086
+ var import_jsx_runtime181 = require("react/jsx-runtime");
12397
13087
  function ConversationList({ items = [], activeId, searchable, onSelect, onDelete, className, style }) {
12398
- const [innerActive, setInnerActive] = (0, import_react63.useState)();
12399
- const [keyword, setKeyword] = (0, import_react63.useState)("");
13088
+ const [innerActive, setInnerActive] = (0, import_react65.useState)();
13089
+ const [keyword, setKeyword] = (0, import_react65.useState)("");
12400
13090
  const active = activeId ?? innerActive;
12401
- const filtered = (0, import_react63.useMemo)(() => {
13091
+ const filtered = (0, import_react65.useMemo)(() => {
12402
13092
  const query = keyword.trim().toLowerCase();
12403
13093
  if (!query) return items;
12404
13094
  return items.filter(
@@ -12411,10 +13101,10 @@ function ConversationList({ items = [], activeId, searchable, onSelect, onDelete
12411
13101
  }
12412
13102
  onSelect?.(id);
12413
13103
  };
12414
- return /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)("div", { "data-slot": "conversation-list", className: cn("flex w-full flex-col gap-1", className), style, children: [
12415
- searchable ? /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)("div", { className: "relative mb-1", children: [
12416
- /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("span", { className: "absolute top-1/2 left-2 -translate-y-1/2 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(Icon, { name: "search", size: "sm" }) }),
12417
- /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
13104
+ return /* @__PURE__ */ (0, import_jsx_runtime181.jsxs)("div", { "data-slot": "conversation-list", className: cn("flex w-full flex-col gap-1", className), style, children: [
13105
+ searchable ? /* @__PURE__ */ (0, import_jsx_runtime181.jsxs)("div", { className: "relative mb-1", children: [
13106
+ /* @__PURE__ */ (0, import_jsx_runtime181.jsx)("span", { className: "absolute top-1/2 left-2 -translate-y-1/2 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime181.jsx)(Icon, { name: "search", size: "sm" }) }),
13107
+ /* @__PURE__ */ (0, import_jsx_runtime181.jsx)(
12418
13108
  "input",
12419
13109
  {
12420
13110
  "data-slot": "conversation-list-search",
@@ -12425,7 +13115,7 @@ function ConversationList({ items = [], activeId, searchable, onSelect, onDelete
12425
13115
  }
12426
13116
  )
12427
13117
  ] }) : null,
12428
- filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
13118
+ filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime181.jsxs)(
12429
13119
  "div",
12430
13120
  {
12431
13121
  "data-slot": "conversation-list-item",
@@ -12436,12 +13126,12 @@ function ConversationList({ items = [], activeId, searchable, onSelect, onDelete
12436
13126
  ),
12437
13127
  onClick: () => select(item.id),
12438
13128
  children: [
12439
- /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)("div", { className: "min-w-0 flex-1", children: [
12440
- /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { className: cn("truncate text-sm", item.id === active && "font-medium"), children: item.title }),
12441
- item.description ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null
13129
+ /* @__PURE__ */ (0, import_jsx_runtime181.jsxs)("div", { className: "min-w-0 flex-1", children: [
13130
+ /* @__PURE__ */ (0, import_jsx_runtime181.jsx)("div", { className: cn("truncate text-sm", item.id === active && "font-medium"), children: item.title }),
13131
+ item.description ? /* @__PURE__ */ (0, import_jsx_runtime181.jsx)("div", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null
12442
13132
  ] }),
12443
- item.time ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.time }) : null,
12444
- onDelete ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
13133
+ item.time ? /* @__PURE__ */ (0, import_jsx_runtime181.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.time }) : null,
13134
+ onDelete ? /* @__PURE__ */ (0, import_jsx_runtime181.jsx)(
12445
13135
  "button",
12446
13136
  {
12447
13137
  type: "button",
@@ -12452,41 +13142,42 @@ function ConversationList({ items = [], activeId, searchable, onSelect, onDelete
12452
13142
  event.stopPropagation();
12453
13143
  onDelete(item.id);
12454
13144
  },
12455
- children: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(Icon, { name: "trash-2", size: "sm" })
13145
+ children: /* @__PURE__ */ (0, import_jsx_runtime181.jsx)(Icon, { name: "trash-2", size: "sm" })
12456
13146
  }
12457
13147
  ) : null
12458
13148
  ]
12459
13149
  },
12460
13150
  item.id
12461
13151
  )),
12462
- filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { className: "px-2 py-4 text-center text-sm text-muted-foreground", children: "\u65E0\u5339\u914D\u4F1A\u8BDD" }) : null
13152
+ filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime181.jsx)("div", { className: "px-2 py-4 text-center text-sm text-muted-foreground", children: "\u65E0\u5339\u914D\u4F1A\u8BDD" }) : null
12463
13153
  ] });
12464
13154
  }
12465
13155
 
12466
13156
  // src/components/chat/MessageList/index.tsx
12467
- var import_react64 = require("react");
12468
- var import_jsx_runtime181 = require("react/jsx-runtime");
12469
- function MessageList({ messages = [], autoScroll = true, onAction, className, style }) {
12470
- const listRef = (0, import_react64.useRef)(null);
12471
- (0, import_react64.useEffect)(() => {
13157
+ var import_react66 = require("react");
13158
+ var import_jsx_runtime182 = require("react/jsx-runtime");
13159
+ function MessageList({ messages = [], autoScroll = true, onAction, onOpenArtifacts, className, style }) {
13160
+ const listRef = (0, import_react66.useRef)(null);
13161
+ (0, import_react66.useEffect)(() => {
12472
13162
  if (!autoScroll) return;
12473
13163
  const el = listRef.current;
12474
13164
  if (el) {
12475
13165
  el.scrollTop = el.scrollHeight;
12476
13166
  }
12477
13167
  }, [messages, autoScroll]);
12478
- return /* @__PURE__ */ (0, import_jsx_runtime181.jsx)(
13168
+ return /* @__PURE__ */ (0, import_jsx_runtime182.jsx)(
12479
13169
  "div",
12480
13170
  {
12481
13171
  ref: listRef,
12482
13172
  "data-slot": "message-list",
12483
13173
  className: cn("flex w-full flex-col gap-4 overflow-y-auto", className),
12484
13174
  style,
12485
- children: messages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime181.jsx)(
13175
+ children: messages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime182.jsx)(
12486
13176
  ChatMessage,
12487
13177
  {
12488
13178
  ...message,
12489
- onAction: (action) => onAction?.({ id: message.id, action })
13179
+ onAction: (action) => onAction?.({ id: message.id, action }),
13180
+ onOpenArtifacts: onOpenArtifacts ? () => onOpenArtifacts({ id: message.id }) : void 0
12490
13181
  },
12491
13182
  message.id ?? index
12492
13183
  ))
@@ -12495,9 +13186,9 @@ function MessageList({ messages = [], autoScroll = true, onAction, className, st
12495
13186
  }
12496
13187
 
12497
13188
  // src/components/chat/Prompt/index.tsx
12498
- var import_jsx_runtime182 = require("react/jsx-runtime");
13189
+ var import_jsx_runtime183 = require("react/jsx-runtime");
12499
13190
  function Prompt({ title, description, icon, value, disabled, onSelect, className, style }) {
12500
- return /* @__PURE__ */ (0, import_jsx_runtime182.jsxs)(
13191
+ return /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)(
12501
13192
  "button",
12502
13193
  {
12503
13194
  type: "button",
@@ -12510,10 +13201,10 @@ function Prompt({ title, description, icon, value, disabled, onSelect, className
12510
13201
  style,
12511
13202
  onClick: () => onSelect?.(value ?? title ?? ""),
12512
13203
  children: [
12513
- icon ? /* @__PURE__ */ (0, import_jsx_runtime182.jsx)("span", { className: "mt-0.5 shrink-0 text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime182.jsx)(Icon, { name: icon, size: "sm" }) }) : null,
12514
- /* @__PURE__ */ (0, import_jsx_runtime182.jsxs)("span", { className: "min-w-0", children: [
12515
- /* @__PURE__ */ (0, import_jsx_runtime182.jsx)("span", { "data-slot": "prompt-title", className: "block text-sm font-medium", children: title }),
12516
- description ? /* @__PURE__ */ (0, import_jsx_runtime182.jsx)("span", { "data-slot": "prompt-description", className: "mt-0.5 block text-xs text-muted-foreground", children: description }) : null
13204
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { className: "mt-0.5 shrink-0 text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(Icon, { name: icon, size: "sm" }) }) : null,
13205
+ /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)("span", { className: "min-w-0", children: [
13206
+ /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { "data-slot": "prompt-title", className: "block text-sm font-medium", children: title }),
13207
+ description ? /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { "data-slot": "prompt-description", className: "mt-0.5 block text-xs text-muted-foreground", children: description }) : null
12517
13208
  ] })
12518
13209
  ]
12519
13210
  }
@@ -12521,7 +13212,7 @@ function Prompt({ title, description, icon, value, disabled, onSelect, className
12521
13212
  }
12522
13213
 
12523
13214
  // src/components/chat/Welcome/index.tsx
12524
- var import_jsx_runtime183 = require("react/jsx-runtime");
13215
+ var import_jsx_runtime184 = require("react/jsx-runtime");
12525
13216
  function Welcome({
12526
13217
  title = "\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u4F60\uFF1F",
12527
13218
  description,
@@ -12531,19 +13222,19 @@ function Welcome({
12531
13222
  className,
12532
13223
  style
12533
13224
  }) {
12534
- return /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)(
13225
+ return /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(
12535
13226
  "div",
12536
13227
  {
12537
13228
  "data-slot": "welcome",
12538
13229
  className: cn("flex w-full flex-col items-center gap-4 py-10 text-center", className),
12539
13230
  style,
12540
13231
  children: [
12541
- /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { "data-slot": "welcome-icon", className: "text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(Icon, { name: icon, size: "lg" }) }),
12542
- /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)("div", { children: [
12543
- /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("div", { "data-slot": "welcome-title", className: "text-xl font-semibold", children: title }),
12544
- description ? /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("div", { "data-slot": "welcome-description", className: "mt-1 text-sm text-muted-foreground", children: description }) : null
13232
+ /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("span", { "data-slot": "welcome-icon", className: "text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: icon, size: "lg" }) }),
13233
+ /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { children: [
13234
+ /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("div", { "data-slot": "welcome-title", className: "text-xl font-semibold", children: title }),
13235
+ description ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("div", { "data-slot": "welcome-description", className: "mt-1 text-sm text-muted-foreground", children: description }) : null
12545
13236
  ] }),
12546
- prompts.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("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__ */ (0, import_jsx_runtime183.jsx)(
13237
+ prompts.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("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__ */ (0, import_jsx_runtime184.jsx)(
12547
13238
  Prompt,
12548
13239
  {
12549
13240
  title: item.title,
@@ -12560,7 +13251,7 @@ function Welcome({
12560
13251
  }
12561
13252
 
12562
13253
  // src/components/chat/ChatPage/index.tsx
12563
- var import_jsx_runtime184 = require("react/jsx-runtime");
13254
+ var import_jsx_runtime185 = require("react/jsx-runtime");
12564
13255
  function ChatPage({
12565
13256
  brand,
12566
13257
  menuItems = [],
@@ -12586,12 +13277,26 @@ function ChatPage({
12586
13277
  defaultFooterSectionCollapsed = false,
12587
13278
  onFooterSectionToggle,
12588
13279
  conversationTitle,
13280
+ conversationHeaderAction,
13281
+ onConversationHeaderAction,
12589
13282
  messages = [],
12590
13283
  sending,
12591
13284
  composerPlaceholder,
12592
13285
  welcome,
12593
13286
  onSend,
12594
13287
  onMessageAction,
13288
+ models,
13289
+ model,
13290
+ onModelChange,
13291
+ contexts,
13292
+ contextItems,
13293
+ onContextItemsChange,
13294
+ attachments,
13295
+ onAttachFiles,
13296
+ onRemoveAttachment,
13297
+ onRetryAttachment,
13298
+ composerFooter,
13299
+ composerBottom,
12595
13300
  artifactTitle = "\u4EA7\u7269",
12596
13301
  artifacts = [],
12597
13302
  activeArtifactId,
@@ -12602,20 +13307,22 @@ function ChatPage({
12602
13307
  artifactViewers,
12603
13308
  onDownloadArtifact,
12604
13309
  artifactOpen,
12605
- defaultArtifactOpen = true,
13310
+ defaultArtifactOpen = false,
12606
13311
  onArtifactOpenChange,
12607
13312
  className,
12608
13313
  style
12609
13314
  }) {
12610
13315
  const controlled = artifactOpen !== void 0;
12611
- const [innerOpen, setInnerOpen] = (0, import_react65.useState)(defaultArtifactOpen);
13316
+ const [innerOpen, setInnerOpen] = (0, import_react67.useState)(defaultArtifactOpen);
12612
13317
  const open = controlled ? artifactOpen === true : innerOpen;
12613
13318
  const setOpen = (next) => {
12614
13319
  if (!controlled) setInnerOpen(next);
12615
13320
  onArtifactOpenChange?.(next);
12616
13321
  };
13322
+ const { renderChildren } = (0, import_runtime26.useRenderer)();
13323
+ const renderSlot = (slot) => (0, import_react67.isValidElement)(slot) || typeof slot !== "object" || slot === null ? slot : renderChildren([slot]);
12617
13324
  const convCollControlled = conversationSectionCollapsed !== void 0;
12618
- const [convCollapsedInner, setConvCollapsedInner] = (0, import_react65.useState)(
13325
+ const [convCollapsedInner, setConvCollapsedInner] = (0, import_react67.useState)(
12619
13326
  defaultConversationSectionCollapsed
12620
13327
  );
12621
13328
  const convCollapsed = convCollControlled ? conversationSectionCollapsed === true : convCollapsedInner;
@@ -12625,7 +13332,7 @@ function ChatPage({
12625
13332
  onConversationSectionToggle?.(next);
12626
13333
  };
12627
13334
  const footerCollControlled = footerSectionCollapsed !== void 0;
12628
- const [footerCollapsedInner, setFooterCollapsedInner] = (0, import_react65.useState)(
13335
+ const [footerCollapsedInner, setFooterCollapsedInner] = (0, import_react67.useState)(
12629
13336
  defaultFooterSectionCollapsed
12630
13337
  );
12631
13338
  const footerCollapsed = footerCollControlled ? footerSectionCollapsed === true : footerCollapsedInner;
@@ -12635,7 +13342,7 @@ function ChatPage({
12635
13342
  onFooterSectionToggle?.(next);
12636
13343
  };
12637
13344
  const railVisible = railItems.length > 0 || railFooterItems.length > 0;
12638
- const railButton = (item) => /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Tooltip2, { content: item.label, side: "right", children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
13345
+ const railButton = (item) => /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Tooltip2, { content: item.label, side: "right", children: /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
12639
13346
  Button2,
12640
13347
  {
12641
13348
  icon: item.icon,
@@ -12643,17 +13350,25 @@ function ChatPage({
12643
13350
  onClick: () => onMenuSelect?.(item.key)
12644
13351
  }
12645
13352
  ) }, item.key);
12646
- const chatArea = /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { "data-slot": "chat-page-conversation", className: "flex h-full min-w-0 flex-1 flex-col", children: [
12647
- /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(
13353
+ const chatArea = /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)("div", { "data-slot": "chat-page-conversation", className: "flex h-full min-w-0 flex-1 flex-col", children: [
13354
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
12648
13355
  "div",
12649
13356
  {
12650
13357
  className: "flex shrink-0 items-center justify-between border-b border-border px-4 py-2.5",
12651
13358
  children: [
12652
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Text, { text: conversationTitle, strong: true }),
12653
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Tooltip2, { content: artifactTitle, side: "bottom", children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
13359
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Text, { text: conversationTitle, strong: true }),
13360
+ conversationHeaderAction ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Tooltip2, { content: conversationHeaderAction.tooltip ?? conversationHeaderAction.label, side: "bottom", children: /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
12654
13361
  Button2,
12655
13362
  {
12656
- icon: "panel-right-open",
13363
+ text: conversationHeaderAction.label,
13364
+ icon: conversationHeaderAction.icon,
13365
+ variant: "text",
13366
+ onClick: () => onConversationHeaderAction?.()
13367
+ }
13368
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Tooltip2, { content: open ? "\u6536\u8D77\u4EA7\u7269\u533A" : artifactTitle, side: "bottom", children: /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
13369
+ Button2,
13370
+ {
13371
+ icon: open ? "panel-right-close" : "panel-right-open",
12657
13372
  variant: "text",
12658
13373
  onClick: () => setOpen(!open)
12659
13374
  }
@@ -12661,40 +13376,63 @@ function ChatPage({
12661
13376
  ]
12662
13377
  }
12663
13378
  ),
12664
- messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
12665
- Welcome,
12666
- {
12667
- title: welcome?.title,
12668
- description: welcome?.description,
12669
- prompts: welcome?.prompts,
12670
- style: { flex: 1 },
12671
- onSelect: (value) => onSend?.(value)
12672
- }
12673
- ) : /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
12674
- MessageList,
12675
- {
12676
- messages,
12677
- style: { flex: 1, minHeight: 0, padding: 16 },
12678
- onAction: onMessageAction
12679
- }
12680
- ),
12681
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
12682
- Composer,
13379
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
13380
+ "div",
12683
13381
  {
12684
- placeholder: composerPlaceholder,
12685
- loading: sending,
12686
- style: { padding: 16, borderTop: "1px solid var(--border)", flexShrink: 0 },
12687
- onSubmit: (text) => onSend?.(text)
13382
+ "data-slot": "chat-page-conversation-body",
13383
+ className: "mx-auto flex min-h-0 w-[61.8cqw] max-w-full flex-1 flex-col",
13384
+ children: [
13385
+ messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
13386
+ Welcome,
13387
+ {
13388
+ title: welcome?.title,
13389
+ description: welcome?.description,
13390
+ prompts: welcome?.prompts,
13391
+ style: { flex: 1 },
13392
+ onSelect: (value) => onSend?.(value)
13393
+ }
13394
+ ) : /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
13395
+ MessageList,
13396
+ {
13397
+ messages,
13398
+ className: "scrollbar-subtle",
13399
+ style: { flex: 1, minHeight: 0, padding: 16 },
13400
+ onAction: onMessageAction,
13401
+ onOpenArtifacts: () => setOpen(true)
13402
+ }
13403
+ ),
13404
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
13405
+ Composer,
13406
+ {
13407
+ placeholder: composerPlaceholder,
13408
+ loading: sending,
13409
+ models,
13410
+ model,
13411
+ contexts,
13412
+ contextItems,
13413
+ attachments,
13414
+ footer: composerFooter,
13415
+ style: { padding: 16, paddingBottom: composerBottom ? 8 : 16, flexShrink: 0 },
13416
+ onModelChange,
13417
+ onContextItemsChange,
13418
+ onAttachFiles,
13419
+ onRemoveAttachment,
13420
+ onRetryAttachment,
13421
+ onSubmit: (text) => onSend?.(text)
13422
+ }
13423
+ ),
13424
+ composerBottom ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { "data-slot": "chat-page-composer-bottom", className: "shrink-0 px-4 pb-2 text-center", children: renderSlot(composerBottom) }) : null
13425
+ ]
12688
13426
  }
12689
13427
  )
12690
13428
  ] });
12691
13429
  const activeArtifact = artifacts.find((item) => item.id === activeArtifactId) ?? (activeArtifactId === void 0 || activeArtifactId === "" ? artifacts[artifacts.length - 1] : void 0);
12692
- const artifactPanel = /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
13430
+ const artifactPanel = /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
12693
13431
  "div",
12694
13432
  {
12695
13433
  "data-slot": "chat-page-artifact",
12696
13434
  className: "flex h-full min-w-0 flex-col border-l border-border bg-muted",
12697
- children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
13435
+ children: /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
12698
13436
  ArtifactPanel,
12699
13437
  {
12700
13438
  artifact: activeArtifact,
@@ -12712,37 +13450,37 @@ function ChatPage({
12712
13450
  )
12713
13451
  }
12714
13452
  );
12715
- return /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(
13453
+ return /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
12716
13454
  "div",
12717
13455
  {
12718
13456
  "data-slot": "chat-page",
12719
13457
  className: cn("flex w-full overflow-hidden", className),
12720
13458
  style: { height: "100vh", ...style },
12721
13459
  children: [
12722
- railVisible ? /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(
13460
+ railVisible ? /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
12723
13461
  "div",
12724
13462
  {
12725
13463
  "data-slot": "chat-page-rail",
12726
13464
  className: "flex h-full w-[52px] shrink-0 flex-col items-center gap-1 border-r border-border py-2.5",
12727
13465
  children: [
12728
13466
  railItems.map(railButton),
12729
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("div", { className: "flex-1" }),
13467
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { className: "flex-1" }),
12730
13468
  railFooterItems.map(railButton)
12731
13469
  ]
12732
13470
  }
12733
13471
  ) : null,
12734
- /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(
13472
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
12735
13473
  "div",
12736
13474
  {
12737
13475
  "data-slot": "chat-page-menu",
12738
- className: "flex h-full w-[264px] shrink-0 flex-col gap-2 overflow-auto border-r border-border px-2 py-3",
13476
+ className: "flex h-full w-[264px] shrink-0 flex-col gap-2 overflow-hidden border-r border-border px-2 py-3",
12739
13477
  children: [
12740
- brand ? /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { className: "flex items-center justify-between px-2", children: [
12741
- /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
12742
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Text, { text: brand.title, strong: true, size: "large" }),
12743
- brand.version !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Text, { text: brand.version, type: "secondary", size: "small" }) : null
13478
+ brand ? /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)("div", { className: "flex shrink-0 items-center justify-between px-2", children: [
13479
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
13480
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Text, { text: brand.title, strong: true, size: "large" }),
13481
+ brand.version !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Text, { text: brand.version, type: "secondary", size: "small" }) : null
12744
13482
  ] }),
12745
- menuAction ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
13483
+ menuAction ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
12746
13484
  Button2,
12747
13485
  {
12748
13486
  text: menuAction.label,
@@ -12752,24 +13490,24 @@ function ChatPage({
12752
13490
  }
12753
13491
  ) : null
12754
13492
  ] }) : null,
12755
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
13493
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { className: "scrollbar-subtle max-h-[40%] min-h-0 shrink-0 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
12756
13494
  Menu2,
12757
13495
  {
12758
13496
  items: menuItems,
12759
13497
  selectedKey: activeMenuKey,
12760
13498
  onSelect: (key) => onMenuSelect?.(key)
12761
13499
  }
12762
- ),
12763
- conversationSectionTitle !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(
13500
+ ) }),
13501
+ conversationSectionTitle !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
12764
13502
  "button",
12765
13503
  {
12766
13504
  type: "button",
12767
13505
  "data-slot": "chat-page-section-toggle",
12768
13506
  "aria-expanded": !convCollapsed,
12769
- className: "flex w-full cursor-pointer items-center justify-between px-2 pt-2",
13507
+ className: "flex w-full shrink-0 cursor-pointer items-center justify-between px-2 pt-2",
12770
13508
  onClick: toggleConvSection,
12771
13509
  children: [
12772
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
13510
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
12773
13511
  Text,
12774
13512
  {
12775
13513
  text: `${conversationSectionTitle} (${conversations.length})`,
@@ -12778,48 +13516,50 @@ function ChatPage({
12778
13516
  strong: true
12779
13517
  }
12780
13518
  ),
12781
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: convCollapsed ? "chevron-right" : "chevron-down", size: 14 })
13519
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Icon, { name: convCollapsed ? "chevron-right" : "chevron-down", size: 14 })
12782
13520
  ]
12783
13521
  }
12784
13522
  ) : null,
12785
- !convCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
12786
- ConversationList,
12787
- {
12788
- items: conversations,
12789
- activeId: activeConversationId,
12790
- onSelect: (id) => onSelectConversation?.(id),
12791
- onDelete: (id) => onDeleteConversation?.(id)
12792
- }
12793
- ) : null,
12794
- !convCollapsed && moreLabel !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Button2, { text: `${moreLabel} >>`, variant: "link", size: "small", onClick: () => onMore?.() }) }) : null,
12795
- footerSectionTitle !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(
13523
+ !convCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)("div", { "data-slot": "chat-page-section-body", className: "scrollbar-subtle flex min-h-0 flex-1 flex-col overflow-y-auto", children: [
13524
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
13525
+ ConversationList,
13526
+ {
13527
+ items: conversations,
13528
+ activeId: activeConversationId,
13529
+ onSelect: (id) => onSelectConversation?.(id),
13530
+ onDelete: (id) => onDeleteConversation?.(id)
13531
+ }
13532
+ ),
13533
+ moreLabel !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Button2, { text: `${moreLabel} >>`, variant: "link", size: "small", onClick: () => onMore?.() }) }) : null
13534
+ ] }) : null,
13535
+ footerSectionTitle !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
12796
13536
  "button",
12797
13537
  {
12798
13538
  type: "button",
12799
13539
  "data-slot": "chat-page-section-toggle",
12800
13540
  "aria-expanded": !footerCollapsed,
12801
- className: "flex w-full cursor-pointer items-center justify-between px-2 pt-2",
13541
+ className: "flex w-full shrink-0 cursor-pointer items-center justify-between px-2 pt-2",
12802
13542
  onClick: toggleFooterSection,
12803
13543
  children: [
12804
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Text, { text: footerSectionTitle, type: "secondary", className: "text-sm", strong: true }),
12805
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: footerCollapsed ? "chevron-right" : "chevron-down", size: 14 })
13544
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Text, { text: footerSectionTitle, type: "secondary", className: "text-sm", strong: true }),
13545
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Icon, { name: footerCollapsed ? "chevron-right" : "chevron-down", size: 14 })
12806
13546
  ]
12807
13547
  }
12808
13548
  ) : null,
12809
- !footerCollapsed && footerItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
13549
+ !footerCollapsed && footerItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { "data-slot": "chat-page-section-body", className: "scrollbar-subtle min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
12810
13550
  Menu2,
12811
13551
  {
12812
13552
  items: footerItems,
12813
13553
  onSelect: (key) => onMenuSelect?.(key)
12814
13554
  }
12815
- ) : null
13555
+ ) }) : null
12816
13556
  ]
12817
13557
  }
12818
13558
  ),
12819
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("div", { className: "h-full min-w-0 flex-1", children: open ? /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(PanelGroup, { orientation: "horizontal", style: { width: "100%", height: "100%" }, children: [
12820
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Panel, { defaultSize: "62%", children: chatArea }),
12821
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(ResizableHandle, { withHandle: true }),
12822
- /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Panel, { defaultSize: "38%", minSize: "320px", maxSize: "760px", children: artifactPanel })
13559
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { className: "@container h-full min-w-0 flex-1", children: open ? /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(PanelGroup, { orientation: "horizontal", style: { width: "100%", height: "100%" }, children: [
13560
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Panel, { defaultSize: "62%", children: chatArea }),
13561
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(ResizableHandle, { withHandle: true }),
13562
+ /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Panel, { defaultSize: "38%", minSize: "380px", maxSize: "760px", children: artifactPanel })
12823
13563
  ] }) : chatArea })
12824
13564
  ]
12825
13565
  }
@@ -12827,10 +13567,10 @@ function ChatPage({
12827
13567
  }
12828
13568
 
12829
13569
  // src/components/chat/Citation/index.tsx
12830
- var import_jsx_runtime185 = require("react/jsx-runtime");
13570
+ var import_jsx_runtime186 = require("react/jsx-runtime");
12831
13571
  function Citation({ items = [], start = 1, className, style }) {
12832
- return /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("span", { "data-slot": "citation", className: cn("inline-flex gap-1 align-super", className), style, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(HoverCard, { children: [
12833
- /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
13572
+ return /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("span", { "data-slot": "citation", className: cn("inline-flex gap-1 align-super", className), style, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(HoverCard, { children: [
13573
+ /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(
12834
13574
  HoverCardTrigger,
12835
13575
  {
12836
13576
  "data-slot": "citation-marker",
@@ -12842,10 +13582,10 @@ function Citation({ items = [], start = 1, className, style }) {
12842
13582
  ]
12843
13583
  }
12844
13584
  ),
12845
- /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(HoverCardContent, { "data-slot": "citation-card", className: "w-72", children: [
12846
- /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { className: "text-sm font-medium", children: item.title }),
12847
- item.snippet ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { className: "mt-1 line-clamp-3 text-xs text-muted-foreground", children: item.snippet }) : null,
12848
- item.url ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
13585
+ /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(HoverCardContent, { "data-slot": "citation-card", className: "w-72", children: [
13586
+ /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { className: "text-sm font-medium", children: item.title }),
13587
+ item.snippet ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { className: "mt-1 line-clamp-3 text-xs text-muted-foreground", children: item.snippet }) : null,
13588
+ item.url ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
12849
13589
  "a",
12850
13590
  {
12851
13591
  href: item.url,
@@ -12860,13 +13600,13 @@ function Citation({ items = [], start = 1, className, style }) {
12860
13600
  }
12861
13601
 
12862
13602
  // src/components/chat/Suggestion/index.tsx
12863
- var import_jsx_runtime186 = require("react/jsx-runtime");
13603
+ var import_jsx_runtime187 = require("react/jsx-runtime");
12864
13604
  function normalize(item) {
12865
13605
  if (typeof item === "string") return { label: item, value: item };
12866
13606
  return { label: item.label, value: item.value ?? item.label, icon: item.icon };
12867
13607
  }
12868
13608
  function Suggestion({ items = [], justify = "start", onSelect, className, style }) {
12869
- return /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
13609
+ return /* @__PURE__ */ (0, import_jsx_runtime187.jsx)(
12870
13610
  "div",
12871
13611
  {
12872
13612
  "data-slot": "suggestion",
@@ -12874,7 +13614,7 @@ function Suggestion({ items = [], justify = "start", onSelect, className, style
12874
13614
  style,
12875
13615
  children: items.map((item, index) => {
12876
13616
  const { label, value, icon } = normalize(item);
12877
- return /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(
13617
+ return /* @__PURE__ */ (0, import_jsx_runtime187.jsxs)(
12878
13618
  "button",
12879
13619
  {
12880
13620
  type: "button",
@@ -12883,7 +13623,7 @@ function Suggestion({ items = [], justify = "start", onSelect, className, style
12883
13623
  className: "flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-sm transition-colors hover:bg-accent",
12884
13624
  onClick: () => onSelect?.(value),
12885
13625
  children: [
12886
- icon ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { name: icon, size: "sm" }) : null,
13626
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime187.jsx)(Icon, { name: icon, size: "sm" }) : null,
12887
13627
  label
12888
13628
  ]
12889
13629
  },
@@ -12895,7 +13635,7 @@ function Suggestion({ items = [], justify = "start", onSelect, className, style
12895
13635
  }
12896
13636
 
12897
13637
  // src/components/chart/EChartBase/index.tsx
12898
- var import_react66 = require("react");
13638
+ var import_react68 = require("react");
12899
13639
 
12900
13640
  // src/components/chart/echarts-modules.ts
12901
13641
  var echarts = __toESM(require("echarts/core"), 1);
@@ -12926,7 +13666,7 @@ echarts.use([
12926
13666
  ]);
12927
13667
 
12928
13668
  // src/components/chart/EChartBase/index.tsx
12929
- var import_jsx_runtime187 = require("react/jsx-runtime");
13669
+ var import_jsx_runtime188 = require("react/jsx-runtime");
12930
13670
  function EChartBase({
12931
13671
  option,
12932
13672
  height = 256,
@@ -12935,12 +13675,12 @@ function EChartBase({
12935
13675
  style,
12936
13676
  slot
12937
13677
  }) {
12938
- const hostRef = (0, import_react66.useRef)(null);
12939
- const chartRef = (0, import_react66.useRef)(null);
12940
- const onSelectRef = (0, import_react66.useRef)(onSelect);
13678
+ const hostRef = (0, import_react68.useRef)(null);
13679
+ const chartRef = (0, import_react68.useRef)(null);
13680
+ const onSelectRef = (0, import_react68.useRef)(onSelect);
12941
13681
  onSelectRef.current = onSelect;
12942
- const [failed, setFailed] = (0, import_react66.useState)(false);
12943
- (0, import_react66.useEffect)(() => {
13682
+ const [failed, setFailed] = (0, import_react68.useState)(false);
13683
+ (0, import_react68.useEffect)(() => {
12944
13684
  const host = hostRef.current;
12945
13685
  if (!host) return;
12946
13686
  let chart = null;
@@ -12959,22 +13699,22 @@ function EChartBase({
12959
13699
  dataIndex: params.dataIndex
12960
13700
  });
12961
13701
  });
12962
- const observer = new ResizeObserver(() => chart?.resize());
12963
- observer.observe(host);
13702
+ const observer2 = new ResizeObserver(() => chart?.resize());
13703
+ observer2.observe(host);
12964
13704
  return () => {
12965
- observer.disconnect();
13705
+ observer2.disconnect();
12966
13706
  chart?.dispose();
12967
13707
  chartRef.current = null;
12968
13708
  };
12969
13709
  }, []);
12970
- (0, import_react66.useEffect)(() => {
13710
+ (0, import_react68.useEffect)(() => {
12971
13711
  try {
12972
13712
  chartRef.current?.setOption(option, { notMerge: true });
12973
13713
  } catch {
12974
13714
  }
12975
13715
  }, [option]);
12976
13716
  if (failed) {
12977
- return /* @__PURE__ */ (0, import_jsx_runtime187.jsx)(
13717
+ return /* @__PURE__ */ (0, import_jsx_runtime188.jsx)(
12978
13718
  "div",
12979
13719
  {
12980
13720
  "data-slot": "chart-fallback",
@@ -12987,7 +13727,7 @@ function EChartBase({
12987
13727
  }
12988
13728
  );
12989
13729
  }
12990
- return /* @__PURE__ */ (0, import_jsx_runtime187.jsx)(
13730
+ return /* @__PURE__ */ (0, import_jsx_runtime188.jsx)(
12991
13731
  "div",
12992
13732
  {
12993
13733
  ref: hostRef,
@@ -13423,6 +14163,9 @@ function buildComposedOption(input, theme) {
13423
14163
  };
13424
14164
  }
13425
14165
 
14166
+ // src/components/chart/lib/use-chart-theme.ts
14167
+ var import_react69 = require("react");
14168
+
13426
14169
  // src/components/chart/lib/color.ts
13427
14170
  var LPAREN = String.fromCharCode(40);
13428
14171
  var RPAREN = String.fromCharCode(41);
@@ -13519,9 +14262,67 @@ function getChartTheme() {
13519
14262
  return FALLBACK_THEME;
13520
14263
  }
13521
14264
  }
14265
+ function resetChartTheme() {
14266
+ cached = null;
14267
+ }
14268
+ var CHART_SKIN_CHANGE_EVENT = "pactor:skin-change";
14269
+ var listeners = /* @__PURE__ */ new Set();
14270
+ var observer = null;
14271
+ var scheduled = false;
14272
+ function scheduleNotify() {
14273
+ if (scheduled) return;
14274
+ scheduled = true;
14275
+ const enqueue = typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
14276
+ enqueue(() => {
14277
+ scheduled = false;
14278
+ resetChartTheme();
14279
+ for (const listener of [...listeners]) {
14280
+ listener();
14281
+ }
14282
+ });
14283
+ }
14284
+ function handleResourceLoad(event) {
14285
+ const target = event.target;
14286
+ if (target instanceof HTMLLinkElement || target instanceof HTMLStyleElement) {
14287
+ scheduleNotify();
14288
+ }
14289
+ }
14290
+ function subscribeChartTheme(listener) {
14291
+ if (typeof document === "undefined" || typeof MutationObserver === "undefined") {
14292
+ return () => {
14293
+ };
14294
+ }
14295
+ listeners.add(listener);
14296
+ if (!observer) {
14297
+ observer = new MutationObserver(scheduleNotify);
14298
+ observer.observe(document.documentElement, { attributes: true });
14299
+ observer.observe(document.head, {
14300
+ attributes: true,
14301
+ childList: true,
14302
+ characterData: true,
14303
+ subtree: true
14304
+ });
14305
+ document.addEventListener("load", handleResourceLoad, true);
14306
+ window.addEventListener(CHART_SKIN_CHANGE_EVENT, scheduleNotify);
14307
+ }
14308
+ return () => {
14309
+ listeners.delete(listener);
14310
+ if (listeners.size === 0 && observer) {
14311
+ observer.disconnect();
14312
+ observer = null;
14313
+ document.removeEventListener("load", handleResourceLoad, true);
14314
+ window.removeEventListener(CHART_SKIN_CHANGE_EVENT, scheduleNotify);
14315
+ }
14316
+ };
14317
+ }
14318
+
14319
+ // src/components/chart/lib/use-chart-theme.ts
14320
+ function useChartTheme() {
14321
+ return (0, import_react69.useSyncExternalStore)(subscribeChartTheme, getChartTheme, getChartTheme);
14322
+ }
13522
14323
 
13523
14324
  // src/components/chart/AreaChart/index.tsx
13524
- var import_jsx_runtime188 = require("react/jsx-runtime");
14325
+ var import_jsx_runtime189 = require("react/jsx-runtime");
13525
14326
  function AreaChart({
13526
14327
  data = [],
13527
14328
  xKey,
@@ -13537,9 +14338,9 @@ function AreaChart({
13537
14338
  }) {
13538
14339
  const option = buildAreaOption(
13539
14340
  { data, xKey, yKeys, stacked, fillOpacity, colors, title },
13540
- getChartTheme()
14341
+ useChartTheme()
13541
14342
  );
13542
- return /* @__PURE__ */ (0, import_jsx_runtime188.jsx)(
14343
+ return /* @__PURE__ */ (0, import_jsx_runtime189.jsx)(
13543
14344
  EChartBase,
13544
14345
  {
13545
14346
  slot: "area-chart",
@@ -13553,7 +14354,7 @@ function AreaChart({
13553
14354
  }
13554
14355
 
13555
14356
  // src/components/chart/BarChart/index.tsx
13556
- var import_jsx_runtime189 = require("react/jsx-runtime");
14357
+ var import_jsx_runtime190 = require("react/jsx-runtime");
13557
14358
  function BarChart2({
13558
14359
  data = [],
13559
14360
  yKey,
@@ -13568,9 +14369,9 @@ function BarChart2({
13568
14369
  }) {
13569
14370
  const option = buildBarOption(
13570
14371
  { data, yKey, yKeys: xKeys, stacked, colors, title },
13571
- getChartTheme()
14372
+ useChartTheme()
13572
14373
  );
13573
- return /* @__PURE__ */ (0, import_jsx_runtime189.jsx)(
14374
+ return /* @__PURE__ */ (0, import_jsx_runtime190.jsx)(
13574
14375
  EChartBase,
13575
14376
  {
13576
14377
  slot: "bar-chart",
@@ -13584,7 +14385,7 @@ function BarChart2({
13584
14385
  }
13585
14386
 
13586
14387
  // src/components/chart/BubbleChart/index.tsx
13587
- var import_jsx_runtime190 = require("react/jsx-runtime");
14388
+ var import_jsx_runtime191 = require("react/jsx-runtime");
13588
14389
  function BubbleChart({
13589
14390
  data = [],
13590
14391
  xKey,
@@ -13600,9 +14401,9 @@ function BubbleChart({
13600
14401
  }) {
13601
14402
  const option = buildBubbleOption(
13602
14403
  { data, xKey, yKey, sizeKey, seriesKey, colors, title },
13603
- getChartTheme()
14404
+ useChartTheme()
13604
14405
  );
13605
- return /* @__PURE__ */ (0, import_jsx_runtime190.jsx)(
14406
+ return /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
13606
14407
  EChartBase,
13607
14408
  {
13608
14409
  slot: "bubble-chart",
@@ -13616,7 +14417,7 @@ function BubbleChart({
13616
14417
  }
13617
14418
 
13618
14419
  // src/components/chart/ColumnChart/index.tsx
13619
- var import_jsx_runtime191 = require("react/jsx-runtime");
14420
+ var import_jsx_runtime192 = require("react/jsx-runtime");
13620
14421
  function ColumnChart({
13621
14422
  data = [],
13622
14423
  xKey,
@@ -13631,9 +14432,9 @@ function ColumnChart({
13631
14432
  }) {
13632
14433
  const option = buildColumnOption(
13633
14434
  { data, xKey, yKeys, stacked, colors, title },
13634
- getChartTheme()
14435
+ useChartTheme()
13635
14436
  );
13636
- return /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
14437
+ return /* @__PURE__ */ (0, import_jsx_runtime192.jsx)(
13637
14438
  EChartBase,
13638
14439
  {
13639
14440
  slot: "column-chart",
@@ -13647,7 +14448,7 @@ function ColumnChart({
13647
14448
  }
13648
14449
 
13649
14450
  // src/components/chart/ComposedChart/index.tsx
13650
- var import_jsx_runtime192 = require("react/jsx-runtime");
14451
+ var import_jsx_runtime193 = require("react/jsx-runtime");
13651
14452
  function ComposedChart({
13652
14453
  data = [],
13653
14454
  xKey,
@@ -13661,9 +14462,9 @@ function ComposedChart({
13661
14462
  }) {
13662
14463
  const option = buildComposedOption(
13663
14464
  { data, xKey, series, colors, title },
13664
- getChartTheme()
14465
+ useChartTheme()
13665
14466
  );
13666
- return /* @__PURE__ */ (0, import_jsx_runtime192.jsx)(
14467
+ return /* @__PURE__ */ (0, import_jsx_runtime193.jsx)(
13667
14468
  EChartBase,
13668
14469
  {
13669
14470
  slot: "composed-chart",
@@ -13677,7 +14478,7 @@ function ComposedChart({
13677
14478
  }
13678
14479
 
13679
14480
  // src/components/chart/DonutChart/index.tsx
13680
- var import_jsx_runtime193 = require("react/jsx-runtime");
14481
+ var import_jsx_runtime194 = require("react/jsx-runtime");
13681
14482
  function DonutChart({
13682
14483
  data = [],
13683
14484
  nameKey,
@@ -13707,9 +14508,9 @@ function DonutChart({
13707
14508
  colors,
13708
14509
  title
13709
14510
  },
13710
- getChartTheme()
14511
+ useChartTheme()
13711
14512
  );
13712
- return /* @__PURE__ */ (0, import_jsx_runtime193.jsx)(
14513
+ return /* @__PURE__ */ (0, import_jsx_runtime194.jsx)(
13713
14514
  EChartBase,
13714
14515
  {
13715
14516
  slot: "donut-chart",
@@ -13723,7 +14524,7 @@ function DonutChart({
13723
14524
  }
13724
14525
 
13725
14526
  // src/components/chart/FunnelChart/index.tsx
13726
- var import_jsx_runtime194 = require("react/jsx-runtime");
14527
+ var import_jsx_runtime195 = require("react/jsx-runtime");
13727
14528
  function FunnelChart2({
13728
14529
  data = [],
13729
14530
  nameKey,
@@ -13738,9 +14539,9 @@ function FunnelChart2({
13738
14539
  }) {
13739
14540
  const option = buildFunnelOption(
13740
14541
  { data, nameKey, valueKey, sort, colors, title },
13741
- getChartTheme()
14542
+ useChartTheme()
13742
14543
  );
13743
- return /* @__PURE__ */ (0, import_jsx_runtime194.jsx)(
14544
+ return /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
13744
14545
  EChartBase,
13745
14546
  {
13746
14547
  slot: "funnel-chart",
@@ -13754,7 +14555,7 @@ function FunnelChart2({
13754
14555
  }
13755
14556
 
13756
14557
  // src/components/chart/GaugeChart/index.tsx
13757
- var import_jsx_runtime195 = require("react/jsx-runtime");
14558
+ var import_jsx_runtime196 = require("react/jsx-runtime");
13758
14559
  function GaugeChart2({
13759
14560
  value = 0,
13760
14561
  min,
@@ -13769,9 +14570,9 @@ function GaugeChart2({
13769
14570
  }) {
13770
14571
  const option = buildGaugeOption(
13771
14572
  { value, min, max, thresholds, unit, title },
13772
- getChartTheme()
14573
+ useChartTheme()
13773
14574
  );
13774
- return /* @__PURE__ */ (0, import_jsx_runtime195.jsx)(
14575
+ return /* @__PURE__ */ (0, import_jsx_runtime196.jsx)(
13775
14576
  EChartBase,
13776
14577
  {
13777
14578
  slot: "gauge-chart",
@@ -13785,7 +14586,7 @@ function GaugeChart2({
13785
14586
  }
13786
14587
 
13787
14588
  // src/components/chart/Heatmap/index.tsx
13788
- var import_jsx_runtime196 = require("react/jsx-runtime");
14589
+ var import_jsx_runtime197 = require("react/jsx-runtime");
13789
14590
  function Heatmap({
13790
14591
  data = [],
13791
14592
  xKey,
@@ -13799,9 +14600,9 @@ function Heatmap({
13799
14600
  }) {
13800
14601
  const option = buildHeatmapOption(
13801
14602
  { data, xKey, yKey, valueKey, title },
13802
- getChartTheme()
14603
+ useChartTheme()
13803
14604
  );
13804
- return /* @__PURE__ */ (0, import_jsx_runtime196.jsx)(
14605
+ return /* @__PURE__ */ (0, import_jsx_runtime197.jsx)(
13805
14606
  EChartBase,
13806
14607
  {
13807
14608
  slot: "heatmap",
@@ -13815,7 +14616,7 @@ function Heatmap({
13815
14616
  }
13816
14617
 
13817
14618
  // src/components/chart/LineChart/index.tsx
13818
- var import_jsx_runtime197 = require("react/jsx-runtime");
14619
+ var import_jsx_runtime198 = require("react/jsx-runtime");
13819
14620
  function LineChart2({
13820
14621
  data = [],
13821
14622
  xKey,
@@ -13832,9 +14633,9 @@ function LineChart2({
13832
14633
  }) {
13833
14634
  const option = buildLineOption(
13834
14635
  { data, xKey, yKeys, smooth, showArea, stacked, colors, title },
13835
- getChartTheme()
14636
+ useChartTheme()
13836
14637
  );
13837
- return /* @__PURE__ */ (0, import_jsx_runtime197.jsx)(
14638
+ return /* @__PURE__ */ (0, import_jsx_runtime198.jsx)(
13838
14639
  EChartBase,
13839
14640
  {
13840
14641
  slot: "line-chart",
@@ -13848,8 +14649,8 @@ function LineChart2({
13848
14649
  }
13849
14650
 
13850
14651
  // src/components/chart/MapChart/index.tsx
13851
- var import_react67 = require("react");
13852
- var import_jsx_runtime198 = require("react/jsx-runtime");
14652
+ var import_react70 = require("react");
14653
+ var import_jsx_runtime199 = require("react/jsx-runtime");
13853
14654
  var fetchedMaps = /* @__PURE__ */ new Set();
13854
14655
  function hasRegisteredMap(mapName) {
13855
14656
  try {
@@ -13871,7 +14672,8 @@ function MapChart2({
13871
14672
  className,
13872
14673
  style
13873
14674
  }) {
13874
- const [loadState, setLoadState] = (0, import_react67.useState)(
14675
+ const theme = useChartTheme();
14676
+ const [loadState, setLoadState] = (0, import_react70.useState)(
13875
14677
  () => geoJson || !geoJsonUrl || hasRegisteredMap(mapName) ? "idle" : "loading"
13876
14678
  );
13877
14679
  if (geoJson) {
@@ -13880,7 +14682,7 @@ function MapChart2({
13880
14682
  } catch {
13881
14683
  }
13882
14684
  }
13883
- (0, import_react67.useEffect)(() => {
14685
+ (0, import_react70.useEffect)(() => {
13884
14686
  if (geoJson || !geoJsonUrl || hasRegisteredMap(mapName) || fetchedMaps.has(mapName)) {
13885
14687
  setLoadState("idle");
13886
14688
  return;
@@ -13905,7 +14707,7 @@ function MapChart2({
13905
14707
  };
13906
14708
  }, [geoJson, geoJsonUrl, mapName]);
13907
14709
  if (geoJsonUrl && !geoJson && loadState === "loading") {
13908
- return /* @__PURE__ */ (0, import_jsx_runtime198.jsx)(
14710
+ return /* @__PURE__ */ (0, import_jsx_runtime199.jsx)(
13909
14711
  "div",
13910
14712
  {
13911
14713
  "data-slot": "map-chart-loading",
@@ -13915,7 +14717,7 @@ function MapChart2({
13915
14717
  );
13916
14718
  }
13917
14719
  if (!geoJson && loadState === "error") {
13918
- return /* @__PURE__ */ (0, import_jsx_runtime198.jsx)(
14720
+ return /* @__PURE__ */ (0, import_jsx_runtime199.jsx)(
13919
14721
  Empty2,
13920
14722
  {
13921
14723
  title: "\u5730\u56FE\u52A0\u8F7D\u5931\u8D25",
@@ -13927,7 +14729,7 @@ function MapChart2({
13927
14729
  }
13928
14730
  if (!geoJson && !hasRegisteredMap(mapName)) {
13929
14731
  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`);
13930
- return /* @__PURE__ */ (0, import_jsx_runtime198.jsx)(
14732
+ return /* @__PURE__ */ (0, import_jsx_runtime199.jsx)(
13931
14733
  Empty2,
13932
14734
  {
13933
14735
  title: "\u5730\u56FE\u672A\u6CE8\u518C",
@@ -13937,8 +14739,8 @@ function MapChart2({
13937
14739
  }
13938
14740
  );
13939
14741
  }
13940
- const option = buildMapOption({ mapName, data, nameKey, valueKey, title }, getChartTheme());
13941
- return /* @__PURE__ */ (0, import_jsx_runtime198.jsx)(
14742
+ const option = buildMapOption({ mapName, data, nameKey, valueKey, title }, theme);
14743
+ return /* @__PURE__ */ (0, import_jsx_runtime199.jsx)(
13942
14744
  EChartBase,
13943
14745
  {
13944
14746
  slot: "map-chart",
@@ -13953,7 +14755,7 @@ function MapChart2({
13953
14755
 
13954
14756
  // src/components/chart/MetricCard/index.tsx
13955
14757
  var import_lucide_react37 = require("lucide-react");
13956
- var import_jsx_runtime199 = require("react/jsx-runtime");
14758
+ var import_jsx_runtime200 = require("react/jsx-runtime");
13957
14759
  function MetricCard({
13958
14760
  title,
13959
14761
  value,
@@ -13966,15 +14768,15 @@ function MetricCard({
13966
14768
  }) {
13967
14769
  const showTrend = typeof trend === "number" && trend !== 0;
13968
14770
  const rising = (trend ?? 0) > 0;
13969
- return /* @__PURE__ */ (0, import_jsx_runtime199.jsxs)(
14771
+ return /* @__PURE__ */ (0, import_jsx_runtime200.jsxs)(
13970
14772
  "div",
13971
14773
  {
13972
14774
  "data-slot": "metric-card",
13973
14775
  className: cn("rounded-lg border bg-card p-4 text-card-foreground shadow-sm", className),
13974
14776
  style,
13975
14777
  children: [
13976
- title ? /* @__PURE__ */ (0, import_jsx_runtime199.jsx)("div", { "data-slot": "metric-card-title", className: "text-sm text-muted-foreground", children: title }) : null,
13977
- /* @__PURE__ */ (0, import_jsx_runtime199.jsxs)(
14778
+ title ? /* @__PURE__ */ (0, import_jsx_runtime200.jsx)("div", { "data-slot": "metric-card-title", className: "text-sm text-muted-foreground", children: title }) : null,
14779
+ /* @__PURE__ */ (0, import_jsx_runtime200.jsxs)(
13978
14780
  "div",
13979
14781
  {
13980
14782
  "data-slot": "metric-card-value",
@@ -13986,7 +14788,7 @@ function MetricCard({
13986
14788
  ]
13987
14789
  }
13988
14790
  ),
13989
- showTrend ? /* @__PURE__ */ (0, import_jsx_runtime199.jsxs)(
14791
+ showTrend ? /* @__PURE__ */ (0, import_jsx_runtime200.jsxs)(
13990
14792
  "div",
13991
14793
  {
13992
14794
  "data-slot": "metric-card-trend",
@@ -13996,10 +14798,10 @@ function MetricCard({
13996
14798
  rising ? "text-success" : "text-destructive"
13997
14799
  ),
13998
14800
  children: [
13999
- rising ? /* @__PURE__ */ (0, import_jsx_runtime199.jsx)(import_lucide_react37.ArrowUpRight, { className: "size-4" }) : /* @__PURE__ */ (0, import_jsx_runtime199.jsx)(import_lucide_react37.ArrowDownRight, { className: "size-4" }),
14801
+ rising ? /* @__PURE__ */ (0, import_jsx_runtime200.jsx)(import_lucide_react37.ArrowUpRight, { className: "size-4" }) : /* @__PURE__ */ (0, import_jsx_runtime200.jsx)(import_lucide_react37.ArrowDownRight, { className: "size-4" }),
14000
14802
  Math.abs(trend ?? 0),
14001
14803
  "%",
14002
- trendLabel ? /* @__PURE__ */ (0, import_jsx_runtime199.jsx)("span", { className: "ml-1 text-muted-foreground", children: trendLabel }) : null
14804
+ trendLabel ? /* @__PURE__ */ (0, import_jsx_runtime200.jsx)("span", { className: "ml-1 text-muted-foreground", children: trendLabel }) : null
14003
14805
  ]
14004
14806
  }
14005
14807
  ) : null
@@ -14009,7 +14811,7 @@ function MetricCard({
14009
14811
  }
14010
14812
 
14011
14813
  // src/components/chart/PieChart/index.tsx
14012
- var import_jsx_runtime200 = require("react/jsx-runtime");
14814
+ var import_jsx_runtime201 = require("react/jsx-runtime");
14013
14815
  function PieChart2({
14014
14816
  data = [],
14015
14817
  nameKey,
@@ -14024,9 +14826,9 @@ function PieChart2({
14024
14826
  }) {
14025
14827
  const option = buildPieOption(
14026
14828
  { data, nameKey, valueKey, showLabel, colors, title },
14027
- getChartTheme()
14829
+ useChartTheme()
14028
14830
  );
14029
- return /* @__PURE__ */ (0, import_jsx_runtime200.jsx)(
14831
+ return /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(
14030
14832
  EChartBase,
14031
14833
  {
14032
14834
  slot: "pie-chart",
@@ -14040,7 +14842,7 @@ function PieChart2({
14040
14842
  }
14041
14843
 
14042
14844
  // src/components/chart/RadarChart/index.tsx
14043
- var import_jsx_runtime201 = require("react/jsx-runtime");
14845
+ var import_jsx_runtime202 = require("react/jsx-runtime");
14044
14846
  function RadarChart2({
14045
14847
  data = [],
14046
14848
  indicatorKey,
@@ -14054,9 +14856,9 @@ function RadarChart2({
14054
14856
  }) {
14055
14857
  const option = buildRadarOption(
14056
14858
  { data, indicatorKey, yKeys, colors, title },
14057
- getChartTheme()
14859
+ useChartTheme()
14058
14860
  );
14059
- return /* @__PURE__ */ (0, import_jsx_runtime201.jsx)(
14861
+ return /* @__PURE__ */ (0, import_jsx_runtime202.jsx)(
14060
14862
  EChartBase,
14061
14863
  {
14062
14864
  slot: "radar-chart",
@@ -14070,7 +14872,7 @@ function RadarChart2({
14070
14872
  }
14071
14873
 
14072
14874
  // src/components/chart/SankeyChart/index.tsx
14073
- var import_jsx_runtime202 = require("react/jsx-runtime");
14875
+ var import_jsx_runtime203 = require("react/jsx-runtime");
14074
14876
  function SankeyChart2({
14075
14877
  nodes = [],
14076
14878
  links = [],
@@ -14080,8 +14882,8 @@ function SankeyChart2({
14080
14882
  className,
14081
14883
  style
14082
14884
  }) {
14083
- const option = buildSankeyOption({ nodes, links, title }, getChartTheme());
14084
- return /* @__PURE__ */ (0, import_jsx_runtime202.jsx)(
14885
+ const option = buildSankeyOption({ nodes, links, title }, useChartTheme());
14886
+ return /* @__PURE__ */ (0, import_jsx_runtime203.jsx)(
14085
14887
  EChartBase,
14086
14888
  {
14087
14889
  slot: "sankey-chart",
@@ -14095,7 +14897,7 @@ function SankeyChart2({
14095
14897
  }
14096
14898
 
14097
14899
  // src/components/chart/ScatterChart/index.tsx
14098
- var import_jsx_runtime203 = require("react/jsx-runtime");
14900
+ var import_jsx_runtime204 = require("react/jsx-runtime");
14099
14901
  function ScatterChart2({
14100
14902
  data = [],
14101
14903
  xKey,
@@ -14110,9 +14912,9 @@ function ScatterChart2({
14110
14912
  }) {
14111
14913
  const option = buildScatterOption(
14112
14914
  { data, xKey, yKey, seriesKey, colors, title },
14113
- getChartTheme()
14915
+ useChartTheme()
14114
14916
  );
14115
- return /* @__PURE__ */ (0, import_jsx_runtime203.jsx)(
14917
+ return /* @__PURE__ */ (0, import_jsx_runtime204.jsx)(
14116
14918
  EChartBase,
14117
14919
  {
14118
14920
  slot: "scatter-chart",
@@ -14126,7 +14928,7 @@ function ScatterChart2({
14126
14928
  }
14127
14929
 
14128
14930
  // src/components/chart/TreeChart/index.tsx
14129
- var import_jsx_runtime204 = require("react/jsx-runtime");
14931
+ var import_jsx_runtime205 = require("react/jsx-runtime");
14130
14932
  function TreeChart2({
14131
14933
  data = [],
14132
14934
  title,
@@ -14140,9 +14942,9 @@ function TreeChart2({
14140
14942
  }) {
14141
14943
  const option = buildTreeOption(
14142
14944
  { data, title, orient, edgeShape, initialTreeDepth },
14143
- getChartTheme()
14945
+ useChartTheme()
14144
14946
  );
14145
- return /* @__PURE__ */ (0, import_jsx_runtime204.jsx)(
14947
+ return /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
14146
14948
  EChartBase,
14147
14949
  {
14148
14950
  slot: "tree-chart",
@@ -14376,11 +15178,11 @@ function collectDefaultOpenKeys(registry, activeMenuId) {
14376
15178
  // src/layout/admin/AdminLayout.tsx
14377
15179
  var import_permission = require("@pactor-app/permission");
14378
15180
  var import_router = require("@pactor-app/router");
14379
- var import_runtime26 = require("@pactor-app/runtime");
14380
- var import_react69 = require("react");
15181
+ var import_runtime27 = require("@pactor-app/runtime");
15182
+ var import_react72 = require("react");
14381
15183
 
14382
15184
  // src/layout/admin/use-media-query.ts
14383
- var import_react68 = require("react");
15185
+ var import_react71 = require("react");
14384
15186
  var BREAKPOINT_PX = {
14385
15187
  xs: 480,
14386
15188
  sm: 576,
@@ -14390,10 +15192,10 @@ var BREAKPOINT_PX = {
14390
15192
  xxl: 1600
14391
15193
  };
14392
15194
  function useMediaQuery(query) {
14393
- const [matches, setMatches] = (0, import_react68.useState)(
15195
+ const [matches, setMatches] = (0, import_react71.useState)(
14394
15196
  () => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false
14395
15197
  );
14396
- (0, import_react68.useEffect)(() => {
15198
+ (0, import_react71.useEffect)(() => {
14397
15199
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
14398
15200
  return;
14399
15201
  }
@@ -14413,7 +15215,7 @@ function useBreakpointBelow(breakpoint) {
14413
15215
  }
14414
15216
 
14415
15217
  // src/layout/admin/AdminLayout.tsx
14416
- var import_jsx_runtime205 = require("react/jsx-runtime");
15218
+ var import_jsx_runtime206 = require("react/jsx-runtime");
14417
15219
  function buildVisibleMenuTree(registry, permissionChecker) {
14418
15220
  const tree = registry.tree();
14419
15221
  return permissionChecker === void 0 ? [...tree] : (0, import_permission.filterMenusByPermission)(tree, permissionChecker);
@@ -14436,8 +15238,8 @@ function CollapsedGroupFlyout({
14436
15238
  activeMenuId,
14437
15239
  defaultOpenKeys
14438
15240
  }) {
14439
- const [open, setOpen] = (0, import_react69.useState)(false);
14440
- const closeTimer = (0, import_react69.useRef)(void 0);
15241
+ const [open, setOpen] = (0, import_react72.useState)(false);
15242
+ const closeTimer = (0, import_react72.useRef)(void 0);
14441
15243
  const openNow = () => {
14442
15244
  window.clearTimeout(closeTimer.current);
14443
15245
  setOpen(true);
@@ -14446,12 +15248,12 @@ function CollapsedGroupFlyout({
14446
15248
  window.clearTimeout(closeTimer.current);
14447
15249
  closeTimer.current = window.setTimeout(() => setOpen(false), 200);
14448
15250
  };
14449
- (0, import_react69.useEffect)(() => () => window.clearTimeout(closeTimer.current), []);
14450
- return /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(Popover, { open, onOpenChange: setOpen, children: [
14451
- /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15251
+ (0, import_react72.useEffect)(() => () => window.clearTimeout(closeTimer.current), []);
15252
+ return /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(Popover, { open, onOpenChange: setOpen, children: [
15253
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14452
15254
  PopoverTrigger,
14453
15255
  {
14454
- render: /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15256
+ render: /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14455
15257
  "button",
14456
15258
  {
14457
15259
  type: "button",
@@ -14469,7 +15271,7 @@ function CollapsedGroupFlyout({
14469
15271
  )
14470
15272
  }
14471
15273
  ),
14472
- /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(
15274
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(
14473
15275
  PopoverContent,
14474
15276
  {
14475
15277
  "data-slot": "menu-flyout",
@@ -14486,8 +15288,8 @@ function CollapsedGroupFlyout({
14486
15288
  }
14487
15289
  },
14488
15290
  children: [
14489
- /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("div", { className: "px-3 pt-2 pb-1 text-xs font-semibold text-muted-foreground", children: menu.title }),
14490
- /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15291
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("div", { className: "px-3 pt-2 pb-1 text-xs font-semibold text-muted-foreground", children: menu.title }),
15292
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14491
15293
  MenuTree,
14492
15294
  {
14493
15295
  menus: menu.children ?? [],
@@ -14511,9 +15313,9 @@ function MenuTree({
14511
15313
  collapsed = false
14512
15314
  }) {
14513
15315
  if (collapsed) {
14514
- return /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("div", { "data-slot": "menu", "data-collapsed": "true", className: "flex flex-col gap-1", children: menus.map((menu) => {
15316
+ return /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("div", { "data-slot": "menu", "data-collapsed": "true", className: "flex flex-col gap-1", children: menus.map((menu) => {
14515
15317
  if (menu.type === "group") {
14516
- return /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15318
+ return /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14517
15319
  CollapsedGroupFlyout,
14518
15320
  {
14519
15321
  menu,
@@ -14525,7 +15327,7 @@ function MenuTree({
14525
15327
  menu.id
14526
15328
  );
14527
15329
  }
14528
- return /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15330
+ return /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14529
15331
  "button",
14530
15332
  {
14531
15333
  type: "button",
@@ -14545,7 +15347,7 @@ function MenuTree({
14545
15347
  );
14546
15348
  }) });
14547
15349
  }
14548
- return /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15350
+ return /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14549
15351
  Accordion,
14550
15352
  {
14551
15353
  type: "multiple",
@@ -14554,27 +15356,27 @@ function MenuTree({
14554
15356
  className: "flex flex-col gap-0.5 px-2",
14555
15357
  children: menus.map((menu) => {
14556
15358
  if (menu.type === "group") {
14557
- return /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(
15359
+ return /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(
14558
15360
  AccordionItem,
14559
15361
  {
14560
15362
  value: menu.id,
14561
15363
  "data-slot": "menu-group",
14562
15364
  className: "border-b-0",
14563
15365
  children: [
14564
- /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15366
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14565
15367
  AccordionTrigger,
14566
15368
  {
14567
15369
  "data-slot": "menu-group-trigger",
14568
15370
  className: cn(menuItemClass2, "py-2 font-medium"),
14569
15371
  disabled: menu.disabled,
14570
15372
  title: menu.title,
14571
- children: /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)("span", { className: "inline-flex items-center gap-2", children: [
14572
- menu.icon ? /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(Icon, { name: menu.icon, size: "sm" }) : null,
15373
+ children: /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)("span", { className: "inline-flex items-center gap-2", children: [
15374
+ menu.icon ? /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(Icon, { name: menu.icon, size: "sm" }) : null,
14573
15375
  menu.title
14574
15376
  ] })
14575
15377
  }
14576
15378
  ),
14577
- /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(AccordionContent, { "data-slot": "menu-group-content", className: "pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("div", { className: "flex flex-col gap-0.5 pl-3", children: /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15379
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(AccordionContent, { "data-slot": "menu-group-content", className: "pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("div", { className: "flex flex-col gap-0.5 pl-3", children: /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14578
15380
  MenuTree,
14579
15381
  {
14580
15382
  menus: menu.children ?? [],
@@ -14589,7 +15391,7 @@ function MenuTree({
14589
15391
  menu.id
14590
15392
  );
14591
15393
  }
14592
- return /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(
15394
+ return /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(
14593
15395
  "button",
14594
15396
  {
14595
15397
  type: "button",
@@ -14603,7 +15405,7 @@ function MenuTree({
14603
15405
  title: menu.title,
14604
15406
  onClick: () => navigateMenuItem(registry.findById(menu.id), bridge),
14605
15407
  children: [
14606
- menu.icon ? /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(Icon, { name: menu.icon, size: "sm" }) : null,
15408
+ menu.icon ? /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(Icon, { name: menu.icon, size: "sm" }) : null,
14607
15409
  menu.title
14608
15410
  ]
14609
15411
  },
@@ -14623,23 +15425,23 @@ function AdminLayout({
14623
15425
  headerExtra,
14624
15426
  children
14625
15427
  }) {
14626
- const { t } = (0, import_runtime26.useI18n)();
15428
+ const { t } = (0, import_runtime27.useI18n)();
14627
15429
  const mode = config.mode ?? "top-side";
14628
15430
  const showHeader = config.header ?? true;
14629
15431
  const showSidebar = (config.sidebar ?? true) && mode !== "top-bottom";
14630
15432
  const showTabs = config.tabs ?? false;
14631
15433
  const showBreadcrumb = config.breadcrumb ?? false;
14632
15434
  const showFooter = config.footer ?? false;
14633
- const [collapsed, setCollapsed] = (0, import_react69.useState)(config.collapsed ?? false);
15435
+ const [collapsed, setCollapsed] = (0, import_react72.useState)(config.collapsed ?? false);
14634
15436
  const broken = useBreakpointBelow(config.breakpoint);
14635
15437
  const effectiveCollapsed = collapsed || broken;
14636
- const [bridgeRoute, setBridgeRoute] = (0, import_react69.useState)(
15438
+ const [bridgeRoute, setBridgeRoute] = (0, import_react72.useState)(
14637
15439
  () => (0, import_router.resolveRoute)(registry, bridge.getLocation())
14638
15440
  );
14639
- const [tabs, setTabs] = (0, import_react69.useState)([]);
14640
- const tabsRef = (0, import_react69.useRef)(tabs);
15441
+ const [tabs, setTabs] = (0, import_react72.useState)([]);
15442
+ const tabsRef = (0, import_react72.useRef)(tabs);
14641
15443
  tabsRef.current = tabs;
14642
- (0, import_react69.useEffect)(() => {
15444
+ (0, import_react72.useEffect)(() => {
14643
15445
  const handleLocation = (location) => {
14644
15446
  const next = (0, import_router.resolveRoute)(registry, location);
14645
15447
  setBridgeRoute(next);
@@ -14660,16 +15462,16 @@ function AdminLayout({
14660
15462
  }, [registry, bridge]);
14661
15463
  const route = routeProp ?? bridgeRoute;
14662
15464
  const activeMenuId = route?.activeMenu;
14663
- const visibleMenus = (0, import_react69.useMemo)(
15465
+ const visibleMenus = (0, import_react72.useMemo)(
14664
15466
  () => buildVisibleMenuTree(registry, permissionChecker),
14665
15467
  [registry, permissionChecker]
14666
15468
  );
14667
- const defaultOpenKeysRef = (0, import_react69.useRef)(null);
15469
+ const defaultOpenKeysRef = (0, import_react72.useRef)(null);
14668
15470
  if (defaultOpenKeysRef.current === null) {
14669
15471
  defaultOpenKeysRef.current = collectDefaultOpenKeys(registry, activeMenuId);
14670
15472
  }
14671
15473
  const defaultOpenKeys = defaultOpenKeysRef.current;
14672
- const activeTopId = (0, import_react69.useMemo)(() => {
15474
+ const activeTopId = (0, import_react72.useMemo)(() => {
14673
15475
  if (activeMenuId !== void 0) {
14674
15476
  const chain = findMenuChain(registry, activeMenuId);
14675
15477
  if (chain.length > 0) {
@@ -14678,11 +15480,11 @@ function AdminLayout({
14678
15480
  }
14679
15481
  return void 0;
14680
15482
  }, [registry, activeMenuId]);
14681
- const [selectedTopId, setSelectedTopId] = (0, import_react69.useState)();
15483
+ const [selectedTopId, setSelectedTopId] = (0, import_react72.useState)();
14682
15484
  const secondaryTopId = selectedTopId ?? activeTopId ?? visibleMenus.find((m) => m.type === "group")?.id ?? visibleMenus[0]?.id;
14683
15485
  const secondaryTop = visibleMenus.find((m) => m.id === secondaryTopId);
14684
15486
  const hasSecondary = (secondaryTop?.children?.length ?? 0) > 0;
14685
- const breadcrumbItems = (0, import_react69.useMemo)(() => {
15487
+ const breadcrumbItems = (0, import_react72.useMemo)(() => {
14686
15488
  if (!showBreadcrumb || activeMenuId === void 0) {
14687
15489
  return [];
14688
15490
  }
@@ -14698,7 +15500,7 @@ function AdminLayout({
14698
15500
  };
14699
15501
  const fixedHeader = config.fixedHeader ?? true;
14700
15502
  const fixedSider = config.fixedSider ?? true;
14701
- const header = showHeader ? /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(
15503
+ const header = showHeader ? /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(
14702
15504
  "header",
14703
15505
  {
14704
15506
  "data-slot": "admin-header",
@@ -14707,21 +15509,21 @@ function AdminLayout({
14707
15509
  fixedHeader && "sticky top-0 z-20"
14708
15510
  ),
14709
15511
  children: [
14710
- mode !== "side-full" && /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(import_jsx_runtime205.Fragment, { children: [
15512
+ mode !== "side-full" && /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(import_jsx_runtime206.Fragment, { children: [
14711
15513
  brand.logo,
14712
- /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("span", { "data-slot": "admin-brand", className: "text-lg font-semibold", children: brand.title })
15514
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("span", { "data-slot": "admin-brand", className: "text-lg font-semibold", children: brand.title })
14713
15515
  ] }),
14714
- /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("div", { className: "flex-1" }),
15516
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("div", { className: "flex-1" }),
14715
15517
  headerExtra
14716
15518
  ]
14717
15519
  }
14718
15520
  ) : null;
14719
- const primaryColumn = /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15521
+ const primaryColumn = /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14720
15522
  "div",
14721
15523
  {
14722
15524
  "data-slot": "admin-primary-col",
14723
15525
  className: "flex w-12 shrink-0 flex-col items-center gap-1 border-r border-border py-2",
14724
- children: visibleMenus.map((menu) => /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15526
+ children: visibleMenus.map((menu) => /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14725
15527
  "button",
14726
15528
  {
14727
15529
  type: "button",
@@ -14748,7 +15550,7 @@ function AdminLayout({
14748
15550
  }
14749
15551
  );
14750
15552
  const showTrigger = config.collapsible && mode !== "two-column";
14751
- const sidebar = showSidebar ? /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(
15553
+ const sidebar = showSidebar ? /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(
14752
15554
  "aside",
14753
15555
  {
14754
15556
  "data-slot": "admin-sidebar",
@@ -14760,20 +15562,20 @@ function AdminLayout({
14760
15562
  ),
14761
15563
  style: mode === "two-column" && !hasSecondary ? { width: 56 } : void 0,
14762
15564
  children: [
14763
- mode === "side-full" && /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(
15565
+ mode === "side-full" && /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(
14764
15566
  "div",
14765
15567
  {
14766
15568
  "data-slot": "admin-sidebar-brand",
14767
15569
  className: "flex items-center gap-2 border-b border-border px-4 py-4 font-semibold",
14768
15570
  children: [
14769
15571
  brand.logo,
14770
- /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("span", { children: brand.title })
15572
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("span", { children: brand.title })
14771
15573
  ]
14772
15574
  }
14773
15575
  ),
14774
- mode === "two-column" ? /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)("div", { "data-slot": "admin-two-col", className: "flex h-full", children: [
15576
+ mode === "two-column" ? /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)("div", { "data-slot": "admin-two-col", className: "flex h-full", children: [
14775
15577
  primaryColumn,
14776
- hasSecondary && /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("div", { "data-slot": "admin-secondary-col", className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15578
+ hasSecondary && /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("div", { "data-slot": "admin-secondary-col", className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14777
15579
  MenuTree,
14778
15580
  {
14779
15581
  menus: secondaryTop?.children ?? [],
@@ -14783,7 +15585,7 @@ function AdminLayout({
14783
15585
  defaultOpenKeys
14784
15586
  }
14785
15587
  ) })
14786
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15588
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14787
15589
  MenuTree,
14788
15590
  {
14789
15591
  menus: visibleMenus,
@@ -14794,7 +15596,7 @@ function AdminLayout({
14794
15596
  collapsed: effectiveCollapsed
14795
15597
  }
14796
15598
  ),
14797
- showTrigger && /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15599
+ showTrigger && /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14798
15600
  "button",
14799
15601
  {
14800
15602
  type: "button",
@@ -14809,14 +15611,14 @@ function AdminLayout({
14809
15611
  ]
14810
15612
  }
14811
15613
  ) : null;
14812
- const body = /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)("div", { "data-slot": "admin-body", className: "flex min-w-0 flex-1 flex-col", children: [
14813
- showTabs && /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15614
+ const body = /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)("div", { "data-slot": "admin-body", className: "flex min-w-0 flex-1 flex-col", children: [
15615
+ showTabs && /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14814
15616
  "div",
14815
15617
  {
14816
15618
  "data-slot": "admin-tabs",
14817
15619
  role: "tablist",
14818
15620
  className: "flex items-center gap-1 border-b border-border bg-card px-4 pt-2",
14819
- children: tabs.map((tab, index) => /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(
15621
+ children: tabs.map((tab, index) => /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(
14820
15622
  "div",
14821
15623
  {
14822
15624
  "data-slot": "admin-tab",
@@ -14827,7 +15629,7 @@ function AdminLayout({
14827
15629
  tab.key === currentPath ? "bg-card font-medium text-foreground" : "bg-muted text-muted-foreground"
14828
15630
  ),
14829
15631
  children: [
14830
- /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15632
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14831
15633
  "button",
14832
15634
  {
14833
15635
  type: "button",
@@ -14838,7 +15640,7 @@ function AdminLayout({
14838
15640
  children: tab.title
14839
15641
  }
14840
15642
  ),
14841
- index > 0 && /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15643
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14842
15644
  "button",
14843
15645
  {
14844
15646
  type: "button",
@@ -14855,21 +15657,21 @@ function AdminLayout({
14855
15657
  ))
14856
15658
  }
14857
15659
  ),
14858
- /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(
15660
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(
14859
15661
  "main",
14860
15662
  {
14861
15663
  "data-slot": "admin-content",
14862
15664
  className: "flex-1 bg-muted/40 p-6",
14863
15665
  children: [
14864
- showBreadcrumb && breadcrumbItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15666
+ showBreadcrumb && breadcrumbItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14865
15667
  "nav",
14866
15668
  {
14867
15669
  "data-slot": "admin-breadcrumb",
14868
15670
  "aria-label": t("pactor.layout.breadcrumb"),
14869
15671
  className: "mb-4",
14870
- children: /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("ol", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: breadcrumbItems.map((title, index) => /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)("li", { className: "flex items-center gap-2", children: [
14871
- index > 0 && /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("span", { "aria-hidden": true, children: "/" }),
14872
- /* @__PURE__ */ (0, import_jsx_runtime205.jsx)("span", { "data-slot": "breadcrumb-link", children: title })
15672
+ children: /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("ol", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: breadcrumbItems.map((title, index) => /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)("li", { className: "flex items-center gap-2", children: [
15673
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("span", { "aria-hidden": true, children: "/" }),
15674
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsx)("span", { "data-slot": "breadcrumb-link", children: title })
14873
15675
  ] }, index)) })
14874
15676
  }
14875
15677
  ),
@@ -14878,7 +15680,7 @@ function AdminLayout({
14878
15680
  }
14879
15681
  )
14880
15682
  ] });
14881
- const footer = showFooter ? /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15683
+ const footer = showFooter ? /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14882
15684
  "footer",
14883
15685
  {
14884
15686
  "data-slot": "admin-footer",
@@ -14886,7 +15688,7 @@ function AdminLayout({
14886
15688
  children: brand.title
14887
15689
  }
14888
15690
  ) : null;
14889
- return /* @__PURE__ */ (0, import_jsx_runtime205.jsx)(
15691
+ return /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
14890
15692
  "div",
14891
15693
  {
14892
15694
  "data-slot": "admin-layout",
@@ -14894,9 +15696,9 @@ function AdminLayout({
14894
15696
  "data-fixed-header": fixedHeader || void 0,
14895
15697
  "data-fixed-sider": fixedSider || void 0,
14896
15698
  className: "flex min-h-screen flex-col bg-background text-foreground",
14897
- children: mode === "side-full" ? /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)("div", { "data-slot": "admin-side-full", className: "flex min-h-screen flex-1", children: [
15699
+ children: mode === "side-full" ? /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)("div", { "data-slot": "admin-side-full", className: "flex min-h-screen flex-1", children: [
14898
15700
  sidebar,
14899
- /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(
15701
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(
14900
15702
  "div",
14901
15703
  {
14902
15704
  "data-slot": "admin-side-full-main",
@@ -14908,9 +15710,9 @@ function AdminLayout({
14908
15710
  ]
14909
15711
  }
14910
15712
  )
14911
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)(import_jsx_runtime205.Fragment, { children: [
15713
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)(import_jsx_runtime206.Fragment, { children: [
14912
15714
  header,
14913
- /* @__PURE__ */ (0, import_jsx_runtime205.jsxs)("div", { "data-slot": "admin-main", className: "flex min-h-0 flex-1", children: [
15715
+ /* @__PURE__ */ (0, import_jsx_runtime206.jsxs)("div", { "data-slot": "admin-main", className: "flex min-h-0 flex-1", children: [
14914
15716
  sidebar,
14915
15717
  body
14916
15718
  ] }),
@@ -14921,9 +15723,9 @@ function AdminLayout({
14921
15723
  }
14922
15724
 
14923
15725
  // src/layout/basic/BlankLayout.tsx
14924
- var import_jsx_runtime206 = require("react/jsx-runtime");
15726
+ var import_jsx_runtime207 = require("react/jsx-runtime");
14925
15727
  function BlankLayout({ children }) {
14926
- return /* @__PURE__ */ (0, import_jsx_runtime206.jsx)(
15728
+ return /* @__PURE__ */ (0, import_jsx_runtime207.jsx)(
14927
15729
  "div",
14928
15730
  {
14929
15731
  "data-slot": "blank-layout",
@@ -14935,8 +15737,8 @@ function BlankLayout({ children }) {
14935
15737
 
14936
15738
  // src/layout/chat/ChatLayout.tsx
14937
15739
  var import_permission2 = require("@pactor-app/permission");
14938
- var import_react70 = require("react");
14939
- var import_jsx_runtime207 = require("react/jsx-runtime");
15740
+ var import_react73 = require("react");
15741
+ var import_jsx_runtime208 = require("react/jsx-runtime");
14940
15742
  function ChatLayout({
14941
15743
  brand,
14942
15744
  menu,
@@ -14951,7 +15753,7 @@ function ChatLayout({
14951
15753
  sidebarFooter,
14952
15754
  children
14953
15755
  }) {
14954
- const registryMenus = (0, import_react70.useMemo)(() => {
15756
+ const registryMenus = (0, import_react73.useMemo)(() => {
14955
15757
  if (menu !== void 0 || registry === void 0) {
14956
15758
  return [];
14957
15759
  }
@@ -14960,10 +15762,10 @@ function ChatLayout({
14960
15762
  return visible.flatMap((item) => menuItemToMenuData(item));
14961
15763
  }, [menu, registry, permissionChecker]);
14962
15764
  const menuItems = menu ?? registryMenus;
14963
- const [bridgePath, setBridgePath] = (0, import_react70.useState)(
15765
+ const [bridgePath, setBridgePath] = (0, import_react73.useState)(
14964
15766
  () => bridge?.getLocation().pathname ?? "/"
14965
15767
  );
14966
- (0, import_react70.useEffect)(() => {
15768
+ (0, import_react73.useEffect)(() => {
14967
15769
  if (bridge === void 0) {
14968
15770
  return;
14969
15771
  }
@@ -14971,7 +15773,7 @@ function ChatLayout({
14971
15773
  setBridgePath(location.pathname);
14972
15774
  });
14973
15775
  }, [bridge]);
14974
- const activeKey = (0, import_react70.useMemo)(() => {
15776
+ const activeKey = (0, import_react73.useMemo)(() => {
14975
15777
  if (activeMenuKey !== void 0) {
14976
15778
  return activeMenuKey;
14977
15779
  }
@@ -14991,7 +15793,7 @@ function ChatLayout({
14991
15793
  bridge.push(item.path);
14992
15794
  }
14993
15795
  };
14994
- const sidebarContent = sidebar !== void 0 && sidebar !== null ? sidebar : menuItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime207.jsx)(
15796
+ const sidebarContent = sidebar !== void 0 && sidebar !== null ? sidebar : menuItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime208.jsx)(
14995
15797
  Menu2,
14996
15798
  {
14997
15799
  items: menuItems.map((item) => chatMenuItemToUiMenuItem(item)),
@@ -14999,7 +15801,7 @@ function ChatLayout({
14999
15801
  onSelect: handleSelect
15000
15802
  }
15001
15803
  ) : void 0;
15002
- return /* @__PURE__ */ (0, import_jsx_runtime207.jsx)(
15804
+ return /* @__PURE__ */ (0, import_jsx_runtime208.jsx)(
15003
15805
  Sidebar,
15004
15806
  {
15005
15807
  brand,
@@ -15007,7 +15809,7 @@ function ChatLayout({
15007
15809
  sidebarFooter,
15008
15810
  collapsible,
15009
15811
  locationKey: routeProp?.path ?? bridgePath,
15010
- children: /* @__PURE__ */ (0, import_jsx_runtime207.jsx)(
15812
+ children: /* @__PURE__ */ (0, import_jsx_runtime208.jsx)(
15011
15813
  "div",
15012
15814
  {
15013
15815
  "data-slot": "chat-layout-content",
@@ -15061,26 +15863,26 @@ function menuItemToMenuData(item) {
15061
15863
  }
15062
15864
 
15063
15865
  // src/layout/basic/LoginLayout.tsx
15064
- var import_jsx_runtime208 = require("react/jsx-runtime");
15866
+ var import_jsx_runtime209 = require("react/jsx-runtime");
15065
15867
  function LoginLayout({
15066
15868
  variant = "center",
15067
15869
  brand,
15068
15870
  children
15069
15871
  }) {
15070
- const brandBlock = /* @__PURE__ */ (0, import_jsx_runtime208.jsxs)("div", { "data-slot": "login-brand", className: "flex flex-col items-center gap-2", children: [
15872
+ const brandBlock = /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)("div", { "data-slot": "login-brand", className: "flex flex-col items-center gap-2", children: [
15071
15873
  brand.logo,
15072
- /* @__PURE__ */ (0, import_jsx_runtime208.jsx)("h1", { className: "text-xl font-semibold", children: brand.title }),
15073
- brand.description !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime208.jsx)("div", { className: "text-sm text-muted-foreground", children: brand.description })
15874
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("h1", { className: "text-xl font-semibold", children: brand.title }),
15875
+ brand.description !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("div", { className: "text-sm text-muted-foreground", children: brand.description })
15074
15876
  ] });
15075
15877
  if (variant === "split") {
15076
- return /* @__PURE__ */ (0, import_jsx_runtime208.jsxs)(
15878
+ return /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)(
15077
15879
  "div",
15078
15880
  {
15079
15881
  "data-slot": "login-layout",
15080
15882
  "data-variant": "split",
15081
15883
  className: "grid min-h-screen grid-cols-2 bg-background text-foreground",
15082
15884
  children: [
15083
- /* @__PURE__ */ (0, import_jsx_runtime208.jsx)(
15885
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
15084
15886
  "div",
15085
15887
  {
15086
15888
  "data-slot": "login-brand-panel",
@@ -15088,7 +15890,7 @@ function LoginLayout({
15088
15890
  children: brandBlock
15089
15891
  }
15090
15892
  ),
15091
- /* @__PURE__ */ (0, import_jsx_runtime208.jsx)(
15893
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
15092
15894
  "div",
15093
15895
  {
15094
15896
  "data-slot": "login-form-panel",
@@ -15100,37 +15902,37 @@ function LoginLayout({
15100
15902
  }
15101
15903
  );
15102
15904
  }
15103
- return /* @__PURE__ */ (0, import_jsx_runtime208.jsx)(
15905
+ return /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
15104
15906
  "div",
15105
15907
  {
15106
15908
  "data-slot": "login-layout",
15107
15909
  "data-variant": "center",
15108
15910
  className: "flex min-h-screen items-center justify-center bg-muted/40 text-foreground",
15109
- children: /* @__PURE__ */ (0, import_jsx_runtime208.jsxs)(Card, { "data-slot": "login-card", className: "w-full max-w-sm gap-4 py-6", children: [
15110
- /* @__PURE__ */ (0, import_jsx_runtime208.jsxs)(CardHeader, { className: "px-6", children: [
15111
- /* @__PURE__ */ (0, import_jsx_runtime208.jsx)(CardTitle, { className: "sr-only", children: brand.title }),
15911
+ children: /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)(Card, { "data-slot": "login-card", className: "w-full max-w-sm gap-4 py-6", children: [
15912
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)(CardHeader, { className: "px-6", children: [
15913
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(CardTitle, { className: "sr-only", children: brand.title }),
15112
15914
  brandBlock
15113
15915
  ] }),
15114
- /* @__PURE__ */ (0, import_jsx_runtime208.jsx)(CardContent, { className: "flex flex-col gap-4 px-6", children })
15916
+ /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(CardContent, { className: "flex flex-col gap-4 px-6", children })
15115
15917
  ] })
15116
15918
  }
15117
15919
  );
15118
15920
  }
15119
15921
 
15120
15922
  // src/layout/basic/LandingLayout.tsx
15121
- var import_jsx_runtime209 = require("react/jsx-runtime");
15923
+ var import_jsx_runtime210 = require("react/jsx-runtime");
15122
15924
  function LandingLayout({
15123
15925
  navbar,
15124
15926
  footer,
15125
15927
  children
15126
15928
  }) {
15127
- return /* @__PURE__ */ (0, import_jsx_runtime209.jsxs)(
15929
+ return /* @__PURE__ */ (0, import_jsx_runtime210.jsxs)(
15128
15930
  "div",
15129
15931
  {
15130
15932
  "data-slot": "landing-layout",
15131
15933
  className: "flex min-h-screen flex-col bg-background text-foreground",
15132
15934
  children: [
15133
- navbar !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
15935
+ navbar !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime210.jsx)(
15134
15936
  "header",
15135
15937
  {
15136
15938
  "data-slot": "landing-navbar",
@@ -15138,8 +15940,8 @@ function LandingLayout({
15138
15940
  children: navbar
15139
15941
  }
15140
15942
  ),
15141
- /* @__PURE__ */ (0, import_jsx_runtime209.jsx)("main", { "data-slot": "landing-content", className: "flex-1", children }),
15142
- footer !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime209.jsx)(
15943
+ /* @__PURE__ */ (0, import_jsx_runtime210.jsx)("main", { "data-slot": "landing-content", className: "flex-1", children }),
15944
+ footer !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime210.jsx)(
15143
15945
  "footer",
15144
15946
  {
15145
15947
  "data-slot": "landing-footer",
@@ -15266,7 +16068,7 @@ var OverlayManager = class {
15266
16068
  };
15267
16069
 
15268
16070
  // src/interaction/actions.ts
15269
- var import_runtime27 = require("@pactor-app/runtime");
16071
+ var import_runtime28 = require("@pactor-app/runtime");
15270
16072
  function createUiBridge() {
15271
16073
  return {};
15272
16074
  }
@@ -15282,7 +16084,7 @@ function registerInteractionActions(actions, manager, ui) {
15282
16084
  return failure("[pactor-interaction] overlay.open \u7F3A\u5C11 overlay \u914D\u7F6E\u53C2\u6570");
15283
16085
  }
15284
16086
  const { content, ...rest } = overlay;
15285
- const resolved = (0, import_runtime27.resolveDeep)(rest, ctx.scope);
16087
+ const resolved = (0, import_runtime28.resolveDeep)(rest, ctx.scope);
15286
16088
  const config = { ...resolved, content };
15287
16089
  const data = await manager.open(config, {
15288
16090
  parentScope: { ...ctx.scope }
@@ -15345,10 +16147,10 @@ function isRecord(value) {
15345
16147
  }
15346
16148
 
15347
16149
  // src/interaction/provider.tsx
15348
- var import_runtime28 = require("@pactor-app/runtime");
15349
- var import_react71 = require("react");
16150
+ var import_runtime29 = require("@pactor-app/runtime");
16151
+ var import_react74 = require("react");
15350
16152
  var import_react_dom2 = require("react-dom");
15351
- var import_jsx_runtime210 = require("react/jsx-runtime");
16153
+ var import_jsx_runtime211 = require("react/jsx-runtime");
15352
16154
  var TOAST_DURATION = 3e3;
15353
16155
  var toastTypeClass = {
15354
16156
  success: "border-l-4 border-l-success",
@@ -15360,11 +16162,11 @@ function InteractionProvider({
15360
16162
  bridge,
15361
16163
  children
15362
16164
  }) {
15363
- const [confirmState, setConfirmState] = (0, import_react71.useState)(null);
15364
- const [confirmOpen, setConfirmOpen] = (0, import_react71.useState)(false);
15365
- const [toasts, setToasts] = (0, import_react71.useState)([]);
15366
- const { t } = (0, import_runtime28.useI18n)();
15367
- const { modal, message } = (0, import_react71.useMemo)(() => {
16165
+ const [confirmState, setConfirmState] = (0, import_react74.useState)(null);
16166
+ const [confirmOpen, setConfirmOpen] = (0, import_react74.useState)(false);
16167
+ const [toasts, setToasts] = (0, import_react74.useState)([]);
16168
+ const { t } = (0, import_runtime29.useI18n)();
16169
+ const { modal, message } = (0, import_react74.useMemo)(() => {
15368
16170
  const pushToast = (type, content) => {
15369
16171
  const id = Date.now() + Math.random();
15370
16172
  setToasts((prev) => [...prev, { id, type, content }]);
@@ -15386,7 +16188,7 @@ function InteractionProvider({
15386
16188
  };
15387
16189
  return { modal: modalImpl, message: messageImpl };
15388
16190
  }, []);
15389
- (0, import_react71.useEffect)(() => {
16191
+ (0, import_react74.useEffect)(() => {
15390
16192
  bridge.modal = modal;
15391
16193
  bridge.message = message;
15392
16194
  return () => {
@@ -15404,11 +16206,11 @@ function InteractionProvider({
15404
16206
  setConfirmOpen(false);
15405
16207
  state?.onCancel?.();
15406
16208
  };
15407
- return /* @__PURE__ */ (0, import_jsx_runtime210.jsxs)(import_jsx_runtime210.Fragment, { children: [
16209
+ return /* @__PURE__ */ (0, import_jsx_runtime211.jsxs)(import_jsx_runtime211.Fragment, { children: [
15408
16210
  children,
15409
16211
  typeof document !== "undefined" && (0, import_react_dom2.createPortal)(
15410
- /* @__PURE__ */ (0, import_jsx_runtime210.jsxs)(import_jsx_runtime210.Fragment, { children: [
15411
- /* @__PURE__ */ (0, import_jsx_runtime210.jsx)(
16212
+ /* @__PURE__ */ (0, import_jsx_runtime211.jsxs)(import_jsx_runtime211.Fragment, { children: [
16213
+ /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(
15412
16214
  Dialog,
15413
16215
  {
15414
16216
  open: confirmOpen,
@@ -15422,29 +16224,29 @@ function InteractionProvider({
15422
16224
  setConfirmState(null);
15423
16225
  }
15424
16226
  },
15425
- children: /* @__PURE__ */ (0, import_jsx_runtime210.jsxs)(DialogContent, { "data-slot": "confirm-dialog", className: "sm:max-w-sm", children: [
15426
- /* @__PURE__ */ (0, import_jsx_runtime210.jsxs)(DialogHeader, { children: [
15427
- /* @__PURE__ */ (0, import_jsx_runtime210.jsx)(DialogTitle, { children: confirmState?.title ?? "" }),
15428
- confirmState?.content !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime210.jsx)(
16227
+ children: /* @__PURE__ */ (0, import_jsx_runtime211.jsxs)(DialogContent, { "data-slot": "confirm-dialog", className: "sm:max-w-sm", children: [
16228
+ /* @__PURE__ */ (0, import_jsx_runtime211.jsxs)(DialogHeader, { children: [
16229
+ /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(DialogTitle, { children: confirmState?.title ?? "" }),
16230
+ confirmState?.content !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(
15429
16231
  DialogDescription,
15430
16232
  {
15431
- render: /* @__PURE__ */ (0, import_jsx_runtime210.jsx)("div", { children: confirmState.content })
16233
+ render: /* @__PURE__ */ (0, import_jsx_runtime211.jsx)("div", { children: confirmState.content })
15432
16234
  }
15433
16235
  )
15434
16236
  ] }),
15435
- /* @__PURE__ */ (0, import_jsx_runtime210.jsxs)(DialogFooter, { children: [
15436
- /* @__PURE__ */ (0, import_jsx_runtime210.jsx)(Button, { type: "button", variant: "outline", onClick: handleCancel, children: t("pactor.alertDialog.cancel") }),
15437
- /* @__PURE__ */ (0, import_jsx_runtime210.jsx)(Button, { type: "button", onClick: handleOk, children: t("pactor.alertDialog.confirm") })
16237
+ /* @__PURE__ */ (0, import_jsx_runtime211.jsxs)(DialogFooter, { children: [
16238
+ /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(Button, { type: "button", variant: "outline", onClick: handleCancel, children: t("pactor.alertDialog.cancel") }),
16239
+ /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(Button, { type: "button", onClick: handleOk, children: t("pactor.alertDialog.confirm") })
15438
16240
  ] })
15439
16241
  ] })
15440
16242
  }
15441
16243
  ),
15442
- toasts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime210.jsx)(
16244
+ toasts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(
15443
16245
  "div",
15444
16246
  {
15445
16247
  "data-slot": "toast-container",
15446
16248
  className: "fixed top-4 right-4 z-[100] flex w-80 flex-col gap-2",
15447
- children: toasts.map((toast2) => /* @__PURE__ */ (0, import_jsx_runtime210.jsx)(
16249
+ children: toasts.map((toast2) => /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(
15448
16250
  "div",
15449
16251
  {
15450
16252
  "data-slot": "toast",
@@ -15468,9 +16270,9 @@ function InteractionProvider({
15468
16270
 
15469
16271
  // src/interaction/host.tsx
15470
16272
  var import_lucide_react38 = require("lucide-react");
15471
- var import_runtime29 = require("@pactor-app/runtime");
15472
- var import_react72 = require("react");
15473
- var import_jsx_runtime211 = require("react/jsx-runtime");
16273
+ var import_runtime30 = require("@pactor-app/runtime");
16274
+ var import_react75 = require("react");
16275
+ var import_jsx_runtime212 = require("react/jsx-runtime");
15474
16276
  function toCssWidth(width) {
15475
16277
  if (width === void 0) {
15476
16278
  return void 0;
@@ -15478,12 +16280,12 @@ function toCssWidth(width) {
15478
16280
  return typeof width === "number" ? `${width}px` : width;
15479
16281
  }
15480
16282
  function OverlayHost({ manager, resolvePage }) {
15481
- const renderer = (0, import_runtime29.useRenderer)();
15482
- const stack = (0, import_react72.useSyncExternalStore)(
16283
+ const renderer = (0, import_runtime30.useRenderer)();
16284
+ const stack = (0, import_react75.useSyncExternalStore)(
15483
16285
  (onChange) => manager.subscribe(onChange),
15484
16286
  () => manager.stack()
15485
16287
  );
15486
- (0, import_react72.useSyncExternalStore)(
16288
+ (0, import_react75.useSyncExternalStore)(
15487
16289
  (onChange) => {
15488
16290
  const offState = renderer.context.state.subscribe(onChange);
15489
16291
  const offData = renderer.context.data.subscribe(onChange);
@@ -15494,7 +16296,7 @@ function OverlayHost({ manager, resolvePage }) {
15494
16296
  },
15495
16297
  () => `${renderer.context.state.getVersion()}:${renderer.context.data.getVersion()}`
15496
16298
  );
15497
- return /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(import_jsx_runtime211.Fragment, { children: stack.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(
16299
+ return /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(import_jsx_runtime212.Fragment, { children: stack.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(
15498
16300
  OverlayEntryView,
15499
16301
  {
15500
16302
  entry,
@@ -15511,7 +16313,7 @@ function OverlayEntryView({
15511
16313
  renderer,
15512
16314
  resolvePage
15513
16315
  }) {
15514
- const { t } = (0, import_runtime29.useI18n)();
16316
+ const { t } = (0, import_runtime30.useI18n)();
15515
16317
  const handleCancel = () => manager.close(entry.id);
15516
16318
  let body = null;
15517
16319
  if (entry.content) {
@@ -15520,7 +16322,7 @@ function OverlayEntryView({
15520
16322
  parent: manager.parentScopeOf(entry.id)
15521
16323
  });
15522
16324
  } else if (entry.page) {
15523
- body = /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(
16325
+ body = /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(
15524
16326
  PageOverlayBody,
15525
16327
  {
15526
16328
  entry,
@@ -15530,9 +16332,9 @@ function OverlayEntryView({
15530
16332
  );
15531
16333
  }
15532
16334
  if (entry.type === "drawer") {
15533
- return /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(ShadcnDrawerView, { entry, onCancel: handleCancel, children: body });
16335
+ return /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(ShadcnDrawerView, { entry, onCancel: handleCancel, children: body });
15534
16336
  }
15535
- return /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(
16337
+ return /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(
15536
16338
  Dialog,
15537
16339
  {
15538
16340
  open: true,
@@ -15541,7 +16343,7 @@ function OverlayEntryView({
15541
16343
  handleCancel();
15542
16344
  }
15543
16345
  },
15544
- children: /* @__PURE__ */ (0, import_jsx_runtime211.jsxs)(
16346
+ children: /* @__PURE__ */ (0, import_jsx_runtime212.jsxs)(
15545
16347
  DialogContent,
15546
16348
  {
15547
16349
  "data-slot": "overlay-modal",
@@ -15549,25 +16351,25 @@ function OverlayEntryView({
15549
16351
  style: entry.width === void 0 ? void 0 : { width: toCssWidth(entry.width) },
15550
16352
  showCloseButton: false,
15551
16353
  children: [
15552
- /* @__PURE__ */ (0, import_jsx_runtime211.jsxs)(DialogHeader, { children: [
15553
- /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(DialogTitle, { children: entry.title ?? "" }),
15554
- /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(
16354
+ /* @__PURE__ */ (0, import_jsx_runtime212.jsxs)(DialogHeader, { children: [
16355
+ /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(DialogTitle, { children: entry.title ?? "" }),
16356
+ /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(
15555
16357
  DialogClose,
15556
16358
  {
15557
- render: /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(
16359
+ render: /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(
15558
16360
  "button",
15559
16361
  {
15560
16362
  type: "button",
15561
16363
  "data-slot": "overlay-modal-close",
15562
16364
  "aria-label": t("pactor.overlay.close"),
15563
16365
  className: "absolute top-4 right-4 cursor-pointer rounded-xs opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-none",
15564
- children: /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(import_lucide_react38.XIcon, { className: "size-4" })
16366
+ children: /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(import_lucide_react38.XIcon, { className: "size-4" })
15565
16367
  }
15566
16368
  )
15567
16369
  }
15568
16370
  )
15569
16371
  ] }),
15570
- /* @__PURE__ */ (0, import_jsx_runtime211.jsx)("div", { "data-slot": "overlay-modal-body", children: body })
16372
+ /* @__PURE__ */ (0, import_jsx_runtime212.jsx)("div", { "data-slot": "overlay-modal-body", children: body })
15571
16373
  ]
15572
16374
  }
15573
16375
  )
@@ -15579,9 +16381,9 @@ function ShadcnDrawerView({
15579
16381
  onCancel,
15580
16382
  children
15581
16383
  }) {
15582
- const { t } = (0, import_runtime29.useI18n)();
16384
+ const { t } = (0, import_runtime30.useI18n)();
15583
16385
  const panelStyle = entry.width === void 0 ? void 0 : { width: toCssWidth(entry.width) };
15584
- return /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(
16386
+ return /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(
15585
16387
  Drawer,
15586
16388
  {
15587
16389
  direction: "right",
@@ -15591,34 +16393,34 @@ function ShadcnDrawerView({
15591
16393
  onCancel();
15592
16394
  }
15593
16395
  },
15594
- children: /* @__PURE__ */ (0, import_jsx_runtime211.jsxs)(
16396
+ children: /* @__PURE__ */ (0, import_jsx_runtime212.jsxs)(
15595
16397
  DrawerContent,
15596
16398
  {
15597
16399
  "data-slot": "drawer-panel",
15598
16400
  className: cn(entry.width !== void 0 && "sm:max-w-none"),
15599
16401
  style: panelStyle,
15600
16402
  children: [
15601
- /* @__PURE__ */ (0, import_jsx_runtime211.jsxs)(
16403
+ /* @__PURE__ */ (0, import_jsx_runtime212.jsxs)(
15602
16404
  DrawerHeader,
15603
16405
  {
15604
16406
  "data-slot": "drawer-header",
15605
16407
  className: "flex flex-row items-center justify-between border-b border-border px-6 py-4",
15606
16408
  children: [
15607
- /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(DrawerTitle, { className: "text-lg", children: entry.title ?? "" }),
15608
- /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(DrawerClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(
16409
+ /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(DrawerTitle, { className: "text-lg", children: entry.title ?? "" }),
16410
+ /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(DrawerClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(
15609
16411
  "button",
15610
16412
  {
15611
16413
  type: "button",
15612
16414
  "data-slot": "drawer-close",
15613
16415
  "aria-label": t("pactor.overlay.close"),
15614
16416
  className: "cursor-pointer rounded-xs opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-none",
15615
- children: /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(import_lucide_react38.XIcon, { className: "size-4" })
16417
+ children: /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(import_lucide_react38.XIcon, { className: "size-4" })
15616
16418
  }
15617
16419
  ) })
15618
16420
  ]
15619
16421
  }
15620
16422
  ),
15621
- /* @__PURE__ */ (0, import_jsx_runtime211.jsx)("div", { "data-slot": "drawer-body", className: "flex-1 overflow-auto p-6", children })
16423
+ /* @__PURE__ */ (0, import_jsx_runtime212.jsx)("div", { "data-slot": "drawer-body", className: "flex-1 overflow-auto p-6", children })
15622
16424
  ]
15623
16425
  }
15624
16426
  )
@@ -15630,9 +16432,9 @@ function PageOverlayBody({
15630
16432
  renderer,
15631
16433
  resolvePage
15632
16434
  }) {
15633
- const [child, setChild] = (0, import_react72.useState)(null);
15634
- const [error, setError] = (0, import_react72.useState)(null);
15635
- (0, import_react72.useEffect)(() => {
16435
+ const [child, setChild] = (0, import_react75.useState)(null);
16436
+ const [error, setError] = (0, import_react75.useState)(null);
16437
+ (0, import_react75.useEffect)(() => {
15636
16438
  if (!resolvePage) {
15637
16439
  setError(
15638
16440
  new Error(
@@ -15650,7 +16452,7 @@ function PageOverlayBody({
15650
16452
  return;
15651
16453
  }
15652
16454
  const host = renderer.context;
15653
- created = (0, import_runtime29.createPageRuntime)(pageDsl, {
16455
+ created = (0, import_runtime30.createPageRuntime)(pageDsl, {
15654
16456
  app: host.app,
15655
16457
  user: host.user,
15656
16458
  components: host.components,
@@ -15674,12 +16476,12 @@ function PageOverlayBody({
15674
16476
  };
15675
16477
  }, [entry.id]);
15676
16478
  if (error) {
15677
- return /* @__PURE__ */ (0, import_jsx_runtime211.jsx)("div", { role: "alert", children: error.message });
16479
+ return /* @__PURE__ */ (0, import_jsx_runtime212.jsx)("div", { role: "alert", children: error.message });
15678
16480
  }
15679
16481
  if (!child) {
15680
16482
  return null;
15681
16483
  }
15682
- return /* @__PURE__ */ (0, import_jsx_runtime211.jsx)(import_runtime29.PageRuntimeView, { runtime: child });
16484
+ return /* @__PURE__ */ (0, import_jsx_runtime212.jsx)(import_runtime30.PageRuntimeView, { runtime: child });
15683
16485
  }
15684
16486
  // Annotate the CommonJS export names for ESM import in node:
15685
16487
  0 && (module.exports = {