kurtosis-ui-components 0.85.55 → 0.86.0

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.
@@ -22,6 +22,6 @@ export const CopyButton = ({ valueToCopy, text, contentName, isIconButton, ...bu
22
22
  return (_jsx(IconButton, { icon: _jsx(FiCopy, {}), size: "xs", variant: "ghost", colorScheme: "darkBlue", onClick: handleCopyClick, ...buttonProps, children: text || "Copy" }));
23
23
  }
24
24
  else {
25
- return (_jsx(Button, { leftIcon: _jsx(FiCopy, {}), size: "xs", colorScheme: "darkBlue", onClick: handleCopyClick, ...buttonProps, children: text || "Copy" }));
25
+ return (_jsx(Button, { leftIcon: _jsx(FiCopy, {}), size: "xs", colorScheme: "darkBlue", variant: "outline", onClick: handleCopyClick, ...buttonProps, children: text || "Copy" }));
26
26
  }
27
27
  };
@@ -25,7 +25,7 @@ export function DataTable({ data, columns, defaultSorting, rowSelection, onRowSe
25
25
  onRowSelectionChange: onRowSelectionChange,
26
26
  state: tableState,
27
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) => {
28
+ return (_jsx(Box, { w: "100%", h: "100%", flex: "1", 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
29
  const meta = header.column.columnDef.meta;
30
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
31
  }) }, headerGroup.id))) }), _jsx(Tbody, { children: table.getRowModel().rows.map((row) => (_jsx(Tr, { bg: row.getIsSelected() ? "gray.700" : "", children: row.getVisibleCells().map((cell) => {
@@ -26,6 +26,6 @@ export const DownloadButton = ({ valueToDownload, text, fileName, isIconButton,
26
26
  return (_jsx(IconButton, { icon: _jsx(FiDownload, {}), size: "xs", variant: "ghost", colorScheme: "darkBlue", onClick: handleDownloadClick, ...buttonProps }));
27
27
  }
28
28
  else {
29
- return (_jsx(Button, { leftIcon: _jsx(FiDownload, {}), size: "xs", colorScheme: "darkBlue", onClick: handleDownloadClick, ...buttonProps, children: text || "Download" }));
29
+ return (_jsx(Button, { leftIcon: _jsx(FiDownload, {}), size: "xs", colorScheme: "darkBlue", variant: "outline", onClick: handleDownloadClick, ...buttonProps, children: text || "Download" }));
30
30
  }
31
31
  };
@@ -2,5 +2,5 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Button } from "@chakra-ui/react";
3
3
  import { BiPaintRoll } from "react-icons/bi";
4
4
  export const FormatButton = ({ ...buttonProps }) => {
5
- return (_jsx(Button, { leftIcon: _jsx(BiPaintRoll, {}), size: "sm", colorScheme: "darkBlue", loadingText: "Format", ...buttonProps, children: "Format" }));
5
+ return (_jsx(Button, { leftIcon: _jsx(BiPaintRoll, {}), size: "sm", colorScheme: "darkBlue", loadingText: "Format", variant: "outline", ...buttonProps, children: "Format" }));
6
6
  };
@@ -1,5 +1,5 @@
1
1
  type HoverLineTabListProps = {
2
- tabs: string[];
2
+ tabs: readonly string[];
3
3
  activeTab: string;
4
4
  };
5
5
  /**
@@ -3,7 +3,8 @@ import { FallbackProps } from "react-error-boundary";
3
3
  type KurtosisAlertProps = AlertProps & {
4
4
  message: string;
5
5
  details?: string;
6
+ onClose?: () => void;
6
7
  };
7
- export declare const KurtosisAlert: ({ message, details, ...alertProps }: KurtosisAlertProps) => import("react/jsx-runtime").JSX.Element;
8
+ export declare const KurtosisAlert: ({ message, details, onClose, ...alertProps }: KurtosisAlertProps) => import("react/jsx-runtime").JSX.Element;
8
9
  export declare const KurtosisAlertError: ({ error }: FallbackProps) => import("react/jsx-runtime").JSX.Element;
9
10
  export {};
@@ -1,8 +1,8 @@
1
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";
2
+ import { Accordion, AccordionButton, AccordionIcon, AccordionItem, AccordionPanel, Alert, AlertDescription, AlertIcon, AlertTitle, Box, CloseButton, Flex, } from "@chakra-ui/react";
3
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 }) })] }) }))] })] }));
4
+ export const KurtosisAlert = ({ message, details, onClose, ...alertProps }) => {
5
+ return (_jsxs(Alert, { status: "error", overflowY: "auto", maxHeight: "300px", position: "relative", alignItems: "flex-start", ...alertProps, children: [_jsx(AlertIcon, {}), isDefined(onClose) && (_jsx(CloseButton, { alignSelf: "flex-start", position: "absolute", right: "4px", top: "4px", onClick: onClose })), _jsxs(Flex, { flexDirection: "column", width: "100%", gap: "8px", 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
6
  };
7
7
  export const KurtosisAlertError = ({ error }) => {
8
8
  return _jsx(KurtosisAlert, { message: "An error ocurred, details below", details: stringifyError(error) });
@@ -5,6 +5,7 @@ import { mode } from "@chakra-ui/theme-tools";
5
5
  import { useEffect } from "react";
6
6
  import Fonts from "./theme/Fonts";
7
7
  import { formsTheme } from "./theme/formsTheme";
8
+ import { progressTheme } from "./theme/progressTheme";
8
9
  import { tabsTheme } from "./theme/tabsTheme";
9
10
  import { tagTheme } from "./theme/tagsTheme";
10
11
  // https://github.com/chakra-ui/chakra-ui/issues/3347
@@ -26,13 +27,13 @@ const theme = extendTheme({
26
27
  },
27
28
  colors: {
28
29
  kurtosisGreen: {
29
- 100: "#18371E",
30
- 200: "#008c19",
31
- 300: "#00bb22",
30
+ 100: "#99f7aa",
31
+ 200: "#66f27f",
32
+ 300: "#33ee55",
32
33
  400: "#00C223",
33
- 500: "#33ee55",
34
- 600: "#66f27f",
35
- 700: "#99f7aa",
34
+ 500: "#00bb22",
35
+ 600: "#008c19",
36
+ 700: "#18371E",
36
37
  },
37
38
  darkBlue: {
38
39
  200: "#516A77",
@@ -53,6 +54,19 @@ const theme = extendTheme({
53
54
  850: "#1B1B1D",
54
55
  900: "#111111", // ui background
55
56
  },
57
+ red: {
58
+ 450: "#BD3737",
59
+ 650: "#943031",
60
+ 900: "#441C1C",
61
+ },
62
+ green: {
63
+ 450: "#05A122",
64
+ 650: "#0B7F21",
65
+ },
66
+ blue: {
67
+ 450: "#2D6DAB",
68
+ 650: "#285987",
69
+ },
56
70
  },
57
71
  fontSizes: {
58
72
  xs: "12px",
@@ -78,6 +92,16 @@ const theme = extendTheme({
78
92
  }),
79
93
  },
80
94
  components: {
95
+ Alert: {
96
+ baseStyle: defineStyle(({ colorScheme }) => ({
97
+ container: {
98
+ bg: `${colorScheme}.900`,
99
+ },
100
+ icon: {
101
+ color: `${colorScheme}.500`,
102
+ },
103
+ })),
104
+ },
81
105
  Badge: {
82
106
  baseStyle: {
83
107
  textTransform: "none",
@@ -86,15 +110,32 @@ const theme = extendTheme({
86
110
  },
87
111
  Button: {
88
112
  defaultProps: {
89
- variant: "outline",
113
+ variant: "solid",
90
114
  },
91
115
  variants: {
92
- outline: (props) => ({
93
- _hover: { borderColor: `${props.colorScheme}.400`, bg: `gray.650` },
94
- _active: { bg: `gray.700` },
95
- color: `${props.colorScheme}.400`,
96
- borderColor: "gray.300",
97
- }),
116
+ solid: (props) => {
117
+ const bg = ["red", "green", "blue"].includes(props.colorScheme)
118
+ ? `${props.colorScheme}.650`
119
+ : `${props.colorScheme}.600`;
120
+ const bgInteraction = ["red", "green", "blue"].includes(props.colorScheme)
121
+ ? `${props.colorScheme}.450`
122
+ : `${props.colorScheme}.400`;
123
+ return {
124
+ _hover: { bg: bgInteraction, _disabled: { bg } },
125
+ _active: { bg: bgInteraction },
126
+ bg,
127
+ color: `white`,
128
+ };
129
+ },
130
+ outline: (props) => {
131
+ const color = props.colorScheme === "gray" ? "gray.100" : `${props.colorScheme}.400`;
132
+ return {
133
+ _hover: { borderColor: `${props.colorScheme}.400`, bg: `gray.650` },
134
+ _active: { bg: `gray.700` },
135
+ color,
136
+ borderColor: "gray.300",
137
+ };
138
+ },
98
139
  activeFilterControl: (props) => ({
99
140
  _hover: { borderColor: `${props.colorScheme}.200` },
100
141
  borderColor: `${props.colorScheme}.400`,
@@ -122,9 +163,6 @@ const theme = extendTheme({
122
163
  borderColor: "gray.300",
123
164
  };
124
165
  },
125
- solid: defineStyle((props) => ({
126
- color: `white`,
127
- })),
128
166
  savedSolid: (props) => {
129
167
  const solid = theme.components.Button.variants.solid(props);
130
168
  return {
@@ -263,7 +301,28 @@ const theme = extendTheme({
263
301
  },
264
302
  })),
265
303
  },
304
+ Drawer: {
305
+ baseStyle: {
306
+ overlay: {
307
+ bg: "blackAlpha.100",
308
+ },
309
+ header: {
310
+ borderBottomWidth: "1px",
311
+ borderBottomColor: "gray.500",
312
+ },
313
+ body: { bg: "gray.900", h: "100%", p: "16px" },
314
+ footer: {
315
+ borderTopWidth: "1px",
316
+ borderTopColor: "gray.500",
317
+ },
318
+ },
319
+ },
266
320
  Form: formsTheme,
321
+ Input: {
322
+ baseStyle: {
323
+ field: { _dark: { bg: "gray.850" } },
324
+ },
325
+ },
267
326
  Menu: {
268
327
  baseStyle: {
269
328
  list: {
@@ -274,7 +333,7 @@ const theme = extendTheme({
274
333
  item: {
275
334
  borderRadius: "6px",
276
335
  },
277
- icon: { color: "gray.400", "font-size": "18px !important" },
336
+ icon: { color: "gray.400", fontSize: "18px !important" },
278
337
  },
279
338
  },
280
339
  Popover: {
@@ -285,6 +344,7 @@ const theme = extendTheme({
285
344
  },
286
345
  },
287
346
  },
347
+ Progress: progressTheme,
288
348
  Switch: {
289
349
  defaultProps: {
290
350
  colorScheme: "green",
@@ -22,6 +22,6 @@ export const PasteButton = ({ onValuePasted, text, isIconButton, ...buttonProps
22
22
  return (_jsx(IconButton, { icon: _jsx(FiClipboard, {}), size: "xs", variant: "ghost", colorScheme: "darkBlue", onClick: handlePasteClick, isLoading: isLoading, ...buttonProps, children: text || "Paste" }));
23
23
  }
24
24
  else {
25
- return (_jsx(Button, { leftIcon: _jsx(FiClipboard, {}), size: "xs", colorScheme: "darkBlue", onClick: handlePasteClick, isLoading: isLoading, ...buttonProps, children: text || "Paste" }));
25
+ return (_jsx(Button, { leftIcon: _jsx(FiClipboard, {}), size: "xs", colorScheme: "darkBlue", variant: "outline", onClick: handlePasteClick, isLoading: isLoading, ...buttonProps, children: text || "Paste" }));
26
26
  }
27
27
  };
@@ -0,0 +1,7 @@
1
+ import { KurtosisPackage } from "kurtosis-cloud-indexer-sdk";
2
+ type KurtosisPackageCardHorizontalProps = {
3
+ kurtosisPackage: KurtosisPackage;
4
+ onClick: () => void;
5
+ };
6
+ export declare const KurtosisPackageCardHorizontal: ({ kurtosisPackage, onClick }: KurtosisPackageCardHorizontalProps) => import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Flex, Icon, Text, Tooltip } from "@chakra-ui/react";
3
+ import { IoPlay, IoStar } from "react-icons/io5";
4
+ import { numberSummary } from "../utils";
5
+ import { readablePackageName } from "./utils";
6
+ import { PackageLogo } from "./widgets/PackageLogo";
7
+ import { SaveKurtosisPackageButton } from "./widgets/SaveKurtosisPackageButton";
8
+ export const KurtosisPackageCardHorizontal = ({ kurtosisPackage, onClick }) => {
9
+ var _a;
10
+ return (_jsxs(Flex, { h: "76px", w: "100%", p: "16px", bg: "gray.900", borderColor: "whiteAlpha.300", borderWidth: "1px", borderStyle: "solid", borderRadius: "6px", gap: "16px", alignItems: "center", _hover: { bg: "gray.850", cursor: "pointer" }, onClick: onClick, children: [_jsx(PackageLogo, { kurtosisPackage: kurtosisPackage, h: "44px", w: "44px" }), _jsxs(Flex, { flexDirection: "column", flex: "1", justifyContent: "space-between", children: [_jsxs(Text, { noOfLines: 1, fontSize: "md", children: [readablePackageName(kurtosisPackage.name), _jsx(SaveKurtosisPackageButton, { isIconButton: true, "aria-label": "Toggle button save", kurtosisPackage: kurtosisPackage, flex: "1", variant: "ghost" })] }), _jsxs(Flex, { gap: "12px", fontSize: "sm", children: [_jsx(Text, { as: "span", textTransform: "capitalize", noOfLines: 1, fontSize: "xs", children: ((_a = kurtosisPackage.repositoryMetadata) === null || _a === void 0 ? void 0 : _a.owner.replaceAll("-", " ")) || "Unknown owner" }), _jsx(Tooltip, { label: `This package has ${kurtosisPackage.runCount} stars`, children: _jsxs(Flex, { gap: "4px", alignItems: "center", children: [_jsx(Icon, { as: IoStar }), _jsx(Text, { as: "span", children: numberSummary(Number(kurtosisPackage.stars)) })] }) }), _jsx(Tooltip, { label: `This package has been run ${kurtosisPackage.runCount} times`, children: _jsxs(Flex, { gap: "4px", alignItems: "center", children: [_jsx(Icon, { as: IoPlay }), _jsx(Text, { as: "span", children: numberSummary(kurtosisPackage.runCount) })] }) })] })] })] }));
11
+ };
@@ -1,5 +1,6 @@
1
1
  export * from "./KurtosisPackageCard";
2
2
  export * from "./KurtosisPackageCardGrid";
3
+ export * from "./KurtosisPackageCardHorizontal";
3
4
  export * from "./KurtosisPackageCardRow";
4
5
  export * from "./SavedPackages";
5
6
  export * from "./utils";
@@ -1,5 +1,6 @@
1
1
  export * from "./KurtosisPackageCard";
2
2
  export * from "./KurtosisPackageCardGrid";
3
+ export * from "./KurtosisPackageCardHorizontal";
3
4
  export * from "./KurtosisPackageCardRow";
4
5
  export * from "./SavedPackages";
5
6
  export * from "./utils";
@@ -16,7 +16,7 @@ const SaveKurtosisPackageButtonImpl = ({ kurtosisPackage, ...buttonProps }) => {
16
16
  const { savedPackages, togglePackageSaved } = useSavedPackages();
17
17
  const isPackageSaved = useMemo(() => savedPackages.some((p) => p.name === kurtosisPackage.name), [savedPackages, kurtosisPackage]);
18
18
  const handleClick = useCallback((e) => {
19
- e.preventDefault();
19
+ e.stopPropagation();
20
20
  togglePackageSaved(kurtosisPackage);
21
21
  }, [togglePackageSaved, kurtosisPackage]);
22
22
  return _jsx(SaveKurtosisPackageButtonMemo, { isPackageSaved: isPackageSaved, onClick: handleClick, ...buttonProps });
package/build/index.d.ts CHANGED
@@ -4,7 +4,6 @@ export * from "./CodeEditor";
4
4
  export * from "./CopyButton";
5
5
  export * from "./DataTable";
6
6
  export * from "./DownloadButton";
7
- export * from "./FeatureNotImplementedModal";
8
7
  export * from "./FileDisplay";
9
8
  export * from "./FileSize";
10
9
  export * from "./FileTree";
package/build/index.js CHANGED
@@ -4,7 +4,6 @@ export * from "./CodeEditor";
4
4
  export * from "./CopyButton";
5
5
  export * from "./DataTable";
6
6
  export * from "./DownloadButton";
7
- export * from "./FeatureNotImplementedModal";
8
7
  export * from "./FileDisplay";
9
8
  export * from "./FileSize";
10
9
  export * from "./FileTree";
@@ -3,9 +3,9 @@ import { Box, Flex } from "@chakra-ui/react";
3
3
  import Convert from "ansi-to-html";
4
4
  import parse from "html-react-parser";
5
5
  import { hasAnsi, isDefined } from "../utils";
6
+ import { logFontFamily } from "./constants";
6
7
  import { normalizeLogText } from "./utils";
7
8
  const convert = new Convert();
8
- const logFontFamily = "Menlo, Monaco, Inconsolata, Consolas, Courier, monospace";
9
9
  export const LogLine = ({ timestamp, message, status, highlightPattern, selected }) => {
10
10
  const statusToColor = (status) => {
11
11
  switch (status) {
@@ -17,7 +17,7 @@ export const LogLine = ({ timestamp, message, status, highlightPattern, selected
17
17
  return "white";
18
18
  }
19
19
  };
20
- return (_jsxs(Flex, { p: "2px 0", m: "0 16px", gap: "8px", alignItems: "top", backgroundColor: selected ? "gray.600" : "", children: [isDefined(timestamp) && (_jsx(Box, { as: "pre", whiteSpace: "pre-wrap", fontSize: "xs", lineHeight: "2", fontWeight: 600, fontFamily: logFontFamily, color: "grey", minW: "200px", children: _jsx(_Fragment, { children: timestamp.toLocal().toFormat("yyyy-MM-dd HH:mm:ss ZZZZ") }) })), _jsx(Box, { as: "pre", whiteSpace: "pre-wrap", overflowWrap: "anywhere", fontSize: "xs", lineHeight: "2", fontWeight: 400, fontFamily: logFontFamily, color: statusToColor(status), _focus: { boxShadow: "outline" }, children: _jsx(Message, { message: message, highlightPattern: highlightPattern }) })] }));
20
+ return (_jsxs(Flex, { p: "2px 0", m: "0 16px", gap: "8px", alignItems: "top", backgroundColor: selected ? "gray.600" : "", children: [isDefined(timestamp) && (_jsx(Box, { as: "pre", whiteSpace: "pre-wrap", fontSize: "xs", lineHeight: "2", fontWeight: 600, fontFamily: logFontFamily, color: "grey", minW: "140px", children: _jsx(_Fragment, { children: timestamp.toLocal().toFormat("yyyy-MM-dd HH:mm:ss ZZZZ") }) })), _jsx(Box, { as: "pre", whiteSpace: "pre-wrap", overflowWrap: "anywhere", fontSize: "xs", lineHeight: "2", fontWeight: 400, fontFamily: logFontFamily, color: statusToColor(status), _focus: { boxShadow: "outline" }, children: _jsx(Message, { message: message, highlightPattern: highlightPattern }) })] }));
21
21
  };
22
22
  const Message = ({ message, highlightPattern }) => {
23
23
  if (!isDefined(message)) {
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { SmallCloseIcon } from "@chakra-ui/icons";
3
- import { Button, ButtonGroup, Editable, EditableInput, EditablePreview, Flex, FormControl, FormErrorMessage, FormLabel, Icon, Input, InputGroup, InputLeftElement, InputRightElement, Progress, Switch, Text, Tooltip, } from "@chakra-ui/react";
3
+ import { Button, ButtonGroup, Editable, EditableInput, EditablePreview, Flex, FormControl, FormErrorMessage, FormLabel, Icon, IconButton, Input, InputGroup, InputLeftElement, InputRightElement, Progress, Switch, Text, Tooltip, } from "@chakra-ui/react";
4
4
  import { throttle } from "lodash";
5
5
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
6
6
  import { FiSearch } from "react-icons/fi";
@@ -11,11 +11,13 @@ import { DownloadButton } from "../DownloadButton";
11
11
  import { FindCommand } from "../KeyboardCommands";
12
12
  import { useKeyboardAction } from "../useKeyboardAction";
13
13
  import { isDefined, isNotEmpty, stringifyError, stripAnsi } from "../utils";
14
+ import { logFontFamily } from "./constants";
14
15
  import { LogLine } from "./LogLine";
15
16
  import { normalizeLogText } from "./utils";
16
17
  export const LogViewer = ({ progressPercent, logLines: propsLogLines, ProgressWidget, logsFileName, searchEnabled, copyLogsEnabled, onGetAllLogs, }) => {
17
18
  const virtuosoRef = useRef(null);
18
19
  const [logLines, setLogLines] = useState(propsLogLines);
20
+ const logLinesToShow = useMemo(() => logLines.filter(({ message }) => isDefined(message)), [logLines]);
19
21
  const [userIsScrolling, setUserIsScrolling] = useState(false);
20
22
  const [automaticScroll, setAutomaticScroll] = useState(true);
21
23
  const [searchState, setSearchState] = useState({ type: "init", rawSearchTerm: "" });
@@ -48,7 +50,7 @@ export const LogViewer = ({ progressPercent, logLines: propsLogLines, ProgressWi
48
50
  });
49
51
  }, []);
50
52
  const getLogsValue = () => {
51
- return logLines
53
+ return logLinesToShow
52
54
  .map(({ message }) => message)
53
55
  .filter(isDefined)
54
56
  .map(stripAnsi)
@@ -62,7 +64,7 @@ export const LogViewer = ({ progressPercent, logLines: propsLogLines, ProgressWi
62
64
  useEffect(() => {
63
65
  throttledSetLogLines(propsLogLines);
64
66
  }, [propsLogLines, throttledSetLogLines]);
65
- return (_jsxs(Flex, { flexDirection: "column", h: "100%", w: "100%", flex: "1", borderRadius: "6px", borderColor: "whiteAlpha.300", borderWidth: "1px", borderStyle: "solid", overflow: "clip", children: [_jsxs(Flex, { width: "100%", p: "12px", bg: "gray.850", gap: "16px", children: [searchEnabled && (_jsx(SearchControls, { searchState: searchState, onChangeSearchState: handleSearchStateChange, logLines: logLines })), isDefined(ProgressWidget) && ProgressWidget] }), _jsxs(Flex, { flexDirection: "column", position: "relative", h: "100%", flex: "1", children: [_jsx(Virtuoso, { ref: virtuosoRef, followOutput: automaticScroll, atBottomStateChange: handleBottomStateChange, isScrolling: setUserIsScrolling, style: { height: "100%", flex: "1" }, data: logLines.filter(({ message }) => isDefined(message)), itemContent: (index, line) => (_jsx(LogLine, { ...line, highlightPattern: searchState.type === "success" ? searchState.pattern : undefined, selected: isIndexSelected(index) })) }), isDefined(progressPercent) && (_jsx(Progress, { value: typeof progressPercent === "number" ? progressPercent : progressPercent === "failed" ? 100 : 0, isIndeterminate: progressPercent === "indeterminate", height: "4px", colorScheme: progressPercent === "failed" ? "red.500" : "kurtosisGreen" }))] }), _jsxs(Flex, { alignItems: "space-between", width: "100%", p: "12px", bg: "gray.850", children: [_jsxs(FormControl, { display: "flex", alignItems: "center", children: [_jsx(Switch, { isChecked: automaticScroll, onChange: handleAutomaticScrollChange, size: "sm" }), _jsx(FormLabel, { mb: "0", marginInlineStart: 3, fontSize: "sm", children: "Automatic Scroll" })] }), _jsxs(ButtonGroup, { children: [copyLogsEnabled && (_jsx(CopyButton, { contentName: "logs", valueToCopy: getLogsValue, size: "sm", isDisabled: logLines.length === 0, isIconButton: true, "aria-label": "Copy logs", color: "gray.100" })), _jsx(DownloadButton, { valueToDownload: onGetAllLogs || getLogsValue, size: "sm", fileName: logsFileName || `logs.txt`, isDisabled: logLines.length === 0, isIconButton: true, "aria-label": "Download logs", color: "gray.100" })] })] })] }));
67
+ return (_jsxs(Flex, { flexDirection: "column", h: "100%", w: "100%", flex: "1", borderRadius: "6px", borderColor: "whiteAlpha.300", borderWidth: "1px", borderStyle: "solid", overflow: "clip", children: [_jsxs(Flex, { width: "100%", p: "12px", bg: "gray.850", gap: "16px", children: [searchEnabled && (_jsx(SearchControls, { searchState: searchState, onChangeSearchState: handleSearchStateChange, logLines: logLines })), isDefined(ProgressWidget) && ProgressWidget] }), _jsxs(Flex, { flexDirection: "column", position: "relative", h: "100%", flex: "1", children: [logLinesToShow.length === 0 ? (_jsx(Flex, { justifyContent: "center", alignItems: "center", fontSize: "sm", lineHeight: "2", fontWeight: 400, flex: "1", fontFamily: logFontFamily, children: "No logs to display" })) : (_jsx(Virtuoso, { ref: virtuosoRef, followOutput: automaticScroll, atBottomStateChange: handleBottomStateChange, isScrolling: setUserIsScrolling, style: { height: "100%", flex: "1" }, data: logLinesToShow, itemContent: (index, line) => (_jsx(LogLine, { ...line, highlightPattern: searchState.type === "success" ? searchState.pattern : undefined, selected: isIndexSelected(index) })) })), isDefined(progressPercent) && (_jsx(Progress, { value: typeof progressPercent === "number" ? progressPercent : progressPercent === "failed" ? 100 : 0, isIndeterminate: progressPercent === "indeterminate", height: "4px", colorScheme: progressPercent === "failed" ? "red" : progressPercent === 100 ? "kurtosisGreen" : "blue" }))] }), _jsxs(Flex, { alignItems: "space-between", width: "100%", p: "12px", bg: "gray.850", children: [_jsxs(FormControl, { display: "flex", alignItems: "center", children: [_jsx(Switch, { isChecked: automaticScroll, onChange: handleAutomaticScrollChange, size: "sm" }), _jsx(FormLabel, { mb: "0", marginInlineStart: 3, fontSize: "sm", children: "Automatic Scroll" })] }), _jsxs(ButtonGroup, { children: [copyLogsEnabled && (_jsx(CopyButton, { contentName: "logs", valueToCopy: getLogsValue, size: "sm", isDisabled: logLines.length === 0, isIconButton: true, "aria-label": "Copy logs", color: "gray.100" })), _jsx(DownloadButton, { valueToDownload: onGetAllLogs || getLogsValue, size: "sm", fileName: logsFileName || `logs.txt`, isDisabled: logLines.length === 0, isIconButton: true, "aria-label": "Download logs", color: "gray.100" })] })] })] }));
66
68
  };
67
69
  const SearchControls = ({ searchState, onChangeSearchState, logLines }) => {
68
70
  const searchRef = useRef(null);
@@ -164,6 +166,6 @@ const SearchControls = ({ searchState, onChangeSearchState, logLines }) => {
164
166
  return (_jsx(Button, { bg: "gray.650", color: "gray.150", leftIcon: _jsx(FiSearch, {}), rightIcon: _jsx(FindCommand, {}), variant: "solid", onClick: () => setShowSearchForm(true), children: "Search" }));
165
167
  }
166
168
  else {
167
- return (_jsxs(FormControl, { isInvalid: searchState.type === "error", children: [_jsxs(Flex, { gap: "16px", alignItems: "center", children: [_jsxs(InputGroup, { size: "md", width: "296px", bg: "gray.650", color: "gray.150", variant: "filled", borderRadius: "6px", children: [_jsx(InputLeftElement, { pointerEvents: "none", children: _jsx(Icon, { as: FiSearch, color: "gray.100" }) }), _jsx(Input, { autoFocus: true, ref: searchRef, value: searchState.rawSearchTerm, onChange: handleOnChange, placeholder: "Search" }), searchState.type !== "init" && (_jsx(InputRightElement, { children: _jsx(SmallCloseIcon, { onClick: handleClearSearch }) }))] }), _jsxs(ButtonGroup, { children: [_jsx(Button, { size: "sm", ml: 2, onClick: handlePriorMatchClick, isDisabled: searchState.type !== "success" || searchState.searchMatchesIndices.length === 0, colorScheme: "darkBlue", leftIcon: _jsx(MdArrowBackIosNew, {}), children: "Previous" }), _jsx(Button, { size: "sm", ml: 2, onClick: handleNextMatchClick, isDisabled: searchState.type !== "success" || searchState.searchMatchesIndices.length === 0, colorScheme: "darkBlue", rightIcon: _jsx(MdArrowForwardIos, {}), children: "Next" })] }), searchState.rawSearchTerm.length > 0 && (_jsx(Flex, { ml: 2, alignItems: "center", children: searchState.type === "success" && (_jsxs(Text, { align: "left", color: searchState.searchMatchesIndices.length === 0 ? "red" : "kurtosisGreen.400", children: [searchState.searchMatchesIndices.length > 0 && searchState.currentSearchIndex !== undefined && (_jsxs("span", { children: [_jsxs(Editable, { display: "inline", p: 0, m: "0 4px 0 0", size: "sm", value: `${searchState.currentSearchIndex + 1}`, onChange: handleIndexInputChange, children: [_jsx(Tooltip, { label: "Click to edit", shouldWrapChildren: true, children: _jsx(EditablePreview, {}) }), _jsx(EditableInput, { p: 1, width: "50px" })] }), _jsx(_Fragment, { children: "/ " })] })), _jsxs("span", { children: [searchState.searchMatchesIndices.length, " matches"] })] })) }))] }), searchState.type === "error" && _jsx(FormErrorMessage, { children: searchState.error })] }));
169
+ return (_jsxs(FormControl, { isInvalid: searchState.type === "error", children: [_jsxs(Flex, { gap: "16px", alignItems: "center", children: [_jsxs(InputGroup, { size: "md", width: "296px", color: "gray.150", variant: "filled", borderRadius: "6px", children: [_jsx(InputLeftElement, { pointerEvents: "none", children: _jsx(Icon, { as: FiSearch, color: "gray.100" }) }), _jsx(Input, { autoFocus: true, ref: searchRef, value: searchState.rawSearchTerm, onChange: handleOnChange, placeholder: "Search", _dark: { bg: "gray.650" } }), searchState.type !== "init" && (_jsx(InputRightElement, { children: _jsx(IconButton, { variant: "ghost", icon: _jsx(SmallCloseIcon, {}), size: "sm", onClick: handleClearSearch, "aria-label": "Clear search" }) }))] }), _jsxs(ButtonGroup, { size: "xs", colorScheme: "darkBlue", variant: "outline", children: [_jsx(Button, { ml: 2, onClick: handlePriorMatchClick, isDisabled: searchState.type !== "success" || searchState.searchMatchesIndices.length === 0, leftIcon: _jsx(MdArrowBackIosNew, {}), children: "Previous" }), _jsx(Button, { ml: 2, onClick: handleNextMatchClick, isDisabled: searchState.type !== "success" || searchState.searchMatchesIndices.length === 0, rightIcon: _jsx(MdArrowForwardIos, {}), children: "Next" })] }), searchState.rawSearchTerm.length > 0 && (_jsx(Flex, { alignItems: "center", children: searchState.type === "success" && (_jsxs(Text, { align: "left", fontSize: "xs", fontWeight: "semibold", children: [searchState.searchMatchesIndices.length > 0 && searchState.currentSearchIndex !== undefined && (_jsxs("span", { children: [_jsxs(Editable, { display: "inline", borderWidth: "1px", p: "2px 6px", borderColor: "gray.500", borderRadius: "6px", size: "sm", value: `${searchState.currentSearchIndex + 1}`, onChange: handleIndexInputChange, children: [_jsx(Tooltip, { label: "Click to edit", shouldWrapChildren: true, children: _jsx(EditablePreview, {}) }), _jsx(EditableInput, { width: "50px" })] }), _jsx(_Fragment, { children: " of " })] })), _jsxs("span", { children: [searchState.searchMatchesIndices.length, " matches"] })] })) }))] }), searchState.type === "error" && _jsx(FormErrorMessage, { children: searchState.error })] }));
168
170
  }
169
171
  };
@@ -0,0 +1 @@
1
+ export declare const logFontFamily = "Menlo, Monaco, Inconsolata, Consolas, Courier, monospace";
@@ -0,0 +1 @@
1
+ export const logFontFamily = "Menlo, Monaco, Inconsolata, Consolas, Courier, monospace";
@@ -16,9 +16,9 @@ const baseStyleHelperText = defineStyle({
16
16
  _dark: {
17
17
  [$fg.variable]: "colors.whiteAlpha.600",
18
18
  },
19
- color: $fg.reference,
19
+ color: "gray.100",
20
20
  lineHeight: "normal",
21
- fontSize: "sm",
21
+ fontSize: "xs",
22
22
  });
23
23
  const baseStyle = definePartsStyle({
24
24
  container: {
@@ -0,0 +1,30 @@
1
+ export declare const progressTheme: {
2
+ baseStyle?: ((props: import("@chakra-ui/styled-system").StyleFunctionProps) => {
3
+ label: {
4
+ lineHeight: string;
5
+ fontSize: string;
6
+ fontWeight: string;
7
+ color: string;
8
+ };
9
+ filledTrack: any;
10
+ track: {
11
+ bg: string;
12
+ };
13
+ }) | undefined;
14
+ sizes?: {
15
+ [key: string]: import("@chakra-ui/styled-system").PartsStyleInterpolation<{
16
+ keys: ("label" | "track" | "filledTrack")[];
17
+ }>;
18
+ } | undefined;
19
+ variants?: {
20
+ [key: string]: import("@chakra-ui/styled-system").PartsStyleInterpolation<{
21
+ keys: ("label" | "track" | "filledTrack")[];
22
+ }>;
23
+ } | undefined;
24
+ defaultProps?: {
25
+ size?: string | number | undefined;
26
+ variant?: string | number | undefined;
27
+ colorScheme?: string | undefined;
28
+ } | undefined;
29
+ parts: ("label" | "track" | "filledTrack")[];
30
+ };
@@ -0,0 +1,46 @@
1
+ import { progressAnatomy as parts } from "@chakra-ui/anatomy";
2
+ import { createMultiStyleConfigHelpers, defineStyle } from "@chakra-ui/styled-system";
3
+ import { generateStripe, getColor, mode } from "@chakra-ui/theme-tools";
4
+ const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(parts.keys);
5
+ const filledStyle = defineStyle((props) => {
6
+ const { colorScheme: c, theme: t, isIndeterminate, hasStripe } = props;
7
+ const stripeStyle = mode(generateStripe(), generateStripe("1rem", "rgba(0,0,0,0.1)"))(props);
8
+ const bgColor = mode(`${c}.500`, `${c}.400`)(props);
9
+ const gradient = `linear-gradient(
10
+ to right,
11
+ transparent 0%,
12
+ ${getColor(t, bgColor)} 50%,
13
+ transparent 100%
14
+ )`;
15
+ const addStripe = !isIndeterminate && hasStripe;
16
+ return {
17
+ ...(addStripe && stripeStyle),
18
+ ...(isIndeterminate ? { bgImage: gradient } : { bgColor }),
19
+ };
20
+ });
21
+ const baseStyleLabel = defineStyle({
22
+ lineHeight: "1",
23
+ fontSize: "0.25em",
24
+ fontWeight: "bold",
25
+ color: "white",
26
+ });
27
+ const baseStyleTrack = defineStyle((props) => {
28
+ return {
29
+ bg: `${props.colorScheme}.100`,
30
+ };
31
+ });
32
+ const baseStyleFilledTrack = defineStyle((props) => {
33
+ return {
34
+ transitionProperty: "common",
35
+ transitionDuration: "slow",
36
+ ...filledStyle(props),
37
+ };
38
+ });
39
+ const baseStyle = definePartsStyle((props) => ({
40
+ label: baseStyleLabel,
41
+ filledTrack: baseStyleFilledTrack(props),
42
+ track: baseStyleTrack(props),
43
+ }));
44
+ export const progressTheme = defineMultiStyleConfig({
45
+ baseStyle,
46
+ });
@@ -9,7 +9,25 @@ export declare const tabsTheme: {
9
9
  }>;
10
10
  } | undefined;
11
11
  variants?: {
12
- line: (props: StyleFunctionProps) => {
12
+ line: {
13
+ root: {
14
+ display: string;
15
+ flexDirection: string;
16
+ };
17
+ tablist: {
18
+ borderBottom: string;
19
+ };
20
+ tab: {
21
+ color: string;
22
+ };
23
+ tabpanels: {
24
+ flex: string;
25
+ borderRadius: string;
26
+ borderColor: string;
27
+ borderWidth: string;
28
+ };
29
+ };
30
+ kurtosisHeaderLine: (props: StyleFunctionProps) => {
13
31
  root: {
14
32
  display: string;
15
33
  flexDirection: string;
@@ -49,7 +67,7 @@ export declare const tabsTheme: {
49
67
  } | undefined;
50
68
  defaultProps?: {
51
69
  size?: string | number | undefined;
52
- variant?: "line" | undefined;
70
+ variant?: "line" | "kurtosisHeaderLine" | undefined;
53
71
  colorScheme?: string | undefined;
54
72
  } | undefined;
55
73
  parts: ("tab" | "tablist" | "tabpanel" | "tabpanels" | "root" | "indicator")[];
@@ -8,7 +8,25 @@ export const tabsTheme = defineMultiStyleConfig({
8
8
  colorScheme: "kurtosisGreen",
9
9
  },
10
10
  variants: {
11
- line: (props) => ({
11
+ line: {
12
+ root: {
13
+ display: "flex",
14
+ flexDirection: "column",
15
+ },
16
+ tablist: {
17
+ borderBottom: "none",
18
+ },
19
+ tab: {
20
+ color: "gray.100",
21
+ },
22
+ tabpanels: {
23
+ flex: "1",
24
+ borderRadius: "0 6px 6px 6px",
25
+ borderColor: "gray.500",
26
+ borderWidth: "1px",
27
+ },
28
+ },
29
+ kurtosisHeaderLine: (props) => ({
12
30
  root: {
13
31
  display: "flex",
14
32
  flexDirection: "column",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kurtosis-ui-components",
3
- "version": "0.85.55",
3
+ "version": "0.86.0",
4
4
  "private": false,
5
5
  "main": "build/index",
6
6
  "description": "This repo contains components used by Kurtosis UI applications.",
@@ -35,7 +35,7 @@
35
35
  "kurtosis-cloud-indexer-sdk": "^0.0.2",
36
36
  "react-error-boundary": "^4.0.11",
37
37
  "react-markdown": "^9.0.0",
38
- "react-router-dom": "^6.17.0",
38
+ "react-router-dom": "^6.21.1",
39
39
  "react-virtuoso": "^4.6.2",
40
40
  "streamsaver": "^2.0.6",
41
41
  "yaml": "^2.3.4"
@@ -1,9 +0,0 @@
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 {};
@@ -1,9 +0,0 @@
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
- };