@mseep/anything-analyzer 3.6.50

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 (172) hide show
  1. package/.codeartsdoer/.codebaseignore +0 -0
  2. package/.codeartsdoer/AGENTS.md +12 -0
  3. package/.github/workflows/build.yml +146 -0
  4. package/README.en.md +264 -0
  5. package/README.md +276 -0
  6. package/RELEASE_NOTES.md +16 -0
  7. package/USAGE.md +490 -0
  8. package/color-preview-r3.html +414 -0
  9. package/color-preview.html +414 -0
  10. package/dev-app-update.yml +3 -0
  11. package/electron-builder.yml +36 -0
  12. package/electron.vite.config.ts +40 -0
  13. package/package.json +53 -0
  14. package/report-2026-04-13-copilot-claude-sonnet-4.6.md +955 -0
  15. package/resources/doloffer-logo.png +0 -0
  16. package/resources/entitlements.mac.plist +12 -0
  17. package/resources/icon.ico +0 -0
  18. package/resources/icon.png +0 -0
  19. package/src/main/ai/ai-analyzer.ts +517 -0
  20. package/src/main/ai/crypto-script-extractor.ts +206 -0
  21. package/src/main/ai/data-assembler.ts +205 -0
  22. package/src/main/ai/llm-router.ts +1120 -0
  23. package/src/main/ai/prompt-builder.ts +349 -0
  24. package/src/main/ai/scene-detector.ts +302 -0
  25. package/src/main/capture/capture-engine.ts +130 -0
  26. package/src/main/capture/interaction-recorder.ts +171 -0
  27. package/src/main/capture/js-injector.ts +57 -0
  28. package/src/main/capture/replay-engine.ts +256 -0
  29. package/src/main/capture/storage-collector.ts +76 -0
  30. package/src/main/cdp/cdp-manager.ts +233 -0
  31. package/src/main/db/database.ts +41 -0
  32. package/src/main/db/migrations.ts +235 -0
  33. package/src/main/db/repositories.ts +574 -0
  34. package/src/main/fingerprint/http-spoofing.ts +48 -0
  35. package/src/main/fingerprint/presets.ts +173 -0
  36. package/src/main/fingerprint/profile-generator.ts +115 -0
  37. package/src/main/fingerprint/profile-store.ts +52 -0
  38. package/src/main/index.ts +260 -0
  39. package/src/main/ipc.ts +856 -0
  40. package/src/main/logger.ts +42 -0
  41. package/src/main/mcp/mcp-config.ts +66 -0
  42. package/src/main/mcp/mcp-manager.ts +155 -0
  43. package/src/main/mcp/mcp-server.ts +1038 -0
  44. package/src/main/prompt-templates.ts +170 -0
  45. package/src/main/proxy/ca-manager.ts +204 -0
  46. package/src/main/proxy/cert-download-page.ts +171 -0
  47. package/src/main/proxy/cert-installer.ts +242 -0
  48. package/src/main/proxy/mitm-proxy-config.ts +37 -0
  49. package/src/main/proxy/mitm-proxy-server.ts +1085 -0
  50. package/src/main/proxy/system-proxy.ts +248 -0
  51. package/src/main/session/session-manager.ts +724 -0
  52. package/src/main/tab-manager.ts +582 -0
  53. package/src/main/updater.ts +111 -0
  54. package/src/main/window.ts +235 -0
  55. package/src/preload/hook-script.ts +270 -0
  56. package/src/preload/index.ts +211 -0
  57. package/src/preload/interaction-hook.ts +286 -0
  58. package/src/preload/stealth-script.ts +302 -0
  59. package/src/preload/target-preload.ts +15 -0
  60. package/src/renderer/App.tsx +656 -0
  61. package/src/renderer/components/AiLogDetail.tsx +173 -0
  62. package/src/renderer/components/AiLogList.tsx +101 -0
  63. package/src/renderer/components/AiLogView.module.css +364 -0
  64. package/src/renderer/components/AiLogView.tsx +86 -0
  65. package/src/renderer/components/AnalyzeBar.module.css +79 -0
  66. package/src/renderer/components/AnalyzeBar.tsx +104 -0
  67. package/src/renderer/components/BrowserPanel.module.css +67 -0
  68. package/src/renderer/components/BrowserPanel.tsx +90 -0
  69. package/src/renderer/components/ControlBar.module.css +47 -0
  70. package/src/renderer/components/ControlBar.tsx +205 -0
  71. package/src/renderer/components/HookLog.tsx +132 -0
  72. package/src/renderer/components/InteractionLog.tsx +183 -0
  73. package/src/renderer/components/MCPServerModal.tsx +427 -0
  74. package/src/renderer/components/PromptTemplateModal.tsx +254 -0
  75. package/src/renderer/components/ReportView.module.css +413 -0
  76. package/src/renderer/components/ReportView.tsx +429 -0
  77. package/src/renderer/components/RequestDetail.module.css +191 -0
  78. package/src/renderer/components/RequestDetail.tsx +202 -0
  79. package/src/renderer/components/RequestLog.module.css +69 -0
  80. package/src/renderer/components/RequestLog.tsx +208 -0
  81. package/src/renderer/components/SessionList.module.css +245 -0
  82. package/src/renderer/components/SessionList.tsx +247 -0
  83. package/src/renderer/components/SettingsModal.tsx +100 -0
  84. package/src/renderer/components/StatusBar.module.css +44 -0
  85. package/src/renderer/components/StatusBar.tsx +102 -0
  86. package/src/renderer/components/StorageView.module.css +41 -0
  87. package/src/renderer/components/StorageView.tsx +178 -0
  88. package/src/renderer/components/TabBar.module.css +88 -0
  89. package/src/renderer/components/TabBar.tsx +70 -0
  90. package/src/renderer/components/Titlebar.module.css +254 -0
  91. package/src/renderer/components/Titlebar.tsx +169 -0
  92. package/src/renderer/components/settings/FingerprintSection.tsx +198 -0
  93. package/src/renderer/components/settings/GeneralSection.tsx +164 -0
  94. package/src/renderer/components/settings/LLMSection.tsx +148 -0
  95. package/src/renderer/components/settings/MCPServerSection.tsx +136 -0
  96. package/src/renderer/components/settings/MitmProxySection.tsx +320 -0
  97. package/src/renderer/components/settings/ProxySection.tsx +110 -0
  98. package/src/renderer/css-modules.d.ts +4 -0
  99. package/src/renderer/hooks/useCapture.ts +383 -0
  100. package/src/renderer/hooks/useConfirm.tsx +91 -0
  101. package/src/renderer/hooks/useSession.ts +136 -0
  102. package/src/renderer/hooks/useTabs.ts +103 -0
  103. package/src/renderer/i18n/en.ts +167 -0
  104. package/src/renderer/i18n/index.ts +47 -0
  105. package/src/renderer/i18n/zh.ts +170 -0
  106. package/src/renderer/index.html +12 -0
  107. package/src/renderer/main.tsx +15 -0
  108. package/src/renderer/styles/global.css +144 -0
  109. package/src/renderer/styles/themes/ayu-dark.css +59 -0
  110. package/src/renderer/styles/themes/catppuccin.css +59 -0
  111. package/src/renderer/styles/themes/discord.css +59 -0
  112. package/src/renderer/styles/themes/dracula.css +59 -0
  113. package/src/renderer/styles/themes/github-dark.css +59 -0
  114. package/src/renderer/styles/themes/gruvbox.css +59 -0
  115. package/src/renderer/styles/themes/index.css +11 -0
  116. package/src/renderer/styles/themes/light.css +59 -0
  117. package/src/renderer/styles/themes/nord.css +59 -0
  118. package/src/renderer/styles/themes/one-dark.css +59 -0
  119. package/src/renderer/styles/themes/tokyo-night.css +59 -0
  120. package/src/renderer/styles/tokens.css +137 -0
  121. package/src/renderer/theme.ts +31 -0
  122. package/src/renderer/ui/Badge.module.css +38 -0
  123. package/src/renderer/ui/Badge.tsx +36 -0
  124. package/src/renderer/ui/Button.module.css +142 -0
  125. package/src/renderer/ui/Button.tsx +46 -0
  126. package/src/renderer/ui/Collapse.module.css +49 -0
  127. package/src/renderer/ui/Collapse.tsx +57 -0
  128. package/src/renderer/ui/CopyableBlock.module.css +56 -0
  129. package/src/renderer/ui/CopyableBlock.tsx +42 -0
  130. package/src/renderer/ui/Empty.module.css +19 -0
  131. package/src/renderer/ui/Empty.tsx +34 -0
  132. package/src/renderer/ui/Icons.tsx +346 -0
  133. package/src/renderer/ui/Input.module.css +103 -0
  134. package/src/renderer/ui/Input.tsx +94 -0
  135. package/src/renderer/ui/InputNumber.module.css +68 -0
  136. package/src/renderer/ui/InputNumber.tsx +104 -0
  137. package/src/renderer/ui/Modal.module.css +83 -0
  138. package/src/renderer/ui/Modal.tsx +67 -0
  139. package/src/renderer/ui/Popconfirm.module.css +73 -0
  140. package/src/renderer/ui/Popconfirm.tsx +74 -0
  141. package/src/renderer/ui/Progress.module.css +35 -0
  142. package/src/renderer/ui/Progress.tsx +30 -0
  143. package/src/renderer/ui/Select.module.css +91 -0
  144. package/src/renderer/ui/Select.tsx +100 -0
  145. package/src/renderer/ui/Spinner.module.css +44 -0
  146. package/src/renderer/ui/Spinner.tsx +27 -0
  147. package/src/renderer/ui/Switch.module.css +39 -0
  148. package/src/renderer/ui/Switch.tsx +43 -0
  149. package/src/renderer/ui/Tabs.module.css +76 -0
  150. package/src/renderer/ui/Tabs.tsx +53 -0
  151. package/src/renderer/ui/Tag.module.css +66 -0
  152. package/src/renderer/ui/Tag.tsx +47 -0
  153. package/src/renderer/ui/Timeline.module.css +42 -0
  154. package/src/renderer/ui/Timeline.tsx +29 -0
  155. package/src/renderer/ui/Toast.module.css +99 -0
  156. package/src/renderer/ui/Toast.tsx +90 -0
  157. package/src/renderer/ui/Tooltip.module.css +26 -0
  158. package/src/renderer/ui/Tooltip.tsx +23 -0
  159. package/src/renderer/ui/VirtualTable.module.css +230 -0
  160. package/src/renderer/ui/VirtualTable.tsx +416 -0
  161. package/src/renderer/ui/index.ts +55 -0
  162. package/src/shared/types.ts +695 -0
  163. package/tests/main/ai/crypto-script-extractor.test.ts +281 -0
  164. package/tests/main/ai/llm-router.test.ts +1537 -0
  165. package/tests/main/ai/prompt-builder.test.ts +178 -0
  166. package/tests/main/ai/scene-detector.test.ts +212 -0
  167. package/tests/main/db/migrations.test.ts +134 -0
  168. package/tests/main/release-workflow.test.ts +59 -0
  169. package/tsconfig.json +7 -0
  170. package/tsconfig.node.json +23 -0
  171. package/tsconfig.web.json +24 -0
  172. package/vitest.config.ts +13 -0
