npcts 0.1.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.
Files changed (285) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +139 -0
  3. package/dist/adapters/base.d.ts +13 -0
  4. package/dist/adapters/base.js +1 -0
  5. package/dist/adapters/electron/bridge.d.ts +4 -0
  6. package/dist/adapters/electron/bridge.js +88 -0
  7. package/dist/adapters/index.d.ts +2 -0
  8. package/dist/adapters/index.js +3 -0
  9. package/dist/core/browser.d.ts +25 -0
  10. package/dist/core/browser.js +1 -0
  11. package/dist/core/chat.d.ts +41 -0
  12. package/dist/core/chat.js +1 -0
  13. package/dist/core/database.d.ts +56 -0
  14. package/dist/core/database.js +50 -0
  15. package/dist/core/files.d.ts +24 -0
  16. package/dist/core/files.js +15 -0
  17. package/dist/core/index.d.ts +9 -0
  18. package/dist/core/index.js +10 -0
  19. package/dist/core/jobs.d.ts +20 -0
  20. package/dist/core/jobs.js +1 -0
  21. package/dist/core/layout.d.ts +30 -0
  22. package/dist/core/layout.js +41 -0
  23. package/dist/core/stream.d.ts +10 -0
  24. package/dist/core/stream.js +1 -0
  25. package/dist/core/types.d.ts +23 -0
  26. package/dist/core/types.js +1 -0
  27. package/dist/core/utils.d.ts +19 -0
  28. package/dist/core/utils.js +19 -0
  29. package/dist/index.d.ts +25 -0
  30. package/dist/index.js +29 -0
  31. package/dist/ui/chat/components/ChatHeaderBar.d.ts +13 -0
  32. package/dist/ui/chat/components/ChatHeaderBar.js +32 -0
  33. package/dist/ui/chat/components/ChatInterface.d.ts +10 -0
  34. package/dist/ui/chat/components/ChatInterface.js +19 -0
  35. package/dist/ui/chat/components/ChatMessage.d.ts +7 -0
  36. package/dist/ui/chat/components/ChatMessage.js +10 -0
  37. package/dist/ui/chat/components/ChatPane.d.ts +20 -0
  38. package/dist/ui/chat/components/ChatPane.js +20 -0
  39. package/dist/ui/chat/components/ChatView.d.ts +10 -0
  40. package/dist/ui/chat/components/ChatView.js +36 -0
  41. package/dist/ui/chat/components/ConversationList.d.ts +28 -0
  42. package/dist/ui/chat/components/ConversationList.js +113 -0
  43. package/dist/ui/chat/components/InPaneSearchBar.d.ts +12 -0
  44. package/dist/ui/chat/components/InPaneSearchBar.js +44 -0
  45. package/dist/ui/chat/components/InputArea.d.ts +7 -0
  46. package/dist/ui/chat/components/InputArea.js +46 -0
  47. package/dist/ui/chat/components/MessageAttachments.d.ts +5 -0
  48. package/dist/ui/chat/components/MessageAttachments.js +6 -0
  49. package/dist/ui/chat/components/MessageItem.d.ts +28 -0
  50. package/dist/ui/chat/components/MessageItem.js +43 -0
  51. package/dist/ui/chat/components/PredictiveTextOverlay.d.ts +10 -0
  52. package/dist/ui/chat/components/PredictiveTextOverlay.js +75 -0
  53. package/dist/ui/chat/context/ChatContext.d.ts +33 -0
  54. package/dist/ui/chat/context/ChatContext.js +157 -0
  55. package/dist/ui/chat/hooks/useAutoScroll.d.ts +1 -0
  56. package/dist/ui/chat/hooks/useAutoScroll.js +11 -0
  57. package/dist/ui/chat/index.d.ts +7 -0
  58. package/dist/ui/chat/index.js +7 -0
  59. package/dist/ui/dashboard/ChartWidget.d.ts +18 -0
  60. package/dist/ui/dashboard/ChartWidget.js +98 -0
  61. package/dist/ui/dashboard/QueryWidget.d.ts +29 -0
  62. package/dist/ui/dashboard/QueryWidget.js +117 -0
  63. package/dist/ui/dashboard/TableWidget.d.ts +14 -0
  64. package/dist/ui/dashboard/TableWidget.js +117 -0
  65. package/dist/ui/dashboard/Widget.d.ts +40 -0
  66. package/dist/ui/dashboard/Widget.js +26 -0
  67. package/dist/ui/dashboard/WidgetBuilder.d.ts +47 -0
  68. package/dist/ui/dashboard/WidgetBuilder.js +286 -0
  69. package/dist/ui/dashboard/WidgetGrid.d.ts +19 -0
  70. package/dist/ui/dashboard/WidgetGrid.js +11 -0
  71. package/dist/ui/dashboard/index.d.ts +8 -0
  72. package/dist/ui/dashboard/index.js +4 -0
  73. package/dist/ui/dialogs/BrowserUrlDialog.d.ts +8 -0
  74. package/dist/ui/dialogs/BrowserUrlDialog.js +203 -0
  75. package/dist/ui/dialogs/index.d.ts +1 -0
  76. package/dist/ui/dialogs/index.js +1 -0
  77. package/dist/ui/editors/ImageEditor.d.ts +49 -0
  78. package/dist/ui/editors/ImageEditor.js +264 -0
  79. package/dist/ui/editors/index.d.ts +2 -0
  80. package/dist/ui/editors/index.js +1 -0
  81. package/dist/ui/execution/ExecutionFilters.d.ts +11 -0
  82. package/dist/ui/execution/ExecutionFilters.js +27 -0
  83. package/dist/ui/execution/ExecutionHistoryList.d.ts +19 -0
  84. package/dist/ui/execution/ExecutionHistoryList.js +35 -0
  85. package/dist/ui/execution/index.d.ts +3 -0
  86. package/dist/ui/execution/index.js +2 -0
  87. package/dist/ui/files/components/FileTree.d.ts +18 -0
  88. package/dist/ui/files/components/FileTree.js +61 -0
  89. package/dist/ui/files/components/Sidebar.d.ts +18 -0
  90. package/dist/ui/files/components/Sidebar.js +67 -0
  91. package/dist/ui/files/components/index.d.ts +2 -0
  92. package/dist/ui/files/components/index.js +2 -0
  93. package/dist/ui/files/context/FileSystemContext.d.ts +23 -0
  94. package/dist/ui/files/context/FileSystemContext.js +65 -0
  95. package/dist/ui/files/context/index.d.ts +1 -0
  96. package/dist/ui/files/context/index.js +1 -0
  97. package/dist/ui/files/index.d.ts +2 -0
  98. package/dist/ui/files/index.js +2 -0
  99. package/dist/ui/hooks/index.d.ts +4 -0
  100. package/dist/ui/hooks/index.js +3 -0
  101. package/dist/ui/hooks/useDebounce.d.ts +8 -0
  102. package/dist/ui/hooks/useDebounce.js +18 -0
  103. package/dist/ui/hooks/usePaneTracking.d.ts +15 -0
  104. package/dist/ui/hooks/usePaneTracking.js +20 -0
  105. package/dist/ui/hooks/useQuery.d.ts +25 -0
  106. package/dist/ui/hooks/useQuery.js +71 -0
  107. package/dist/ui/index.d.ts +19 -0
  108. package/dist/ui/index.js +20 -0
  109. package/dist/ui/jinx/JinxEditor.d.ts +20 -0
  110. package/dist/ui/jinx/JinxEditor.js +34 -0
  111. package/dist/ui/jinx/JinxTree.d.ts +14 -0
  112. package/dist/ui/jinx/JinxTree.js +65 -0
  113. package/dist/ui/jinx/index.d.ts +3 -0
  114. package/dist/ui/jinx/index.js +2 -0
  115. package/dist/ui/knowledge-graph/KGControls.d.ts +12 -0
  116. package/dist/ui/knowledge-graph/KGControls.js +21 -0
  117. package/dist/ui/knowledge-graph/KGStats.d.ts +13 -0
  118. package/dist/ui/knowledge-graph/KGStats.js +18 -0
  119. package/dist/ui/knowledge-graph/KnowledgeGraphViewer.d.ts +22 -0
  120. package/dist/ui/knowledge-graph/KnowledgeGraphViewer.js +16 -0
  121. package/dist/ui/knowledge-graph/index.d.ts +4 -0
  122. package/dist/ui/knowledge-graph/index.js +3 -0
  123. package/dist/ui/layout/components/AppShell.d.ts +8 -0
  124. package/dist/ui/layout/components/AppShell.js +19 -0
  125. package/dist/ui/layout/components/ContentPaneContainer.d.ts +8 -0
  126. package/dist/ui/layout/components/ContentPaneContainer.js +95 -0
  127. package/dist/ui/layout/components/LayoutNode.d.ts +8 -0
  128. package/dist/ui/layout/components/LayoutNode.js +12 -0
  129. package/dist/ui/layout/components/PaneHeader.d.ts +17 -0
  130. package/dist/ui/layout/components/PaneHeader.js +40 -0
  131. package/dist/ui/layout/components/SplitView.d.ts +8 -0
  132. package/dist/ui/layout/components/SplitView.js +51 -0
  133. package/dist/ui/layout/components/Studio.d.ts +7 -0
  134. package/dist/ui/layout/components/Studio.js +12 -0
  135. package/dist/ui/layout/components/contextMenus/BrowserContextMenu.d.ts +13 -0
  136. package/dist/ui/layout/components/contextMenus/BrowserContextMenu.js +23 -0
  137. package/dist/ui/layout/components/contextMenus/EditorContextMenu.d.ts +15 -0
  138. package/dist/ui/layout/components/contextMenus/EditorContextMenu.js +32 -0
  139. package/dist/ui/layout/components/contextMenus/FileContextMenu.d.ts +15 -0
  140. package/dist/ui/layout/components/contextMenus/FileContextMenu.js +33 -0
  141. package/dist/ui/layout/components/contextMenus/PdfContextMenu.d.ts +13 -0
  142. package/dist/ui/layout/components/contextMenus/PdfContextMenu.js +23 -0
  143. package/dist/ui/layout/components/contextMenus/index.d.ts +4 -0
  144. package/dist/ui/layout/components/contextMenus/index.js +4 -0
  145. package/dist/ui/layout/components/index.d.ts +8 -0
  146. package/dist/ui/layout/components/index.js +8 -0
  147. package/dist/ui/layout/components/modals/AIEditModal.d.ts +9 -0
  148. package/dist/ui/layout/components/modals/AIEditModal.js +33 -0
  149. package/dist/ui/layout/components/modals/MemoryApprovalModal.d.ts +15 -0
  150. package/dist/ui/layout/components/modals/MemoryApprovalModal.js +23 -0
  151. package/dist/ui/layout/components/modals/PromptModal.d.ts +11 -0
  152. package/dist/ui/layout/components/modals/PromptModal.js +20 -0
  153. package/dist/ui/layout/components/modals/ResendModal.d.ts +16 -0
  154. package/dist/ui/layout/components/modals/ResendModal.js +22 -0
  155. package/dist/ui/layout/components/modals/index.d.ts +4 -0
  156. package/dist/ui/layout/components/modals/index.js +4 -0
  157. package/dist/ui/layout/context/LayoutContext.d.ts +32 -0
  158. package/dist/ui/layout/context/LayoutContext.js +144 -0
  159. package/dist/ui/layout/index.d.ts +2 -0
  160. package/dist/ui/layout/index.js +2 -0
  161. package/dist/ui/markdown/Markdown.d.ts +4 -0
  162. package/dist/ui/markdown/Markdown.js +4 -0
  163. package/dist/ui/memory/MemoryFilters.d.ts +12 -0
  164. package/dist/ui/memory/MemoryFilters.js +23 -0
  165. package/dist/ui/memory/MemoryList.d.ts +19 -0
  166. package/dist/ui/memory/MemoryList.js +36 -0
  167. package/dist/ui/memory/index.d.ts +3 -0
  168. package/dist/ui/memory/index.js +2 -0
  169. package/dist/ui/models/ModelCard.d.ts +16 -0
  170. package/dist/ui/models/ModelCard.js +30 -0
  171. package/dist/ui/models/ModelSelector.d.ts +13 -0
  172. package/dist/ui/models/ModelSelector.js +6 -0
  173. package/dist/ui/models/index.d.ts +3 -0
  174. package/dist/ui/models/index.js +2 -0
  175. package/dist/ui/npc/McpServerMenu.d.ts +15 -0
  176. package/dist/ui/npc/McpServerMenu.js +48 -0
  177. package/dist/ui/npc/NPCEditor.d.ts +21 -0
  178. package/dist/ui/npc/NPCEditor.js +17 -0
  179. package/dist/ui/npc/NPCList.d.ts +19 -0
  180. package/dist/ui/npc/NPCList.js +28 -0
  181. package/dist/ui/npc/index.d.ts +3 -0
  182. package/dist/ui/npc/index.js +2 -0
  183. package/dist/ui/photo/GalleryGrid.d.ts +25 -0
  184. package/dist/ui/photo/GalleryGrid.js +46 -0
  185. package/dist/ui/photo/ImageAdjustmentSliders.d.ts +37 -0
  186. package/dist/ui/photo/ImageAdjustmentSliders.js +56 -0
  187. package/dist/ui/photo/ImageLabelingCanvas.d.ts +47 -0
  188. package/dist/ui/photo/ImageLabelingCanvas.js +174 -0
  189. package/dist/ui/photo/ImageSourceTabs.d.ts +28 -0
  190. package/dist/ui/photo/ImageSourceTabs.js +46 -0
  191. package/dist/ui/photo/LayerPanel.d.ts +87 -0
  192. package/dist/ui/photo/LayerPanel.js +70 -0
  193. package/dist/ui/photo/Lightbox.d.ts +12 -0
  194. package/dist/ui/photo/Lightbox.js +90 -0
  195. package/dist/ui/photo/index.d.ts +6 -0
  196. package/dist/ui/photo/index.js +7 -0
  197. package/dist/ui/primitives/AutosizeTextarea.d.ts +8 -0
  198. package/dist/ui/primitives/AutosizeTextarea.js +17 -0
  199. package/dist/ui/primitives/Button.d.ts +7 -0
  200. package/dist/ui/primitives/Button.js +17 -0
  201. package/dist/ui/primitives/Card.d.ts +12 -0
  202. package/dist/ui/primitives/Card.js +8 -0
  203. package/dist/ui/primitives/Chart.d.ts +34 -0
  204. package/dist/ui/primitives/Chart.js +140 -0
  205. package/dist/ui/primitives/ContextMenu.d.ts +17 -0
  206. package/dist/ui/primitives/ContextMenu.js +33 -0
  207. package/dist/ui/primitives/DataTable.d.ts +13 -0
  208. package/dist/ui/primitives/DataTable.js +13 -0
  209. package/dist/ui/primitives/FileUpload.d.ts +10 -0
  210. package/dist/ui/primitives/FileUpload.js +24 -0
  211. package/dist/ui/primitives/ImageGrid.d.ts +21 -0
  212. package/dist/ui/primitives/ImageGrid.js +29 -0
  213. package/dist/ui/primitives/Input.d.ts +7 -0
  214. package/dist/ui/primitives/Input.js +10 -0
  215. package/dist/ui/primitives/Lightbox.d.ts +12 -0
  216. package/dist/ui/primitives/Lightbox.js +36 -0
  217. package/dist/ui/primitives/Modal.d.ts +10 -0
  218. package/dist/ui/primitives/Modal.js +33 -0
  219. package/dist/ui/primitives/RangeSlider.d.ts +13 -0
  220. package/dist/ui/primitives/RangeSlider.js +6 -0
  221. package/dist/ui/primitives/Select.d.ts +11 -0
  222. package/dist/ui/primitives/Select.js +10 -0
  223. package/dist/ui/primitives/Slider.d.ts +13 -0
  224. package/dist/ui/primitives/Slider.js +8 -0
  225. package/dist/ui/primitives/SortableList.d.ts +9 -0
  226. package/dist/ui/primitives/SortableList.js +19 -0
  227. package/dist/ui/primitives/Spinner.d.ts +2 -0
  228. package/dist/ui/primitives/Spinner.js +2 -0
  229. package/dist/ui/primitives/StarRating.d.ts +10 -0
  230. package/dist/ui/primitives/StarRating.js +10 -0
  231. package/dist/ui/primitives/Tabs.d.ts +15 -0
  232. package/dist/ui/primitives/Tabs.js +11 -0
  233. package/dist/ui/primitives/TagInput.d.ts +10 -0
  234. package/dist/ui/primitives/TagInput.js +25 -0
  235. package/dist/ui/primitives/index.d.ts +20 -0
  236. package/dist/ui/primitives/index.js +19 -0
  237. package/dist/ui/specialized/DiskUsageAnalyzer.d.ts +12 -0
  238. package/dist/ui/specialized/DiskUsageAnalyzer.js +38 -0
  239. package/dist/ui/specialized/OllamaModelManager.d.ts +2 -0
  240. package/dist/ui/specialized/OllamaModelManager.js +48 -0
  241. package/dist/ui/specialized/RichTextEditor.d.ts +8 -0
  242. package/dist/ui/specialized/RichTextEditor.js +64 -0
  243. package/dist/ui/specialized/SlideCanvas.d.ts +24 -0
  244. package/dist/ui/specialized/SlideCanvas.js +31 -0
  245. package/dist/ui/specialized/SpreadsheetGrid.d.ts +18 -0
  246. package/dist/ui/specialized/SpreadsheetGrid.js +28 -0
  247. package/dist/ui/specialized/StepEditor.d.ts +12 -0
  248. package/dist/ui/specialized/StepEditor.js +22 -0
  249. package/dist/ui/specialized/TerminalEmbed.d.ts +13 -0
  250. package/dist/ui/specialized/TerminalEmbed.js +50 -0
  251. package/dist/ui/specialized/index.d.ts +7 -0
  252. package/dist/ui/specialized/index.js +7 -0
  253. package/dist/ui/sql/SQLQueryEditor.d.ts +9 -0
  254. package/dist/ui/sql/SQLQueryEditor.js +10 -0
  255. package/dist/ui/sql/SQLResultsTable.d.ts +6 -0
  256. package/dist/ui/sql/SQLResultsTable.js +12 -0
  257. package/dist/ui/sql/SQLSchemaViewer.d.ts +14 -0
  258. package/dist/ui/sql/SQLSchemaViewer.js +18 -0
  259. package/dist/ui/sql/index.d.ts +3 -0
  260. package/dist/ui/sql/index.js +3 -0
  261. package/dist/ui/utils/cn.d.ts +1 -0
  262. package/dist/ui/utils/cn.js +1 -0
  263. package/dist/ui/utils/fileIcons.d.ts +2 -0
  264. package/dist/ui/utils/fileIcons.js +24 -0
  265. package/dist/ui/utils/fileUtils.d.ts +4 -0
  266. package/dist/ui/utils/fileUtils.js +11 -0
  267. package/dist/ui/utils/index.d.ts +3 -0
  268. package/dist/ui/utils/index.js +3 -0
  269. package/dist/ui/viewers/components/BrowserViewer.d.ts +9 -0
  270. package/dist/ui/viewers/components/BrowserViewer.js +44 -0
  271. package/dist/ui/viewers/components/CodeEditor.d.ts +11 -0
  272. package/dist/ui/viewers/components/CodeEditor.js +115 -0
  273. package/dist/ui/viewers/components/CsvViewer.d.ts +7 -0
  274. package/dist/ui/viewers/components/CsvViewer.js +18 -0
  275. package/dist/ui/viewers/components/ImageViewer.d.ts +7 -0
  276. package/dist/ui/viewers/components/ImageViewer.js +23 -0
  277. package/dist/ui/viewers/components/PdfViewer.d.ts +7 -0
  278. package/dist/ui/viewers/components/PdfViewer.js +29 -0
  279. package/dist/ui/viewers/components/Terminal.d.ts +7 -0
  280. package/dist/ui/viewers/components/Terminal.js +31 -0
  281. package/dist/ui/viewers/components/index.d.ts +6 -0
  282. package/dist/ui/viewers/components/index.js +6 -0
  283. package/dist/ui/viewers/index.d.ts +1 -0
  284. package/dist/ui/viewers/index.js +1 -0
  285. package/package.json +76 -0
