@flanksource/clicky-ui 0.2.18 → 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 +21 -1
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +11 -1
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +21 -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/TabButton.cjs +17 -2
- package/dist/data/TabButton.cjs.map +1 -1
- package/dist/data/TabButton.d.ts +5 -1
- package/dist/data/TabButton.d.ts.map +1 -1
- package/dist/data/TabButton.js +17 -2
- package/dist/data/TabButton.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 +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +19 -6
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +14 -6
- 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 +57 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +56 -6
- package/dist/index.js.map +1 -1
- package/dist/layout/AppShell.cjs +332 -0
- package/dist/layout/AppShell.cjs.map +1 -0
- package/dist/layout/AppShell.d.ts +75 -0
- package/dist/layout/AppShell.d.ts.map +1 -0
- package/dist/layout/AppShell.js +332 -0
- package/dist/layout/AppShell.js.map +1 -0
- 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/layout/Panel.cjs +66 -0
- package/dist/layout/Panel.cjs.map +1 -0
- package/dist/layout/Panel.d.ts +34 -0
- package/dist/layout/Panel.d.ts.map +1 -0
- package/dist/layout/Panel.js +66 -0
- package/dist/layout/Panel.js.map +1 -0
- package/dist/layout/Tabs.cjs +36 -0
- package/dist/layout/Tabs.cjs.map +1 -0
- package/dist/layout/Tabs.d.ts +36 -0
- package/dist/layout/Tabs.d.ts.map +1 -0
- package/dist/layout/Tabs.js +36 -0
- package/dist/layout/Tabs.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.cjs +1 -0
- package/dist/styles.cjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.d.ts.map +1 -1
- package/dist/styles.js +1 -0
- package/dist/styles.js.map +1 -1
- package/dist/tailwind-preset.cjs +36 -19
- package/dist/tailwind-preset.cjs.map +1 -1
- package/dist/tailwind-preset.d.ts.map +1 -1
- package/dist/tailwind-preset.js +36 -19
- package/dist/tailwind-preset.js.map +1 -1
- package/package.json +11 -1
|
@@ -1,141 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { assignAxes, latestOf } from './TimeseriesPanel.axes';
|
|
1
|
+
import { TimeseriesPanelProps } from './TimeseriesPanel.model';
|
|
3
2
|
export type { AxisAssignment, AxisOrientation, AxisSpec } from './TimeseriesPanel.axes';
|
|
4
|
-
export
|
|
5
|
-
at: string;
|
|
6
|
-
value: number;
|
|
7
|
-
}
|
|
8
|
-
export interface TimeseriesResponse {
|
|
9
|
-
id: string;
|
|
10
|
-
points: TimeseriesPoint[];
|
|
11
|
-
}
|
|
12
|
-
/** One metric plotted on a panel. Its request URL is `baseUrl + id`. */
|
|
13
|
-
export interface TimeseriesSeries {
|
|
14
|
-
/** Metric id appended to the panel's baseUrl, e.g. "sqlserver.iops.read". */
|
|
15
|
-
id: string;
|
|
16
|
-
/** Tooltip/legend label; defaults to the id. */
|
|
17
|
-
label?: string;
|
|
18
|
-
/**
|
|
19
|
-
* Maps each point's value before plotting — e.g. writes pass `(v) => -v` to
|
|
20
|
-
* render below the zero axis. Identity when omitted.
|
|
21
|
-
*/
|
|
22
|
-
transform?: (value: number) => number;
|
|
23
|
-
/**
|
|
24
|
-
* Stroke/fill override as a CSS color value (e.g. "#10b981", "var(--chart-3)")
|
|
25
|
-
* or a Tailwind color class (e.g. "bg-emerald-500"); Tailwind classes are
|
|
26
|
-
* resolved to a CSS value for the chart. Defaults cycle a small palette by index.
|
|
27
|
-
*/
|
|
28
|
-
color?: string;
|
|
29
|
-
/**
|
|
30
|
-
* Grafana-style unit key for this series' readout/tooltip (e.g. "percent",
|
|
31
|
-
* "short"). Falls back to the panel-level `unit`. Lets one panel mix units
|
|
32
|
-
* (e.g. a percent series alongside a plain-count series).
|
|
33
|
-
*/
|
|
34
|
-
unit?: string;
|
|
35
|
-
/**
|
|
36
|
-
* Instantaneous value for the `breakdown` variant — the size of this series'
|
|
37
|
-
* bar segment and its legend readout. When omitted, the breakdown falls back
|
|
38
|
-
* to the latest polled point. Ignored by the time-series variants.
|
|
39
|
-
*/
|
|
40
|
-
current?: number;
|
|
41
|
-
}
|
|
42
|
-
export interface TimeseriesPanelProps {
|
|
43
|
-
/**
|
|
44
|
-
* Single-metric endpoint returning a TimeseriesResponse,
|
|
45
|
-
* e.g. "/api/v1/metrics/sqlserver.cpu". Mutually exclusive with baseUrl/series.
|
|
46
|
-
*/
|
|
47
|
-
url?: string;
|
|
48
|
-
/** Common prefix for a multi-series panel; each series requests `baseUrl + series.id`. */
|
|
49
|
-
baseUrl?: string;
|
|
50
|
-
/** Metrics to plot on one chart. Provide together with baseUrl. */
|
|
51
|
-
series?: TimeseriesSeries[];
|
|
52
|
-
title: string;
|
|
53
|
-
/** Iconify name or static icon component shown beside the title. */
|
|
54
|
-
icon?: string | StaticIconComponent;
|
|
55
|
-
/**
|
|
56
|
-
* Default Grafana-style unit key for the panel (e.g. "bytes", "percent",
|
|
57
|
-
* "ms", "short"); each series may override it. Unknown strings are appended
|
|
58
|
-
* as a raw suffix (so "%" still works). Used for the readout, axis, and tooltip.
|
|
59
|
-
*/
|
|
60
|
-
unit?: string;
|
|
61
|
-
/** Look-back window passed as ?since=; defaults to "1h". */
|
|
62
|
-
range?: string;
|
|
63
|
-
/** Poll interval in ms; defaults to 5000. Pass 0 to disable polling. */
|
|
64
|
-
refreshMs?: number;
|
|
65
|
-
/** Chart height in px; defaults to 160. */
|
|
66
|
-
height?: number;
|
|
67
|
-
/**
|
|
68
|
-
* "area" (overlaid, default), "line", "stacked" (areas sum vertically), or
|
|
69
|
-
* "breakdown" (an instantaneous stacked bar + legend; the expand modal still
|
|
70
|
-
* shows a time-series graph of the polled history).
|
|
71
|
-
*/
|
|
72
|
-
variant?: "area" | "line" | "stacked" | "breakdown";
|
|
73
|
-
/**
|
|
74
|
-
* Chart variant rendered in the expand modal. Defaults to `variant` for the
|
|
75
|
-
* time-series variants and to "area" for `breakdown` (which has no inline chart).
|
|
76
|
-
*/
|
|
77
|
-
expandVariant?: "area" | "line" | "stacked";
|
|
78
|
-
/**
|
|
79
|
-
* Denominator for the `breakdown` bar and per-segment percentages. Defaults to
|
|
80
|
-
* the sum of the series' `current` values when omitted.
|
|
81
|
-
*/
|
|
82
|
-
total?: number;
|
|
83
|
-
/** Show a header button that opens the chart larger in a modal. Default true. */
|
|
84
|
-
expandable?: boolean;
|
|
85
|
-
/** Override the default fetch (e.g. to route through an app's API client). */
|
|
86
|
-
fetcher?: (url: string) => Promise<TimeseriesResponse>;
|
|
87
|
-
className?: string;
|
|
88
|
-
}
|
|
89
|
-
/** A series with its full request URL, resolved label, color, and unit. Exported for tests. */
|
|
90
|
-
export interface ResolvedSeries {
|
|
91
|
-
/** Stable key used as the merged-row field and recharts dataKey. */
|
|
92
|
-
key: string;
|
|
93
|
-
url: string;
|
|
94
|
-
label: string;
|
|
95
|
-
color: string;
|
|
96
|
-
/** Resolved Grafana unit key: the series' own unit, else the panel default. */
|
|
97
|
-
unit?: string;
|
|
98
|
-
transform?: (value: number) => number;
|
|
99
|
-
/** Instantaneous value used by the `breakdown` variant. */
|
|
100
|
-
current?: number;
|
|
101
|
-
}
|
|
102
|
-
/** Normalises the single-url and baseUrl+series forms to one list. Exported for tests. */
|
|
103
|
-
export declare function resolveSeries(props: TimeseriesPanelProps): ResolvedSeries[];
|
|
104
|
-
/** One legend/bar row of the breakdown variant: resolved value, color, label, unit, percentage. */
|
|
105
|
-
export interface BreakdownItem {
|
|
106
|
-
key: string;
|
|
107
|
-
label: string;
|
|
108
|
-
color: string;
|
|
109
|
-
unit?: string;
|
|
110
|
-
value: number;
|
|
111
|
-
/** Share of `total`, clamped to 0..100. */
|
|
112
|
-
percent: number;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Derives the breakdown bar segments and per-item percentages from the resolved
|
|
116
|
-
* series' `current` values. `total` defaults to the sum of those values; the
|
|
117
|
-
* percentage is each value's share of that denominator, clamped to 0..100.
|
|
118
|
-
* Latest polled point fills in for a series with no explicit `current`. Pure —
|
|
119
|
-
* exported for tests.
|
|
120
|
-
*/
|
|
121
|
-
export declare function resolveBreakdown(series: ResolvedSeries[], rows: MergedRow[], total?: number): {
|
|
122
|
-
items: BreakdownItem[];
|
|
123
|
-
total: number;
|
|
124
|
-
};
|
|
125
|
-
/**
|
|
126
|
-
* One row of the merged chart data: the timestamp in `at` plus each series'
|
|
127
|
-
* value under its key. Values are absent (undefined) where a series has no
|
|
128
|
-
* point at that timestamp.
|
|
129
|
-
*/
|
|
130
|
-
export interface MergedRow {
|
|
131
|
-
at: string;
|
|
132
|
-
[seriesKey: string]: string | number | undefined;
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Joins per-series point lists into rows keyed by timestamp and applies each
|
|
136
|
-
* series' transform. Timestamps present in any series produce a row; missing
|
|
137
|
-
* values are left undefined so recharts gaps the line rather than drawing zero.
|
|
138
|
-
*/
|
|
139
|
-
export declare function mergeSeries(series: ResolvedSeries[], pointsBySeries: (TimeseriesPoint[] | undefined)[]): MergedRow[];
|
|
3
|
+
export type { BreakdownItem, MergedRow, ResolvedSeries, TimeseriesPanelProps, TimeseriesPoint, TimeseriesResponse, TimeseriesSeries, } from './TimeseriesPanel.model';
|
|
140
4
|
export declare function TimeseriesPanel(props: TimeseriesPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
141
5
|
//# sourceMappingURL=TimeseriesPanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeseriesPanel.d.ts","sourceRoot":"","sources":["../../src/data/TimeseriesPanel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TimeseriesPanel.d.ts","sourceRoot":"","sources":["../../src/data/TimeseriesPanel.tsx"],"names":[],"mappings":"AAsBA,OAAO,EAOL,KAAK,oBAAoB,EAE1B,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACxF,YAAY,EACV,aAAa,EACb,SAAS,EACT,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AAcjC,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,2CA6G1D"}
|
|
@@ -9,42 +9,8 @@ import { Modal } from "../overlay/Modal.js";
|
|
|
9
9
|
import { ProgressBar } from "./ProgressBar.js";
|
|
10
10
|
import { Icon } from "./Icon.js";
|
|
11
11
|
import { latestOf, assignAxes } from "./TimeseriesPanel.axes.js";
|
|
12
|
+
import { resolveSeries, mergeSeries, resolveBreakdown } from "./TimeseriesPanel.model.js";
|
|
12
13
|
import { UiFullscreen } from "../icons/components/UiFullscreen.js";
|
|
13
|
-
const SERIES_PALETTE = [
|
|
14
|
-
"var(--chart-1, #3b82f6)",
|
|
15
|
-
"var(--chart-2, #ef4444)",
|
|
16
|
-
"var(--chart-3, #10b981)",
|
|
17
|
-
"var(--chart-4, #f59e0b)"
|
|
18
|
-
];
|
|
19
|
-
function paletteColor(index) {
|
|
20
|
-
return SERIES_PALETTE[index % SERIES_PALETTE.length] ?? SERIES_PALETTE[0];
|
|
21
|
-
}
|
|
22
|
-
function resolveSeries(props) {
|
|
23
|
-
const base = props.baseUrl ?? "";
|
|
24
|
-
const list = props.series ?? (props.url ? [{ id: props.url }] : []);
|
|
25
|
-
return list.map((s, i) => ({
|
|
26
|
-
key: s.id,
|
|
27
|
-
url: base + s.id,
|
|
28
|
-
label: s.label ?? s.id,
|
|
29
|
-
color: s.color ?? paletteColor(i),
|
|
30
|
-
...s.unit ?? props.unit ? { unit: s.unit ?? props.unit } : {},
|
|
31
|
-
...s.transform ? { transform: s.transform } : {},
|
|
32
|
-
...s.current !== void 0 ? { current: s.current } : {}
|
|
33
|
-
}));
|
|
34
|
-
}
|
|
35
|
-
function resolveBreakdown(series, rows, total) {
|
|
36
|
-
const withValue = series.map((s) => ({ s, value: s.current ?? latestOf(rows, s.key) ?? 0 }));
|
|
37
|
-
const denom = total ?? withValue.reduce((acc, w) => acc + w.value, 0);
|
|
38
|
-
const items = withValue.map(({ s, value }) => ({
|
|
39
|
-
key: s.key,
|
|
40
|
-
label: s.label,
|
|
41
|
-
color: s.color,
|
|
42
|
-
...s.unit ? { unit: s.unit } : {},
|
|
43
|
-
value,
|
|
44
|
-
percent: denom > 0 ? Math.min(100, Math.max(0, value / denom * 100)) : 0
|
|
45
|
-
}));
|
|
46
|
-
return { items, total: denom };
|
|
47
|
-
}
|
|
48
14
|
const defaultFetcher = async (url) => {
|
|
49
15
|
const res = await fetch(url);
|
|
50
16
|
if (!res.ok) throw new Error(`metrics request failed: ${res.status}`);
|
|
@@ -55,17 +21,6 @@ function formatClock(at) {
|
|
|
55
21
|
if (Number.isNaN(date.getTime())) return "";
|
|
56
22
|
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
57
23
|
}
|
|
58
|
-
function mergeSeries(series, pointsBySeries) {
|
|
59
|
-
const rows = /* @__PURE__ */ new Map();
|
|
60
|
-
series.forEach((s, i) => {
|
|
61
|
-
for (const p of pointsBySeries[i] ?? []) {
|
|
62
|
-
const row = rows.get(p.at) ?? { at: p.at };
|
|
63
|
-
row[s.key] = s.transform ? s.transform(p.value) : p.value;
|
|
64
|
-
rows.set(p.at, row);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
return [...rows.values()].sort((a, b) => a.at.localeCompare(b.at));
|
|
68
|
-
}
|
|
69
24
|
function TimeseriesPanel(props) {
|
|
70
25
|
var _a;
|
|
71
26
|
const {
|
|
@@ -314,11 +269,6 @@ function PanelIcon({ icon }) {
|
|
|
314
269
|
return /* @__PURE__ */ jsx(Icon, { icon, width: 16, height: 16, className: "text-muted-foreground" });
|
|
315
270
|
}
|
|
316
271
|
export {
|
|
317
|
-
TimeseriesPanel
|
|
318
|
-
assignAxes,
|
|
319
|
-
latestOf,
|
|
320
|
-
mergeSeries,
|
|
321
|
-
resolveBreakdown,
|
|
322
|
-
resolveSeries
|
|
272
|
+
TimeseriesPanel
|
|
323
273
|
};
|
|
324
274
|
//# sourceMappingURL=TimeseriesPanel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeseriesPanel.js","sources":["../../src/data/TimeseriesPanel.tsx"],"sourcesContent":["import { useQueries } from \"@tanstack/react-query\";\nimport { useMemo, useState } from \"react\";\nimport {\n Area,\n AreaChart,\n CartesianGrid,\n Line,\n LineChart,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport { cn } from \"../lib/utils\";\nimport { resolveCssColor } from \"../lib/color\";\nimport { formatUnit } from \"../lib/format\";\nimport { Modal } from \"../overlay/Modal\";\nimport { ProgressBar, type ProgressSegment } from \"./ProgressBar\";\nimport { UiFullscreen } from \"../icons\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { assignAxes, latestOf } from \"./TimeseriesPanel.axes\";\n\nexport { assignAxes, latestOf } from \"./TimeseriesPanel.axes\";\nexport type { AxisAssignment, AxisOrientation, AxisSpec } from \"./TimeseriesPanel.axes\";\n\nexport interface TimeseriesPoint {\n at: string;\n value: number;\n}\n\nexport interface TimeseriesResponse {\n id: string;\n points: TimeseriesPoint[];\n}\n\n/** One metric plotted on a panel. Its request URL is `baseUrl + id`. */\nexport interface TimeseriesSeries {\n /** Metric id appended to the panel's baseUrl, e.g. \"sqlserver.iops.read\". */\n id: string;\n /** Tooltip/legend label; defaults to the id. */\n label?: string;\n /**\n * Maps each point's value before plotting — e.g. writes pass `(v) => -v` to\n * render below the zero axis. Identity when omitted.\n */\n transform?: (value: number) => number;\n /**\n * Stroke/fill override as a CSS color value (e.g. \"#10b981\", \"var(--chart-3)\")\n * or a Tailwind color class (e.g. \"bg-emerald-500\"); Tailwind classes are\n * resolved to a CSS value for the chart. Defaults cycle a small palette by index.\n */\n color?: string;\n /**\n * Grafana-style unit key for this series' readout/tooltip (e.g. \"percent\",\n * \"short\"). Falls back to the panel-level `unit`. Lets one panel mix units\n * (e.g. a percent series alongside a plain-count series).\n */\n unit?: string;\n /**\n * Instantaneous value for the `breakdown` variant — the size of this series'\n * bar segment and its legend readout. When omitted, the breakdown falls back\n * to the latest polled point. Ignored by the time-series variants.\n */\n current?: number;\n}\n\nexport interface TimeseriesPanelProps {\n /**\n * Single-metric endpoint returning a TimeseriesResponse,\n * e.g. \"/api/v1/metrics/sqlserver.cpu\". Mutually exclusive with baseUrl/series.\n */\n url?: string;\n /** Common prefix for a multi-series panel; each series requests `baseUrl + series.id`. */\n baseUrl?: string;\n /** Metrics to plot on one chart. Provide together with baseUrl. */\n series?: TimeseriesSeries[];\n title: string;\n /** Iconify name or static icon component shown beside the title. */\n icon?: string | StaticIconComponent;\n /**\n * Default Grafana-style unit key for the panel (e.g. \"bytes\", \"percent\",\n * \"ms\", \"short\"); each series may override it. Unknown strings are appended\n * as a raw suffix (so \"%\" still works). Used for the readout, axis, and tooltip.\n */\n unit?: string;\n /** Look-back window passed as ?since=; defaults to \"1h\". */\n range?: string;\n /** Poll interval in ms; defaults to 5000. Pass 0 to disable polling. */\n refreshMs?: number;\n /** Chart height in px; defaults to 160. */\n height?: number;\n /**\n * \"area\" (overlaid, default), \"line\", \"stacked\" (areas sum vertically), or\n * \"breakdown\" (an instantaneous stacked bar + legend; the expand modal still\n * shows a time-series graph of the polled history).\n */\n variant?: \"area\" | \"line\" | \"stacked\" | \"breakdown\";\n /**\n * Chart variant rendered in the expand modal. Defaults to `variant` for the\n * time-series variants and to \"area\" for `breakdown` (which has no inline chart).\n */\n expandVariant?: \"area\" | \"line\" | \"stacked\";\n /**\n * Denominator for the `breakdown` bar and per-segment percentages. Defaults to\n * the sum of the series' `current` values when omitted.\n */\n total?: number;\n /** Show a header button that opens the chart larger in a modal. Default true. */\n expandable?: boolean;\n /** Override the default fetch (e.g. to route through an app's API client). */\n fetcher?: (url: string) => Promise<TimeseriesResponse>;\n className?: string;\n}\n\nconst SERIES_PALETTE = [\n \"var(--chart-1, #3b82f6)\",\n \"var(--chart-2, #ef4444)\",\n \"var(--chart-3, #10b981)\",\n \"var(--chart-4, #f59e0b)\",\n] as const;\n\nfunction paletteColor(index: number): string {\n return SERIES_PALETTE[index % SERIES_PALETTE.length] ?? SERIES_PALETTE[0];\n}\n\n/** A series with its full request URL, resolved label, color, and unit. Exported for tests. */\nexport interface ResolvedSeries {\n /** Stable key used as the merged-row field and recharts dataKey. */\n key: string;\n url: string;\n label: string;\n color: string;\n /** Resolved Grafana unit key: the series' own unit, else the panel default. */\n unit?: string;\n transform?: (value: number) => number;\n /** Instantaneous value used by the `breakdown` variant. */\n current?: number;\n}\n\n/** Normalises the single-url and baseUrl+series forms to one list. Exported for tests. */\nexport function resolveSeries(props: TimeseriesPanelProps): ResolvedSeries[] {\n const base = props.baseUrl ?? \"\";\n const list = props.series ?? (props.url ? [{ id: props.url }] : []);\n return list.map((s, i) => ({\n key: s.id,\n url: base + s.id,\n label: s.label ?? s.id,\n color: s.color ?? paletteColor(i),\n ...(s.unit ?? props.unit ? { unit: s.unit ?? props.unit } : {}),\n ...(s.transform ? { transform: s.transform } : {}),\n ...(s.current !== undefined ? { current: s.current } : {}),\n }));\n}\n\n/** One legend/bar row of the breakdown variant: resolved value, color, label, unit, percentage. */\nexport interface BreakdownItem {\n key: string;\n label: string;\n color: string;\n unit?: string;\n value: number;\n /** Share of `total`, clamped to 0..100. */\n percent: number;\n}\n\n/**\n * Derives the breakdown bar segments and per-item percentages from the resolved\n * series' `current` values. `total` defaults to the sum of those values; the\n * percentage is each value's share of that denominator, clamped to 0..100.\n * Latest polled point fills in for a series with no explicit `current`. Pure —\n * exported for tests.\n */\nexport function resolveBreakdown(\n series: ResolvedSeries[],\n rows: MergedRow[],\n total?: number,\n): { items: BreakdownItem[]; total: number } {\n const withValue = series.map((s) => ({ s, value: s.current ?? latestOf(rows, s.key) ?? 0 }));\n const denom = total ?? withValue.reduce((acc, w) => acc + w.value, 0);\n const items = withValue.map(({ s, value }) => ({\n key: s.key,\n label: s.label,\n color: s.color,\n ...(s.unit ? { unit: s.unit } : {}),\n value,\n percent: denom > 0 ? Math.min(100, Math.max(0, (value / denom) * 100)) : 0,\n }));\n return { items, total: denom };\n}\n\nconst defaultFetcher = async (url: string): Promise<TimeseriesResponse> => {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`metrics request failed: ${res.status}`);\n return res.json();\n};\n\nfunction formatClock(at: string): string {\n const date = new Date(at);\n if (Number.isNaN(date.getTime())) return \"\";\n return date.toLocaleTimeString([], { hour: \"2-digit\", minute: \"2-digit\" });\n}\n\n/**\n * One row of the merged chart data: the timestamp in `at` plus each series'\n * value under its key. Values are absent (undefined) where a series has no\n * point at that timestamp.\n */\nexport interface MergedRow {\n at: string;\n [seriesKey: string]: string | number | undefined;\n}\n\n/**\n * Joins per-series point lists into rows keyed by timestamp and applies each\n * series' transform. Timestamps present in any series produce a row; missing\n * values are left undefined so recharts gaps the line rather than drawing zero.\n */\nexport function mergeSeries(\n series: ResolvedSeries[],\n pointsBySeries: (TimeseriesPoint[] | undefined)[],\n): MergedRow[] {\n const rows = new Map<string, MergedRow>();\n series.forEach((s, i) => {\n for (const p of pointsBySeries[i] ?? []) {\n const row = rows.get(p.at) ?? { at: p.at };\n row[s.key] = s.transform ? s.transform(p.value) : p.value;\n rows.set(p.at, row);\n }\n });\n return [...rows.values()].sort((a, b) => a.at.localeCompare(b.at));\n}\n\nexport function TimeseriesPanel(props: TimeseriesPanelProps) {\n const {\n title,\n icon,\n unit,\n range = \"1h\",\n refreshMs = 5000,\n height = 160,\n variant = \"area\",\n expandable = true,\n total,\n fetcher = defaultFetcher,\n className,\n } = props;\n const isBreakdown = variant === \"breakdown\";\n // The inline chart (non-breakdown only) and the expand modal both need a\n // time-series variant; breakdown has no inline chart and expands to \"area\".\n const chartVariant: ChartVariant = isBreakdown ? \"area\" : variant;\n const expandVariant = props.expandVariant ?? chartVariant;\n\n const [expanded, setExpanded] = useState(false);\n\n const series = useMemo(() => resolveSeries(props), [props]);\n const requestUrls = useMemo(\n () =>\n series.map((s) => {\n const u = new URL(s.url, window.location.origin);\n if (range) u.searchParams.set(\"since\", range);\n return u.pathname + u.search;\n }),\n [series, range],\n );\n\n const results = useQueries({\n queries: requestUrls.map((requestUrl) => ({\n queryKey: [\"timeseries\", requestUrl],\n queryFn: () => fetcher(requestUrl),\n refetchInterval: refreshMs > 0 ? refreshMs : false,\n staleTime: 0,\n retry: 0,\n })),\n });\n\n const isError = results.some((r) => r.isError);\n const error = results.find((r) => r.isError)?.error;\n const isLoading = results.some((r) => r.isLoading) && results.every((r) => !r.data);\n const pointsBySeries = results.map((r) => r.data?.points);\n const rows = useMemo(() => mergeSeries(series, pointsBySeries), [series, pointsBySeries]);\n const hasMirrored = series.some((s) => s.transform);\n const breakdown = useMemo(\n () => (isBreakdown ? resolveBreakdown(series, rows, total) : null),\n [isBreakdown, series, rows, total],\n );\n\n // Breakdown renders instantly from `current`; the modal still needs polled\n // history. Other variants gate on having ≥2 points to draw a line.\n const canExpand = expandable && rows.length >= 2;\n\n return (\n <div className={cn(\"flex flex-col rounded-lg border border-border bg-card p-3\", className)}>\n <div className=\"flex items-center justify-between gap-2 text-xs text-muted-foreground\">\n <span className=\"inline-flex min-w-0 items-center gap-1.5\">\n {icon ? <PanelIcon icon={icon} /> : null}\n <span className=\"truncate font-medium text-foreground\">{title}</span>\n </span>\n <span className=\"inline-flex shrink-0 items-center gap-1.5\">\n {breakdown ? (\n <BreakdownReadout total={breakdown.total} unit={unit} items={breakdown.items} />\n ) : (\n <LatestReadout series={series} rows={rows} />\n )}\n {canExpand ? (\n <button\n type=\"button\"\n aria-label=\"Expand chart\"\n onClick={() => setExpanded(true)}\n className=\"text-muted-foreground transition-colors hover:text-foreground\"\n >\n <Icon icon={UiFullscreen} width={14} height={14} />\n </button>\n ) : null}\n </span>\n </div>\n <div className=\"mt-2\" style={breakdown ? undefined : { height }}>\n {breakdown ? (\n <BreakdownView total={breakdown.total} unit={unit} items={breakdown.items} />\n ) : isError ? (\n <PanelMessage>{(error as Error)?.message ?? \"Failed to load metric\"}</PanelMessage>\n ) : isLoading ? (\n <PanelMessage>Loading…</PanelMessage>\n ) : rows.length < 2 ? (\n <PanelMessage>Collecting data…</PanelMessage>\n ) : (\n <Chart rows={rows} series={series} variant={chartVariant} unit={unit} showZeroLine={hasMirrored} />\n )}\n </div>\n {!breakdown && !isError && !isLoading && rows.length >= 2 && series.length > 1 ? (\n <ChartLegend series={series} rows={rows} />\n ) : null}\n {canExpand ? (\n <Modal open={expanded} onClose={() => setExpanded(false)} title={title} size=\"xl\">\n <div style={{ height: 360 }}>\n <Chart rows={rows} series={series} variant={expandVariant} unit={unit} showZeroLine={hasMirrored} />\n </div>\n {series.length > 1 ? <ChartLegend series={series} rows={rows} /> : null}\n </Modal>\n ) : null}\n </div>\n );\n}\n\n/**\n * Header readout for a single-series panel: the latest value, formatted with the\n * series' unit. Multi-series panels render the per-series values in {@link ChartLegend}\n * below the chart instead, so this returns null for them to avoid overlapping the title.\n */\nfunction LatestReadout({ series, rows }: { series: ResolvedSeries[]; rows: MergedRow[] }) {\n const only = series.length === 1 ? series[0] : undefined;\n if (!only) return null;\n const v = latestOf(rows, only.key);\n if (v === undefined) return null;\n return <span className=\"tabular-nums\">{formatUnit(Math.abs(v), only.unit)}</span>;\n}\n\n/** Wrapping color-keyed legend for the time-series variants: dot + label + latest value. */\nfunction ChartLegend({ series, rows }: { series: ResolvedSeries[]; rows: MergedRow[] }) {\n return (\n <ul className=\"mt-1.5 flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground\">\n {series.map((s) => {\n const v = latestOf(rows, s.key);\n return (\n <li key={s.key} className=\"inline-flex min-w-0 items-center gap-1.5\">\n <span\n className=\"h-2 w-2 shrink-0 rounded-full\"\n style={{ backgroundColor: resolveCssColor(s.color) }}\n aria-hidden\n />\n <span className=\"truncate text-foreground\">{s.label}</span>\n {v !== undefined ? (\n <span className=\"tabular-nums\">{formatUnit(Math.abs(v), s.unit)}</span>\n ) : null}\n </li>\n );\n })}\n </ul>\n );\n}\n\n/** Breakdown header readout: `used / total · pct%`, where used is the sum of segments. */\nfunction BreakdownReadout({\n total,\n unit,\n items,\n}: {\n total: number;\n unit: string | undefined;\n items: BreakdownItem[];\n}) {\n const used = items.reduce((acc, it) => acc + it.value, 0);\n const pct = total > 0 ? Math.min(100, (used / total) * 100) : 0;\n return (\n <span className=\"font-mono tabular-nums\">\n {formatUnit(used, unit)} / {formatUnit(total, unit)} · {pct.toFixed(0)}%\n </span>\n );\n}\n\n/** Instantaneous stacked bar + legend list. The expand button (in the panel header) opens the graph. */\nfunction BreakdownView({\n total,\n unit,\n items,\n}: {\n total: number;\n unit: string | undefined;\n items: BreakdownItem[];\n}) {\n const segments: ProgressSegment[] = items.map((it) => ({\n count: it.value,\n color: it.color,\n label: it.label,\n }));\n return (\n <div className=\"flex flex-col gap-2\">\n <ProgressBar segments={segments} total={total > 0 ? total : 1} height=\"h-3\" />\n {items.length > 0 ? (\n <ul className=\"grid grid-cols-1 gap-y-1 text-xs\">\n {items.map((it) => (\n <li key={it.key} className=\"flex items-center gap-2\">\n <span\n className=\"h-2 w-2 shrink-0 rounded-full\"\n style={{ backgroundColor: resolveCssColor(it.color) }}\n aria-hidden\n />\n <span className=\"min-w-0 flex-1 truncate font-mono text-muted-foreground\">\n {it.label}\n </span>\n <span className=\"font-mono tabular-nums text-foreground\">\n {formatUnit(it.value, it.unit ?? unit)}\n </span>\n <span className=\"w-10 text-right font-mono tabular-nums text-muted-foreground\">\n {it.percent.toFixed(0)}%\n </span>\n </li>\n ))}\n </ul>\n ) : null}\n </div>\n );\n}\n\ntype ChartVariant = \"area\" | \"line\" | \"stacked\";\n\nfunction Chart({\n rows,\n series,\n variant,\n unit,\n showZeroLine,\n}: {\n rows: MergedRow[];\n series: ResolvedSeries[];\n variant: ChartVariant;\n unit: string | undefined;\n showZeroLine: boolean;\n}) {\n const stacked = variant === \"stacked\";\n // Mirrored series carry negative values; show magnitudes on axis and tooltip.\n const seriesByKey = new Map(series.map((s) => [s.key, s]));\n // recharts needs a CSS color value; a series may carry a Tailwind class.\n const strokeOf = (s: ResolvedSeries) => resolveCssColor(s.color);\n // Distinct units map to a left and (when present) right axis; each series draws\n // against the axis for its unit so mixed-unit panels keep independent scales.\n const { axes: yAxes, axisOfKey } = useMemo(() => assignAxes(series), [series]);\n const axisOf = (key: string): \"left\" | \"right\" => axisOfKey.get(key) ?? \"left\";\n const axes = (\n <>\n <CartesianGrid strokeOpacity={0.12} vertical={false} />\n <XAxis\n dataKey=\"at\"\n tickFormatter={formatClock}\n tick={{ fontSize: 10 }}\n stroke=\"currentColor\"\n strokeOpacity={0.35}\n minTickGap={32}\n />\n {yAxes.map((ax) => (\n <YAxis\n key={ax.id}\n yAxisId={ax.id}\n orientation={ax.orientation}\n tick={{ fontSize: 10 }}\n stroke=\"currentColor\"\n strokeOpacity={0.35}\n width={40}\n tickFormatter={(v: number) => formatUnit(Math.abs(v), ax.unit)}\n />\n ))}\n <Tooltip\n labelFormatter={(label) => formatClock(String(label))}\n formatter={(value, name) => {\n const s = seriesByKey.get(String(name));\n return [formatUnit(Math.abs(Number(value) || 0), s?.unit ?? unit), s?.label ?? String(name)];\n }}\n contentStyle={{ fontSize: 12 }}\n />\n {showZeroLine ? (\n <ReferenceLine yAxisId=\"left\" y={0} stroke=\"currentColor\" strokeOpacity={0.35} />\n ) : null}\n </>\n );\n\n return (\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n {variant === \"line\" ? (\n <LineChart data={rows} margin={{ top: 4, right: 8, bottom: 0, left: 0 }}>\n {axes}\n {series.map((s) => (\n <Line\n key={s.key}\n yAxisId={axisOf(s.key)}\n type=\"monotone\"\n dataKey={s.key}\n name={s.key}\n stroke={strokeOf(s)}\n strokeWidth={2}\n dot={false}\n connectNulls\n isAnimationActive={false}\n />\n ))}\n </LineChart>\n ) : (\n <AreaChart data={rows} margin={{ top: 4, right: 8, bottom: 0, left: 0 }}>\n {axes}\n {series.map((s) => (\n <Area\n key={s.key}\n yAxisId={axisOf(s.key)}\n type=\"monotone\"\n dataKey={s.key}\n name={s.key}\n stroke={strokeOf(s)}\n fill={strokeOf(s)}\n {...(stacked ? { stackId: `stack-${axisOf(s.key)}` } : {})}\n fillOpacity={stacked ? 0.7 : 0.12}\n strokeWidth={stacked ? 0 : 2}\n connectNulls\n isAnimationActive={false}\n />\n ))}\n </AreaChart>\n )}\n </ResponsiveContainer>\n );\n}\n\nfunction PanelMessage({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"flex h-full items-center justify-center text-xs text-muted-foreground\">\n {children}\n </div>\n );\n}\n\nfunction PanelIcon({ icon }: { icon: string | StaticIconComponent }) {\n if (typeof icon === \"string\") {\n return <Icon name={icon} width={16} height={16} className=\"text-muted-foreground\" />;\n }\n return <Icon icon={icon} width={16} height={16} className=\"text-muted-foreground\" />;\n}\n"],"names":["_a"],"mappings":";;;;;;;;;;;;AAmHA,MAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,eAAe,QAAQ,eAAe,MAAM,KAAK,eAAe,CAAC;AAC1E;AAiBO,SAAS,cAAc,OAA+C;AAC3E,QAAM,OAAO,MAAM,WAAW;AAC9B,QAAM,OAAO,MAAM,WAAW,MAAM,MAAM,CAAC,EAAE,IAAI,MAAM,IAAA,CAAK,IAAI,CAAA;AAChE,SAAO,KAAK,IAAI,CAAC,GAAG,OAAO;AAAA,IACzB,KAAK,EAAE;AAAA,IACP,KAAK,OAAO,EAAE;AAAA,IACd,OAAO,EAAE,SAAS,EAAE;AAAA,IACpB,OAAO,EAAE,SAAS,aAAa,CAAC;AAAA,IAChC,GAAI,EAAE,QAAQ,MAAM,OAAO,EAAE,MAAM,EAAE,QAAQ,MAAM,KAAA,IAAS,CAAA;AAAA,IAC5D,GAAI,EAAE,YAAY,EAAE,WAAW,EAAE,UAAA,IAAc,CAAA;AAAA,IAC/C,GAAI,EAAE,YAAY,SAAY,EAAE,SAAS,EAAE,YAAY,CAAA;AAAA,EAAC,EACxD;AACJ;AAoBO,SAAS,iBACd,QACA,MACA,OAC2C;AAC3C,QAAM,YAAY,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,OAAO,EAAE,WAAW,SAAS,MAAM,EAAE,GAAG,KAAK,IAAI;AAC3F,QAAM,QAAQ,SAAS,UAAU,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;AACpE,QAAM,QAAQ,UAAU,IAAI,CAAC,EAAE,GAAG,aAAa;AAAA,IAC7C,KAAK,EAAE;AAAA,IACP,OAAO,EAAE;AAAA,IACT,OAAO,EAAE;AAAA,IACT,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAA,IAAS,CAAA;AAAA,IAChC;AAAA,IACA,SAAS,QAAQ,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,GAAI,QAAQ,QAAS,GAAG,CAAC,IAAI;AAAA,EAAA,EACzE;AACF,SAAO,EAAE,OAAO,OAAO,MAAA;AACzB;AAEA,MAAM,iBAAiB,OAAO,QAA6C;AACzE,QAAM,MAAM,MAAM,MAAM,GAAG;AAC3B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,2BAA2B,IAAI,MAAM,EAAE;AACpE,SAAO,IAAI,KAAA;AACb;AAEA,SAAS,YAAY,IAAoB;AACvC,QAAM,OAAO,IAAI,KAAK,EAAE;AACxB,MAAI,OAAO,MAAM,KAAK,QAAA,CAAS,EAAG,QAAO;AACzC,SAAO,KAAK,mBAAmB,IAAI,EAAE,MAAM,WAAW,QAAQ,WAAW;AAC3E;AAiBO,SAAS,YACd,QACA,gBACa;AACb,QAAM,2BAAW,IAAA;AACjB,SAAO,QAAQ,CAAC,GAAG,MAAM;AACvB,eAAW,KAAK,eAAe,CAAC,KAAK,CAAA,GAAI;AACvC,YAAM,MAAM,KAAK,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAA;AACtC,UAAI,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE;AACpD,WAAK,IAAI,EAAE,IAAI,GAAG;AAAA,IACpB;AAAA,EACF,CAAC;AACD,SAAO,CAAC,GAAG,KAAK,OAAA,CAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AACnE;AAEO,SAAS,gBAAgB,OAA6B;;AAC3D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,UAAU;AAAA,IACV,aAAa;AAAA,IACb;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EAAA,IACE;AACJ,QAAM,cAAc,YAAY;AAGhC,QAAM,eAA6B,cAAc,SAAS;AAC1D,QAAM,gBAAgB,MAAM,iBAAiB;AAE7C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAE9C,QAAM,SAAS,QAAQ,MAAM,cAAc,KAAK,GAAG,CAAC,KAAK,CAAC;AAC1D,QAAM,cAAc;AAAA,IAClB,MACE,OAAO,IAAI,CAAC,MAAM;AAChB,YAAM,IAAI,IAAI,IAAI,EAAE,KAAK,OAAO,SAAS,MAAM;AAC/C,UAAI,MAAO,GAAE,aAAa,IAAI,SAAS,KAAK;AAC5C,aAAO,EAAE,WAAW,EAAE;AAAA,IACxB,CAAC;AAAA,IACH,CAAC,QAAQ,KAAK;AAAA,EAAA;AAGhB,QAAM,UAAU,WAAW;AAAA,IACzB,SAAS,YAAY,IAAI,CAAC,gBAAgB;AAAA,MACxC,UAAU,CAAC,cAAc,UAAU;AAAA,MACnC,SAAS,MAAM,QAAQ,UAAU;AAAA,MACjC,iBAAiB,YAAY,IAAI,YAAY;AAAA,MAC7C,WAAW;AAAA,MACX,OAAO;AAAA,IAAA,EACP;AAAA,EAAA,CACH;AAED,QAAM,UAAU,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO;AAC7C,QAAM,SAAQ,aAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,MAA7B,mBAAgC;AAC9C,QAAM,YAAY,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,KAAK,QAAQ,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI;AAClF,QAAM,iBAAiB,QAAQ,IAAI,CAAC;;AAAM,YAAAA,MAAA,EAAE,SAAF,gBAAAA,IAAQ;AAAA,GAAM;AACxD,QAAM,OAAO,QAAQ,MAAM,YAAY,QAAQ,cAAc,GAAG,CAAC,QAAQ,cAAc,CAAC;AACxF,QAAM,cAAc,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS;AAClD,QAAM,YAAY;AAAA,IAChB,MAAO,cAAc,iBAAiB,QAAQ,MAAM,KAAK,IAAI;AAAA,IAC7D,CAAC,aAAa,QAAQ,MAAM,KAAK;AAAA,EAAA;AAKnC,QAAM,YAAY,cAAc,KAAK,UAAU;AAE/C,8BACG,OAAA,EAAI,WAAW,GAAG,6DAA6D,SAAS,GACvF,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,yEACb,UAAA;AAAA,MAAA,qBAAC,QAAA,EAAK,WAAU,4CACb,UAAA;AAAA,QAAA,OAAO,oBAAC,WAAA,EAAU,KAAA,CAAY,IAAK;AAAA,QACpC,oBAAC,QAAA,EAAK,WAAU,wCAAwC,UAAA,MAAA,CAAM;AAAA,MAAA,GAChE;AAAA,MACA,qBAAC,QAAA,EAAK,WAAU,6CACb,UAAA;AAAA,QAAA,YACC,oBAAC,kBAAA,EAAiB,OAAO,UAAU,OAAO,MAAY,OAAO,UAAU,MAAA,CAAO,IAE9E,oBAAC,eAAA,EAAc,QAAgB,MAAY;AAAA,QAE5C,YACC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,cAAW;AAAA,YACX,SAAS,MAAM,YAAY,IAAI;AAAA,YAC/B,WAAU;AAAA,YAEV,8BAAC,MAAA,EAAK,MAAM,cAAc,OAAO,IAAI,QAAQ,GAAA,CAAI;AAAA,UAAA;AAAA,QAAA,IAEjD;AAAA,MAAA,EAAA,CACN;AAAA,IAAA,GACF;AAAA,IACA,oBAAC,SAAI,WAAU,QAAO,OAAO,YAAY,SAAY,EAAE,OAAA,GACpD,UAAA,gCACE,eAAA,EAAc,OAAO,UAAU,OAAO,MAAY,OAAO,UAAU,OAAO,IACzE,UACF,oBAAC,cAAA,EAAe,0CAAiB,YAAW,wBAAA,CAAwB,IAClE,YACF,oBAAC,gBAAa,UAAA,WAAA,CAAQ,IACpB,KAAK,SAAS,IAChB,oBAAC,gBAAa,UAAA,mBAAA,CAAgB,IAE9B,oBAAC,OAAA,EAAM,MAAY,QAAgB,SAAS,cAAc,MAAY,cAAc,YAAA,CAAa,EAAA,CAErG;AAAA,IACC,CAAC,aAAa,CAAC,WAAW,CAAC,aAAa,KAAK,UAAU,KAAK,OAAO,SAAS,IAC3E,oBAAC,aAAA,EAAY,QAAgB,MAAY,IACvC;AAAA,IACH,YACC,qBAAC,OAAA,EAAM,MAAM,UAAU,SAAS,MAAM,YAAY,KAAK,GAAG,OAAc,MAAK,MAC3E,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,OAAO,EAAE,QAAQ,OACpB,UAAA,oBAAC,OAAA,EAAM,MAAY,QAAgB,SAAS,eAAe,MAAY,cAAc,aAAa,GACpG;AAAA,MACC,OAAO,SAAS,wBAAK,aAAA,EAAY,QAAgB,MAAY,IAAK;AAAA,IAAA,EAAA,CACrE,IACE;AAAA,EAAA,GACN;AAEJ;AAOA,SAAS,cAAc,EAAE,QAAQ,QAAyD;AACxF,QAAM,OAAO,OAAO,WAAW,IAAI,OAAO,CAAC,IAAI;AAC/C,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,IAAI,SAAS,MAAM,KAAK,GAAG;AACjC,MAAI,MAAM,OAAW,QAAO;AAC5B,SAAO,oBAAC,QAAA,EAAK,WAAU,gBAAgB,UAAA,WAAW,KAAK,IAAI,CAAC,GAAG,KAAK,IAAI,EAAA,CAAE;AAC5E;AAGA,SAAS,YAAY,EAAE,QAAQ,QAAyD;AACtF,6BACG,MAAA,EAAG,WAAU,uEACX,UAAA,OAAO,IAAI,CAAC,MAAM;AACjB,UAAM,IAAI,SAAS,MAAM,EAAE,GAAG;AAC9B,WACE,qBAAC,MAAA,EAAe,WAAU,4CACxB,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,EAAE,iBAAiB,gBAAgB,EAAE,KAAK,EAAA;AAAA,UACjD,eAAW;AAAA,QAAA;AAAA,MAAA;AAAA,MAEb,oBAAC,QAAA,EAAK,WAAU,4BAA4B,YAAE,OAAM;AAAA,MACnD,MAAM,SACL,oBAAC,QAAA,EAAK,WAAU,gBAAgB,UAAA,WAAW,KAAK,IAAI,CAAC,GAAG,EAAE,IAAI,GAAE,IAC9D;AAAA,IAAA,EAAA,GATG,EAAE,GAUX;AAAA,EAEJ,CAAC,EAAA,CACH;AAEJ;AAGA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,OAAO,MAAM,OAAO,CAAC,KAAK,OAAO,MAAM,GAAG,OAAO,CAAC;AACxD,QAAM,MAAM,QAAQ,IAAI,KAAK,IAAI,KAAM,OAAO,QAAS,GAAG,IAAI;AAC9D,SACE,qBAAC,QAAA,EAAK,WAAU,0BACb,UAAA;AAAA,IAAA,WAAW,MAAM,IAAI;AAAA,IAAE;AAAA,IAAI,WAAW,OAAO,IAAI;AAAA,IAAE;AAAA,IAAI,IAAI,QAAQ,CAAC;AAAA,IAAE;AAAA,EAAA,GACzE;AAEJ;AAGA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,WAA8B,MAAM,IAAI,CAAC,QAAQ;AAAA,IACrD,OAAO,GAAG;AAAA,IACV,OAAO,GAAG;AAAA,IACV,OAAO,GAAG;AAAA,EAAA,EACV;AACF,SACE,qBAAC,OAAA,EAAI,WAAU,uBACb,UAAA;AAAA,IAAA,oBAAC,aAAA,EAAY,UAAoB,OAAO,QAAQ,IAAI,QAAQ,GAAG,QAAO,MAAA,CAAM;AAAA,IAC3E,MAAM,SAAS,IACd,oBAAC,QAAG,WAAU,oCACX,UAAA,MAAM,IAAI,CAAC,OACV,qBAAC,MAAA,EAAgB,WAAU,2BACzB,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,EAAE,iBAAiB,gBAAgB,GAAG,KAAK,EAAA;AAAA,UAClD,eAAW;AAAA,QAAA;AAAA,MAAA;AAAA,MAEb,oBAAC,QAAA,EAAK,WAAU,2DACb,aAAG,OACN;AAAA,MACA,oBAAC,QAAA,EAAK,WAAU,0CACb,UAAA,WAAW,GAAG,OAAO,GAAG,QAAQ,IAAI,EAAA,CACvC;AAAA,MACA,qBAAC,QAAA,EAAK,WAAU,gEACb,UAAA;AAAA,QAAA,GAAG,QAAQ,QAAQ,CAAC;AAAA,QAAE;AAAA,MAAA,EAAA,CACzB;AAAA,IAAA,EAAA,GAdO,GAAG,GAeZ,CACD,EAAA,CACH,IACE;AAAA,EAAA,GACN;AAEJ;AAIA,SAAS,MAAM;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAM,UAAU,YAAY;AAE5B,QAAM,cAAc,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAEzD,QAAM,WAAW,CAAC,MAAsB,gBAAgB,EAAE,KAAK;AAG/D,QAAM,EAAE,MAAM,OAAO,cAAc,QAAQ,MAAM,WAAW,MAAM,GAAG,CAAC,MAAM,CAAC;AAC7E,QAAM,SAAS,CAAC,QAAkC,UAAU,IAAI,GAAG,KAAK;AACxE,QAAM,OACJ,qBAAA,UAAA,EACE,UAAA;AAAA,IAAA,oBAAC,eAAA,EAAc,eAAe,MAAM,UAAU,OAAO;AAAA,IACrD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,eAAe;AAAA,QACf,MAAM,EAAE,UAAU,GAAA;AAAA,QAClB,QAAO;AAAA,QACP,eAAe;AAAA,QACf,YAAY;AAAA,MAAA;AAAA,IAAA;AAAA,IAEb,MAAM,IAAI,CAAC,OACV;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,SAAS,GAAG;AAAA,QACZ,aAAa,GAAG;AAAA,QAChB,MAAM,EAAE,UAAU,GAAA;AAAA,QAClB,QAAO;AAAA,QACP,eAAe;AAAA,QACf,OAAO;AAAA,QACP,eAAe,CAAC,MAAc,WAAW,KAAK,IAAI,CAAC,GAAG,GAAG,IAAI;AAAA,MAAA;AAAA,MAPxD,GAAG;AAAA,IAAA,CASX;AAAA,IACD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,gBAAgB,CAAC,UAAU,YAAY,OAAO,KAAK,CAAC;AAAA,QACpD,WAAW,CAAC,OAAO,SAAS;AAC1B,gBAAM,IAAI,YAAY,IAAI,OAAO,IAAI,CAAC;AACtC,iBAAO,CAAC,WAAW,KAAK,IAAI,OAAO,KAAK,KAAK,CAAC,IAAG,uBAAG,SAAQ,IAAI,IAAG,uBAAG,UAAS,OAAO,IAAI,CAAC;AAAA,QAC7F;AAAA,QACA,cAAc,EAAE,UAAU,GAAA;AAAA,MAAG;AAAA,IAAA;AAAA,IAE9B,eACC,oBAAC,eAAA,EAAc,SAAQ,QAAO,GAAG,GAAG,QAAO,gBAAe,eAAe,KAAA,CAAM,IAC7E;AAAA,EAAA,GACN;AAGF,SACE,oBAAC,uBAAoB,OAAM,QAAO,QAAO,QACtC,UAAA,YAAY,SACX,qBAAC,WAAA,EAAU,MAAM,MAAM,QAAQ,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,EAAA,GACjE,UAAA;AAAA,IAAA;AAAA,IACA,OAAO,IAAI,CAAC,MACX;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,SAAS,OAAO,EAAE,GAAG;AAAA,QACrB,MAAK;AAAA,QACL,SAAS,EAAE;AAAA,QACX,MAAM,EAAE;AAAA,QACR,QAAQ,SAAS,CAAC;AAAA,QAClB,aAAa;AAAA,QACb,KAAK;AAAA,QACL,cAAY;AAAA,QACZ,mBAAmB;AAAA,MAAA;AAAA,MATd,EAAE;AAAA,IAAA,CAWV;AAAA,EAAA,EAAA,CACH,IAEA,qBAAC,WAAA,EAAU,MAAM,MAAM,QAAQ,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,KACjE,UAAA;AAAA,IAAA;AAAA,IACA,OAAO,IAAI,CAAC,MACX;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,SAAS,OAAO,EAAE,GAAG;AAAA,QACrB,MAAK;AAAA,QACL,SAAS,EAAE;AAAA,QACX,MAAM,EAAE;AAAA,QACR,QAAQ,SAAS,CAAC;AAAA,QAClB,MAAM,SAAS,CAAC;AAAA,QACf,GAAI,UAAU,EAAE,SAAS,SAAS,OAAO,EAAE,GAAG,CAAC,GAAA,IAAO,CAAA;AAAA,QACvD,aAAa,UAAU,MAAM;AAAA,QAC7B,aAAa,UAAU,IAAI;AAAA,QAC3B,cAAY;AAAA,QACZ,mBAAmB;AAAA,MAAA;AAAA,MAXd,EAAE;AAAA,IAAA,CAaV;AAAA,EAAA,EAAA,CACH,EAAA,CAEJ;AAEJ;AAEA,SAAS,aAAa,EAAE,YAA2C;AACjE,SACE,oBAAC,OAAA,EAAI,WAAU,yEACZ,SAAA,CACH;AAEJ;AAEA,SAAS,UAAU,EAAE,QAAgD;AACnE,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO,oBAAC,QAAK,MAAM,MAAM,OAAO,IAAI,QAAQ,IAAI,WAAU,wBAAA,CAAwB;AAAA,EACpF;AACA,SAAO,oBAAC,QAAK,MAAY,OAAO,IAAI,QAAQ,IAAI,WAAU,yBAAwB;AACpF;"}
|
|
1
|
+
{"version":3,"file":"TimeseriesPanel.js","sources":["../../src/data/TimeseriesPanel.tsx"],"sourcesContent":["import { useQueries } from \"@tanstack/react-query\";\nimport { useMemo, useState } from \"react\";\nimport {\n Area,\n AreaChart,\n CartesianGrid,\n Line,\n LineChart,\n ReferenceLine,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport { cn } from \"../lib/utils\";\nimport { resolveCssColor } from \"../lib/color\";\nimport { formatUnit } from \"../lib/format\";\nimport { Modal } from \"../overlay/Modal\";\nimport { ProgressBar, type ProgressSegment } from \"./ProgressBar\";\nimport { UiFullscreen } from \"../icons\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { assignAxes, latestOf } from \"./TimeseriesPanel.axes\";\nimport {\n mergeSeries,\n resolveBreakdown,\n resolveSeries,\n type BreakdownItem,\n type MergedRow,\n type ResolvedSeries,\n type TimeseriesPanelProps,\n type TimeseriesResponse,\n} from \"./TimeseriesPanel.model\";\n\nexport type { AxisAssignment, AxisOrientation, AxisSpec } from \"./TimeseriesPanel.axes\";\nexport type {\n BreakdownItem,\n MergedRow,\n ResolvedSeries,\n TimeseriesPanelProps,\n TimeseriesPoint,\n TimeseriesResponse,\n TimeseriesSeries,\n} from \"./TimeseriesPanel.model\";\n\nconst defaultFetcher = async (url: string): Promise<TimeseriesResponse> => {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`metrics request failed: ${res.status}`);\n return res.json();\n};\n\nfunction formatClock(at: string): string {\n const date = new Date(at);\n if (Number.isNaN(date.getTime())) return \"\";\n return date.toLocaleTimeString([], { hour: \"2-digit\", minute: \"2-digit\" });\n}\n\nexport function TimeseriesPanel(props: TimeseriesPanelProps) {\n const {\n title,\n icon,\n unit,\n range = \"1h\",\n refreshMs = 5000,\n height = 160,\n variant = \"area\",\n expandable = true,\n total,\n fetcher = defaultFetcher,\n className,\n } = props;\n const isBreakdown = variant === \"breakdown\";\n // The inline chart (non-breakdown only) and the expand modal both need a\n // time-series variant; breakdown has no inline chart and expands to \"area\".\n const chartVariant: ChartVariant = isBreakdown ? \"area\" : variant;\n const expandVariant = props.expandVariant ?? chartVariant;\n\n const [expanded, setExpanded] = useState(false);\n\n const series = useMemo(() => resolveSeries(props), [props]);\n const requestUrls = useMemo(\n () =>\n series.map((s) => {\n const u = new URL(s.url, window.location.origin);\n if (range) u.searchParams.set(\"since\", range);\n return u.pathname + u.search;\n }),\n [series, range],\n );\n\n const results = useQueries({\n queries: requestUrls.map((requestUrl) => ({\n queryKey: [\"timeseries\", requestUrl],\n queryFn: () => fetcher(requestUrl),\n refetchInterval: refreshMs > 0 ? refreshMs : false,\n staleTime: 0,\n retry: 0,\n })),\n });\n\n const isError = results.some((r) => r.isError);\n const error = results.find((r) => r.isError)?.error;\n const isLoading = results.some((r) => r.isLoading) && results.every((r) => !r.data);\n const pointsBySeries = results.map((r) => r.data?.points);\n const rows = useMemo(() => mergeSeries(series, pointsBySeries), [series, pointsBySeries]);\n const hasMirrored = series.some((s) => s.transform);\n const breakdown = useMemo(\n () => (isBreakdown ? resolveBreakdown(series, rows, total) : null),\n [isBreakdown, series, rows, total],\n );\n\n // Breakdown renders instantly from `current`; the modal still needs polled\n // history. Other variants gate on having ≥2 points to draw a line.\n const canExpand = expandable && rows.length >= 2;\n\n return (\n <div className={cn(\"flex flex-col rounded-lg border border-border bg-card p-3\", className)}>\n <div className=\"flex items-center justify-between gap-2 text-xs text-muted-foreground\">\n <span className=\"inline-flex min-w-0 items-center gap-1.5\">\n {icon ? <PanelIcon icon={icon} /> : null}\n <span className=\"truncate font-medium text-foreground\">{title}</span>\n </span>\n <span className=\"inline-flex shrink-0 items-center gap-1.5\">\n {breakdown ? (\n <BreakdownReadout total={breakdown.total} unit={unit} items={breakdown.items} />\n ) : (\n <LatestReadout series={series} rows={rows} />\n )}\n {canExpand ? (\n <button\n type=\"button\"\n aria-label=\"Expand chart\"\n onClick={() => setExpanded(true)}\n className=\"text-muted-foreground transition-colors hover:text-foreground\"\n >\n <Icon icon={UiFullscreen} width={14} height={14} />\n </button>\n ) : null}\n </span>\n </div>\n <div className=\"mt-2\" style={breakdown ? undefined : { height }}>\n {breakdown ? (\n <BreakdownView total={breakdown.total} unit={unit} items={breakdown.items} />\n ) : isError ? (\n <PanelMessage>{(error as Error)?.message ?? \"Failed to load metric\"}</PanelMessage>\n ) : isLoading ? (\n <PanelMessage>Loading…</PanelMessage>\n ) : rows.length < 2 ? (\n <PanelMessage>Collecting data…</PanelMessage>\n ) : (\n <Chart rows={rows} series={series} variant={chartVariant} unit={unit} showZeroLine={hasMirrored} />\n )}\n </div>\n {!breakdown && !isError && !isLoading && rows.length >= 2 && series.length > 1 ? (\n <ChartLegend series={series} rows={rows} />\n ) : null}\n {canExpand ? (\n <Modal open={expanded} onClose={() => setExpanded(false)} title={title} size=\"xl\">\n <div style={{ height: 360 }}>\n <Chart rows={rows} series={series} variant={expandVariant} unit={unit} showZeroLine={hasMirrored} />\n </div>\n {series.length > 1 ? <ChartLegend series={series} rows={rows} /> : null}\n </Modal>\n ) : null}\n </div>\n );\n}\n\n/**\n * Header readout for a single-series panel: the latest value, formatted with the\n * series' unit. Multi-series panels render the per-series values in {@link ChartLegend}\n * below the chart instead, so this returns null for them to avoid overlapping the title.\n */\nfunction LatestReadout({ series, rows }: { series: ResolvedSeries[]; rows: MergedRow[] }) {\n const only = series.length === 1 ? series[0] : undefined;\n if (!only) return null;\n const v = latestOf(rows, only.key);\n if (v === undefined) return null;\n return <span className=\"tabular-nums\">{formatUnit(Math.abs(v), only.unit)}</span>;\n}\n\n/** Wrapping color-keyed legend for the time-series variants: dot + label + latest value. */\nfunction ChartLegend({ series, rows }: { series: ResolvedSeries[]; rows: MergedRow[] }) {\n return (\n <ul className=\"mt-1.5 flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground\">\n {series.map((s) => {\n const v = latestOf(rows, s.key);\n return (\n <li key={s.key} className=\"inline-flex min-w-0 items-center gap-1.5\">\n <span\n className=\"h-2 w-2 shrink-0 rounded-full\"\n style={{ backgroundColor: resolveCssColor(s.color) }}\n aria-hidden\n />\n <span className=\"truncate text-foreground\">{s.label}</span>\n {v !== undefined ? (\n <span className=\"tabular-nums\">{formatUnit(Math.abs(v), s.unit)}</span>\n ) : null}\n </li>\n );\n })}\n </ul>\n );\n}\n\n/** Breakdown header readout: `used / total · pct%`, where used is the sum of segments. */\nfunction BreakdownReadout({\n total,\n unit,\n items,\n}: {\n total: number;\n unit: string | undefined;\n items: BreakdownItem[];\n}) {\n const used = items.reduce((acc, it) => acc + it.value, 0);\n const pct = total > 0 ? Math.min(100, (used / total) * 100) : 0;\n return (\n <span className=\"font-mono tabular-nums\">\n {formatUnit(used, unit)} / {formatUnit(total, unit)} · {pct.toFixed(0)}%\n </span>\n );\n}\n\n/** Instantaneous stacked bar + legend list. The expand button (in the panel header) opens the graph. */\nfunction BreakdownView({\n total,\n unit,\n items,\n}: {\n total: number;\n unit: string | undefined;\n items: BreakdownItem[];\n}) {\n const segments: ProgressSegment[] = items.map((it) => ({\n count: it.value,\n color: it.color,\n label: it.label,\n }));\n return (\n <div className=\"flex flex-col gap-2\">\n <ProgressBar segments={segments} total={total > 0 ? total : 1} height=\"h-3\" />\n {items.length > 0 ? (\n <ul className=\"grid grid-cols-1 gap-y-1 text-xs\">\n {items.map((it) => (\n <li key={it.key} className=\"flex items-center gap-2\">\n <span\n className=\"h-2 w-2 shrink-0 rounded-full\"\n style={{ backgroundColor: resolveCssColor(it.color) }}\n aria-hidden\n />\n <span className=\"min-w-0 flex-1 truncate font-mono text-muted-foreground\">\n {it.label}\n </span>\n <span className=\"font-mono tabular-nums text-foreground\">\n {formatUnit(it.value, it.unit ?? unit)}\n </span>\n <span className=\"w-10 text-right font-mono tabular-nums text-muted-foreground\">\n {it.percent.toFixed(0)}%\n </span>\n </li>\n ))}\n </ul>\n ) : null}\n </div>\n );\n}\n\ntype ChartVariant = \"area\" | \"line\" | \"stacked\";\n\nfunction Chart({\n rows,\n series,\n variant,\n unit,\n showZeroLine,\n}: {\n rows: MergedRow[];\n series: ResolvedSeries[];\n variant: ChartVariant;\n unit: string | undefined;\n showZeroLine: boolean;\n}) {\n const stacked = variant === \"stacked\";\n // Mirrored series carry negative values; show magnitudes on axis and tooltip.\n const seriesByKey = new Map(series.map((s) => [s.key, s]));\n // recharts needs a CSS color value; a series may carry a Tailwind class.\n const strokeOf = (s: ResolvedSeries) => resolveCssColor(s.color);\n // Distinct units map to a left and (when present) right axis; each series draws\n // against the axis for its unit so mixed-unit panels keep independent scales.\n const { axes: yAxes, axisOfKey } = useMemo(() => assignAxes(series), [series]);\n const axisOf = (key: string): \"left\" | \"right\" => axisOfKey.get(key) ?? \"left\";\n const axes = (\n <>\n <CartesianGrid strokeOpacity={0.12} vertical={false} />\n <XAxis\n dataKey=\"at\"\n tickFormatter={formatClock}\n tick={{ fontSize: 10 }}\n stroke=\"currentColor\"\n strokeOpacity={0.35}\n minTickGap={32}\n />\n {yAxes.map((ax) => (\n <YAxis\n key={ax.id}\n yAxisId={ax.id}\n orientation={ax.orientation}\n tick={{ fontSize: 10 }}\n stroke=\"currentColor\"\n strokeOpacity={0.35}\n width={40}\n tickFormatter={(v: number) => formatUnit(Math.abs(v), ax.unit)}\n />\n ))}\n <Tooltip\n labelFormatter={(label) => formatClock(String(label))}\n formatter={(value, name) => {\n const s = seriesByKey.get(String(name));\n return [formatUnit(Math.abs(Number(value) || 0), s?.unit ?? unit), s?.label ?? String(name)];\n }}\n contentStyle={{ fontSize: 12 }}\n />\n {showZeroLine ? (\n <ReferenceLine yAxisId=\"left\" y={0} stroke=\"currentColor\" strokeOpacity={0.35} />\n ) : null}\n </>\n );\n\n return (\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n {variant === \"line\" ? (\n <LineChart data={rows} margin={{ top: 4, right: 8, bottom: 0, left: 0 }}>\n {axes}\n {series.map((s) => (\n <Line\n key={s.key}\n yAxisId={axisOf(s.key)}\n type=\"monotone\"\n dataKey={s.key}\n name={s.key}\n stroke={strokeOf(s)}\n strokeWidth={2}\n dot={false}\n connectNulls\n isAnimationActive={false}\n />\n ))}\n </LineChart>\n ) : (\n <AreaChart data={rows} margin={{ top: 4, right: 8, bottom: 0, left: 0 }}>\n {axes}\n {series.map((s) => (\n <Area\n key={s.key}\n yAxisId={axisOf(s.key)}\n type=\"monotone\"\n dataKey={s.key}\n name={s.key}\n stroke={strokeOf(s)}\n fill={strokeOf(s)}\n {...(stacked ? { stackId: `stack-${axisOf(s.key)}` } : {})}\n fillOpacity={stacked ? 0.7 : 0.12}\n strokeWidth={stacked ? 0 : 2}\n connectNulls\n isAnimationActive={false}\n />\n ))}\n </AreaChart>\n )}\n </ResponsiveContainer>\n );\n}\n\nfunction PanelMessage({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"flex h-full items-center justify-center text-xs text-muted-foreground\">\n {children}\n </div>\n );\n}\n\nfunction PanelIcon({ icon }: { icon: string | StaticIconComponent }) {\n if (typeof icon === \"string\") {\n return <Icon name={icon} width={16} height={16} className=\"text-muted-foreground\" />;\n }\n return <Icon icon={icon} width={16} height={16} className=\"text-muted-foreground\" />;\n}\n"],"names":["_a"],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const TimeseriesPanel_axes = require("./TimeseriesPanel.axes.cjs");
|
|
4
|
+
const SERIES_PALETTE = [
|
|
5
|
+
"var(--chart-1, #3b82f6)",
|
|
6
|
+
"var(--chart-2, #ef4444)",
|
|
7
|
+
"var(--chart-3, #10b981)",
|
|
8
|
+
"var(--chart-4, #f59e0b)"
|
|
9
|
+
];
|
|
10
|
+
function paletteColor(index) {
|
|
11
|
+
return SERIES_PALETTE[index % SERIES_PALETTE.length] ?? SERIES_PALETTE[0];
|
|
12
|
+
}
|
|
13
|
+
function resolveSeries(props) {
|
|
14
|
+
const base = props.baseUrl ?? "";
|
|
15
|
+
const list = props.series ?? (props.url ? [{ id: props.url }] : []);
|
|
16
|
+
return list.map((s, i) => ({
|
|
17
|
+
key: s.id,
|
|
18
|
+
url: base + s.id,
|
|
19
|
+
label: s.label ?? s.id,
|
|
20
|
+
color: s.color ?? paletteColor(i),
|
|
21
|
+
...s.unit ?? props.unit ? { unit: s.unit ?? props.unit } : {},
|
|
22
|
+
...s.transform ? { transform: s.transform } : {},
|
|
23
|
+
...s.current !== void 0 ? { current: s.current } : {}
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
function resolveBreakdown(series, rows, total) {
|
|
27
|
+
const withValue = series.map((s) => ({ s, value: s.current ?? TimeseriesPanel_axes.latestOf(rows, s.key) ?? 0 }));
|
|
28
|
+
const denom = total ?? withValue.reduce((acc, w) => acc + w.value, 0);
|
|
29
|
+
const items = withValue.map(({ s, value }) => ({
|
|
30
|
+
key: s.key,
|
|
31
|
+
label: s.label,
|
|
32
|
+
color: s.color,
|
|
33
|
+
...s.unit ? { unit: s.unit } : {},
|
|
34
|
+
value,
|
|
35
|
+
percent: denom > 0 ? Math.min(100, Math.max(0, value / denom * 100)) : 0
|
|
36
|
+
}));
|
|
37
|
+
return { items, total: denom };
|
|
38
|
+
}
|
|
39
|
+
function mergeSeries(series, pointsBySeries) {
|
|
40
|
+
const rows = /* @__PURE__ */ new Map();
|
|
41
|
+
series.forEach((s, i) => {
|
|
42
|
+
for (const p of pointsBySeries[i] ?? []) {
|
|
43
|
+
const row = rows.get(p.at) ?? { at: p.at };
|
|
44
|
+
row[s.key] = s.transform ? s.transform(p.value) : p.value;
|
|
45
|
+
rows.set(p.at, row);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return [...rows.values()].sort((a, b) => a.at.localeCompare(b.at));
|
|
49
|
+
}
|
|
50
|
+
exports.mergeSeries = mergeSeries;
|
|
51
|
+
exports.resolveBreakdown = resolveBreakdown;
|
|
52
|
+
exports.resolveSeries = resolveSeries;
|
|
53
|
+
//# sourceMappingURL=TimeseriesPanel.model.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimeseriesPanel.model.cjs","sources":["../../src/data/TimeseriesPanel.model.ts"],"sourcesContent":["import type { StaticIconComponent } from \"./Icon\";\nimport { latestOf } from \"./TimeseriesPanel.axes\";\n\nexport interface TimeseriesPoint {\n at: string;\n value: number;\n}\n\nexport interface TimeseriesResponse {\n id: string;\n points: TimeseriesPoint[];\n}\n\n/** One metric plotted on a panel. Its request URL is `baseUrl + id`. */\nexport interface TimeseriesSeries {\n /** Metric id appended to the panel's baseUrl, e.g. \"sqlserver.iops.read\". */\n id: string;\n /** Tooltip/legend label; defaults to the id. */\n label?: string;\n /**\n * Maps each point's value before plotting, e.g. writes pass `(v) => -v` to\n * render below the zero axis. Identity when omitted.\n */\n transform?: (value: number) => number;\n /**\n * Stroke/fill override as a CSS color value or a Tailwind color class.\n * Defaults cycle a small palette by index.\n */\n color?: string;\n /**\n * Grafana-style unit key for this series' readout/tooltip. Falls back to the\n * panel-level `unit`.\n */\n unit?: string;\n /**\n * Instantaneous value for the `breakdown` variant. When omitted, the\n * breakdown falls back to the latest polled point.\n */\n current?: number;\n}\n\nexport interface TimeseriesPanelProps {\n url?: string;\n baseUrl?: string;\n series?: TimeseriesSeries[];\n title: string;\n icon?: string | StaticIconComponent;\n unit?: string;\n range?: string;\n refreshMs?: number;\n height?: number;\n variant?: \"area\" | \"line\" | \"stacked\" | \"breakdown\";\n expandVariant?: \"area\" | \"line\" | \"stacked\";\n total?: number;\n expandable?: boolean;\n fetcher?: (url: string) => Promise<TimeseriesResponse>;\n className?: string;\n}\n\nconst SERIES_PALETTE = [\n \"var(--chart-1, #3b82f6)\",\n \"var(--chart-2, #ef4444)\",\n \"var(--chart-3, #10b981)\",\n \"var(--chart-4, #f59e0b)\",\n] as const;\n\nfunction paletteColor(index: number): string {\n return SERIES_PALETTE[index % SERIES_PALETTE.length] ?? SERIES_PALETTE[0];\n}\n\n/** A series with its full request URL, resolved label, color, and unit. */\nexport interface ResolvedSeries {\n key: string;\n url: string;\n label: string;\n color: string;\n unit?: string;\n transform?: (value: number) => number;\n current?: number;\n}\n\n/** Normalises the single-url and baseUrl+series forms to one list. */\nexport function resolveSeries(props: TimeseriesPanelProps): ResolvedSeries[] {\n const base = props.baseUrl ?? \"\";\n const list = props.series ?? (props.url ? [{ id: props.url }] : []);\n return list.map((s, i) => ({\n key: s.id,\n url: base + s.id,\n label: s.label ?? s.id,\n color: s.color ?? paletteColor(i),\n ...(s.unit ?? props.unit ? { unit: s.unit ?? props.unit } : {}),\n ...(s.transform ? { transform: s.transform } : {}),\n ...(s.current !== undefined ? { current: s.current } : {}),\n }));\n}\n\n/** One legend/bar row of the breakdown variant. */\nexport interface BreakdownItem {\n key: string;\n label: string;\n color: string;\n unit?: string;\n value: number;\n percent: number;\n}\n\n/**\n * One row of the merged chart data: the timestamp in `at` plus each series'\n * value under its key.\n */\nexport interface MergedRow {\n at: string;\n [seriesKey: string]: string | number | undefined;\n}\n\nexport function resolveBreakdown(\n series: ResolvedSeries[],\n rows: MergedRow[],\n total?: number,\n): { items: BreakdownItem[]; total: number } {\n const withValue = series.map((s) => ({ s, value: s.current ?? latestOf(rows, s.key) ?? 0 }));\n const denom = total ?? withValue.reduce((acc, w) => acc + w.value, 0);\n const items = withValue.map(({ s, value }) => ({\n key: s.key,\n label: s.label,\n color: s.color,\n ...(s.unit ? { unit: s.unit } : {}),\n value,\n percent: denom > 0 ? Math.min(100, Math.max(0, (value / denom) * 100)) : 0,\n }));\n return { items, total: denom };\n}\n\nexport function mergeSeries(\n series: ResolvedSeries[],\n pointsBySeries: (TimeseriesPoint[] | undefined)[],\n): MergedRow[] {\n const rows = new Map<string, MergedRow>();\n series.forEach((s, i) => {\n for (const p of pointsBySeries[i] ?? []) {\n const row = rows.get(p.at) ?? { at: p.at };\n row[s.key] = s.transform ? s.transform(p.value) : p.value;\n rows.set(p.at, row);\n }\n });\n return [...rows.values()].sort((a, b) => a.at.localeCompare(b.at));\n}\n"],"names":["latestOf"],"mappings":";;;AA2DA,MAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,eAAe,QAAQ,eAAe,MAAM,KAAK,eAAe,CAAC;AAC1E;AAcO,SAAS,cAAc,OAA+C;AAC3E,QAAM,OAAO,MAAM,WAAW;AAC9B,QAAM,OAAO,MAAM,WAAW,MAAM,MAAM,CAAC,EAAE,IAAI,MAAM,IAAA,CAAK,IAAI,CAAA;AAChE,SAAO,KAAK,IAAI,CAAC,GAAG,OAAO;AAAA,IACzB,KAAK,EAAE;AAAA,IACP,KAAK,OAAO,EAAE;AAAA,IACd,OAAO,EAAE,SAAS,EAAE;AAAA,IACpB,OAAO,EAAE,SAAS,aAAa,CAAC;AAAA,IAChC,GAAI,EAAE,QAAQ,MAAM,OAAO,EAAE,MAAM,EAAE,QAAQ,MAAM,KAAA,IAAS,CAAA;AAAA,IAC5D,GAAI,EAAE,YAAY,EAAE,WAAW,EAAE,UAAA,IAAc,CAAA;AAAA,IAC/C,GAAI,EAAE,YAAY,SAAY,EAAE,SAAS,EAAE,YAAY,CAAA;AAAA,EAAC,EACxD;AACJ;AAqBO,SAAS,iBACd,QACA,MACA,OAC2C;AAC3C,QAAM,YAAY,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,OAAO,EAAE,WAAWA,qBAAAA,SAAS,MAAM,EAAE,GAAG,KAAK,IAAI;AAC3F,QAAM,QAAQ,SAAS,UAAU,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;AACpE,QAAM,QAAQ,UAAU,IAAI,CAAC,EAAE,GAAG,aAAa;AAAA,IAC7C,KAAK,EAAE;AAAA,IACP,OAAO,EAAE;AAAA,IACT,OAAO,EAAE;AAAA,IACT,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAA,IAAS,CAAA;AAAA,IAChC;AAAA,IACA,SAAS,QAAQ,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,GAAI,QAAQ,QAAS,GAAG,CAAC,IAAI;AAAA,EAAA,EACzE;AACF,SAAO,EAAE,OAAO,OAAO,MAAA;AACzB;AAEO,SAAS,YACd,QACA,gBACa;AACb,QAAM,2BAAW,IAAA;AACjB,SAAO,QAAQ,CAAC,GAAG,MAAM;AACvB,eAAW,KAAK,eAAe,CAAC,KAAK,CAAA,GAAI;AACvC,YAAM,MAAM,KAAK,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAA;AACtC,UAAI,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE;AACpD,WAAK,IAAI,EAAE,IAAI,GAAG;AAAA,IACpB;AAAA,EACF,CAAC;AACD,SAAO,CAAC,GAAG,KAAK,OAAA,CAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AACnE;;;;"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { StaticIconComponent } from './Icon';
|
|
2
|
+
export interface TimeseriesPoint {
|
|
3
|
+
at: string;
|
|
4
|
+
value: number;
|
|
5
|
+
}
|
|
6
|
+
export interface TimeseriesResponse {
|
|
7
|
+
id: string;
|
|
8
|
+
points: TimeseriesPoint[];
|
|
9
|
+
}
|
|
10
|
+
/** One metric plotted on a panel. Its request URL is `baseUrl + id`. */
|
|
11
|
+
export interface TimeseriesSeries {
|
|
12
|
+
/** Metric id appended to the panel's baseUrl, e.g. "sqlserver.iops.read". */
|
|
13
|
+
id: string;
|
|
14
|
+
/** Tooltip/legend label; defaults to the id. */
|
|
15
|
+
label?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Maps each point's value before plotting, e.g. writes pass `(v) => -v` to
|
|
18
|
+
* render below the zero axis. Identity when omitted.
|
|
19
|
+
*/
|
|
20
|
+
transform?: (value: number) => number;
|
|
21
|
+
/**
|
|
22
|
+
* Stroke/fill override as a CSS color value or a Tailwind color class.
|
|
23
|
+
* Defaults cycle a small palette by index.
|
|
24
|
+
*/
|
|
25
|
+
color?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Grafana-style unit key for this series' readout/tooltip. Falls back to the
|
|
28
|
+
* panel-level `unit`.
|
|
29
|
+
*/
|
|
30
|
+
unit?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Instantaneous value for the `breakdown` variant. When omitted, the
|
|
33
|
+
* breakdown falls back to the latest polled point.
|
|
34
|
+
*/
|
|
35
|
+
current?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface TimeseriesPanelProps {
|
|
38
|
+
url?: string;
|
|
39
|
+
baseUrl?: string;
|
|
40
|
+
series?: TimeseriesSeries[];
|
|
41
|
+
title: string;
|
|
42
|
+
icon?: string | StaticIconComponent;
|
|
43
|
+
unit?: string;
|
|
44
|
+
range?: string;
|
|
45
|
+
refreshMs?: number;
|
|
46
|
+
height?: number;
|
|
47
|
+
variant?: "area" | "line" | "stacked" | "breakdown";
|
|
48
|
+
expandVariant?: "area" | "line" | "stacked";
|
|
49
|
+
total?: number;
|
|
50
|
+
expandable?: boolean;
|
|
51
|
+
fetcher?: (url: string) => Promise<TimeseriesResponse>;
|
|
52
|
+
className?: string;
|
|
53
|
+
}
|
|
54
|
+
/** A series with its full request URL, resolved label, color, and unit. */
|
|
55
|
+
export interface ResolvedSeries {
|
|
56
|
+
key: string;
|
|
57
|
+
url: string;
|
|
58
|
+
label: string;
|
|
59
|
+
color: string;
|
|
60
|
+
unit?: string;
|
|
61
|
+
transform?: (value: number) => number;
|
|
62
|
+
current?: number;
|
|
63
|
+
}
|
|
64
|
+
/** Normalises the single-url and baseUrl+series forms to one list. */
|
|
65
|
+
export declare function resolveSeries(props: TimeseriesPanelProps): ResolvedSeries[];
|
|
66
|
+
/** One legend/bar row of the breakdown variant. */
|
|
67
|
+
export interface BreakdownItem {
|
|
68
|
+
key: string;
|
|
69
|
+
label: string;
|
|
70
|
+
color: string;
|
|
71
|
+
unit?: string;
|
|
72
|
+
value: number;
|
|
73
|
+
percent: number;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* One row of the merged chart data: the timestamp in `at` plus each series'
|
|
77
|
+
* value under its key.
|
|
78
|
+
*/
|
|
79
|
+
export interface MergedRow {
|
|
80
|
+
at: string;
|
|
81
|
+
[seriesKey: string]: string | number | undefined;
|
|
82
|
+
}
|
|
83
|
+
export declare function resolveBreakdown(series: ResolvedSeries[], rows: MergedRow[], total?: number): {
|
|
84
|
+
items: BreakdownItem[];
|
|
85
|
+
total: number;
|
|
86
|
+
};
|
|
87
|
+
export declare function mergeSeries(series: ResolvedSeries[], pointsBySeries: (TimeseriesPoint[] | undefined)[]): MergedRow[];
|
|
88
|
+
//# sourceMappingURL=TimeseriesPanel.model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimeseriesPanel.model.d.ts","sourceRoot":"","sources":["../../src/data/TimeseriesPanel.model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { latestOf } from "./TimeseriesPanel.axes.js";
|
|
2
|
+
const SERIES_PALETTE = [
|
|
3
|
+
"var(--chart-1, #3b82f6)",
|
|
4
|
+
"var(--chart-2, #ef4444)",
|
|
5
|
+
"var(--chart-3, #10b981)",
|
|
6
|
+
"var(--chart-4, #f59e0b)"
|
|
7
|
+
];
|
|
8
|
+
function paletteColor(index) {
|
|
9
|
+
return SERIES_PALETTE[index % SERIES_PALETTE.length] ?? SERIES_PALETTE[0];
|
|
10
|
+
}
|
|
11
|
+
function resolveSeries(props) {
|
|
12
|
+
const base = props.baseUrl ?? "";
|
|
13
|
+
const list = props.series ?? (props.url ? [{ id: props.url }] : []);
|
|
14
|
+
return list.map((s, i) => ({
|
|
15
|
+
key: s.id,
|
|
16
|
+
url: base + s.id,
|
|
17
|
+
label: s.label ?? s.id,
|
|
18
|
+
color: s.color ?? paletteColor(i),
|
|
19
|
+
...s.unit ?? props.unit ? { unit: s.unit ?? props.unit } : {},
|
|
20
|
+
...s.transform ? { transform: s.transform } : {},
|
|
21
|
+
...s.current !== void 0 ? { current: s.current } : {}
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
function resolveBreakdown(series, rows, total) {
|
|
25
|
+
const withValue = series.map((s) => ({ s, value: s.current ?? latestOf(rows, s.key) ?? 0 }));
|
|
26
|
+
const denom = total ?? withValue.reduce((acc, w) => acc + w.value, 0);
|
|
27
|
+
const items = withValue.map(({ s, value }) => ({
|
|
28
|
+
key: s.key,
|
|
29
|
+
label: s.label,
|
|
30
|
+
color: s.color,
|
|
31
|
+
...s.unit ? { unit: s.unit } : {},
|
|
32
|
+
value,
|
|
33
|
+
percent: denom > 0 ? Math.min(100, Math.max(0, value / denom * 100)) : 0
|
|
34
|
+
}));
|
|
35
|
+
return { items, total: denom };
|
|
36
|
+
}
|
|
37
|
+
function mergeSeries(series, pointsBySeries) {
|
|
38
|
+
const rows = /* @__PURE__ */ new Map();
|
|
39
|
+
series.forEach((s, i) => {
|
|
40
|
+
for (const p of pointsBySeries[i] ?? []) {
|
|
41
|
+
const row = rows.get(p.at) ?? { at: p.at };
|
|
42
|
+
row[s.key] = s.transform ? s.transform(p.value) : p.value;
|
|
43
|
+
rows.set(p.at, row);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return [...rows.values()].sort((a, b) => a.at.localeCompare(b.at));
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
mergeSeries,
|
|
50
|
+
resolveBreakdown,
|
|
51
|
+
resolveSeries
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=TimeseriesPanel.model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimeseriesPanel.model.js","sources":["../../src/data/TimeseriesPanel.model.ts"],"sourcesContent":["import type { StaticIconComponent } from \"./Icon\";\nimport { latestOf } from \"./TimeseriesPanel.axes\";\n\nexport interface TimeseriesPoint {\n at: string;\n value: number;\n}\n\nexport interface TimeseriesResponse {\n id: string;\n points: TimeseriesPoint[];\n}\n\n/** One metric plotted on a panel. Its request URL is `baseUrl + id`. */\nexport interface TimeseriesSeries {\n /** Metric id appended to the panel's baseUrl, e.g. \"sqlserver.iops.read\". */\n id: string;\n /** Tooltip/legend label; defaults to the id. */\n label?: string;\n /**\n * Maps each point's value before plotting, e.g. writes pass `(v) => -v` to\n * render below the zero axis. Identity when omitted.\n */\n transform?: (value: number) => number;\n /**\n * Stroke/fill override as a CSS color value or a Tailwind color class.\n * Defaults cycle a small palette by index.\n */\n color?: string;\n /**\n * Grafana-style unit key for this series' readout/tooltip. Falls back to the\n * panel-level `unit`.\n */\n unit?: string;\n /**\n * Instantaneous value for the `breakdown` variant. When omitted, the\n * breakdown falls back to the latest polled point.\n */\n current?: number;\n}\n\nexport interface TimeseriesPanelProps {\n url?: string;\n baseUrl?: string;\n series?: TimeseriesSeries[];\n title: string;\n icon?: string | StaticIconComponent;\n unit?: string;\n range?: string;\n refreshMs?: number;\n height?: number;\n variant?: \"area\" | \"line\" | \"stacked\" | \"breakdown\";\n expandVariant?: \"area\" | \"line\" | \"stacked\";\n total?: number;\n expandable?: boolean;\n fetcher?: (url: string) => Promise<TimeseriesResponse>;\n className?: string;\n}\n\nconst SERIES_PALETTE = [\n \"var(--chart-1, #3b82f6)\",\n \"var(--chart-2, #ef4444)\",\n \"var(--chart-3, #10b981)\",\n \"var(--chart-4, #f59e0b)\",\n] as const;\n\nfunction paletteColor(index: number): string {\n return SERIES_PALETTE[index % SERIES_PALETTE.length] ?? SERIES_PALETTE[0];\n}\n\n/** A series with its full request URL, resolved label, color, and unit. */\nexport interface ResolvedSeries {\n key: string;\n url: string;\n label: string;\n color: string;\n unit?: string;\n transform?: (value: number) => number;\n current?: number;\n}\n\n/** Normalises the single-url and baseUrl+series forms to one list. */\nexport function resolveSeries(props: TimeseriesPanelProps): ResolvedSeries[] {\n const base = props.baseUrl ?? \"\";\n const list = props.series ?? (props.url ? [{ id: props.url }] : []);\n return list.map((s, i) => ({\n key: s.id,\n url: base + s.id,\n label: s.label ?? s.id,\n color: s.color ?? paletteColor(i),\n ...(s.unit ?? props.unit ? { unit: s.unit ?? props.unit } : {}),\n ...(s.transform ? { transform: s.transform } : {}),\n ...(s.current !== undefined ? { current: s.current } : {}),\n }));\n}\n\n/** One legend/bar row of the breakdown variant. */\nexport interface BreakdownItem {\n key: string;\n label: string;\n color: string;\n unit?: string;\n value: number;\n percent: number;\n}\n\n/**\n * One row of the merged chart data: the timestamp in `at` plus each series'\n * value under its key.\n */\nexport interface MergedRow {\n at: string;\n [seriesKey: string]: string | number | undefined;\n}\n\nexport function resolveBreakdown(\n series: ResolvedSeries[],\n rows: MergedRow[],\n total?: number,\n): { items: BreakdownItem[]; total: number } {\n const withValue = series.map((s) => ({ s, value: s.current ?? latestOf(rows, s.key) ?? 0 }));\n const denom = total ?? withValue.reduce((acc, w) => acc + w.value, 0);\n const items = withValue.map(({ s, value }) => ({\n key: s.key,\n label: s.label,\n color: s.color,\n ...(s.unit ? { unit: s.unit } : {}),\n value,\n percent: denom > 0 ? Math.min(100, Math.max(0, (value / denom) * 100)) : 0,\n }));\n return { items, total: denom };\n}\n\nexport function mergeSeries(\n series: ResolvedSeries[],\n pointsBySeries: (TimeseriesPoint[] | undefined)[],\n): MergedRow[] {\n const rows = new Map<string, MergedRow>();\n series.forEach((s, i) => {\n for (const p of pointsBySeries[i] ?? []) {\n const row = rows.get(p.at) ?? { at: p.at };\n row[s.key] = s.transform ? s.transform(p.value) : p.value;\n rows.set(p.at, row);\n }\n });\n return [...rows.values()].sort((a, b) => a.at.localeCompare(b.at));\n}\n"],"names":[],"mappings":";AA2DA,MAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,eAAe,QAAQ,eAAe,MAAM,KAAK,eAAe,CAAC;AAC1E;AAcO,SAAS,cAAc,OAA+C;AAC3E,QAAM,OAAO,MAAM,WAAW;AAC9B,QAAM,OAAO,MAAM,WAAW,MAAM,MAAM,CAAC,EAAE,IAAI,MAAM,IAAA,CAAK,IAAI,CAAA;AAChE,SAAO,KAAK,IAAI,CAAC,GAAG,OAAO;AAAA,IACzB,KAAK,EAAE;AAAA,IACP,KAAK,OAAO,EAAE;AAAA,IACd,OAAO,EAAE,SAAS,EAAE;AAAA,IACpB,OAAO,EAAE,SAAS,aAAa,CAAC;AAAA,IAChC,GAAI,EAAE,QAAQ,MAAM,OAAO,EAAE,MAAM,EAAE,QAAQ,MAAM,KAAA,IAAS,CAAA;AAAA,IAC5D,GAAI,EAAE,YAAY,EAAE,WAAW,EAAE,UAAA,IAAc,CAAA;AAAA,IAC/C,GAAI,EAAE,YAAY,SAAY,EAAE,SAAS,EAAE,YAAY,CAAA;AAAA,EAAC,EACxD;AACJ;AAqBO,SAAS,iBACd,QACA,MACA,OAC2C;AAC3C,QAAM,YAAY,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,OAAO,EAAE,WAAW,SAAS,MAAM,EAAE,GAAG,KAAK,IAAI;AAC3F,QAAM,QAAQ,SAAS,UAAU,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,CAAC;AACpE,QAAM,QAAQ,UAAU,IAAI,CAAC,EAAE,GAAG,aAAa;AAAA,IAC7C,KAAK,EAAE;AAAA,IACP,OAAO,EAAE;AAAA,IACT,OAAO,EAAE;AAAA,IACT,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAA,IAAS,CAAA;AAAA,IAChC;AAAA,IACA,SAAS,QAAQ,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,GAAI,QAAQ,QAAS,GAAG,CAAC,IAAI;AAAA,EAAA,EACzE;AACF,SAAO,EAAE,OAAO,OAAO,MAAA;AACzB;AAEO,SAAS,YACd,QACA,gBACa;AACb,QAAM,2BAAW,IAAA;AACjB,SAAO,QAAQ,CAAC,GAAG,MAAM;AACvB,eAAW,KAAK,eAAe,CAAC,KAAK,CAAA,GAAI;AACvC,YAAM,MAAM,KAAK,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAA;AACtC,UAAI,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,IAAI,EAAE;AACpD,WAAK,IAAI,EAAE,IAAI,GAAG;AAAA,IACpB;AAAA,EACF,CAAC;AACD,SAAO,CAAC,GAAG,KAAK,OAAA,CAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AACnE;"}
|
package/dist/data/Tree.cjs
CHANGED
|
@@ -201,7 +201,7 @@ function Tree({
|
|
|
201
201
|
value: filterQuery,
|
|
202
202
|
onChange: (event) => setFilterQuery(event.target.value),
|
|
203
203
|
placeholder: "Filter tree",
|
|
204
|
-
className: "h-5 w-full border-0 bg-transparent p-0 text-xs outline-none placeholder:text-muted-foreground",
|
|
204
|
+
className: "h-5 w-full min-w-0 border-0 bg-transparent p-0 text-xs outline-none placeholder:text-muted-foreground",
|
|
205
205
|
"aria-label": "Filter tree nodes"
|
|
206
206
|
}
|
|
207
207
|
),
|