@@ -0,0 +1,346 @@
1
+ import React from 'react'
2
+
3
+ // All icons are 1em by default, inherit currentColor
4
+ interface IconProps extends React.SVGAttributes<SVGSVGElement> {
5
+ size?: number | string
6
+ }
7
+
8
+ const defaultProps = (props: IconProps): React.SVGAttributes<SVGSVGElement> => {
9
+ const { size = '1em', ...rest } = props
10
+ return {
11
+ width: size,
12
+ height: size,
13
+ viewBox: '0 0 24 24',
14
+ fill: 'none',
15
+ stroke: 'currentColor',
16
+ strokeWidth: 2,
17
+ strokeLinecap: 'round' as const,
18
+ strokeLinejoin: 'round' as const,
19
+ ...rest,
20
+ }
21
+ }
22
+
23
+ // --- Navigation ---
24
+ export const IconArrowLeft: React.FC<IconProps> = (props) => (
25
+ <svg {...defaultProps(props)}>
26
+ <line x1="19" y1="12" x2="5" y2="12" />
27
+ <polyline points="12 19 5 12 12 5" />
28
+ </svg>
29
+ )
30
+
31
+ export const IconArrowRight: React.FC<IconProps> = (props) => (
32
+ <svg {...defaultProps(props)}>
33
+ <line x1="5" y1="12" x2="19" y2="12" />
34
+ <polyline points="12 5 19 12 12 19" />
35
+ </svg>
36
+ )
37
+
38
+ // --- Actions ---
39
+ export const IconPlus: React.FC<IconProps> = (props) => (
40
+ <svg {...defaultProps(props)}>
41
+ <line x1="12" y1="5" x2="12" y2="19" />
42
+ <line x1="5" y1="12" x2="19" y2="12" />
43
+ </svg>
44
+ )
45
+
46
+ export const IconClose: React.FC<IconProps> = (props) => (
47
+ <svg {...defaultProps(props)}>
48
+ <line x1="18" y1="6" x2="6" y2="18" />
49
+ <line x1="6" y1="6" x2="18" y2="18" />
50
+ </svg>
51
+ )
52
+
53
+ export const IconCheck: React.FC<IconProps> = (props) => (
54
+ <svg {...defaultProps(props)}>
55
+ <polyline points="20 6 9 17 4 12" />
56
+ </svg>
57
+ )
58
+
59
+ export const IconDelete: React.FC<IconProps> = (props) => (
60
+ <svg {...defaultProps(props)}>
61
+ <polyline points="3 6 5 6 21 6" />
62
+ <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
63
+ </svg>
64
+ )
65
+
66
+ export const IconSave: React.FC<IconProps> = (props) => (
67
+ <svg {...defaultProps(props)}>
68
+ <path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" />
69
+ <polyline points="17 21 17 13 7 13 7 21" />
70
+ <polyline points="7 3 7 8 15 8" />
71
+ </svg>
72
+ )
73
+
74
+ export const IconExport: React.FC<IconProps> = (props) => (
75
+ <svg {...defaultProps(props)}>
76
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
77
+ <polyline points="7 10 12 15 17 10" />
78
+ <line x1="12" y1="15" x2="12" y2="3" />
79
+ </svg>
80
+ )
81
+
82
+ export const IconClear: React.FC<IconProps> = (props) => (
83
+ <svg {...defaultProps(props)}>
84
+ <circle cx="12" cy="12" r="10" />
85
+ <line x1="4.93" y1="4.93" x2="19.07" y2="19.07" />
86
+ </svg>
87
+ )
88
+
89
+ export const IconReload: React.FC<IconProps> = (props) => (
90
+ <svg {...defaultProps(props)}>
91
+ <polyline points="23 4 23 10 17 10" />
92
+ <path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10" />
93
+ </svg>
94
+ )
95
+
96
+ export const IconUndo: React.FC<IconProps> = (props) => (
97
+ <svg {...defaultProps(props)}>
98
+ <polyline points="1 4 1 10 7 10" />
99
+ <path d="M3.51 15a9 9 0 1 0 2.12-9.36L1 10" />
100
+ </svg>
101
+ )
102
+
103
+ export const IconSend: React.FC<IconProps> = (props) => (
104
+ <svg {...defaultProps(props)}>
105
+ <line x1="22" y1="2" x2="11" y2="13" />
106
+ <polygon points="22 2 15 22 11 13 2 9 22 2" />
107
+ </svg>
108
+ )
109
+
110
+ // --- Media Controls ---
111
+ export const IconPlay: React.FC<IconProps> = (props) => (
112
+ <svg {...defaultProps(props)}>
113
+ <polygon points="5 3 19 12 5 21 5 3" fill="currentColor" stroke="none" />
114
+ </svg>
115
+ )
116
+
117
+ export const IconPause: React.FC<IconProps> = (props) => (
118
+ <svg {...defaultProps(props)}>
119
+ <rect x="6" y="4" width="4" height="16" fill="currentColor" stroke="none" />
120
+ <rect x="14" y="4" width="4" height="16" fill="currentColor" stroke="none" />
121
+ </svg>
122
+ )
123
+
124
+ export const IconStop: React.FC<IconProps> = (props) => (
125
+ <svg {...defaultProps(props)}>
126
+ <rect x="6" y="6" width="12" height="12" rx="1" fill="currentColor" stroke="none" />
127
+ </svg>
128
+ )
129
+
130
+ // --- Objects ---
131
+ export const IconSettings: React.FC<IconProps> = (props) => (
132
+ <svg {...defaultProps(props)}>
133
+ <circle cx="12" cy="12" r="3" />
134
+ <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" />
135
+ </svg>
136
+ )
137
+
138
+ export const IconGlobe: React.FC<IconProps> = (props) => (
139
+ <svg {...defaultProps(props)}>
140
+ <circle cx="12" cy="12" r="10" />
141
+ <line x1="2" y1="12" x2="22" y2="12" />
142
+ <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" />
143
+ </svg>
144
+ )
145
+
146
+ export const IconRobot: React.FC<IconProps> = (props) => (
147
+ <svg {...defaultProps(props)}>
148
+ <rect x="3" y="8" width="18" height="12" rx="2" />
149
+ <circle cx="9" cy="14" r="1.5" fill="currentColor" stroke="none" />
150
+ <circle cx="15" cy="14" r="1.5" fill="currentColor" stroke="none" />
151
+ <line x1="12" y1="4" x2="12" y2="8" />
152
+ <circle cx="12" cy="3" r="1" fill="currentColor" stroke="none" />
153
+ </svg>
154
+ )
155
+
156
+ export const IconFileText: React.FC<IconProps> = (props) => (
157
+ <svg {...defaultProps(props)}>
158
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
159
+ <polyline points="14 2 14 8 20 8" />
160
+ <line x1="16" y1="13" x2="8" y2="13" />
161
+ <line x1="16" y1="17" x2="8" y2="17" />
162
+ <polyline points="10 9 9 9 8 9" />
163
+ </svg>
164
+ )
165
+
166
+ export const IconMessage: React.FC<IconProps> = (props) => (
167
+ <svg {...defaultProps(props)}>
168
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
169
+ </svg>
170
+ )
171
+
172
+ export const IconExperiment: React.FC<IconProps> = (props) => (
173
+ <svg {...defaultProps(props)}>
174
+ <path d="M9 3h6v4l4 8H5l4-8V3z" />
175
+ <line x1="9" y1="3" x2="15" y2="3" />
176
+ <path d="M5 15h14v2a4 4 0 0 1-4 4H9a4 4 0 0 1-4-4v-2z" />
177
+ </svg>
178
+ )
179
+
180
+ export const IconSwap: React.FC<IconProps> = (props) => (
181
+ <svg {...defaultProps(props)}>
182
+ <polyline points="16 3 21 3 21 8" />
183
+ <line x1="4" y1="20" x2="21" y2="3" />
184
+ <polyline points="21 16 21 21 16 21" />
185
+ <line x1="15" y1="15" x2="21" y2="21" />
186
+ <line x1="4" y1="4" x2="9" y2="9" />
187
+ </svg>
188
+ )
189
+
190
+ export const IconCloudDownload: React.FC<IconProps> = (props) => (
191
+ <svg {...defaultProps(props)}>
192
+ <polyline points="8 17 12 21 16 17" />
193
+ <line x1="12" y1="12" x2="12" y2="21" />
194
+ <path d="M20.88 18.09A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.29" />
195
+ </svg>
196
+ )
197
+
198
+ export const IconCode: React.FC<IconProps> = (props) => (
199
+ <svg {...defaultProps(props)}>
200
+ <polyline points="16 18 22 12 16 6" />
201
+ <polyline points="8 6 2 12 8 18" />
202
+ </svg>
203
+ )
204
+
205
+ export const IconDatabase: React.FC<IconProps> = (props) => (
206
+ <svg {...defaultProps(props)}>
207
+ <ellipse cx="12" cy="5" rx="9" ry="3" />
208
+ <path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" />
209
+ <path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" />
210
+ </svg>
211
+ )
212
+
213
+ export const IconShield: React.FC<IconProps> = (props) => (
214
+ <svg {...defaultProps(props)}>
215
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
216
+ </svg>
217
+ )
218
+
219
+ export const IconApp: React.FC<IconProps> = (props) => (
220
+ <svg {...defaultProps(props)}>
221
+ <rect x="3" y="3" width="7" height="7" rx="1" />
222
+ <rect x="14" y="3" width="7" height="7" rx="1" />
223
+ <rect x="14" y="14" width="7" height="7" rx="1" />
224
+ <rect x="3" y="14" width="7" height="7" rx="1" />
225
+ </svg>
226
+ )
227
+
228
+ export const IconBolt: React.FC<IconProps> = (props) => (
229
+ <svg {...defaultProps(props)}>
230
+ <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" fill="currentColor" stroke="none" />
231
+ </svg>
232
+ )
233
+
234
+ export const IconApi: React.FC<IconProps> = (props) => (
235
+ <svg {...defaultProps(props)}>
236
+ <path d="M10 20l4-16" />
237
+ <path d="M6 8l-4 4 4 4" />
238
+ <path d="M18 8l4 4-4 4" />
239
+ </svg>
240
+ )
241
+
242
+ export const IconEdit: React.FC<IconProps> = (props) => (
243
+ <svg {...defaultProps(props)}>
244
+ <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
245
+ <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
246
+ </svg>
247
+ )
248
+
249
+ export const IconSync: React.FC<IconProps> = (props) => (
250
+ <svg {...defaultProps(props)}>
251
+ <polyline points="23 4 23 10 17 10" />
252
+ <polyline points="1 20 1 14 7 14" />
253
+ <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" />
254
+ </svg>
255
+ )
256
+
257
+ export const IconCheckCircle: React.FC<IconProps> = (props) => (
258
+ <svg {...defaultProps(props)}>
259
+ <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
260
+ <polyline points="22 4 12 14.01 9 11.01" />
261
+ </svg>
262
+ )
263
+
264
+ export const IconCloseCircle: React.FC<IconProps> = (props) => (
265
+ <svg {...defaultProps(props)}>
266
+ <circle cx="12" cy="12" r="10" />
267
+ <line x1="15" y1="9" x2="9" y2="15" />
268
+ <line x1="9" y1="9" x2="15" y2="15" />
269
+ </svg>
270
+ )
271
+
272
+ export const IconWifi: React.FC<IconProps> = (props) => (
273
+ <svg {...defaultProps(props)}>
274
+ <path d="M5 12.55a11 11 0 0 1 14.08 0" />
275
+ <path d="M1.42 9a16 16 0 0 1 21.16 0" />
276
+ <path d="M8.53 16.11a6 6 0 0 1 6.95 0" />
277
+ <line x1="12" y1="20" x2="12.01" y2="20" />
278
+ </svg>
279
+ )
280
+
281
+ export const IconLoading: React.FC<IconProps> = (props) => {
282
+ const { size = '1em', ...rest } = props
283
+ return (
284
+ <svg
285
+ width={size}
286
+ height={size}
287
+ viewBox="0 0 24 24"
288
+ fill="none"
289
+ stroke="currentColor"
290
+ strokeWidth="2"
291
+ strokeLinecap="round"
292
+ {...rest}
293
+ >
294
+ <path d="M21 12a9 9 0 1 1-6.219-8.56" />
295
+ <animateTransform
296
+ attributeName="transform"
297
+ type="rotate"
298
+ from="0 12 12"
299
+ to="360 12 12"
300
+ dur="0.6s"
301
+ repeatCount="indefinite"
302
+ />
303
+ </svg>
304
+ )
305
+ }
306
+
307
+ // --- Window Controls ---
308
+ export const IconMinimize: React.FC<IconProps> = (props) => (
309
+ <svg {...defaultProps(props)}>
310
+ <line x1="5" y1="12" x2="19" y2="12" />
311
+ </svg>
312
+ )
313
+
314
+ export const IconMaximize: React.FC<IconProps> = (props) => (
315
+ <svg {...defaultProps(props)}>
316
+ <rect x="5" y="5" width="14" height="14" rx="1" />
317
+ </svg>
318
+ )
319
+
320
+ export const IconSun: React.FC<IconProps> = (props) => (
321
+ <svg {...defaultProps(props)}>
322
+ <circle cx="12" cy="12" r="5" />
323
+ <line x1="12" y1="1" x2="12" y2="3" />
324
+ <line x1="12" y1="21" x2="12" y2="23" />
325
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
326
+ <line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
327
+ <line x1="1" y1="12" x2="3" y2="12" />
328
+ <line x1="21" y1="12" x2="23" y2="12" />
329
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
330
+ <line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
331
+ </svg>
332
+ )
333
+
334
+ export const IconMoon: React.FC<IconProps> = (props) => (
335
+ <svg {...defaultProps(props)}>
336
+ <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
337
+ </svg>
338
+ )
339
+
340
+ export const IconGitHub: React.FC<IconProps> = (props) => (
341
+ <svg {...defaultProps(props)} viewBox="0 0 24 24" fill="currentColor" stroke="none">
342
+ <path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z" />
343
+ </svg>
344
+ )
345
+
346
+ // IconClose is already defined above and works for window close too
@@ -0,0 +1,103 @@
1
+ .input {
2
+ display: flex;
3
+ align-items: center;
4
+ width: 100%;
5
+ height: 28px;
6
+ padding: 0 var(--space-lg);
7
+ font-family: var(--font-sans);
8
+ font-size: var(--font-size-base);
9
+ color: var(--text-primary);
10
+ background: var(--color-surface);
11
+ border: 1px solid var(--color-border);
12
+ border-radius: var(--radius-input);
13
+ outline: none;
14
+ transition: border-color var(--transition-normal);
15
+ }
16
+
17
+ .input::placeholder {
18
+ color: var(--text-muted);
19
+ }
20
+
21
+ .input:hover {
22
+ border-color: var(--color-border-hover);
23
+ }
24
+
25
+ .input:focus {
26
+ border-color: var(--color-accent);
27
+ box-shadow: 0 0 0 2px var(--color-focus-ring);
28
+ }
29
+
30
+ .input:disabled {
31
+ opacity: 0.4;
32
+ cursor: not-allowed;
33
+ }
34
+
35
+ /* Textarea */
36
+ .textarea {
37
+ composes: input;
38
+ height: auto;
39
+ min-height: 60px;
40
+ padding: var(--space-md) var(--space-lg);
41
+ resize: vertical;
42
+ line-height: var(--line-height-normal);
43
+ }
44
+
45
+ /* Password wrapper */
46
+ .passwordWrapper {
47
+ position: relative;
48
+ width: 100%;
49
+ }
50
+
51
+ .passwordWrapper .input {
52
+ padding-right: 36px;
53
+ }
54
+
55
+ .passwordToggle {
56
+ position: absolute;
57
+ right: var(--space-md);
58
+ top: 50%;
59
+ transform: translateY(-50%);
60
+ background: none;
61
+ border: none;
62
+ color: var(--text-muted);
63
+ cursor: pointer;
64
+ padding: 2px;
65
+ display: flex;
66
+ align-items: center;
67
+ }
68
+
69
+ .passwordToggle:hover {
70
+ color: var(--text-secondary);
71
+ }
72
+
73
+ /* Input with suffix */
74
+ .inputWrapper {
75
+ position: relative;
76
+ display: flex;
77
+ width: 100%;
78
+ }
79
+
80
+ .inputWrapper .input {
81
+ flex: 1;
82
+ }
83
+
84
+ .suffix {
85
+ position: absolute;
86
+ right: var(--space-xs);
87
+ top: 50%;
88
+ transform: translateY(-50%);
89
+ display: flex;
90
+ align-items: center;
91
+ }
92
+
93
+ /* Sizes */
94
+ .sm {
95
+ height: 24px;
96
+ font-size: var(--font-size-sm);
97
+ padding: 0 var(--space-md);
98
+ }
99
+
100
+ .lg {
101
+ height: 32px;
102
+ font-size: var(--font-size-md);
103
+ }
@@ -0,0 +1,94 @@
1
+ import React, { useState, forwardRef } from 'react'
2
+ import styles from './Input.module.css'
3
+
4
+ /* ---- Text Input ---- */
5
+ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
6
+ inputSize?: 'sm' | 'md' | 'lg'
7
+ suffix?: React.ReactNode
8
+ }
9
+
10
+ export const Input = forwardRef<HTMLInputElement, InputProps>(
11
+ ({ inputSize = 'md', suffix, className, ...rest }, ref) => {
12
+ const cls = [styles.input, inputSize !== 'md' && styles[inputSize], className]
13
+ .filter(Boolean)
14
+ .join(' ')
15
+
16
+ if (suffix) {
17
+ return (
18
+ <div className={styles.inputWrapper}>
19
+ <input ref={ref} className={cls} {...rest} />
20
+ <span className={styles.suffix}>{suffix}</span>
21
+ </div>
22
+ )
23
+ }
24
+
25
+ return <input ref={ref} className={cls} {...rest} />
26
+ }
27
+ )
28
+ Input.displayName = 'Input'
29
+
30
+ /* ---- Textarea ---- */
31
+ export interface TextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
32
+ autoSize?: boolean | { minRows?: number; maxRows?: number }
33
+ }
34
+
35
+ export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
36
+ ({ autoSize, className, style, ...rest }, ref) => {
37
+ const cls = [styles.textarea, className].filter(Boolean).join(' ')
38
+
39
+ const handleInput: React.FormEventHandler<HTMLTextAreaElement> = (e) => {
40
+ if (autoSize) {
41
+ const el = e.currentTarget
42
+ el.style.height = 'auto'
43
+ const minRows = typeof autoSize === 'object' ? autoSize.minRows ?? 2 : 2
44
+ const maxRows = typeof autoSize === 'object' ? autoSize.maxRows ?? 10 : 10
45
+ const lineHeight = 20
46
+ const minH = minRows * lineHeight
47
+ const maxH = maxRows * lineHeight
48
+ el.style.height = `${Math.min(Math.max(el.scrollHeight, minH), maxH)}px`
49
+ }
50
+ }
51
+
52
+ return <textarea ref={ref} className={cls} onInput={handleInput} style={style} {...rest} />
53
+ }
54
+ )
55
+ TextArea.displayName = 'TextArea'
56
+
57
+ /* ---- Password Input ---- */
58
+ export interface PasswordInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
59
+ inputSize?: 'sm' | 'md' | 'lg'
60
+ }
61
+
62
+ export const PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(
63
+ ({ inputSize = 'md', className, ...rest }, ref) => {
64
+ const [visible, setVisible] = useState(false)
65
+ const cls = [styles.input, inputSize !== 'md' && styles[inputSize], className]
66
+ .filter(Boolean)
67
+ .join(' ')
68
+
69
+ return (
70
+ <div className={styles.passwordWrapper}>
71
+ <input ref={ref} type={visible ? 'text' : 'password'} className={cls} {...rest} />
72
+ <button
73
+ type="button"
74
+ className={styles.passwordToggle}
75
+ onClick={() => setVisible(!visible)}
76
+ tabIndex={-1}
77
+ >
78
+ {visible ? (
79
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
80
+ <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" />
81
+ <line x1="1" y1="1" x2="23" y2="23" />
82
+ </svg>
83
+ ) : (
84
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
85
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
86
+ <circle cx="12" cy="12" r="3" />
87
+ </svg>
88
+ )}
89
+ </button>
90
+ </div>
91
+ )
92
+ }
93
+ )
94
+ PasswordInput.displayName = 'PasswordInput'
@@ -0,0 +1,68 @@
1
+ .wrapper {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ height: 28px;
5
+ border: 1px solid var(--color-border);
6
+ border-radius: var(--radius-input);
7
+ background: var(--color-surface);
8
+ overflow: hidden;
9
+ }
10
+
11
+ .input {
12
+ width: 60px;
13
+ height: 100%;
14
+ padding: 0 var(--space-md);
15
+ font-family: var(--font-sans);
16
+ font-size: var(--font-size-base);
17
+ color: var(--text-primary);
18
+ background: transparent;
19
+ border: none;
20
+ outline: none;
21
+ text-align: center;
22
+ -moz-appearance: textfield;
23
+ }
24
+
25
+ .input::-webkit-outer-spin-button,
26
+ .input::-webkit-inner-spin-button {
27
+ -webkit-appearance: none;
28
+ margin: 0;
29
+ }
30
+
31
+ .controls {
32
+ display: flex;
33
+ flex-direction: column;
34
+ border-left: 1px solid var(--color-border);
35
+ }
36
+
37
+ .stepBtn {
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: center;
41
+ width: 20px;
42
+ height: 14px;
43
+ background: transparent;
44
+ border: none;
45
+ color: var(--text-muted);
46
+ cursor: pointer;
47
+ padding: 0;
48
+ font-size: var(--font-size-2xs);
49
+ }
50
+
51
+ .stepBtn:hover {
52
+ background: var(--color-hover);
53
+ color: var(--text-secondary);
54
+ }
55
+
56
+ .stepBtn + .stepBtn {
57
+ border-top: 1px solid var(--color-border);
58
+ }
59
+
60
+ .wrapper:focus-within {
61
+ border-color: var(--color-accent);
62
+ box-shadow: 0 0 0 2px var(--color-focus-ring);
63
+ }
64
+
65
+ .wrapper.disabled {
66
+ opacity: 0.4;
67
+ cursor: not-allowed;
68
+ }