@spaced-out/ui-design-system 0.6.32 → 0.6.34

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.
@@ -94,7 +94,14 @@ jobs:
94
94
  fi
95
95
  # Note(Nishant): Unified step for version bump, respecting prerelease condition
96
96
 
97
- # Push changes
97
+ # Publish version to NPM repository
98
+ - name: Publish to NPM
99
+ env:
100
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
101
+ run: yarn publish --verbose --access public --tag "$RELEASE_TAG"
102
+
103
+ # Push changes only after a successful publish, so a failed publish
104
+ # never leaves a chore(release) commit/tag behind on the branch.
98
105
  - name: Push CHANGELOG.md and created release tag
99
106
  env:
100
107
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -103,9 +110,3 @@ jobs:
103
110
  git push --follow-tags origin "${GITHUB_REF_NAME}"
104
111
 
105
112
  # Note(Nishant): Push to selected branch, not hardcoded master
106
-
107
- # Publish version to NPM repository
108
- - name: Publish to NPM
109
- env:
110
- NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
111
- run: yarn publish --verbose --access public --tag "$RELEASE_TAG"
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [0.6.34](https://github.com/spaced-out/ui-design-system/compare/v0.6.33...v0.6.34) (2026-09-16)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * truncated text with tooltip issues ([#507](https://github.com/spaced-out/ui-design-system/issues/507)) ([8dd98b9](https://github.com/spaced-out/ui-design-system/commit/8dd98b903010b1fccf2e42cd3d370c56a5ab21be))
11
+
12
+ ### [0.6.33](https://github.com/spaced-out/ui-design-system/compare/v0.6.32...v0.6.33) (2026-09-15)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * **chore-release:** commit version update only after successful npm publish ([#503](https://github.com/spaced-out/ui-design-system/issues/503)) ([3e89b88](https://github.com/spaced-out/ui-design-system/commit/3e89b88492fb0461fb5e9ddf32481f13005e0633))
18
+ * **truncated-text-with-tooltip:** re-attach ResizeObserver when truncated node changes ([#502](https://github.com/spaced-out/ui-design-system/issues/502)) ([5305ba6](https://github.com/spaced-out/ui-design-system/commit/5305ba6fceb6643f8432b4c8bd85c07ff25d4c4b))
19
+
5
20
  ### [0.6.32](https://github.com/spaced-out/ui-design-system/compare/v0.6.31...v0.6.32) (2026-09-04)
6
21
 
7
22
  ### [0.6.31](https://github.com/spaced-out/ui-design-system/compare/v0.6.30...v0.6.31) (2026-08-31)
@@ -1 +1 @@
1
- {"version":3,"file":"TruncatedTextWithTooltip.d.ts","sourceRoot":"","sources":["../../../src/components/TruncatedTextWithTooltip/TruncatedTextWithTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,wBAAwB,CAAC;AAM7D,KAAK,UAAU,GAAG,QAAQ,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAYD,eAAO,MAAM,wBAAwB,GAAI,uEAQtC,6BAA6B,sBAuF/B,CAAC"}
1
+ {"version":3,"file":"TruncatedTextWithTooltip.d.ts","sourceRoot":"","sources":["../../../src/components/TruncatedTextWithTooltip/TruncatedTextWithTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,wBAAwB,CAAC;AAM7D,KAAK,UAAU,GAAG,QAAQ,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,wBAAwB,GAAI,uEAQtC,6BAA6B,sBAiH/B,CAAC"}
@@ -6,19 +6,13 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.TruncatedTextWithTooltip = void 0;
7
7
  var React = _interopRequireWildcard(require("react"));
8
8
  var _debounce = _interopRequireDefault(require("lodash/debounce"));
9
- var _useWindowSize = require("../../hooks/useWindowSize");
10
9
  var _classify = _interopRequireDefault(require("../../utils/classify"));
11
10
  var _qa = require("../../utils/qa");
12
- var _ConditionalWrapper = require("../ConditionalWrapper");
13
11
  var _Tooltip = require("../Tooltip");
14
12
  var _TruncatedTextWithTooltipModule = _interopRequireDefault(require("./TruncatedTextWithTooltip.module.css"));
15
13
  var _jsxRuntime = require("react/jsx-runtime");
16
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
15
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
18
- // Define the expected props for the child element that can be cloned
19
-
20
- // Type for a child element that can be cloned
21
-
22
16
  const TruncatedTextWithTooltip = _ref => {
23
17
  let {
24
18
  classNames,
@@ -29,78 +23,105 @@ const TruncatedTextWithTooltip = _ref => {
29
23
  wordBreak = 'break-all',
30
24
  testId
31
25
  } = _ref;
32
- const {
33
- width
34
- } = (0, _useWindowSize.useWindowSize)();
35
26
  const [showMouseTip, setShowMouseTip] = React.useState(false);
36
- const truncatedRef = React.useRef(null);
27
+ const [truncatedNode, setTruncatedNode] = React.useState(null);
37
28
  const checkIfTextOverflowing = React.useMemo(() => (0, _debounce.default)(() => {
38
- if (!wrapText && truncatedRef && truncatedRef.current && truncatedRef.current.scrollHeight > truncatedRef.current.clientHeight) {
29
+ if (!wrapText && truncatedNode && truncatedNode.scrollHeight > truncatedNode.clientHeight) {
39
30
  setShowMouseTip(true);
40
31
  } else {
41
32
  setShowMouseTip(false);
42
33
  }
43
34
  }, 200, {
44
35
  leading: true
45
- }), []);
36
+ }), [truncatedNode, wrapText]);
46
37
  React.useEffect(() => {
47
38
  checkIfTextOverflowing();
48
- }, [width, line, children, wrapText]);
39
+ // Cancel the outgoing debounce instance's pending trailing-edge call.
40
+ // checkIfTextOverflowing is recreated whenever truncatedNode changes
41
+ // (e.g. once on mount, null -> real node). Without this cancel, the
42
+ // stale instance's trailing call still fires ~200ms later using its
43
+ // frozen closure (truncatedNode as it was when THAT instance was
44
+ // created) and can stomp a correct value the new instance already set.
45
+ return () => {
46
+ checkIfTextOverflowing.cancel();
47
+ };
48
+ }, [line, children, wrapText, checkIfTextOverflowing]);
49
+ React.useEffect(() => {
50
+ if (!truncatedNode) {
51
+ return undefined;
52
+ }
53
+ const observer = new ResizeObserver(() => {
54
+ checkIfTextOverflowing();
55
+ });
56
+ observer.observe(truncatedNode);
57
+ return () => {
58
+ observer.disconnect();
59
+ };
60
+ }, [truncatedNode, checkIfTextOverflowing]);
49
61
  const styles = {
50
62
  '--line-clamp': wrapText ? 'unset' : line,
51
63
  '--word-break': wordBreak
52
64
  };
53
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ConditionalWrapper.ConditionalWrapper, {
54
- condition: Boolean(showMouseTip),
55
- wrapper: children => {
56
- const child = React.Children.only(children);
57
65
 
58
- // Type guard to ensure child is a ReactElement
59
- if (! /*#__PURE__*/React.isValidElement(child)) {
60
- return child;
61
- }
62
-
63
- // Cast to our typed child element
64
- const childElement = child;
65
- const childProps = childElement.props;
66
+ // Always render the same <span>, always wrapped in the same <Tooltip>,
67
+ // toggling only Tooltip's `hidden` prop. Previously a ConditionalWrapper
68
+ // swapped between a bare <span> and <Tooltip><div>{span}</div></Tooltip>
69
+ // based on showMouseTip — changing the element type at this tree position
70
+ // forces React to unmount/remount the span every time showMouseTip
71
+ // toggles. The remounted span (now a flex child of an extra wrapper div)
72
+ // measures different scrollHeight/clientHeight than the bare span, so the
73
+ // ResizeObserver above sees its own self-inflicted resize and flips
74
+ // showMouseTip again — an infinite loop where the tooltip never
75
+ // stabilizes. Tooltip clones its trigger prop onto the same element (no
76
+ // wrapper element inserted), so keeping the span's identity stable here
77
+ // means toggling showMouseTip no longer causes a remount.
78
+ const truncatedSpan = /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
79
+ className: (0, _classify.default)(_TruncatedTextWithTooltipModule.default.truncateLineClamp, classNames?.wrapper),
80
+ style: styles,
81
+ ref: setTruncatedNode,
82
+ "data-testid": (0, _qa.generateTestId)({
83
+ base: testId,
84
+ slot: 'text'
85
+ }),
86
+ children: children
87
+ });
66
88
 
67
- //Vivek: This children in tooltip body is modified to remove line clamp style
68
- const modifiedChild = /*#__PURE__*/React.cloneElement(childElement, {
69
- ...childProps,
70
- style: {
71
- ...childProps.style,
72
- '--line-clamp': tooltip?.bodyMaxLines || line,
73
- '--word-break': wordBreak
74
- }
75
- });
76
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.Tooltip, {
77
- ...tooltip,
78
- body: tooltip?.body || modifiedChild,
79
- elevation: tooltip?.elevation ?? 'toast',
80
- testId: (0, _qa.generateTestId)({
81
- base: testId,
82
- slot: 'tooltip'
83
- }),
84
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
85
- className: _TruncatedTextWithTooltipModule.default.childrenWrapper,
86
- "data-testid": (0, _qa.generateTestId)({
87
- base: testId,
88
- slot: 'wrapper'
89
- }),
90
- children: children
91
- })
92
- });
93
- },
94
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
95
- className: (0, _classify.default)(_TruncatedTextWithTooltipModule.default.truncateLineClamp, classNames?.wrapper),
96
- style: styles,
97
- ref: truncatedRef,
98
- "data-testid": (0, _qa.generateTestId)({
99
- base: testId,
100
- slot: 'text'
101
- }),
102
- children: children
89
+ // `ref: null` is required here: React.cloneElement inherits the source
90
+ // element's ref unless explicitly overridden. Without this, this
91
+ // body-only clone (rendered separately inside Tooltip's floating panel,
92
+ // gated by `hidden`) would share the trigger span's ref. Mounting/
93
+ // unmounting this clone as `hidden` toggles would hijack truncatedNode
94
+ // away from the actual trigger, eventually losing the ref to the real
95
+ // trigger permanently once this clone unmounts.
96
+ //
97
+ // No className/style here (rather than trying to override --line-clamp):
98
+ // Tooltip already wraps body in <Truncate line={bodyMaxLines}>, which puts
99
+ // its own webkit-box line-clamp on the containing div. Keeping
100
+ // css.truncateLineClamp on this span would make it a second, nested
101
+ // webkit-box with its own --word-break (this component's `wordBreak` prop,
102
+ // meant for the single-line trigger) — since that inner box is what
103
+ // actually renders the text, it silently wins over the outer div's
104
+ // word-break even when both clamp to the same line count. Dropping the
105
+ // class/style lets the outer div be the only clamp in the chain.
106
+ const modifiedChild = /*#__PURE__*/React.cloneElement(truncatedSpan, {
107
+ ref: null,
108
+ className: undefined,
109
+ style: undefined,
110
+ 'data-testid': (0, _qa.generateTestId)({
111
+ base: testId,
112
+ slot: 'body-text'
103
113
  })
104
114
  });
115
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.Tooltip, {
116
+ ...tooltip,
117
+ hidden: tooltip?.hidden ?? !showMouseTip,
118
+ body: tooltip?.body || modifiedChild,
119
+ elevation: tooltip?.elevation ?? 'toast',
120
+ testId: (0, _qa.generateTestId)({
121
+ base: testId,
122
+ slot: 'tooltip'
123
+ }),
124
+ children: truncatedSpan
125
+ });
105
126
  };
106
127
  exports.TruncatedTextWithTooltip = TruncatedTextWithTooltip;
@@ -2,6 +2,3 @@
2
2
  composes: truncate from '../../styles/typography.module.css';
3
3
  white-space: normal;
4
4
  }
5
- .childrenWrapper {
6
- display: flex;
7
- }
package/mcp/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaced-out/genesis-mcp",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "description": "MCP server for Genesis UI Design System - provides AI assistants with access to components, hooks, and design tokens",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaced-out/ui-design-system",
3
- "version": "0.6.32",
3
+ "version": "0.6.34",
4
4
  "description": "Sense UI components library",
5
5
  "author": {
6
6
  "name": "Spaced Out"