@flanksource/clicky-ui 0.2.19 → 0.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.cjs +26 -0
- package/dist/ai.cjs.map +1 -0
- package/dist/ai.d.ts +2 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +26 -0
- package/dist/ai.js.map +1 -0
- package/dist/chat.cjs +7 -0
- package/dist/chat.cjs.map +1 -1
- package/dist/chat.js +7 -0
- package/dist/chat.js.map +1 -1
- package/dist/components/FilterBar.cjs +49 -18
- package/dist/components/FilterBar.cjs.map +1 -1
- package/dist/components/FilterBar.d.ts +0 -2
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterBar.js +50 -19
- package/dist/components/FilterBar.js.map +1 -1
- package/dist/components/SearchInput.cjs +63 -0
- package/dist/components/SearchInput.cjs.map +1 -0
- package/dist/components/SearchInput.d.ts +31 -0
- package/dist/components/SearchInput.d.ts.map +1 -0
- package/dist/components/SearchInput.js +63 -0
- package/dist/components/SearchInput.js.map +1 -0
- package/dist/components/SegmentedControl.cjs +88 -0
- package/dist/components/SegmentedControl.cjs.map +1 -0
- package/dist/components/SegmentedControl.d.ts +38 -0
- package/dist/components/SegmentedControl.d.ts.map +1 -0
- package/dist/components/SegmentedControl.js +88 -0
- package/dist/components/SegmentedControl.js.map +1 -0
- package/dist/components/Switch.cjs +51 -0
- package/dist/components/Switch.cjs.map +1 -0
- package/dist/components/Switch.d.ts +23 -0
- package/dist/components/Switch.d.ts.map +1 -0
- package/dist/components/Switch.js +51 -0
- package/dist/components/Switch.js.map +1 -0
- package/dist/components/TimeRange.cjs +53 -45
- package/dist/components/TimeRange.cjs.map +1 -1
- package/dist/components/TimeRange.d.ts.map +1 -1
- package/dist/components/TimeRange.js +53 -45
- package/dist/components/TimeRange.js.map +1 -1
- package/dist/components/TreePickerField.cjs +5 -1
- package/dist/components/TreePickerField.cjs.map +1 -1
- package/dist/components/TreePickerField.d.ts.map +1 -1
- package/dist/components/TreePickerField.js +5 -1
- package/dist/components/TreePickerField.js.map +1 -1
- package/dist/components/filter-bar-utils.cjs +5 -0
- package/dist/components/filter-bar-utils.cjs.map +1 -1
- package/dist/components/filter-bar-utils.d.ts +2 -0
- package/dist/components/filter-bar-utils.d.ts.map +1 -1
- package/dist/components/filter-bar-utils.js +5 -0
- package/dist/components/filter-bar-utils.js.map +1 -1
- package/dist/components/json-schema-form-fields.cjs +8 -2
- package/dist/components/json-schema-form-fields.cjs.map +1 -1
- package/dist/components/json-schema-form-fields.d.ts.map +1 -1
- package/dist/components/json-schema-form-fields.js +8 -2
- package/dist/components/json-schema-form-fields.js.map +1 -1
- package/dist/components/json-schema-form-resolve.cjs +1 -1
- package/dist/components/json-schema-form-resolve.cjs.map +1 -1
- package/dist/components/json-schema-form-resolve.js +1 -1
- package/dist/components/json-schema-form-resolve.js.map +1 -1
- package/dist/components.cjs +15 -1
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +8 -1
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +15 -1
- package/dist/components.js.map +1 -1
- package/dist/data/Clicky.cjs +33 -44
- package/dist/data/Clicky.cjs.map +1 -1
- package/dist/data/Clicky.d.ts +0 -9
- package/dist/data/Clicky.d.ts.map +1 -1
- package/dist/data/Clicky.js +31 -42
- package/dist/data/Clicky.js.map +1 -1
- package/dist/data/DataTable.cjs +73 -50
- package/dist/data/DataTable.cjs.map +1 -1
- package/dist/data/DataTable.d.ts +4 -0
- package/dist/data/DataTable.d.ts.map +1 -1
- package/dist/data/DataTable.js +73 -50
- package/dist/data/DataTable.js.map +1 -1
- package/dist/data/Icon.cjs +2 -5
- package/dist/data/Icon.cjs.map +1 -1
- package/dist/data/Icon.d.ts +1 -21
- package/dist/data/Icon.d.ts.map +1 -1
- package/dist/data/Icon.js +3 -6
- package/dist/data/Icon.js.map +1 -1
- package/dist/data/MatrixTable.cjs +4 -4
- package/dist/data/MatrixTable.cjs.map +1 -1
- package/dist/data/MatrixTable.js +4 -4
- package/dist/data/MatrixTable.js.map +1 -1
- package/dist/data/RadialGauge.cjs +76 -0
- package/dist/data/RadialGauge.cjs.map +1 -0
- package/dist/data/RadialGauge.d.ts +24 -0
- package/dist/data/RadialGauge.d.ts.map +1 -0
- package/dist/data/RadialGauge.js +76 -0
- package/dist/data/RadialGauge.js.map +1 -0
- package/dist/data/StatusBreakdown.cjs +0 -4
- package/dist/data/StatusBreakdown.cjs.map +1 -1
- package/dist/data/StatusBreakdown.d.ts +0 -2
- package/dist/data/StatusBreakdown.d.ts.map +1 -1
- package/dist/data/StatusBreakdown.js +1 -5
- package/dist/data/StatusBreakdown.js.map +1 -1
- package/dist/data/Timeline.cjs +61 -0
- package/dist/data/Timeline.cjs.map +1 -0
- package/dist/data/Timeline.d.ts +36 -0
- package/dist/data/Timeline.d.ts.map +1 -0
- package/dist/data/Timeline.js +61 -0
- package/dist/data/Timeline.js.map +1 -0
- package/dist/data/TimeseriesCoreBars.cjs +2 -25
- package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
- package/dist/data/TimeseriesCoreBars.d.ts +0 -19
- package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
- package/dist/data/TimeseriesCoreBars.js +2 -25
- package/dist/data/TimeseriesCoreBars.js.map +1 -1
- package/dist/data/TimeseriesCoreBars.model.cjs +27 -0
- package/dist/data/TimeseriesCoreBars.model.cjs.map +1 -0
- package/dist/data/TimeseriesCoreBars.model.d.ts +20 -0
- package/dist/data/TimeseriesCoreBars.model.d.ts.map +1 -0
- package/dist/data/TimeseriesCoreBars.model.js +27 -0
- package/dist/data/TimeseriesCoreBars.model.js.map +1 -0
- package/dist/data/TimeseriesPanel.axes.cjs.map +1 -1
- package/dist/data/TimeseriesPanel.axes.d.ts +1 -1
- package/dist/data/TimeseriesPanel.axes.d.ts.map +1 -1
- package/dist/data/TimeseriesPanel.axes.js.map +1 -1
- package/dist/data/TimeseriesPanel.cjs +4 -54
- package/dist/data/TimeseriesPanel.cjs.map +1 -1
- package/dist/data/TimeseriesPanel.d.ts +2 -138
- package/dist/data/TimeseriesPanel.d.ts.map +1 -1
- package/dist/data/TimeseriesPanel.js +2 -52
- package/dist/data/TimeseriesPanel.js.map +1 -1
- package/dist/data/TimeseriesPanel.model.cjs +53 -0
- package/dist/data/TimeseriesPanel.model.cjs.map +1 -0
- package/dist/data/TimeseriesPanel.model.d.ts +88 -0
- package/dist/data/TimeseriesPanel.model.d.ts.map +1 -0
- package/dist/data/TimeseriesPanel.model.js +53 -0
- package/dist/data/TimeseriesPanel.model.js.map +1 -0
- package/dist/data/Tree.cjs +1 -1
- package/dist/data/Tree.cjs.map +1 -1
- package/dist/data/Tree.js +1 -1
- package/dist/data/Tree.js.map +1 -1
- package/dist/data/ai/ChatFab.cjs +29 -0
- package/dist/data/ai/ChatFab.cjs.map +1 -0
- package/dist/data/ai/ChatFab.d.ts +12 -0
- package/dist/data/ai/ChatFab.d.ts.map +1 -0
- package/dist/data/ai/ChatFab.js +29 -0
- package/dist/data/ai/ChatFab.js.map +1 -0
- package/dist/data/ai/ChatWindow.cjs +178 -0
- package/dist/data/ai/ChatWindow.cjs.map +1 -0
- package/dist/data/ai/ChatWindow.d.ts +38 -0
- package/dist/data/ai/ChatWindow.d.ts.map +1 -0
- package/dist/data/ai/ChatWindow.js +156 -0
- package/dist/data/ai/ChatWindow.js.map +1 -0
- package/dist/data/ai/ChatWindowManager.cjs +139 -0
- package/dist/data/ai/ChatWindowManager.cjs.map +1 -0
- package/dist/data/ai/ChatWindowManager.d.ts +12 -0
- package/dist/data/ai/ChatWindowManager.d.ts.map +1 -0
- package/dist/data/ai/ChatWindowManager.js +139 -0
- package/dist/data/ai/ChatWindowManager.js.map +1 -0
- package/dist/data/ai/ContextBadges.cjs +74 -0
- package/dist/data/ai/ContextBadges.cjs.map +1 -0
- package/dist/data/ai/ContextBadges.d.ts +16 -0
- package/dist/data/ai/ContextBadges.d.ts.map +1 -0
- package/dist/data/ai/ContextBadges.js +74 -0
- package/dist/data/ai/ContextBadges.js.map +1 -0
- package/dist/data/ai/ThreadPicker.cjs +148 -0
- package/dist/data/ai/ThreadPicker.cjs.map +1 -0
- package/dist/data/ai/ThreadPicker.d.ts +37 -0
- package/dist/data/ai/ThreadPicker.d.ts.map +1 -0
- package/dist/data/ai/ThreadPicker.js +148 -0
- package/dist/data/ai/ThreadPicker.js.map +1 -0
- package/dist/data/ai/ToolPreferences.cjs +80 -0
- package/dist/data/ai/ToolPreferences.cjs.map +1 -0
- package/dist/data/ai/ToolPreferences.d.ts +19 -0
- package/dist/data/ai/ToolPreferences.d.ts.map +1 -0
- package/dist/data/ai/ToolPreferences.js +80 -0
- package/dist/data/ai/ToolPreferences.js.map +1 -0
- package/dist/data/ai/chat-window-context.cjs +78 -0
- package/dist/data/ai/chat-window-context.cjs.map +1 -0
- package/dist/data/ai/chat-window-context.d.ts +57 -0
- package/dist/data/ai/chat-window-context.d.ts.map +1 -0
- package/dist/data/ai/chat-window-context.js +78 -0
- package/dist/data/ai/chat-window-context.js.map +1 -0
- package/dist/data/ai/context.cjs +43 -0
- package/dist/data/ai/context.cjs.map +1 -0
- package/dist/data/ai/context.d.ts +35 -0
- package/dist/data/ai/context.d.ts.map +1 -0
- package/dist/data/ai/context.js +43 -0
- package/dist/data/ai/context.js.map +1 -0
- package/dist/data/ai/index.d.ts +10 -0
- package/dist/data/ai/index.d.ts.map +1 -0
- package/dist/data/cache-browser/CacheDetailPanel.cjs +15 -0
- package/dist/data/cache-browser/CacheDetailPanel.cjs.map +1 -1
- package/dist/data/cache-browser/CacheDetailPanel.d.ts.map +1 -1
- package/dist/data/cache-browser/CacheDetailPanel.js +15 -0
- package/dist/data/cache-browser/CacheDetailPanel.js.map +1 -1
- package/dist/data/cache-browser/cache-browser.fixtures.d.ts +10 -0
- package/dist/data/cache-browser/cache-browser.fixtures.d.ts.map +1 -0
- package/dist/data/cache-browser/download.cjs +13 -0
- package/dist/data/cache-browser/download.cjs.map +1 -0
- package/dist/data/cache-browser/download.d.ts +3 -0
- package/dist/data/cache-browser/download.d.ts.map +1 -0
- package/dist/data/cache-browser/download.js +13 -0
- package/dist/data/cache-browser/download.js.map +1 -0
- package/dist/data/chat/Chat.cjs +44 -3
- 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 +45 -4
- 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/Conversation.cjs +47 -2
- package/dist/data/chat/Conversation.cjs.map +1 -1
- package/dist/data/chat/Conversation.d.ts +8 -2
- package/dist/data/chat/Conversation.d.ts.map +1 -1
- package/dist/data/chat/Conversation.js +47 -2
- package/dist/data/chat/Conversation.js.map +1 -1
- 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 +13 -5
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +18 -5
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +51 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +50 -6
- package/dist/index.js.map +1 -1
- package/dist/layout/AppShell.cjs +179 -29
- package/dist/layout/AppShell.cjs.map +1 -1
- package/dist/layout/AppShell.d.ts +5 -5
- package/dist/layout/AppShell.d.ts.map +1 -1
- package/dist/layout/AppShell.js +179 -29
- package/dist/layout/AppShell.js.map +1 -1
- package/dist/layout/AppSidebar.cjs +239 -0
- package/dist/layout/AppSidebar.cjs.map +1 -0
- package/dist/layout/AppSidebar.d.ts +62 -0
- package/dist/layout/AppSidebar.d.ts.map +1 -0
- package/dist/layout/AppSidebar.js +239 -0
- package/dist/layout/AppSidebar.js.map +1 -0
- package/dist/overlay/DropdownMenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenu.d.ts.map +1 -1
- package/dist/overlay/DropdownMenu.js.map +1 -1
- package/dist/overlay/Modal.cjs +4 -2
- package/dist/overlay/Modal.cjs.map +1 -1
- package/dist/overlay/Modal.d.ts +1 -1
- package/dist/overlay/Modal.d.ts.map +1 -1
- package/dist/overlay/Modal.js +4 -2
- package/dist/overlay/Modal.js.map +1 -1
- package/dist/overlay/Toast.cjs +89 -0
- package/dist/overlay/Toast.cjs.map +1 -0
- package/dist/overlay/Toast.d.ts +14 -0
- package/dist/overlay/Toast.d.ts.map +1 -0
- package/dist/overlay/Toast.js +89 -0
- package/dist/overlay/Toast.js.map +1 -0
- package/dist/overlay/toast-context.cjs +12 -0
- package/dist/overlay/toast-context.cjs.map +1 -0
- package/dist/overlay/toast-context.d.ts +24 -0
- package/dist/overlay/toast-context.d.ts.map +1 -0
- package/dist/overlay/toast-context.js +12 -0
- package/dist/overlay/toast-context.js.map +1 -0
- package/dist/rpc/AcceptPicker.cjs +81 -58
- package/dist/rpc/AcceptPicker.cjs.map +1 -1
- package/dist/rpc/AcceptPicker.d.ts.map +1 -1
- package/dist/rpc/AcceptPicker.js +81 -58
- package/dist/rpc/AcceptPicker.js.map +1 -1
- package/dist/rpc/CommandForm.cjs +5 -35
- package/dist/rpc/CommandForm.cjs.map +1 -1
- package/dist/rpc/CommandForm.d.ts +0 -3
- package/dist/rpc/CommandForm.d.ts.map +1 -1
- package/dist/rpc/CommandForm.js +2 -32
- package/dist/rpc/CommandForm.js.map +1 -1
- package/dist/rpc/CommandOutput.cjs +2 -1
- package/dist/rpc/CommandOutput.cjs.map +1 -1
- package/dist/rpc/CommandOutput.d.ts.map +1 -1
- package/dist/rpc/CommandOutput.js +2 -1
- package/dist/rpc/CommandOutput.js.map +1 -1
- package/dist/rpc/EntityExplorerApp.cjs +28 -83
- package/dist/rpc/EntityExplorerApp.cjs.map +1 -1
- package/dist/rpc/EntityExplorerApp.d.ts +1 -4
- package/dist/rpc/EntityExplorerApp.d.ts.map +1 -1
- package/dist/rpc/EntityExplorerApp.js +13 -68
- package/dist/rpc/EntityExplorerApp.js.map +1 -1
- package/dist/rpc/OperationCatalog.cjs +2 -2
- package/dist/rpc/OperationCatalog.cjs.map +1 -1
- package/dist/rpc/OperationCatalog.d.ts +1 -1
- package/dist/rpc/OperationCatalog.d.ts.map +1 -1
- package/dist/rpc/OperationCatalog.js +1 -1
- package/dist/rpc/OperationCatalog.js.map +1 -1
- package/dist/rpc/OperationCommandPage.cjs +6 -4
- package/dist/rpc/OperationCommandPage.cjs.map +1 -1
- package/dist/rpc/OperationCommandPage.d.ts.map +1 -1
- package/dist/rpc/OperationCommandPage.js +3 -1
- package/dist/rpc/OperationCommandPage.js.map +1 -1
- package/dist/rpc/RouterProvider.cjs +10 -0
- package/dist/rpc/RouterProvider.cjs.map +1 -0
- package/dist/rpc/RouterProvider.d.ts +10 -0
- package/dist/rpc/RouterProvider.d.ts.map +1 -0
- package/dist/rpc/RouterProvider.js +10 -0
- package/dist/rpc/RouterProvider.js.map +1 -0
- package/dist/rpc/apiClient.cjs +4 -4
- package/dist/rpc/apiClient.cjs.map +1 -1
- package/dist/rpc/apiClient.js +4 -4
- package/dist/rpc/apiClient.js.map +1 -1
- package/dist/rpc/command-form-utils.cjs +43 -0
- package/dist/rpc/command-form-utils.cjs.map +1 -0
- package/dist/rpc/command-form-utils.d.ts +5 -0
- package/dist/rpc/command-form-utils.d.ts.map +1 -0
- package/dist/rpc/command-form-utils.js +43 -0
- package/dist/rpc/command-form-utils.js.map +1 -0
- package/dist/rpc/commandHref.cjs +62 -0
- package/dist/rpc/commandHref.cjs.map +1 -0
- package/dist/rpc/commandHref.d.ts +7 -0
- package/dist/rpc/commandHref.d.ts.map +1 -0
- package/dist/rpc/commandHref.js +62 -0
- package/dist/rpc/commandHref.js.map +1 -0
- package/dist/rpc/formMetadata.cjs +1 -1
- package/dist/rpc/formMetadata.cjs.map +1 -1
- package/dist/rpc/formMetadata.js +1 -1
- package/dist/rpc/formMetadata.js.map +1 -1
- package/dist/rpc/router.cjs +83 -0
- package/dist/rpc/router.cjs.map +1 -0
- package/dist/rpc/router.d.ts +24 -0
- package/dist/rpc/router.d.ts.map +1 -0
- package/dist/rpc/router.js +83 -0
- package/dist/rpc/router.js.map +1 -0
- package/dist/rpc/rpc-story-fixtures/orders.fixture.d.ts +3 -0
- package/dist/rpc/rpc-story-fixtures/orders.fixture.d.ts.map +1 -0
- package/dist/rpc/rpc-story-fixtures/services.fixture.d.ts +3 -0
- package/dist/rpc/rpc-story-fixtures/services.fixture.d.ts.map +1 -0
- package/dist/rpc/rpc-story-fixtures/surface-fixture.d.ts +24 -0
- package/dist/rpc/rpc-story-fixtures/surface-fixture.d.ts.map +1 -0
- package/dist/rpc/rpc-story-fixtures/widgets.fixture.d.ts +3 -0
- package/dist/rpc/rpc-story-fixtures/widgets.fixture.d.ts.map +1 -0
- package/dist/rpc/rpc-story.fixtures.d.ts +16 -0
- package/dist/rpc/rpc-story.fixtures.d.ts.map +1 -0
- package/dist/rpc.cjs +17 -0
- package/dist/rpc.cjs.map +1 -1
- package/dist/rpc.d.ts +5 -0
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +18 -1
- package/dist/rpc.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +11 -1
package/dist/overlay/Modal.d.ts
CHANGED
|
@@ -50,5 +50,5 @@ export type ModalProps = {
|
|
|
50
50
|
/** Modal body content. */
|
|
51
51
|
children: ReactNode;
|
|
52
52
|
};
|
|
53
|
-
export declare function Modal({ open, onClose, confirmClose, title, subtitle, size, closeOnBackdrop, closeOnEsc, hideClose, expandable, className, headerSlot, footer, children, }: ModalProps): import(
|
|
53
|
+
export declare function Modal({ open, onClose, confirmClose, title, subtitle, size, closeOnBackdrop, closeOnEsc, hideClose, expandable, className, headerSlot, footer, children, }: ModalProps): import('react').ReactPortal | null;
|
|
54
54
|
//# sourceMappingURL=Modal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/overlay/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/overlay/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAQpE,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAE3D,6EAA6E;AAC7E,MAAM,MAAM,mBAAmB,GAAG;IAChC,0CAA0C;IAC1C,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,6CAA6C;IAC7C,IAAI,EAAE,OAAO,CAAC;IACd,+CAA+C;IAC/C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,mBAAmB,CAAC;IAC7C,oEAAoE;IACpE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,gGAAgG;IAChG,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oCAAoC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qCAAqC;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,uDAAuD;IACvD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,0BAA0B;IAC1B,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAiBF,wBAAgB,KAAK,CAAC,EACpB,IAAI,EACJ,OAAO,EACP,YAAoB,EACpB,KAAK,EACL,QAAQ,EACR,IAAW,EACX,eAAuB,EACvB,UAAiB,EACjB,SAAiB,EACjB,UAAiB,EACjB,SAAS,EACT,UAAU,EACV,MAAM,EACN,QAAQ,GACT,EAAE,UAAU,sCAoIZ"}
|
package/dist/overlay/Modal.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useRef, useState, useEffect } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
3
4
|
import { cn } from "../lib/utils.js";
|
|
4
5
|
import { Icon } from "../data/Icon.js";
|
|
5
6
|
import { Button } from "../components/button.js";
|
|
@@ -73,7 +74,7 @@ function Modal({
|
|
|
73
74
|
};
|
|
74
75
|
}, [open]);
|
|
75
76
|
if (!open) return null;
|
|
76
|
-
|
|
77
|
+
const overlay = /* @__PURE__ */ jsx(
|
|
77
78
|
"div",
|
|
78
79
|
{
|
|
79
80
|
className: cn(
|
|
@@ -81,7 +82,7 @@ function Modal({
|
|
|
81
82
|
// Nested modals dim less so the dialog they opened over stays visible.
|
|
82
83
|
depth === 0 ? "bg-black/40" : "bg-black/20"
|
|
83
84
|
),
|
|
84
|
-
style: { zIndex:
|
|
85
|
+
style: { zIndex: 1e4 + depth * 10 },
|
|
85
86
|
onClick: closeOnBackdrop ? requestClose : void 0,
|
|
86
87
|
role: "presentation",
|
|
87
88
|
children: /* @__PURE__ */ jsxs(
|
|
@@ -144,6 +145,7 @@ function Modal({
|
|
|
144
145
|
)
|
|
145
146
|
}
|
|
146
147
|
);
|
|
148
|
+
return typeof document !== "undefined" ? createPortal(overlay, document.body) : null;
|
|
147
149
|
}
|
|
148
150
|
function ConfirmClosePrompt({
|
|
149
151
|
options,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.js","sources":["../../src/overlay/Modal.tsx"],"sourcesContent":["import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { Button } from \"../components/button\";\nimport { UiClose, UiFullscreen, UiFullscreenFilled } from \"../icons\";\nimport { useModalStack } from \"./modalStack\";\n\nexport type ModalSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\";\n\n/** Copy for the discard-confirmation prompt shown before a guarded close. */\nexport type ConfirmCloseOptions = {\n /** Heading of the confirmation prompt. */\n title?: ReactNode;\n /** Body explaining what is lost on close. */\n message?: ReactNode;\n /** Label of the button that proceeds with closing. */\n confirmLabel?: string;\n /** Label of the button that dismisses the prompt and keeps the modal open. */\n cancelLabel?: string;\n};\n\nexport type ModalProps = {\n /** Controls whether the modal is mounted. */\n open: boolean;\n /** Called when the modal requests to close. */\n onClose: () => void;\n /**\n * Guard every close path (close button, Escape, backdrop) behind a discard\n * confirmation. `true` uses the default copy; pass options to customise it.\n * `onClose` only fires once the user confirms. Set this while the modal holds\n * unsaved edits and clear it (or pass `false`) once there is nothing to lose.\n */\n confirmClose?: boolean | ConfirmCloseOptions;\n /** Header title and accessible dialog label when it is a string. */\n title?: ReactNode;\n /**\n * Secondary header content rendered on its own row directly beneath the title.\n * The title stays a single row alongside the expand/close buttons, so a tall\n * subtitle (e.g. a tab switcher) never pushes those buttons down.\n */\n subtitle?: ReactNode;\n /** Width/height preset for the dialog. */\n size?: ModalSize;\n /** Close when the backdrop is clicked. Off by default; close via Escape or the close button. */\n closeOnBackdrop?: boolean;\n /** Close when Escape is pressed. */\n closeOnEsc?: boolean;\n /** Hide the close button. */\n hideClose?: boolean;\n /** Show an expand/restore button. */\n expandable?: boolean;\n /** Classes applied to the dialog panel. */\n className?: string;\n /** Extra header content rendered before the expand/close buttons. */\n headerSlot?: ReactNode;\n /** Footer content pinned below the scrollable body. */\n footer?: ReactNode;\n /** Modal body content. */\n children: ReactNode;\n};\n\nconst sizeClass: Record<ModalSize, string> = {\n sm: \"max-w-sm max-h-[90vh]\",\n md: \"max-w-md max-h-[90vh]\",\n lg: \"max-w-2xl max-h-[90vh]\",\n xl: \"max-w-4xl max-h-[90vh]\",\n full: \"max-w-[95vw] max-h-[95vh]\",\n};\n\nconst DEFAULT_CONFIRM: Required<ConfirmCloseOptions> = {\n title: \"Discard changes?\",\n message: \"You have unsaved changes. Closing now will discard them.\",\n confirmLabel: \"Discard\",\n cancelLabel: \"Keep editing\",\n};\n\nexport function Modal({\n open,\n onClose,\n confirmClose = false,\n title,\n subtitle,\n size = \"md\",\n closeOnBackdrop = false,\n closeOnEsc = true,\n hideClose = false,\n expandable = true,\n className,\n headerSlot,\n footer,\n children,\n}: ModalProps) {\n const dialogRef = useRef<HTMLDivElement>(null);\n const { isTop, depth } = useModalStack(open);\n const [expanded, setExpanded] = useState(false);\n // When confirmClose is active, a close request opens this prompt instead of\n // closing outright; onClose only fires once the user confirms the discard.\n const [confirming, setConfirming] = useState(false);\n\n // requestClose is the single entry point for every close affordance. With the\n // guard on, it surfaces the confirmation; otherwise it closes immediately.\n const requestClose = () => {\n if (confirmClose) setConfirming(true);\n else onClose();\n };\n\n useEffect(() => {\n if (!open) {\n setExpanded(false);\n setConfirming(false);\n }\n }, [open]);\n\n // A close guard that disappears mid-prompt (changes saved/reverted) should\n // not leave a stale confirmation dialog up.\n useEffect(() => {\n if (!confirmClose) setConfirming(false);\n }, [confirmClose]);\n\n useEffect(() => {\n // Only the topmost modal handles Escape so a keypress closes one nested\n // layer at a time instead of every open modal at once.\n if (!open || !closeOnEsc || !isTop) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\") return;\n // While the prompt is up, Escape dismisses the prompt rather than the modal.\n if (confirming) setConfirming(false);\n else requestClose();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, closeOnEsc, isTop, confirming, confirmClose, onClose]);\n\n useEffect(() => {\n if (!open) return;\n const prev = document.activeElement as HTMLElement | null;\n dialogRef.current?.focus();\n return () => prev?.focus?.();\n }, [open]);\n\n if (!open) return null;\n\n return (\n <div\n className={cn(\n \"fixed inset-0 flex items-center justify-center\",\n // Nested modals dim less so the dialog they opened over stays visible.\n depth === 0 ? \"bg-black/40\" : \"bg-black/20\",\n )}\n style={{ zIndex: 50 + depth * 10 }}\n onClick={closeOnBackdrop ? requestClose : undefined}\n role=\"presentation\"\n >\n <div\n ref={dialogRef}\n tabIndex={-1}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={typeof title === \"string\" ? title : undefined}\n className={cn(\n \"relative bg-background border border-border rounded-lg shadow-xl w-full flex flex-col\",\n expanded ? sizeClass.full : sizeClass[size],\n className,\n )}\n onClick={(e) => e.stopPropagation()}\n >\n {(title || subtitle || headerSlot || expandable || !hideClose) && (\n <div className=\"px-density-4 py-density-3 border-b border-border\">\n <div className=\"flex items-center gap-density-2\">\n {title ? (\n <h2 className=\"text-sm font-semibold flex-1\">{title}</h2>\n ) : (\n <span className=\"flex-1\" />\n )}\n {headerSlot}\n {expandable && (\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n aria-label={expanded ? \"Restore size\" : \"Expand to fullscreen\"}\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <Icon icon={expanded ? UiFullscreenFilled : UiFullscreen} />\n </button>\n )}\n {!hideClose && (\n <button\n type=\"button\"\n onClick={requestClose}\n aria-label=\"Close\"\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <Icon icon={UiClose} />\n </button>\n )}\n </div>\n {subtitle ? <div className=\"mt-density-2\">{subtitle}</div> : null}\n </div>\n )}\n <div className=\"flex-1 overflow-auto px-density-4 py-density-3\">{children}</div>\n {footer && <div className=\"px-density-4 py-density-3 border-t border-border\">{footer}</div>}\n {confirming && (\n <ConfirmClosePrompt\n options={confirmClose === true ? DEFAULT_CONFIRM : { ...DEFAULT_CONFIRM, ...confirmClose }}\n onConfirm={() => {\n setConfirming(false);\n onClose();\n }}\n onCancel={() => setConfirming(false)}\n />\n )}\n </div>\n </div>\n );\n}\n\nfunction ConfirmClosePrompt({\n options,\n onConfirm,\n onCancel,\n}: {\n options: Required<ConfirmCloseOptions>;\n onConfirm: () => void;\n onCancel: () => void;\n}) {\n return (\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center rounded-lg bg-background/80 p-density-4\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-label={typeof options.title === \"string\" ? options.title : \"Confirm close\"}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"w-full max-w-sm rounded-lg border border-border bg-background p-density-4 shadow-xl\">\n <h3 className=\"text-sm font-semibold\">{options.title}</h3>\n <p className=\"mt-density-2 text-sm text-muted-foreground\">{options.message}</p>\n <div className=\"mt-density-4 flex justify-end gap-density-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n {options.cancelLabel}\n </Button>\n <Button variant=\"destructive\" size=\"sm\" onClick={onConfirm}>\n {options.confirmLabel}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n"],"names":["_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Modal.js","sources":["../../src/overlay/Modal.tsx"],"sourcesContent":["import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { Button } from \"../components/button\";\nimport { UiClose, UiFullscreen, UiFullscreenFilled } from \"../icons\";\nimport { useModalStack } from \"./modalStack\";\n\nexport type ModalSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\";\n\n/** Copy for the discard-confirmation prompt shown before a guarded close. */\nexport type ConfirmCloseOptions = {\n /** Heading of the confirmation prompt. */\n title?: ReactNode;\n /** Body explaining what is lost on close. */\n message?: ReactNode;\n /** Label of the button that proceeds with closing. */\n confirmLabel?: string;\n /** Label of the button that dismisses the prompt and keeps the modal open. */\n cancelLabel?: string;\n};\n\nexport type ModalProps = {\n /** Controls whether the modal is mounted. */\n open: boolean;\n /** Called when the modal requests to close. */\n onClose: () => void;\n /**\n * Guard every close path (close button, Escape, backdrop) behind a discard\n * confirmation. `true` uses the default copy; pass options to customise it.\n * `onClose` only fires once the user confirms. Set this while the modal holds\n * unsaved edits and clear it (or pass `false`) once there is nothing to lose.\n */\n confirmClose?: boolean | ConfirmCloseOptions;\n /** Header title and accessible dialog label when it is a string. */\n title?: ReactNode;\n /**\n * Secondary header content rendered on its own row directly beneath the title.\n * The title stays a single row alongside the expand/close buttons, so a tall\n * subtitle (e.g. a tab switcher) never pushes those buttons down.\n */\n subtitle?: ReactNode;\n /** Width/height preset for the dialog. */\n size?: ModalSize;\n /** Close when the backdrop is clicked. Off by default; close via Escape or the close button. */\n closeOnBackdrop?: boolean;\n /** Close when Escape is pressed. */\n closeOnEsc?: boolean;\n /** Hide the close button. */\n hideClose?: boolean;\n /** Show an expand/restore button. */\n expandable?: boolean;\n /** Classes applied to the dialog panel. */\n className?: string;\n /** Extra header content rendered before the expand/close buttons. */\n headerSlot?: ReactNode;\n /** Footer content pinned below the scrollable body. */\n footer?: ReactNode;\n /** Modal body content. */\n children: ReactNode;\n};\n\nconst sizeClass: Record<ModalSize, string> = {\n sm: \"max-w-sm max-h-[90vh]\",\n md: \"max-w-md max-h-[90vh]\",\n lg: \"max-w-2xl max-h-[90vh]\",\n xl: \"max-w-4xl max-h-[90vh]\",\n full: \"max-w-[95vw] max-h-[95vh]\",\n};\n\nconst DEFAULT_CONFIRM: Required<ConfirmCloseOptions> = {\n title: \"Discard changes?\",\n message: \"You have unsaved changes. Closing now will discard them.\",\n confirmLabel: \"Discard\",\n cancelLabel: \"Keep editing\",\n};\n\nexport function Modal({\n open,\n onClose,\n confirmClose = false,\n title,\n subtitle,\n size = \"md\",\n closeOnBackdrop = false,\n closeOnEsc = true,\n hideClose = false,\n expandable = true,\n className,\n headerSlot,\n footer,\n children,\n}: ModalProps) {\n const dialogRef = useRef<HTMLDivElement>(null);\n const { isTop, depth } = useModalStack(open);\n const [expanded, setExpanded] = useState(false);\n // When confirmClose is active, a close request opens this prompt instead of\n // closing outright; onClose only fires once the user confirms the discard.\n const [confirming, setConfirming] = useState(false);\n\n // requestClose is the single entry point for every close affordance. With the\n // guard on, it surfaces the confirmation; otherwise it closes immediately.\n const requestClose = () => {\n if (confirmClose) setConfirming(true);\n else onClose();\n };\n\n useEffect(() => {\n if (!open) {\n setExpanded(false);\n setConfirming(false);\n }\n }, [open]);\n\n // A close guard that disappears mid-prompt (changes saved/reverted) should\n // not leave a stale confirmation dialog up.\n useEffect(() => {\n if (!confirmClose) setConfirming(false);\n }, [confirmClose]);\n\n useEffect(() => {\n // Only the topmost modal handles Escape so a keypress closes one nested\n // layer at a time instead of every open modal at once.\n if (!open || !closeOnEsc || !isTop) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\") return;\n // While the prompt is up, Escape dismisses the prompt rather than the modal.\n if (confirming) setConfirming(false);\n else requestClose();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, closeOnEsc, isTop, confirming, confirmClose, onClose]);\n\n useEffect(() => {\n if (!open) return;\n const prev = document.activeElement as HTMLElement | null;\n dialogRef.current?.focus();\n return () => prev?.focus?.();\n }, [open]);\n\n if (!open) return null;\n\n const overlay = (\n <div\n className={cn(\n \"fixed inset-0 flex items-center justify-center\",\n // Nested modals dim less so the dialog they opened over stays visible.\n depth === 0 ? \"bg-black/40\" : \"bg-black/20\",\n )}\n // Above the z-[9999] popover/overlay layer (dropdowns, tooltips, toasts) so a\n // modal opened from one of them stacks on top; +depth keeps nested modals\n // above their parent.\n style={{ zIndex: 10000 + depth * 10 }}\n onClick={closeOnBackdrop ? requestClose : undefined}\n role=\"presentation\"\n >\n <div\n ref={dialogRef}\n tabIndex={-1}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={typeof title === \"string\" ? title : undefined}\n className={cn(\n \"relative bg-background border border-border rounded-lg shadow-xl w-full flex flex-col\",\n expanded ? sizeClass.full : sizeClass[size],\n className,\n )}\n onClick={(e) => e.stopPropagation()}\n >\n {(title || subtitle || headerSlot || expandable || !hideClose) && (\n <div className=\"px-density-4 py-density-3 border-b border-border\">\n <div className=\"flex items-center gap-density-2\">\n {title ? (\n <h2 className=\"text-sm font-semibold flex-1\">{title}</h2>\n ) : (\n <span className=\"flex-1\" />\n )}\n {headerSlot}\n {expandable && (\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n aria-label={expanded ? \"Restore size\" : \"Expand to fullscreen\"}\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <Icon icon={expanded ? UiFullscreenFilled : UiFullscreen} />\n </button>\n )}\n {!hideClose && (\n <button\n type=\"button\"\n onClick={requestClose}\n aria-label=\"Close\"\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <Icon icon={UiClose} />\n </button>\n )}\n </div>\n {subtitle ? <div className=\"mt-density-2\">{subtitle}</div> : null}\n </div>\n )}\n <div className=\"flex-1 overflow-auto px-density-4 py-density-3\">{children}</div>\n {footer && <div className=\"px-density-4 py-density-3 border-t border-border\">{footer}</div>}\n {confirming && (\n <ConfirmClosePrompt\n options={confirmClose === true ? DEFAULT_CONFIRM : { ...DEFAULT_CONFIRM, ...confirmClose }}\n onConfirm={() => {\n setConfirming(false);\n onClose();\n }}\n onCancel={() => setConfirming(false)}\n />\n )}\n </div>\n </div>\n );\n\n // Render into document.body so the fixed-position overlay escapes any ancestor\n // transform/overflow (e.g. a dropdown menu positioned via a CSS transform),\n // which would otherwise trap position:fixed inside that ancestor's box and clip\n // the modal to it.\n return typeof document !== \"undefined\" ? createPortal(overlay, document.body) : null;\n}\n\nfunction ConfirmClosePrompt({\n options,\n onConfirm,\n onCancel,\n}: {\n options: Required<ConfirmCloseOptions>;\n onConfirm: () => void;\n onCancel: () => void;\n}) {\n return (\n <div\n className=\"absolute inset-0 z-10 flex items-center justify-center rounded-lg bg-background/80 p-density-4\"\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-label={typeof options.title === \"string\" ? options.title : \"Confirm close\"}\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"w-full max-w-sm rounded-lg border border-border bg-background p-density-4 shadow-xl\">\n <h3 className=\"text-sm font-semibold\">{options.title}</h3>\n <p className=\"mt-density-2 text-sm text-muted-foreground\">{options.message}</p>\n <div className=\"mt-density-4 flex justify-end gap-density-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n {options.cancelLabel}\n </Button>\n <Button variant=\"destructive\" size=\"sm\" onClick={onConfirm}>\n {options.confirmLabel}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n"],"names":["_a"],"mappings":";;;;;;;;;AA8DA,MAAM,YAAuC;AAAA,EAC3C,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,MAAM;AACR;AAEA,MAAM,kBAAiD;AAAA,EACrD,OAAO;AAAA,EACP,SAAS;AAAA,EACT,cAAc;AAAA,EACd,aAAa;AACf;AAEO,SAAS,MAAM;AAAA,EACpB;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,kBAAkB;AAAA,EAClB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAe;AACb,QAAM,YAAY,OAAuB,IAAI;AAC7C,QAAM,EAAE,OAAO,UAAU,cAAc,IAAI;AAC3C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAG9C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAIlD,QAAM,eAAe,MAAM;AACzB,QAAI,4BAA4B,IAAI;AAAA,QAC/B,SAAA;AAAA,EACP;AAEA,YAAU,MAAM;AACd,QAAI,CAAC,MAAM;AACT,kBAAY,KAAK;AACjB,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAIT,YAAU,MAAM;AACd,QAAI,CAAC,aAAc,eAAc,KAAK;AAAA,EACxC,GAAG,CAAC,YAAY,CAAC;AAEjB,YAAU,MAAM;AAGd,QAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,MAAO;AACpC,UAAM,QAAQ,CAAC,MAAqB;AAClC,UAAI,EAAE,QAAQ,SAAU;AAExB,UAAI,0BAA0B,KAAK;AAAA,UAC9B,cAAA;AAAA,IACP;AACA,aAAS,iBAAiB,WAAW,KAAK;AAC1C,WAAO,MAAM,SAAS,oBAAoB,WAAW,KAAK;AAAA,EAC5D,GAAG,CAAC,MAAM,YAAY,OAAO,YAAY,cAAc,OAAO,CAAC;AAE/D,YAAU,MAAM;;AACd,QAAI,CAAC,KAAM;AACX,UAAM,OAAO,SAAS;AACtB,oBAAU,YAAV,mBAAmB;AACnB,WAAO,MAAA;;AAAM,cAAAA,MAAA,6BAAM,UAAN,gBAAAA,IAAA;AAAA;AAAA,EACf,GAAG,CAAC,IAAI,CAAC;AAET,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,UACJ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA;AAAA,QAEA,UAAU,IAAI,gBAAgB;AAAA,MAAA;AAAA,MAKhC,OAAO,EAAE,QAAQ,MAAQ,QAAQ,GAAA;AAAA,MACjC,SAAS,kBAAkB,eAAe;AAAA,MAC1C,MAAK;AAAA,MAEL,UAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK;AAAA,UACL,UAAU;AAAA,UACV,MAAK;AAAA,UACL,cAAW;AAAA,UACX,cAAY,OAAO,UAAU,WAAW,QAAQ;AAAA,UAChD,WAAW;AAAA,YACT;AAAA,YACA,WAAW,UAAU,OAAO,UAAU,IAAI;AAAA,YAC1C;AAAA,UAAA;AAAA,UAEF,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,UAEhB,UAAA;AAAA,aAAA,SAAS,YAAY,cAAc,cAAc,CAAC,cAClD,qBAAC,OAAA,EAAI,WAAU,oDACb,UAAA;AAAA,cAAA,qBAAC,OAAA,EAAI,WAAU,mCACZ,UAAA;AAAA,gBAAA,QACC,oBAAC,QAAG,WAAU,gCAAgC,iBAAM,IAEpD,oBAAC,QAAA,EAAK,WAAU,SAAA,CAAS;AAAA,gBAE1B;AAAA,gBACA,cACC;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;AAAA,oBACpC,cAAY,WAAW,iBAAiB;AAAA,oBACxC,WAAU;AAAA,oBAEV,UAAA,oBAAC,MAAA,EAAK,MAAM,WAAW,qBAAqB,aAAA,CAAc;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAG7D,CAAC,aACA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS;AAAA,oBACT,cAAW;AAAA,oBACX,WAAU;AAAA,oBAEV,UAAA,oBAAC,MAAA,EAAK,MAAM,QAAA,CAAS;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACvB,GAEJ;AAAA,cACC,WAAW,oBAAC,OAAA,EAAI,WAAU,gBAAgB,oBAAS,IAAS;AAAA,YAAA,GAC/D;AAAA,YAEF,oBAAC,OAAA,EAAI,WAAU,kDAAkD,SAAA,CAAS;AAAA,YACzE,UAAU,oBAAC,OAAA,EAAI,WAAU,oDAAoD,UAAA,QAAO;AAAA,YACpF,cACC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAS,iBAAiB,OAAO,kBAAkB,EAAE,GAAG,iBAAiB,GAAG,aAAA;AAAA,gBAC5E,WAAW,MAAM;AACf,gCAAc,KAAK;AACnB,0BAAA;AAAA,gBACF;AAAA,gBACA,UAAU,MAAM,cAAc,KAAK;AAAA,cAAA;AAAA,YAAA;AAAA,UACrC;AAAA,QAAA;AAAA,MAAA;AAAA,IAEJ;AAAA,EAAA;AAQJ,SAAO,OAAO,aAAa,cAAc,aAAa,SAAS,SAAS,IAAI,IAAI;AAClF;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,MAAK;AAAA,MACL,cAAW;AAAA,MACX,cAAY,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAAA,MAChE,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,MAElB,UAAA,qBAAC,OAAA,EAAI,WAAU,uFACb,UAAA;AAAA,QAAA,oBAAC,MAAA,EAAG,WAAU,yBAAyB,UAAA,QAAQ,OAAM;AAAA,QACrD,oBAAC,KAAA,EAAE,WAAU,8CAA8C,kBAAQ,SAAQ;AAAA,QAC3E,qBAAC,OAAA,EAAI,WAAU,+CACb,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAO,SAAQ,SAAQ,MAAK,MAAK,SAAS,UACxC,kBAAQ,YAAA,CACX;AAAA,UACA,oBAAC,UAAO,SAAQ,eAAc,MAAK,MAAK,SAAS,WAC9C,UAAA,QAAQ,aAAA,CACX;AAAA,QAAA,EAAA,CACF;AAAA,MAAA,EAAA,CACF;AAAA,IAAA;AAAA,EAAA;AAGN;"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const react = require("react");
|
|
5
|
+
const reactDom = require("react-dom");
|
|
6
|
+
const utils = require("../lib/utils.cjs");
|
|
7
|
+
const Icon = require("../data/Icon.cjs");
|
|
8
|
+
const toastContext = require("./toast-context.cjs");
|
|
9
|
+
const UiClose = require("../icons/components/UiClose.cjs");
|
|
10
|
+
const DEFAULT_DURATION_MS = 2200;
|
|
11
|
+
const DOT_TONE = {
|
|
12
|
+
success: "bg-emerald-500",
|
|
13
|
+
danger: "bg-rose-500",
|
|
14
|
+
warning: "bg-amber-500",
|
|
15
|
+
info: "bg-sky-500",
|
|
16
|
+
neutral: "bg-primary"
|
|
17
|
+
};
|
|
18
|
+
function ToastProvider({ children, durationMs = DEFAULT_DURATION_MS }) {
|
|
19
|
+
const [toasts, setToasts] = react.useState([]);
|
|
20
|
+
const idRef = react.useRef(0);
|
|
21
|
+
const timers = react.useRef(/* @__PURE__ */ new Map());
|
|
22
|
+
const dismiss = react.useCallback((id) => {
|
|
23
|
+
setToasts((cur) => cur.filter((t) => t.id !== id));
|
|
24
|
+
const handle = timers.current.get(id);
|
|
25
|
+
if (handle !== void 0) {
|
|
26
|
+
clearTimeout(handle);
|
|
27
|
+
timers.current.delete(id);
|
|
28
|
+
}
|
|
29
|
+
}, []);
|
|
30
|
+
const toast = react.useCallback(
|
|
31
|
+
(options) => {
|
|
32
|
+
const normalized = typeof options === "string" ? { message: options } : options;
|
|
33
|
+
const id = idRef.current += 1;
|
|
34
|
+
setToasts((cur) => [...cur, { tone: "neutral", ...normalized, id }]);
|
|
35
|
+
const ttl = normalized.durationMs ?? durationMs;
|
|
36
|
+
if (ttl > 0) {
|
|
37
|
+
timers.current.set(
|
|
38
|
+
id,
|
|
39
|
+
setTimeout(() => dismiss(id), ttl)
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return id;
|
|
43
|
+
},
|
|
44
|
+
[dismiss, durationMs]
|
|
45
|
+
);
|
|
46
|
+
react.useEffect(() => {
|
|
47
|
+
const pending = timers.current;
|
|
48
|
+
return () => {
|
|
49
|
+
pending.forEach((handle) => clearTimeout(handle));
|
|
50
|
+
pending.clear();
|
|
51
|
+
};
|
|
52
|
+
}, []);
|
|
53
|
+
const value = react.useMemo(() => ({ toast, dismiss }), [toast, dismiss]);
|
|
54
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(toastContext.ToastContext.Provider, { value, children: [
|
|
55
|
+
children,
|
|
56
|
+
typeof document !== "undefined" && reactDom.createPortal(
|
|
57
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none fixed inset-x-0 bottom-6 z-[9999] flex flex-col items-center gap-density-2", children: toasts.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(ToastView, { entry, onDismiss: () => dismiss(entry.id) }, entry.id)) }),
|
|
58
|
+
document.body
|
|
59
|
+
)
|
|
60
|
+
] });
|
|
61
|
+
}
|
|
62
|
+
function ToastView({ entry, onDismiss }) {
|
|
63
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
64
|
+
"div",
|
|
65
|
+
{
|
|
66
|
+
role: "status",
|
|
67
|
+
className: utils.cn(
|
|
68
|
+
"pointer-events-auto flex items-center gap-density-2 rounded-md border border-border",
|
|
69
|
+
"bg-popover px-density-3 py-density-2 text-sm font-medium text-popover-foreground shadow-lg"
|
|
70
|
+
),
|
|
71
|
+
children: [
|
|
72
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: utils.cn("h-2 w-2 shrink-0 rounded-full", DOT_TONE[entry.tone ?? "neutral"]) }),
|
|
73
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: entry.message }),
|
|
74
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
75
|
+
"button",
|
|
76
|
+
{
|
|
77
|
+
type: "button",
|
|
78
|
+
onClick: onDismiss,
|
|
79
|
+
"aria-label": "Dismiss",
|
|
80
|
+
className: "ml-1 text-muted-foreground transition-colors hover:text-foreground",
|
|
81
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiClose.UiClose, className: "h-3 w-3" })
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
exports.ToastProvider = ToastProvider;
|
|
89
|
+
//# sourceMappingURL=Toast.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.cjs","sources":["../../src/overlay/Toast.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiClose } from \"../icons\";\nimport {\n ToastContext,\n type ToastEntry,\n type ToastOptions,\n type ToastTone,\n} from \"./toast-context\";\n\nconst DEFAULT_DURATION_MS = 2200;\n\nconst DOT_TONE: Record<ToastTone, string> = {\n success: \"bg-emerald-500\",\n danger: \"bg-rose-500\",\n warning: \"bg-amber-500\",\n info: \"bg-sky-500\",\n neutral: \"bg-primary\",\n};\n\nexport type ToastProviderProps = {\n children: ReactNode;\n /** Default auto-dismiss delay applied when a toast omits `durationMs`. */\n durationMs?: number;\n};\n\n/**\n * Provides the imperative toast API and renders the bottom-center stack into a\n * portal (the Gavel `PRDetail` confirmation toast — a tone dot plus a transient\n * message). Built on clicky tokens; auto-dismisses after `durationMs`. Consume\n * the API with `useToast()` from `./toast-context`.\n */\nexport function ToastProvider({ children, durationMs = DEFAULT_DURATION_MS }: ToastProviderProps) {\n const [toasts, setToasts] = useState<ToastEntry[]>([]);\n const idRef = useRef(0);\n const timers = useRef<Map<number, ReturnType<typeof setTimeout>>>(new Map());\n\n const dismiss = useCallback((id: number) => {\n setToasts((cur) => cur.filter((t) => t.id !== id));\n const handle = timers.current.get(id);\n if (handle !== undefined) {\n clearTimeout(handle);\n timers.current.delete(id);\n }\n }, []);\n\n const toast = useCallback(\n (options: ToastOptions | string) => {\n const normalized: ToastOptions = typeof options === \"string\" ? { message: options } : options;\n const id = (idRef.current += 1);\n setToasts((cur) => [...cur, { tone: \"neutral\", ...normalized, id }]);\n const ttl = normalized.durationMs ?? durationMs;\n if (ttl > 0) {\n timers.current.set(\n id,\n setTimeout(() => dismiss(id), ttl),\n );\n }\n return id;\n },\n [dismiss, durationMs],\n );\n\n useEffect(() => {\n const pending = timers.current;\n return () => {\n pending.forEach((handle) => clearTimeout(handle));\n pending.clear();\n };\n }, []);\n\n const value = useMemo(() => ({ toast, dismiss }), [toast, dismiss]);\n\n return (\n <ToastContext.Provider value={value}>\n {children}\n {typeof document !== \"undefined\" &&\n createPortal(\n <div className=\"pointer-events-none fixed inset-x-0 bottom-6 z-[9999] flex flex-col items-center gap-density-2\">\n {toasts.map((entry) => (\n <ToastView key={entry.id} entry={entry} onDismiss={() => dismiss(entry.id)} />\n ))}\n </div>,\n document.body,\n )}\n </ToastContext.Provider>\n );\n}\n\nfunction ToastView({ entry, onDismiss }: { entry: ToastEntry; onDismiss: () => void }) {\n return (\n <div\n role=\"status\"\n className={cn(\n \"pointer-events-auto flex items-center gap-density-2 rounded-md border border-border\",\n \"bg-popover px-density-3 py-density-2 text-sm font-medium text-popover-foreground shadow-lg\",\n )}\n >\n <span className={cn(\"h-2 w-2 shrink-0 rounded-full\", DOT_TONE[entry.tone ?? \"neutral\"])} />\n <span>{entry.message}</span>\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label=\"Dismiss\"\n className=\"ml-1 text-muted-foreground transition-colors hover:text-foreground\"\n >\n <Icon icon={UiClose} className=\"h-3 w-3\" />\n </button>\n </div>\n );\n}\n"],"names":["useState","useRef","useCallback","useEffect","useMemo","jsxs","ToastContext","createPortal","jsx","cn","Icon","UiClose"],"mappings":";;;;;;;;;AAYA,MAAM,sBAAsB;AAE5B,MAAM,WAAsC;AAAA,EAC1C,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AACX;AAcO,SAAS,cAAc,EAAE,UAAU,aAAa,uBAA2C;AAChG,QAAM,CAAC,QAAQ,SAAS,IAAIA,MAAAA,SAAuB,CAAA,CAAE;AACrD,QAAM,QAAQC,MAAAA,OAAO,CAAC;AACtB,QAAM,SAASA,MAAAA,OAAmD,oBAAI,KAAK;AAE3E,QAAM,UAAUC,kBAAY,CAAC,OAAe;AAC1C,cAAU,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AACjD,UAAM,SAAS,OAAO,QAAQ,IAAI,EAAE;AACpC,QAAI,WAAW,QAAW;AACxB,mBAAa,MAAM;AACnB,aAAO,QAAQ,OAAO,EAAE;AAAA,IAC1B;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,QAAQA,MAAAA;AAAAA,IACZ,CAAC,YAAmC;AAClC,YAAM,aAA2B,OAAO,YAAY,WAAW,EAAE,SAAS,YAAY;AACtF,YAAM,KAAM,MAAM,WAAW;AAC7B,gBAAU,CAAC,QAAQ,CAAC,GAAG,KAAK,EAAE,MAAM,WAAW,GAAG,YAAY,GAAA,CAAI,CAAC;AACnE,YAAM,MAAM,WAAW,cAAc;AACrC,UAAI,MAAM,GAAG;AACX,eAAO,QAAQ;AAAA,UACb;AAAA,UACA,WAAW,MAAM,QAAQ,EAAE,GAAG,GAAG;AAAA,QAAA;AAAA,MAErC;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,SAAS,UAAU;AAAA,EAAA;AAGtBC,QAAAA,UAAU,MAAM;AACd,UAAM,UAAU,OAAO;AACvB,WAAO,MAAM;AACX,cAAQ,QAAQ,CAAC,WAAW,aAAa,MAAM,CAAC;AAChD,cAAQ,MAAA;AAAA,IACV;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,QAAQC,cAAQ,OAAO,EAAE,OAAO,YAAY,CAAC,OAAO,OAAO,CAAC;AAElE,SACEC,2BAAAA,KAACC,aAAAA,aAAa,UAAb,EAAsB,OACpB,UAAA;AAAA,IAAA;AAAA,IACA,OAAO,aAAa,eACnBC,SAAAA;AAAAA,MACEC,+BAAC,SAAI,WAAU,kGACZ,iBAAO,IAAI,CAAC,UACXA,+BAAC,WAAA,EAAyB,OAAc,WAAW,MAAM,QAAQ,MAAM,EAAE,KAAzD,MAAM,EAAsD,CAC7E,GACH;AAAA,MACA,SAAS;AAAA,IAAA;AAAA,EACX,GACJ;AAEJ;AAEA,SAAS,UAAU,EAAE,OAAO,aAA2D;AACrF,SACEH,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAWI,MAAAA;AAAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAGF,UAAA;AAAA,QAAAD,2BAAAA,IAAC,QAAA,EAAK,WAAWC,SAAG,iCAAiC,SAAS,MAAM,QAAQ,SAAS,CAAC,EAAA,CAAG;AAAA,QACzFD,2BAAAA,IAAC,QAAA,EAAM,UAAA,MAAM,QAAA,CAAQ;AAAA,QACrBA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS;AAAA,YACT,cAAW;AAAA,YACX,WAAU;AAAA,YAEV,UAAAA,2BAAAA,IAACE,WAAA,EAAK,MAAMC,QAAAA,SAAS,WAAU,UAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MAC3C;AAAA,IAAA;AAAA,EAAA;AAGN;;"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export type ToastProviderProps = {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
/** Default auto-dismiss delay applied when a toast omits `durationMs`. */
|
|
5
|
+
durationMs?: number;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Provides the imperative toast API and renders the bottom-center stack into a
|
|
9
|
+
* portal (the Gavel `PRDetail` confirmation toast — a tone dot plus a transient
|
|
10
|
+
* message). Built on clicky tokens; auto-dismisses after `durationMs`. Consume
|
|
11
|
+
* the API with `useToast()` from `./toast-context`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function ToastProvider({ children, durationMs }: ToastProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=Toast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../src/overlay/Toast.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAsB1F,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,UAAgC,EAAE,EAAE,kBAAkB,2CAuD/F"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useRef, useCallback, useEffect, useMemo } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
4
|
+
import { cn } from "../lib/utils.js";
|
|
5
|
+
import { Icon } from "../data/Icon.js";
|
|
6
|
+
import { ToastContext } from "./toast-context.js";
|
|
7
|
+
import { UiClose } from "../icons/components/UiClose.js";
|
|
8
|
+
const DEFAULT_DURATION_MS = 2200;
|
|
9
|
+
const DOT_TONE = {
|
|
10
|
+
success: "bg-emerald-500",
|
|
11
|
+
danger: "bg-rose-500",
|
|
12
|
+
warning: "bg-amber-500",
|
|
13
|
+
info: "bg-sky-500",
|
|
14
|
+
neutral: "bg-primary"
|
|
15
|
+
};
|
|
16
|
+
function ToastProvider({ children, durationMs = DEFAULT_DURATION_MS }) {
|
|
17
|
+
const [toasts, setToasts] = useState([]);
|
|
18
|
+
const idRef = useRef(0);
|
|
19
|
+
const timers = useRef(/* @__PURE__ */ new Map());
|
|
20
|
+
const dismiss = useCallback((id) => {
|
|
21
|
+
setToasts((cur) => cur.filter((t) => t.id !== id));
|
|
22
|
+
const handle = timers.current.get(id);
|
|
23
|
+
if (handle !== void 0) {
|
|
24
|
+
clearTimeout(handle);
|
|
25
|
+
timers.current.delete(id);
|
|
26
|
+
}
|
|
27
|
+
}, []);
|
|
28
|
+
const toast = useCallback(
|
|
29
|
+
(options) => {
|
|
30
|
+
const normalized = typeof options === "string" ? { message: options } : options;
|
|
31
|
+
const id = idRef.current += 1;
|
|
32
|
+
setToasts((cur) => [...cur, { tone: "neutral", ...normalized, id }]);
|
|
33
|
+
const ttl = normalized.durationMs ?? durationMs;
|
|
34
|
+
if (ttl > 0) {
|
|
35
|
+
timers.current.set(
|
|
36
|
+
id,
|
|
37
|
+
setTimeout(() => dismiss(id), ttl)
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
return id;
|
|
41
|
+
},
|
|
42
|
+
[dismiss, durationMs]
|
|
43
|
+
);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const pending = timers.current;
|
|
46
|
+
return () => {
|
|
47
|
+
pending.forEach((handle) => clearTimeout(handle));
|
|
48
|
+
pending.clear();
|
|
49
|
+
};
|
|
50
|
+
}, []);
|
|
51
|
+
const value = useMemo(() => ({ toast, dismiss }), [toast, dismiss]);
|
|
52
|
+
return /* @__PURE__ */ jsxs(ToastContext.Provider, { value, children: [
|
|
53
|
+
children,
|
|
54
|
+
typeof document !== "undefined" && createPortal(
|
|
55
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-none fixed inset-x-0 bottom-6 z-[9999] flex flex-col items-center gap-density-2", children: toasts.map((entry) => /* @__PURE__ */ jsx(ToastView, { entry, onDismiss: () => dismiss(entry.id) }, entry.id)) }),
|
|
56
|
+
document.body
|
|
57
|
+
)
|
|
58
|
+
] });
|
|
59
|
+
}
|
|
60
|
+
function ToastView({ entry, onDismiss }) {
|
|
61
|
+
return /* @__PURE__ */ jsxs(
|
|
62
|
+
"div",
|
|
63
|
+
{
|
|
64
|
+
role: "status",
|
|
65
|
+
className: cn(
|
|
66
|
+
"pointer-events-auto flex items-center gap-density-2 rounded-md border border-border",
|
|
67
|
+
"bg-popover px-density-3 py-density-2 text-sm font-medium text-popover-foreground shadow-lg"
|
|
68
|
+
),
|
|
69
|
+
children: [
|
|
70
|
+
/* @__PURE__ */ jsx("span", { className: cn("h-2 w-2 shrink-0 rounded-full", DOT_TONE[entry.tone ?? "neutral"]) }),
|
|
71
|
+
/* @__PURE__ */ jsx("span", { children: entry.message }),
|
|
72
|
+
/* @__PURE__ */ jsx(
|
|
73
|
+
"button",
|
|
74
|
+
{
|
|
75
|
+
type: "button",
|
|
76
|
+
onClick: onDismiss,
|
|
77
|
+
"aria-label": "Dismiss",
|
|
78
|
+
className: "ml-1 text-muted-foreground transition-colors hover:text-foreground",
|
|
79
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: UiClose, className: "h-3 w-3" })
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
export {
|
|
87
|
+
ToastProvider
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=Toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.js","sources":["../../src/overlay/Toast.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiClose } from \"../icons\";\nimport {\n ToastContext,\n type ToastEntry,\n type ToastOptions,\n type ToastTone,\n} from \"./toast-context\";\n\nconst DEFAULT_DURATION_MS = 2200;\n\nconst DOT_TONE: Record<ToastTone, string> = {\n success: \"bg-emerald-500\",\n danger: \"bg-rose-500\",\n warning: \"bg-amber-500\",\n info: \"bg-sky-500\",\n neutral: \"bg-primary\",\n};\n\nexport type ToastProviderProps = {\n children: ReactNode;\n /** Default auto-dismiss delay applied when a toast omits `durationMs`. */\n durationMs?: number;\n};\n\n/**\n * Provides the imperative toast API and renders the bottom-center stack into a\n * portal (the Gavel `PRDetail` confirmation toast — a tone dot plus a transient\n * message). Built on clicky tokens; auto-dismisses after `durationMs`. Consume\n * the API with `useToast()` from `./toast-context`.\n */\nexport function ToastProvider({ children, durationMs = DEFAULT_DURATION_MS }: ToastProviderProps) {\n const [toasts, setToasts] = useState<ToastEntry[]>([]);\n const idRef = useRef(0);\n const timers = useRef<Map<number, ReturnType<typeof setTimeout>>>(new Map());\n\n const dismiss = useCallback((id: number) => {\n setToasts((cur) => cur.filter((t) => t.id !== id));\n const handle = timers.current.get(id);\n if (handle !== undefined) {\n clearTimeout(handle);\n timers.current.delete(id);\n }\n }, []);\n\n const toast = useCallback(\n (options: ToastOptions | string) => {\n const normalized: ToastOptions = typeof options === \"string\" ? { message: options } : options;\n const id = (idRef.current += 1);\n setToasts((cur) => [...cur, { tone: \"neutral\", ...normalized, id }]);\n const ttl = normalized.durationMs ?? durationMs;\n if (ttl > 0) {\n timers.current.set(\n id,\n setTimeout(() => dismiss(id), ttl),\n );\n }\n return id;\n },\n [dismiss, durationMs],\n );\n\n useEffect(() => {\n const pending = timers.current;\n return () => {\n pending.forEach((handle) => clearTimeout(handle));\n pending.clear();\n };\n }, []);\n\n const value = useMemo(() => ({ toast, dismiss }), [toast, dismiss]);\n\n return (\n <ToastContext.Provider value={value}>\n {children}\n {typeof document !== \"undefined\" &&\n createPortal(\n <div className=\"pointer-events-none fixed inset-x-0 bottom-6 z-[9999] flex flex-col items-center gap-density-2\">\n {toasts.map((entry) => (\n <ToastView key={entry.id} entry={entry} onDismiss={() => dismiss(entry.id)} />\n ))}\n </div>,\n document.body,\n )}\n </ToastContext.Provider>\n );\n}\n\nfunction ToastView({ entry, onDismiss }: { entry: ToastEntry; onDismiss: () => void }) {\n return (\n <div\n role=\"status\"\n className={cn(\n \"pointer-events-auto flex items-center gap-density-2 rounded-md border border-border\",\n \"bg-popover px-density-3 py-density-2 text-sm font-medium text-popover-foreground shadow-lg\",\n )}\n >\n <span className={cn(\"h-2 w-2 shrink-0 rounded-full\", DOT_TONE[entry.tone ?? \"neutral\"])} />\n <span>{entry.message}</span>\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label=\"Dismiss\"\n className=\"ml-1 text-muted-foreground transition-colors hover:text-foreground\"\n >\n <Icon icon={UiClose} className=\"h-3 w-3\" />\n </button>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAYA,MAAM,sBAAsB;AAE5B,MAAM,WAAsC;AAAA,EAC1C,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AACX;AAcO,SAAS,cAAc,EAAE,UAAU,aAAa,uBAA2C;AAChG,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAuB,CAAA,CAAE;AACrD,QAAM,QAAQ,OAAO,CAAC;AACtB,QAAM,SAAS,OAAmD,oBAAI,KAAK;AAE3E,QAAM,UAAU,YAAY,CAAC,OAAe;AAC1C,cAAU,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AACjD,UAAM,SAAS,OAAO,QAAQ,IAAI,EAAE;AACpC,QAAI,WAAW,QAAW;AACxB,mBAAa,MAAM;AACnB,aAAO,QAAQ,OAAO,EAAE;AAAA,IAC1B;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,QAAQ;AAAA,IACZ,CAAC,YAAmC;AAClC,YAAM,aAA2B,OAAO,YAAY,WAAW,EAAE,SAAS,YAAY;AACtF,YAAM,KAAM,MAAM,WAAW;AAC7B,gBAAU,CAAC,QAAQ,CAAC,GAAG,KAAK,EAAE,MAAM,WAAW,GAAG,YAAY,GAAA,CAAI,CAAC;AACnE,YAAM,MAAM,WAAW,cAAc;AACrC,UAAI,MAAM,GAAG;AACX,eAAO,QAAQ;AAAA,UACb;AAAA,UACA,WAAW,MAAM,QAAQ,EAAE,GAAG,GAAG;AAAA,QAAA;AAAA,MAErC;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,SAAS,UAAU;AAAA,EAAA;AAGtB,YAAU,MAAM;AACd,UAAM,UAAU,OAAO;AACvB,WAAO,MAAM;AACX,cAAQ,QAAQ,CAAC,WAAW,aAAa,MAAM,CAAC;AAChD,cAAQ,MAAA;AAAA,IACV;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,QAAQ,QAAQ,OAAO,EAAE,OAAO,YAAY,CAAC,OAAO,OAAO,CAAC;AAElE,SACE,qBAAC,aAAa,UAAb,EAAsB,OACpB,UAAA;AAAA,IAAA;AAAA,IACA,OAAO,aAAa,eACnB;AAAA,MACE,oBAAC,SAAI,WAAU,kGACZ,iBAAO,IAAI,CAAC,UACX,oBAAC,WAAA,EAAyB,OAAc,WAAW,MAAM,QAAQ,MAAM,EAAE,KAAzD,MAAM,EAAsD,CAC7E,GACH;AAAA,MACA,SAAS;AAAA,IAAA;AAAA,EACX,GACJ;AAEJ;AAEA,SAAS,UAAU,EAAE,OAAO,aAA2D;AACrF,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAGF,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAW,GAAG,iCAAiC,SAAS,MAAM,QAAQ,SAAS,CAAC,EAAA,CAAG;AAAA,QACzF,oBAAC,QAAA,EAAM,UAAA,MAAM,QAAA,CAAQ;AAAA,QACrB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS;AAAA,YACT,cAAW;AAAA,YACX,WAAU;AAAA,YAEV,UAAA,oBAAC,MAAA,EAAK,MAAM,SAAS,WAAU,UAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MAC3C;AAAA,IAAA;AAAA,EAAA;AAGN;"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const react = require("react");
|
|
4
|
+
const ToastContext = react.createContext(null);
|
|
5
|
+
function useToast() {
|
|
6
|
+
const ctx = react.useContext(ToastContext);
|
|
7
|
+
if (!ctx) throw new Error("useToast must be used within a <ToastProvider>");
|
|
8
|
+
return ctx;
|
|
9
|
+
}
|
|
10
|
+
exports.ToastContext = ToastContext;
|
|
11
|
+
exports.useToast = useToast;
|
|
12
|
+
//# sourceMappingURL=toast-context.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast-context.cjs","sources":["../../src/overlay/toast-context.ts"],"sourcesContent":["import { createContext, useContext, type ReactNode } from \"react\";\nimport type { BadgeTone } from \"../data/Badge\";\n\nexport type ToastTone = BadgeTone;\n\nexport type ToastOptions = {\n /** Message body. */\n message: ReactNode;\n /** Semantic color of the leading dot. Defaults to `neutral`. */\n tone?: ToastTone;\n /** Auto-dismiss delay in ms. `0` keeps it until dismissed. */\n durationMs?: number;\n};\n\nexport type ToastEntry = ToastOptions & { id: number };\n\nexport type ToastContextValue = {\n /** Show a toast; returns its id. Pass a string for a neutral message. */\n toast: (options: ToastOptions | string) => number;\n /** Dismiss a toast by id. */\n dismiss: (id: number) => void;\n};\n\nexport const ToastContext = createContext<ToastContextValue | null>(null);\n\n/** Access the toast API. Must be called under a `<ToastProvider>`. */\nexport function useToast(): ToastContextValue {\n const ctx = useContext(ToastContext);\n if (!ctx) throw new Error(\"useToast must be used within a <ToastProvider>\");\n return ctx;\n}\n"],"names":["createContext","useContext"],"mappings":";;;AAuBO,MAAM,eAAeA,MAAAA,cAAwC,IAAI;AAGjE,SAAS,WAA8B;AAC5C,QAAM,MAAMC,MAAAA,WAAW,YAAY;AACnC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,gDAAgD;AAC1E,SAAO;AACT;;;"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { BadgeTone } from '../data/Badge';
|
|
3
|
+
export type ToastTone = BadgeTone;
|
|
4
|
+
export type ToastOptions = {
|
|
5
|
+
/** Message body. */
|
|
6
|
+
message: ReactNode;
|
|
7
|
+
/** Semantic color of the leading dot. Defaults to `neutral`. */
|
|
8
|
+
tone?: ToastTone;
|
|
9
|
+
/** Auto-dismiss delay in ms. `0` keeps it until dismissed. */
|
|
10
|
+
durationMs?: number;
|
|
11
|
+
};
|
|
12
|
+
export type ToastEntry = ToastOptions & {
|
|
13
|
+
id: number;
|
|
14
|
+
};
|
|
15
|
+
export type ToastContextValue = {
|
|
16
|
+
/** Show a toast; returns its id. Pass a string for a neutral message. */
|
|
17
|
+
toast: (options: ToastOptions | string) => number;
|
|
18
|
+
/** Dismiss a toast by id. */
|
|
19
|
+
dismiss: (id: number) => void;
|
|
20
|
+
};
|
|
21
|
+
export declare const ToastContext: import('react').Context<ToastContextValue | null>;
|
|
22
|
+
/** Access the toast API. Must be called under a `<ToastProvider>`. */
|
|
23
|
+
export declare function useToast(): ToastContextValue;
|
|
24
|
+
//# sourceMappingURL=toast-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast-context.d.ts","sourceRoot":"","sources":["../../src/overlay/toast-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC;AAElC,MAAM,MAAM,YAAY,GAAG;IACzB,oBAAoB;IACpB,OAAO,EAAE,SAAS,CAAC;IACnB,gEAAgE;IAChE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,yEAAyE;IACzE,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,KAAK,MAAM,CAAC;IAClD,6BAA6B;IAC7B,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,YAAY,mDAAgD,CAAC;AAE1E,sEAAsE;AACtE,wBAAgB,QAAQ,IAAI,iBAAiB,CAI5C"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useContext, createContext } from "react";
|
|
2
|
+
const ToastContext = createContext(null);
|
|
3
|
+
function useToast() {
|
|
4
|
+
const ctx = useContext(ToastContext);
|
|
5
|
+
if (!ctx) throw new Error("useToast must be used within a <ToastProvider>");
|
|
6
|
+
return ctx;
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
ToastContext,
|
|
10
|
+
useToast
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=toast-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast-context.js","sources":["../../src/overlay/toast-context.ts"],"sourcesContent":["import { createContext, useContext, type ReactNode } from \"react\";\nimport type { BadgeTone } from \"../data/Badge\";\n\nexport type ToastTone = BadgeTone;\n\nexport type ToastOptions = {\n /** Message body. */\n message: ReactNode;\n /** Semantic color of the leading dot. Defaults to `neutral`. */\n tone?: ToastTone;\n /** Auto-dismiss delay in ms. `0` keeps it until dismissed. */\n durationMs?: number;\n};\n\nexport type ToastEntry = ToastOptions & { id: number };\n\nexport type ToastContextValue = {\n /** Show a toast; returns its id. Pass a string for a neutral message. */\n toast: (options: ToastOptions | string) => number;\n /** Dismiss a toast by id. */\n dismiss: (id: number) => void;\n};\n\nexport const ToastContext = createContext<ToastContextValue | null>(null);\n\n/** Access the toast API. Must be called under a `<ToastProvider>`. */\nexport function useToast(): ToastContextValue {\n const ctx = useContext(ToastContext);\n if (!ctx) throw new Error(\"useToast must be used within a <ToastProvider>\");\n return ctx;\n}\n"],"names":[],"mappings":";AAuBO,MAAM,eAAe,cAAwC,IAAI;AAGjE,SAAS,WAA8B;AAC5C,QAAM,MAAM,WAAW,YAAY;AACnC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,gDAAgD;AAC1E,SAAO;AACT;"}
|
|
@@ -22,14 +22,16 @@ function AcceptPicker({
|
|
|
22
22
|
onPreviewModeChange,
|
|
23
23
|
className
|
|
24
24
|
}) {
|
|
25
|
+
var _a;
|
|
25
26
|
const rootRef = react.useRef(null);
|
|
26
27
|
const [open, setOpen] = react.useState(false);
|
|
27
28
|
const pad = size === "sm" ? "px-2 py-0.5" : "px-2.5 py-1";
|
|
29
|
+
const activeLabel = ((_a = options.find((opt) => opt.value === value)) == null ? void 0 : _a.label) ?? value;
|
|
28
30
|
react.useEffect(() => {
|
|
29
31
|
if (!open) return;
|
|
30
32
|
const onPointerDown = (event) => {
|
|
31
|
-
var
|
|
32
|
-
if (!((
|
|
33
|
+
var _a2;
|
|
34
|
+
if (!((_a2 = rootRef.current) == null ? void 0 : _a2.contains(event.target))) {
|
|
33
35
|
setOpen(false);
|
|
34
36
|
}
|
|
35
37
|
};
|
|
@@ -43,70 +45,91 @@ function AcceptPicker({
|
|
|
43
45
|
document.removeEventListener("keydown", onKeyDown);
|
|
44
46
|
};
|
|
45
47
|
}, [open]);
|
|
46
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: rootRef, className: utils.cn("relative flex
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: rootRef, className: utils.cn("relative flex", className), children: [
|
|
49
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
50
|
+
button.Button,
|
|
49
51
|
{
|
|
50
52
|
type: "button",
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
),
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
53
|
+
variant: "outline",
|
|
54
|
+
size: "sm",
|
|
55
|
+
"aria-label": "Open format menu",
|
|
56
|
+
"aria-haspopup": "menu",
|
|
57
|
+
"aria-expanded": open,
|
|
58
|
+
className: utils.cn("h-auto gap-1.5", pad),
|
|
59
|
+
onClick: () => setOpen((current) => !current),
|
|
60
|
+
children: [
|
|
61
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: activeLabel }),
|
|
62
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiEllipsis.UiEllipsis, className: "text-muted-foreground" })
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
),
|
|
66
|
+
open && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
67
|
+
"div",
|
|
68
|
+
{
|
|
69
|
+
role: "menu",
|
|
70
|
+
"aria-label": "Format and preview options",
|
|
71
|
+
className: "absolute right-0 top-[calc(100%+0.375rem)] z-50 min-w-[12rem] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5",
|
|
72
|
+
children: [
|
|
73
|
+
/* @__PURE__ */ jsxRuntime.jsx(MenuSectionLabel, { children: "Format" }),
|
|
74
|
+
options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
75
|
+
MenuRadioItem,
|
|
76
|
+
{
|
|
77
|
+
label: opt.label,
|
|
78
|
+
active: opt.value === value,
|
|
79
|
+
onSelect: () => {
|
|
80
|
+
onChange(opt.value);
|
|
81
|
+
setOpen(false);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
opt.value
|
|
85
|
+
)),
|
|
86
|
+
onPreviewModeChange && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
87
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { role: "separator", className: "my-1 h-px bg-border" }),
|
|
88
|
+
/* @__PURE__ */ jsxRuntime.jsx(MenuSectionLabel, { children: "Preview" }),
|
|
89
|
+
PREVIEW_OPTIONS.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
90
|
+
MenuRadioItem,
|
|
86
91
|
{
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
className: utils.cn(
|
|
91
|
-
"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm transition-colors",
|
|
92
|
-
"hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none"
|
|
93
|
-
),
|
|
94
|
-
onClick: () => {
|
|
92
|
+
label: option.label,
|
|
93
|
+
active: option.value === previewMode,
|
|
94
|
+
onSelect: () => {
|
|
95
95
|
onPreviewModeChange(option.value);
|
|
96
96
|
setOpen(false);
|
|
97
|
-
}
|
|
98
|
-
children: [
|
|
99
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1", children: option.label }),
|
|
100
|
-
active ? /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiCheck.UiCheck, className: "shrink-0" }) : null
|
|
101
|
-
]
|
|
97
|
+
}
|
|
102
98
|
},
|
|
103
99
|
option.value
|
|
104
|
-
)
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
))
|
|
101
|
+
] })
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
)
|
|
109
105
|
] });
|
|
110
106
|
}
|
|
107
|
+
function MenuSectionLabel({ children }) {
|
|
108
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground", children });
|
|
109
|
+
}
|
|
110
|
+
function MenuRadioItem({
|
|
111
|
+
label,
|
|
112
|
+
active,
|
|
113
|
+
onSelect
|
|
114
|
+
}) {
|
|
115
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
116
|
+
"button",
|
|
117
|
+
{
|
|
118
|
+
type: "button",
|
|
119
|
+
role: "menuitemradio",
|
|
120
|
+
"aria-checked": active,
|
|
121
|
+
className: utils.cn(
|
|
122
|
+
"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm transition-colors",
|
|
123
|
+
"hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none",
|
|
124
|
+
active && "font-medium"
|
|
125
|
+
),
|
|
126
|
+
onClick: onSelect,
|
|
127
|
+
children: [
|
|
128
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1", children: label }),
|
|
129
|
+
active ? /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiCheck.UiCheck, className: "shrink-0" }) : null
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
}
|
|
111
134
|
exports.AcceptPicker = AcceptPicker;
|
|
112
135
|
//# sourceMappingURL=AcceptPicker.cjs.map
|