@nextclaw/ui 0.20.2 → 0.20.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/assets/{api-DvpQWjTS.js → api-iMkU_o5P.js} +3 -3
  3. package/dist/assets/{appearance-settings-page-U0m0ktu3.js → appearance-settings-page-CU5k4b-M.js} +1 -1
  4. package/dist/assets/{book-open-DRofSTWr.js → book-open-nD8gdMhA.js} +1 -1
  5. package/dist/assets/{channels-list-page-BURQarD0.js → channels-list-page-Drlt62kY.js} +1 -1
  6. package/dist/assets/{config-split-page-BrAQYTIl.js → config-split-page-BtJZp1E5.js} +1 -1
  7. package/dist/assets/{confirm-dialog-DDJomLnO.js → confirm-dialog-k2-Jq_x3.js} +1 -1
  8. package/dist/assets/{createLucideIcon-DzkNHr5Z.js → createLucideIcon-DxlwKLr-.js} +1 -1
  9. package/dist/assets/{desktop-update-config-BzZFhMv9.js → desktop-update-config-BiZmy7FC.js} +1 -1
  10. package/dist/assets/{dist-DXbLo2b1.js → dist-Cy_e4kNb.js} +1 -1
  11. package/dist/assets/{dist-NskPB_yW.js → dist-m08DUswB.js} +1 -1
  12. package/dist/assets/doc-browser-CPsPHh12.js +1 -0
  13. package/dist/assets/{doc-browser-context-CnKV4gJy.js → doc-browser-context-jiy-O4F8.js} +1 -1
  14. package/dist/assets/doc-browser-npOvWtgf.js +1 -0
  15. package/dist/assets/{extensions-DvlFMpAs.js → extensions-CIb17__o.js} +1 -1
  16. package/dist/assets/{form-actions-UnPEZBkx.js → form-actions-DGf5zUg_.js} +1 -1
  17. package/dist/assets/{index-Dc_ZMkmo.css → index-C86hxgv5.css} +1 -1
  18. package/dist/assets/index-CYBXR7zN.js +109 -0
  19. package/dist/assets/loader-circle-BlLuRFVW.js +1 -0
  20. package/dist/assets/mcp-marketplace-page-B12JNh7Q.js +1 -0
  21. package/dist/assets/{mcp-marketplace-page-BIgFTbMq.js → mcp-marketplace-page-kLWW6kzt.js} +1 -1
  22. package/dist/assets/{model-config-page-CnSm7kfa.js → model-config-page-DSeAjVT_.js} +1 -1
  23. package/dist/assets/{navigation-link-NjUdG6Vp.js → navigation-link-DAfwFCj4.js} +1 -1
  24. package/dist/assets/plus-D4LtWtTk.js +1 -0
  25. package/dist/assets/{privacy-settings-page-DVn2HU7W.js → privacy-settings-page-tN0Mt15x.js} +1 -1
  26. package/dist/assets/{providers-config-page-CzHJS3eg.js → providers-config-page-CgPrXR1u.js} +1 -1
  27. package/dist/assets/react-8iBFECZE.js +8 -0
  28. package/dist/assets/{refresh-cw-CkeninE0.js → refresh-cw-D_Eibznw.js} +1 -1
  29. package/dist/assets/remote-Derr_AQp.js +1 -0
  30. package/dist/assets/{rotate-cw-DP33PuXU.js → rotate-cw-QQjmoWuq.js} +1 -1
  31. package/dist/assets/{runtime-config-page-D69buyGp.js → runtime-config-page-Crq96Jjq.js} +1 -1
  32. package/dist/assets/{save-Cw2Xz-pB.js → save-W2xthJJ2.js} +1 -1
  33. package/dist/assets/{search-C2CFAVvd.js → search-Vih1R2BD.js} +1 -1
  34. package/dist/assets/{search-config-page-dqNT0Swf.js → search-config-page-CtBcL2uc.js} +1 -1
  35. package/dist/assets/{secrets-config-page-De6J3wVx.js → secrets-config-page-Q6XfIj0h.js} +1 -1
  36. package/dist/assets/security-config-CE9rkQvq.js +1 -0
  37. package/dist/assets/{select-DSuMhwVP.js → select-lNdozU4o.js} +1 -1
  38. package/dist/assets/skeleton-B__aTcly.js +1 -0
  39. package/dist/assets/{tag-chip-DFBLgsGf.js → tag-chip-gdaU9bE7.js} +1 -1
  40. package/dist/assets/x-CWdWBu_U.js +1 -0
  41. package/dist/index.html +21 -21
  42. package/package.json +8 -8
  43. package/src/app/components/layout/sidebar.tsx +7 -0
  44. package/src/features/apps/components/app-package-card.tsx +29 -7
  45. package/src/features/apps/components/app-packages-panel.tsx +4 -0
  46. package/src/features/chat/components/conversation/chat-conversation-content.tsx +18 -2
  47. package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +6 -0
  48. package/src/features/chat/components/layout/__tests__/chat-sidebar-session-area.test.tsx +16 -2
  49. package/src/features/chat/components/layout/chat-page-shell.tsx +19 -2
  50. package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +16 -0
  51. package/src/features/chat/components/layout/chat-sidebar.tsx +4 -1
  52. package/src/features/chat/features/message/utils/__tests__/chat-message-timeline-compaction.utils.test.ts +2 -2
  53. package/src/features/chat/features/message/utils/chat-message-timeline.utils.ts +2 -2
  54. package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-session-list-view.test.tsx +11 -3
  55. package/src/features/chat/features/ncp/hooks/use-ncp-session-list-view.ts +12 -5
  56. package/src/features/chat/features/ncp/hooks/use-ncp-session-queries.ts +15 -1
  57. package/src/features/chat/features/workspace/components/__tests__/chat-session-token-usage.test.tsx +4 -1
  58. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.scroll-restoration.test.tsx +182 -0
  59. package/src/features/chat/features/workspace/components/__tests__/session-cron-job-content.test.tsx +78 -0
  60. package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +47 -2
  61. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +14 -1
  62. package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +9 -0
  63. package/src/features/chat/features/workspace/components/overview/chat-session-token-usage.tsx +17 -0
  64. package/src/features/chat/features/workspace/components/session-cron-job-content.tsx +269 -75
  65. package/src/features/chat/features/workspace/hooks/use-chat-conversation-workspace-state.ts +5 -0
  66. package/src/features/cron/components/__tests__/cron-config.test.tsx +16 -5
  67. package/src/features/cron/components/cron-config.tsx +20 -46
  68. package/src/features/cron/components/cron-job-row.tsx +1 -1
  69. package/src/features/cron/hooks/__tests__/use-cron-job-actions.test.tsx +95 -0
  70. package/src/features/cron/hooks/use-cron-job-actions.ts +109 -0
  71. package/src/features/cron/index.ts +2 -0
  72. package/src/features/inbox/pages/inbox-page.tsx +18 -2
  73. package/src/features/marketplace/components/marketplace-page.tsx +7 -0
  74. package/src/features/panel-apps/pages/panel-app-main-page.tsx +8 -0
  75. package/src/platforms/desktop/components/desktop-app-shell.tsx +10 -1
  76. package/src/shared/components/doc-browser/doc-browser.tsx +0 -1
  77. package/src/shared/components/doc-browser/hooks/use-doc-browser-scroll-restoration.ts +9 -113
  78. package/src/shared/hooks/use-panel-app-scroll-restoration.test.tsx +66 -0
  79. package/src/shared/hooks/use-panel-app-scroll-restoration.ts +107 -0
  80. package/src/shared/hooks/use-scroll-restoration.test.tsx +62 -0
  81. package/src/shared/hooks/use-scroll-restoration.ts +61 -0
  82. package/src/shared/lib/api/ncp-session-query-cache.utils.ts +1 -0
  83. package/src/shared/lib/api/ncp-session.types.ts +3 -0
  84. package/src/shared/lib/api/types.ts +1 -0
  85. package/src/shared/lib/api/utils/ncp-session.utils.ts +3 -0
  86. package/src/shared/lib/i18n/locales/en-US/chat.json +8 -5
  87. package/src/shared/lib/i18n/locales/en-US/cron.json +4 -2
  88. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +1 -0
  89. package/src/shared/lib/i18n/locales/zh-CN/chat.json +8 -5
  90. package/src/shared/lib/i18n/locales/zh-CN/cron.json +4 -2
  91. package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +1 -0
  92. package/src/shared/lib/navigation-history/index.ts +1 -0
  93. package/src/shared/lib/navigation-history/scroll-restoration.manager.test.ts +37 -0
  94. package/src/shared/lib/navigation-history/scroll-restoration.manager.ts +60 -0
  95. package/dist/assets/doc-browser-DB22tQKU.js +0 -1
  96. package/dist/assets/doc-browser-sJjw9fl5.js +0 -1
  97. package/dist/assets/index-N1HnesBp.js +0 -109
  98. package/dist/assets/loader-circle-BlPXxgDB.js +0 -1
  99. package/dist/assets/mcp-marketplace-page-CZN4ovdK.js +0 -1
  100. package/dist/assets/plus-DVXol9Q5.js +0 -1
  101. package/dist/assets/react-DCVbGroo.js +0 -8
  102. package/dist/assets/remote-B2lsJF1c.js +0 -1
  103. package/dist/assets/security-config-Dcu9C4OL.js +0 -1
  104. package/dist/assets/skeleton-QoWydNLp.js +0 -1
  105. package/dist/assets/x-BXvAzpjb.js +0 -1
