@wandelbots/wandelbots-js-react-components 2.54.0 → 2.54.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wandelbots/wandelbots-js-react-components",
3
- "version": "2.54.0",
3
+ "version": "2.54.1",
4
4
  "description": "React UI toolkit for building applications on top of the Wandelbots platform",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -59,9 +59,9 @@
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.6",
63
- "@storybook/react-vite": "^9.1.6",
64
- "@storybook/test-runner": "^0.23.0",
62
+ "@storybook/addon-docs": "^10.0.1",
63
+ "@storybook/react-vite": "^10.0.1",
64
+ "@storybook/test-runner": "^0.24.1",
65
65
  "@svgr/rollup": "^8.1.0",
66
66
  "@testing-library/jest-dom": "^6.6.3",
67
67
  "@testing-library/react": "^16.3.0",
@@ -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.6",
75
+ "eslint-plugin-storybook": "^10.0.1",
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.6",
98
+ "storybook": "^10.0.1",
99
99
  "storybook-preset-inline-svg": "^1.0.1",
100
100
  "three": "^0.174.0",
101
101
  "three-stdlib": "^2.35.14",
@@ -1,5 +1,5 @@
1
1
  import type { SxProps } from "@mui/material"
2
- import { Box, Tab, Tabs } from "@mui/material"
2
+ import { Badge, Box, Tab, Tabs } from "@mui/material"
3
3
  import { observer } from "mobx-react-lite"
4
4
  import { useEffect, useState } from "react"
5
5
  import { externalizeComponent } from "../externalizeComponent"
@@ -89,6 +89,8 @@ export const TabBar = externalizeComponent(
89
89
  const [uncontrolledActiveTab, setUncontrolledActiveTab] =
90
90
  useState(defaultActiveTab)
91
91
 
92
+ const currentValue = isControlled ? activeTab! : uncontrolledActiveTab
93
+
92
94
  // Keep uncontrolled state in range when items change
93
95
  useEffect(() => {
94
96
  if (isControlled) return
@@ -101,8 +103,6 @@ export const TabBar = externalizeComponent(
101
103
  }
102
104
  }, [items.length, isControlled, uncontrolledActiveTab])
103
105
 
104
- const currentValue = isControlled ? activeTab! : uncontrolledActiveTab
105
-
106
106
  const handleTabChange = (
107
107
  _event: React.SyntheticEvent,
108
108
  newValue: number,
@@ -124,6 +124,7 @@ export const TabBar = externalizeComponent(
124
124
  px: 0,
125
125
  py: 0,
126
126
  overflow: "visible",
127
+ position: "relative",
127
128
  // Extra padding to prevent badge clipping
128
129
  // Top: accommodates badge positioned at top: -6px with 20px height
129
130
  // Right: accommodates badge positioned at right: -8px with 20px width
@@ -158,7 +159,7 @@ export const TabBar = externalizeComponent(
158
159
  {items.map((item, index) => {
159
160
  // Helper functions for badge logic
160
161
  const getBadgeContent = () => {
161
- if (!item.badge) return ""
162
+ if (!item.badge) return undefined
162
163
  const content = item.badge.content
163
164
  const max = item.badge.max
164
165
 
@@ -167,7 +168,7 @@ export const TabBar = externalizeComponent(
167
168
  return `${max}+`
168
169
  }
169
170
 
170
- return String(content)
171
+ return content
171
172
  }
172
173
 
173
174
  const shouldShowBadge = () => {
@@ -184,13 +185,20 @@ export const TabBar = externalizeComponent(
184
185
  const badgeContent = getBadgeContent()
185
186
  const showBadge = shouldShowBadge()
186
187
 
187
- return (
188
+ const handleTabClick = () => {
189
+ if (!isControlled) {
190
+ setUncontrolledActiveTab(index)
191
+ }
192
+ onTabChange?.(index)
193
+ }
194
+
195
+ const tab = (
188
196
  <Tab
189
- key={item.id}
190
197
  label={item.label}
191
198
  icon={item.icon}
192
199
  iconPosition="start"
193
200
  disableRipple
201
+ onClick={handleTabClick}
194
202
  sx={{
195
203
  minHeight: "32px",
196
204
  height: "32px",
@@ -203,6 +211,7 @@ export const TabBar = externalizeComponent(
203
211
  fontSize: "13px",
204
212
  transition: "all 0.2s ease-in-out",
205
213
  position: "relative",
214
+ overflow: "visible",
206
215
  "&:hover": {
207
216
  opacity: currentValue === index ? 1 : 0.6,
208
217
  },
@@ -219,46 +228,40 @@ export const TabBar = externalizeComponent(
219
228
  "&:active": {
220
229
  transform: "none",
221
230
  },
222
- ...(showBadge && {
223
- "&::after": {
224
- content: `"${badgeContent}"`,
225
- position: "absolute",
226
- // Position badge in top-right corner, extending outside tab bounds
227
- top: -6, // Positions badge above the tab
228
- right: -8, // Positions badge to the right of the tab
229
- // Badge sizing - MUI Badge standard small size
230
- minWidth: "20px", // Min width for single digits
231
- height: "20px", // Fixed height for consistent appearance
232
- borderRadius: "10px", // Half of height for circular shape
233
- backgroundColor: (theme) => {
234
- const colors = {
235
- error: theme.palette.error.main,
236
- info: theme.palette.info.main,
237
- success: theme.palette.success.main,
238
- warning: theme.palette.warning.main,
239
- primary: theme.palette.primary.main,
240
- secondary: theme.palette.secondary.main,
241
- default: theme.palette.grey[500],
242
- }
243
- return (
244
- colors[item.badge?.color || "error"] || colors.error
245
- )
246
- },
247
- color: "white",
248
- fontSize: "12px", // Readable size for badge content
249
- fontWeight: 600, // Semi-bold for better visibility
250
- display: "flex",
251
- alignItems: "center",
252
- justifyContent: "center",
253
- padding: "2px 6px", // Horizontal padding for wider content (e.g., "99+")
254
- zIndex: 1,
255
- pointerEvents: "none", // Allow clicks to pass through to tab
256
- boxShadow: "0 2px 4px rgba(0,0,0,0.2)", // Subtle depth
257
- },
258
- }),
259
231
  }}
260
232
  />
261
233
  )
234
+
235
+ if (!showBadge) {
236
+ return (
237
+ <Box key={item.id} sx={{ display: "inline-flex" }}>
238
+ {tab}
239
+ </Box>
240
+ )
241
+ }
242
+
243
+ return (
244
+ <Badge
245
+ key={item.id}
246
+ badgeContent={badgeContent}
247
+ color={item.badge?.color || "error"}
248
+ max={item.badge?.max}
249
+ showZero={item.badge?.showZero}
250
+ anchorOrigin={{
251
+ vertical: "top",
252
+ horizontal: "right",
253
+ }}
254
+ overlap="rectangular"
255
+ sx={{
256
+ "& .MuiBadge-badge": {
257
+ // Ensure badge doesn't inherit tab opacity
258
+ opacity: "1 !important",
259
+ },
260
+ }}
261
+ >
262
+ {tab}
263
+ </Badge>
264
+ )
262
265
  })}
263
266
  </Tabs>
264
267
  </Box>