@flanksource/clicky-ui 0.1.0 → 0.2.2
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/README.md +29 -2
- package/dist/api-explorer.d.ts +5 -0
- package/dist/api-explorer.d.ts.map +1 -0
- package/dist/api-explorer.js +25 -0
- package/dist/api-explorer.js.map +1 -0
- package/dist/clicky.d.ts +2 -0
- package/dist/clicky.d.ts.map +1 -0
- package/dist/clicky.js +5 -0
- package/dist/clicky.js.map +1 -0
- package/dist/components/DatePicker.d.ts +18 -0
- package/dist/components/DatePicker.d.ts.map +1 -0
- package/dist/components/DatePicker.js +63 -0
- package/dist/components/DatePicker.js.map +1 -0
- package/dist/components/DateTimePicker.d.ts +18 -0
- package/dist/components/DateTimePicker.d.ts.map +1 -0
- package/dist/components/DateTimePicker.js +84 -0
- package/dist/components/DateTimePicker.js.map +1 -0
- package/dist/components/FilterBar.d.ts +180 -0
- package/dist/components/FilterBar.d.ts.map +1 -0
- package/dist/components/FilterBar.js +1685 -0
- package/dist/components/FilterBar.js.map +1 -0
- package/dist/components/MultiSelect.d.ts +19 -0
- package/dist/components/MultiSelect.d.ts.map +1 -0
- package/dist/components/MultiSelect.js +143 -0
- package/dist/components/MultiSelect.js.map +1 -0
- package/dist/components/RangeSlider.d.ts +16 -0
- package/dist/components/RangeSlider.d.ts.map +1 -0
- package/dist/components/RangeSlider.js +92 -0
- package/dist/components/RangeSlider.js.map +1 -0
- package/dist/components/button.d.ts +21 -0
- package/dist/components/button.d.ts.map +1 -0
- package/dist/components/button.js +126 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/density-switcher.d.ts +7 -0
- package/dist/components/density-switcher.d.ts.map +1 -0
- package/dist/components/density-switcher.js +32 -0
- package/dist/components/density-switcher.js.map +1 -0
- package/dist/components/icon-menu-picker.d.ts +23 -0
- package/dist/components/icon-menu-picker.d.ts.map +1 -0
- package/dist/components/icon-menu-picker.js +192 -0
- package/dist/components/icon-menu-picker.js.map +1 -0
- package/dist/components/select.d.ts +15 -0
- package/dist/components/select.d.ts.map +1 -0
- package/dist/components/select.js +39 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/theme-switcher.d.ts +7 -0
- package/dist/components/theme-switcher.d.ts.map +1 -0
- package/dist/components/theme-switcher.js +42 -0
- package/dist/components/theme-switcher.js.map +1 -0
- package/dist/components.d.ts +15 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +33 -0
- package/dist/components.js.map +1 -0
- package/dist/data/AnsiHtml.d.ts +7 -0
- package/dist/data/AnsiHtml.d.ts.map +1 -0
- package/dist/data/AnsiHtml.js +71 -0
- package/dist/data/AnsiHtml.js.map +1 -0
- package/dist/data/Avatar.d.ts +32 -0
- package/dist/data/Avatar.d.ts.map +1 -0
- package/dist/data/Avatar.js +201 -0
- package/dist/data/Avatar.js.map +1 -0
- package/dist/data/AvatarBadge.d.ts +26 -0
- package/dist/data/AvatarBadge.d.ts.map +1 -0
- package/dist/data/AvatarBadge.js +104 -0
- package/dist/data/AvatarBadge.js.map +1 -0
- package/dist/data/Badge.d.ts +44 -0
- package/dist/data/Badge.d.ts.map +1 -0
- package/dist/data/Badge.js +667 -0
- package/dist/data/Badge.js.map +1 -0
- package/dist/data/Clicky.d.ts +147 -0
- package/dist/data/Clicky.d.ts.map +1 -0
- package/dist/data/Clicky.fixtures.d.ts +3 -0
- package/dist/data/Clicky.fixtures.d.ts.map +1 -0
- package/dist/data/Clicky.js +1960 -0
- package/dist/data/Clicky.js.map +1 -0
- package/dist/data/DataTable.d.ts +95 -0
- package/dist/data/DataTable.d.ts.map +1 -0
- package/dist/data/DataTable.js +1464 -0
- package/dist/data/DataTable.js.map +1 -0
- package/dist/data/FilterPill.d.ts +29 -0
- package/dist/data/FilterPill.d.ts.map +1 -0
- package/dist/data/FilterPill.js +153 -0
- package/dist/data/FilterPill.js.map +1 -0
- package/dist/data/Gauge.d.ts +15 -0
- package/dist/data/Gauge.d.ts.map +1 -0
- package/dist/data/Gauge.js +63 -0
- package/dist/data/Gauge.js.map +1 -0
- package/dist/data/Icon.d.ts +53 -0
- package/dist/data/Icon.d.ts.map +1 -0
- package/dist/data/Icon.js +115 -0
- package/dist/data/Icon.js.map +1 -0
- package/dist/data/JsonView.d.ts +8 -0
- package/dist/data/JsonView.d.ts.map +1 -0
- package/dist/data/JsonView.js +74 -0
- package/dist/data/JsonView.js.map +1 -0
- package/dist/data/KeyValueList.d.ts +17 -0
- package/dist/data/KeyValueList.d.ts.map +1 -0
- package/dist/data/KeyValueList.js +33 -0
- package/dist/data/KeyValueList.js.map +1 -0
- package/dist/data/LogViewer.d.ts +10 -0
- package/dist/data/LogViewer.d.ts.map +1 -0
- package/dist/data/LogViewer.js +46 -0
- package/dist/data/LogViewer.js.map +1 -0
- package/dist/data/LogsTable.d.ts +27 -0
- package/dist/data/LogsTable.d.ts.map +1 -0
- package/dist/data/LogsTable.js +580 -0
- package/dist/data/LogsTable.js.map +1 -0
- package/dist/data/Markdown.d.ts +6 -0
- package/dist/data/Markdown.d.ts.map +1 -0
- package/dist/data/Markdown.js +59 -0
- package/dist/data/Markdown.js.map +1 -0
- package/dist/data/MatrixTable.d.ts +22 -0
- package/dist/data/MatrixTable.d.ts.map +1 -0
- package/dist/data/MatrixTable.js +164 -0
- package/dist/data/MatrixTable.js.map +1 -0
- package/dist/data/MethodBadge.d.ts +6 -0
- package/dist/data/MethodBadge.d.ts.map +1 -0
- package/dist/data/MethodBadge.js +18 -0
- package/dist/data/MethodBadge.js.map +1 -0
- package/dist/data/ProgressBar.d.ts +13 -0
- package/dist/data/ProgressBar.d.ts.map +1 -0
- package/dist/data/ProgressBar.js +34 -0
- package/dist/data/ProgressBar.js.map +1 -0
- package/dist/data/SortableHeader.d.ts +12 -0
- package/dist/data/SortableHeader.d.ts.map +1 -0
- package/dist/data/SortableHeader.js +33 -0
- package/dist/data/SortableHeader.js.map +1 -0
- package/dist/data/TabButton.d.ts +12 -0
- package/dist/data/TabButton.d.ts.map +1 -0
- package/dist/data/TabButton.js +45 -0
- package/dist/data/TabButton.js.map +1 -0
- package/dist/data/Tree.d.ts +35 -0
- package/dist/data/Tree.d.ts.map +1 -0
- package/dist/data/Tree.js +236 -0
- package/dist/data/Tree.js.map +1 -0
- package/dist/data/TreeGroupHeader.d.ts +11 -0
- package/dist/data/TreeGroupHeader.d.ts.map +1 -0
- package/dist/data/TreeGroupHeader.js +41 -0
- package/dist/data/TreeGroupHeader.js.map +1 -0
- package/dist/data/TreeNode.d.ts +43 -0
- package/dist/data/TreeNode.d.ts.map +1 -0
- package/dist/data/TreeNode.js +100 -0
- package/dist/data/TreeNode.js.map +1 -0
- package/dist/data/cells/StatusDot.d.ts +11 -0
- package/dist/data/cells/StatusDot.d.ts.map +1 -0
- package/dist/data/cells/StatusDot.js +38 -0
- package/dist/data/cells/StatusDot.js.map +1 -0
- package/dist/data/cells/TagList.d.ts +59 -0
- package/dist/data/cells/TagList.d.ts.map +1 -0
- package/dist/data/cells/TagList.js +257 -0
- package/dist/data/cells/TagList.js.map +1 -0
- package/dist/data/cells/Timestamp.d.ts +46 -0
- package/dist/data/cells/Timestamp.d.ts.map +1 -0
- package/dist/data/cells/Timestamp.js +146 -0
- package/dist/data/cells/Timestamp.js.map +1 -0
- package/dist/data/cells/status-mapping.d.ts +8 -0
- package/dist/data/cells/status-mapping.d.ts.map +1 -0
- package/dist/data/cells/status-mapping.js +44 -0
- package/dist/data/cells/status-mapping.js.map +1 -0
- package/dist/data/code-highlight.d.ts +12 -0
- package/dist/data/code-highlight.d.ts.map +1 -0
- package/dist/data/code-highlight.js +28 -0
- package/dist/data/code-highlight.js.map +1 -0
- package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts +9 -0
- package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts.map +1 -0
- package/dist/data/diagnostics/DiagnosticsDetailPanel.js +445 -0
- package/dist/data/diagnostics/DiagnosticsDetailPanel.js.map +1 -0
- package/dist/data/diagnostics/DiagnosticsTree.d.ts +9 -0
- package/dist/data/diagnostics/DiagnosticsTree.d.ts.map +1 -0
- package/dist/data/diagnostics/DiagnosticsTree.js +78 -0
- package/dist/data/diagnostics/DiagnosticsTree.js.map +1 -0
- package/dist/data/diagnostics/ErrorDetails.d.ts +20 -0
- package/dist/data/diagnostics/ErrorDetails.d.ts.map +1 -0
- package/dist/data/diagnostics/ErrorDetails.js +157 -0
- package/dist/data/diagnostics/ErrorDetails.js.map +1 -0
- package/dist/data/diagnostics/GoroutineCard.d.ts +10 -0
- package/dist/data/diagnostics/GoroutineCard.d.ts.map +1 -0
- package/dist/data/diagnostics/GoroutineCard.js +75 -0
- package/dist/data/diagnostics/GoroutineCard.js.map +1 -0
- package/dist/data/diagnostics/JvmStackTrace.d.ts +11 -0
- package/dist/data/diagnostics/JvmStackTrace.d.ts.map +1 -0
- package/dist/data/diagnostics/JvmStackTrace.js +26 -0
- package/dist/data/diagnostics/JvmStackTrace.js.map +1 -0
- package/dist/data/diagnostics/RenderedStackTrace.d.ts +18 -0
- package/dist/data/diagnostics/RenderedStackTrace.d.ts.map +1 -0
- package/dist/data/diagnostics/RenderedStackTrace.js +235 -0
- package/dist/data/diagnostics/RenderedStackTrace.js.map +1 -0
- package/dist/data/diagnostics/ThreadCard.d.ts +10 -0
- package/dist/data/diagnostics/ThreadCard.d.ts.map +1 -0
- package/dist/data/diagnostics/ThreadCard.js +78 -0
- package/dist/data/diagnostics/ThreadCard.js.map +1 -0
- package/dist/data/diagnostics/error-diagnostics.d.ts +26 -0
- package/dist/data/diagnostics/error-diagnostics.d.ts.map +1 -0
- package/dist/data/diagnostics/error-diagnostics.js +108 -0
- package/dist/data/diagnostics/error-diagnostics.js.map +1 -0
- package/dist/data/diagnostics/fixtures.d.ts +3 -0
- package/dist/data/diagnostics/fixtures.d.ts.map +1 -0
- package/dist/data/diagnostics/jvm-stacktrace.d.ts +34 -0
- package/dist/data/diagnostics/jvm-stacktrace.d.ts.map +1 -0
- package/dist/data/diagnostics/jvm-stacktrace.js +190 -0
- package/dist/data/diagnostics/jvm-stacktrace.js.map +1 -0
- package/dist/data/diagnostics/stacktrace-parse.d.ts +11 -0
- package/dist/data/diagnostics/stacktrace-parse.d.ts.map +1 -0
- package/dist/data/diagnostics/stacktrace-parse.js +87 -0
- package/dist/data/diagnostics/stacktrace-parse.js.map +1 -0
- package/dist/data/diagnostics/stacktrace.d.ts +38 -0
- package/dist/data/diagnostics/stacktrace.d.ts.map +1 -0
- package/dist/data/diagnostics/stacktrace.js +119 -0
- package/dist/data/diagnostics/stacktrace.js.map +1 -0
- package/dist/data/diagnostics/types.d.ts +30 -0
- package/dist/data/diagnostics/types.d.ts.map +1 -0
- package/dist/data/diagnostics/utils.d.ts +8 -0
- package/dist/data/diagnostics/utils.d.ts.map +1 -0
- package/dist/data/diagnostics/utils.js +59 -0
- package/dist/data/diagnostics/utils.js.map +1 -0
- package/dist/data/har/HarPanel.d.ts +9 -0
- package/dist/data/har/HarPanel.d.ts.map +1 -0
- package/dist/data/har/HarPanel.js +175 -0
- package/dist/data/har/HarPanel.js.map +1 -0
- package/dist/data/har/fixtures.d.ts +3 -0
- package/dist/data/har/fixtures.d.ts.map +1 -0
- package/dist/data/har/types.d.ts +47 -0
- package/dist/data/har/types.d.ts.map +1 -0
- package/dist/data.d.ts +39 -0
- package/dist/data.d.ts.map +1 -0
- package/dist/data.js +109 -0
- package/dist/data.js.map +1 -0
- package/dist/hooks/use-density.d.ts +22 -0
- package/dist/hooks/use-density.d.ts.map +1 -0
- package/dist/hooks/use-density.js +54 -0
- package/dist/hooks/use-density.js.map +1 -0
- package/dist/hooks/use-history-route.d.ts +6 -0
- package/dist/hooks/use-history-route.d.ts.map +1 -0
- package/dist/hooks/use-history-route.js +31 -0
- package/dist/hooks/use-history-route.js.map +1 -0
- package/dist/hooks/use-sort.d.ts +17 -0
- package/dist/hooks/use-sort.d.ts.map +1 -0
- package/dist/hooks/use-sort.js +42 -0
- package/dist/hooks/use-sort.js.map +1 -0
- package/dist/hooks/use-theme.d.ts +17 -0
- package/dist/hooks/use-theme.d.ts.map +1 -0
- package/dist/hooks/use-theme.js +68 -0
- package/dist/hooks/use-theme.js.map +1 -0
- package/dist/hooks.d.ts +5 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +14 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +195 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/Section.d.ts +23 -0
- package/dist/layout/Section.d.ts.map +1 -0
- package/dist/layout/Section.js +73 -0
- package/dist/layout/Section.js.map +1 -0
- package/dist/layout/SplitPane.d.ts +13 -0
- package/dist/layout/SplitPane.d.ts.map +1 -0
- package/dist/layout/SplitPane.js +72 -0
- package/dist/layout/SplitPane.js.map +1 -0
- package/dist/lib/palette.d.ts +4 -0
- package/dist/lib/palette.d.ts.map +1 -0
- package/dist/lib/palette.js +35 -0
- package/dist/lib/palette.js.map +1 -0
- package/dist/lib/size.d.ts +6 -0
- package/dist/lib/size.d.ts.map +1 -0
- package/dist/lib/size.js +14 -0
- package/dist/lib/size.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +9 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/overlay/HoverCard.d.ts +13 -0
- package/dist/overlay/HoverCard.d.ts.map +1 -0
- package/dist/overlay/HoverCard.js +170 -0
- package/dist/overlay/HoverCard.js.map +1 -0
- package/dist/overlay/Modal.d.ts +17 -0
- package/dist/overlay/Modal.d.ts.map +1 -0
- package/dist/overlay/Modal.js +91 -0
- package/dist/overlay/Modal.js.map +1 -0
- package/dist/rpc/AcceptPicker.d.ts +52 -0
- package/dist/rpc/AcceptPicker.d.ts.map +1 -0
- package/dist/rpc/AcceptPicker.js +126 -0
- package/dist/rpc/AcceptPicker.js.map +1 -0
- package/dist/rpc/ApiExplorer.d.ts +11 -0
- package/dist/rpc/ApiExplorer.d.ts.map +1 -0
- package/dist/rpc/ApiExplorer.js +37 -0
- package/dist/rpc/ApiExplorer.js.map +1 -0
- package/dist/rpc/CommandForm.d.ts +15 -0
- package/dist/rpc/CommandForm.d.ts.map +1 -0
- package/dist/rpc/CommandForm.js +356 -0
- package/dist/rpc/CommandForm.js.map +1 -0
- package/dist/rpc/CommandOutput.d.ts +11 -0
- package/dist/rpc/CommandOutput.d.ts.map +1 -0
- package/dist/rpc/CommandOutput.js +195 -0
- package/dist/rpc/CommandOutput.js.map +1 -0
- package/dist/rpc/EndpointList.d.ts +18 -0
- package/dist/rpc/EndpointList.d.ts.map +1 -0
- package/dist/rpc/EndpointList.js +56 -0
- package/dist/rpc/EndpointList.js.map +1 -0
- package/dist/rpc/EntityExplorerApp.d.ts +15 -0
- package/dist/rpc/EntityExplorerApp.d.ts.map +1 -0
- package/dist/rpc/EntityExplorerApp.js +282 -0
- package/dist/rpc/EntityExplorerApp.js.map +1 -0
- package/dist/rpc/ExecutionResult.d.ts +14 -0
- package/dist/rpc/ExecutionResult.d.ts.map +1 -0
- package/dist/rpc/ExecutionResult.js +51 -0
- package/dist/rpc/ExecutionResult.js.map +1 -0
- package/dist/rpc/FilterForm.d.ts +22 -0
- package/dist/rpc/FilterForm.d.ts.map +1 -0
- package/dist/rpc/FilterForm.js +392 -0
- package/dist/rpc/FilterForm.js.map +1 -0
- package/dist/rpc/InlineError.d.ts +7 -0
- package/dist/rpc/InlineError.d.ts.map +1 -0
- package/dist/rpc/InlineError.js +54 -0
- package/dist/rpc/InlineError.js.map +1 -0
- package/dist/rpc/OperationActionDialog.d.ts +12 -0
- package/dist/rpc/OperationActionDialog.d.ts.map +1 -0
- package/dist/rpc/OperationActionDialog.js +105 -0
- package/dist/rpc/OperationActionDialog.js.map +1 -0
- package/dist/rpc/OperationCatalog.d.ts +21 -0
- package/dist/rpc/OperationCatalog.d.ts.map +1 -0
- package/dist/rpc/OperationCatalog.js +339 -0
- package/dist/rpc/OperationCatalog.js.map +1 -0
- package/dist/rpc/OperationCommandPage.d.ts +22 -0
- package/dist/rpc/OperationCommandPage.d.ts.map +1 -0
- package/dist/rpc/OperationCommandPage.js +484 -0
- package/dist/rpc/OperationCommandPage.js.map +1 -0
- package/dist/rpc/OperationEntityPage.d.ts +23 -0
- package/dist/rpc/OperationEntityPage.d.ts.map +1 -0
- package/dist/rpc/OperationEntityPage.js +218 -0
- package/dist/rpc/OperationEntityPage.js.map +1 -0
- package/dist/rpc/classify.d.ts +8 -0
- package/dist/rpc/classify.d.ts.map +1 -0
- package/dist/rpc/classify.js +76 -0
- package/dist/rpc/classify.js.map +1 -0
- package/dist/rpc/clickyMetadata.d.ts +12 -0
- package/dist/rpc/clickyMetadata.d.ts.map +1 -0
- package/dist/rpc/clickyMetadata.js +71 -0
- package/dist/rpc/clickyMetadata.js.map +1 -0
- package/dist/rpc/formMetadata.d.ts +27 -0
- package/dist/rpc/formMetadata.d.ts.map +1 -0
- package/dist/rpc/formMetadata.js +250 -0
- package/dist/rpc/formMetadata.js.map +1 -0
- package/dist/rpc/types.d.ts +109 -0
- package/dist/rpc/types.d.ts.map +1 -0
- package/dist/rpc/types.js +8 -0
- package/dist/rpc/types.js.map +1 -0
- package/dist/rpc/useOperations.d.ts +346 -0
- package/dist/rpc/useOperations.d.ts.map +1 -0
- package/dist/rpc/useOperations.js +31 -0
- package/dist/rpc/useOperations.js.map +1 -0
- package/dist/rpc.d.ts +14 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +37 -0
- package/dist/rpc.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/styles.d.ts +1 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +2 -0
- package/dist/styles.js.map +1 -0
- package/dist/tailwind-preset.d.ts +4 -0
- package/dist/tailwind-preset.d.ts.map +1 -0
- package/dist/tailwind-preset.js +69 -0
- package/dist/tailwind-preset.js.map +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +12 -0
- package/dist/utils.js.map +1 -0
- package/package.json +83 -40
- package/dist/index.d.mts +0 -834
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs +0 -2918
- package/dist/index.mjs.map +0 -1
- package/dist/tailwind-preset.d.mts +0 -7
- package/dist/tailwind-preset.d.mts.map +0 -1
- package/dist/tailwind-preset.mjs +0 -64
- package/dist/tailwind-preset.mjs.map +0 -1
- package/src/styles/tokens.css +0 -78
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useRef, useLayoutEffect, useEffect } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
4
|
+
import { cn } from "../lib/utils.js";
|
|
5
|
+
const GAP_PX = 6;
|
|
6
|
+
const HOVER_CLOSE_DELAY_MS = 120;
|
|
7
|
+
function HoverCard({
|
|
8
|
+
trigger,
|
|
9
|
+
children,
|
|
10
|
+
placement = "top",
|
|
11
|
+
delay = 0,
|
|
12
|
+
arrow = true,
|
|
13
|
+
className,
|
|
14
|
+
cardClassName
|
|
15
|
+
}) {
|
|
16
|
+
const [open, setOpen] = useState(false);
|
|
17
|
+
const [position, setPosition] = useState(null);
|
|
18
|
+
const triggerRef = useRef(null);
|
|
19
|
+
const cardRef = useRef(null);
|
|
20
|
+
const openTimerRef = useRef(null);
|
|
21
|
+
const closeTimerRef = useRef(null);
|
|
22
|
+
const cancelClose = () => {
|
|
23
|
+
if (closeTimerRef.current !== null) {
|
|
24
|
+
window.clearTimeout(closeTimerRef.current);
|
|
25
|
+
closeTimerRef.current = null;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
function onEnter() {
|
|
29
|
+
cancelClose();
|
|
30
|
+
if (delay > 0) {
|
|
31
|
+
if (openTimerRef.current !== null) window.clearTimeout(openTimerRef.current);
|
|
32
|
+
openTimerRef.current = window.setTimeout(() => setOpen(true), delay);
|
|
33
|
+
} else {
|
|
34
|
+
setOpen(true);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function onLeave() {
|
|
38
|
+
if (openTimerRef.current !== null) {
|
|
39
|
+
window.clearTimeout(openTimerRef.current);
|
|
40
|
+
openTimerRef.current = null;
|
|
41
|
+
}
|
|
42
|
+
cancelClose();
|
|
43
|
+
closeTimerRef.current = window.setTimeout(() => setOpen(false), HOVER_CLOSE_DELAY_MS);
|
|
44
|
+
}
|
|
45
|
+
useLayoutEffect(() => {
|
|
46
|
+
if (!open) return;
|
|
47
|
+
const update = () => {
|
|
48
|
+
const trigger2 = triggerRef.current;
|
|
49
|
+
const card2 = cardRef.current;
|
|
50
|
+
if (!trigger2 || !card2) return;
|
|
51
|
+
const t = trigger2.getBoundingClientRect();
|
|
52
|
+
const c = card2.getBoundingClientRect();
|
|
53
|
+
let top = 0;
|
|
54
|
+
let left = 0;
|
|
55
|
+
switch (placement) {
|
|
56
|
+
case "top":
|
|
57
|
+
top = t.top - c.height - GAP_PX;
|
|
58
|
+
left = t.left + t.width / 2 - c.width / 2;
|
|
59
|
+
break;
|
|
60
|
+
case "bottom":
|
|
61
|
+
top = t.bottom + GAP_PX;
|
|
62
|
+
left = t.left + t.width / 2 - c.width / 2;
|
|
63
|
+
break;
|
|
64
|
+
case "left":
|
|
65
|
+
top = t.top + t.height / 2 - c.height / 2;
|
|
66
|
+
left = t.left - c.width - GAP_PX;
|
|
67
|
+
break;
|
|
68
|
+
case "right":
|
|
69
|
+
top = t.top + t.height / 2 - c.height / 2;
|
|
70
|
+
left = t.right + GAP_PX;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
const margin = 4;
|
|
74
|
+
left = Math.min(Math.max(margin, left), window.innerWidth - c.width - margin);
|
|
75
|
+
top = Math.min(Math.max(margin, top), window.innerHeight - c.height - margin);
|
|
76
|
+
setPosition({ top, left });
|
|
77
|
+
};
|
|
78
|
+
update();
|
|
79
|
+
window.addEventListener("scroll", update, true);
|
|
80
|
+
window.addEventListener("resize", update);
|
|
81
|
+
return () => {
|
|
82
|
+
window.removeEventListener("scroll", update, true);
|
|
83
|
+
window.removeEventListener("resize", update);
|
|
84
|
+
};
|
|
85
|
+
}, [open, placement, children]);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
return () => {
|
|
88
|
+
if (openTimerRef.current !== null) window.clearTimeout(openTimerRef.current);
|
|
89
|
+
if (closeTimerRef.current !== null) window.clearTimeout(closeTimerRef.current);
|
|
90
|
+
};
|
|
91
|
+
}, []);
|
|
92
|
+
const card = open && typeof document !== "undefined" ? createPortal(
|
|
93
|
+
/* @__PURE__ */ jsxs(
|
|
94
|
+
"div",
|
|
95
|
+
{
|
|
96
|
+
ref: cardRef,
|
|
97
|
+
role: "tooltip",
|
|
98
|
+
onMouseEnter: cancelClose,
|
|
99
|
+
onMouseLeave: onLeave,
|
|
100
|
+
style: position ? { position: "fixed", top: position.top, left: position.left } : { position: "fixed", top: -9999, left: -9999, visibility: "hidden" },
|
|
101
|
+
className: cn(
|
|
102
|
+
"z-[9999] rounded-md border border-border bg-background px-2.5 py-1.5 text-[11px] shadow-lg",
|
|
103
|
+
"whitespace-nowrap",
|
|
104
|
+
cardClassName
|
|
105
|
+
),
|
|
106
|
+
children: [
|
|
107
|
+
children,
|
|
108
|
+
arrow && position && /* @__PURE__ */ jsx(Arrow, { placement })
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
),
|
|
112
|
+
document.body
|
|
113
|
+
) : null;
|
|
114
|
+
return /* @__PURE__ */ jsxs(
|
|
115
|
+
"span",
|
|
116
|
+
{
|
|
117
|
+
ref: triggerRef,
|
|
118
|
+
className: cn("relative inline-flex items-center", className),
|
|
119
|
+
onMouseEnter: onEnter,
|
|
120
|
+
onMouseLeave: onLeave,
|
|
121
|
+
onFocus: onEnter,
|
|
122
|
+
onBlur: onLeave,
|
|
123
|
+
children: [
|
|
124
|
+
trigger,
|
|
125
|
+
card
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
function Arrow({ placement }) {
|
|
131
|
+
const base = "absolute h-1.5 w-1.5 rotate-45 border bg-background border-border";
|
|
132
|
+
switch (placement) {
|
|
133
|
+
case "top":
|
|
134
|
+
return /* @__PURE__ */ jsx(
|
|
135
|
+
"span",
|
|
136
|
+
{
|
|
137
|
+
"aria-hidden": true,
|
|
138
|
+
className: cn(base, "left-1/2 -translate-x-1/2 -bottom-0.5 border-l-0 border-t-0")
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
case "bottom":
|
|
142
|
+
return /* @__PURE__ */ jsx(
|
|
143
|
+
"span",
|
|
144
|
+
{
|
|
145
|
+
"aria-hidden": true,
|
|
146
|
+
className: cn(base, "left-1/2 -translate-x-1/2 -top-0.5 border-r-0 border-b-0")
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
case "left":
|
|
150
|
+
return /* @__PURE__ */ jsx(
|
|
151
|
+
"span",
|
|
152
|
+
{
|
|
153
|
+
"aria-hidden": true,
|
|
154
|
+
className: cn(base, "top-1/2 -translate-y-1/2 -right-0.5 border-l-0 border-b-0")
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
case "right":
|
|
158
|
+
return /* @__PURE__ */ jsx(
|
|
159
|
+
"span",
|
|
160
|
+
{
|
|
161
|
+
"aria-hidden": true,
|
|
162
|
+
className: cn(base, "top-1/2 -translate-y-1/2 -left-0.5 border-r-0 border-t-0")
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
export {
|
|
168
|
+
HoverCard
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=HoverCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HoverCard.js","sources":["../../src/overlay/HoverCard.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\n\nexport type HoverCardPlacement = \"top\" | \"bottom\" | \"left\" | \"right\";\n\nexport type HoverCardProps = {\n trigger: ReactNode;\n children: ReactNode;\n placement?: HoverCardPlacement;\n delay?: number;\n arrow?: boolean;\n className?: string;\n cardClassName?: string;\n};\n\nconst GAP_PX = 6;\n\ntype Position = { top: number; left: number };\n\n// Grace period that lets the cursor cross the gap from the trigger to the\n// portaled card without the card disappearing.\nconst HOVER_CLOSE_DELAY_MS = 120;\n\nexport function HoverCard({\n trigger,\n children,\n placement = \"top\",\n delay = 0,\n arrow = true,\n className,\n cardClassName,\n}: HoverCardProps) {\n const [open, setOpen] = useState(false);\n const [position, setPosition] = useState<Position | null>(null);\n const triggerRef = useRef<HTMLSpanElement | null>(null);\n const cardRef = useRef<HTMLDivElement | null>(null);\n const openTimerRef = useRef<number | null>(null);\n const closeTimerRef = useRef<number | null>(null);\n\n const cancelClose = () => {\n if (closeTimerRef.current !== null) {\n window.clearTimeout(closeTimerRef.current);\n closeTimerRef.current = null;\n }\n };\n\n function onEnter() {\n cancelClose();\n if (delay > 0) {\n if (openTimerRef.current !== null) window.clearTimeout(openTimerRef.current);\n openTimerRef.current = window.setTimeout(() => setOpen(true), delay);\n } else {\n setOpen(true);\n }\n }\n function onLeave() {\n if (openTimerRef.current !== null) {\n window.clearTimeout(openTimerRef.current);\n openTimerRef.current = null;\n }\n cancelClose();\n closeTimerRef.current = window.setTimeout(() => setOpen(false), HOVER_CLOSE_DELAY_MS);\n }\n\n // Recompute position whenever the card opens or the viewport scrolls/resizes\n // while it's open. We position via fixed coordinates so the card escapes\n // every overflow-hidden / transform ancestor — important when the trigger\n // sits inside a table row, dropdown, or modal that would otherwise clip it.\n useLayoutEffect(() => {\n if (!open) return;\n const update = () => {\n const trigger = triggerRef.current;\n const card = cardRef.current;\n if (!trigger || !card) return;\n const t = trigger.getBoundingClientRect();\n const c = card.getBoundingClientRect();\n let top = 0;\n let left = 0;\n switch (placement) {\n case \"top\":\n top = t.top - c.height - GAP_PX;\n left = t.left + t.width / 2 - c.width / 2;\n break;\n case \"bottom\":\n top = t.bottom + GAP_PX;\n left = t.left + t.width / 2 - c.width / 2;\n break;\n case \"left\":\n top = t.top + t.height / 2 - c.height / 2;\n left = t.left - c.width - GAP_PX;\n break;\n case \"right\":\n top = t.top + t.height / 2 - c.height / 2;\n left = t.right + GAP_PX;\n break;\n }\n // Clamp to viewport so cards near the edge don't overflow off-screen.\n const margin = 4;\n left = Math.min(Math.max(margin, left), window.innerWidth - c.width - margin);\n top = Math.min(Math.max(margin, top), window.innerHeight - c.height - margin);\n setPosition({ top, left });\n };\n update();\n window.addEventListener(\"scroll\", update, true);\n window.addEventListener(\"resize\", update);\n return () => {\n window.removeEventListener(\"scroll\", update, true);\n window.removeEventListener(\"resize\", update);\n };\n }, [open, placement, children]);\n\n useEffect(() => {\n return () => {\n if (openTimerRef.current !== null) window.clearTimeout(openTimerRef.current);\n if (closeTimerRef.current !== null) window.clearTimeout(closeTimerRef.current);\n };\n }, []);\n\n const card =\n open && typeof document !== \"undefined\"\n ? createPortal(\n <div\n ref={cardRef}\n role=\"tooltip\"\n onMouseEnter={cancelClose}\n onMouseLeave={onLeave}\n style={\n position\n ? { position: \"fixed\", top: position.top, left: position.left }\n : { position: \"fixed\", top: -9999, left: -9999, visibility: \"hidden\" }\n }\n className={cn(\n \"z-[9999] rounded-md border border-border bg-background px-2.5 py-1.5 text-[11px] shadow-lg\",\n \"whitespace-nowrap\",\n cardClassName,\n )}\n >\n {children}\n {arrow && position && <Arrow placement={placement} />}\n </div>,\n document.body,\n )\n : null;\n\n return (\n <span\n ref={triggerRef}\n className={cn(\"relative inline-flex items-center\", className)}\n onMouseEnter={onEnter}\n onMouseLeave={onLeave}\n onFocus={onEnter}\n onBlur={onLeave}\n >\n {trigger}\n {card}\n </span>\n );\n}\n\nfunction Arrow({ placement }: { placement: HoverCardPlacement }) {\n // The arrow is a small rotated square clipped to look like a notch on the\n // card edge that points back at the trigger. Drawn relative to the card.\n const base = \"absolute h-1.5 w-1.5 rotate-45 border bg-background border-border\";\n switch (placement) {\n case \"top\":\n return (\n <span\n aria-hidden\n className={cn(base, \"left-1/2 -translate-x-1/2 -bottom-0.5 border-l-0 border-t-0\")}\n />\n );\n case \"bottom\":\n return (\n <span\n aria-hidden\n className={cn(base, \"left-1/2 -translate-x-1/2 -top-0.5 border-r-0 border-b-0\")}\n />\n );\n case \"left\":\n return (\n <span\n aria-hidden\n className={cn(base, \"top-1/2 -translate-y-1/2 -right-0.5 border-l-0 border-b-0\")}\n />\n );\n case \"right\":\n return (\n <span\n aria-hidden\n className={cn(base, \"top-1/2 -translate-y-1/2 -left-0.5 border-r-0 border-t-0\")}\n />\n );\n }\n}\n"],"names":["trigger","card"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export type ModalSize = "sm" | "md" | "lg" | "xl" | "full";
|
|
3
|
+
export type ModalProps = {
|
|
4
|
+
open: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
title?: ReactNode;
|
|
7
|
+
size?: ModalSize;
|
|
8
|
+
closeOnBackdrop?: boolean;
|
|
9
|
+
closeOnEsc?: boolean;
|
|
10
|
+
hideClose?: boolean;
|
|
11
|
+
className?: string;
|
|
12
|
+
headerSlot?: ReactNode;
|
|
13
|
+
footer?: ReactNode;
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
};
|
|
16
|
+
export declare function Modal({ open, onClose, title, size, closeOnBackdrop, closeOnEsc, hideClose, className, headerSlot, footer, children, }: ModalProps): import("react/jsx-runtime").JSX.Element | null;
|
|
17
|
+
//# sourceMappingURL=Modal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/overlay/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI1D,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAE3D,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAUF,wBAAgB,KAAK,CAAC,EACpB,IAAI,EACJ,OAAO,EACP,KAAK,EACL,IAAW,EACX,eAAsB,EACtB,UAAiB,EACjB,SAAiB,EACjB,SAAS,EACT,UAAU,EACV,MAAM,EACN,QAAQ,GACT,EAAE,UAAU,kDA6DZ"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useEffect } from "react";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
import { Icon } from "../data/Icon.js";
|
|
5
|
+
const sizeClass = {
|
|
6
|
+
sm: "max-w-sm max-h-[90vh]",
|
|
7
|
+
md: "max-w-md max-h-[90vh]",
|
|
8
|
+
lg: "max-w-2xl max-h-[90vh]",
|
|
9
|
+
xl: "max-w-4xl max-h-[90vh]",
|
|
10
|
+
full: "max-w-[95vw] max-h-[95vh]"
|
|
11
|
+
};
|
|
12
|
+
function Modal({
|
|
13
|
+
open,
|
|
14
|
+
onClose,
|
|
15
|
+
title,
|
|
16
|
+
size = "md",
|
|
17
|
+
closeOnBackdrop = true,
|
|
18
|
+
closeOnEsc = true,
|
|
19
|
+
hideClose = false,
|
|
20
|
+
className,
|
|
21
|
+
headerSlot,
|
|
22
|
+
footer,
|
|
23
|
+
children
|
|
24
|
+
}) {
|
|
25
|
+
const dialogRef = useRef(null);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (!open || !closeOnEsc) return;
|
|
28
|
+
const onKey = (e) => {
|
|
29
|
+
if (e.key === "Escape") onClose();
|
|
30
|
+
};
|
|
31
|
+
document.addEventListener("keydown", onKey);
|
|
32
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
33
|
+
}, [open, closeOnEsc, onClose]);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
var _a;
|
|
36
|
+
if (!open) return;
|
|
37
|
+
const prev = document.activeElement;
|
|
38
|
+
(_a = dialogRef.current) == null ? void 0 : _a.focus();
|
|
39
|
+
return () => {
|
|
40
|
+
var _a2;
|
|
41
|
+
return (_a2 = prev == null ? void 0 : prev.focus) == null ? void 0 : _a2.call(prev);
|
|
42
|
+
};
|
|
43
|
+
}, [open]);
|
|
44
|
+
if (!open) return null;
|
|
45
|
+
return /* @__PURE__ */ jsx(
|
|
46
|
+
"div",
|
|
47
|
+
{
|
|
48
|
+
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/40",
|
|
49
|
+
onClick: closeOnBackdrop ? onClose : void 0,
|
|
50
|
+
role: "presentation",
|
|
51
|
+
children: /* @__PURE__ */ jsxs(
|
|
52
|
+
"div",
|
|
53
|
+
{
|
|
54
|
+
ref: dialogRef,
|
|
55
|
+
tabIndex: -1,
|
|
56
|
+
role: "dialog",
|
|
57
|
+
"aria-modal": "true",
|
|
58
|
+
"aria-label": typeof title === "string" ? title : void 0,
|
|
59
|
+
className: cn(
|
|
60
|
+
"relative bg-background border border-border rounded-lg shadow-xl w-full flex flex-col",
|
|
61
|
+
sizeClass[size],
|
|
62
|
+
className
|
|
63
|
+
),
|
|
64
|
+
onClick: (e) => e.stopPropagation(),
|
|
65
|
+
children: [
|
|
66
|
+
(title || headerSlot || !hideClose) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-density-2 px-density-4 py-density-3 border-b border-border", children: [
|
|
67
|
+
title && /* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold flex-1", children: title }),
|
|
68
|
+
headerSlot,
|
|
69
|
+
!hideClose && /* @__PURE__ */ jsx(
|
|
70
|
+
"button",
|
|
71
|
+
{
|
|
72
|
+
type: "button",
|
|
73
|
+
onClick: onClose,
|
|
74
|
+
"aria-label": "Close",
|
|
75
|
+
className: "text-muted-foreground hover:text-foreground",
|
|
76
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "codicon:close" })
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
] }),
|
|
80
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto px-density-4 py-density-3", children }),
|
|
81
|
+
footer && /* @__PURE__ */ jsx("div", { className: "px-density-4 py-density-3 border-t border-border", children: footer })
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
export {
|
|
89
|
+
Modal
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=Modal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Modal.js","sources":["../../src/overlay/Modal.tsx"],"sourcesContent":["import { useEffect, useRef, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\n\nexport type ModalSize = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\";\n\nexport type ModalProps = {\n open: boolean;\n onClose: () => void;\n title?: ReactNode;\n size?: ModalSize;\n closeOnBackdrop?: boolean;\n closeOnEsc?: boolean;\n hideClose?: boolean;\n className?: string;\n headerSlot?: ReactNode;\n footer?: ReactNode;\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\nexport function Modal({\n open,\n onClose,\n title,\n size = \"md\",\n closeOnBackdrop = true,\n closeOnEsc = true,\n hideClose = false,\n className,\n headerSlot,\n footer,\n children,\n}: ModalProps) {\n const dialogRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open || !closeOnEsc) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, closeOnEsc, 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=\"fixed inset-0 z-50 flex items-center justify-center bg-black/40\"\n onClick={closeOnBackdrop ? onClose : 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 sizeClass[size],\n className,\n )}\n onClick={(e) => e.stopPropagation()}\n >\n {(title || headerSlot || !hideClose) && (\n <div className=\"flex items-center gap-density-2 px-density-4 py-density-3 border-b border-border\">\n {title && <h2 className=\"text-sm font-semibold flex-1\">{title}</h2>}\n {headerSlot}\n {!hideClose && (\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close\"\n className=\"text-muted-foreground hover:text-foreground\"\n >\n <Icon name=\"codicon:close\" />\n </button>\n )}\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 </div>\n </div>\n );\n}\n"],"names":["_a"],"mappings":";;;;AAoBA,MAAM,YAAuC;AAAA,EAC3C,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,MAAM;AACR;AAEO,SAAS,MAAM;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,kBAAkB;AAAA,EAClB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAe;AACb,QAAM,YAAY,OAAuB,IAAI;AAE7C,YAAU,MAAM;AACd,QAAI,CAAC,QAAQ,CAAC,WAAY;AAC1B,UAAM,QAAQ,CAAC,MAAqB;AAClC,UAAI,EAAE,QAAQ,SAAU,SAAA;AAAA,IAC1B;AACA,aAAS,iBAAiB,WAAW,KAAK;AAC1C,WAAO,MAAM,SAAS,oBAAoB,WAAW,KAAK;AAAA,EAC5D,GAAG,CAAC,MAAM,YAAY,OAAO,CAAC;AAE9B,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,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,SAAS,kBAAkB,UAAU;AAAA,MACrC,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,UAAU,IAAI;AAAA,YACd;AAAA,UAAA;AAAA,UAEF,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,UAEhB,UAAA;AAAA,aAAA,SAAS,cAAc,CAAC,cACxB,qBAAC,OAAA,EAAI,WAAU,oFACZ,UAAA;AAAA,cAAA,SAAS,oBAAC,MAAA,EAAG,WAAU,gCAAgC,UAAA,OAAM;AAAA,cAC7D;AAAA,cACA,CAAC,aACA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS;AAAA,kBACT,cAAW;AAAA,kBACX,WAAU;AAAA,kBAEV,UAAA,oBAAC,MAAA,EAAK,MAAK,gBAAA,CAAgB;AAAA,gBAAA;AAAA,cAAA;AAAA,YAC7B,GAEJ;AAAA,YAEF,oBAAC,OAAA,EAAI,WAAU,kDAAkD,SAAA,CAAS;AAAA,YACzE,UAAU,oBAAC,OAAA,EAAI,WAAU,oDAAoD,UAAA,OAAA,CAAO;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IACvF;AAAA,EAAA;AAGN;"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export declare const ACCEPT_OPTIONS: readonly [{
|
|
2
|
+
readonly value: "application/json";
|
|
3
|
+
readonly label: "JSON";
|
|
4
|
+
}, {
|
|
5
|
+
readonly value: "application/clicky+json";
|
|
6
|
+
readonly label: "Clicky";
|
|
7
|
+
}, {
|
|
8
|
+
readonly value: "text/markdown";
|
|
9
|
+
readonly label: "Markdown";
|
|
10
|
+
}, {
|
|
11
|
+
readonly value: "text/html";
|
|
12
|
+
readonly label: "HTML";
|
|
13
|
+
}, {
|
|
14
|
+
readonly value: "application/x-yaml";
|
|
15
|
+
readonly label: "YAML";
|
|
16
|
+
}, {
|
|
17
|
+
readonly value: "text/csv";
|
|
18
|
+
readonly label: "CSV";
|
|
19
|
+
}, {
|
|
20
|
+
readonly value: "application/pdf";
|
|
21
|
+
readonly label: "PDF";
|
|
22
|
+
}, {
|
|
23
|
+
readonly value: "text/plain";
|
|
24
|
+
readonly label: "Pretty";
|
|
25
|
+
}];
|
|
26
|
+
export declare const VIEW_OPTIONS: readonly [{
|
|
27
|
+
readonly value: "application/json";
|
|
28
|
+
readonly label: "JSON";
|
|
29
|
+
}, {
|
|
30
|
+
readonly value: "application/clicky+json";
|
|
31
|
+
readonly label: "Clicky";
|
|
32
|
+
}, {
|
|
33
|
+
readonly value: "application/pdf";
|
|
34
|
+
readonly label: "PDF";
|
|
35
|
+
}];
|
|
36
|
+
export type AcceptOption = {
|
|
37
|
+
value: string;
|
|
38
|
+
label: string;
|
|
39
|
+
};
|
|
40
|
+
export type AcceptValue = (typeof ACCEPT_OPTIONS)[number]["value"];
|
|
41
|
+
export type OperationPreviewMode = "hidden" | "curl" | "cli";
|
|
42
|
+
export type AcceptPickerProps = {
|
|
43
|
+
value: string;
|
|
44
|
+
onChange: (value: string) => void;
|
|
45
|
+
size?: "sm" | "md";
|
|
46
|
+
options?: readonly AcceptOption[];
|
|
47
|
+
previewMode?: OperationPreviewMode;
|
|
48
|
+
onPreviewModeChange?: (mode: OperationPreviewMode) => void;
|
|
49
|
+
className?: string;
|
|
50
|
+
};
|
|
51
|
+
export declare function AcceptPicker({ value, onChange, size, options, previewMode, onPreviewModeChange, className, }: AcceptPickerProps): import("react/jsx-runtime").JSX.Element;
|
|
52
|
+
//# sourceMappingURL=AcceptPicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AcceptPicker.d.ts","sourceRoot":"","sources":["../../src/rpc/AcceptPicker.tsx"],"names":[],"mappings":"AAKA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;EASjB,CAAC;AAEX,eAAO,MAAM,YAAY;;;;;;;;;EAIf,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAC5D,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;AACnE,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;AAE7D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAClC,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAQF,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,IAAW,EACX,OAAwB,EACxB,WAAsB,EACtB,mBAAmB,EACnB,SAAS,GACV,EAAE,iBAAiB,2CAyFnB"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState, useEffect } from "react";
|
|
3
|
+
import { Button } from "../components/button.js";
|
|
4
|
+
import { Icon } from "../data/Icon.js";
|
|
5
|
+
import { cn } from "../lib/utils.js";
|
|
6
|
+
const ACCEPT_OPTIONS = [
|
|
7
|
+
{ value: "application/json", label: "JSON" },
|
|
8
|
+
{ value: "application/clicky+json", label: "Clicky" },
|
|
9
|
+
{ value: "text/markdown", label: "Markdown" },
|
|
10
|
+
{ value: "text/html", label: "HTML" },
|
|
11
|
+
{ value: "application/x-yaml", label: "YAML" },
|
|
12
|
+
{ value: "text/csv", label: "CSV" },
|
|
13
|
+
{ value: "application/pdf", label: "PDF" },
|
|
14
|
+
{ value: "text/plain", label: "Pretty" }
|
|
15
|
+
];
|
|
16
|
+
const VIEW_OPTIONS = [
|
|
17
|
+
{ value: "application/json", label: "JSON" },
|
|
18
|
+
{ value: "application/clicky+json", label: "Clicky" },
|
|
19
|
+
{ value: "application/pdf", label: "PDF" }
|
|
20
|
+
];
|
|
21
|
+
const PREVIEW_OPTIONS = [
|
|
22
|
+
{ value: "curl", label: "Show cURL preview" },
|
|
23
|
+
{ value: "cli", label: "Show CLI preview" },
|
|
24
|
+
{ value: "hidden", label: "Hide preview" }
|
|
25
|
+
];
|
|
26
|
+
function AcceptPicker({
|
|
27
|
+
value,
|
|
28
|
+
onChange,
|
|
29
|
+
size = "md",
|
|
30
|
+
options = ACCEPT_OPTIONS,
|
|
31
|
+
previewMode = "hidden",
|
|
32
|
+
onPreviewModeChange,
|
|
33
|
+
className
|
|
34
|
+
}) {
|
|
35
|
+
const rootRef = useRef(null);
|
|
36
|
+
const [open, setOpen] = useState(false);
|
|
37
|
+
const pad = size === "sm" ? "px-2 py-0.5" : "px-2.5 py-1";
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!open) return;
|
|
40
|
+
const onPointerDown = (event) => {
|
|
41
|
+
var _a;
|
|
42
|
+
if (!((_a = rootRef.current) == null ? void 0 : _a.contains(event.target))) {
|
|
43
|
+
setOpen(false);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const onKeyDown = (event) => {
|
|
47
|
+
if (event.key === "Escape") setOpen(false);
|
|
48
|
+
};
|
|
49
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
50
|
+
document.addEventListener("keydown", onKeyDown);
|
|
51
|
+
return () => {
|
|
52
|
+
document.removeEventListener("pointerdown", onPointerDown);
|
|
53
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
54
|
+
};
|
|
55
|
+
}, [open]);
|
|
56
|
+
return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: cn("relative flex flex-wrap gap-1", className), children: [
|
|
57
|
+
options.map((opt) => /* @__PURE__ */ jsx(
|
|
58
|
+
"button",
|
|
59
|
+
{
|
|
60
|
+
type: "button",
|
|
61
|
+
onClick: () => onChange(opt.value),
|
|
62
|
+
className: cn(
|
|
63
|
+
"rounded-md border text-xs transition-colors",
|
|
64
|
+
pad,
|
|
65
|
+
value === opt.value ? "border-emerald-500 bg-emerald-50 font-medium text-emerald-700 dark:border-emerald-600 dark:bg-emerald-950/30 dark:text-emerald-400" : "text-muted-foreground hover:border-foreground/20 hover:text-foreground"
|
|
66
|
+
),
|
|
67
|
+
children: opt.label
|
|
68
|
+
},
|
|
69
|
+
opt.value
|
|
70
|
+
)),
|
|
71
|
+
onPreviewModeChange && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
72
|
+
/* @__PURE__ */ jsx(
|
|
73
|
+
Button,
|
|
74
|
+
{
|
|
75
|
+
type: "button",
|
|
76
|
+
variant: "outline",
|
|
77
|
+
size: "sm",
|
|
78
|
+
"aria-label": "Open preview menu",
|
|
79
|
+
"aria-haspopup": "menu",
|
|
80
|
+
"aria-expanded": open,
|
|
81
|
+
className: cn("h-auto", pad),
|
|
82
|
+
onClick: () => setOpen((current) => !current),
|
|
83
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "codicon:ellipsis" })
|
|
84
|
+
}
|
|
85
|
+
),
|
|
86
|
+
open && /* @__PURE__ */ jsx(
|
|
87
|
+
"div",
|
|
88
|
+
{
|
|
89
|
+
role: "menu",
|
|
90
|
+
"aria-label": "Preview options",
|
|
91
|
+
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",
|
|
92
|
+
children: PREVIEW_OPTIONS.map((option) => {
|
|
93
|
+
const active = option.value === previewMode;
|
|
94
|
+
return /* @__PURE__ */ jsxs(
|
|
95
|
+
"button",
|
|
96
|
+
{
|
|
97
|
+
type: "button",
|
|
98
|
+
role: "menuitemradio",
|
|
99
|
+
"aria-checked": active,
|
|
100
|
+
className: cn(
|
|
101
|
+
"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm transition-colors",
|
|
102
|
+
"hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none"
|
|
103
|
+
),
|
|
104
|
+
onClick: () => {
|
|
105
|
+
onPreviewModeChange(option.value);
|
|
106
|
+
setOpen(false);
|
|
107
|
+
},
|
|
108
|
+
children: [
|
|
109
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1", children: option.label }),
|
|
110
|
+
active ? /* @__PURE__ */ jsx(Icon, { name: "ph:check", className: "shrink-0" }) : null
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
option.value
|
|
114
|
+
);
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
] })
|
|
119
|
+
] });
|
|
120
|
+
}
|
|
121
|
+
export {
|
|
122
|
+
ACCEPT_OPTIONS,
|
|
123
|
+
AcceptPicker,
|
|
124
|
+
VIEW_OPTIONS
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=AcceptPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AcceptPicker.js","sources":["../../src/rpc/AcceptPicker.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { Icon } from \"../data/Icon\";\nimport { cn } from \"../lib/utils\";\n\nexport const ACCEPT_OPTIONS = [\n { value: \"application/json\", label: \"JSON\" },\n { value: \"application/clicky+json\", label: \"Clicky\" },\n { value: \"text/markdown\", label: \"Markdown\" },\n { value: \"text/html\", label: \"HTML\" },\n { value: \"application/x-yaml\", label: \"YAML\" },\n { value: \"text/csv\", label: \"CSV\" },\n { value: \"application/pdf\", label: \"PDF\" },\n { value: \"text/plain\", label: \"Pretty\" },\n] as const;\n\nexport const VIEW_OPTIONS = [\n { value: \"application/json\", label: \"JSON\" },\n { value: \"application/clicky+json\", label: \"Clicky\" },\n { value: \"application/pdf\", label: \"PDF\" },\n] as const;\n\nexport type AcceptOption = { value: string; label: string };\nexport type AcceptValue = (typeof ACCEPT_OPTIONS)[number][\"value\"];\nexport type OperationPreviewMode = \"hidden\" | \"curl\" | \"cli\";\n\nexport type AcceptPickerProps = {\n value: string;\n onChange: (value: string) => void;\n size?: \"sm\" | \"md\";\n options?: readonly AcceptOption[];\n previewMode?: OperationPreviewMode;\n onPreviewModeChange?: (mode: OperationPreviewMode) => void;\n className?: string;\n};\n\nconst PREVIEW_OPTIONS: Array<{ value: OperationPreviewMode; label: string }> = [\n { value: \"curl\", label: \"Show cURL preview\" },\n { value: \"cli\", label: \"Show CLI preview\" },\n { value: \"hidden\", label: \"Hide preview\" },\n];\n\nexport function AcceptPicker({\n value,\n onChange,\n size = \"md\",\n options = ACCEPT_OPTIONS,\n previewMode = \"hidden\",\n onPreviewModeChange,\n className,\n}: AcceptPickerProps) {\n const rootRef = useRef<HTMLDivElement>(null);\n const [open, setOpen] = useState(false);\n const pad = size === \"sm\" ? \"px-2 py-0.5\" : \"px-2.5 py-1\";\n\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (event: PointerEvent) => {\n if (!rootRef.current?.contains(event.target as Node)) {\n setOpen(false);\n }\n };\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(\"pointerdown\", onPointerDown);\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"pointerdown\", onPointerDown);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [open]);\n\n return (\n <div ref={rootRef} className={cn(\"relative flex flex-wrap gap-1\", className)}>\n {options.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n onClick={() => onChange(opt.value)}\n className={cn(\n \"rounded-md border text-xs transition-colors\",\n pad,\n value === opt.value\n ? \"border-emerald-500 bg-emerald-50 font-medium text-emerald-700 dark:border-emerald-600 dark:bg-emerald-950/30 dark:text-emerald-400\"\n : \"text-muted-foreground hover:border-foreground/20 hover:text-foreground\",\n )}\n >\n {opt.label}\n </button>\n ))}\n {onPreviewModeChange && (\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n aria-label=\"Open preview menu\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n className={cn(\"h-auto\", pad)}\n onClick={() => setOpen((current) => !current)}\n >\n <Icon name=\"codicon:ellipsis\" />\n </Button>\n {open && (\n <div\n role=\"menu\"\n aria-label=\"Preview options\"\n 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\"\n >\n {PREVIEW_OPTIONS.map((option) => {\n const active = option.value === previewMode;\n return (\n <button\n key={option.value}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n className={cn(\n \"flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm transition-colors\",\n \"hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none\",\n )}\n onClick={() => {\n onPreviewModeChange(option.value);\n setOpen(false);\n }}\n >\n <span className=\"min-w-0 flex-1\">{option.label}</span>\n {active ? <Icon name=\"ph:check\" className=\"shrink-0\" /> : null}\n </button>\n );\n })}\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { AnyApiReferenceConfiguration } from '@scalar/api-reference-react';
|
|
3
|
+
export declare const DEFAULT_OPENAPI_URL = "/api/openapi.json";
|
|
4
|
+
export type ApiExplorerProps = {
|
|
5
|
+
openApiUrl?: string;
|
|
6
|
+
configuration?: AnyApiReferenceConfiguration;
|
|
7
|
+
className?: string;
|
|
8
|
+
style?: CSSProperties;
|
|
9
|
+
};
|
|
10
|
+
export declare function ApiExplorer({ openApiUrl, configuration, className, style, }: ApiExplorerProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=ApiExplorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiExplorer.d.ts","sourceRoot":"","sources":["../../src/rpc/ApiExplorer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAGhF,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAQvD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,4BAA4B,CAAC;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAC1B,UAAgC,EAChC,aAAa,EACb,SAAS,EACT,KAAK,GACN,EAAE,gBAAgB,2CAoBlB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, Suspense, lazy } from "react";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
const DEFAULT_OPENAPI_URL = "/api/openapi.json";
|
|
5
|
+
const ScalarApiReference = lazy(async () => {
|
|
6
|
+
await import("@scalar/api-reference-react/style.css");
|
|
7
|
+
const mod = await import("@scalar/api-reference-react");
|
|
8
|
+
return { default: mod.ApiReferenceReact };
|
|
9
|
+
});
|
|
10
|
+
function ApiExplorer({
|
|
11
|
+
openApiUrl = DEFAULT_OPENAPI_URL,
|
|
12
|
+
configuration,
|
|
13
|
+
className,
|
|
14
|
+
style
|
|
15
|
+
}) {
|
|
16
|
+
const scalarConfiguration = useMemo(() => {
|
|
17
|
+
if (configuration == null) {
|
|
18
|
+
return { url: openApiUrl };
|
|
19
|
+
}
|
|
20
|
+
if (Array.isArray(configuration)) {
|
|
21
|
+
return configuration;
|
|
22
|
+
}
|
|
23
|
+
return { url: openApiUrl, ...configuration };
|
|
24
|
+
}, [configuration, openApiUrl]);
|
|
25
|
+
return /* @__PURE__ */ jsx("div", { className: cn("h-full min-h-0 overflow-auto", className), style, children: /* @__PURE__ */ jsx(
|
|
26
|
+
Suspense,
|
|
27
|
+
{
|
|
28
|
+
fallback: /* @__PURE__ */ jsx("div", { className: "p-4 text-sm text-muted-foreground", children: "Loading API explorer..." }),
|
|
29
|
+
children: /* @__PURE__ */ jsx(ScalarApiReference, { configuration: scalarConfiguration })
|
|
30
|
+
}
|
|
31
|
+
) });
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
ApiExplorer,
|
|
35
|
+
DEFAULT_OPENAPI_URL
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=ApiExplorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiExplorer.js","sources":["../../src/rpc/ApiExplorer.tsx"],"sourcesContent":["import { lazy, Suspense, useMemo, type CSSProperties } from \"react\";\nimport type { AnyApiReferenceConfiguration } from \"@scalar/api-reference-react\";\nimport { cn } from \"../lib/utils\";\n\nexport const DEFAULT_OPENAPI_URL = \"/api/openapi.json\";\n\nconst ScalarApiReference = lazy(async () => {\n await import(\"@scalar/api-reference-react/style.css\");\n const mod = await import(\"@scalar/api-reference-react\");\n return { default: mod.ApiReferenceReact };\n});\n\nexport type ApiExplorerProps = {\n openApiUrl?: string;\n configuration?: AnyApiReferenceConfiguration;\n className?: string;\n style?: CSSProperties;\n};\n\nexport function ApiExplorer({\n openApiUrl = DEFAULT_OPENAPI_URL,\n configuration,\n className,\n style,\n}: ApiExplorerProps) {\n const scalarConfiguration = useMemo<AnyApiReferenceConfiguration>(() => {\n if (configuration == null) {\n return { url: openApiUrl };\n }\n if (Array.isArray(configuration)) {\n return configuration;\n }\n return { url: openApiUrl, ...configuration };\n }, [configuration, openApiUrl]);\n\n return (\n <div className={cn(\"h-full min-h-0 overflow-auto\", className)} style={style}>\n <Suspense\n fallback={<div className=\"p-4 text-sm text-muted-foreground\">Loading API explorer...</div>}\n >\n <ScalarApiReference configuration={scalarConfiguration} />\n </Suspense>\n </div>\n );\n}\n"],"names":[],"mappings":";;;AAIO,MAAM,sBAAsB;AAEnC,MAAM,qBAAqB,KAAK,YAAY;AAC1C,QAAM,OAAO,uCAAuC;AACpD,QAAM,MAAM,MAAM,OAAO,6BAA6B;AACtD,SAAO,EAAE,SAAS,IAAI,kBAAA;AACxB,CAAC;AASM,SAAS,YAAY;AAAA,EAC1B,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,sBAAsB,QAAsC,MAAM;AACtE,QAAI,iBAAiB,MAAM;AACzB,aAAO,EAAE,KAAK,WAAA;AAAA,IAChB;AACA,QAAI,MAAM,QAAQ,aAAa,GAAG;AAChC,aAAO;AAAA,IACT;AACA,WAAO,EAAE,KAAK,YAAY,GAAG,cAAA;AAAA,EAC/B,GAAG,CAAC,eAAe,UAAU,CAAC;AAE9B,6BACG,OAAA,EAAI,WAAW,GAAG,gCAAgC,SAAS,GAAG,OAC7D,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,UAAU,oBAAC,OAAA,EAAI,WAAU,qCAAoC,UAAA,2BAAuB;AAAA,MAEpF,UAAA,oBAAC,oBAAA,EAAmB,eAAe,oBAAA,CAAqB;AAAA,IAAA;AAAA,EAAA,GAE5D;AAEJ;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { OpenAPIParameter } from './types';
|
|
2
|
+
export type CommandFormProps = {
|
|
3
|
+
parameters: OpenAPIParameter[];
|
|
4
|
+
onExecute: (params: Record<string, string>, headers: Record<string, string>) => void;
|
|
5
|
+
isPending: boolean;
|
|
6
|
+
method: string;
|
|
7
|
+
path: string;
|
|
8
|
+
accept: string;
|
|
9
|
+
initialValues?: Record<string, string>;
|
|
10
|
+
};
|
|
11
|
+
export declare function CommandForm({ parameters, onExecute, isPending, method: _method, path, accept, initialValues, }: CommandFormProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export declare function normalizeParameters(parameters: OpenAPIParameter[], path: string): OpenAPIParameter[];
|
|
13
|
+
export declare function pathParamNames(path: string): string[];
|
|
14
|
+
export declare function submitValue(param: OpenAPIParameter, value: string | undefined): string | null;
|
|
15
|
+
//# sourceMappingURL=CommandForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandForm.d.ts","sourceRoot":"","sources":["../../src/rpc/CommandForm.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEnE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IACrF,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC,CAAC;AASF,wBAAgB,WAAW,CAAC,EAC1B,UAAU,EACV,SAAS,EACT,SAAS,EACT,MAAM,EAAE,OAAO,EACf,IAAI,EACJ,MAAM,EACN,aAAa,GACd,EAAE,gBAAgB,2CA2DlB;AA2OD,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,gBAAgB,EAAE,EAC9B,IAAI,EAAE,MAAM,GACX,gBAAgB,EAAE,CAkBpB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAIrD;AAiCD,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAK7F"}
|