@dreamtree-org/twreact-ui 1.0.61 → 1.0.63

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/dist/index.js CHANGED
@@ -10430,7 +10430,7 @@ function Switch(props) {
10430
10430
 
10431
10431
  // Container layout: column if top or bottom labels exist, otherwise row
10432
10432
  var containerIsColumn = Boolean(topLabel || bottomLabel);
10433
- var containerClass = [containerIsColumn ? "flex flex-col items-center" : "inline-flex items-center", "gap-2", className].filter(Boolean).join(" ");
10433
+ var containerClass = [containerIsColumn ? "flex flex-col " : "inline-flex items-center", "gap-2", className].filter(Boolean).join(" ");
10434
10434
  var labelOpacityClass = disabled ? "opacity-50" : "";
10435
10435
  return /*#__PURE__*/React.createElement("div", {
10436
10436
  className: containerClass
@@ -15112,23 +15112,39 @@ function LocationPicker(_ref) {
15112
15112
  }, iconButton)));
15113
15113
  }
15114
15114
 
15115
- var _excluded$d = ["items", "collapsed", "onToggle", "className", "logo", "user", "onUserClick", "drawerPosition", "isMobileOpen", "setIsMobileOpen"];
15116
- var Sidebar = function Sidebar(_ref) {
15117
- var _ref$items = _ref.items,
15118
- items = _ref$items === void 0 ? [] : _ref$items,
15119
- _ref$collapsed = _ref.collapsed,
15120
- collapsed = _ref$collapsed === void 0 ? false : _ref$collapsed,
15121
- onToggle = _ref.onToggle,
15122
- className = _ref.className,
15123
- logo = _ref.logo,
15124
- user = _ref.user,
15125
- onUserClick = _ref.onUserClick,
15126
- _ref$drawerPosition = _ref.drawerPosition,
15127
- drawerPosition = _ref$drawerPosition === void 0 ? "left" : _ref$drawerPosition,
15128
- _ref$isMobileOpen = _ref.isMobileOpen,
15129
- isMobileOpen = _ref$isMobileOpen === void 0 ? false : _ref$isMobileOpen,
15130
- setIsMobileOpen = _ref.setIsMobileOpen,
15131
- props = _objectWithoutProperties$1(_ref, _excluded$d);
15115
+ var _excluded$d = ["items", "collapsed", "onToggle", "className", "logo", "user", "onUserClick", "drawerPosition", "isMobileOpen", "setIsMobileOpen", "showCollapsedTooltips", "tooltipOptions"];
15116
+
15117
+ /**
15118
+ * Sidebar component with custom tooltip for collapsed mode.
15119
+ *
15120
+ * Props:
15121
+ * - items: array of { id, label, icon, children?, onClick?, active? }
15122
+ * - collapsed: boolean (desktop collapsed)
15123
+ * - onToggle: function to toggle collapse
15124
+ * - className, logo, user, onUserClick
15125
+ * - drawerPosition: 'left' | 'right'
15126
+ * - isMobileOpen, setIsMobileOpen
15127
+ * - showCollapsedTooltips: boolean (default true)
15128
+ */
15129
+ var Sidebar = function Sidebar(_ref2) {
15130
+ var _ref2$items = _ref2.items,
15131
+ items = _ref2$items === void 0 ? [] : _ref2$items,
15132
+ _ref2$collapsed = _ref2.collapsed,
15133
+ collapsed = _ref2$collapsed === void 0 ? false : _ref2$collapsed,
15134
+ onToggle = _ref2.onToggle,
15135
+ className = _ref2.className,
15136
+ logo = _ref2.logo,
15137
+ user = _ref2.user,
15138
+ onUserClick = _ref2.onUserClick,
15139
+ _ref2$drawerPosition = _ref2.drawerPosition,
15140
+ drawerPosition = _ref2$drawerPosition === void 0 ? "left" : _ref2$drawerPosition,
15141
+ _ref2$isMobileOpen = _ref2.isMobileOpen,
15142
+ isMobileOpen = _ref2$isMobileOpen === void 0 ? false : _ref2$isMobileOpen,
15143
+ setIsMobileOpen = _ref2.setIsMobileOpen,
15144
+ _ref2$showCollapsedTo = _ref2.showCollapsedTooltips,
15145
+ showCollapsedTooltips = _ref2$showCollapsedTo === void 0 ? true : _ref2$showCollapsedTo,
15146
+ tooltipOptions = _ref2.tooltipOptions,
15147
+ props = _objectWithoutProperties$1(_ref2, _excluded$d);
15132
15148
  var _useState = React.useState(new Set()),
15133
15149
  _useState2 = _slicedToArray(_useState, 2),
15134
15150
  expandedItems = _useState2[0],
@@ -15137,19 +15153,14 @@ var Sidebar = function Sidebar(_ref) {
15137
15153
  _useState4 = _slicedToArray(_useState3, 2),
15138
15154
  activeItemId = _useState4[0],
15139
15155
  setActiveItemId = _useState4[1];
15140
-
15141
- // Use props for mobile state, fallback to false
15156
+ var _useState5 = React.useState(null),
15157
+ _useState6 = _slicedToArray(_useState5, 2);
15158
+ _useState6[0];
15159
+ var setHoveredItemId = _useState6[1];
15142
15160
  var mobileOpen = isMobileOpen !== null && isMobileOpen !== void 0 ? isMobileOpen : false;
15143
-
15144
- // Ensure mobile always shows full sidebar (no collapse on mobile)
15145
15161
  var effectiveCollapsed = mobileOpen ? false : collapsed;
15146
15162
  React.useEffect(function () {
15147
- // Prevent body scroll when mobile sidebar is open
15148
- if (mobileOpen) {
15149
- document.body.style.overflow = "hidden";
15150
- } else {
15151
- document.body.style.overflow = "";
15152
- }
15163
+ if (mobileOpen) document.body.style.overflow = "hidden";else document.body.style.overflow = "";
15153
15164
  return function () {
15154
15165
  document.body.style.overflow = "";
15155
15166
  };
@@ -15159,58 +15170,53 @@ var Sidebar = function Sidebar(_ref) {
15159
15170
  if (next.has(itemId)) next["delete"](itemId);else next.add(itemId);
15160
15171
  setExpandedItems(next);
15161
15172
  };
15162
-
15163
- // New helper to expand a single item (replace existing expanded set)
15164
15173
  var expandSingle = function expandSingle(itemId) {
15165
- var next = new Set(expandedItems);
15174
+ var next = new Set();
15166
15175
  next.add(itemId);
15167
15176
  setExpandedItems(next);
15168
15177
  };
15169
15178
  var handleItemClick = function handleItemClick(item) {
15170
15179
  var hasChildren = item.children && item.children.length > 0;
15171
-
15172
- // If item has children and sidebar is collapsed (desktop),
15173
- // uncollapse the sidebar and expand + activate this item.
15174
15180
  if (hasChildren && effectiveCollapsed && !mobileOpen) {
15175
- // Ask parent to toggle collapsed state (uncollapse)
15181
+ // ask parent to uncollapse
15176
15182
  onToggle === null || onToggle === void 0 || onToggle();
15177
-
15178
- // Mark this item active and expanded locally.
15179
- // We don't delay because the parent prop change will re-render; this state persists.
15180
15183
  setActiveItemId(item.id);
15181
15184
  expandSingle(item.id);
15182
15185
  return;
15183
15186
  }
15184
-
15185
- // Normal behavior when not collapsed or on mobile:
15186
15187
  if (hasChildren) {
15187
15188
  toggleExpanded(item.id);
15188
15189
  setActiveItemId(item.id);
15189
15190
  } else {
15190
15191
  var _item$onClick;
15191
- // leaf item: call its onClick and close mobile if needed
15192
15192
  (_item$onClick = item.onClick) === null || _item$onClick === void 0 || _item$onClick.call(item, item);
15193
15193
  setActiveItemId(item.id);
15194
- if (mobileOpen && setIsMobileOpen) {
15195
- setIsMobileOpen(false);
15196
- }
15194
+ if (mobileOpen && setIsMobileOpen) setIsMobileOpen(false);
15197
15195
  }
15198
15196
  };
15199
15197
  var handleUserClick = function handleUserClick() {
15200
15198
  onUserClick === null || onUserClick === void 0 || onUserClick(user);
15201
- // Close mobile sidebar when user is clicked
15202
- if (mobileOpen && setIsMobileOpen) {
15203
- setIsMobileOpen(false);
15204
- }
15199
+ if (mobileOpen && setIsMobileOpen) setIsMobileOpen(false);
15205
15200
  };
15206
15201
  var _renderMenuItem = function renderMenuItem(item) {
15207
15202
  var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
15208
15203
  var hasChildren = item.children && item.children.length > 0;
15209
15204
  var isExpanded = expandedItems.has(item.id);
15210
- // isActive if either the prop says so or we marked it active locally
15211
15205
  var isActive = Boolean(item.active) || activeItemId === item.id;
15206
+ var showTooltipForThis = effectiveCollapsed && level === 0 && showCollapsedTooltips;
15207
+
15208
+ // container needs relative to position tooltip
15212
15209
  return /*#__PURE__*/React.createElement("div", {
15213
- key: item.id
15210
+ key: item.id,
15211
+ className: "relative",
15212
+ onMouseEnter: function onMouseEnter() {
15213
+ return setHoveredItemId(item.id);
15214
+ },
15215
+ onMouseLeave: function onMouseLeave() {
15216
+ return setHoveredItemId(function (id) {
15217
+ return id === item.id ? null : id;
15218
+ });
15219
+ }
15214
15220
  }, /*#__PURE__*/React.createElement("div", {
15215
15221
  className: cn$1("flex items-center rounded-md px-3 py-2 text-sm font-medium transition-colors cursor-pointer", {
15216
15222
  "bg-primary-100 text-primary-700": isActive,
@@ -15222,18 +15228,36 @@ var Sidebar = function Sidebar(_ref) {
15222
15228
  },
15223
15229
  role: "button",
15224
15230
  tabIndex: 0,
15231
+ "aria-label": item.label,
15225
15232
  onKeyDown: function onKeyDown(e) {
15226
15233
  if (e.key === "Enter" || e.key === " ") {
15227
15234
  e.preventDefault();
15228
15235
  handleItemClick(item);
15229
15236
  }
15237
+ },
15238
+ onFocus: function onFocus() {
15239
+ return setHoveredItemId(item.id);
15240
+ },
15241
+ onBlur: function onBlur() {
15242
+ return setHoveredItemId(function (id) {
15243
+ return id === item.id ? null : id;
15244
+ });
15230
15245
  }
15231
- }, item.icon && /*#__PURE__*/React.createElement("span", {
15246
+ }, showTooltipForThis ? /*#__PURE__*/React.createElement(Tooltip, _extends({}, tooltipOptions, {
15247
+ trigger: "hover",
15248
+ content: item.label,
15249
+ position: "right"
15250
+ }), item.icon && /*#__PURE__*/React.createElement("span", {
15232
15251
  className: cn$1("flex-shrink-0", {
15233
15252
  "mr-3": !effectiveCollapsed || level > 0,
15234
15253
  "mr-0": effectiveCollapsed && level === 0
15235
15254
  })
15236
- }, item.icon), (!effectiveCollapsed || level > 0) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
15255
+ }, item.icon)) : /*#__PURE__*/React.createElement(React.Fragment, null, item.icon && /*#__PURE__*/React.createElement("span", {
15256
+ className: cn$1("flex-shrink-0", {
15257
+ "mr-3": !effectiveCollapsed || level > 0,
15258
+ "mr-0": effectiveCollapsed && level === 0
15259
+ })
15260
+ }, item.icon)), (!effectiveCollapsed || level > 0) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
15237
15261
  className: "flex-1 truncate"
15238
15262
  }, item.label), hasChildren && /*#__PURE__*/React.createElement("span", {
15239
15263
  className: "ml-2 flex-shrink-0"
@@ -15244,17 +15268,11 @@ var Sidebar = function Sidebar(_ref) {
15244
15268
  })))), hasChildren && isExpanded && (!effectiveCollapsed || level > 0) && /*#__PURE__*/React.createElement("div", {
15245
15269
  className: "mt-1 space-y-1 ml-2"
15246
15270
  }, item.children.map(function (child) {
15247
- return _renderMenuItem(child, level + 1);
15271
+ return _renderMenuItem(child, level + 1, tooltipOptions);
15248
15272
  })));
15249
15273
  };
15250
-
15251
- // When on mobile, clicking the toggle should close drawer instead of toggling collapse
15252
15274
  var handleToggleClick = function handleToggleClick() {
15253
- if (mobileOpen && setIsMobileOpen) {
15254
- setIsMobileOpen(false);
15255
- } else {
15256
- onToggle === null || onToggle === void 0 || onToggle();
15257
- }
15275
+ if (mobileOpen && setIsMobileOpen) setIsMobileOpen(false);else onToggle === null || onToggle === void 0 || onToggle();
15258
15276
  };
15259
15277
  var SidebarContent = /*#__PURE__*/React.createElement("div", {
15260
15278
  className: cn$1("flex h-full flex-col bg-white border-r border-gray-200 shadow-sm", "w-64 transition-all duration-200", {
@@ -15274,11 +15292,21 @@ var Sidebar = function Sidebar(_ref) {
15274
15292
  }) : /*#__PURE__*/React.createElement(ChevronLeft, {
15275
15293
  className: "h-5 w-5"
15276
15294
  }))), /*#__PURE__*/React.createElement("nav", {
15277
- className: "flex-1 space-y-1 p-4 overflow-y-auto [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-gray-100 [&::-webkit-scrollbar-thumb]:bg-gray-300 hover:[&::-webkit-scrollbar-thumb]:bg-gray-400"
15295
+ className: "flex-1 space-y-1 overflow-y-auto p-4 [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-gray-100 [&::-webkit-scrollbar-thumb]:bg-gray-300 hover:[&::-webkit-scrollbar-thumb]:bg-gray-400"
15278
15296
  }, items.map(function (item) {
15279
15297
  return _renderMenuItem(item);
15280
15298
  })), user && /*#__PURE__*/React.createElement("div", {
15281
15299
  className: "border-t border-gray-200 p-4"
15300
+ }, /*#__PURE__*/React.createElement("div", {
15301
+ className: "relative",
15302
+ onMouseEnter: function onMouseEnter() {
15303
+ return setHoveredItemId("user");
15304
+ },
15305
+ onMouseLeave: function onMouseLeave() {
15306
+ return setHoveredItemId(function (id) {
15307
+ return id === "user" ? null : id;
15308
+ });
15309
+ }
15282
15310
  }, /*#__PURE__*/React.createElement("div", {
15283
15311
  className: cn$1("flex items-center rounded-md px-3 py-2 cursor-pointer hover:bg-gray-100 transition-colors", {
15284
15312
  "justify-center": effectiveCollapsed,
@@ -15287,10 +15315,13 @@ var Sidebar = function Sidebar(_ref) {
15287
15315
  onClick: handleUserClick,
15288
15316
  role: "button",
15289
15317
  tabIndex: 0,
15290
- onKeyDown: function onKeyDown(e) {
15291
- if (e.key === "Enter" || e.key === " ") {
15292
- handleUserClick();
15293
- }
15318
+ onFocus: function onFocus() {
15319
+ return setHoveredItemId("user");
15320
+ },
15321
+ onBlur: function onBlur() {
15322
+ return setHoveredItemId(function (id) {
15323
+ return id === "user" ? null : id;
15324
+ });
15294
15325
  }
15295
15326
  }, user.avatar && /*#__PURE__*/React.createElement("img", {
15296
15327
  src: user.avatar,
@@ -15302,12 +15333,8 @@ var Sidebar = function Sidebar(_ref) {
15302
15333
  className: "text-sm font-medium text-gray-700 truncate"
15303
15334
  }, user.name), /*#__PURE__*/React.createElement("p", {
15304
15335
  className: "text-xs text-gray-500 truncate"
15305
- }, user.email)))));
15306
-
15307
- // Compute classes based on drawer position
15336
+ }, user.email))))));
15308
15337
  var isRight = drawerPosition === "right";
15309
-
15310
- // Mobile drawer styles
15311
15338
  var mobileDrawerClasses = cn$1("fixed top-0 z-50 h-full transition-transform duration-300 ease-in-out md:hidden", {
15312
15339
  "left-0": !isRight,
15313
15340
  "right-0": isRight
@@ -15316,8 +15343,6 @@ var Sidebar = function Sidebar(_ref) {
15316
15343
  "-translate-x-full": !mobileOpen && !isRight,
15317
15344
  "translate-x-full": !mobileOpen && isRight
15318
15345
  });
15319
-
15320
- // Desktop placement
15321
15346
  var desktopPlacementClass = isRight ? "md:order-last" : "";
15322
15347
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
15323
15348
  className: "hidden md:flex sticky top-0 h-screen"