@@ -0,0 +1,203 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { Globe, Bookmark, History, Star, Trash, X, ExternalLink } from 'lucide-react';
3
+ const BrowserUrlDialog = ({ isOpen, onClose, onNavigate, currentPath }) => {
4
+ const [activeTab, setActiveTab] = useState('url');
5
+ const [urlInput, setUrlInput] = useState('');
6
+ const [bookmarks, setBookmarks] = useState([]);
7
+ const [history, setHistory] = useState([]);
8
+ const [loading, setLoading] = useState(false);
9
+ useEffect(() => {
10
+ if (isOpen) {
11
+ loadBookmarksAndHistory();
12
+ setUrlInput('');
13
+ }
14
+ }, [isOpen, currentPath]);
15
+ const loadBookmarksAndHistory = async () => {
16
+ setLoading(true);
17
+ try {
18
+ const [bookmarkRes, historyRes] = await Promise.all([
19
+ window.api.browserGetBookmarks({ folderPath: currentPath }),
20
+ window.api.browserGetHistory({ folderPath: currentPath, limit: 20 })
21
+ ]);
22
+ if (bookmarkRes.success)
23
+ setBookmarks(bookmarkRes.bookmarks);
24
+ if (historyRes.success)
25
+ setHistory(historyRes.history);
26
+ }
27
+ catch (error) {
28
+ console.error('Error loading bookmarks/history:', error);
29
+ }
30
+ finally {
31
+ setLoading(false);
32
+ }
33
+ };
34
+ const handleUrlSubmit = (e) => {
35
+ e.preventDefault();
36
+ if (urlInput.trim()) {
37
+ const finalUrl = urlInput.startsWith('http') ? urlInput : `https://${urlInput}`;
38
+ onNavigate(finalUrl);
39
+ onClose();
40
+ }
41
+ };
42
+ const handleItemSelect = (url) => {
43
+ onNavigate(url);
44
+ onClose();
45
+ };
46
+ const handleAddBookmark = async () => {
47
+ if (!urlInput.trim())
48
+ return;
49
+ try {
50
+ const finalUrl = urlInput.startsWith('http') ? urlInput : `https://${urlInput}`;
51
+ const title = finalUrl.replace(/^https?:\/\//, '').split('/')[0];
52
+ const result = await window.api.browserAddBookmark({
53
+ url: finalUrl,
54
+ title,
55
+ folderPath: currentPath,
56
+ isGlobal: false
57
+ });
58
+ if (result.success) {
59
+ await loadBookmarksAndHistory();
60
+ setActiveTab('bookmarks');
61
+ }
62
+ }
63
+ catch (error) {
64
+ console.error('Error adding bookmark:', error);
65
+ }
66
+ };
67
+ const handleDeleteBookmark = async (bookmarkId, e) => {
68
+ e.stopPropagation();
69
+ try {
70
+ const result = await window.api.browserDeleteBookmark({ bookmarkId });
71
+ if (result.success) {
72
+ await loadBookmarksAndHistory();
73
+ }
74
+ }
75
+ catch (error) {
76
+ console.error('Error deleting bookmark:', error);
77
+ }
78
+ };
79
+ const handleMakeGlobal = async (bookmark, e) => {
80
+ e.stopPropagation();
81
+ try {
82
+ await window.api.browserDeleteBookmark({ bookmarkId: bookmark.id });
83
+ await window.api.browserAddBookmark({
84
+ url: bookmark.url,
85
+ title: bookmark.title,
86
+ folderPath: currentPath,
87
+ isGlobal: true
88
+ });
89
+ await loadBookmarksAndHistory();
90
+ }
91
+ catch (error) {
92
+ console.error('Error making bookmark global:', error);
93
+ }
94
+ };
95
+ const clearHistory = async () => {
96
+ try {
97
+ const result = await window.api.browserClearHistory({ folderPath: currentPath });
98
+ if (result.success) {
99
+ setHistory([]);
100
+ }
101
+ }
102
+ catch (error) {
103
+ console.error('Error clearing history:', error);
104
+ }
105
+ };
106
+ if (!isOpen)
107
+ return null;
108
+ return (React.createElement("div", { className: "fixed inset-0 bg-black/60 flex items-center justify-center z-50 p-4" },
109
+ React.createElement("div", { className: "theme-bg-secondary p-6 theme-border border rounded-lg shadow-xl max-w-2xl w-full max-h-[80vh] flex flex-col" },
110
+ React.createElement("div", { className: "flex items-center justify-between mb-4" },
111
+ React.createElement("h3", { className: "text-lg font-medium theme-text-primary flex items-center gap-2" },
112
+ React.createElement(Globe, { size: 20 }),
113
+ "Open Website"),
114
+ React.createElement("button", { onClick: onClose, className: "p-1 theme-hover rounded-full transition-colors" },
115
+ React.createElement(X, { size: 16 }))),
116
+ React.createElement("div", { className: "flex border-b theme-border mb-4 -mx-2" },
117
+ React.createElement("button", { onClick: () => setActiveTab('url'), className: `px-4 py-2 text-sm border-b-2 transition-colors flex items-center gap-2 ${activeTab === 'url'
118
+ ? 'border-blue-500 theme-text-primary bg-blue-500/10'
119
+ : 'border-transparent theme-text-muted hover:theme-text-primary hover:bg-gray-700/30'}` },
120
+ React.createElement(ExternalLink, { size: 14 }),
121
+ "Enter URL"),
122
+ React.createElement("button", { onClick: () => setActiveTab('bookmarks'), className: `px-4 py-2 text-sm border-b-2 transition-colors flex items-center gap-2 ${activeTab === 'bookmarks'
123
+ ? 'border-blue-500 theme-text-primary bg-blue-500/10'
124
+ : 'border-transparent theme-text-muted hover:theme-text-primary hover:bg-gray-700/30'}` },
125
+ React.createElement(Bookmark, { size: 14 }),
126
+ "Bookmarks (",
127
+ bookmarks.length,
128
+ ")"),
129
+ React.createElement("button", { onClick: () => setActiveTab('history'), className: `px-4 py-2 text-sm border-b-2 transition-colors flex items-center gap-2 ${activeTab === 'history'
130
+ ? 'border-blue-500 theme-text-primary bg-blue-500/10'
131
+ : 'border-transparent theme-text-muted hover:theme-text-primary hover:bg-gray-700/30'}` },
132
+ React.createElement(History, { size: 14 }),
133
+ "History (",
134
+ history.length,
135
+ ")")),
136
+ React.createElement("div", { className: "flex-1 overflow-y-auto min-h-0" },
137
+ activeTab === 'url' && (React.createElement("div", { className: "space-y-4" },
138
+ React.createElement("form", { onSubmit: handleUrlSubmit, className: "space-y-3" },
139
+ React.createElement("div", { className: "flex gap-2" },
140
+ React.createElement("input", { type: "text", value: urlInput, onChange: (e) => setUrlInput(e.target.value), placeholder: "Enter URL (e.g., google.com or https://example.com)", className: "flex-1 theme-input text-sm rounded px-3 py-2 border focus:outline-none focus:ring-2 focus:ring-blue-500", autoFocus: true }),
141
+ React.createElement("button", { type: "button", onClick: handleAddBookmark, disabled: !urlInput.trim(), className: "px-3 py-2 theme-button theme-hover rounded text-sm disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-1" },
142
+ React.createElement(Star, { size: 14 }))),
143
+ React.createElement("button", { type: "submit", disabled: !urlInput.trim(), className: "w-full px-4 py-2 theme-button-primary rounded text-sm disabled:opacity-50 disabled:cursor-not-allowed" }, "Open Website")),
144
+ React.createElement("div", { className: "text-xs theme-text-muted space-y-1 theme-bg-tertiary p-3 rounded" },
145
+ React.createElement("p", null,
146
+ React.createElement("strong", null, "Tips:")),
147
+ React.createElement("p", null,
148
+ "\u2022 Enter just the domain: ",
149
+ React.createElement("code", null, "google.com")),
150
+ React.createElement("p", null,
151
+ "\u2022 Or full URL: ",
152
+ React.createElement("code", null, "https://example.com/page")),
153
+ React.createElement("p", null, "\u2022 Use the star button to save as a bookmark")))),
154
+ activeTab === 'bookmarks' && (React.createElement("div", { className: "space-y-2" }, loading ? (React.createElement("div", { className: "text-center py-8 theme-text-muted" },
155
+ React.createElement("div", { className: "w-6 h-6 border-2 border-blue-400 border-t-transparent rounded-full animate-spin mx-auto mb-2" }),
156
+ "Loading bookmarks...")) : bookmarks.length === 0 ? (React.createElement("div", { className: "text-center py-8 theme-text-muted" },
157
+ React.createElement(Bookmark, { size: 32, className: "mx-auto mb-2 opacity-50" }),
158
+ React.createElement("p", null, "No bookmarks yet"),
159
+ React.createElement("p", { className: "text-xs mt-1" }, "Add URLs from the \"Enter URL\" tab"))) : (bookmarks.map((bookmark) => (React.createElement("div", { key: bookmark.id, className: "flex items-center gap-3 p-3 theme-hover rounded cursor-pointer group transition-colors", onClick: () => handleItemSelect(bookmark.url) },
160
+ React.createElement("div", { className: "flex-shrink-0" }, bookmark.is_global ? (React.createElement(Globe, { size: 16, className: "text-blue-400" })) : (React.createElement(Bookmark, { size: 16, className: "text-yellow-400" }))),
161
+ React.createElement("div", { className: "flex-1 min-w-0" },
162
+ React.createElement("div", { className: "font-medium theme-text-primary truncate" }, bookmark.title),
163
+ React.createElement("div", { className: "text-sm theme-text-muted truncate" }, bookmark.url),
164
+ React.createElement("div", { className: "text-xs theme-text-muted" },
165
+ bookmark.is_global ? 'Global' : 'Local',
166
+ " \u2022 ",
167
+ new Date(bookmark.timestamp).toLocaleDateString())),
168
+ React.createElement("div", { className: "flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity" },
169
+ !bookmark.is_global && (React.createElement("button", { onClick: (e) => handleMakeGlobal(bookmark, e), className: "p-1 theme-hover rounded text-blue-400" },
170
+ React.createElement(Globe, { size: 12 }))),
171
+ React.createElement("button", { onClick: (e) => handleDeleteBookmark(bookmark.id, e), className: "p-1 theme-hover rounded text-red-400" },
172
+ React.createElement(Trash, { size: 12 }))))))))),
173
+ activeTab === 'history' && (React.createElement("div", { className: "space-y-2" },
174
+ React.createElement("div", { className: "flex justify-between items-center mb-3" },
175
+ React.createElement("span", { className: "text-sm theme-text-muted" }, "Recent visits in this folder"),
176
+ history.length > 0 && (React.createElement("button", { onClick: clearHistory, className: "px-2 py-1 text-xs theme-button theme-hover rounded text-red-400" }, "Clear History"))),
177
+ loading ? (React.createElement("div", { className: "text-center py-8 theme-text-muted" },
178
+ React.createElement("div", { className: "w-6 h-6 border-2 border-blue-400 border-t-transparent rounded-full animate-spin mx-auto mb-2" }),
179
+ "Loading history...")) : history.length === 0 ? (React.createElement("div", { className: "text-center py-8 theme-text-muted" },
180
+ React.createElement(History, { size: 32, className: "mx-auto mb-2 opacity-50" }),
181
+ React.createElement("p", null, "No browsing history"),
182
+ React.createElement("p", { className: "text-xs mt-1" }, "Visited websites will appear here"))) : (history.map((item) => (React.createElement("div", { key: item.id, className: "flex items-center gap-3 p-3 theme-hover rounded cursor-pointer group transition-colors", onClick: () => handleItemSelect(item.url) },
183
+ React.createElement(History, { size: 16, className: "text-gray-400 flex-shrink-0" }),
184
+ React.createElement("div", { className: "flex-1 min-w-0" },
185
+ React.createElement("div", { className: "font-medium theme-text-primary truncate" }, item.title || item.url),
186
+ React.createElement("div", { className: "text-sm theme-text-muted truncate" }, item.url),
187
+ React.createElement("div", { className: "text-xs theme-text-muted" },
188
+ item.visit_count,
189
+ " visit",
190
+ item.visit_count !== 1 ? 's' : '',
191
+ " \u2022 ",
192
+ new Date(item.last_visited).toLocaleDateString())),
193
+ React.createElement("button", { onClick: (e) => {
194
+ e.stopPropagation();
195
+ handleAddBookmark();
196
+ setUrlInput(item.url);
197
+ setActiveTab('url');
198
+ }, className: "opacity-0 group-hover:opacity-100 p-1 theme-hover rounded text-yellow-400" },
199
+ React.createElement(Star, { size: 12 }))))))))),
200
+ React.createElement("div", { className: "flex justify-end gap-3 mt-4 pt-4 border-t theme-border" },
201
+ React.createElement("button", { onClick: onClose, className: "px-4 py-2 theme-button theme-hover rounded text-sm" }, "Cancel")))));
202
+ };
203
+ export default BrowserUrlDialog;
@@ -0,0 +1 @@
1
+ export { default as BrowserUrlDialog } from "./BrowserUrlDialog";
@@ -0,0 +1 @@
1
+ export { default as BrowserUrlDialog } from "./BrowserUrlDialog";
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ export type EditorTool = 'select' | 'rect-select' | 'lasso' | 'text' | 'brush' | 'eraser' | 'crop';
3
+ export interface ImageAdjustments {
4
+ exposure: number;
5
+ contrast: number;
6
+ highlights: number;
7
+ shadows: number;
8
+ whites: number;
9
+ blacks: number;
10
+ saturation: number;
11
+ warmth: number;
12
+ tint: number;
13
+ pop: number;
14
+ vignette: number;
15
+ blur: number;
16
+ }
17
+ export interface TextLayer {
18
+ id: string;
19
+ content: string;
20
+ x: number;
21
+ y: number;
22
+ fontSize: number;
23
+ color: string;
24
+ fontFamily: string;
25
+ }
26
+ export interface Selection {
27
+ type: 'rect' | 'lasso';
28
+ x1?: number;
29
+ y1?: number;
30
+ x2?: number;
31
+ y2?: number;
32
+ points?: Array<{
33
+ x: number;
34
+ y: number;
35
+ }>;
36
+ }
37
+ export interface ImageEditorProps {
38
+ imageSrc: string | null;
39
+ onSave?: (data: {
40
+ adjustments: ImageAdjustments;
41
+ textLayers: TextLayer[];
42
+ }) => void;
43
+ onClose?: () => void;
44
+ onGenerativeFill?: (selection: Selection, prompt: string) => Promise<void>;
45
+ className?: string;
46
+ showHeader?: boolean;
47
+ title?: string;
48
+ }
49
+ export declare const ImageEditor: React.FC<ImageEditorProps>;
@@ -0,0 +1,264 @@
1
+ import React, { useState, useRef, useCallback } from 'react';
2
+ import { Camera, Type, Crop, Undo, Redo, Save, X, Brush, Eraser } from 'lucide-react';
3
+ // Icons for tools (using inline SVG for cursor/select tool)
4
+ const CursorIcon = () => (React.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
5
+ React.createElement("path", { d: "M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z" })));
6
+ const RectSelectIcon = () => (React.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
7
+ React.createElement("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", strokeDasharray: "4 2" })));
8
+ const LassoIcon = () => (React.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
9
+ React.createElement("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c2.5 0 4.8-.9 6.6-2.4" }),
10
+ React.createElement("circle", { cx: "18", cy: "18", r: "3" })));
11
+ const SliderControl = ({ label, value, min, max, onChange, onCommit }) => (React.createElement("div", { className: "flex items-center gap-2" },
12
+ React.createElement("span", { className: "text-xs w-20 flex-shrink-0" }, label),
13
+ React.createElement("input", { type: "range", min: min, max: max, value: value, onChange: (e) => onChange(Number(e.target.value)), onMouseUp: onCommit, className: "flex-1 h-1 bg-gray-600 rounded appearance-none cursor-pointer" }),
14
+ React.createElement("span", { className: "text-xs w-8 text-right font-mono" }, value)));
15
+ const ToolButton = ({ active, onClick, title, children }) => (React.createElement("button", { onClick: onClick, className: `p-2 rounded transition-colors ${active ? 'bg-blue-600 text-white' : 'hover:bg-gray-700'}`, title: title }, children));
16
+ // ----- Default Values -----
17
+ const defaultAdjustments = {
18
+ exposure: 0,
19
+ contrast: 0,
20
+ highlights: 0,
21
+ shadows: 0,
22
+ whites: 0,
23
+ blacks: 0,
24
+ saturation: 100,
25
+ warmth: 0,
26
+ tint: 0,
27
+ pop: 0,
28
+ vignette: 0,
29
+ blur: 0
30
+ };
31
+ const generateId = () => `layer_${Math.random().toString(36).substring(2, 11)}`;
32
+ // ----- Main Component -----
33
+ export const ImageEditor = ({ imageSrc, onSave, onClose, onGenerativeFill, className = '', showHeader = true, title = 'Image Editor' }) => {
34
+ // Tool state
35
+ const [activeTool, setActiveTool] = useState('select');
36
+ // Adjustments
37
+ const [adjustments, setAdjustments] = useState(defaultAdjustments);
38
+ // Text layers
39
+ const [textLayers, setTextLayers] = useState([]);
40
+ const [editingTextId, setEditingTextId] = useState(null);
41
+ // Selection
42
+ const [selection, setSelection] = useState(null);
43
+ const [isDrawingSelection, setIsDrawingSelection] = useState(false);
44
+ const [selectionPoints, setSelectionPoints] = useState([]);
45
+ // History
46
+ const [history, setHistory] = useState([]);
47
+ const [historyIndex, setHistoryIndex] = useState(-1);
48
+ // Refs
49
+ const containerRef = useRef(null);
50
+ const imageRef = useRef(null);
51
+ // Generative fill prompt
52
+ const [fillPrompt, setFillPrompt] = useState('');
53
+ // Push to history
54
+ const pushHistory = useCallback(() => {
55
+ const newEntry = { adjustments: { ...adjustments }, textLayers: [...textLayers] };
56
+ setHistory(prev => [...prev.slice(0, historyIndex + 1), newEntry]);
57
+ setHistoryIndex(prev => prev + 1);
58
+ }, [adjustments, textLayers, historyIndex]);
59
+ // Undo/Redo
60
+ const canUndo = historyIndex > 0;
61
+ const canRedo = historyIndex < history.length - 1;
62
+ const undo = useCallback(() => {
63
+ if (canUndo) {
64
+ const prev = history[historyIndex - 1];
65
+ setAdjustments(prev.adjustments);
66
+ setTextLayers(prev.textLayers);
67
+ setHistoryIndex(i => i - 1);
68
+ }
69
+ }, [canUndo, history, historyIndex]);
70
+ const redo = useCallback(() => {
71
+ if (canRedo) {
72
+ const next = history[historyIndex + 1];
73
+ setAdjustments(next.adjustments);
74
+ setTextLayers(next.textLayers);
75
+ setHistoryIndex(i => i + 1);
76
+ }
77
+ }, [canRedo, history, historyIndex]);
78
+ // Handle adjustment change
79
+ const handleAdjustmentChange = (key, value) => {
80
+ setAdjustments(prev => ({ ...prev, [key]: value }));
81
+ };
82
+ // Calculate CSS filter from adjustments
83
+ const calculateImageStyle = useCallback(() => {
84
+ const { exposure, contrast, saturation, warmth, blur } = adjustments;
85
+ const brightness = 1 + (exposure / 100);
86
+ const contrastVal = 1 + (contrast / 100);
87
+ const saturateVal = saturation / 100;
88
+ const sepiaVal = warmth > 0 ? warmth / 200 : 0;
89
+ const hueRotate = warmth < 0 ? warmth : 0;
90
+ return {
91
+ filter: `
92
+ brightness(${brightness})
93
+ contrast(${contrastVal})
94
+ saturate(${saturateVal})
95
+ sepia(${sepiaVal})
96
+ hue-rotate(${hueRotate}deg)
97
+ blur(${blur}px)
98
+ `.trim(),
99
+ maxWidth: '100%',
100
+ maxHeight: '100%',
101
+ objectFit: 'contain'
102
+ };
103
+ }, [adjustments]);
104
+ // Mouse handlers for selection
105
+ const handleMouseDown = (e) => {
106
+ if (activeTool === 'select' || activeTool === 'crop')
107
+ return;
108
+ const rect = containerRef.current?.getBoundingClientRect();
109
+ if (!rect)
110
+ return;
111
+ const x = ((e.clientX - rect.left) / rect.width) * 100;
112
+ const y = ((e.clientY - rect.top) / rect.height) * 100;
113
+ if (activeTool === 'text') {
114
+ const newText = {
115
+ id: generateId(),
116
+ content: 'Text',
117
+ x: e.clientX - rect.left,
118
+ y: e.clientY - rect.top,
119
+ fontSize: 24,
120
+ color: '#ffffff',
121
+ fontFamily: 'Arial'
122
+ };
123
+ setTextLayers(prev => [...prev, newText]);
124
+ setEditingTextId(newText.id);
125
+ pushHistory();
126
+ return;
127
+ }
128
+ if (activeTool === 'rect-select') {
129
+ setIsDrawingSelection(true);
130
+ setSelection({ type: 'rect', x1: x, y1: y, x2: x, y2: y });
131
+ }
132
+ else if (activeTool === 'lasso') {
133
+ setIsDrawingSelection(true);
134
+ setSelectionPoints([{ x, y }]);
135
+ }
136
+ };
137
+ const handleMouseMove = (e) => {
138
+ if (!isDrawingSelection)
139
+ return;
140
+ const rect = containerRef.current?.getBoundingClientRect();
141
+ if (!rect)
142
+ return;
143
+ const x = ((e.clientX - rect.left) / rect.width) * 100;
144
+ const y = ((e.clientY - rect.top) / rect.height) * 100;
145
+ if (activeTool === 'rect-select' && selection?.type === 'rect') {
146
+ setSelection(prev => prev ? { ...prev, x2: x, y2: y } : null);
147
+ }
148
+ else if (activeTool === 'lasso') {
149
+ setSelectionPoints(prev => [...prev, { x, y }]);
150
+ }
151
+ };
152
+ const handleMouseUp = () => {
153
+ if (!isDrawingSelection)
154
+ return;
155
+ setIsDrawingSelection(false);
156
+ if (activeTool === 'lasso' && selectionPoints.length > 2) {
157
+ setSelection({ type: 'lasso', points: selectionPoints });
158
+ }
159
+ };
160
+ // Handle save
161
+ const handleSave = () => {
162
+ onSave?.({ adjustments, textLayers });
163
+ };
164
+ // Reset adjustments
165
+ const resetAdjustments = () => {
166
+ setAdjustments(defaultAdjustments);
167
+ pushHistory();
168
+ };
169
+ if (!imageSrc) {
170
+ return (React.createElement("div", { className: `flex items-center justify-center h-full bg-gray-900 ${className}` },
171
+ React.createElement("div", { className: "text-center text-gray-500" },
172
+ React.createElement(Camera, { size: 48, className: "mx-auto mb-4" }),
173
+ React.createElement("p", null, "No image selected"))));
174
+ }
175
+ return (React.createElement("div", { className: `flex flex-col h-full bg-gray-900 ${className}` },
176
+ showHeader && (React.createElement("div", { className: "flex items-center justify-between px-4 py-2 border-b border-gray-700 bg-gray-800" },
177
+ React.createElement("h3", { className: "font-semibold flex items-center gap-2" },
178
+ React.createElement(Camera, { size: 18 }),
179
+ " ",
180
+ title),
181
+ React.createElement("div", { className: "flex items-center gap-2" },
182
+ React.createElement("button", { onClick: undo, disabled: !canUndo, className: "p-2 rounded hover:bg-gray-700 disabled:opacity-50", title: "Undo" },
183
+ React.createElement(Undo, { size: 18 })),
184
+ React.createElement("button", { onClick: redo, disabled: !canRedo, className: "p-2 rounded hover:bg-gray-700 disabled:opacity-50", title: "Redo" },
185
+ React.createElement(Redo, { size: 18 })),
186
+ onSave && (React.createElement("button", { onClick: handleSave, className: "px-3 py-1 bg-blue-600 rounded text-sm hover:bg-blue-700" },
187
+ React.createElement(Save, { size: 14, className: "inline mr-1" }),
188
+ " Save")),
189
+ onClose && (React.createElement("button", { onClick: onClose, className: "p-2 rounded hover:bg-gray-700" },
190
+ React.createElement(X, { size: 18 })))))),
191
+ React.createElement("div", { className: "flex-1 flex overflow-hidden" },
192
+ React.createElement("div", { className: "w-14 border-r border-gray-700 flex flex-col items-center py-2 gap-1 bg-gray-800" },
193
+ React.createElement(ToolButton, { active: activeTool === 'select', onClick: () => setActiveTool('select'), title: "Select" },
194
+ React.createElement(CursorIcon, null)),
195
+ React.createElement(ToolButton, { active: activeTool === 'rect-select', onClick: () => setActiveTool('rect-select'), title: "Rectangle Select" },
196
+ React.createElement(RectSelectIcon, null)),
197
+ React.createElement(ToolButton, { active: activeTool === 'lasso', onClick: () => setActiveTool('lasso'), title: "Lasso Select" },
198
+ React.createElement(LassoIcon, null)),
199
+ React.createElement(ToolButton, { active: activeTool === 'text', onClick: () => setActiveTool('text'), title: "Text Tool" },
200
+ React.createElement(Type, { size: 20 })),
201
+ React.createElement("div", { className: "border-t border-gray-600 w-full my-2" }),
202
+ React.createElement(ToolButton, { active: activeTool === 'brush', onClick: () => setActiveTool('brush'), title: "Brush" },
203
+ React.createElement(Brush, { size: 20 })),
204
+ React.createElement(ToolButton, { active: activeTool === 'eraser', onClick: () => setActiveTool('eraser'), title: "Eraser" },
205
+ React.createElement(Eraser, { size: 20 })),
206
+ React.createElement("div", { className: "border-t border-gray-600 w-full my-2" }),
207
+ React.createElement(ToolButton, { active: activeTool === 'crop', onClick: () => setActiveTool('crop'), title: "Crop" },
208
+ React.createElement(Crop, { size: 20 }))),
209
+ React.createElement("div", { ref: containerRef, className: "flex-1 flex items-center justify-center p-4 overflow-hidden relative bg-gray-800/50", onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onMouseUp: handleMouseUp, style: { cursor: activeTool === 'text' ? 'text' : activeTool === 'lasso' ? 'crosshair' : 'default' } },
210
+ React.createElement("div", { className: "relative" },
211
+ React.createElement("img", { ref: imageRef, src: imageSrc, style: calculateImageStyle(), alt: "Editing", draggable: false }),
212
+ selection?.type === 'rect' && (React.createElement("div", { className: "absolute border-2 border-dashed border-blue-400 pointer-events-none", style: {
213
+ left: `${Math.min(selection.x1 || 0, selection.x2 || 0)}%`,
214
+ top: `${Math.min(selection.y1 || 0, selection.y2 || 0)}%`,
215
+ width: `${Math.abs((selection.x2 || 0) - (selection.x1 || 0))}%`,
216
+ height: `${Math.abs((selection.y2 || 0) - (selection.y1 || 0))}%`
217
+ } })),
218
+ selection?.type === 'lasso' && selection.points && (React.createElement("svg", { className: "absolute inset-0 pointer-events-none w-full h-full" },
219
+ React.createElement("polygon", { points: selection.points.map(p => `${p.x}%,${p.y}%`).join(' '), fill: "rgba(59, 130, 246, 0.1)", stroke: "rgb(59, 130, 246)", strokeWidth: "2", strokeDasharray: "5,5" }))),
220
+ textLayers.map(text => (React.createElement("div", { key: text.id, className: "absolute cursor-move", style: {
221
+ left: text.x,
222
+ top: text.y,
223
+ fontSize: text.fontSize,
224
+ color: text.color,
225
+ fontFamily: text.fontFamily,
226
+ zIndex: 10
227
+ }, onDoubleClick: () => setEditingTextId(text.id) }, editingTextId === text.id ? (React.createElement("input", { type: "text", value: text.content, onChange: (e) => setTextLayers(prev => prev.map(t => t.id === text.id ? { ...t, content: e.target.value } : t)), onBlur: () => setEditingTextId(null), onKeyDown: (e) => e.key === 'Enter' && setEditingTextId(null), autoFocus: true, className: "bg-black/50 border border-blue-400 outline-none px-2", style: {
228
+ fontSize: text.fontSize,
229
+ color: text.color,
230
+ fontFamily: text.fontFamily
231
+ } })) : (React.createElement("span", { className: "px-2 py-1 bg-black/30 rounded" }, text.content))))),
232
+ adjustments.vignette > 0 && (React.createElement("div", { className: "absolute inset-0 pointer-events-none", style: {
233
+ boxShadow: `inset 0 0 ${adjustments.vignette * 2.5}px ${adjustments.vignette * 1.5}px rgba(0,0,0,0.9)`
234
+ } })))),
235
+ React.createElement("div", { className: "w-72 border-l border-gray-700 bg-gray-800 flex flex-col overflow-hidden" },
236
+ React.createElement("div", { className: "p-3 border-b border-gray-700" },
237
+ React.createElement("h4", { className: "font-semibold text-sm" }, "Adjustments")),
238
+ React.createElement("div", { className: "flex-1 overflow-y-auto p-3 space-y-4" },
239
+ React.createElement("details", { open: true },
240
+ React.createElement("summary", { className: "font-semibold text-sm cursor-pointer mb-2" }, "Light"),
241
+ React.createElement("div", { className: "space-y-2" },
242
+ React.createElement(SliderControl, { label: "Exposure", value: adjustments.exposure, min: -100, max: 100, onChange: (v) => handleAdjustmentChange('exposure', v), onCommit: pushHistory }),
243
+ React.createElement(SliderControl, { label: "Contrast", value: adjustments.contrast, min: -100, max: 100, onChange: (v) => handleAdjustmentChange('contrast', v), onCommit: pushHistory }),
244
+ React.createElement(SliderControl, { label: "Highlights", value: adjustments.highlights, min: -100, max: 100, onChange: (v) => handleAdjustmentChange('highlights', v), onCommit: pushHistory }),
245
+ React.createElement(SliderControl, { label: "Shadows", value: adjustments.shadows, min: -100, max: 100, onChange: (v) => handleAdjustmentChange('shadows', v), onCommit: pushHistory }))),
246
+ React.createElement("details", { open: true },
247
+ React.createElement("summary", { className: "font-semibold text-sm cursor-pointer mb-2" }, "Color"),
248
+ React.createElement("div", { className: "space-y-2" },
249
+ React.createElement(SliderControl, { label: "Saturation", value: adjustments.saturation, min: 0, max: 200, onChange: (v) => handleAdjustmentChange('saturation', v), onCommit: pushHistory }),
250
+ React.createElement(SliderControl, { label: "Warmth", value: adjustments.warmth, min: -100, max: 100, onChange: (v) => handleAdjustmentChange('warmth', v), onCommit: pushHistory }),
251
+ React.createElement(SliderControl, { label: "Tint", value: adjustments.tint, min: -100, max: 100, onChange: (v) => handleAdjustmentChange('tint', v), onCommit: pushHistory }))),
252
+ React.createElement("details", { open: true },
253
+ React.createElement("summary", { className: "font-semibold text-sm cursor-pointer mb-2" }, "Effects"),
254
+ React.createElement("div", { className: "space-y-2" },
255
+ React.createElement(SliderControl, { label: "Vignette", value: adjustments.vignette, min: 0, max: 100, onChange: (v) => handleAdjustmentChange('vignette', v), onCommit: pushHistory }),
256
+ React.createElement(SliderControl, { label: "Blur", value: adjustments.blur, min: 0, max: 20, onChange: (v) => handleAdjustmentChange('blur', v), onCommit: pushHistory }))),
257
+ selection && onGenerativeFill && (React.createElement("div", { className: "border-t border-gray-700 pt-4 space-y-2" },
258
+ React.createElement("h5", { className: "font-semibold text-sm" }, "Selection"),
259
+ React.createElement("input", { type: "text", value: fillPrompt, onChange: (e) => setFillPrompt(e.target.value), placeholder: "Fill prompt...", className: "w-full bg-gray-700 rounded px-2 py-1 text-sm" }),
260
+ React.createElement("div", { className: "flex gap-2" },
261
+ React.createElement("button", { onClick: () => onGenerativeFill(selection, fillPrompt), className: "flex-1 bg-blue-600 rounded py-1 text-sm hover:bg-blue-700" }, "Fill"),
262
+ React.createElement("button", { onClick: () => setSelection(null), className: "flex-1 bg-gray-700 rounded py-1 text-sm hover:bg-gray-600" }, "Clear")))),
263
+ React.createElement("button", { onClick: resetAdjustments, className: "w-full bg-gray-700 rounded py-2 text-sm hover:bg-gray-600" }, "Reset All"))))));
264
+ };
@@ -0,0 +1,2 @@
1
+ export { ImageEditor } from './ImageEditor';
2
+ export type { ImageEditorProps, ImageAdjustments, TextLayer, Selection, EditorTool } from './ImageEditor';
@@ -0,0 +1 @@
1
+ export { ImageEditor } from './ImageEditor';
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ interface ExecutionFiltersProps {
3
+ searchTerm: string;
4
+ onSearchChange: (term: string) => void;
5
+ labelFilter: string;
6
+ onLabelFilterChange: (label: string) => void;
7
+ dateRange: string;
8
+ onDateRangeChange: (range: string) => void;
9
+ }
10
+ export declare const ExecutionFilters: React.FC<ExecutionFiltersProps>;
11
+ export {};
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ import { Search, Filter } from 'lucide-react';
3
+ export const ExecutionFilters = ({ searchTerm, onSearchChange, labelFilter, onLabelFilterChange, dateRange, onDateRangeChange }) => {
4
+ return (React.createElement("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4" },
5
+ React.createElement("div", null,
6
+ React.createElement("label", { className: "text-sm font-medium mb-2 block" },
7
+ React.createElement(Search, { size: 14, className: "inline mr-1" }),
8
+ "Search"),
9
+ React.createElement("input", { type: "text", value: searchTerm, onChange: (e) => onSearchChange(e.target.value), placeholder: "Search executions...", className: "w-full px-3 py-2 bg-gray-800 border border-gray-700 rounded text-sm" })),
10
+ React.createElement("div", null,
11
+ React.createElement("label", { className: "text-sm font-medium mb-2 block" },
12
+ React.createElement(Filter, { size: 14, className: "inline mr-1" }),
13
+ "Label Filter"),
14
+ React.createElement("select", { value: labelFilter, onChange: (e) => onLabelFilterChange(e.target.value), className: "w-full px-3 py-2 bg-gray-800 border border-gray-700 rounded text-sm" },
15
+ React.createElement("option", { value: "all" }, "All Labels"),
16
+ React.createElement("option", { value: "good" }, "Good"),
17
+ React.createElement("option", { value: "bad" }, "Bad"),
18
+ React.createElement("option", { value: "neutral" }, "Neutral"),
19
+ React.createElement("option", { value: "unlabeled" }, "Unlabeled"))),
20
+ React.createElement("div", null,
21
+ React.createElement("label", { className: "text-sm font-medium mb-2 block" }, "Date Range"),
22
+ React.createElement("select", { value: dateRange, onChange: (e) => onDateRangeChange(e.target.value), className: "w-full px-3 py-2 bg-gray-800 border border-gray-700 rounded text-sm" },
23
+ React.createElement("option", { value: "all" }, "All Time"),
24
+ React.createElement("option", { value: "7d" }, "Last 7 Days"),
25
+ React.createElement("option", { value: "30d" }, "Last 30 Days"),
26
+ React.createElement("option", { value: "90d" }, "Last 90 Days")))));
27
+ };
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ export interface Execution {
3
+ id: string;
4
+ timestamp: string;
5
+ input: string;
6
+ output: string;
7
+ label?: 'good' | 'bad' | 'neutral';
8
+ favorited?: boolean;
9
+ }
10
+ interface ExecutionHistoryListProps {
11
+ executions: Execution[];
12
+ onRun?: (id: string) => void;
13
+ onCopy?: (id: string) => void;
14
+ onToggleFavorite?: (id: string) => void;
15
+ onDelete?: (id: string) => void;
16
+ onLabel?: (id: string, label: 'good' | 'bad' | 'neutral') => void;
17
+ }
18
+ export declare const ExecutionHistoryList: React.FC<ExecutionHistoryListProps>;
19
+ export {};
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { Play, Copy, Star, Trash2, ChevronDown, ChevronRight } from 'lucide-react';
3
+ export const ExecutionHistoryList = ({ executions, onRun, onCopy, onToggleFavorite, onDelete, onLabel }) => {
4
+ const [expandedId, setExpandedId] = React.useState(null);
5
+ return (React.createElement("ul", { className: "space-y-1 text-sm font-mono" },
6
+ executions.map((exec) => (React.createElement("li", { key: exec.id, className: "group rounded hover:bg-gray-800" },
7
+ React.createElement("div", { className: "flex items-center justify-between p-2" },
8
+ React.createElement("button", { onClick: () => setExpandedId(expandedId === exec.id ? null : exec.id), className: "flex-1 text-left truncate flex items-center gap-2", title: exec.input },
9
+ expandedId === exec.id ? React.createElement(ChevronDown, { size: 14 }) : React.createElement(ChevronRight, { size: 14 }),
10
+ React.createElement("span", { className: "truncate" }, exec.input)),
11
+ React.createElement("div", { className: "flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity" },
12
+ onRun && (React.createElement("button", { onClick: () => onRun(exec.id), className: "p-1 hover:bg-gray-700 rounded", title: "Run" },
13
+ React.createElement(Play, { size: 14 }))),
14
+ onCopy && (React.createElement("button", { onClick: () => onCopy(exec.id), className: "p-1 hover:bg-gray-700 rounded", title: "Copy" },
15
+ React.createElement(Copy, { size: 14 }))),
16
+ onToggleFavorite && (React.createElement("button", { onClick: () => onToggleFavorite(exec.id), className: "p-1 hover:bg-gray-700 rounded", title: "Favorite" },
17
+ React.createElement(Star, { size: 14, className: exec.favorited ? 'fill-yellow-400 text-yellow-400' : '' }))),
18
+ onDelete && (React.createElement("button", { onClick: () => onDelete(exec.id), className: "p-1 hover:bg-gray-700 rounded text-red-400", title: "Delete" },
19
+ React.createElement(Trash2, { size: 14 }))))),
20
+ expandedId === exec.id && (React.createElement("div", { className: "px-2 pb-2 space-y-2 text-xs" },
21
+ React.createElement("div", { className: "bg-gray-900 p-2 rounded" },
22
+ React.createElement("div", { className: "text-gray-500 mb-1" }, "Output:"),
23
+ React.createElement("div", null, exec.output)),
24
+ onLabel && (React.createElement("div", { className: "flex gap-2" },
25
+ React.createElement("button", { onClick: () => onLabel(exec.id, 'good'), className: `px-2 py-1 rounded ${exec.label === 'good'
26
+ ? 'bg-green-600 text-white'
27
+ : 'bg-gray-700 hover:bg-gray-600'}` }, "Good"),
28
+ React.createElement("button", { onClick: () => onLabel(exec.id, 'bad'), className: `px-2 py-1 rounded ${exec.label === 'bad'
29
+ ? 'bg-red-600 text-white'
30
+ : 'bg-gray-700 hover:bg-gray-600'}` }, "Bad"),
31
+ React.createElement("button", { onClick: () => onLabel(exec.id, 'neutral'), className: `px-2 py-1 rounded ${exec.label === 'neutral'
32
+ ? 'bg-gray-600 text-white'
33
+ : 'bg-gray-700 hover:bg-gray-600'}` }, "Neutral")))))))),
34
+ executions.length === 0 && (React.createElement("li", { className: "text-center p-4 text-gray-500" }, "No execution history"))));
35
+ };
@@ -0,0 +1,3 @@
1
+ export { ExecutionHistoryList } from './ExecutionHistoryList';
2
+ export { ExecutionFilters } from './ExecutionFilters';
3
+ export type { Execution } from './ExecutionHistoryList';