kurtosis-ui-components 0.0.0 → 0.0.4
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 +16 -0
- package/build/AppLayout.d.ts +10 -0
- package/build/AppLayout.js +24 -0
- package/build/CodeEditor.d.ts +14 -0
- package/build/CodeEditor.js +130 -0
- package/build/CopyButton.d.ts +9 -0
- package/build/CopyButton.js +27 -0
- package/build/DataTable.d.ts +17 -0
- package/build/DataTable.js +35 -0
- package/build/DownloadButton.d.ts +9 -0
- package/build/DownloadButton.js +31 -0
- package/build/FeatureNotImplementedModal.d.ts +9 -0
- package/build/FeatureNotImplementedModal.js +9 -0
- package/build/FileDisplay.d.ts +7 -0
- package/build/FileDisplay.js +9 -0
- package/build/FileSize.d.ts +6 -0
- package/build/FileSize.js +16 -0
- package/build/FileTree.d.ts +19 -0
- package/build/FileTree.js +34 -0
- package/build/FormatButton.d.ts +2 -0
- package/build/FormatButton.js +6 -0
- package/build/FormatDateTime.d.ts +8 -0
- package/build/FormatDateTime.js +19 -0
- package/build/HoverLineTabList.d.ts +9 -0
- package/build/HoverLineTabList.js +22 -0
- package/build/KeyboardCommands.d.ts +3 -0
- package/build/KeyboardCommands.js +16 -0
- package/build/KurtosisAlert.d.ts +9 -0
- package/build/KurtosisAlert.js +9 -0
- package/build/KurtosisAlertModal.d.ts +13 -0
- package/build/KurtosisAlertModal.js +5 -0
- package/build/KurtosisBreadcrumbs.d.ts +25 -0
- package/build/KurtosisBreadcrumbs.js +41 -0
- package/build/KurtosisMarkdown.d.ts +5 -0
- package/build/KurtosisMarkdown.js +56 -0
- package/build/KurtosisThemeProvider.d.ts +3 -0
- package/build/KurtosisThemeProvider.js +359 -0
- package/build/Navigation.d.ts +10 -0
- package/build/Navigation.js +10 -0
- package/build/PackageSourceButton.d.ts +7 -0
- package/build/PackageSourceButton.js +25 -0
- package/build/PageTitle.d.ts +5 -0
- package/build/PageTitle.js +5 -0
- package/build/PasteButton.d.ts +8 -0
- package/build/PasteButton.js +27 -0
- package/build/TitledBox.d.ts +6 -0
- package/build/TitledBox.js +5 -0
- package/build/TitledCard.d.ts +10 -0
- package/build/TitledCard.js +5 -0
- package/build/Toasts.d.ts +5 -0
- package/build/Toasts.js +6 -0
- package/build/ValueCard.d.ts +9 -0
- package/build/ValueCard.js +7 -0
- package/build/catalog/KurtosisPackageCard.d.ts +7 -0
- package/build/catalog/KurtosisPackageCard.js +18 -0
- package/build/catalog/KurtosisPackageCardGrid.d.ts +9 -0
- package/build/catalog/KurtosisPackageCardGrid.js +7 -0
- package/build/catalog/SavedPackages.d.ts +9 -0
- package/build/catalog/SavedPackages.js +9 -0
- package/build/catalog/index.d.ts +6 -0
- package/build/catalog/index.js +6 -0
- package/build/catalog/utils.d.ts +1 -0
- package/build/catalog/utils.js +8 -0
- package/build/catalog/widgets/RunKurtosisPackageButton.d.ts +7 -0
- package/build/catalog/widgets/RunKurtosisPackageButton.js +12 -0
- package/build/catalog/widgets/SaveKurtosisPackageButton.d.ts +7 -0
- package/build/catalog/widgets/SaveKurtosisPackageButton.js +28 -0
- package/build/constants.d.ts +3 -0
- package/build/constants.js +3 -0
- package/build/index.d.ts +30 -1
- package/build/index.js +30 -1
- package/build/logs/LogLine.d.ts +7 -0
- package/build/logs/LogLine.js +39 -0
- package/build/logs/LogViewer.d.ts +13 -0
- package/build/logs/LogViewer.js +169 -0
- package/build/logs/index.d.ts +3 -0
- package/build/logs/index.js +3 -0
- package/build/logs/types.d.ts +7 -0
- package/build/logs/types.js +1 -0
- package/build/logs/utils.d.ts +1 -0
- package/build/logs/utils.js +3 -0
- package/build/theme/Fonts.d.ts +2 -0
- package/build/theme/Fonts.js +4 -0
- package/build/theme/constants.d.ts +8 -0
- package/build/theme/constants.js +7 -0
- package/build/theme/formsTheme.d.ts +46 -0
- package/build/theme/formsTheme.js +33 -0
- package/build/theme/tabsTheme.d.ts +56 -0
- package/build/theme/tabsTheme.js +49 -0
- package/build/theme/tagsTheme.d.ts +55 -0
- package/build/theme/tagsTheme.js +45 -0
- package/build/useKeyboardAction.d.ts +3 -0
- package/build/useKeyboardAction.js +40 -0
- package/build/utils/download.d.ts +4 -0
- package/build/utils/download.js +10 -0
- package/build/utils/index.d.ts +19 -0
- package/build/utils/index.js +96 -0
- package/build/utils/packageUtils.d.ts +6 -0
- package/build/utils/packageUtils.js +15 -0
- package/build/utils/types.d.ts +5 -0
- package/build/utils/types.js +1 -0
- package/package.json +25 -3
package/README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Kurtosis UI Components
|
|
2
|
+
|
|
3
|
+
This guide provides instructions and code snippets to help you get started with the Kurtosis UI Components. This library
|
|
4
|
+
can be used to create
|
|
5
|
+
|
|
6
|
+
## Setting Up
|
|
7
|
+
|
|
8
|
+
To use the Kurtosis Typescript SDK, you need to add it as a dependency to your NPM package. You can do this with the following `npm i` command:
|
|
9
|
+
|
|
10
|
+
```console
|
|
11
|
+
$ yarn add kurtosis-ui-components
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
Instructions to follow.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PropsWithChildren, ReactElement } from "react";
|
|
2
|
+
type AppLayoutProps = PropsWithChildren<{
|
|
3
|
+
navbar?: ReactElement;
|
|
4
|
+
}>;
|
|
5
|
+
export declare const AppLayout: ({ children, navbar }: AppLayoutProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
type AppPageLayoutProps = PropsWithChildren<{
|
|
7
|
+
preventPageScroll?: boolean;
|
|
8
|
+
}>;
|
|
9
|
+
export declare const AppPageLayout: ({ preventPageScroll, children }: AppPageLayoutProps) => import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Flex } from "@chakra-ui/react";
|
|
3
|
+
import { createContext, useContext } from "react";
|
|
4
|
+
import { KurtosisBreadcrumbs } from "./KurtosisBreadcrumbs";
|
|
5
|
+
import { MAIN_APP_BOTTOM_PADDING, MAIN_APP_LEFT_PADDING_WITHOUT_NAV, MAIN_APP_LEFT_PADDING_WITH_NAV, MAIN_APP_MAX_WIDTH, MAIN_APP_RIGHT_PADDING, MAIN_APP_TOP_PADDING, } from "./theme/constants";
|
|
6
|
+
import { isDefined } from "./utils";
|
|
7
|
+
const AppLayoutContext = createContext({ hasNavbar: true });
|
|
8
|
+
export const AppLayout = ({ children, navbar }) => {
|
|
9
|
+
return (_jsxs(_Fragment, { children: [isDefined(navbar) && navbar, _jsx(Flex, { flexDirection: "column", as: "main", w: "100%", minH: "100vh", className: "app-container", children: _jsx(AppLayoutContext.Provider, { value: { hasNavbar: isDefined(navbar) }, children: children }) })] }));
|
|
10
|
+
};
|
|
11
|
+
export const AppPageLayout = ({ preventPageScroll, children }) => {
|
|
12
|
+
const { hasNavbar } = useContext(AppLayoutContext);
|
|
13
|
+
const numberOfChildren = Array.isArray(children) ? children.length : 1;
|
|
14
|
+
if (numberOfChildren === 1) {
|
|
15
|
+
return (_jsx(Box, { w: "100%", h: preventPageScroll ? `100vh` : "100%", children: _jsxs(Flex, { flexDirection: "column", flex: "1", w: "100%", h: "100%", maxWidth: MAIN_APP_MAX_WIDTH, pl: hasNavbar ? MAIN_APP_LEFT_PADDING_WITH_NAV : MAIN_APP_LEFT_PADDING_WITHOUT_NAV, pr: MAIN_APP_RIGHT_PADDING, children: [_jsx(KurtosisBreadcrumbs, {}), _jsx(Box, { w: "100%", h: "100%", minH: preventPageScroll ? "0" : undefined, pt: MAIN_APP_TOP_PADDING, pb: MAIN_APP_BOTTOM_PADDING, flexDirection: "column", flex: "1", children: children })] }) }));
|
|
16
|
+
}
|
|
17
|
+
// TS cannot infer that children is an array if numberOfChildren === 2
|
|
18
|
+
if (numberOfChildren === 2 && Array.isArray(children)) {
|
|
19
|
+
return (_jsxs(Flex, { flexDirection: "column", width: "100%", h: preventPageScroll ? `100vh` : "100%", flex: "1", children: [_jsx(Box, { width: "100%", bg: "gray.850", children: _jsxs(Box, { width: "100%", pl: hasNavbar ? MAIN_APP_LEFT_PADDING_WITH_NAV : MAIN_APP_LEFT_PADDING_WITHOUT_NAV, pr: MAIN_APP_RIGHT_PADDING, maxW: MAIN_APP_MAX_WIDTH, children: [_jsx(KurtosisBreadcrumbs, {}), children[0]] }) }), _jsx(Flex, { maxWidth: MAIN_APP_MAX_WIDTH, pl: hasNavbar ? MAIN_APP_LEFT_PADDING_WITH_NAV : MAIN_APP_LEFT_PADDING_WITHOUT_NAV, pr: MAIN_APP_RIGHT_PADDING, pt: MAIN_APP_TOP_PADDING, pb: MAIN_APP_BOTTOM_PADDING, w: "100%", h: "100%", flex: "1", flexDirection: "column", minH: preventPageScroll ? "0" : undefined, children: children[1] })] }));
|
|
20
|
+
}
|
|
21
|
+
throw new Error(`AppPageLayout expects to receive exactly one or two children. ` +
|
|
22
|
+
`If there are two children, the first child is the header section and the next child is the body. ` +
|
|
23
|
+
`Otherwise the only child is the body.`);
|
|
24
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
type CodeEditorProps = {
|
|
3
|
+
text: string;
|
|
4
|
+
fileName?: string;
|
|
5
|
+
onTextChange?: (newText: string) => void;
|
|
6
|
+
showLineNumbers?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type CodeEditorImperativeAttributes = {
|
|
9
|
+
formatCode: () => Promise<void>;
|
|
10
|
+
setText: (text: string) => void;
|
|
11
|
+
setLanguage: (language: string) => void;
|
|
12
|
+
};
|
|
13
|
+
export declare const CodeEditor: import("react").ForwardRefExoticComponent<CodeEditorProps & import("react").RefAttributes<CodeEditorImperativeAttributes>>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from "@chakra-ui/react";
|
|
3
|
+
import { Editor } from "@monaco-editor/react";
|
|
4
|
+
import { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
|
|
5
|
+
import YAML from "yaml";
|
|
6
|
+
import { assertDefined, isDefined, stringifyError } from "./utils";
|
|
7
|
+
const MONACO_READ_ONLY_CHANGE_EVENT_ID = 89;
|
|
8
|
+
export const CodeEditor = forwardRef(({ text, fileName, onTextChange, showLineNumbers }, ref) => {
|
|
9
|
+
const isReadOnly = !isDefined(onTextChange);
|
|
10
|
+
const [monaco, setMonaco] = useState();
|
|
11
|
+
const [editor, setEditor] = useState();
|
|
12
|
+
const resizeEditorBasedOnContent = useCallback(() => {
|
|
13
|
+
if (isDefined(editor)) {
|
|
14
|
+
// An initial layout call is needed, else getContentHeight is garbage
|
|
15
|
+
editor.layout();
|
|
16
|
+
const contentHeight = editor.getContentHeight();
|
|
17
|
+
editor.layout({ width: editor.getContentWidth(), height: contentHeight });
|
|
18
|
+
// Unclear why layout must be called twice, but seems to be necessary
|
|
19
|
+
editor.layout();
|
|
20
|
+
}
|
|
21
|
+
}, [editor]);
|
|
22
|
+
const handleMount = (editor, monaco) => {
|
|
23
|
+
setMonaco(monaco);
|
|
24
|
+
setEditor(editor);
|
|
25
|
+
const colors = {};
|
|
26
|
+
if (isReadOnly) {
|
|
27
|
+
colors["editor.background"] = "#111111";
|
|
28
|
+
}
|
|
29
|
+
monaco.editor.defineTheme("kurtosis-theme", {
|
|
30
|
+
base: "vs-dark",
|
|
31
|
+
inherit: true,
|
|
32
|
+
rules: [],
|
|
33
|
+
colors,
|
|
34
|
+
});
|
|
35
|
+
monaco.editor.setTheme("kurtosis-theme");
|
|
36
|
+
};
|
|
37
|
+
const handleChange = (value, ev) => {
|
|
38
|
+
if (isDefined(value) && onTextChange) {
|
|
39
|
+
onTextChange(value);
|
|
40
|
+
resizeEditorBasedOnContent();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
useImperativeHandle(ref, () => ({
|
|
44
|
+
formatCode: async () => {
|
|
45
|
+
if (!isDefined(editor)) {
|
|
46
|
+
// do nothing
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const doFormat = async () => {
|
|
50
|
+
var _a;
|
|
51
|
+
if (((_a = editor.getModel()) === null || _a === void 0 ? void 0 : _a.getLanguageId()) === "yaml") {
|
|
52
|
+
try {
|
|
53
|
+
const formattedText = YAML.stringify(YAML.parse(editor.getValue()));
|
|
54
|
+
editor.setValue(formattedText);
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
console.error(stringifyError(e));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const formatAction = editor.getAction("editor.action.formatDocument");
|
|
62
|
+
assertDefined(formatAction, `Format action is not defined`);
|
|
63
|
+
await formatAction.run();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
if (isReadOnly) {
|
|
67
|
+
return new Promise((resolve) => {
|
|
68
|
+
const listenerDisposer = editor.onDidChangeConfiguration((event) => {
|
|
69
|
+
if (event.hasChanged(MONACO_READ_ONLY_CHANGE_EVENT_ID)) {
|
|
70
|
+
doFormat().then(() => {
|
|
71
|
+
listenerDisposer.dispose();
|
|
72
|
+
editor.updateOptions({
|
|
73
|
+
readOnly: isReadOnly,
|
|
74
|
+
});
|
|
75
|
+
resizeEditorBasedOnContent();
|
|
76
|
+
resolve();
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
editor.updateOptions({
|
|
81
|
+
readOnly: false,
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
return doFormat();
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
setText: (text) => {
|
|
90
|
+
if (!isDefined(editor)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
editor.setValue(text);
|
|
94
|
+
},
|
|
95
|
+
setLanguage: (language) => {
|
|
96
|
+
if (!isDefined(editor) || !isDefined(monaco)) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const model = editor.getModel();
|
|
100
|
+
if (!isDefined(model)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
monaco.editor.setModelLanguage(model, language);
|
|
104
|
+
},
|
|
105
|
+
}), [isReadOnly, editor, monaco, resizeEditorBasedOnContent]);
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
// Triggered as the text can change without internal editing. (ie if the
|
|
108
|
+
// controlled prop changes)
|
|
109
|
+
resizeEditorBasedOnContent();
|
|
110
|
+
}, [text, resizeEditorBasedOnContent]);
|
|
111
|
+
// Triggering this on every render seems to keep the editor correctly sized
|
|
112
|
+
// it is unclear why this is the case.
|
|
113
|
+
resizeEditorBasedOnContent();
|
|
114
|
+
return (_jsx(Box, { width: "100%", children: _jsx(Editor, { onMount: handleMount, value: text, path: fileName, onChange: handleChange, options: {
|
|
115
|
+
automaticLayout: false,
|
|
116
|
+
readOnly: isReadOnly,
|
|
117
|
+
lineNumbers: showLineNumbers || (!isDefined(showLineNumbers) && !isReadOnly) ? "on" : "off",
|
|
118
|
+
minimap: { enabled: false },
|
|
119
|
+
wordWrap: "on",
|
|
120
|
+
wrappingStrategy: "advanced",
|
|
121
|
+
scrollBeyondLastLine: false,
|
|
122
|
+
renderLineHighlight: isReadOnly ? "none" : "line",
|
|
123
|
+
selectionHighlight: !isReadOnly,
|
|
124
|
+
occurrencesHighlight: !isReadOnly,
|
|
125
|
+
overviewRulerLanes: isReadOnly ? 0 : 3,
|
|
126
|
+
scrollbar: {
|
|
127
|
+
alwaysConsumeMouseWheel: false,
|
|
128
|
+
},
|
|
129
|
+
}, defaultLanguage: !isDefined(fileName) ? "json" : undefined, theme: "vs-dark" }) }));
|
|
130
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ButtonProps, IconButtonProps } from "@chakra-ui/react";
|
|
2
|
+
type CopyButtonProps<IsIconButton extends boolean> = (IsIconButton extends true ? IconButtonProps : ButtonProps) & {
|
|
3
|
+
valueToCopy?: (() => string) | string | null;
|
|
4
|
+
text?: IsIconButton extends true ? string : never;
|
|
5
|
+
isIconButton?: IsIconButton;
|
|
6
|
+
contentName: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const CopyButton: <IsIconButton extends boolean>({ valueToCopy, text, contentName, isIconButton, ...buttonProps }: CopyButtonProps<IsIconButton>) => import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Button, IconButton, useToast } from "@chakra-ui/react";
|
|
3
|
+
import { FiCopy } from "react-icons/fi";
|
|
4
|
+
import { SuccessToast } from "./Toasts";
|
|
5
|
+
import { isDefined } from "./utils";
|
|
6
|
+
export const CopyButton = ({ valueToCopy, text, contentName, isIconButton, ...buttonProps }) => {
|
|
7
|
+
const toast = useToast();
|
|
8
|
+
const handleCopyClick = () => {
|
|
9
|
+
if (isDefined(valueToCopy)) {
|
|
10
|
+
const v = typeof valueToCopy === "string" ? valueToCopy : valueToCopy();
|
|
11
|
+
navigator.clipboard.writeText(v);
|
|
12
|
+
toast({
|
|
13
|
+
position: "bottom",
|
|
14
|
+
render: () => _jsx(SuccessToast, { message: `Copied ${contentName} to the clipboard` }),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
if (!isDefined(valueToCopy) && !isDefined(buttonProps.onClick)) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
if (isIconButton) {
|
|
22
|
+
return (_jsx(IconButton, { icon: _jsx(FiCopy, {}), size: "xs", variant: "ghost", colorScheme: "darkBlue", onClick: handleCopyClick, ...buttonProps, children: text || "Copy" }));
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return (_jsx(Button, { leftIcon: _jsx(FiCopy, {}), size: "xs", colorScheme: "darkBlue", onClick: handleCopyClick, ...buttonProps, children: text || "Copy" }));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ColumnDef, RowData, SortingState } from "@tanstack/react-table";
|
|
2
|
+
import { type RowSelectionState } from "@tanstack/table-core/src/features/RowSelection";
|
|
3
|
+
import { type OnChangeFn } from "@tanstack/table-core/src/types";
|
|
4
|
+
declare module "@tanstack/table-core" {
|
|
5
|
+
interface ColumnMeta<TData extends RowData, TValue> {
|
|
6
|
+
isNumeric?: boolean;
|
|
7
|
+
centerAligned?: boolean;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export type DataTableProps<Data extends object> = {
|
|
11
|
+
data: Data[];
|
|
12
|
+
columns: ColumnDef<Data, any>[];
|
|
13
|
+
defaultSorting?: SortingState;
|
|
14
|
+
rowSelection?: Record<string, boolean>;
|
|
15
|
+
onRowSelectionChange?: OnChangeFn<RowSelectionState>;
|
|
16
|
+
};
|
|
17
|
+
export declare function DataTable<Data extends object>({ data, columns, defaultSorting, rowSelection, onRowSelectionChange, }: DataTableProps<Data>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Button, Icon, Table, Tbody, Td, Th, Thead, Tr } from "@chakra-ui/react";
|
|
3
|
+
import { flexRender, getCoreRowModel, getSortedRowModel, useReactTable, } from "@tanstack/react-table";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import { BiDownArrowAlt, BiUpArrowAlt } from "react-icons/bi";
|
|
6
|
+
import { assertDefined, isDefined } from "./utils";
|
|
7
|
+
export function DataTable({ data, columns, defaultSorting, rowSelection, onRowSelectionChange, }) {
|
|
8
|
+
if (isDefined(rowSelection) || isDefined(onRowSelectionChange)) {
|
|
9
|
+
assertDefined(rowSelection, `rowSelection and onRowSelectionChange must both be defined in DataTable if either are defined.`);
|
|
10
|
+
assertDefined(onRowSelectionChange, `rowSelection and onRowSelectionChange must both be defined in DataTable if either are defined.`);
|
|
11
|
+
}
|
|
12
|
+
const [sorting, setSorting] = useState(defaultSorting || []);
|
|
13
|
+
const tableState = { sorting };
|
|
14
|
+
if (isDefined(rowSelection)) {
|
|
15
|
+
tableState["rowSelection"] = rowSelection;
|
|
16
|
+
}
|
|
17
|
+
const table = useReactTable({
|
|
18
|
+
columns,
|
|
19
|
+
data,
|
|
20
|
+
enableSortingRemoval: false,
|
|
21
|
+
getCoreRowModel: getCoreRowModel(),
|
|
22
|
+
onSortingChange: setSorting,
|
|
23
|
+
getSortedRowModel: getSortedRowModel(),
|
|
24
|
+
enableRowSelection: isDefined(rowSelection),
|
|
25
|
+
onRowSelectionChange: onRowSelectionChange,
|
|
26
|
+
state: tableState,
|
|
27
|
+
});
|
|
28
|
+
return (_jsx(Box, { w: "100%", h: "100%", borderRadius: "6px", border: "1px solid", borderColor: "whiteAlpha.300", overflow: "clip", children: _jsxs(Table, { children: [_jsx(Thead, { children: table.getHeaderGroups().map((headerGroup) => (_jsx(Tr, { children: headerGroup.headers.map((header) => {
|
|
29
|
+
const meta = header.column.columnDef.meta;
|
|
30
|
+
return (_jsxs(Th, { onClick: header.column.getToggleSortingHandler(), isNumeric: meta === null || meta === void 0 ? void 0 : meta.isNumeric, textAlign: !!(meta === null || meta === void 0 ? void 0 : meta.centerAligned) ? "center" : undefined, children: [header.column.getCanSort() && (_jsx(Button, { variant: "sortableHeader", size: "xs", rightIcon: header.column.getIsSorted() === "desc" ? (_jsx(Icon, { as: BiDownArrowAlt, color: "gray.400" })) : header.column.getIsSorted() === "asc" ? (_jsx(Icon, { as: BiUpArrowAlt, color: "gray.400" })) : undefined, children: flexRender(header.column.columnDef.header, header.getContext()) })), !header.column.getCanSort() && flexRender(header.column.columnDef.header, header.getContext())] }, header.id));
|
|
31
|
+
}) }, headerGroup.id))) }), _jsx(Tbody, { children: table.getRowModel().rows.map((row) => (_jsx(Tr, { bg: row.getIsSelected() ? "gray.700" : "", children: row.getVisibleCells().map((cell) => {
|
|
32
|
+
const meta = cell.column.columnDef.meta;
|
|
33
|
+
return (_jsx(Td, { isNumeric: meta === null || meta === void 0 ? void 0 : meta.isNumeric, textAlign: !!(meta === null || meta === void 0 ? void 0 : meta.centerAligned) ? "center" : undefined, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
|
|
34
|
+
}) }, row.id))) })] }) }));
|
|
35
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ButtonProps, IconButtonProps } from "@chakra-ui/react";
|
|
2
|
+
type DownloadButtonProps<IsIconButton extends boolean> = (IsIconButton extends true ? IconButtonProps : ButtonProps) & {
|
|
3
|
+
valueToDownload?: (() => string) | (() => AsyncIterable<string>) | string | null;
|
|
4
|
+
fileName: string;
|
|
5
|
+
text?: IsIconButton extends true ? string : never;
|
|
6
|
+
isIconButton?: IsIconButton;
|
|
7
|
+
};
|
|
8
|
+
export declare const DownloadButton: <IsIconButton extends boolean>({ valueToDownload, text, fileName, isIconButton, ...buttonProps }: DownloadButtonProps<IsIconButton>) => import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Button, IconButton } from "@chakra-ui/react";
|
|
3
|
+
import { FiDownload } from "react-icons/fi";
|
|
4
|
+
import streamsaver from "streamsaver";
|
|
5
|
+
import { isAsyncIterable, isDefined, saveTextAsFile, stripAnsi } from "./utils";
|
|
6
|
+
export const DownloadButton = ({ valueToDownload, text, fileName, isIconButton, ...buttonProps }) => {
|
|
7
|
+
const handleDownloadClick = async () => {
|
|
8
|
+
if (isDefined(valueToDownload)) {
|
|
9
|
+
const v = typeof valueToDownload === "string" ? valueToDownload : valueToDownload();
|
|
10
|
+
if (isAsyncIterable(v)) {
|
|
11
|
+
const writableStream = streamsaver.createWriteStream(fileName);
|
|
12
|
+
const writer = writableStream.getWriter();
|
|
13
|
+
for await (const part of v) {
|
|
14
|
+
await writer.write(new TextEncoder().encode(`${stripAnsi(part)}\n`));
|
|
15
|
+
}
|
|
16
|
+
await writer.close();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
saveTextAsFile(v, fileName);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
if (!isDefined(valueToDownload) && !isDefined(buttonProps.onClick)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
if (isIconButton) {
|
|
26
|
+
return (_jsx(IconButton, { icon: _jsx(FiDownload, {}), size: "xs", variant: "ghost", colorScheme: "darkBlue", onClick: handleDownloadClick, ...buttonProps }));
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
return (_jsx(Button, { leftIcon: _jsx(FiDownload, {}), size: "xs", colorScheme: "darkBlue", onClick: handleDownloadClick, ...buttonProps, children: text || "Download" }));
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type FeatureNotImplementedModalProps = {
|
|
2
|
+
featureName: string;
|
|
3
|
+
issueUrl: string;
|
|
4
|
+
message?: string;
|
|
5
|
+
isOpen: boolean;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
};
|
|
8
|
+
export declare const FeatureNotImplementedModal: ({ featureName, issueUrl, message, isOpen, onClose, }: FeatureNotImplementedModalProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { KurtosisAlertModal } from "./KurtosisAlertModal";
|
|
3
|
+
export const FeatureNotImplementedModal = ({ featureName, issueUrl, message, isOpen, onClose, }) => {
|
|
4
|
+
return (_jsx(KurtosisAlertModal, { title: `${featureName} unavailable`, isOpen: isOpen, onClose: onClose, confirmText: "Go to Issue", onConfirm: () => {
|
|
5
|
+
onClose();
|
|
6
|
+
window.open(issueUrl, "_blank");
|
|
7
|
+
}, confirmButtonProps: { colorScheme: "kurtosisGreen" }, content: message ||
|
|
8
|
+
`${featureName} is not currently available. Please comment/upvote the issue if you would like to use it.` }));
|
|
9
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ButtonGroup } from "@chakra-ui/react";
|
|
3
|
+
import { CodeEditor } from "./CodeEditor";
|
|
4
|
+
import { CopyButton } from "./CopyButton";
|
|
5
|
+
import { DownloadButton } from "./DownloadButton";
|
|
6
|
+
import { TitledCard } from "./TitledCard";
|
|
7
|
+
export const FileDisplay = ({ value, filename, title }) => {
|
|
8
|
+
return (_jsx(TitledCard, { title: title, controls: _jsxs(ButtonGroup, { children: [_jsx(CopyButton, { contentName: title.toLowerCase(), valueToCopy: value, isIconButton: true, "aria-label": `Copy ${title}` }), _jsx(DownloadButton, { fileName: filename, valueToDownload: value, isIconButton: true, "aria-label": `Download ${filename}` })] }), children: _jsx(CodeEditor, { text: value }) }));
|
|
9
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Text } from "@chakra-ui/react";
|
|
3
|
+
import { isDefined } from "./utils";
|
|
4
|
+
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
5
|
+
export const FileSize = ({ fileSize, ...textProps }) => {
|
|
6
|
+
if (!isDefined(fileSize)) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
let size = fileSize;
|
|
10
|
+
let unitIndex = 0;
|
|
11
|
+
while (size > 1024 && unitIndex < units.length - 1) {
|
|
12
|
+
size = size / BigInt(1024);
|
|
13
|
+
unitIndex += 1;
|
|
14
|
+
}
|
|
15
|
+
return (_jsx(Text, { as: "span", ...textProps, children: `${size}${units[unitIndex]}` }));
|
|
16
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file tree component recursively renders itself to present a file tree.
|
|
3
|
+
* To keep this performant the nodes (DirectoryNode and FileNode) must make use of
|
|
4
|
+
* useCallback and useMemo. This allows the React.memo around FileTreeMode to function
|
|
5
|
+
* and skip rendering unchanged components.
|
|
6
|
+
*/
|
|
7
|
+
export type FileTreeNode = {
|
|
8
|
+
name: string;
|
|
9
|
+
size?: bigint;
|
|
10
|
+
childNodes?: FileTreeNode[];
|
|
11
|
+
};
|
|
12
|
+
type FileTreeProps = {
|
|
13
|
+
nodes: FileTreeNode[];
|
|
14
|
+
selectedFilePath?: string[];
|
|
15
|
+
onFileSelected: (selectedFilePath: string[]) => void;
|
|
16
|
+
_isChildNode?: boolean;
|
|
17
|
+
};
|
|
18
|
+
export declare const FileTree: ({ nodes, selectedFilePath, onFileSelected, _isChildNode }: FileTreeProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Flex, Text } from "@chakra-ui/react";
|
|
3
|
+
import React, { useCallback, useMemo, useState } from "react";
|
|
4
|
+
import { AiFillFile, AiFillFolder, AiFillFolderOpen } from "react-icons/ai";
|
|
5
|
+
import { FileSize } from "./FileSize";
|
|
6
|
+
import { isDefined } from "./utils";
|
|
7
|
+
export const FileTree = ({ nodes, selectedFilePath, onFileSelected, _isChildNode }) => {
|
|
8
|
+
return (_jsx(Flex, { flexDirection: "column", pl: _isChildNode ? "22px" : undefined, w: "100%", children: nodes.map((node, i) => (_jsx(FileTreeNodeComponent, { node: node, selectedFilePath: isDefined(selectedFilePath) && selectedFilePath.length > 0 && selectedFilePath[0] === node.name
|
|
9
|
+
? selectedFilePath
|
|
10
|
+
: undefined, onFileSelected: onFileSelected }, node.name))) }));
|
|
11
|
+
};
|
|
12
|
+
const FileTreeNodeComponent = React.memo((props) => {
|
|
13
|
+
if (isDefined(props.node.childNodes)) {
|
|
14
|
+
return _jsx(DirectoryNode, { ...props });
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
return _jsx(FileNode, { ...props });
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const DirectoryNode = ({ node, selectedFilePath, onFileSelected, }) => {
|
|
21
|
+
const [collapsed, setCollapsed] = useState(false);
|
|
22
|
+
const childSelectedFilePath = useMemo(() => isDefined(selectedFilePath) && selectedFilePath.length > 0 && selectedFilePath[0] === node.name
|
|
23
|
+
? selectedFilePath.slice(1)
|
|
24
|
+
: undefined, [selectedFilePath, node]);
|
|
25
|
+
const handleClick = useCallback(() => {
|
|
26
|
+
setCollapsed((collapsed) => !collapsed);
|
|
27
|
+
}, []);
|
|
28
|
+
const handleFileSelected = useCallback((filePath) => onFileSelected([node.name, ...filePath]), [onFileSelected, node]);
|
|
29
|
+
return (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "fileTree", size: "xs", onClick: handleClick, leftIcon: collapsed ? _jsx(AiFillFolder, {}) : _jsx(AiFillFolderOpen, {}), children: node.name }), !collapsed && (_jsx(FileTree, { nodes: node.childNodes, onFileSelected: handleFileSelected, selectedFilePath: childSelectedFilePath, _isChildNode: true }))] }));
|
|
30
|
+
};
|
|
31
|
+
const FileNode = ({ node, selectedFilePath, onFileSelected }) => {
|
|
32
|
+
const isSelected = isDefined(selectedFilePath) && selectedFilePath.length === 1 && selectedFilePath[0] === node.name;
|
|
33
|
+
return (_jsx(Button, { variant: "fileTree", size: "xs", leftIcon: _jsx(AiFillFile, {}), rightIcon: _jsx(FileSize, { fileSize: node.size, color: "gray.250" }), isActive: isSelected, onClick: () => onFileSelected([node.name]), children: _jsx(Text, { as: "span", w: "100%", textAlign: "left", children: node.name }) }));
|
|
34
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from "@chakra-ui/react";
|
|
3
|
+
import { BiPaintRoll } from "react-icons/bi";
|
|
4
|
+
export const FormatButton = ({ ...buttonProps }) => {
|
|
5
|
+
return (_jsx(Button, { leftIcon: _jsx(BiPaintRoll, {}), size: "sm", colorScheme: "darkBlue", loadingText: "Format", ...buttonProps, children: "Format" }));
|
|
6
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TextProps } from "@chakra-ui/react";
|
|
2
|
+
import { DateTime } from "luxon";
|
|
3
|
+
type FormatDateTimeProps = TextProps & {
|
|
4
|
+
dateTime: DateTime | null;
|
|
5
|
+
format: Intl.DateTimeFormatOptions | "relative";
|
|
6
|
+
};
|
|
7
|
+
export declare const FormatDateTime: ({ dateTime, format, ...textProps }: FormatDateTimeProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Text, Tooltip } from "@chakra-ui/react";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { isDefined } from "./utils";
|
|
5
|
+
export const FormatDateTime = ({ dateTime, format, ...textProps }) => {
|
|
6
|
+
const [formattedDateTime, setFormattedDateTime] = useState(format === "relative" ? dateTime === null || dateTime === void 0 ? void 0 : dateTime.toRelative() : dateTime === null || dateTime === void 0 ? void 0 : dateTime.toLocaleString(format));
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
if (format === "relative") {
|
|
9
|
+
const timeout = setTimeout(() => {
|
|
10
|
+
setFormattedDateTime(dateTime === null || dateTime === void 0 ? void 0 : dateTime.toRelative());
|
|
11
|
+
}, 15 * 1000);
|
|
12
|
+
return () => clearTimeout(timeout);
|
|
13
|
+
}
|
|
14
|
+
}, [dateTime, format]);
|
|
15
|
+
if (!isDefined(dateTime)) {
|
|
16
|
+
return (_jsx(Text, { as: "span", ...textProps, children: "Unknown" }));
|
|
17
|
+
}
|
|
18
|
+
return (_jsx(Tooltip, { label: dateTime.toLocal().toFormat("yyyy-MM-dd HH:mm:ss ZZZZ"), children: _jsx(Text, { as: "span", ...textProps, children: formattedDateTime }) }));
|
|
19
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type HoverLineTabListProps = {
|
|
2
|
+
tabs: string[];
|
|
3
|
+
activeTab: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* This component is needed as the hover interaction cannot be controlled with CSS
|
|
7
|
+
*/
|
|
8
|
+
export declare const HoverLineTabList: ({ tabs, activeTab }: HoverLineTabListProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Tab, TabList } from "@chakra-ui/react";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { isDefined } from "./utils";
|
|
5
|
+
/**
|
|
6
|
+
* This component is needed as the hover interaction cannot be controlled with CSS
|
|
7
|
+
*/
|
|
8
|
+
export const HoverLineTabList = ({ tabs, activeTab }) => {
|
|
9
|
+
const [hoveredTab, setHoveredTab] = useState();
|
|
10
|
+
return (_jsx(TabList, { children: tabs.map((tab) => {
|
|
11
|
+
return (_jsx(Tab, { sx: {
|
|
12
|
+
_selected: {
|
|
13
|
+
borderBottom: hoveredTab === tab || (!isDefined(hoveredTab) && activeTab === tab)
|
|
14
|
+
? "2px solid var(--chakra-colors-kurtosisGreen-400)"
|
|
15
|
+
: undefined,
|
|
16
|
+
},
|
|
17
|
+
borderBottom: hoveredTab === tab || (!isDefined(hoveredTab) && activeTab === tab)
|
|
18
|
+
? "2px solid var(--chakra-colors-kurtosisGreen-400)"
|
|
19
|
+
: "2px solid transparent",
|
|
20
|
+
}, onMouseEnter: () => setHoveredTab(tab), onMouseLeave: () => setHoveredTab(undefined), children: tab }, tab));
|
|
21
|
+
}) }));
|
|
22
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Text } from "@chakra-ui/react";
|
|
3
|
+
export const FindCommand = (props) => {
|
|
4
|
+
let text = "Ctrl + F";
|
|
5
|
+
if (navigator.userAgent.indexOf("Mac") > -1) {
|
|
6
|
+
text = "⌘F";
|
|
7
|
+
}
|
|
8
|
+
return (_jsx(Text, { as: "span", ...props, children: text }));
|
|
9
|
+
};
|
|
10
|
+
export const OmniboxCommand = (props) => {
|
|
11
|
+
let text = "Ctrl + K";
|
|
12
|
+
if (navigator.userAgent.indexOf("Mac") > -1) {
|
|
13
|
+
text = "⌘K";
|
|
14
|
+
}
|
|
15
|
+
return (_jsx(Text, { as: "span", ...props, children: text }));
|
|
16
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AlertProps } from "@chakra-ui/react";
|
|
2
|
+
import { FallbackProps } from "react-error-boundary";
|
|
3
|
+
type KurtosisAlertProps = AlertProps & {
|
|
4
|
+
message: string;
|
|
5
|
+
details?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const KurtosisAlert: ({ message, details, ...alertProps }: KurtosisAlertProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare const KurtosisAlertError: ({ error }: FallbackProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Alert, AlertDescription, AlertIcon, AlertTitle, Box, Flex, } from "@chakra-ui/react";
|
|
3
|
+
import { isDefined, stringifyError } from "./utils";
|
|
4
|
+
export const KurtosisAlert = ({ message, details, ...alertProps }) => {
|
|
5
|
+
return (_jsxs(Alert, { status: "error", overflowY: "auto", maxHeight: "300px", alignItems: "flex-start", ...alertProps, children: [_jsx(AlertIcon, {}), _jsxs(Flex, { flexDirection: "column", width: "100%", gap: "8px", children: [_jsxs(Flex, { direction: "row", children: [_jsx(AlertTitle, { children: "Error" }), _jsx(AlertDescription, { children: message })] }), isDefined(details) && (_jsx(Accordion, { allowToggle: true, children: _jsxs(AccordionItem, { children: [_jsx("h2", { children: _jsxs(AccordionButton, { children: [_jsx(Box, { as: "span", flex: "1", textAlign: "left", children: "Error details" }), _jsx(AccordionIcon, {})] }) }), _jsx(AccordionPanel, { pb: 4, children: _jsx(Box, { as: "pre", whiteSpace: "pre-wrap", wordBreak: "break-word", children: details }) })] }) }))] })] }));
|
|
6
|
+
};
|
|
7
|
+
export const KurtosisAlertError = ({ error }) => {
|
|
8
|
+
return _jsx(KurtosisAlert, { message: "An error ocurred, details below", details: stringifyError(error) });
|
|
9
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ButtonProps } from "@chakra-ui/react";
|
|
2
|
+
type KurtosisAlertModalProps = {
|
|
3
|
+
title: string;
|
|
4
|
+
content: string;
|
|
5
|
+
isOpen: boolean;
|
|
6
|
+
isLoading?: boolean;
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
onConfirm: () => void;
|
|
9
|
+
confirmText: string;
|
|
10
|
+
confirmButtonProps?: ButtonProps;
|
|
11
|
+
};
|
|
12
|
+
export declare const KurtosisAlertModal: ({ title, content, isOpen, isLoading, onClose, onConfirm, confirmText, confirmButtonProps, }: KurtosisAlertModalProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Flex, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, Text, } from "@chakra-ui/react";
|
|
3
|
+
export const KurtosisAlertModal = ({ title, content, isOpen, isLoading, onClose, onConfirm, confirmText, confirmButtonProps, }) => {
|
|
4
|
+
return (_jsxs(Modal, { isOpen: isOpen, onClose: () => !isLoading && onClose(), isCentered: true, children: [_jsx(ModalOverlay, {}), _jsxs(ModalContent, { children: [_jsx(ModalHeader, { children: title }), _jsx(ModalCloseButton, {}), _jsx(ModalBody, { children: _jsx(Text, { children: content }) }), _jsx(ModalFooter, { children: _jsxs(Flex, { justifyContent: "flex-end", gap: "12px", children: [_jsx(Button, { color: "gray.100", onClick: onClose, isDisabled: isLoading, children: "Dismiss" }), _jsx(Button, { onClick: onConfirm, ...confirmButtonProps, isLoading: isLoading, children: confirmText })] }) })] })] }));
|
|
5
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import { UIMatch } from "react-router-dom";
|
|
3
|
+
export type KurtosisBreadcrumbsHandle<T extends string> = {
|
|
4
|
+
type: T;
|
|
5
|
+
};
|
|
6
|
+
export declare const registerBreadcrumbHandler: <T extends string>(type: T, render: (props: {
|
|
7
|
+
matches: UIMatch<object, KurtosisBreadcrumbsHandle<T>>[];
|
|
8
|
+
}) => ReactElement) => void;
|
|
9
|
+
type KurtosisBreadcrumbMenuItem = {
|
|
10
|
+
name: string;
|
|
11
|
+
destination: string;
|
|
12
|
+
icon?: ReactElement;
|
|
13
|
+
};
|
|
14
|
+
export type KurtosisBreadcrumb = {
|
|
15
|
+
name: string;
|
|
16
|
+
destination: string;
|
|
17
|
+
alternatives?: KurtosisBreadcrumbMenuItem[];
|
|
18
|
+
};
|
|
19
|
+
export declare const KurtosisBreadcrumbs: () => import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
type KurtosisBreadcrumbsImplProps = {
|
|
21
|
+
matchCrumbs: KurtosisBreadcrumb[];
|
|
22
|
+
extraControls?: ReactElement[];
|
|
23
|
+
};
|
|
24
|
+
export declare const KurtosisBreadcrumbsImpl: ({ matchCrumbs, extraControls }: KurtosisBreadcrumbsImplProps) => import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export {};
|