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