@flanksource/clicky-ui 0.2.19 → 0.2.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.cjs +26 -0
- package/dist/ai.cjs.map +1 -0
- package/dist/ai.d.ts +2 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +26 -0
- package/dist/ai.js.map +1 -0
- package/dist/chat.cjs +7 -0
- package/dist/chat.cjs.map +1 -1
- package/dist/chat.js +7 -0
- package/dist/chat.js.map +1 -1
- package/dist/components/FilterBar.cjs +49 -18
- package/dist/components/FilterBar.cjs.map +1 -1
- package/dist/components/FilterBar.d.ts +0 -2
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterBar.js +50 -19
- package/dist/components/FilterBar.js.map +1 -1
- package/dist/components/SearchInput.cjs +63 -0
- package/dist/components/SearchInput.cjs.map +1 -0
- package/dist/components/SearchInput.d.ts +31 -0
- package/dist/components/SearchInput.d.ts.map +1 -0
- package/dist/components/SearchInput.js +63 -0
- package/dist/components/SearchInput.js.map +1 -0
- package/dist/components/SegmentedControl.cjs +88 -0
- package/dist/components/SegmentedControl.cjs.map +1 -0
- package/dist/components/SegmentedControl.d.ts +38 -0
- package/dist/components/SegmentedControl.d.ts.map +1 -0
- package/dist/components/SegmentedControl.js +88 -0
- package/dist/components/SegmentedControl.js.map +1 -0
- package/dist/components/Switch.cjs +51 -0
- package/dist/components/Switch.cjs.map +1 -0
- package/dist/components/Switch.d.ts +23 -0
- package/dist/components/Switch.d.ts.map +1 -0
- package/dist/components/Switch.js +51 -0
- package/dist/components/Switch.js.map +1 -0
- package/dist/components/TimeRange.cjs +53 -45
- package/dist/components/TimeRange.cjs.map +1 -1
- package/dist/components/TimeRange.d.ts.map +1 -1
- package/dist/components/TimeRange.js +53 -45
- package/dist/components/TimeRange.js.map +1 -1
- package/dist/components/TreePickerField.cjs +5 -1
- package/dist/components/TreePickerField.cjs.map +1 -1
- package/dist/components/TreePickerField.d.ts.map +1 -1
- package/dist/components/TreePickerField.js +5 -1
- package/dist/components/TreePickerField.js.map +1 -1
- package/dist/components/filter-bar-utils.cjs +5 -0
- package/dist/components/filter-bar-utils.cjs.map +1 -1
- package/dist/components/filter-bar-utils.d.ts +2 -0
- package/dist/components/filter-bar-utils.d.ts.map +1 -1
- package/dist/components/filter-bar-utils.js +5 -0
- package/dist/components/filter-bar-utils.js.map +1 -1
- package/dist/components/json-schema-form-fields.cjs +8 -2
- package/dist/components/json-schema-form-fields.cjs.map +1 -1
- package/dist/components/json-schema-form-fields.d.ts.map +1 -1
- package/dist/components/json-schema-form-fields.js +8 -2
- package/dist/components/json-schema-form-fields.js.map +1 -1
- package/dist/components/json-schema-form-resolve.cjs +1 -1
- package/dist/components/json-schema-form-resolve.cjs.map +1 -1
- package/dist/components/json-schema-form-resolve.js +1 -1
- package/dist/components/json-schema-form-resolve.js.map +1 -1
- package/dist/components.cjs +15 -1
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +8 -1
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +15 -1
- package/dist/components.js.map +1 -1
- package/dist/data/Clicky.cjs +33 -44
- package/dist/data/Clicky.cjs.map +1 -1
- package/dist/data/Clicky.d.ts +0 -9
- package/dist/data/Clicky.d.ts.map +1 -1
- package/dist/data/Clicky.js +31 -42
- package/dist/data/Clicky.js.map +1 -1
- package/dist/data/DataTable.cjs +73 -50
- package/dist/data/DataTable.cjs.map +1 -1
- package/dist/data/DataTable.d.ts +4 -0
- package/dist/data/DataTable.d.ts.map +1 -1
- package/dist/data/DataTable.js +73 -50
- package/dist/data/DataTable.js.map +1 -1
- package/dist/data/Icon.cjs +2 -5
- package/dist/data/Icon.cjs.map +1 -1
- package/dist/data/Icon.d.ts +1 -21
- package/dist/data/Icon.d.ts.map +1 -1
- package/dist/data/Icon.js +3 -6
- package/dist/data/Icon.js.map +1 -1
- package/dist/data/MatrixTable.cjs +4 -4
- package/dist/data/MatrixTable.cjs.map +1 -1
- package/dist/data/MatrixTable.js +4 -4
- package/dist/data/MatrixTable.js.map +1 -1
- package/dist/data/RadialGauge.cjs +76 -0
- package/dist/data/RadialGauge.cjs.map +1 -0
- package/dist/data/RadialGauge.d.ts +24 -0
- package/dist/data/RadialGauge.d.ts.map +1 -0
- package/dist/data/RadialGauge.js +76 -0
- package/dist/data/RadialGauge.js.map +1 -0
- package/dist/data/StatusBreakdown.cjs +0 -4
- package/dist/data/StatusBreakdown.cjs.map +1 -1
- package/dist/data/StatusBreakdown.d.ts +0 -2
- package/dist/data/StatusBreakdown.d.ts.map +1 -1
- package/dist/data/StatusBreakdown.js +1 -5
- package/dist/data/StatusBreakdown.js.map +1 -1
- package/dist/data/Timeline.cjs +61 -0
- package/dist/data/Timeline.cjs.map +1 -0
- package/dist/data/Timeline.d.ts +36 -0
- package/dist/data/Timeline.d.ts.map +1 -0
- package/dist/data/Timeline.js +61 -0
- package/dist/data/Timeline.js.map +1 -0
- package/dist/data/TimeseriesCoreBars.cjs +2 -25
- package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
- package/dist/data/TimeseriesCoreBars.d.ts +0 -19
- package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
- package/dist/data/TimeseriesCoreBars.js +2 -25
- package/dist/data/TimeseriesCoreBars.js.map +1 -1
- package/dist/data/TimeseriesCoreBars.model.cjs +27 -0
- package/dist/data/TimeseriesCoreBars.model.cjs.map +1 -0
- package/dist/data/TimeseriesCoreBars.model.d.ts +20 -0
- package/dist/data/TimeseriesCoreBars.model.d.ts.map +1 -0
- package/dist/data/TimeseriesCoreBars.model.js +27 -0
- package/dist/data/TimeseriesCoreBars.model.js.map +1 -0
- package/dist/data/TimeseriesPanel.axes.cjs.map +1 -1
- package/dist/data/TimeseriesPanel.axes.d.ts +1 -1
- package/dist/data/TimeseriesPanel.axes.d.ts.map +1 -1
- package/dist/data/TimeseriesPanel.axes.js.map +1 -1
- package/dist/data/TimeseriesPanel.cjs +4 -54
- package/dist/data/TimeseriesPanel.cjs.map +1 -1
- package/dist/data/TimeseriesPanel.d.ts +2 -138
- package/dist/data/TimeseriesPanel.d.ts.map +1 -1
- package/dist/data/TimeseriesPanel.js +2 -52
- package/dist/data/TimeseriesPanel.js.map +1 -1
- package/dist/data/TimeseriesPanel.model.cjs +53 -0
- package/dist/data/TimeseriesPanel.model.cjs.map +1 -0
- package/dist/data/TimeseriesPanel.model.d.ts +88 -0
- package/dist/data/TimeseriesPanel.model.d.ts.map +1 -0
- package/dist/data/TimeseriesPanel.model.js +53 -0
- package/dist/data/TimeseriesPanel.model.js.map +1 -0
- package/dist/data/Tree.cjs +1 -1
- package/dist/data/Tree.cjs.map +1 -1
- package/dist/data/Tree.js +1 -1
- package/dist/data/Tree.js.map +1 -1
- package/dist/data/ai/ChatFab.cjs +29 -0
- package/dist/data/ai/ChatFab.cjs.map +1 -0
- package/dist/data/ai/ChatFab.d.ts +12 -0
- package/dist/data/ai/ChatFab.d.ts.map +1 -0
- package/dist/data/ai/ChatFab.js +29 -0
- package/dist/data/ai/ChatFab.js.map +1 -0
- package/dist/data/ai/ChatWindow.cjs +178 -0
- package/dist/data/ai/ChatWindow.cjs.map +1 -0
- package/dist/data/ai/ChatWindow.d.ts +38 -0
- package/dist/data/ai/ChatWindow.d.ts.map +1 -0
- package/dist/data/ai/ChatWindow.js +156 -0
- package/dist/data/ai/ChatWindow.js.map +1 -0
- package/dist/data/ai/ChatWindowManager.cjs +139 -0
- package/dist/data/ai/ChatWindowManager.cjs.map +1 -0
- package/dist/data/ai/ChatWindowManager.d.ts +12 -0
- package/dist/data/ai/ChatWindowManager.d.ts.map +1 -0
- package/dist/data/ai/ChatWindowManager.js +139 -0
- package/dist/data/ai/ChatWindowManager.js.map +1 -0
- package/dist/data/ai/ContextBadges.cjs +74 -0
- package/dist/data/ai/ContextBadges.cjs.map +1 -0
- package/dist/data/ai/ContextBadges.d.ts +16 -0
- package/dist/data/ai/ContextBadges.d.ts.map +1 -0
- package/dist/data/ai/ContextBadges.js +74 -0
- package/dist/data/ai/ContextBadges.js.map +1 -0
- package/dist/data/ai/ThreadPicker.cjs +148 -0
- package/dist/data/ai/ThreadPicker.cjs.map +1 -0
- package/dist/data/ai/ThreadPicker.d.ts +37 -0
- package/dist/data/ai/ThreadPicker.d.ts.map +1 -0
- package/dist/data/ai/ThreadPicker.js +148 -0
- package/dist/data/ai/ThreadPicker.js.map +1 -0
- package/dist/data/ai/ToolPreferences.cjs +80 -0
- package/dist/data/ai/ToolPreferences.cjs.map +1 -0
- package/dist/data/ai/ToolPreferences.d.ts +19 -0
- package/dist/data/ai/ToolPreferences.d.ts.map +1 -0
- package/dist/data/ai/ToolPreferences.js +80 -0
- package/dist/data/ai/ToolPreferences.js.map +1 -0
- package/dist/data/ai/chat-window-context.cjs +78 -0
- package/dist/data/ai/chat-window-context.cjs.map +1 -0
- package/dist/data/ai/chat-window-context.d.ts +57 -0
- package/dist/data/ai/chat-window-context.d.ts.map +1 -0
- package/dist/data/ai/chat-window-context.js +78 -0
- package/dist/data/ai/chat-window-context.js.map +1 -0
- package/dist/data/ai/context.cjs +43 -0
- package/dist/data/ai/context.cjs.map +1 -0
- package/dist/data/ai/context.d.ts +35 -0
- package/dist/data/ai/context.d.ts.map +1 -0
- package/dist/data/ai/context.js +43 -0
- package/dist/data/ai/context.js.map +1 -0
- package/dist/data/ai/index.d.ts +10 -0
- package/dist/data/ai/index.d.ts.map +1 -0
- package/dist/data/cache-browser/CacheDetailPanel.cjs +15 -0
- package/dist/data/cache-browser/CacheDetailPanel.cjs.map +1 -1
- package/dist/data/cache-browser/CacheDetailPanel.d.ts.map +1 -1
- package/dist/data/cache-browser/CacheDetailPanel.js +15 -0
- package/dist/data/cache-browser/CacheDetailPanel.js.map +1 -1
- package/dist/data/cache-browser/cache-browser.fixtures.d.ts +10 -0
- package/dist/data/cache-browser/cache-browser.fixtures.d.ts.map +1 -0
- package/dist/data/cache-browser/download.cjs +13 -0
- package/dist/data/cache-browser/download.cjs.map +1 -0
- package/dist/data/cache-browser/download.d.ts +3 -0
- package/dist/data/cache-browser/download.d.ts.map +1 -0
- package/dist/data/cache-browser/download.js +13 -0
- package/dist/data/cache-browser/download.js.map +1 -0
- package/dist/data/chat/Chat.cjs +40 -2
- package/dist/data/chat/Chat.cjs.map +1 -1
- package/dist/data/chat/Chat.d.ts +5 -2
- package/dist/data/chat/Chat.d.ts.map +1 -1
- package/dist/data/chat/Chat.fixtures.cjs +86 -0
- package/dist/data/chat/Chat.fixtures.cjs.map +1 -0
- package/dist/data/chat/Chat.fixtures.d.ts +4 -0
- package/dist/data/chat/Chat.fixtures.d.ts.map +1 -1
- package/dist/data/chat/Chat.fixtures.js +86 -0
- package/dist/data/chat/Chat.fixtures.js.map +1 -0
- package/dist/data/chat/Chat.js +41 -3
- package/dist/data/chat/Chat.js.map +1 -1
- package/dist/data/chat/ContextUsage.cjs +99 -0
- package/dist/data/chat/ContextUsage.cjs.map +1 -0
- package/dist/data/chat/ContextUsage.d.ts +19 -0
- package/dist/data/chat/ContextUsage.d.ts.map +1 -0
- package/dist/data/chat/ContextUsage.js +99 -0
- package/dist/data/chat/ContextUsage.js.map +1 -0
- package/dist/data/chat/ModelSelector.cjs +28 -14
- package/dist/data/chat/ModelSelector.cjs.map +1 -1
- package/dist/data/chat/ModelSelector.d.ts +5 -4
- package/dist/data/chat/ModelSelector.d.ts.map +1 -1
- package/dist/data/chat/ModelSelector.js +28 -14
- package/dist/data/chat/ModelSelector.js.map +1 -1
- package/dist/data/chat/clickyOperationsToTools.cjs +21 -1
- package/dist/data/chat/clickyOperationsToTools.cjs.map +1 -1
- package/dist/data/chat/clickyOperationsToTools.d.ts +5 -4
- package/dist/data/chat/clickyOperationsToTools.d.ts.map +1 -1
- package/dist/data/chat/clickyOperationsToTools.js +21 -1
- package/dist/data/chat/clickyOperationsToTools.js.map +1 -1
- package/dist/data/chat/index.d.ts +4 -1
- package/dist/data/chat/index.d.ts.map +1 -1
- package/dist/data/chat/provider-icons.cjs +15 -0
- package/dist/data/chat/provider-icons.cjs.map +1 -0
- package/dist/data/chat/provider-icons.d.ts +7 -0
- package/dist/data/chat/provider-icons.d.ts.map +1 -0
- package/dist/data/chat/provider-icons.js +15 -0
- package/dist/data/chat/provider-icons.js.map +1 -0
- package/dist/data/chat/types.cjs.map +1 -1
- package/dist/data/chat/types.d.ts +41 -9
- package/dist/data/chat/types.d.ts.map +1 -1
- package/dist/data/chat/types.js.map +1 -1
- package/dist/data/clicky-parse.cjs +42 -0
- package/dist/data/clicky-parse.cjs.map +1 -0
- package/dist/data/clicky-parse.d.ts +11 -0
- package/dist/data/clicky-parse.d.ts.map +1 -0
- package/dist/data/clicky-parse.js +42 -0
- package/dist/data/clicky-parse.js.map +1 -0
- package/dist/data/diagnostics/FrameSourceWindow.cjs +0 -4
- package/dist/data/diagnostics/FrameSourceWindow.cjs.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.d.ts +1 -11
- package/dist/data/diagnostics/FrameSourceWindow.d.ts.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.js +1 -5
- package/dist/data/diagnostics/FrameSourceWindow.js.map +1 -1
- package/dist/data/diagnostics/FrameSourceWindow.utils.cjs +7 -0
- package/dist/data/diagnostics/FrameSourceWindow.utils.cjs.map +1 -0
- package/dist/data/diagnostics/FrameSourceWindow.utils.d.ts +12 -0
- package/dist/data/diagnostics/FrameSourceWindow.utils.d.ts.map +1 -0
- package/dist/data/diagnostics/FrameSourceWindow.utils.js +7 -0
- package/dist/data/diagnostics/FrameSourceWindow.utils.js.map +1 -0
- package/dist/data/diagnostics/JvmStackTrace.cjs +2 -1
- package/dist/data/diagnostics/JvmStackTrace.cjs.map +1 -1
- package/dist/data/diagnostics/JvmStackTrace.d.ts.map +1 -1
- package/dist/data/diagnostics/JvmStackTrace.js +2 -1
- package/dist/data/diagnostics/JvmStackTrace.js.map +1 -1
- package/dist/data/icon-fallback.cjs +12 -0
- package/dist/data/icon-fallback.cjs.map +1 -0
- package/dist/data/icon-fallback.d.ts +19 -0
- package/dist/data/icon-fallback.d.ts.map +1 -0
- package/dist/data/icon-fallback.js +12 -0
- package/dist/data/icon-fallback.js.map +1 -0
- package/dist/data/status-breakdown-utils.cjs +7 -0
- package/dist/data/status-breakdown-utils.cjs.map +1 -0
- package/dist/data/status-breakdown-utils.d.ts +4 -0
- package/dist/data/status-breakdown-utils.d.ts.map +1 -0
- package/dist/data/status-breakdown-utils.js +7 -0
- package/dist/data/status-breakdown-utils.js.map +1 -0
- package/dist/data/test-runner/TestRunSummary.cjs +36 -0
- package/dist/data/test-runner/TestRunSummary.cjs.map +1 -1
- package/dist/data/test-runner/TestRunSummary.d.ts +7 -1
- package/dist/data/test-runner/TestRunSummary.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunSummary.js +36 -0
- package/dist/data/test-runner/TestRunSummary.js.map +1 -1
- package/dist/data/test-runner/TestRunner.cjs +5 -3
- package/dist/data/test-runner/TestRunner.cjs.map +1 -1
- package/dist/data/test-runner/TestRunner.d.ts +13 -1
- package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.js +5 -3
- package/dist/data/test-runner/TestRunner.js.map +1 -1
- package/dist/data/version-info.cjs +2 -2
- package/dist/data/version-info.js +2 -2
- package/dist/data.cjs +19 -6
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +13 -5
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +18 -5
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +51 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +50 -6
- package/dist/index.js.map +1 -1
- package/dist/layout/AppShell.cjs +179 -29
- package/dist/layout/AppShell.cjs.map +1 -1
- package/dist/layout/AppShell.d.ts +5 -5
- package/dist/layout/AppShell.d.ts.map +1 -1
- package/dist/layout/AppShell.js +179 -29
- package/dist/layout/AppShell.js.map +1 -1
- package/dist/layout/AppSidebar.cjs +239 -0
- package/dist/layout/AppSidebar.cjs.map +1 -0
- package/dist/layout/AppSidebar.d.ts +62 -0
- package/dist/layout/AppSidebar.d.ts.map +1 -0
- package/dist/layout/AppSidebar.js +239 -0
- package/dist/layout/AppSidebar.js.map +1 -0
- package/dist/overlay/DropdownMenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenu.d.ts.map +1 -1
- package/dist/overlay/DropdownMenu.js.map +1 -1
- package/dist/overlay/Modal.cjs +4 -2
- package/dist/overlay/Modal.cjs.map +1 -1
- package/dist/overlay/Modal.d.ts +1 -1
- package/dist/overlay/Modal.d.ts.map +1 -1
- package/dist/overlay/Modal.js +4 -2
- package/dist/overlay/Modal.js.map +1 -1
- package/dist/overlay/Toast.cjs +89 -0
- package/dist/overlay/Toast.cjs.map +1 -0
- package/dist/overlay/Toast.d.ts +14 -0
- package/dist/overlay/Toast.d.ts.map +1 -0
- package/dist/overlay/Toast.js +89 -0
- package/dist/overlay/Toast.js.map +1 -0
- package/dist/overlay/toast-context.cjs +12 -0
- package/dist/overlay/toast-context.cjs.map +1 -0
- package/dist/overlay/toast-context.d.ts +24 -0
- package/dist/overlay/toast-context.d.ts.map +1 -0
- package/dist/overlay/toast-context.js +12 -0
- package/dist/overlay/toast-context.js.map +1 -0
- package/dist/rpc/AcceptPicker.cjs +81 -58
- package/dist/rpc/AcceptPicker.cjs.map +1 -1
- package/dist/rpc/AcceptPicker.d.ts.map +1 -1
- package/dist/rpc/AcceptPicker.js +81 -58
- package/dist/rpc/AcceptPicker.js.map +1 -1
- package/dist/rpc/CommandForm.cjs +5 -35
- package/dist/rpc/CommandForm.cjs.map +1 -1
- package/dist/rpc/CommandForm.d.ts +0 -3
- package/dist/rpc/CommandForm.d.ts.map +1 -1
- package/dist/rpc/CommandForm.js +2 -32
- package/dist/rpc/CommandForm.js.map +1 -1
- package/dist/rpc/CommandOutput.cjs +2 -1
- package/dist/rpc/CommandOutput.cjs.map +1 -1
- package/dist/rpc/CommandOutput.d.ts.map +1 -1
- package/dist/rpc/CommandOutput.js +2 -1
- package/dist/rpc/CommandOutput.js.map +1 -1
- package/dist/rpc/EntityExplorerApp.cjs +28 -83
- package/dist/rpc/EntityExplorerApp.cjs.map +1 -1
- package/dist/rpc/EntityExplorerApp.d.ts +1 -4
- package/dist/rpc/EntityExplorerApp.d.ts.map +1 -1
- package/dist/rpc/EntityExplorerApp.js +13 -68
- package/dist/rpc/EntityExplorerApp.js.map +1 -1
- package/dist/rpc/OperationCatalog.cjs +2 -2
- package/dist/rpc/OperationCatalog.cjs.map +1 -1
- package/dist/rpc/OperationCatalog.d.ts +1 -1
- package/dist/rpc/OperationCatalog.d.ts.map +1 -1
- package/dist/rpc/OperationCatalog.js +1 -1
- package/dist/rpc/OperationCatalog.js.map +1 -1
- package/dist/rpc/OperationCommandPage.cjs +6 -4
- package/dist/rpc/OperationCommandPage.cjs.map +1 -1
- package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
- package/dist/rpc/OperationCommandPage.js +3 -1
- package/dist/rpc/OperationCommandPage.js.map +1 -1
- package/dist/rpc/RouterProvider.cjs +10 -0
- package/dist/rpc/RouterProvider.cjs.map +1 -0
- package/dist/rpc/RouterProvider.d.ts +10 -0
- package/dist/rpc/RouterProvider.d.ts.map +1 -0
- package/dist/rpc/RouterProvider.js +10 -0
- package/dist/rpc/RouterProvider.js.map +1 -0
- package/dist/rpc/apiClient.cjs +4 -4
- package/dist/rpc/apiClient.cjs.map +1 -1
- package/dist/rpc/apiClient.js +4 -4
- package/dist/rpc/apiClient.js.map +1 -1
- package/dist/rpc/command-form-utils.cjs +43 -0
- package/dist/rpc/command-form-utils.cjs.map +1 -0
- package/dist/rpc/command-form-utils.d.ts +5 -0
- package/dist/rpc/command-form-utils.d.ts.map +1 -0
- package/dist/rpc/command-form-utils.js +43 -0
- package/dist/rpc/command-form-utils.js.map +1 -0
- package/dist/rpc/commandHref.cjs +62 -0
- package/dist/rpc/commandHref.cjs.map +1 -0
- package/dist/rpc/commandHref.d.ts +7 -0
- package/dist/rpc/commandHref.d.ts.map +1 -0
- package/dist/rpc/commandHref.js +62 -0
- package/dist/rpc/commandHref.js.map +1 -0
- package/dist/rpc/formMetadata.cjs +1 -1
- package/dist/rpc/formMetadata.cjs.map +1 -1
- package/dist/rpc/formMetadata.js +1 -1
- package/dist/rpc/formMetadata.js.map +1 -1
- package/dist/rpc/router.cjs +83 -0
- package/dist/rpc/router.cjs.map +1 -0
- package/dist/rpc/router.d.ts +24 -0
- package/dist/rpc/router.d.ts.map +1 -0
- package/dist/rpc/router.js +83 -0
- package/dist/rpc/router.js.map +1 -0
- package/dist/rpc/rpc-story-fixtures/orders.fixture.d.ts +3 -0
- package/dist/rpc/rpc-story-fixtures/orders.fixture.d.ts.map +1 -0
- package/dist/rpc/rpc-story-fixtures/services.fixture.d.ts +3 -0
- package/dist/rpc/rpc-story-fixtures/services.fixture.d.ts.map +1 -0
- package/dist/rpc/rpc-story-fixtures/surface-fixture.d.ts +24 -0
- package/dist/rpc/rpc-story-fixtures/surface-fixture.d.ts.map +1 -0
- package/dist/rpc/rpc-story-fixtures/widgets.fixture.d.ts +3 -0
- package/dist/rpc/rpc-story-fixtures/widgets.fixture.d.ts.map +1 -0
- package/dist/rpc/rpc-story.fixtures.d.ts +16 -0
- package/dist/rpc/rpc-story.fixtures.d.ts.map +1 -0
- package/dist/rpc.cjs +17 -0
- package/dist/rpc.cjs.map +1 -1
- package/dist/rpc.d.ts +5 -0
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +18 -1
- package/dist/rpc.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +11 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const react = require("react");
|
|
4
|
+
const ChatWindowManagerContext = react.createContext(null);
|
|
5
|
+
function useChatWindowManager() {
|
|
6
|
+
const ctx = react.useContext(ChatWindowManagerContext);
|
|
7
|
+
if (!ctx) throw new Error("useChatWindowManager must be used within <ChatWindowManagerProvider>");
|
|
8
|
+
return ctx;
|
|
9
|
+
}
|
|
10
|
+
const MAX_PANELS = 6;
|
|
11
|
+
const DEFAULT_WIDTH = 520;
|
|
12
|
+
const DEFAULT_HEIGHT = 700;
|
|
13
|
+
const CASCADE_OFFSET = 30;
|
|
14
|
+
const Z_BASE = 61;
|
|
15
|
+
function storageKey(storageId) {
|
|
16
|
+
return `chat-panels:${storageId}`;
|
|
17
|
+
}
|
|
18
|
+
function loadPanels(storageId) {
|
|
19
|
+
if (typeof window === "undefined") return [];
|
|
20
|
+
try {
|
|
21
|
+
const raw = localStorage.getItem(storageKey(storageId));
|
|
22
|
+
if (!raw) return [];
|
|
23
|
+
const persisted = JSON.parse(raw);
|
|
24
|
+
return persisted.map((p, i) => ({
|
|
25
|
+
...p,
|
|
26
|
+
initialModel: null,
|
|
27
|
+
zIndex: Z_BASE + i,
|
|
28
|
+
initialPrompt: null,
|
|
29
|
+
contextItems: []
|
|
30
|
+
}));
|
|
31
|
+
} catch {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function savePanels(storageId, panels) {
|
|
36
|
+
const persisted = panels.map((p) => ({
|
|
37
|
+
id: p.id,
|
|
38
|
+
threadId: p.threadId,
|
|
39
|
+
x: p.x,
|
|
40
|
+
y: p.y,
|
|
41
|
+
width: p.width,
|
|
42
|
+
height: p.height,
|
|
43
|
+
maximized: p.maximized
|
|
44
|
+
}));
|
|
45
|
+
localStorage.setItem(storageKey(storageId), JSON.stringify(persisted));
|
|
46
|
+
}
|
|
47
|
+
let _panelId = 0;
|
|
48
|
+
function nextPanelId() {
|
|
49
|
+
return `panel-${++_panelId}-${Date.now()}`;
|
|
50
|
+
}
|
|
51
|
+
let _promptId = 0;
|
|
52
|
+
function nextPromptId() {
|
|
53
|
+
return ++_promptId;
|
|
54
|
+
}
|
|
55
|
+
function reindex(panels, frontId) {
|
|
56
|
+
const sorted = [...panels].sort((a, b) => a.zIndex - b.zIndex);
|
|
57
|
+
if (frontId) {
|
|
58
|
+
const idx = sorted.findIndex((p) => p.id === frontId);
|
|
59
|
+
if (idx >= 0) {
|
|
60
|
+
const [item] = sorted.splice(idx, 1);
|
|
61
|
+
if (item) sorted.push(item);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return sorted.map((p, i) => ({ ...p, zIndex: Z_BASE + i }));
|
|
65
|
+
}
|
|
66
|
+
exports.CASCADE_OFFSET = CASCADE_OFFSET;
|
|
67
|
+
exports.ChatWindowManagerContext = ChatWindowManagerContext;
|
|
68
|
+
exports.DEFAULT_HEIGHT = DEFAULT_HEIGHT;
|
|
69
|
+
exports.DEFAULT_WIDTH = DEFAULT_WIDTH;
|
|
70
|
+
exports.MAX_PANELS = MAX_PANELS;
|
|
71
|
+
exports.Z_BASE = Z_BASE;
|
|
72
|
+
exports.loadPanels = loadPanels;
|
|
73
|
+
exports.nextPanelId = nextPanelId;
|
|
74
|
+
exports.nextPromptId = nextPromptId;
|
|
75
|
+
exports.reindex = reindex;
|
|
76
|
+
exports.savePanels = savePanels;
|
|
77
|
+
exports.useChatWindowManager = useChatWindowManager;
|
|
78
|
+
//# sourceMappingURL=chat-window-context.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-window-context.cjs","sources":["../../../src/data/ai/chat-window-context.ts"],"sourcesContent":["// Non-component half of the chat window manager: the context object, the hook,\n// id helpers, persistence and layout maths. Split from the Provider (a .tsx\n// component) so this file stays JSX-free — matching the repo idiom of keeping\n// context/hooks in a .ts (see hooks/use-theme.ts, data/test-runner/context.ts)\n// and keeping React-Fast-Refresh happy.\nimport { createContext, useContext } from \"react\";\nimport type { ChatContextItem } from \"./context\";\n\n/** Live state of one floating chat window. Position/size/maximized are\n * persisted to localStorage; the rest is session-only. */\nexport interface ChatWindowState {\n id: string;\n threadId: string | null;\n initialModel: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n zIndex: number;\n maximized: boolean;\n /** A prompt to auto-send when the window mounts (the `id` lets the window\n * detect a fresh request even if the text repeats). */\n initialPrompt: { id: number; text: string } | null;\n contextItems: ChatContextItem[];\n}\n\nexport interface OpenPanelOpts {\n threadId?: string | null;\n initialModel?: string | null;\n initialPrompt?: { id: number; text: string } | null;\n contextItems?: ChatContextItem[];\n}\n\nexport interface ChatWindowManagerValue {\n panels: ChatWindowState[];\n openPanel: (opts?: OpenPanelOpts) => string;\n closePanel: (id: string) => void;\n updatePanel: (id: string, partial: Partial<ChatWindowState>) => void;\n bringToFront: (id: string) => void;\n maximizePanel: (id: string) => void;\n /** Reuses the front-most existing window (merging in any new prompt/context)\n * or opens a fresh one when none exist. */\n findOrCreatePanel: (opts?: OpenPanelOpts) => string;\n}\n\nexport const ChatWindowManagerContext = createContext<ChatWindowManagerValue | null>(null);\n\nexport function useChatWindowManager(): ChatWindowManagerValue {\n const ctx = useContext(ChatWindowManagerContext);\n if (!ctx) throw new Error(\"useChatWindowManager must be used within <ChatWindowManagerProvider>\");\n return ctx;\n}\n\nexport const MAX_PANELS = 6;\nexport const DEFAULT_WIDTH = 520;\nexport const DEFAULT_HEIGHT = 700;\nexport const CASCADE_OFFSET = 30;\nexport const Z_BASE = 61;\n\nfunction storageKey(storageId: string) {\n return `chat-panels:${storageId}`;\n}\n\ninterface PersistedPanel {\n id: string;\n threadId: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n maximized: boolean;\n}\n\nexport function loadPanels(storageId: string): ChatWindowState[] {\n if (typeof window === \"undefined\") return [];\n try {\n const raw = localStorage.getItem(storageKey(storageId));\n if (!raw) return [];\n const persisted: PersistedPanel[] = JSON.parse(raw);\n return persisted.map((p, i) => ({\n ...p,\n initialModel: null,\n zIndex: Z_BASE + i,\n initialPrompt: null,\n contextItems: [],\n }));\n } catch {\n return [];\n }\n}\n\nexport function savePanels(storageId: string, panels: ChatWindowState[]) {\n const persisted: PersistedPanel[] = panels.map((p) => ({\n id: p.id,\n threadId: p.threadId,\n x: p.x,\n y: p.y,\n width: p.width,\n height: p.height,\n maximized: p.maximized,\n }));\n localStorage.setItem(storageKey(storageId), JSON.stringify(persisted));\n}\n\nlet _panelId = 0;\nexport function nextPanelId(): string {\n return `panel-${++_panelId}-${Date.now()}`;\n}\n\nlet _promptId = 0;\n/** A monotonic id stamped onto an `initialPrompt` so a window re-sends even when\n * the same text is requested twice. */\nexport function nextPromptId(): number {\n return ++_promptId;\n}\n\n/** Re-indexes z so values stay compact (61, 62, …) with `frontId` on top. */\nexport function reindex(panels: ChatWindowState[], frontId?: string): ChatWindowState[] {\n const sorted = [...panels].sort((a, b) => a.zIndex - b.zIndex);\n if (frontId) {\n const idx = sorted.findIndex((p) => p.id === frontId);\n if (idx >= 0) {\n const [item] = sorted.splice(idx, 1);\n if (item) sorted.push(item);\n }\n }\n return sorted.map((p, i) => ({ ...p, zIndex: Z_BASE + i }));\n}\n"],"names":["createContext","useContext"],"mappings":";;;AA6CO,MAAM,2BAA2BA,MAAAA,cAA6C,IAAI;AAElF,SAAS,uBAA+C;AAC7D,QAAM,MAAMC,MAAAA,WAAW,wBAAwB;AAC/C,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sEAAsE;AAChG,SAAO;AACT;AAEO,MAAM,aAAa;AACnB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,SAAS;AAEtB,SAAS,WAAW,WAAmB;AACrC,SAAO,eAAe,SAAS;AACjC;AAYO,SAAS,WAAW,WAAsC;AAC/D,MAAI,OAAO,WAAW,YAAa,QAAO,CAAA;AAC1C,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,WAAW,SAAS,CAAC;AACtD,QAAI,CAAC,IAAK,QAAO,CAAA;AACjB,UAAM,YAA8B,KAAK,MAAM,GAAG;AAClD,WAAO,UAAU,IAAI,CAAC,GAAG,OAAO;AAAA,MAC9B,GAAG;AAAA,MACH,cAAc;AAAA,MACd,QAAQ,SAAS;AAAA,MACjB,eAAe;AAAA,MACf,cAAc,CAAA;AAAA,IAAC,EACf;AAAA,EACJ,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AACF;AAEO,SAAS,WAAW,WAAmB,QAA2B;AACvE,QAAM,YAA8B,OAAO,IAAI,CAAC,OAAO;AAAA,IACrD,IAAI,EAAE;AAAA,IACN,UAAU,EAAE;AAAA,IACZ,GAAG,EAAE;AAAA,IACL,GAAG,EAAE;AAAA,IACL,OAAO,EAAE;AAAA,IACT,QAAQ,EAAE;AAAA,IACV,WAAW,EAAE;AAAA,EAAA,EACb;AACF,eAAa,QAAQ,WAAW,SAAS,GAAG,KAAK,UAAU,SAAS,CAAC;AACvE;AAEA,IAAI,WAAW;AACR,SAAS,cAAsB;AACpC,SAAO,SAAS,EAAE,QAAQ,IAAI,KAAK,KAAK;AAC1C;AAEA,IAAI,YAAY;AAGT,SAAS,eAAuB;AACrC,SAAO,EAAE;AACX;AAGO,SAAS,QAAQ,QAA2B,SAAqC;AACtF,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC7D,MAAI,SAAS;AACX,UAAM,MAAM,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO;AACpD,QAAI,OAAO,GAAG;AACZ,YAAM,CAAC,IAAI,IAAI,OAAO,OAAO,KAAK,CAAC;AACnC,UAAI,KAAM,QAAO,KAAK,IAAI;AAAA,IAC5B;AAAA,EACF;AACA,SAAO,OAAO,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,QAAQ,SAAS,EAAA,EAAI;AAC5D;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ChatContextItem } from './context';
|
|
2
|
+
/** Live state of one floating chat window. Position/size/maximized are
|
|
3
|
+
* persisted to localStorage; the rest is session-only. */
|
|
4
|
+
export interface ChatWindowState {
|
|
5
|
+
id: string;
|
|
6
|
+
threadId: string | null;
|
|
7
|
+
initialModel: string | null;
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
zIndex: number;
|
|
13
|
+
maximized: boolean;
|
|
14
|
+
/** A prompt to auto-send when the window mounts (the `id` lets the window
|
|
15
|
+
* detect a fresh request even if the text repeats). */
|
|
16
|
+
initialPrompt: {
|
|
17
|
+
id: number;
|
|
18
|
+
text: string;
|
|
19
|
+
} | null;
|
|
20
|
+
contextItems: ChatContextItem[];
|
|
21
|
+
}
|
|
22
|
+
export interface OpenPanelOpts {
|
|
23
|
+
threadId?: string | null;
|
|
24
|
+
initialModel?: string | null;
|
|
25
|
+
initialPrompt?: {
|
|
26
|
+
id: number;
|
|
27
|
+
text: string;
|
|
28
|
+
} | null;
|
|
29
|
+
contextItems?: ChatContextItem[];
|
|
30
|
+
}
|
|
31
|
+
export interface ChatWindowManagerValue {
|
|
32
|
+
panels: ChatWindowState[];
|
|
33
|
+
openPanel: (opts?: OpenPanelOpts) => string;
|
|
34
|
+
closePanel: (id: string) => void;
|
|
35
|
+
updatePanel: (id: string, partial: Partial<ChatWindowState>) => void;
|
|
36
|
+
bringToFront: (id: string) => void;
|
|
37
|
+
maximizePanel: (id: string) => void;
|
|
38
|
+
/** Reuses the front-most existing window (merging in any new prompt/context)
|
|
39
|
+
* or opens a fresh one when none exist. */
|
|
40
|
+
findOrCreatePanel: (opts?: OpenPanelOpts) => string;
|
|
41
|
+
}
|
|
42
|
+
export declare const ChatWindowManagerContext: import('react').Context<ChatWindowManagerValue | null>;
|
|
43
|
+
export declare function useChatWindowManager(): ChatWindowManagerValue;
|
|
44
|
+
export declare const MAX_PANELS = 6;
|
|
45
|
+
export declare const DEFAULT_WIDTH = 520;
|
|
46
|
+
export declare const DEFAULT_HEIGHT = 700;
|
|
47
|
+
export declare const CASCADE_OFFSET = 30;
|
|
48
|
+
export declare const Z_BASE = 61;
|
|
49
|
+
export declare function loadPanels(storageId: string): ChatWindowState[];
|
|
50
|
+
export declare function savePanels(storageId: string, panels: ChatWindowState[]): void;
|
|
51
|
+
export declare function nextPanelId(): string;
|
|
52
|
+
/** A monotonic id stamped onto an `initialPrompt` so a window re-sends even when
|
|
53
|
+
* the same text is requested twice. */
|
|
54
|
+
export declare function nextPromptId(): number;
|
|
55
|
+
/** Re-indexes z so values stay compact (61, 62, …) with `frontId` on top. */
|
|
56
|
+
export declare function reindex(panels: ChatWindowState[], frontId?: string): ChatWindowState[];
|
|
57
|
+
//# sourceMappingURL=chat-window-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-window-context.d.ts","sourceRoot":"","sources":["../../../src/data/ai/chat-window-context.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD;2DAC2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB;4DACwD;IACxD,aAAa,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnD,YAAY,EAAE,eAAe,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD,YAAY,CAAC,EAAE,eAAe,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,aAAa,KAAK,MAAM,CAAC;IAC5C,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;IACrE,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC;gDAC4C;IAC5C,iBAAiB,EAAE,CAAC,IAAI,CAAC,EAAE,aAAa,KAAK,MAAM,CAAC;CACrD;AAED,eAAO,MAAM,wBAAwB,wDAAqD,CAAC;AAE3F,wBAAgB,oBAAoB,IAAI,sBAAsB,CAI7D;AAED,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,MAAM,KAAK,CAAC;AAgBzB,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAgB/D;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,QAWtE;AAGD,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAGD;wCACwC;AACxC,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE,CAUtF"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { useContext, createContext } from "react";
|
|
2
|
+
const ChatWindowManagerContext = createContext(null);
|
|
3
|
+
function useChatWindowManager() {
|
|
4
|
+
const ctx = useContext(ChatWindowManagerContext);
|
|
5
|
+
if (!ctx) throw new Error("useChatWindowManager must be used within <ChatWindowManagerProvider>");
|
|
6
|
+
return ctx;
|
|
7
|
+
}
|
|
8
|
+
const MAX_PANELS = 6;
|
|
9
|
+
const DEFAULT_WIDTH = 520;
|
|
10
|
+
const DEFAULT_HEIGHT = 700;
|
|
11
|
+
const CASCADE_OFFSET = 30;
|
|
12
|
+
const Z_BASE = 61;
|
|
13
|
+
function storageKey(storageId) {
|
|
14
|
+
return `chat-panels:${storageId}`;
|
|
15
|
+
}
|
|
16
|
+
function loadPanels(storageId) {
|
|
17
|
+
if (typeof window === "undefined") return [];
|
|
18
|
+
try {
|
|
19
|
+
const raw = localStorage.getItem(storageKey(storageId));
|
|
20
|
+
if (!raw) return [];
|
|
21
|
+
const persisted = JSON.parse(raw);
|
|
22
|
+
return persisted.map((p, i) => ({
|
|
23
|
+
...p,
|
|
24
|
+
initialModel: null,
|
|
25
|
+
zIndex: Z_BASE + i,
|
|
26
|
+
initialPrompt: null,
|
|
27
|
+
contextItems: []
|
|
28
|
+
}));
|
|
29
|
+
} catch {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function savePanels(storageId, panels) {
|
|
34
|
+
const persisted = panels.map((p) => ({
|
|
35
|
+
id: p.id,
|
|
36
|
+
threadId: p.threadId,
|
|
37
|
+
x: p.x,
|
|
38
|
+
y: p.y,
|
|
39
|
+
width: p.width,
|
|
40
|
+
height: p.height,
|
|
41
|
+
maximized: p.maximized
|
|
42
|
+
}));
|
|
43
|
+
localStorage.setItem(storageKey(storageId), JSON.stringify(persisted));
|
|
44
|
+
}
|
|
45
|
+
let _panelId = 0;
|
|
46
|
+
function nextPanelId() {
|
|
47
|
+
return `panel-${++_panelId}-${Date.now()}`;
|
|
48
|
+
}
|
|
49
|
+
let _promptId = 0;
|
|
50
|
+
function nextPromptId() {
|
|
51
|
+
return ++_promptId;
|
|
52
|
+
}
|
|
53
|
+
function reindex(panels, frontId) {
|
|
54
|
+
const sorted = [...panels].sort((a, b) => a.zIndex - b.zIndex);
|
|
55
|
+
if (frontId) {
|
|
56
|
+
const idx = sorted.findIndex((p) => p.id === frontId);
|
|
57
|
+
if (idx >= 0) {
|
|
58
|
+
const [item] = sorted.splice(idx, 1);
|
|
59
|
+
if (item) sorted.push(item);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return sorted.map((p, i) => ({ ...p, zIndex: Z_BASE + i }));
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
CASCADE_OFFSET,
|
|
66
|
+
ChatWindowManagerContext,
|
|
67
|
+
DEFAULT_HEIGHT,
|
|
68
|
+
DEFAULT_WIDTH,
|
|
69
|
+
MAX_PANELS,
|
|
70
|
+
Z_BASE,
|
|
71
|
+
loadPanels,
|
|
72
|
+
nextPanelId,
|
|
73
|
+
nextPromptId,
|
|
74
|
+
reindex,
|
|
75
|
+
savePanels,
|
|
76
|
+
useChatWindowManager
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=chat-window-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-window-context.js","sources":["../../../src/data/ai/chat-window-context.ts"],"sourcesContent":["// Non-component half of the chat window manager: the context object, the hook,\n// id helpers, persistence and layout maths. Split from the Provider (a .tsx\n// component) so this file stays JSX-free — matching the repo idiom of keeping\n// context/hooks in a .ts (see hooks/use-theme.ts, data/test-runner/context.ts)\n// and keeping React-Fast-Refresh happy.\nimport { createContext, useContext } from \"react\";\nimport type { ChatContextItem } from \"./context\";\n\n/** Live state of one floating chat window. Position/size/maximized are\n * persisted to localStorage; the rest is session-only. */\nexport interface ChatWindowState {\n id: string;\n threadId: string | null;\n initialModel: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n zIndex: number;\n maximized: boolean;\n /** A prompt to auto-send when the window mounts (the `id` lets the window\n * detect a fresh request even if the text repeats). */\n initialPrompt: { id: number; text: string } | null;\n contextItems: ChatContextItem[];\n}\n\nexport interface OpenPanelOpts {\n threadId?: string | null;\n initialModel?: string | null;\n initialPrompt?: { id: number; text: string } | null;\n contextItems?: ChatContextItem[];\n}\n\nexport interface ChatWindowManagerValue {\n panels: ChatWindowState[];\n openPanel: (opts?: OpenPanelOpts) => string;\n closePanel: (id: string) => void;\n updatePanel: (id: string, partial: Partial<ChatWindowState>) => void;\n bringToFront: (id: string) => void;\n maximizePanel: (id: string) => void;\n /** Reuses the front-most existing window (merging in any new prompt/context)\n * or opens a fresh one when none exist. */\n findOrCreatePanel: (opts?: OpenPanelOpts) => string;\n}\n\nexport const ChatWindowManagerContext = createContext<ChatWindowManagerValue | null>(null);\n\nexport function useChatWindowManager(): ChatWindowManagerValue {\n const ctx = useContext(ChatWindowManagerContext);\n if (!ctx) throw new Error(\"useChatWindowManager must be used within <ChatWindowManagerProvider>\");\n return ctx;\n}\n\nexport const MAX_PANELS = 6;\nexport const DEFAULT_WIDTH = 520;\nexport const DEFAULT_HEIGHT = 700;\nexport const CASCADE_OFFSET = 30;\nexport const Z_BASE = 61;\n\nfunction storageKey(storageId: string) {\n return `chat-panels:${storageId}`;\n}\n\ninterface PersistedPanel {\n id: string;\n threadId: string | null;\n x: number;\n y: number;\n width: number;\n height: number;\n maximized: boolean;\n}\n\nexport function loadPanels(storageId: string): ChatWindowState[] {\n if (typeof window === \"undefined\") return [];\n try {\n const raw = localStorage.getItem(storageKey(storageId));\n if (!raw) return [];\n const persisted: PersistedPanel[] = JSON.parse(raw);\n return persisted.map((p, i) => ({\n ...p,\n initialModel: null,\n zIndex: Z_BASE + i,\n initialPrompt: null,\n contextItems: [],\n }));\n } catch {\n return [];\n }\n}\n\nexport function savePanels(storageId: string, panels: ChatWindowState[]) {\n const persisted: PersistedPanel[] = panels.map((p) => ({\n id: p.id,\n threadId: p.threadId,\n x: p.x,\n y: p.y,\n width: p.width,\n height: p.height,\n maximized: p.maximized,\n }));\n localStorage.setItem(storageKey(storageId), JSON.stringify(persisted));\n}\n\nlet _panelId = 0;\nexport function nextPanelId(): string {\n return `panel-${++_panelId}-${Date.now()}`;\n}\n\nlet _promptId = 0;\n/** A monotonic id stamped onto an `initialPrompt` so a window re-sends even when\n * the same text is requested twice. */\nexport function nextPromptId(): number {\n return ++_promptId;\n}\n\n/** Re-indexes z so values stay compact (61, 62, …) with `frontId` on top. */\nexport function reindex(panels: ChatWindowState[], frontId?: string): ChatWindowState[] {\n const sorted = [...panels].sort((a, b) => a.zIndex - b.zIndex);\n if (frontId) {\n const idx = sorted.findIndex((p) => p.id === frontId);\n if (idx >= 0) {\n const [item] = sorted.splice(idx, 1);\n if (item) sorted.push(item);\n }\n }\n return sorted.map((p, i) => ({ ...p, zIndex: Z_BASE + i }));\n}\n"],"names":[],"mappings":";AA6CO,MAAM,2BAA2B,cAA6C,IAAI;AAElF,SAAS,uBAA+C;AAC7D,QAAM,MAAM,WAAW,wBAAwB;AAC/C,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,sEAAsE;AAChG,SAAO;AACT;AAEO,MAAM,aAAa;AACnB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,SAAS;AAEtB,SAAS,WAAW,WAAmB;AACrC,SAAO,eAAe,SAAS;AACjC;AAYO,SAAS,WAAW,WAAsC;AAC/D,MAAI,OAAO,WAAW,YAAa,QAAO,CAAA;AAC1C,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,WAAW,SAAS,CAAC;AACtD,QAAI,CAAC,IAAK,QAAO,CAAA;AACjB,UAAM,YAA8B,KAAK,MAAM,GAAG;AAClD,WAAO,UAAU,IAAI,CAAC,GAAG,OAAO;AAAA,MAC9B,GAAG;AAAA,MACH,cAAc;AAAA,MACd,QAAQ,SAAS;AAAA,MACjB,eAAe;AAAA,MACf,cAAc,CAAA;AAAA,IAAC,EACf;AAAA,EACJ,QAAQ;AACN,WAAO,CAAA;AAAA,EACT;AACF;AAEO,SAAS,WAAW,WAAmB,QAA2B;AACvE,QAAM,YAA8B,OAAO,IAAI,CAAC,OAAO;AAAA,IACrD,IAAI,EAAE;AAAA,IACN,UAAU,EAAE;AAAA,IACZ,GAAG,EAAE;AAAA,IACL,GAAG,EAAE;AAAA,IACL,OAAO,EAAE;AAAA,IACT,QAAQ,EAAE;AAAA,IACV,WAAW,EAAE;AAAA,EAAA,EACb;AACF,eAAa,QAAQ,WAAW,SAAS,GAAG,KAAK,UAAU,SAAS,CAAC;AACvE;AAEA,IAAI,WAAW;AACR,SAAS,cAAsB;AACpC,SAAO,SAAS,EAAE,QAAQ,IAAI,KAAK,KAAK;AAC1C;AAEA,IAAI,YAAY;AAGT,SAAS,eAAuB;AACrC,SAAO,EAAE;AACX;AAGO,SAAS,QAAQ,QAA2B,SAAqC;AACtF,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC7D,MAAI,SAAS;AACX,UAAM,MAAM,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO;AACpD,QAAI,OAAO,GAAG;AACZ,YAAM,CAAC,IAAI,IAAI,OAAO,OAAO,KAAK,CAAC;AACnC,UAAI,KAAM,QAAO,KAAK,IAAI;AAAA,IAC5B;AAAA,EACF;AACA,SAAO,OAAO,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,QAAQ,SAAS,EAAA,EAAI;AAC5D;"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
function serializeContext(items) {
|
|
4
|
+
if (items.length === 0) return "";
|
|
5
|
+
const lines = items.map((item) => {
|
|
6
|
+
const entries = Object.entries(item.fields ?? {}).filter(([, v]) => v != null && v !== "").map(([k, v]) => `${k}: ${v}`).join(", ");
|
|
7
|
+
return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;
|
|
8
|
+
});
|
|
9
|
+
return `Context:
|
|
10
|
+
${lines.join("\n")}
|
|
11
|
+
|
|
12
|
+
`;
|
|
13
|
+
}
|
|
14
|
+
const CONTEXT_LINE_RE = /^\[([^\]]+)\]\s+(.+?)(?:\s+\((.+)\))?$/;
|
|
15
|
+
function parseContextPrefix(text) {
|
|
16
|
+
if (!text.startsWith("Context:\n")) return { items: [], question: text };
|
|
17
|
+
const blockEnd = text.indexOf("\n\n");
|
|
18
|
+
if (blockEnd === -1) return { items: [], question: text };
|
|
19
|
+
const block = text.slice("Context:\n".length, blockEnd);
|
|
20
|
+
const question = text.slice(blockEnd + 2);
|
|
21
|
+
const items = [];
|
|
22
|
+
for (const line of block.split("\n")) {
|
|
23
|
+
const m = line.match(CONTEXT_LINE_RE);
|
|
24
|
+
if (!m) continue;
|
|
25
|
+
const fields = {};
|
|
26
|
+
if (m[3]) {
|
|
27
|
+
for (const pair of m[3].split(/,\s*(?=[A-Za-z0-9_]+:)/)) {
|
|
28
|
+
const idx = pair.indexOf(":");
|
|
29
|
+
if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
items.push({ id: `parsed-${items.length}`, type: m[1], label: m[2], fields });
|
|
33
|
+
}
|
|
34
|
+
return { items, question };
|
|
35
|
+
}
|
|
36
|
+
let nextId = 0;
|
|
37
|
+
function makeContextId() {
|
|
38
|
+
return `ctx-${++nextId}-${Date.now()}`;
|
|
39
|
+
}
|
|
40
|
+
exports.makeContextId = makeContextId;
|
|
41
|
+
exports.parseContextPrefix = parseContextPrefix;
|
|
42
|
+
exports.serializeContext = serializeContext;
|
|
43
|
+
//# sourceMappingURL=context.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.cjs","sources":["../../../src/data/ai/context.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\n\n/** A piece of context the user has attached to a chat (a record, a selection,\n * a document…). The `type` is an arbitrary caller-defined string; a\n * {@link ContextTypeConfig} maps it to an icon/colour for display. `fields`\n * are flat key/value details serialized into the prompt and rendered as a\n * compact suffix on the badge. */\nexport interface ChatContextItem {\n id: string;\n type: string;\n label: string;\n fields?: Record<string, string>;\n}\n\n/** Per-type display style for context badges, keyed by `ChatContextItem.type`. */\nexport interface ContextTypeStyle {\n /** Iconify name or an imported icon component. */\n icon?: string | StaticIconComponent;\n /** Tailwind classes for the badge (text + background colour). */\n className?: string;\n}\n\nexport type ContextTypeConfig = Record<string, ContextTypeStyle>;\n\n/** Serializes attached context into a `Context:` block the backend can prepend\n * to (or read alongside) the user's message. Mirrors the format parsed by\n * {@link parseContextPrefix}: `[type] label (k: v, k: v)`. Returns \"\" when\n * there is nothing attached. */\nexport function serializeContext(items: ChatContextItem[]): string {\n if (items.length === 0) return \"\";\n const lines = items.map((item) => {\n const entries = Object.entries(item.fields ?? {})\n .filter(([, v]) => v != null && v !== \"\")\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;\n });\n return `Context:\\n${lines.join(\"\\n\")}\\n\\n`;\n}\n\nconst CONTEXT_LINE_RE = /^\\[([^\\]]+)\\]\\s+(.+?)(?:\\s+\\((.+)\\))?$/;\n\n/** Splits a message produced with a {@link serializeContext} prefix back into\n * its attached items and the bare question. When no prefix is present the\n * whole text is returned as the question with no items. */\nexport function parseContextPrefix(text: string): { items: ChatContextItem[]; question: string } {\n if (!text.startsWith(\"Context:\\n\")) return { items: [], question: text };\n const blockEnd = text.indexOf(\"\\n\\n\");\n if (blockEnd === -1) return { items: [], question: text };\n const block = text.slice(\"Context:\\n\".length, blockEnd);\n const question = text.slice(blockEnd + 2);\n const items: ChatContextItem[] = [];\n for (const line of block.split(\"\\n\")) {\n const m = line.match(CONTEXT_LINE_RE);\n if (!m) continue;\n const fields: Record<string, string> = {};\n if (m[3]) {\n for (const pair of m[3].split(/,\\s*(?=[A-Za-z0-9_]+:)/)) {\n const idx = pair.indexOf(\":\");\n if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();\n }\n }\n items.push({ id: `parsed-${items.length}`, type: m[1]!, label: m[2]!, fields });\n }\n return { items, question };\n}\n\nlet nextId = 0;\n/** A process-unique id for a newly attached context item. */\nexport function makeContextId(): string {\n return `ctx-${++nextId}-${Date.now()}`;\n}\n"],"names":[],"mappings":";;AA4BO,SAAS,iBAAiB,OAAkC;AACjE,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,QAAQ,MAAM,IAAI,CAAC,SAAS;AAChC,UAAM,UAAU,OAAO,QAAQ,KAAK,UAAU,CAAA,CAAE,EAC7C,OAAO,CAAC,CAAA,EAAG,CAAC,MAAM,KAAK,QAAQ,MAAM,EAAE,EACvC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,EAC5B,KAAK,IAAI;AACZ,WAAO,UAAU,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,OAAO,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,EAC7F,CAAC;AACD,SAAO;AAAA,EAAa,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA;AACtC;AAEA,MAAM,kBAAkB;AAKjB,SAAS,mBAAmB,MAA8D;AAC/F,MAAI,CAAC,KAAK,WAAW,YAAY,EAAG,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AAClE,QAAM,WAAW,KAAK,QAAQ,MAAM;AACpC,MAAI,aAAa,GAAI,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AACnD,QAAM,QAAQ,KAAK,MAAM,aAAa,QAAQ,QAAQ;AACtD,QAAM,WAAW,KAAK,MAAM,WAAW,CAAC;AACxC,QAAM,QAA2B,CAAA;AACjC,aAAW,QAAQ,MAAM,MAAM,IAAI,GAAG;AACpC,UAAM,IAAI,KAAK,MAAM,eAAe;AACpC,QAAI,CAAC,EAAG;AACR,UAAM,SAAiC,CAAA;AACvC,QAAI,EAAE,CAAC,GAAG;AACR,iBAAW,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,GAAG;AACvD,cAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,YAAI,MAAM,EAAG,QAAO,KAAK,MAAM,GAAG,GAAG,EAAE,KAAA,CAAM,IAAI,KAAK,MAAM,MAAM,CAAC,EAAE,KAAA;AAAA,MACvE;AAAA,IACF;AACA,UAAM,KAAK,EAAE,IAAI,UAAU,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC,GAAI,OAAO,EAAE,CAAC,GAAI,QAAQ;AAAA,EAChF;AACA,SAAO,EAAE,OAAO,SAAA;AAClB;AAEA,IAAI,SAAS;AAEN,SAAS,gBAAwB;AACtC,SAAO,OAAO,EAAE,MAAM,IAAI,KAAK,KAAK;AACtC;;;;"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { StaticIconComponent } from '../Icon';
|
|
2
|
+
/** A piece of context the user has attached to a chat (a record, a selection,
|
|
3
|
+
* a document…). The `type` is an arbitrary caller-defined string; a
|
|
4
|
+
* {@link ContextTypeConfig} maps it to an icon/colour for display. `fields`
|
|
5
|
+
* are flat key/value details serialized into the prompt and rendered as a
|
|
6
|
+
* compact suffix on the badge. */
|
|
7
|
+
export interface ChatContextItem {
|
|
8
|
+
id: string;
|
|
9
|
+
type: string;
|
|
10
|
+
label: string;
|
|
11
|
+
fields?: Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
/** Per-type display style for context badges, keyed by `ChatContextItem.type`. */
|
|
14
|
+
export interface ContextTypeStyle {
|
|
15
|
+
/** Iconify name or an imported icon component. */
|
|
16
|
+
icon?: string | StaticIconComponent;
|
|
17
|
+
/** Tailwind classes for the badge (text + background colour). */
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
export type ContextTypeConfig = Record<string, ContextTypeStyle>;
|
|
21
|
+
/** Serializes attached context into a `Context:` block the backend can prepend
|
|
22
|
+
* to (or read alongside) the user's message. Mirrors the format parsed by
|
|
23
|
+
* {@link parseContextPrefix}: `[type] label (k: v, k: v)`. Returns "" when
|
|
24
|
+
* there is nothing attached. */
|
|
25
|
+
export declare function serializeContext(items: ChatContextItem[]): string;
|
|
26
|
+
/** Splits a message produced with a {@link serializeContext} prefix back into
|
|
27
|
+
* its attached items and the bare question. When no prefix is present the
|
|
28
|
+
* whole text is returned as the question with no items. */
|
|
29
|
+
export declare function parseContextPrefix(text: string): {
|
|
30
|
+
items: ChatContextItem[];
|
|
31
|
+
question: string;
|
|
32
|
+
};
|
|
33
|
+
/** A process-unique id for a newly attached context item. */
|
|
34
|
+
export declare function makeContextId(): string;
|
|
35
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/data/ai/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD;;;;mCAImC;AACnC,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACpC,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAEjE;;;iCAGiC;AACjC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,MAAM,CAUjE;AAID;;4DAE4D;AAC5D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,eAAe,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAoB/F;AAGD,6DAA6D;AAC7D,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
function serializeContext(items) {
|
|
2
|
+
if (items.length === 0) return "";
|
|
3
|
+
const lines = items.map((item) => {
|
|
4
|
+
const entries = Object.entries(item.fields ?? {}).filter(([, v]) => v != null && v !== "").map(([k, v]) => `${k}: ${v}`).join(", ");
|
|
5
|
+
return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;
|
|
6
|
+
});
|
|
7
|
+
return `Context:
|
|
8
|
+
${lines.join("\n")}
|
|
9
|
+
|
|
10
|
+
`;
|
|
11
|
+
}
|
|
12
|
+
const CONTEXT_LINE_RE = /^\[([^\]]+)\]\s+(.+?)(?:\s+\((.+)\))?$/;
|
|
13
|
+
function parseContextPrefix(text) {
|
|
14
|
+
if (!text.startsWith("Context:\n")) return { items: [], question: text };
|
|
15
|
+
const blockEnd = text.indexOf("\n\n");
|
|
16
|
+
if (blockEnd === -1) return { items: [], question: text };
|
|
17
|
+
const block = text.slice("Context:\n".length, blockEnd);
|
|
18
|
+
const question = text.slice(blockEnd + 2);
|
|
19
|
+
const items = [];
|
|
20
|
+
for (const line of block.split("\n")) {
|
|
21
|
+
const m = line.match(CONTEXT_LINE_RE);
|
|
22
|
+
if (!m) continue;
|
|
23
|
+
const fields = {};
|
|
24
|
+
if (m[3]) {
|
|
25
|
+
for (const pair of m[3].split(/,\s*(?=[A-Za-z0-9_]+:)/)) {
|
|
26
|
+
const idx = pair.indexOf(":");
|
|
27
|
+
if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
items.push({ id: `parsed-${items.length}`, type: m[1], label: m[2], fields });
|
|
31
|
+
}
|
|
32
|
+
return { items, question };
|
|
33
|
+
}
|
|
34
|
+
let nextId = 0;
|
|
35
|
+
function makeContextId() {
|
|
36
|
+
return `ctx-${++nextId}-${Date.now()}`;
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
makeContextId,
|
|
40
|
+
parseContextPrefix,
|
|
41
|
+
serializeContext
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sources":["../../../src/data/ai/context.ts"],"sourcesContent":["import type { StaticIconComponent } from \"../Icon\";\n\n/** A piece of context the user has attached to a chat (a record, a selection,\n * a document…). The `type` is an arbitrary caller-defined string; a\n * {@link ContextTypeConfig} maps it to an icon/colour for display. `fields`\n * are flat key/value details serialized into the prompt and rendered as a\n * compact suffix on the badge. */\nexport interface ChatContextItem {\n id: string;\n type: string;\n label: string;\n fields?: Record<string, string>;\n}\n\n/** Per-type display style for context badges, keyed by `ChatContextItem.type`. */\nexport interface ContextTypeStyle {\n /** Iconify name or an imported icon component. */\n icon?: string | StaticIconComponent;\n /** Tailwind classes for the badge (text + background colour). */\n className?: string;\n}\n\nexport type ContextTypeConfig = Record<string, ContextTypeStyle>;\n\n/** Serializes attached context into a `Context:` block the backend can prepend\n * to (or read alongside) the user's message. Mirrors the format parsed by\n * {@link parseContextPrefix}: `[type] label (k: v, k: v)`. Returns \"\" when\n * there is nothing attached. */\nexport function serializeContext(items: ChatContextItem[]): string {\n if (items.length === 0) return \"\";\n const lines = items.map((item) => {\n const entries = Object.entries(item.fields ?? {})\n .filter(([, v]) => v != null && v !== \"\")\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n return entries ? `[${item.type}] ${item.label} (${entries})` : `[${item.type}] ${item.label}`;\n });\n return `Context:\\n${lines.join(\"\\n\")}\\n\\n`;\n}\n\nconst CONTEXT_LINE_RE = /^\\[([^\\]]+)\\]\\s+(.+?)(?:\\s+\\((.+)\\))?$/;\n\n/** Splits a message produced with a {@link serializeContext} prefix back into\n * its attached items and the bare question. When no prefix is present the\n * whole text is returned as the question with no items. */\nexport function parseContextPrefix(text: string): { items: ChatContextItem[]; question: string } {\n if (!text.startsWith(\"Context:\\n\")) return { items: [], question: text };\n const blockEnd = text.indexOf(\"\\n\\n\");\n if (blockEnd === -1) return { items: [], question: text };\n const block = text.slice(\"Context:\\n\".length, blockEnd);\n const question = text.slice(blockEnd + 2);\n const items: ChatContextItem[] = [];\n for (const line of block.split(\"\\n\")) {\n const m = line.match(CONTEXT_LINE_RE);\n if (!m) continue;\n const fields: Record<string, string> = {};\n if (m[3]) {\n for (const pair of m[3].split(/,\\s*(?=[A-Za-z0-9_]+:)/)) {\n const idx = pair.indexOf(\":\");\n if (idx > 0) fields[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();\n }\n }\n items.push({ id: `parsed-${items.length}`, type: m[1]!, label: m[2]!, fields });\n }\n return { items, question };\n}\n\nlet nextId = 0;\n/** A process-unique id for a newly attached context item. */\nexport function makeContextId(): string {\n return `ctx-${++nextId}-${Date.now()}`;\n}\n"],"names":[],"mappings":"AA4BO,SAAS,iBAAiB,OAAkC;AACjE,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,QAAQ,MAAM,IAAI,CAAC,SAAS;AAChC,UAAM,UAAU,OAAO,QAAQ,KAAK,UAAU,CAAA,CAAE,EAC7C,OAAO,CAAC,CAAA,EAAG,CAAC,MAAM,KAAK,QAAQ,MAAM,EAAE,EACvC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,EAC5B,KAAK,IAAI;AACZ,WAAO,UAAU,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,KAAK,OAAO,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,EAC7F,CAAC;AACD,SAAO;AAAA,EAAa,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA;AACtC;AAEA,MAAM,kBAAkB;AAKjB,SAAS,mBAAmB,MAA8D;AAC/F,MAAI,CAAC,KAAK,WAAW,YAAY,EAAG,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AAClE,QAAM,WAAW,KAAK,QAAQ,MAAM;AACpC,MAAI,aAAa,GAAI,QAAO,EAAE,OAAO,CAAA,GAAI,UAAU,KAAA;AACnD,QAAM,QAAQ,KAAK,MAAM,aAAa,QAAQ,QAAQ;AACtD,QAAM,WAAW,KAAK,MAAM,WAAW,CAAC;AACxC,QAAM,QAA2B,CAAA;AACjC,aAAW,QAAQ,MAAM,MAAM,IAAI,GAAG;AACpC,UAAM,IAAI,KAAK,MAAM,eAAe;AACpC,QAAI,CAAC,EAAG;AACR,UAAM,SAAiC,CAAA;AACvC,QAAI,EAAE,CAAC,GAAG;AACR,iBAAW,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,GAAG;AACvD,cAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,YAAI,MAAM,EAAG,QAAO,KAAK,MAAM,GAAG,GAAG,EAAE,KAAA,CAAM,IAAI,KAAK,MAAM,MAAM,CAAC,EAAE,KAAA;AAAA,MACvE;AAAA,IACF;AACA,UAAM,KAAK,EAAE,IAAI,UAAU,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC,GAAI,OAAO,EAAE,CAAC,GAAI,QAAQ;AAAA,EAChF;AACA,SAAO,EAAE,OAAO,SAAA;AAClB;AAEA,IAAI,SAAS;AAEN,SAAS,gBAAwB;AACtC,SAAO,OAAO,EAAE,MAAM,IAAI,KAAK,KAAK;AACtC;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { ChatWindowManagerProvider, type ChatWindowManagerProviderProps, } from './ChatWindowManager';
|
|
2
|
+
export { useChatWindowManager, nextPromptId, type ChatWindowManagerValue, type ChatWindowState, type OpenPanelOpts, } from './chat-window-context';
|
|
3
|
+
export { ChatWindow, ChatWindowLayer, type ChatWindowProps } from './ChatWindow';
|
|
4
|
+
export { ChatFab, type ChatFabProps } from './ChatFab';
|
|
5
|
+
export { ThreadPicker, type ThreadPickerProps, type ThreadSummary, type ThreadSource, } from './ThreadPicker';
|
|
6
|
+
export { ContextBadges, ContextBadgesReadonly, type ContextBadgesProps, } from './ContextBadges';
|
|
7
|
+
export { ToolPreferences, type ToolPreferencesProps, type ToolMeta, type ToolMode, } from './ToolPreferences';
|
|
8
|
+
export { ContextUsage, type ContextUsageProps } from '../chat/ContextUsage';
|
|
9
|
+
export { serializeContext, parseContextPrefix, makeContextId, type ChatContextItem, type ContextTypeConfig, type ContextTypeStyle, } from './context';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/data/ai/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,yBAAyB,EACzB,KAAK,8BAA8B,GACpC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,KAAK,sBAAsB,EAC3B,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EACL,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EACb,KAAK,QAAQ,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE5E,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,WAAW,CAAC"}
|
|
@@ -12,8 +12,10 @@ const Section = require("../../layout/Section.cjs");
|
|
|
12
12
|
const api = require("./api.cjs");
|
|
13
13
|
const CacheValue = require("./CacheValue.cjs");
|
|
14
14
|
const types = require("./types.cjs");
|
|
15
|
+
const download = require("./download.cjs");
|
|
15
16
|
const UiFolder = require("../../icons/components/UiFolder.cjs");
|
|
16
17
|
const UiRefresh = require("../../icons/components/UiRefresh.cjs");
|
|
18
|
+
const UiDownload = require("../../icons/components/UiDownload.cjs");
|
|
17
19
|
const UiTrash = require("../../icons/components/UiTrash.cjs");
|
|
18
20
|
function CacheDetailPanel(props) {
|
|
19
21
|
return types.isLeaf(props.node) ? /* @__PURE__ */ jsxRuntime.jsx(KeyPanel, { ...props }) : /* @__PURE__ */ jsxRuntime.jsx(PrefixPanel, { ...props });
|
|
@@ -42,6 +44,7 @@ function KeyPanel({ client, registry, node, onDeleted, className }) {
|
|
|
42
44
|
{
|
|
43
45
|
title: key,
|
|
44
46
|
onRefresh: () => detail.refetch(),
|
|
47
|
+
onDownload: detail.data ? () => download.downloadJson(key, detail.data) : void 0,
|
|
45
48
|
onDelete: remove,
|
|
46
49
|
deleteLabel: "Delete key"
|
|
47
50
|
}
|
|
@@ -157,6 +160,7 @@ function PrefixPanel({ client, node, onDeleted, onSelect, className }) {
|
|
|
157
160
|
function PanelHeader({
|
|
158
161
|
title,
|
|
159
162
|
onRefresh,
|
|
163
|
+
onDownload,
|
|
160
164
|
onDelete,
|
|
161
165
|
deleteLabel
|
|
162
166
|
}) {
|
|
@@ -173,6 +177,17 @@ function PanelHeader({
|
|
|
173
177
|
children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiRefresh.UiRefresh, className: "text-sm" })
|
|
174
178
|
}
|
|
175
179
|
),
|
|
180
|
+
onDownload && /* @__PURE__ */ jsxRuntime.jsx(
|
|
181
|
+
"button",
|
|
182
|
+
{
|
|
183
|
+
type: "button",
|
|
184
|
+
onClick: onDownload,
|
|
185
|
+
"aria-label": "Download JSON",
|
|
186
|
+
title: "Download JSON",
|
|
187
|
+
className: "inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground",
|
|
188
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiDownload.UiDownload, className: "text-sm" })
|
|
189
|
+
}
|
|
190
|
+
),
|
|
176
191
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
177
192
|
"button",
|
|
178
193
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CacheDetailPanel.cjs","sources":["../../../src/data/cache-browser/CacheDetailPanel.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { cn } from \"../../lib/utils\";\nimport { formatBytes, formatDuration, formatShort } from \"../../lib/format\";\nimport { Icon } from \"../Icon\";\nimport { UiFolder, UiRefresh, UiTrash } from \"../../icons\";\nimport { KeyValueList } from \"../KeyValueList\";\nimport { TabButton } from \"../TabButton\";\nimport { Section } from \"../../layout/Section\";\nimport { cacheQueryKeys, type CacheClient } from \"./api\";\nimport type { CacheAdapterRegistry } from \"./adapter\";\nimport { CacheValue } from \"./CacheValue\";\nimport { isLeaf, type CacheTreeNode } from \"./types\";\n\nexport type CacheDetailPanelProps = {\n client: CacheClient;\n registry: CacheAdapterRegistry;\n node: CacheTreeNode;\n /** Called after the node (key or whole prefix) was deleted. */\n onDeleted?: (node: CacheTreeNode) => void;\n /** Drill into a child prefix/key from the subtree overview. */\n onSelect?: (node: CacheTreeNode) => void;\n className?: string;\n};\n\n/**\n * Right-hand pane of the cache browser: full key detail (metadata + adapter\n * or type-aware value rendering) for leaves, an aggregated subtree overview\n * for prefix groups.\n */\nexport function CacheDetailPanel(props: CacheDetailPanelProps) {\n return isLeaf(props.node) ? <KeyPanel {...props} /> : <PrefixPanel {...props} />;\n}\n\nfunction KeyPanel({ client, registry, node, onDeleted, className }: CacheDetailPanelProps) {\n const queryClient = useQueryClient();\n const key = node.key!;\n const detail = useQuery({\n queryKey: cacheQueryKeys.key(client.baseUrl, key),\n queryFn: () => client.key(key),\n });\n const [activeTab, setActiveTab] = useState(\"value\");\n\n const ctx = { node, detail: detail.data ?? null, client };\n const adapter = registry.resolveDetail(node, detail.data ?? null);\n const tabs = registry.resolveTabs(ctx);\n\n const remove = async () => {\n if (!window.confirm(`Delete key ${key}?`)) return;\n await client.deleteKey(key);\n await queryClient.invalidateQueries({ queryKey: cacheQueryKeys.all(client.baseUrl) });\n onDeleted?.(node);\n };\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-density-3 overflow-y-auto p-density-3\", className)}>\n <PanelHeader\n title={key}\n onRefresh={() => detail.refetch()}\n onDelete={remove}\n deleteLabel=\"Delete key\"\n />\n {detail.isError && <PanelError error={detail.error} />}\n {detail.data && (\n <>\n <KeyValueList\n items={[\n { key: \"type\", label: \"Type\", value: <code>{detail.data.type}</code> },\n {\n key: \"ttl\",\n label: \"TTL\",\n value:\n detail.data.ttlSeconds < 0\n ? \"none\"\n : formatDuration(detail.data.ttlSeconds, { from: \"s\" }),\n },\n {\n key: \"bytes\",\n label: \"Memory\",\n value: formatBytes(detail.data.bytes),\n hidden: !detail.data.bytes,\n },\n { key: \"length\", label: \"Length\", value: formatShort(detail.data.length) },\n ]}\n />\n {tabs.length > 0 && (\n <div role=\"tablist\" className=\"flex flex-wrap items-center gap-1\">\n <TabButton\n active={activeTab === \"value\"}\n onClick={() => setActiveTab(\"value\")}\n label=\"Value\"\n />\n {tabs.map((tab) => (\n <TabButton\n key={tab.id}\n active={activeTab === tab.id}\n onClick={() => setActiveTab(tab.id)}\n label={tab.label}\n />\n ))}\n </div>\n )}\n {activeTab === \"value\"\n ? (adapter?.renderDetail?.(ctx) ?? <CacheValue detail={detail.data} />)\n : tabs.find((t) => t.id === activeTab)?.render()}\n </>\n )}\n {detail.isLoading && <div className=\"text-sm text-muted-foreground\">Loading key…</div>}\n </div>\n );\n}\n\nfunction PrefixPanel({ client, node, onDeleted, onSelect, className }: CacheDetailPanelProps) {\n const queryClient = useQueryClient();\n const prefix = node.prefix ?? \"\";\n const subtree = useQuery({\n queryKey: cacheQueryKeys.tree(client.baseUrl, prefix),\n queryFn: () => client.tree(prefix),\n });\n\n const remove = async () => {\n const count = subtree.data?.keys ?? node.keys;\n if (!window.confirm(`Delete all ${count} keys under ${prefix}?`)) return;\n await client.deletePrefix(prefix);\n await queryClient.invalidateQueries({ queryKey: cacheQueryKeys.all(client.baseUrl) });\n onDeleted?.(node);\n };\n\n const children = subtree.data?.nodes ?? [];\n const maxKeys = Math.max(1, ...children.map((c) => c.keys));\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-density-3 overflow-y-auto p-density-3\", className)}>\n <PanelHeader\n title={\n <span className=\"inline-flex items-center gap-1.5\">\n <Icon icon={UiFolder} className=\"text-muted-foreground\" />\n {prefix}\n </span>\n }\n onRefresh={() => subtree.refetch()}\n onDelete={remove}\n deleteLabel=\"Delete prefix\"\n />\n {subtree.isError && <PanelError error={subtree.error} />}\n {subtree.data && (\n <Section\n title={`${formatShort(subtree.data.keys)} keys${subtree.data.truncated ? \"+\" : \"\"}`}\n summary={`${children.length} children`}\n >\n <div className=\"flex flex-col\">\n {children.map((child) => (\n <button\n key={child.prefix ?? child.key ?? child.name}\n type=\"button\"\n onClick={() => onSelect?.(child)}\n className=\"grid grid-cols-[minmax(0,14rem)_minmax(0,1fr)_4rem] items-center gap-density-3 rounded px-density-2 py-density-1 text-left text-sm hover:bg-accent\"\n >\n <span className=\"truncate font-mono text-xs\">{child.name}</span>\n <span className=\"h-2 overflow-hidden rounded bg-muted\">\n <span\n className=\"block h-full bg-primary/60\"\n style={{ width: `${(child.keys / maxKeys) * 100}%` }}\n />\n </span>\n <span className=\"text-right text-xs text-muted-foreground\">\n {formatShort(child.keys)}\n </span>\n </button>\n ))}\n </div>\n </Section>\n )}\n {subtree.isLoading && <div className=\"text-sm text-muted-foreground\">Loading prefix…</div>}\n </div>\n );\n}\n\nfunction PanelHeader({\n title,\n onRefresh,\n onDelete,\n deleteLabel,\n}: {\n title: React.ReactNode;\n onRefresh: () => void;\n onDelete: () => void;\n deleteLabel: string;\n}) {\n return (\n <div className=\"flex items-center gap-2\">\n <h3 className=\"min-w-0 flex-1 truncate font-mono text-sm font-semibold\">{title}</h3>\n <button\n type=\"button\"\n onClick={onRefresh}\n aria-label=\"Refresh\"\n title=\"Refresh\"\n className=\"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n >\n <Icon icon={UiRefresh} className=\"text-sm\" />\n </button>\n <button\n type=\"button\"\n onClick={onDelete}\n aria-label={deleteLabel}\n title={deleteLabel}\n className=\"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive\"\n >\n <Icon icon={UiTrash} className=\"text-sm\" />\n </button>\n </div>\n );\n}\n\nfunction PanelError({ error }: { error: unknown }) {\n return (\n <div className=\"rounded-md border border-red-300 bg-red-50 px-density-3 py-density-2 text-xs text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200\">\n {error instanceof Error ? error.message : String(error)}\n </div>\n );\n}\n"],"names":["isLeaf","jsx","useQueryClient","useQuery","cacheQueryKeys","useState","cn","jsxs","Fragment","KeyValueList","formatDuration","formatBytes","formatShort","TabButton","CacheValue","_a","Icon","UiFolder","Section","UiRefresh","UiTrash"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CacheDetailPanel.cjs","sources":["../../../src/data/cache-browser/CacheDetailPanel.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { cn } from \"../../lib/utils\";\nimport { formatBytes, formatDuration, formatShort } from \"../../lib/format\";\nimport { Icon } from \"../Icon\";\nimport { UiDownload, UiFolder, UiRefresh, UiTrash } from \"../../icons\";\nimport { KeyValueList } from \"../KeyValueList\";\nimport { TabButton } from \"../TabButton\";\nimport { Section } from \"../../layout/Section\";\nimport { cacheQueryKeys, type CacheClient } from \"./api\";\nimport type { CacheAdapterRegistry } from \"./adapter\";\nimport { CacheValue } from \"./CacheValue\";\nimport { isLeaf, type CacheTreeNode } from \"./types\";\nimport { downloadJson } from \"./download\";\n\nexport type CacheDetailPanelProps = {\n client: CacheClient;\n registry: CacheAdapterRegistry;\n node: CacheTreeNode;\n /** Called after the node (key or whole prefix) was deleted. */\n onDeleted?: (node: CacheTreeNode) => void;\n /** Drill into a child prefix/key from the subtree overview. */\n onSelect?: (node: CacheTreeNode) => void;\n className?: string;\n};\n\n/**\n * Right-hand pane of the cache browser: full key detail (metadata + adapter\n * or type-aware value rendering) for leaves, an aggregated subtree overview\n * for prefix groups.\n */\nexport function CacheDetailPanel(props: CacheDetailPanelProps) {\n return isLeaf(props.node) ? <KeyPanel {...props} /> : <PrefixPanel {...props} />;\n}\n\nfunction KeyPanel({ client, registry, node, onDeleted, className }: CacheDetailPanelProps) {\n const queryClient = useQueryClient();\n const key = node.key!;\n const detail = useQuery({\n queryKey: cacheQueryKeys.key(client.baseUrl, key),\n queryFn: () => client.key(key),\n });\n const [activeTab, setActiveTab] = useState(\"value\");\n\n const ctx = { node, detail: detail.data ?? null, client };\n const adapter = registry.resolveDetail(node, detail.data ?? null);\n const tabs = registry.resolveTabs(ctx);\n\n const remove = async () => {\n if (!window.confirm(`Delete key ${key}?`)) return;\n await client.deleteKey(key);\n await queryClient.invalidateQueries({ queryKey: cacheQueryKeys.all(client.baseUrl) });\n onDeleted?.(node);\n };\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-density-3 overflow-y-auto p-density-3\", className)}>\n <PanelHeader\n title={key}\n onRefresh={() => detail.refetch()}\n onDownload={detail.data ? () => downloadJson(key, detail.data!) : undefined}\n onDelete={remove}\n deleteLabel=\"Delete key\"\n />\n {detail.isError && <PanelError error={detail.error} />}\n {detail.data && (\n <>\n <KeyValueList\n items={[\n { key: \"type\", label: \"Type\", value: <code>{detail.data.type}</code> },\n {\n key: \"ttl\",\n label: \"TTL\",\n value:\n detail.data.ttlSeconds < 0\n ? \"none\"\n : formatDuration(detail.data.ttlSeconds, { from: \"s\" }),\n },\n {\n key: \"bytes\",\n label: \"Memory\",\n value: formatBytes(detail.data.bytes),\n hidden: !detail.data.bytes,\n },\n { key: \"length\", label: \"Length\", value: formatShort(detail.data.length) },\n ]}\n />\n {tabs.length > 0 && (\n <div role=\"tablist\" className=\"flex flex-wrap items-center gap-1\">\n <TabButton\n active={activeTab === \"value\"}\n onClick={() => setActiveTab(\"value\")}\n label=\"Value\"\n />\n {tabs.map((tab) => (\n <TabButton\n key={tab.id}\n active={activeTab === tab.id}\n onClick={() => setActiveTab(tab.id)}\n label={tab.label}\n />\n ))}\n </div>\n )}\n {activeTab === \"value\"\n ? (adapter?.renderDetail?.(ctx) ?? <CacheValue detail={detail.data} />)\n : tabs.find((t) => t.id === activeTab)?.render()}\n </>\n )}\n {detail.isLoading && <div className=\"text-sm text-muted-foreground\">Loading key…</div>}\n </div>\n );\n}\n\nfunction PrefixPanel({ client, node, onDeleted, onSelect, className }: CacheDetailPanelProps) {\n const queryClient = useQueryClient();\n const prefix = node.prefix ?? \"\";\n const subtree = useQuery({\n queryKey: cacheQueryKeys.tree(client.baseUrl, prefix),\n queryFn: () => client.tree(prefix),\n });\n\n const remove = async () => {\n const count = subtree.data?.keys ?? node.keys;\n if (!window.confirm(`Delete all ${count} keys under ${prefix}?`)) return;\n await client.deletePrefix(prefix);\n await queryClient.invalidateQueries({ queryKey: cacheQueryKeys.all(client.baseUrl) });\n onDeleted?.(node);\n };\n\n const children = subtree.data?.nodes ?? [];\n const maxKeys = Math.max(1, ...children.map((c) => c.keys));\n\n return (\n <div className={cn(\"flex min-h-0 flex-col gap-density-3 overflow-y-auto p-density-3\", className)}>\n <PanelHeader\n title={\n <span className=\"inline-flex items-center gap-1.5\">\n <Icon icon={UiFolder} className=\"text-muted-foreground\" />\n {prefix}\n </span>\n }\n onRefresh={() => subtree.refetch()}\n onDelete={remove}\n deleteLabel=\"Delete prefix\"\n />\n {subtree.isError && <PanelError error={subtree.error} />}\n {subtree.data && (\n <Section\n title={`${formatShort(subtree.data.keys)} keys${subtree.data.truncated ? \"+\" : \"\"}`}\n summary={`${children.length} children`}\n >\n <div className=\"flex flex-col\">\n {children.map((child) => (\n <button\n key={child.prefix ?? child.key ?? child.name}\n type=\"button\"\n onClick={() => onSelect?.(child)}\n className=\"grid grid-cols-[minmax(0,14rem)_minmax(0,1fr)_4rem] items-center gap-density-3 rounded px-density-2 py-density-1 text-left text-sm hover:bg-accent\"\n >\n <span className=\"truncate font-mono text-xs\">{child.name}</span>\n <span className=\"h-2 overflow-hidden rounded bg-muted\">\n <span\n className=\"block h-full bg-primary/60\"\n style={{ width: `${(child.keys / maxKeys) * 100}%` }}\n />\n </span>\n <span className=\"text-right text-xs text-muted-foreground\">\n {formatShort(child.keys)}\n </span>\n </button>\n ))}\n </div>\n </Section>\n )}\n {subtree.isLoading && <div className=\"text-sm text-muted-foreground\">Loading prefix…</div>}\n </div>\n );\n}\n\nfunction PanelHeader({\n title,\n onRefresh,\n onDownload,\n onDelete,\n deleteLabel,\n}: {\n title: React.ReactNode;\n onRefresh: () => void;\n onDownload?: (() => void) | undefined;\n onDelete: () => void;\n deleteLabel: string;\n}) {\n return (\n <div className=\"flex items-center gap-2\">\n <h3 className=\"min-w-0 flex-1 truncate font-mono text-sm font-semibold\">{title}</h3>\n <button\n type=\"button\"\n onClick={onRefresh}\n aria-label=\"Refresh\"\n title=\"Refresh\"\n className=\"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n >\n <Icon icon={UiRefresh} className=\"text-sm\" />\n </button>\n {onDownload && (\n <button\n type=\"button\"\n onClick={onDownload}\n aria-label=\"Download JSON\"\n title=\"Download JSON\"\n className=\"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground\"\n >\n <Icon icon={UiDownload} className=\"text-sm\" />\n </button>\n )}\n <button\n type=\"button\"\n onClick={onDelete}\n aria-label={deleteLabel}\n title={deleteLabel}\n className=\"inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-destructive/10 hover:text-destructive\"\n >\n <Icon icon={UiTrash} className=\"text-sm\" />\n </button>\n </div>\n );\n}\n\nfunction PanelError({ error }: { error: unknown }) {\n return (\n <div className=\"rounded-md border border-red-300 bg-red-50 px-density-3 py-density-2 text-xs text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200\">\n {error instanceof Error ? error.message : String(error)}\n </div>\n );\n}\n"],"names":["isLeaf","jsx","useQueryClient","useQuery","cacheQueryKeys","useState","cn","downloadJson","jsxs","Fragment","KeyValueList","formatDuration","formatBytes","formatShort","TabButton","CacheValue","_a","Icon","UiFolder","Section","UiRefresh","UiDownload","UiTrash"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CacheDetailPanel.d.ts","sourceRoot":"","sources":["../../../src/data/cache-browser/CacheDetailPanel.tsx"],"names":[],"mappings":"AASA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"CacheDetailPanel.d.ts","sourceRoot":"","sources":["../../../src/data/cache-browser/CacheDetailPanel.tsx"],"names":[],"mappings":"AASA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAGrD,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,2CAE5D"}
|
|
@@ -10,8 +10,10 @@ import { Section } from "../../layout/Section.js";
|
|
|
10
10
|
import { cacheQueryKeys } from "./api.js";
|
|
11
11
|
import { CacheValue } from "./CacheValue.js";
|
|
12
12
|
import { isLeaf } from "./types.js";
|
|
13
|
+
import { downloadJson } from "./download.js";
|
|
13
14
|
import { UiFolder } from "../../icons/components/UiFolder.js";
|
|
14
15
|
import { UiRefresh } from "../../icons/components/UiRefresh.js";
|
|
16
|
+
import { UiDownload } from "../../icons/components/UiDownload.js";
|
|
15
17
|
import { UiTrash } from "../../icons/components/UiTrash.js";
|
|
16
18
|
function CacheDetailPanel(props) {
|
|
17
19
|
return isLeaf(props.node) ? /* @__PURE__ */ jsx(KeyPanel, { ...props }) : /* @__PURE__ */ jsx(PrefixPanel, { ...props });
|
|
@@ -40,6 +42,7 @@ function KeyPanel({ client, registry, node, onDeleted, className }) {
|
|
|
40
42
|
{
|
|
41
43
|
title: key,
|
|
42
44
|
onRefresh: () => detail.refetch(),
|
|
45
|
+
onDownload: detail.data ? () => downloadJson(key, detail.data) : void 0,
|
|
43
46
|
onDelete: remove,
|
|
44
47
|
deleteLabel: "Delete key"
|
|
45
48
|
}
|
|
@@ -155,6 +158,7 @@ function PrefixPanel({ client, node, onDeleted, onSelect, className }) {
|
|
|
155
158
|
function PanelHeader({
|
|
156
159
|
title,
|
|
157
160
|
onRefresh,
|
|
161
|
+
onDownload,
|
|
158
162
|
onDelete,
|
|
159
163
|
deleteLabel
|
|
160
164
|
}) {
|
|
@@ -171,6 +175,17 @@ function PanelHeader({
|
|
|
171
175
|
children: /* @__PURE__ */ jsx(Icon, { icon: UiRefresh, className: "text-sm" })
|
|
172
176
|
}
|
|
173
177
|
),
|
|
178
|
+
onDownload && /* @__PURE__ */ jsx(
|
|
179
|
+
"button",
|
|
180
|
+
{
|
|
181
|
+
type: "button",
|
|
182
|
+
onClick: onDownload,
|
|
183
|
+
"aria-label": "Download JSON",
|
|
184
|
+
title: "Download JSON",
|
|
185
|
+
className: "inline-flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-accent-foreground",
|
|
186
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: UiDownload, className: "text-sm" })
|
|
187
|
+
}
|
|
188
|
+
),
|
|
174
189
|
/* @__PURE__ */ jsx(
|
|
175
190
|
"button",
|
|
176
191
|
{
|