@wandelbots/wandelbots-js-react-components 2.35.0 → 2.36.0-pr.feature-design-pass.378.e01a6c5
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 +141 -151
- package/dist/components/CopyableText.d.ts +3 -2
- package/dist/components/CopyableText.d.ts.map +1 -1
- package/dist/components/SelectableFab.d.ts +2 -1
- package/dist/components/SelectableFab.d.ts.map +1 -1
- package/dist/components/TabBar.d.ts +2 -0
- package/dist/components/TabBar.d.ts.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +221 -223
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/components/AppHeader.tsx +1 -1
- package/src/components/CopyableText.tsx +70 -73
- package/src/components/LogViewer.tsx +1 -1
- package/src/components/ProgramControl.tsx +4 -4
- package/src/components/SelectableFab.tsx +14 -15
- package/src/components/TabBar.tsx +12 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wandelbots/wandelbots-js-react-components",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.36.0-pr.feature-design-pass.378.e01a6c5",
|
|
4
4
|
"description": "React UI toolkit for building applications on top of the Wandelbots platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
60
60
|
"@rollup/plugin-terser": "^0.4.4",
|
|
61
61
|
"@rollup/plugin-typescript": "^12.1.2",
|
|
62
|
-
"@storybook/addon-docs": "^9.1.
|
|
63
|
-
"@storybook/react-vite": "^9.1.
|
|
62
|
+
"@storybook/addon-docs": "^9.1.3",
|
|
63
|
+
"@storybook/react-vite": "^9.1.3",
|
|
64
64
|
"@storybook/test-runner": "^0.23.0",
|
|
65
65
|
"@svgr/rollup": "^8.1.0",
|
|
66
66
|
"@testing-library/jest-dom": "^6.6.3",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@vitejs/plugin-react": "^4.3.4",
|
|
73
73
|
"@wandelbots/nova-js": "^2.1.0",
|
|
74
74
|
"add": "^2.0.6",
|
|
75
|
-
"eslint-plugin-storybook": "^9.1.
|
|
75
|
+
"eslint-plugin-storybook": "^9.1.3",
|
|
76
76
|
"glob": "^11.0.1",
|
|
77
77
|
"http-server": "^14.1.1",
|
|
78
78
|
"husky": "^9.1.7",
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
96
96
|
"rollup-plugin-postcss": "^4.0.2",
|
|
97
97
|
"semantic-release": "^24.2.3",
|
|
98
|
-
"storybook": "^9.1.
|
|
98
|
+
"storybook": "^9.1.3",
|
|
99
99
|
"storybook-preset-inline-svg": "^1.0.1",
|
|
100
100
|
"three": "^0.174.0",
|
|
101
101
|
"three-stdlib": "^2.35.14",
|
|
@@ -85,7 +85,7 @@ export const AppHeader = externalizeComponent(
|
|
|
85
85
|
...sx,
|
|
86
86
|
}}
|
|
87
87
|
>
|
|
88
|
-
<Toolbar sx={{ minHeight: "
|
|
88
|
+
<Toolbar sx={{ minHeight: "62px !important" }}>
|
|
89
89
|
{/* App Icon */}
|
|
90
90
|
<Box sx={{ mr: 2, display: "flex", alignItems: "center" }}>
|
|
91
91
|
{appIcon}
|
|
@@ -1,87 +1,84 @@
|
|
|
1
1
|
import { Stack, Tooltip, Typography, useTheme } from "@mui/material"
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect, useState } from "react"
|
|
3
3
|
|
|
4
|
-
export const CopyableText =
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
ref: React.ForwardedRef<HTMLDivElement>,
|
|
14
|
-
) => {
|
|
15
|
-
const theme = useTheme()
|
|
16
|
-
const [tooltipOpen, setTooltipOpen] = useState(false)
|
|
4
|
+
export const CopyableText = (props: {
|
|
5
|
+
label?: string
|
|
6
|
+
value: string
|
|
7
|
+
ref?: React.Ref<HTMLDivElement>
|
|
8
|
+
}) => {
|
|
9
|
+
const { value, ref } = props
|
|
10
|
+
// Note: label prop is available but not currently used in the component
|
|
11
|
+
const theme = useTheme()
|
|
12
|
+
const [tooltipOpen, setTooltipOpen] = useState(false)
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
async function onCopyText(): Promise<boolean> {
|
|
15
|
+
if (!ref || !("current" in ref)) {
|
|
16
|
+
console.warn("No copy target found")
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
await navigator.clipboard.writeText(value)
|
|
21
|
+
console.log("Copied!")
|
|
22
|
+
setTooltipOpen(true)
|
|
23
|
+
return true
|
|
24
|
+
} catch (err) {
|
|
25
|
+
// Direct clipboard copy is not available in non-secure contexts
|
|
26
|
+
console.error(err)
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
// Let's fall back to selecting the text so the user can manually copy easily
|
|
29
|
+
const selection = window.getSelection()
|
|
30
|
+
if (selection && ref && "current" in ref && ref.current) {
|
|
34
31
|
const range = document.createRange()
|
|
35
|
-
range.selectNodeContents(ref.current
|
|
32
|
+
range.selectNodeContents(ref.current)
|
|
36
33
|
selection.removeAllRanges()
|
|
37
34
|
selection.addRange(range)
|
|
38
35
|
}
|
|
39
|
-
return false
|
|
40
36
|
}
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (!tooltipOpen) {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
const timeoutId = setTimeout(() => setTooltipOpen(false), 3000)
|
|
45
|
+
return () => {
|
|
46
|
+
timeoutId ? clearTimeout(timeoutId) : {}
|
|
47
|
+
}
|
|
48
|
+
}, [tooltipOpen])
|
|
51
49
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
return (
|
|
51
|
+
<Tooltip open={tooltipOpen} title="Copied!">
|
|
52
|
+
<Stack
|
|
53
|
+
justifyContent="center"
|
|
54
|
+
sx={{
|
|
55
|
+
height: "100%",
|
|
56
|
+
boxSizing: "border-box",
|
|
57
|
+
padding: "6px 12px",
|
|
58
|
+
background: theme.palette.backgroundPaperElevation?.[8],
|
|
59
|
+
borderRadius: "10px",
|
|
60
|
+
minWidth: "0",
|
|
61
|
+
cursor: "pointer",
|
|
62
|
+
}}
|
|
63
|
+
onClick={() => onCopyText()}
|
|
64
|
+
>
|
|
65
|
+
<Typography
|
|
66
|
+
ref={ref}
|
|
67
|
+
align="center"
|
|
56
68
|
sx={{
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
pointerEvents: "none",
|
|
70
|
+
fontSize: "12px",
|
|
71
|
+
color: theme.palette.text.primary,
|
|
72
|
+
whiteSpace: "nowrap",
|
|
73
|
+
minWidth: 0,
|
|
74
|
+
textOverflow: "ellipsis",
|
|
75
|
+
width: "100%",
|
|
76
|
+
overflow: "hidden",
|
|
64
77
|
}}
|
|
65
|
-
onClick={() => onCopyText()}
|
|
66
78
|
>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
color: theme.palette.text.primary,
|
|
74
|
-
whiteSpace: "nowrap",
|
|
75
|
-
minWidth: 0,
|
|
76
|
-
textOverflow: "ellipsis",
|
|
77
|
-
width: "100%",
|
|
78
|
-
overflow: "hidden",
|
|
79
|
-
}}
|
|
80
|
-
>
|
|
81
|
-
{value}
|
|
82
|
-
</Typography>
|
|
83
|
-
</Stack>
|
|
84
|
-
</Tooltip>
|
|
85
|
-
)
|
|
86
|
-
},
|
|
87
|
-
)
|
|
79
|
+
{value}
|
|
80
|
+
</Typography>
|
|
81
|
+
</Stack>
|
|
82
|
+
</Tooltip>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
@@ -45,7 +45,7 @@ export const createLogMessage = (
|
|
|
45
45
|
level: LogLevel,
|
|
46
46
|
id?: string,
|
|
47
47
|
): LogMessage => ({
|
|
48
|
-
id: id || `${Date.now()}-${Math.random().toString(36).
|
|
48
|
+
id: id || `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
|
|
49
49
|
timestamp: new Date(),
|
|
50
50
|
message,
|
|
51
51
|
level,
|
|
@@ -173,9 +173,9 @@ export const ProgramControl = externalizeComponent(
|
|
|
173
173
|
}
|
|
174
174
|
onClick={config.onClick}
|
|
175
175
|
sx={{
|
|
176
|
-
width: "
|
|
177
|
-
height: "
|
|
178
|
-
borderRadius: "
|
|
176
|
+
width: "88px",
|
|
177
|
+
height: "88px",
|
|
178
|
+
borderRadius: "88px",
|
|
179
179
|
backgroundColor: config.color,
|
|
180
180
|
opacity:
|
|
181
181
|
config.enabled &&
|
|
@@ -197,7 +197,7 @@ export const ProgramControl = externalizeComponent(
|
|
|
197
197
|
backgroundColor: config.color,
|
|
198
198
|
opacity: 0.3,
|
|
199
199
|
},
|
|
200
|
-
minWidth: "
|
|
200
|
+
minWidth: "88px",
|
|
201
201
|
flexShrink: 0,
|
|
202
202
|
}}
|
|
203
203
|
>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Fab,
|
|
2
|
-
import { forwardRef, type Ref } from "react"
|
|
1
|
+
import { Fab, type FabProps, styled } from "@mui/material"
|
|
3
2
|
|
|
4
3
|
const StyledSelectableFab = styled(Fab, {
|
|
5
4
|
shouldForwardProp: (prop) => prop !== "selected",
|
|
@@ -34,18 +33,18 @@ const StyledSelectableFab = styled(Fab, {
|
|
|
34
33
|
|
|
35
34
|
type CodeFabProps = {
|
|
36
35
|
selected?: boolean
|
|
36
|
+
ref?: React.Ref<HTMLButtonElement>
|
|
37
37
|
} & Omit<FabProps, "variant" | "color">
|
|
38
38
|
|
|
39
|
-
export const SelectableFab =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
39
|
+
export const SelectableFab = (props: CodeFabProps) => {
|
|
40
|
+
const { ref, ...otherProps } = props
|
|
41
|
+
return (
|
|
42
|
+
<StyledSelectableFab
|
|
43
|
+
ref={ref}
|
|
44
|
+
selected={props.selected}
|
|
45
|
+
{...otherProps}
|
|
46
|
+
color={"secondary"}
|
|
47
|
+
variant="circular"
|
|
48
|
+
/>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
@@ -24,6 +24,8 @@ export interface TabBarProps {
|
|
|
24
24
|
onTabChange?: (index: number) => void
|
|
25
25
|
/** Additional styling */
|
|
26
26
|
sx?: SxProps
|
|
27
|
+
/** Ref to the root container element */
|
|
28
|
+
ref?: React.Ref<HTMLDivElement>
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
interface TabPanelProps {
|
|
@@ -55,7 +57,7 @@ function TabPanel(props: TabPanelProps) {
|
|
|
55
57
|
*/
|
|
56
58
|
export const TabBar = externalizeComponent(
|
|
57
59
|
observer((props: TabBarProps) => {
|
|
58
|
-
const { items, defaultActiveTab = 0, onTabChange, sx } = props
|
|
60
|
+
const { items, defaultActiveTab = 0, onTabChange, sx, ref } = props
|
|
59
61
|
const [activeTab, setActiveTab] = useState(defaultActiveTab)
|
|
60
62
|
|
|
61
63
|
const handleTabChange = (
|
|
@@ -68,17 +70,17 @@ export const TabBar = externalizeComponent(
|
|
|
68
70
|
|
|
69
71
|
return (
|
|
70
72
|
<Box
|
|
73
|
+
ref={ref}
|
|
71
74
|
sx={{ height: "100%", display: "flex", flexDirection: "column", ...sx }}
|
|
72
75
|
>
|
|
73
76
|
{/* Tabs */}
|
|
74
|
-
<Box sx={{ px:
|
|
77
|
+
<Box sx={{ px: 0, py: 0 }}>
|
|
75
78
|
<Tabs
|
|
76
79
|
value={activeTab}
|
|
77
80
|
onChange={handleTabChange}
|
|
78
81
|
sx={{
|
|
79
|
-
minHeight: "
|
|
82
|
+
minHeight: "32px",
|
|
80
83
|
backgroundColor: "transparent",
|
|
81
|
-
mt: 3,
|
|
82
84
|
"& .MuiTabs-indicator": {
|
|
83
85
|
display: "none", // Hide the default indicator
|
|
84
86
|
},
|
|
@@ -95,16 +97,15 @@ export const TabBar = externalizeComponent(
|
|
|
95
97
|
iconPosition="start"
|
|
96
98
|
disableRipple
|
|
97
99
|
sx={{
|
|
98
|
-
minHeight: "
|
|
99
|
-
|
|
100
|
-
padding: "
|
|
101
|
-
borderRadius: "
|
|
100
|
+
minHeight: "32px",
|
|
101
|
+
height: "32px",
|
|
102
|
+
padding: "0px 10px",
|
|
103
|
+
borderRadius: "12px",
|
|
102
104
|
backgroundColor: (theme) =>
|
|
103
105
|
theme.palette.backgroundPaperElevation?.[11] || "#32344B",
|
|
104
106
|
color: "text.primary",
|
|
105
107
|
opacity: activeTab === index ? 1 : 0.38,
|
|
106
|
-
|
|
107
|
-
fontWeight: 500,
|
|
108
|
+
fontSize: "13px",
|
|
108
109
|
transition: "all 0.2s ease-in-out",
|
|
109
110
|
"&:hover": {
|
|
110
111
|
opacity: activeTab === index ? 1 : 0.6,
|
|
@@ -128,7 +129,7 @@ export const TabBar = externalizeComponent(
|
|
|
128
129
|
</Box>
|
|
129
130
|
|
|
130
131
|
{/* Border line */}
|
|
131
|
-
<Box sx={{
|
|
132
|
+
<Box sx={{ mt: "32px", borderBottom: 1, borderColor: "divider" }} />
|
|
132
133
|
|
|
133
134
|
{/* Tab Content */}
|
|
134
135
|
<Box sx={{ flex: 1, overflow: "auto" }}>
|