@@ -0,0 +1,62 @@
1
+ import { fireEvent, render } from "@testing-library/react";
2
+ import { beforeEach, describe, expect, it } from "vitest";
3
+ import { useScrollRestoration } from "@/shared/hooks/use-scroll-restoration";
4
+ import { scrollRestorationManager } from "@/shared/lib/navigation-history";
5
+
6
+ function ScrollSurface({ restorationKey }: { restorationKey: string }) {
7
+ const scrollRestoration = useScrollRestoration<HTMLDivElement>({ restorationKey });
8
+ const { onScroll, scrollRef } = scrollRestoration;
9
+ return (
10
+ <div
11
+ ref={scrollRef}
12
+ data-testid="scroll-surface"
13
+ onScroll={onScroll}
14
+ />
15
+ );
16
+ }
17
+
18
+ describe("useScrollRestoration", () => {
19
+ beforeEach(() => scrollRestorationManager.clear());
20
+
21
+ it("restores an existing position during layout and saves scroll events", () => {
22
+ scrollRestorationManager.save("page:first", { x: 16, y: 48 });
23
+ const { getByTestId } = render(<ScrollSurface restorationKey="page:first" />);
24
+ const surface = getByTestId("scroll-surface") as HTMLDivElement;
25
+
26
+ expect(surface.scrollLeft).toBe(16);
27
+ expect(surface.scrollTop).toBe(48);
28
+
29
+ surface.scrollLeft = 24;
30
+ surface.scrollTop = 72;
31
+ fireEvent.scroll(surface);
32
+
33
+ expect(scrollRestorationManager.read("page:first")).toEqual({ x: 24, y: 72 });
34
+ });
35
+
36
+ it("saves the previous key and restores the next key when navigation changes", () => {
37
+ scrollRestorationManager.save("page:second", { x: 0, y: 96 });
38
+ const view = render(<ScrollSurface restorationKey="page:first" />);
39
+ const surface = view.getByTestId("scroll-surface") as HTMLDivElement;
40
+ surface.scrollTop = 32;
41
+ fireEvent.scroll(surface);
42
+
43
+ view.rerender(<ScrollSurface restorationKey="page:second" />);
44
+
45
+ expect(scrollRestorationManager.read("page:first")).toEqual({ x: 0, y: 32 });
46
+ expect(surface.scrollTop).toBe(96);
47
+ });
48
+
49
+ it("keeps the last scroll event when React resets the element during navigation", () => {
50
+ const view = render(<ScrollSurface restorationKey="page:first" />);
51
+ const surface = view.getByTestId("scroll-surface") as HTMLDivElement;
52
+ surface.scrollTop = 144;
53
+ fireEvent.scroll(surface);
54
+
55
+ // Switching the content can reset the DOM scroll position before the
56
+ // previous layout effect's cleanup runs.
57
+ surface.scrollTop = 0;
58
+ view.rerender(<ScrollSurface restorationKey="page:second" />);
59
+
60
+ expect(scrollRestorationManager.read("page:first")).toEqual({ x: 0, y: 144 });
61
+ });
62
+ });
@@ -0,0 +1,61 @@
1
+ import { useCallback, useLayoutEffect, useRef, type RefObject, type UIEvent } from "react";
2
+ import {
3
+ scrollRestorationManager,
4
+ type ScrollRestorationPosition,
5
+ } from "@/shared/lib/navigation-history";
6
+
7
+ type UseScrollRestorationParams<T extends HTMLElement> = {
8
+ restorationKey: string | null;
9
+ scrollRef?: RefObject<T>;
10
+ isEnabled?: boolean;
11
+ };
12
+
13
+ /** Connects one DOM scroll surface to the shared in-memory navigation history. */
14
+ export function useScrollRestoration<T extends HTMLElement>({
15
+ restorationKey,
16
+ scrollRef,
17
+ isEnabled = true,
18
+ }: UseScrollRestorationParams<T>) {
19
+ const internalScrollRef = useRef<T>(null);
20
+ const lastKnownPositionRef = useRef<ScrollRestorationPosition | null>(null);
21
+ const resolvedScrollRef = scrollRef ?? internalScrollRef;
22
+
23
+ useLayoutEffect(() => {
24
+ if (!isEnabled || !restorationKey) return;
25
+ const element = resolvedScrollRef.current;
26
+ const position = scrollRestorationManager.read(restorationKey);
27
+ if (element && position) {
28
+ element.scrollLeft = position.x;
29
+ element.scrollTop = position.y;
30
+ }
31
+ if (element) {
32
+ lastKnownPositionRef.current = {
33
+ x: element.scrollLeft,
34
+ y: element.scrollTop,
35
+ };
36
+ }
37
+
38
+ return () => {
39
+ if (!element) return;
40
+ scrollRestorationManager.save(
41
+ restorationKey,
42
+ lastKnownPositionRef.current ?? {
43
+ x: element.scrollLeft,
44
+ y: element.scrollTop,
45
+ },
46
+ );
47
+ };
48
+ }, [isEnabled, restorationKey, resolvedScrollRef]);
49
+
50
+ const onScroll = useCallback((event: UIEvent<T>) => {
51
+ if (!isEnabled || !restorationKey) return;
52
+ const position = {
53
+ x: event.currentTarget.scrollLeft,
54
+ y: event.currentTarget.scrollTop,
55
+ };
56
+ lastKnownPositionRef.current = position;
57
+ scrollRestorationManager.save(restorationKey, position);
58
+ }, [isEnabled, restorationKey]);
59
+
60
+ return { onScroll, scrollRef: resolvedScrollRef };
61
+ }
@@ -149,6 +149,7 @@ export function applyNcpSessionRealtimeEvent(
149
149
  queryClient: QueryClient | undefined,
150
150
  event: Extract<WsEvent, { type: 'session.run-status' | 'session.summary.upsert' | 'session.summary.delete' }>
151
151
  ): void {
152
+ void queryClient?.invalidateQueries({ queryKey: ['ncp-session-pages'] });
152
153
  if (event.type === 'session.run-status') {
153
154
  updateNcpSessionRunStatusInQueryClient(queryClient, event.payload);
154
155
  return;
@@ -103,6 +103,9 @@ export type NcpSessionSummaryView = NcpSessionSummary;
103
103
  export type NcpSessionsListView = {
104
104
  sessions: NcpSessionSummaryView[];
105
105
  total: number;
106
+ page?: number;
107
+ pageSize?: number;
108
+ hasMore?: boolean;
106
109
  };
107
110
 
108
111
  export type NcpMessageView = NcpMessage;
@@ -488,6 +488,7 @@ export type PanelAppListView = {
488
488
  workspacePath: string;
489
489
  panelsPath: string;
490
490
  entries: PanelAppEntryView[];
491
+ unavailablePackages?: Array<{ appId: string; message: string }>;
491
492
  };
492
493
 
493
494
  export type PanelAppPreferencesUpdateView = {
@@ -14,6 +14,9 @@ import type {
14
14
  // GET /api/ncp/sessions
15
15
  export async function fetchNcpSessions(params?: {
16
16
  limit?: number;
17
+ page?: number;
18
+ pageSize?: number;
19
+ query?: string;
17
20
  peerId?: string;
18
21
  }): Promise<NcpSessionsListView> {
19
22
  return (await nextclawClient.sessions.list(params)) as NcpSessionsListView;
@@ -80,7 +80,7 @@
80
80
  "chatWorkspaceContinuousAttentionEmpty": "No continuous attention",
81
81
  "chatWorkspaceContinuousAttentionEmptyDescription": "The Agent has not established this type of ongoing relationship for the session.",
82
82
  "chatWorkspaceTokenUsage": "Token usage",
83
- "chatWorkspaceTokenUsageDescription": "Counts this session's own AI runs. Cached input is included in input tokens; the hit rate is cached reads divided by all input.",
83
+ "chatWorkspaceTokenUsageDescription": "Summarizes this session's recorded Agent rounds. Cached input is included in input tokens; cache read ratio is cached reads divided by all input tokens.",
84
84
  "chatWorkspaceTokenUsageLoading": "Calculating token usage…",
85
85
  "chatWorkspaceTokenUsageLoadFailed": "Couldn’t load token usage.",
86
86
  "chatWorkspaceTokenUsageRetry": "Retry",
@@ -89,11 +89,14 @@
89
89
  "chatWorkspaceTokenUsageInput": "Input",
90
90
  "chatWorkspaceTokenUsageOutput": "Output",
91
91
  "chatWorkspaceTokenUsageCachedInput": "Cached input",
92
- "chatWorkspaceTokenUsageCacheHitRate": "Cache hit rate",
93
- "chatWorkspaceTokenUsageRuns": "AI runs",
92
+ "chatWorkspaceTokenUsageCacheHitRate": "Cache read ratio",
93
+ "chatWorkspaceTokenUsageRuns": "Agent rounds",
94
+ "chatWorkspaceTokenUsageModelCalls": "Model calls",
95
+ "chatWorkspaceTokenUsageReportedModelCalls": "Reported calls",
94
96
  "chatWorkspaceTokenUsageByModel": "By model",
95
- "chatWorkspaceTokenUsageModelRunCount": "Runs: {count}",
96
- "chatWorkspaceTokenUsageModelCacheHitRate": "Cache hit rate: {rate}",
97
+ "chatWorkspaceTokenUsageModelRunCount": "{count} agent rounds",
98
+ "chatWorkspaceTokenUsageModelCallCount": "{count} model calls",
99
+ "chatWorkspaceTokenUsageModelCacheHitRate": "Cache read ratio: {rate}",
97
100
  "chatWorkspaceTokenUsageReported": "Usage reported",
98
101
  "chatWorkspaceTokenUsagePartial": "Partial usage",
99
102
  "chatWorkspaceTokenUsageUnavailable": "Usage unavailable",
@@ -17,6 +17,8 @@
17
17
  "cronNextPage": "Next page",
18
18
  "cronTotalLabel": "Total",
19
19
  "cronLoading": "Loading scheduled tasks...",
20
+ "cronLoadFailed": "Scheduled tasks could not be loaded right now.",
21
+ "cronRetry": "Retry",
20
22
  "cronEmpty": "No scheduled tasks yet.",
21
23
  "cronScheduleLabel": "Schedule",
22
24
  "cronSessionLabel": "Execution session",
@@ -64,8 +66,8 @@
64
66
  "cronRunFailed": "Latest run failed",
65
67
  "cronBoundSession": "Bound session",
66
68
  "cronDedicatedSession": "Dedicated session",
67
- "cronEditDetails": "View and edit task",
68
- "cronDetailDescription": "Review the task and its latest run. Return to its execution session to describe changes.",
69
+ "cronEditDetails": "View task details",
70
+ "cronDetailDescription": "Review the task and its latest run. To change it, return to the execution session and describe what you need.",
69
71
  "cronTaskPrompt": "Task prompt",
70
72
  "cronTaskDetails": "Task settings",
71
73
  "cronAgentLabel": "Execution Agent",
@@ -62,6 +62,7 @@
62
62
  "appPackagesEmptyTitle": "No apps available yet",
63
63
  "appPackagesEmptyDescription": "Install a Mini APP, or upgrade to a NextClaw version that includes built-in apps.",
64
64
  "appPackagesEnabled": "Enabled",
65
+ "appPackagesUnavailable": "Unavailable",
65
66
  "appPackagesAvailable": "Available",
66
67
  "appPackagesBuiltIn": "Built into NextClaw",
67
68
  "appPackagesLocalService": "Local data service",
@@ -80,7 +80,7 @@
80
80
  "chatWorkspaceContinuousAttentionEmpty": "暂无持续关注",
81
81
  "chatWorkspaceContinuousAttentionEmptyDescription": "Agent 尚未为这个会话建立这类持续关系。",
82
82
  "chatWorkspaceTokenUsage": "Token 用量",
83
- "chatWorkspaceTokenUsageDescription": "统计当前会话自身的 AI 运行。缓存输入已包含在输入 Token 中;命中率为缓存读取占全部输入的比例。",
83
+ "chatWorkspaceTokenUsageDescription": "统计当前会话已记录的 Agent 轮次。缓存输入已包含在输入 Token 中;缓存读取占比为缓存读取 Token 占全部输入 Token 的比例。",
84
84
  "chatWorkspaceTokenUsageLoading": "正在统计 Token 用量…",
85
85
  "chatWorkspaceTokenUsageLoadFailed": "Token 用量加载失败。",
86
86
  "chatWorkspaceTokenUsageRetry": "重试",
@@ -89,11 +89,14 @@
89
89
  "chatWorkspaceTokenUsageInput": "输入",
90
90
  "chatWorkspaceTokenUsageOutput": "输出",
91
91
  "chatWorkspaceTokenUsageCachedInput": "缓存输入",
92
- "chatWorkspaceTokenUsageCacheHitRate": "缓存命中率",
93
- "chatWorkspaceTokenUsageRuns": "AI 运行",
92
+ "chatWorkspaceTokenUsageCacheHitRate": "缓存读取占比",
93
+ "chatWorkspaceTokenUsageRuns": "Agent 轮次",
94
+ "chatWorkspaceTokenUsageModelCalls": "模型调用",
95
+ "chatWorkspaceTokenUsageReportedModelCalls": "已报告调用",
94
96
  "chatWorkspaceTokenUsageByModel": "按模型",
95
- "chatWorkspaceTokenUsageModelRunCount": "{count} 次运行",
96
- "chatWorkspaceTokenUsageModelCacheHitRate": "缓存命中率 {rate}",
97
+ "chatWorkspaceTokenUsageModelRunCount": "{count} 个 Agent 轮次",
98
+ "chatWorkspaceTokenUsageModelCallCount": "{count} 次模型调用",
99
+ "chatWorkspaceTokenUsageModelCacheHitRate": "缓存读取占比 {rate}",
97
100
  "chatWorkspaceTokenUsageReported": "用量已报告",
98
101
  "chatWorkspaceTokenUsagePartial": "部分用量",
99
102
  "chatWorkspaceTokenUsageUnavailable": "用量不可用",
@@ -17,6 +17,8 @@
17
17
  "cronNextPage": "下一页",
18
18
  "cronTotalLabel": "总数",
19
19
  "cronLoading": "加载定时任务中...",
20
+ "cronLoadFailed": "暂时无法读取定时任务。",
21
+ "cronRetry": "重试",
20
22
  "cronEmpty": "暂无定时任务。",
21
23
  "cronScheduleLabel": "执行计划",
22
24
  "cronSessionLabel": "执行会话",
@@ -64,8 +66,8 @@
64
66
  "cronRunFailed": "最近执行失败",
65
67
  "cronBoundSession": "绑定会话",
66
68
  "cronDedicatedSession": "独立会话",
67
- "cronEditDetails": "查看与编辑任务",
68
- "cronDetailDescription": "查看任务设置与最近一次运行状态。修改任务可回到执行会话继续说明。",
69
+ "cronEditDetails": "查看任务详情",
70
+ "cronDetailDescription": "查看任务设置与最近一次运行状态。要修改任务,请回到执行会话继续说明。",
69
71
  "cronTaskPrompt": "任务内容",
70
72
  "cronTaskDetails": "任务设置",
71
73
  "cronAgentLabel": "执行 Agent",
@@ -62,6 +62,7 @@
62
62
  "appPackagesEmptyTitle": "还没有可用应用",
63
63
  "appPackagesEmptyDescription": "安装一个 Mini APP,或升级到包含内置应用的 NextClaw 版本。",
64
64
  "appPackagesEnabled": "已启用",
65
+ "appPackagesUnavailable": "不可用",
65
66
  "appPackagesAvailable": "可用",
66
67
  "appPackagesBuiltIn": "NextClaw 内置",
67
68
  "appPackagesLocalService": "本地数据服务",
@@ -1 +1,2 @@
1
1
  export * from './navigation-history.utils';
2
+ export * from './scroll-restoration.manager';
@@ -0,0 +1,37 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { ScrollRestorationManager } from "@/shared/lib/navigation-history";
3
+
4
+ describe("ScrollRestorationManager", () => {
5
+ it("normalizes positions and keeps keys isolated", () => {
6
+ const manager = new ScrollRestorationManager();
7
+
8
+ manager.save("first", { x: -1, y: Number.NaN });
9
+ manager.save("second", { x: 12.5, y: 48 });
10
+
11
+ expect(manager.read("first")).toEqual({ x: 0, y: 0 });
12
+ expect(manager.read("second")).toEqual({ x: 12.5, y: 48 });
13
+ });
14
+
15
+ it("evicts the oldest entry when capacity is exhausted", () => {
16
+ const manager = new ScrollRestorationManager(2);
17
+
18
+ manager.save("first", { x: 0, y: 1 });
19
+ manager.save("second", { x: 0, y: 2 });
20
+ manager.save("third", { x: 0, y: 3 });
21
+
22
+ expect(manager.read("first")).toBeNull();
23
+ expect(manager.read("second")).toEqual({ x: 0, y: 2 });
24
+ expect(manager.read("third")).toEqual({ x: 0, y: 3 });
25
+ });
26
+
27
+ it("removes individual entries and clears the session history", () => {
28
+ const manager = new ScrollRestorationManager();
29
+ manager.save("first", { x: 0, y: 1 });
30
+ manager.save("second", { x: 0, y: 2 });
31
+
32
+ manager.delete("first");
33
+ expect(manager.read("first")).toBeNull();
34
+ manager.clear();
35
+ expect(manager.read("second")).toBeNull();
36
+ });
37
+ });
@@ -0,0 +1,60 @@
1
+ export type ScrollRestorationPosition = Readonly<{
2
+ x: number;
3
+ y: number;
4
+ payload?: unknown;
5
+ }>;
6
+
7
+ const DEFAULT_SCROLL_RESTORATION_CAPACITY = 200;
8
+
9
+ function normalizeCoordinate(value: number): number {
10
+ return Number.isFinite(value) ? Math.max(0, value) : 0;
11
+ }
12
+
13
+ function normalizeKey(key: string): string | null {
14
+ const normalized = key.trim();
15
+ return normalized ? normalized : null;
16
+ }
17
+
18
+ /** Owns bounded, in-memory scroll positions for app-internal return navigation. */
19
+ export class ScrollRestorationManager {
20
+ private readonly positions = new Map<string, ScrollRestorationPosition>();
21
+
22
+ public constructor(
23
+ private readonly capacity = DEFAULT_SCROLL_RESTORATION_CAPACITY,
24
+ ) {}
25
+
26
+ public save(key: string, position: ScrollRestorationPosition): void {
27
+ const normalizedKey = normalizeKey(key);
28
+ if (!normalizedKey) return;
29
+
30
+ this.positions.delete(normalizedKey);
31
+ this.positions.set(normalizedKey, {
32
+ x: normalizeCoordinate(position.x),
33
+ y: normalizeCoordinate(position.y),
34
+ ...(position.payload === undefined ? {} : { payload: position.payload }),
35
+ });
36
+ while (this.positions.size > this.capacity) {
37
+ const oldestKey = this.positions.keys().next().value;
38
+ if (!oldestKey) return;
39
+ this.positions.delete(oldestKey);
40
+ }
41
+ }
42
+
43
+ public read(key: string): ScrollRestorationPosition | null {
44
+ const normalizedKey = normalizeKey(key);
45
+ if (!normalizedKey) return null;
46
+ const position = this.positions.get(normalizedKey);
47
+ return position ? { ...position } : null;
48
+ }
49
+
50
+ public delete(key: string): void {
51
+ const normalizedKey = normalizeKey(key);
52
+ if (normalizedKey) this.positions.delete(normalizedKey);
53
+ }
54
+
55
+ public clear(): void {
56
+ this.positions.clear();
57
+ }
58
+ }
59
+
60
+ export const scrollRestorationManager = new ScrollRestorationManager();
@@ -1 +0,0 @@
1
- import{t as e}from"./doc-browser-sJjw9fl5.js";export{e as DocBrowser};
@@ -1 +0,0 @@
1
- import{i as e}from"./chunk-DseTPa7n.js";import{B as t,H as n,L as r,S as i,V as a,a as o,m as s}from"./react-DCVbGroo.js";import{t as c}from"./navigation-link-NjUdG6Vp.js";import{a as l,b as u,c as d,d as f,h as p,i as m,l as h,m as g,o as _,p as v,r as y,s as b,t as x,v as S,y as C}from"./dist-DXbLo2b1.js";import{t as w}from"./dist-NskPB_yW.js";import{t as T}from"./createLucideIcon-DzkNHr5Z.js";import{n as ee,t as te}from"./search-C2CFAVvd.js";import{t as E}from"./book-open-DRofSTWr.js";import{t as D}from"./plus-DVXol9Q5.js";import{t as O}from"./refresh-cw-CkeninE0.js";import{t as k}from"./x-BXvAzpjb.js";import{_ as ne,d as re,g as A,m as j,n as ie,p as ae}from"./doc-browser-context-CnKV4gJy.js";var M=T(`AppWindow`,[[`rect`,{x:`2`,y:`4`,width:`20`,height:`16`,rx:`2`,key:`izxlao`}],[`path`,{d:`M10 4v4`,key:`pp8u80`}],[`path`,{d:`M2 8h20`,key:`d11cs7`}],[`path`,{d:`M6 4v4`,key:`1svtjw`}]]),N=T(`ArrowRight`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]),P=T(`Boxes`,[[`path`,{d:`M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z`,key:`lc1i9w`}],[`path`,{d:`m7 16.5-4.74-2.85`,key:`1o9zyk`}],[`path`,{d:`m7 16.5 5-3`,key:`va8pkn`}],[`path`,{d:`M7 16.5v5.17`,key:`jnp8gn`}],[`path`,{d:`M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z`,key:`8zsnat`}],[`path`,{d:`m17 16.5-5-3`,key:`8arw3v`}],[`path`,{d:`m17 16.5 4.74-2.85`,key:`8rfmw`}],[`path`,{d:`M17 16.5v5.17`,key:`k6z78m`}],[`path`,{d:`M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z`,key:`1xygjf`}],[`path`,{d:`M12 8 7.26 5.15`,key:`1vbdud`}],[`path`,{d:`m12 8 4.74-2.85`,key:`3rx089`}],[`path`,{d:`M12 13.5V8`,key:`1io7kd`}]]),oe=T(`EllipsisVertical`,[[`circle`,{cx:`12`,cy:`12`,r:`1`,key:`41hilf`}],[`circle`,{cx:`12`,cy:`5`,r:`1`,key:`gxeob9`}],[`circle`,{cx:`12`,cy:`19`,r:`1`,key:`lyex9k`}]]),F=T(`Github`,[[`path`,{d:`M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4`,key:`tonef`}],[`path`,{d:`M9 18c-4.51 2-5-2-7-2`,key:`9comsn`}]]),se=T(`GripVertical`,[[`circle`,{cx:`9`,cy:`12`,r:`1`,key:`1vctgf`}],[`circle`,{cx:`9`,cy:`5`,r:`1`,key:`hp0tcf`}],[`circle`,{cx:`9`,cy:`19`,r:`1`,key:`fkjjf6`}],[`circle`,{cx:`15`,cy:`12`,r:`1`,key:`1tmaij`}],[`circle`,{cx:`15`,cy:`5`,r:`1`,key:`19l28e`}],[`circle`,{cx:`15`,cy:`19`,r:`1`,key:`f4zoj3`}]]),ce=T(`PanelRightOpen`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M15 3v18`,key:`14nvp0`}],[`path`,{d:`m10 15-3-3 3-3`,key:`1pgupc`}]]),le=T(`PictureInPicture2`,[[`path`,{d:`M21 9V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10c0 1.1.9 2 2 2h4`,key:`daa4of`}],[`rect`,{width:`10`,height:`7`,x:`12`,y:`13`,rx:`2`,key:`1nb8gs`}]]),ue=T(`PinOff`,[[`path`,{d:`M12 17v5`,key:`bb1du9`}],[`path`,{d:`M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89`,key:`znwnzq`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}],[`path`,{d:`M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11`,key:`c9qhm2`}]]),I=T(`Pin`,[[`path`,{d:`M12 17v5`,key:`bb1du9`}],[`path`,{d:`M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z`,key:`1nkz8b`}]]),L=e(n(),1),R=t(),[z,de]=S(`Tooltip`,[b]),B=b(),fe=`TooltipProvider`,pe=700,V=`tooltip.open`,[me,H]=z(fe),U=e=>{let{__scopeTooltip:t,delayDuration:n=pe,skipDelayDuration:r=300,disableHoverableContent:i=!1,children:a}=e,o=L.useRef(!0),s=L.useRef(!1),c=L.useRef(0);return L.useEffect(()=>{let e=c.current;return()=>window.clearTimeout(e)},[]),(0,R.jsx)(me,{scope:t,isOpenDelayedRef:o,delayDuration:n,onOpen:L.useCallback(()=>{window.clearTimeout(c.current),o.current=!1},[]),onClose:L.useCallback(()=>{window.clearTimeout(c.current),c.current=window.setTimeout(()=>o.current=!0,r)},[r]),isPointerInTransitRef:s,onPointerInTransitChange:L.useCallback(e=>{s.current=e},[]),disableHoverableContent:i,children:a})};U.displayName=fe;var W=`Tooltip`,[he,G]=z(W),K=e=>{let{__scopeTooltip:t,children:n,open:r,defaultOpen:i,onOpenChange:a,disableHoverableContent:o,delayDuration:s}=e,c=H(W,e.__scopeTooltip),l=B(t),[u,d]=L.useState(null),f=p(),m=L.useRef(0),h=o??c.disableHoverableContent,v=s??c.delayDuration,y=L.useRef(!1),[b,x]=g({prop:r,defaultProp:i??!1,onChange:e=>{e?(c.onOpen(),document.dispatchEvent(new CustomEvent(V))):c.onClose(),a?.(e)},caller:W}),S=L.useMemo(()=>b?y.current?`delayed-open`:`instant-open`:`closed`,[b]),C=L.useCallback(()=>{window.clearTimeout(m.current),m.current=0,y.current=!1,x(!0)},[x]),w=L.useCallback(()=>{window.clearTimeout(m.current),m.current=0,x(!1)},[x]),T=L.useCallback(()=>{window.clearTimeout(m.current),m.current=window.setTimeout(()=>{y.current=!0,x(!0),m.current=0},v)},[v,x]);return L.useEffect(()=>()=>{m.current&&=(window.clearTimeout(m.current),0)},[]),(0,R.jsx)(_,{...l,children:(0,R.jsx)(he,{scope:t,contentId:f,open:b,stateAttribute:S,trigger:u,onTriggerChange:d,onTriggerEnter:L.useCallback(()=>{c.isOpenDelayedRef.current?T():C()},[c.isOpenDelayedRef,T,C]),onTriggerLeave:L.useCallback(()=>{h?w():(window.clearTimeout(m.current),m.current=0)},[w,h]),onOpen:C,onClose:w,disableHoverableContent:h,children:n})})};K.displayName=W;var q=`TooltipTrigger`,ge=L.forwardRef((e,t)=>{let{__scopeTooltip:n,...r}=e,i=G(q,n),a=H(q,n),o=B(n),s=C(t,L.useRef(null),i.onTriggerChange),c=L.useRef(!1),l=L.useRef(!1),d=L.useCallback(()=>c.current=!1,[]);return L.useEffect(()=>()=>document.removeEventListener(`pointerup`,d),[d]),(0,R.jsx)(y,{asChild:!0,...o,children:(0,R.jsx)(f.button,{"aria-describedby":i.open?i.contentId:void 0,"data-state":i.stateAttribute,...r,ref:s,onPointerMove:u(e.onPointerMove,e=>{e.pointerType!==`touch`&&!l.current&&!a.isPointerInTransitRef.current&&(i.onTriggerEnter(),l.current=!0)}),onPointerLeave:u(e.onPointerLeave,()=>{i.onTriggerLeave(),l.current=!1}),onPointerDown:u(e.onPointerDown,()=>{i.open&&i.onClose(),c.current=!0,document.addEventListener(`pointerup`,d,{once:!0})}),onFocus:u(e.onFocus,()=>{c.current||i.onOpen()}),onBlur:u(e.onBlur,i.onClose),onClick:u(e.onClick,i.onClose)})})});ge.displayName=q;var J=`TooltipPortal`,[_e,ve]=z(J,{forceMount:void 0}),ye=e=>{let{__scopeTooltip:t,forceMount:n,children:r,container:i}=e,a=G(J,t);return(0,R.jsx)(_e,{scope:t,forceMount:n,children:(0,R.jsx)(w,{present:n||a.open,children:(0,R.jsx)(d,{asChild:!0,container:i,children:r})})})};ye.displayName=J;var Y=`TooltipContent`,be=L.forwardRef((e,t)=>{let n=ve(Y,e.__scopeTooltip),{forceMount:r=n.forceMount,side:i=`top`,...a}=e,o=G(Y,e.__scopeTooltip);return(0,R.jsx)(w,{present:r||o.open,children:o.disableHoverableContent?(0,R.jsx)(Te,{side:i,...a,ref:t}):(0,R.jsx)(xe,{side:i,...a,ref:t})})}),xe=L.forwardRef((e,t)=>{let n=G(Y,e.__scopeTooltip),r=H(Y,e.__scopeTooltip),i=L.useRef(null),a=C(t,i),[o,s]=L.useState(null),{trigger:c,onClose:l}=n,u=i.current,{onPointerInTransitChange:d}=r,f=L.useCallback(()=>{s(null),d(!1)},[d]),p=L.useCallback((e,t)=>{let n=e.currentTarget,r={x:e.clientX,y:e.clientY},i=ke(r,Oe(r,n.getBoundingClientRect())),a=Ae(t.getBoundingClientRect());s(Me([...i,...a])),d(!0)},[d]);return L.useEffect(()=>()=>f(),[f]),L.useEffect(()=>{if(c&&u){let e=e=>p(e,u),t=e=>p(e,c);return c.addEventListener(`pointerleave`,e),u.addEventListener(`pointerleave`,t),()=>{c.removeEventListener(`pointerleave`,e),u.removeEventListener(`pointerleave`,t)}}},[c,u,p,f]),L.useEffect(()=>{if(o){let e=e=>{let t=e.target,n={x:e.clientX,y:e.clientY},r=c?.contains(t)||u?.contains(t),i=!je(n,o);r?f():i&&(f(),l())};return document.addEventListener(`pointermove`,e),()=>document.removeEventListener(`pointermove`,e)}},[c,u,o,l,f]),(0,R.jsx)(Te,{...e,ref:a})}),[Se,Ce]=z(W,{isInside:!1}),we=v(`TooltipContent`),Te=L.forwardRef((e,t)=>{let{__scopeTooltip:n,children:r,"aria-label":i,onEscapeKeyDown:a,onPointerDownOutside:o,...s}=e,c=G(Y,n),u=B(n),{onClose:d}=c;return L.useEffect(()=>(document.addEventListener(V,d),()=>document.removeEventListener(V,d)),[d]),L.useEffect(()=>{if(c.trigger){let e=e=>{e.target?.contains(c.trigger)&&d()};return window.addEventListener(`scroll`,e,{capture:!0}),()=>window.removeEventListener(`scroll`,e,{capture:!0})}},[c.trigger,d]),(0,R.jsx)(h,{asChild:!0,disableOutsidePointerEvents:!1,onEscapeKeyDown:a,onPointerDownOutside:o,onFocusOutside:e=>e.preventDefault(),onDismiss:d,children:(0,R.jsxs)(l,{"data-state":c.stateAttribute,...u,...s,ref:t,style:{...s.style,"--radix-tooltip-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-tooltip-content-available-width":`var(--radix-popper-available-width)`,"--radix-tooltip-content-available-height":`var(--radix-popper-available-height)`,"--radix-tooltip-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-tooltip-trigger-height":`var(--radix-popper-anchor-height)`},children:[(0,R.jsx)(we,{children:r}),(0,R.jsx)(Se,{scope:n,isInside:!0,children:(0,R.jsx)(x,{id:c.contentId,role:`tooltip`,children:i||r})})]})})});be.displayName=Y;var Ee=`TooltipArrow`,De=L.forwardRef((e,t)=>{let{__scopeTooltip:n,...r}=e,i=B(n);return Ce(Ee,n).isInside?null:(0,R.jsx)(m,{...i,...r,ref:t})});De.displayName=Ee;function Oe(e,t){let n=Math.abs(t.top-e.y),r=Math.abs(t.bottom-e.y),i=Math.abs(t.right-e.x),a=Math.abs(t.left-e.x);switch(Math.min(n,r,i,a)){case a:return`left`;case i:return`right`;case n:return`top`;case r:return`bottom`;default:throw Error(`unreachable`)}}function ke(e,t,n=5){let r=[];switch(t){case`top`:r.push({x:e.x-n,y:e.y+n},{x:e.x+n,y:e.y+n});break;case`bottom`:r.push({x:e.x-n,y:e.y-n},{x:e.x+n,y:e.y-n});break;case`left`:r.push({x:e.x+n,y:e.y-n},{x:e.x+n,y:e.y+n});break;case`right`:r.push({x:e.x-n,y:e.y-n},{x:e.x-n,y:e.y+n});break}return r}function Ae(e){let{top:t,right:n,bottom:r,left:i}=e;return[{x:i,y:t},{x:n,y:t},{x:n,y:r},{x:i,y:r}]}function je(e,t){let{x:n,y:r}=e,i=!1;for(let e=0,a=t.length-1;e<t.length;a=e++){let o=t[e],s=t[a],c=o.x,l=o.y,u=s.x,d=s.y;l>r!=d>r&&n<(u-c)*(r-l)/(d-l)+c&&(i=!i)}return i}function Me(e){let t=e.slice();return t.sort((e,t)=>e.x<t.x?-1:e.x>t.x?1:e.y<t.y?-1:e.y>t.y?1:0),Ne(t)}function Ne(e){if(e.length<=1)return e.slice();let t=[];for(let n=0;n<e.length;n++){let r=e[n];for(;t.length>=2;){let e=t[t.length-1],n=t[t.length-2];if((e.x-n.x)*(r.y-n.y)>=(e.y-n.y)*(r.x-n.x))t.pop();else break}t.push(r)}t.pop();let n=[];for(let t=e.length-1;t>=0;t--){let r=e[t];for(;n.length>=2;){let e=n[n.length-1],t=n[n.length-2];if((e.x-t.x)*(r.y-t.y)>=(e.y-t.y)*(r.x-t.x))n.pop();else break}n.push(r)}return n.pop(),t.length===1&&n.length===1&&t[0].x===n[0].x&&t[0].y===n[0].y?t:t.concat(n)}var Pe=U,Fe=K,Ie=ge,Le=ye,Re=be,ze=Pe,Be=Fe,Ve=L.forwardRef(({onFocus:e,...t},n)=>(0,R.jsx)(Ie,{ref:n,onFocus:t=>{e?.(t),!t.defaultPrevented&&!t.currentTarget.matches(`:focus-visible`)&&t.preventDefault()},...t}));Ve.displayName=Ie.displayName;var X=L.forwardRef(({className:e,sideOffset:t=4,...n},i)=>(0,R.jsx)(Le,{children:(0,R.jsx)(Re,{ref:i,sideOffset:t,className:r(`z-[var(--z-tooltip,10150)] overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2`,e),...n})}));X.displayName=Re.displayName;var He={sm:`h-6 w-6 rounded-md p-1`,md:`h-7 w-7 rounded-md p-1.5`,lg:`h-8 w-8 rounded-lg p-1.5`},Ue={default:`text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground disabled:text-muted-foreground/45 disabled:hover:bg-transparent disabled:hover:text-muted-foreground/45`,surface:`text-muted-foreground hover:bg-gray-200/60 hover:text-gray-900 active:bg-gray-200/80 disabled:text-muted-foreground/45 disabled:hover:bg-transparent disabled:hover:text-muted-foreground/45`,strong:`text-muted-foreground hover:bg-black/10 hover:text-foreground disabled:text-muted-foreground/45 disabled:hover:bg-transparent disabled:hover:text-muted-foreground/45`},Z=L.forwardRef(({className:e,disabled:t=!1,icon:n,label:i,size:a=`md`,tone:o=`default`,tooltip:s,tooltipSide:c=`bottom`,...l},u)=>{let d=(0,R.jsx)(`button`,{...l,ref:u,type:`button`,disabled:t,"aria-label":i,className:r(`inline-flex shrink-0 items-center justify-center transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:cursor-not-allowed`,He[a],Ue[o],e),children:n}),f=s===!1?null:s??i;return f?(0,R.jsx)(ze,{delayDuration:250,children:(0,R.jsxs)(Be,{disableHoverableContent:!0,children:[(0,R.jsx)(Ve,{asChild:!0,children:t?(0,R.jsx)(`span`,{className:`inline-flex`,children:d}):d}),(0,R.jsx)(X,{side:c,className:`text-xs`,children:f})]})}):d});Z.displayName=`IconActionButton`;var We=e(a(),1),Ge=(0,L.createContext)(null),Ke=8;function qe({groups:e,label:t,onClose:n,position:i}){let a=(0,L.useRef)(null);(0,L.useLayoutEffect)(()=>{let e=a.current;if(!e)return;let t=e.getBoundingClientRect(),n=i.align===`end`?i.x-t.width:i.x,r=Math.max(Ke,Math.min(n,window.innerWidth-t.width-Ke)),o=Math.max(Ke,Math.min(i.y,window.innerHeight-t.height-Ke));e.style.left=`${r}px`,e.style.top=`${o}px`,e.querySelector(`[role="menuitem"]:not(:disabled)`)?.focus()},[i]);let o=e=>{let t=Array.from(a.current?.querySelectorAll(`[role="menuitem"]:not(:disabled)`)??[]);if(t.length===0)return;let n=t.indexOf(document.activeElement);t[n<0?0:(n+e+t.length)%t.length]?.focus()};return(0,We.createPortal)((0,R.jsx)(`div`,{className:`fixed inset-0 z-[var(--z-tooltip)]`,onContextMenu:e=>e.preventDefault(),onPointerDown:()=>n(!0),children:(0,R.jsx)(`div`,{ref:a,role:`menu`,"aria-label":t,className:`fixed min-w-52 max-w-72 overflow-hidden rounded-xl border border-border bg-popover p-1 text-popover-foreground shadow-[0_18px_48px_-20px_rgba(15,23,42,0.42)]`,style:{left:i.x,top:i.y},onPointerDown:e=>e.stopPropagation(),onKeyDown:e=>{if(e.key===`Escape`)e.preventDefault(),n(!0);else if(e.key===`ArrowDown`)e.preventDefault(),o(1);else if(e.key===`ArrowUp`)e.preventDefault(),o(-1);else if(e.key===`Home`||e.key===`End`){e.preventDefault();let t=a.current?.querySelectorAll(`[role="menuitem"]:not(:disabled)`);t?.[e.key===`Home`?0:t.length-1]?.focus()}},children:e.map((e,t)=>(0,R.jsxs)(`div`,{role:`group`,children:[t>0?(0,R.jsx)(`div`,{className:`my-1 h-px bg-border`}):null,e.items.map(e=>{let t=r(`flex h-8 w-full items-center gap-2 rounded-lg px-2.5 text-left text-[13px] font-medium outline-none transition-colors`,e.destructive?`text-destructive hover:bg-destructive/10 focus-visible:bg-destructive/10`:`text-foreground hover:bg-muted focus-visible:bg-muted`,`disabled:pointer-events-none disabled:opacity-45`),i=(0,R.jsxs)(R.Fragment,{children:[e.icon?(0,R.jsx)(`span`,{className:r(`inline-flex h-4 w-4 shrink-0 items-center justify-center`,e.destructive?`text-destructive`:`text-muted-foreground`),children:e.icon}):null,(0,R.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.label})]});return e.href?(0,R.jsx)(`a`,{role:`menuitem`,className:t,href:e.href,download:e.download,onClick:()=>{e.onSelect?.(),n(!1)},children:i},e.key):(0,R.jsx)(`button`,{type:`button`,role:`menuitem`,disabled:e.disabled,className:t,onClick:()=>{e.onSelect?.(),n(e.restoreFocus!==!1)},children:i},e.key)})]},e.key))})}),document.body)}function Je({children:e,groups:t,label:n}){let[r,i]=(0,L.useState)(null),a=t.filter(e=>e.items.length>0),o=e=>{let t=r?.trigger;i(null),e&&t&&window.setTimeout(()=>t.isConnected&&t.focus(),0)},s=e=>{if(r?.trigger===e){o(!0);return}if(a.length===0)return;let t=e.getBoundingClientRect();i({align:`end`,x:t.right,y:t.bottom,trigger:e})},c=(0,L.cloneElement)(e,{"data-context-menu-open":r?``:void 0,onContextMenu:t=>{if(e.props.onContextMenu?.(t),t.defaultPrevented||a.length===0)return;t.preventDefault();let n=t.currentTarget,r=n.getBoundingClientRect();i({align:`start`,x:t.clientX||r.left,y:t.clientY||r.bottom,trigger:n})}});return(0,R.jsxs)(Ge.Provider,{value:{isOpen:!!r,toggleFromButton:s},children:[c,r?(0,R.jsx)(qe,{groups:a,label:n,position:r,onClose:o}):null]})}function Ye({children:e}){let t=(0,L.useContext)(Ge);if(!t)throw Error(`ContextMenuTrigger must be rendered inside ContextMenu`);return(0,L.cloneElement)(e,{"aria-expanded":t.isOpen,"aria-haspopup":`menu`,onClick:n=>{e.props.onClick?.(n),!n.defaultPrevented&&(n.stopPropagation(),t.toggleFromButton(n.currentTarget))}})}function Xe(e,t){e.stopPropagation(),t()}function Ze(e){return(0,R.jsx)(Z,{...e,size:`sm`,tone:`strong`})}function Qe({tab:e}){if(!e.menuGroups?.some(e=>e.items.length>0))return null;let t=e.menuLabel??e.label;return(0,R.jsx)(`div`,{className:`flex shrink-0`,children:(0,R.jsx)(Ye,{children:(0,R.jsx)(Ze,{icon:(0,R.jsx)(oe,{className:`h-3.5 w-3.5`}),label:t})})})}function $e({tab:e}){let t=e.menuGroups?.some(e=>e.items.length>0)??!1,n=!!(e.onClose&&e.closePlacement!==`leading-hover`),i=n?(0,R.jsx)(Ze,{icon:(0,R.jsx)(k,{className:`h-3.5 w-3.5`}),label:e.closeLabel??``,tooltip:e.closeLabel??null,onClick:t=>Xe(t,e.onClose)}):null;return!t&&!n?null:(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{"aria-hidden":`true`,"data-compact-tab-trailing-spacer":``,className:r(`shrink-0`,t&&n?`w-[50px]`:`w-6`)}),(0,R.jsxs)(`div`,{"data-compact-tab-trailing-actions":``,className:r(`pointer-events-none absolute inset-y-0 right-1 z-10 flex items-center gap-0.5 opacity-0`,`group-hover:pointer-events-auto group-hover:opacity-100 group-focus-within:pointer-events-auto group-focus-within:opacity-100`,`group-data-[context-menu-open]:pointer-events-auto group-data-[context-menu-open]:opacity-100`),children:[t?(0,R.jsx)(Qe,{tab:e}):null,i]})]})}function et({tab:e}){return!e.onClose||e.closePlacement!==`leading-hover`?null:(0,R.jsx)(`div`,{"data-compact-tab-leading-actions":``,className:r(`pointer-events-none absolute inset-y-0 left-1 z-10 flex items-center opacity-0`,`group-hover:pointer-events-auto group-hover:opacity-100 group-focus-within:pointer-events-auto group-focus-within:opacity-100`),children:(0,R.jsx)(Ze,{icon:(0,R.jsx)(k,{className:`h-3.5 w-3.5`}),label:e.closeLabel??``,tooltip:e.closeLabel??null,onClick:t=>Xe(t,e.onClose)})})}function tt({labelClassName:e,tab:t}){let n=!!(t.onClose&&t.closePlacement===`leading-hover`),i=(0,R.jsxs)(`button`,{type:`button`,onClick:t.onSelect,"aria-label":t.label,className:`flex min-w-0 flex-1 items-center gap-1.5 text-left`,children:[t.leadingIcon||n?(0,R.jsx)(`span`,{"data-compact-tab-leading-slot":``,className:r(`inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center`,n&&`group-hover:opacity-0 group-focus-within:opacity-0`),children:t.leadingIcon}):null,(0,R.jsx)(`span`,{className:r(`min-w-0 truncate text-[12px] font-medium`,e,t.labelClassName),children:t.label}),t.badge,t.unreadIndicator]}),a=t.tooltip??t.label;return a?(0,R.jsx)(ze,{delayDuration:250,children:(0,R.jsxs)(Be,{children:[(0,R.jsx)(Ve,{asChild:!0,children:i}),(0,R.jsx)(X,{side:`bottom`,className:`text-xs`,children:a})]})}):i}function nt({activeTabClassName:e,inactiveTabClassName:t,itemRef:n,labelClassName:i,tab:a,tabBaseClassName:o}){let s=(0,R.jsxs)(`div`,{ref:n,"data-compact-tab-item":``,onClick:e=>e.target===e.currentTarget&&a.onSelect(),className:r(o??`flex max-w-[180px] cursor-pointer items-center gap-1.5 border-r border-gray-200/70 border-b-2 px-2.5 py-2 transition-colors`,`group relative`,a.active?e??`border-b-primary bg-white text-gray-900`:t??`border-b-transparent bg-gray-50/85 text-gray-500 hover:bg-gray-100`),children:[(0,R.jsx)(tt,{tab:a,labelClassName:i}),(0,R.jsx)(et,{tab:a}),(0,R.jsx)($e,{tab:a})]});return a.menuGroups?.some(e=>e.items.length>0)?(0,R.jsx)(Je,{groups:a.menuGroups,label:a.menuLabel??a.label,children:s}):s}function rt({actionButtonClassName:e,actions:t,actionsClassName:n,actionsTestId:i,className:a,onPointerDown:o,onScrollPointerDown:s,scrollClassName:c,scrollTestId:l,tabs:u,tabsClassName:d,testId:f,...p}){let m=L.useCallback(e=>{e?.scrollIntoView?.({block:`nearest`,inline:`nearest`})},[]);return(0,R.jsxs)(`div`,{"data-testid":f,className:r(`flex min-w-0 items-stretch border-b border-gray-200/70 bg-gray-50/85`,a),onPointerDown:o,children:[(0,R.jsx)(`div`,{className:r(`min-w-0 flex-1 overflow-x-auto overflow-y-hidden`,c),onPointerDown:s,children:(0,R.jsx)(`div`,{"data-testid":l,className:r(`flex min-w-max items-stretch`,d),children:u.map(e=>(0,R.jsx)(nt,{itemRef:e.active?m:void 0,tab:e,...p},e.key))})}),(0,R.jsx)(`div`,{className:r(`flex shrink-0 items-center gap-1`,n),"data-testid":i,onPointerDown:e=>e.stopPropagation(),children:t.map(t=>(0,R.jsx)(Z,{icon:t.icon,label:t.label,disabled:t.disabled,onClick:t.onClick,className:e},t.key))})]})}function it(){return(0,R.jsx)(`div`,{className:`flex h-full items-center justify-center bg-background px-5 py-6`,children:(0,R.jsxs)(`div`,{className:`flex max-w-[260px] flex-col items-center gap-3 text-center`,children:[(0,R.jsx)(`span`,{className:`flex h-12 w-12 items-center justify-center rounded-lg border border-border bg-muted text-muted-foreground shadow-[0_1px_2px_rgba(30,20,10,0.04)]`,children:(0,R.jsx)(P,{className:`h-5 w-5`})}),(0,R.jsx)(`span`,{className:`text-sm font-medium text-foreground`,children:o(`docBrowserHomeTitle`)})]})})}function at(e){if(!e||typeof e!=`object`)return!1;let t=e;return t.kind===`document`?!0:t.kind===`element`&&Array.isArray(t.path)&&t.path.length>0&&t.path.length<=30&&t.path.every(e=>typeof e?.index==`number`&&Number.isInteger(e.index)&&e.index>=0&&e.index<=1e3&&typeof e.tagName==`string`&&e.tagName.length>0&&e.tagName.length<=32)}function ot(e){if(!e||typeof e!=`object`)return!1;let t=e;return t.type===s.scrollMessageType&&t.version===s.version&&at(t.target)&&typeof t.x==`number`&&Number.isFinite(t.x)&&t.x>=0&&typeof t.y==`number`&&Number.isFinite(t.y)&&t.y>=0}function st({currentTab:e,iframeRef:t,isEnabled:n,tabs:r}){let i=(0,L.useRef)(new Map);return(0,L.useEffect)(()=>{let e=new Set(r.map(e=>e.id));for(let t of i.current.keys())e.has(t)||i.current.delete(t)},[r]),(0,L.useEffect)(()=>{if(!e||!n)return;let r=n=>{n.source!==t.current?.contentWindow||!ot(n.data)||i.current.set(e.id,{currentUrl:e.currentUrl,target:n.data.target,x:n.data.x,y:n.data.y})};return window.addEventListener(`message`,r),()=>window.removeEventListener(`message`,r)},[e,t,n]),(0,L.useCallback)(()=>{if(!e||!n)return;let r=i.current.get(e.id);!r||r.currentUrl!==e.currentUrl||t.current?.contentWindow?.postMessage({type:s.restoreScrollMessageType,version:s.version,target:r.target,x:r.x,y:r.y},`*`)},[e,t,n])}function ct({isVisible:e,onRefresh:t,onSubmit:n,onUrlInputChange:r,placeholder:i,urlInput:a}){return e?(0,R.jsxs)(`div`,{className:`flex items-center gap-2 border-b border-border/70 bg-card px-3.5 py-2 shrink-0`,children:[(0,R.jsxs)(`form`,{onSubmit:n,className:`flex-1 relative`,children:[(0,R.jsx)(te,{className:`absolute left-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground/70`}),(0,R.jsx)(`input`,{type:`text`,value:a,onChange:e=>r(e.target.value),"aria-label":o(`docBrowserAddressLabel`),placeholder:i,className:`h-8 w-full rounded-lg border border-border/75 bg-background pl-8 pr-3 text-xs text-foreground transition-colors placeholder:text-muted-foreground/55 focus:outline-none focus:ring-0`})]}),(0,R.jsx)(Z,{icon:(0,R.jsx)(O,{className:`h-3.5 w-3.5`}),label:o(`docBrowserRefresh`),onClick:t})]}):null}function lt({currentTab:e,currentUrl:t,customContent:n,iframeRef:r,iframeInstanceId:a,iframeSandbox:o,isDragging:s,isResizing:c,onIframeLoad:l,onIframePointerOver:u}){return(0,R.jsxs)(`div`,{className:`flex-1 relative overflow-hidden`,children:[n||(0,R.jsx)(`iframe`,{ref:r,src:t,name:i(e?.contentParams),className:`absolute inset-0 w-full h-full border-0`,title:e?.title||`NextClaw Docs`,sandbox:o,tabIndex:u?0:void 0,onLoad:l,onPointerOver:u,allow:`clipboard-read; clipboard-write`,allowFullScreen:!0},a),(c||s)&&(0,R.jsx)(`div`,{className:`absolute inset-0 z-10`})]})}function ut(e){try{let t=new URL(e,window.location.origin);return t.protocol===`http:`||t.protocol===`https:`}catch{return!1}}function dt({currentUrl:e,isVisible:t}){if(!t||!ut(e))return null;let n=A(e)?o(`docBrowserOpenExternal`):o(`docBrowserOpenInBrowser`);return(0,R.jsx)(`div`,{className:`flex items-center justify-between border-t border-border/70 bg-muted/55 px-4 py-2 shrink-0`,children:(0,R.jsx)(c,{href:e,external:!0,iconPosition:`trailing`,size:`xs`,"data-doc-external":!0,children:n})})}var ft={apps:P,docs:E,github:F,"new-tab":D,"panel-app":M,"service-apps":M};function pt({fallbackIcon:e,url:t}){let[n,r]=(0,L.useState)(!1);return n?(0,R.jsx)(e,{className:`h-3.5 w-3.5 text-muted-foreground`,"aria-hidden":`true`}):(0,R.jsx)(`img`,{src:t,alt:``,className:`h-3.5 w-3.5 rounded-sm object-cover`,onError:()=>r(!0)})}function mt({tab:e}){let{dockIcon:t}=e,n=e.kind===`docs`?E:e.kind===`home`?D:e.kind===`apps`?P:M,r=t?.type===`builtin`?ft[t.name]??n:n;return t?.type===`url`?(0,R.jsx)(pt,{fallbackIcon:n,url:t.url},t.url):t?.type===`text`?(0,R.jsx)(`span`,{className:`max-w-3.5 truncate text-[10px] font-semibold leading-none`,"aria-hidden":`true`,children:t.value}):(0,R.jsx)(r,{className:`h-3.5 w-3.5 text-muted-foreground`,"aria-hidden":`true`})}function ht(e){return e instanceof Element&&!!e.closest(`button, a, input, textarea, select, [data-compact-tab-item]`)}function gt({tabs:e,activeTabId:t,canGoBack:n,canGoForward:i,isDocked:a,isFullscreen:s,dockState:c,onGoBack:l,onGoForward:u,onOpenNewTab:d,onToggleDock:f,onSetActiveTab:p,onCloseTab:m,onClose:h,onDragStart:g,onToggleMode:_,getTabMenuGroups:v}){let y=o(`docBrowserBack`),b=o(`docBrowserClose`),x=o(`docBrowserCloseTab`),S=c?.isDocked?c.removable?o(`sideDockUnpinCurrent`):o(`sideDockBuiltInDocked`):o(`sideDockPinCurrent`),C=o(`docBrowserForward`),w=o(a?`docBrowserFloatMode`:`docBrowserDockMode`),T=o(`docBrowserNewTab`);return(0,R.jsx)(rt,{testId:`doc-browser-tab-strip`,actionsTestId:`doc-browser-tab-actions`,tabs:e.map(e=>({key:e.id,label:e.title||o(`docBrowserTabUntitled`),active:e.id===t,tooltip:e.title,leadingIcon:(0,R.jsx)(mt,{tab:e}),closeLabel:x,closePlacement:`leading-hover`,onSelect:()=>p(e.id),onClose:()=>m(e.id),menuLabel:o(`docBrowserTabMoreActions`),menuGroups:v?.(e)})),actions:[{key:`back`,disabled:!n,icon:(0,R.jsx)(ee,{className:`h-3.5 w-3.5`}),label:y,onClick:l},{key:`forward`,disabled:!i,icon:(0,R.jsx)(N,{className:`h-3.5 w-3.5`}),label:C,onClick:u},{key:`new-tab`,icon:(0,R.jsx)(D,{className:`h-3.5 w-3.5`}),label:T,onClick:d},...c?.canDock?[{key:`dock`,disabled:c.isDocked&&!c.removable,icon:c.isDocked&&c.removable?(0,R.jsx)(ue,{className:`h-3.5 w-3.5`}):(0,R.jsx)(I,{className:`h-3.5 w-3.5`}),label:S,onClick:()=>f?.()}]:[],...s?[]:[{key:`mode`,icon:a?(0,R.jsx)(le,{className:`h-3.5 w-3.5`}):(0,R.jsx)(ce,{className:`h-3.5 w-3.5`}),label:w,onClick:_}],{key:`close`,icon:(0,R.jsx)(k,{className:`h-3.5 w-3.5`}),label:b,onClick:h}],className:r(`h-10 gap-1.5 border-border/50 bg-card/80 px-2 shrink-0 select-none`,s&&`h-[calc(env(safe-area-inset-top,0px)+2.5rem)] pt-[env(safe-area-inset-top,0px)]`),scrollClassName:r(`doc-browser-tab-scrollbar flex h-full items-center gap-0.5`,!a&&!s&&`cursor-grab active:cursor-grabbing`),tabsClassName:`items-center gap-0.5`,actionsClassName:`h-full items-center gap-0.5`,actionButtonClassName:`rounded-md p-1.5 text-muted-foreground hover:bg-muted/60 hover:text-foreground disabled:opacity-50`,tabBaseClassName:`inline-flex cursor-pointer items-center gap-0.5 h-7 px-2 rounded-md text-xs max-w-[220px] shrink-0 transition-colors`,activeTabClassName:`bg-muted/80 text-foreground`,inactiveTabClassName:`text-muted-foreground hover:bg-muted/45 hover:text-foreground`,labelClassName:`px-0.5 text-xs font-normal`,onPointerDown:!a&&!s?g:void 0,onScrollPointerDown:e=>{if(ht(e.target)){e.stopPropagation();return}!a&&!s&&(e.stopPropagation(),g(e))}})}var Q=40,_t=360,vt=400;function $(e,t,n){return Math.min(n,Math.max(t,e))}function yt(e,t){return e.split(`-`).includes(t)}function bt(){return{x:Math.max(Q,window.innerWidth-520),y:80,w:480,h:600}}function xt(e,t,n){return{...e,x:$(e.x+t,Q,window.innerWidth-Q-e.w),y:$(e.y+n,Q,window.innerHeight-Q-e.h)}}function St(e,t,n,r){let i=t.x+t.w,a=t.y+t.h,o=yt(e,`left`)?$(t.x+n,Q,i-_t):t.x,s=yt(e,`right`)?$(i+n,o+_t,window.innerWidth-Q):i,c=yt(e,`top`)?$(t.y+r,Q,a-vt):t.y,l=yt(e,`bottom`)?$(a+r,c+vt,window.innerHeight-Q):a;return{x:o,y:c,w:s-o,h:l-c}}function Ct({children:e,className:t,style:n,defaultWidth:i=420,minWidth:a=320,maxWidth:o=860,onWidthCommit:s,overlay:c=!1,overlayScope:l=`viewport`,width:u,...d}){let f=(0,L.useRef)(null),p=(0,L.useRef)(u??i),[m,h]=(0,L.useState)(!1),[g,_]=(0,L.useState)(null),[v,y]=(0,L.useState)(i),b=g??u??v,x=c?l===`container`?`absolute inset-0 z-30`:`fixed inset-0 z-40`:`border-l border-border`,S=e=>{if(c)return;e.preventDefault(),e.stopPropagation(),e.currentTarget.setPointerCapture?.(e.pointerId),h(!0),p.current=b,f.current={startX:e.clientX,startWidth:b};let t=e=>{let t=f.current;if(!t)return;let n=t.startWidth+t.startX-e.clientX,r=Math.max(a,Math.min(o,n));p.current=r,_(r)},n=()=>{u===void 0&&y(p.current),s?.(p.current),_(null),h(!1),f.current=null,window.removeEventListener(`pointermove`,t),window.removeEventListener(`pointerup`,n),window.removeEventListener(`pointercancel`,n)};window.addEventListener(`pointermove`,t),window.addEventListener(`pointerup`,n),window.addEventListener(`pointercancel`,n)};return(0,R.jsxs)(`aside`,{...d,className:r(`relative flex h-full min-h-0 shrink-0 overflow-hidden bg-card text-card-foreground`,x,t),style:c?n:{...n,width:b},children:[(0,R.jsx)(`div`,{className:`flex h-full min-h-0 w-full flex-col overflow-hidden`,children:e}),c?null:(0,R.jsx)(`div`,{className:`absolute left-0 top-0 z-30 h-full w-3 cursor-ew-resize transition-colors hover:bg-primary/10`,"data-testid":`resizable-right-panel-handle`,onPointerDown:S}),m?(0,R.jsx)(`div`,{className:`absolute inset-0 z-10 cursor-ew-resize`,"data-testid":`resizable-right-panel-resize-shield`}):null]})}var wt=`allow-same-origin allow-scripts allow-popups allow-forms`;function Tt(e,t){if(e.startsWith(`/`))try{return new URL(e,t).toString()}catch{return e}return/^[a-z][a-z\d+.-]*:\/\//i.test(e)||e===`about:blank`?e:/^(localhost|127\.|0\.0\.0\.0|\[::1\])(?::|\/|$)/i.test(e)?`http://${e}`:`https://${e}`}function Et(e,t){if(!t)return wt;let n=e?.getIframeSandbox?.(t);return n===void 0?t.kind===`content`?void 0:wt:n}function Dt(e,t,n){return(0,L.useCallback)(()=>{if(n?.canDock){if(n.isDocked){n.removable&&e?.unpinTab(t);return}e?.pinTab(t)}},[t,e,n])}function Ot({activeTabId:e,currentUrl:t,isAddressToolbarTab:n,isContentTab:r,isDocsTab:i,navigate:a}){let o=`${e}:${t}:${r?`content`:`docs`}`,[s,c]=(0,L.useState)(null),l=(()=>{if(!n)return``;if(r)return t;try{return new URL(t).pathname}catch{return t}})(),u=s?.key===o?s.value:l,d=(0,L.useCallback)(e=>c({key:o,value:e}),[o]);return{handleUrlSubmit:(0,L.useCallback)(e=>{if(e.preventDefault(),!n)return;let r=u.trim();r&&(i&&r.startsWith(`/`)?a(j(r)):i&&r.startsWith(`http`)?a(r):a(i?j(`/${r}`):Tt(r,t)))},[t,n,i,a,u]),setUrlInput:d,urlInput:u}}function kt({customTabRenderers:e={},displayMode:t=`desktop`,dockControls:n,getTabMenuGroups:i}){let{isOpen:a,mode:s,dockedWidth:c,tabs:l,activeTabId:u,activeHistory:d,activeHistoryIndex:f,currentTab:p,open:m,openTarget:h,openNewTab:g,close:_,toggleMode:v,setDockedWidth:y,goBack:b,goForward:x,navigate:S,syncUrl:C,setActiveTab:w,closeTab:T}=ie(),[ee,te]=(0,L.useState)(0),[E,D]=(0,L.useState)(bt),[O,k]=(0,L.useState)(null),A=(0,L.useRef)(null),j=p?.currentUrl??ae(),M=p?.navVersion??0,N=`${u}:${M}:${ee}`,P=(0,L.useRef)(null),oe=(0,L.useRef)(M),F=p?.kind===`docs`,ce=p?.kind===re,le=f>0,ue=f<d.length-1,I=p?e[p.kind]:void 0,z=n?.getDockState(p),de=p?.kind===`content`,B=F||de,fe=st({currentTab:p,iframeRef:A,isEnabled:I?.supportsScrollRestoration===!0,tabs:l}),{handleUrlSubmit:pe,setUrlInput:V,urlInput:me}=Ot({activeTabId:u,currentUrl:j,isAddressToolbarTab:B,isContentTab:de,isDocsTab:F,navigate:S});(0,L.useEffect)(()=>{if(!F){P.current=null;return}if(M!==oe.current){oe.current=M,P.current=ne(j);return}if(A.current?.contentWindow)try{let e=new URL(j).pathname;P.current=ne(j),A.current.contentWindow.postMessage({type:`docs-navigate`,path:e},`*`)}catch{}},[j,M,F]),(0,L.useEffect)(()=>{let e=e=>{if(F&&e.data?.type===`docs-route-change`&&typeof e.data.url==`string`){let t=ne(e.data.url);if(P.current&&t!==P.current)return;P.current=null,C(e.data.url)}};return window.addEventListener(`message`,e),()=>window.removeEventListener(`message`,e)},[j,C,F]),(0,L.useEffect)(()=>{if(!p||!I?.onIframeMessage)return;let e=e=>{I.onIframeMessage?.({event:e,iframe:A.current,iframeInstanceId:N,tab:p})};return window.addEventListener(`message`,e),()=>window.removeEventListener(`message`,e)},[p,I,N]);let H=(0,L.useCallback)(e=>{e.preventDefault(),k({kind:`drag`,startX:e.clientX,startY:e.clientY,startRect:E})},[E]),U=(0,L.useCallback)(e=>t=>{t.preventDefault(),t.stopPropagation(),k({kind:`resize`,edge:e,startX:t.clientX,startY:t.clientY,startRect:E})},[E]);(0,L.useEffect)(()=>{if(!O)return;let e=e=>{let{startRect:t,startX:n,startY:r}=O,i=e.clientX-n,a=e.clientY-r;if(O.kind===`drag`){D(xt(t,i,a));return}D(St(O.edge,t,i,a))},t=()=>k(null);return window.addEventListener(`pointermove`,e),window.addEventListener(`pointerup`,t),window.addEventListener(`pointercancel`,t),()=>{window.removeEventListener(`pointermove`,e),window.removeEventListener(`pointerup`,t),window.removeEventListener(`pointercancel`,t)}},[O]);let W=(0,L.useCallback)(()=>{te(e=>e+1)},[]),he=Dt(n,p,z);if(!a)return null;let G=s===`docked`,K=t===`fullscreen`,q=p?{currentUrl:j,open:m,openTarget:h,refreshIframe:W,tab:p}:void 0,ge=q?I?.renderToolbar?.(q):null,J=q?I?.renderContent?.(q)??(ce?(0,R.jsx)(it,{}):null):null,_e=Et(I,p),ve=(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(gt,{tabs:l,activeTabId:u,canGoBack:le,canGoForward:ue,dockState:z,isDocked:G,isFullscreen:K,onGoBack:b,onGoForward:x,onOpenNewTab:g,onToggleDock:he,onSetActiveTab:w,onCloseTab:T,onClose:_,onDragStart:H,onToggleMode:v,getTabMenuGroups:i}),(0,R.jsx)(ct,{isVisible:B,onRefresh:W,onSubmit:pe,onUrlInputChange:V,placeholder:o(F?`docBrowserSearchPlaceholder`:`docBrowserAddressPlaceholder`),urlInput:me}),ge,(0,R.jsx)(lt,{currentTab:p,currentUrl:j,customContent:J,iframeRef:A,iframeInstanceId:N,iframeSandbox:_e,isDragging:O?.kind===`drag`,isResizing:O?.kind===`resize`,onIframeLoad:fe,onIframePointerOver:I?.onIframePointerOver}),(0,R.jsx)(dt,{currentUrl:j,isVisible:F||de})]});return G&&!K?(0,R.jsx)(Ct,{"data-testid":`doc-browser-panel`,defaultWidth:c,width:c,minWidth:320,maxWidth:860,onWidthCommit:y,children:ve}):(0,R.jsxs)(`div`,{"data-testid":`doc-browser-panel`,className:r(`relative flex flex-col overflow-hidden bg-card text-card-foreground`,K?`fixed inset-0 z-[var(--z-floating-panel)] h-[100dvh] w-screen rounded-none border-0 shadow-2xl`:`rounded-2xl border border-border shadow-2xl`),style:K?void 0:{position:`fixed`,left:E.x,top:E.y,width:E.w,height:E.h,zIndex:`var(--z-floating-panel)`},children:[ve,!G&&!K&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`div`,{className:`absolute top-0 left-0 h-3 w-full cursor-ns-resize z-20 hover:bg-primary/10 transition-colors`,"data-testid":`doc-browser-resize-top`,onPointerDown:U(`top`)}),(0,R.jsx)(`div`,{className:`absolute top-0 left-0 w-3 h-full cursor-ew-resize z-20 hover:bg-primary/10 transition-colors`,"data-testid":`doc-browser-resize-left`,onPointerDown:U(`left`)}),(0,R.jsx)(`div`,{className:`absolute top-0 right-0 w-3 h-full cursor-ew-resize z-20 hover:bg-primary/10 transition-colors`,"data-testid":`doc-browser-resize-right`,onPointerDown:U(`right`)}),(0,R.jsx)(`div`,{className:`absolute bottom-0 left-0 h-3 w-full cursor-ns-resize z-20 hover:bg-primary/10 transition-colors`,"data-testid":`doc-browser-resize-bottom`,onPointerDown:U(`bottom`)}),(0,R.jsx)(`div`,{className:`absolute top-0 left-0 z-30 h-4 w-4 cursor-nw-resize hover:bg-primary/10 transition-colors`,"data-testid":`doc-browser-resize-top-left`,onPointerDown:U(`top-left`)}),(0,R.jsx)(`div`,{className:`absolute top-0 right-0 z-30 h-4 w-4 cursor-ne-resize hover:bg-primary/10 transition-colors`,"data-testid":`doc-browser-resize-top-right`,onPointerDown:U(`top-right`)}),(0,R.jsx)(`div`,{className:`absolute bottom-0 left-0 z-30 h-4 w-4 cursor-sw-resize hover:bg-primary/10 transition-colors`,"data-testid":`doc-browser-resize-bottom-left`,onPointerDown:U(`bottom-left`)}),(0,R.jsx)(`div`,{className:`absolute bottom-0 right-0 z-30 flex h-4 w-4 cursor-se-resize items-center justify-center text-muted-foreground/45 transition-colors hover:text-muted-foreground`,"data-testid":`doc-browser-resize-bottom-right`,onPointerDown:U(`bottom-right`),children:(0,R.jsx)(se,{className:`w-3 h-3 rotate-[-45deg]`})})]})]})}export{M as S,ce as _,Ye as a,P as b,X as c,Re as d,Le as f,I as g,Ie as h,Je as i,ze as l,Fe as m,Ct as n,Z as o,Pe as p,rt as r,Be as s,kt as t,Ve as u,F as v,N as x,oe as y};