@trackunit/react-table-base-components 1.6.90 → 1.6.91

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/index.cjs.js CHANGED
@@ -166,13 +166,58 @@ const MultiRowTableCell = ({ main, secondary, dataTestId, className }) => {
166
166
  return (jsxRuntime.jsx("div", { className: cvaMultiRowTableCell({ className }), children: jsxRuntime.jsxs("section", { className: cvaMultiRowTableCellSection(), "data-testid": dataTestId, children: [typeof main === "string" ? jsxRuntime.jsx("div", { className: cvaMainRowText(), children: main }) : main, secondary && typeof secondary === "string" ? (jsxRuntime.jsx("div", { className: cvaSecondaryRowText(), children: secondary })) : (secondary)] }) }));
167
167
  };
168
168
 
169
+ /**
170
+ * Generic list to be used as tooltip content.
171
+ * The component is data-shape agnostic. It supports primitives, React elements,
172
+ * and arbitrary objects (with a JSON.stringify fallback).
173
+ *
174
+ * @template TItem Element type of the list.
175
+ * @param {ListTooltipProps<TItem>} props Component props.
176
+ * @returns {ReactNode} Tooltip list markup.
177
+ */
178
+ const ListTooltip = ({ items, dataTestId, getLabel, getKey, loading, }) => {
179
+ const toDisplay = (item, index) => {
180
+ if (getLabel) {
181
+ return getLabel(item, index);
182
+ }
183
+ if (react.isValidElement(item)) {
184
+ return item;
185
+ }
186
+ const kind = typeof item;
187
+ if (kind === "string" || kind === "number" || kind === "boolean") {
188
+ return String(item);
189
+ }
190
+ if (item === null) {
191
+ return "";
192
+ }
193
+ try {
194
+ return JSON.stringify(item);
195
+ }
196
+ catch {
197
+ return String(item);
198
+ }
199
+ };
200
+ const toKey = (item, index) => {
201
+ if (getKey) {
202
+ return getKey(item, index);
203
+ }
204
+ const val = toDisplay(item, index);
205
+ return typeof val === "string" || typeof val === "number" ? `${val}-${index}` : index;
206
+ };
207
+ if (loading) {
208
+ return jsxRuntime.jsx(reactComponents.Spinner, { centering: "centered", mode: "dark" });
209
+ }
210
+ return (jsxRuntime.jsx("ul", { className: "list-inside !ps-1 pl-1", "data-testid": dataTestId, children: items.map((item, index) => {
211
+ const label = toDisplay(item, index);
212
+ if (label === "" || label === null || label === undefined) {
213
+ return null;
214
+ }
215
+ return (jsxRuntime.jsx("li", { className: "list-disc font-normal", children: label }, toKey(item, index)));
216
+ }) }));
217
+ };
218
+
169
219
  const cvaMultiValueTextCellWrapper = cssClassVarianceUtilities.cvaMerge(["flex", "flex-row", "items-center", "gap-1", "overflow-hidden"]);
170
- const cvaMultiValueTextCellTooltip = cssClassVarianceUtilities.cvaMerge([
171
- "whitespace-no-wrap",
172
- "overflow-hidden",
173
- "text-ellipsis",
174
- "text-sm",
175
- ]);
220
+ const cvaMultiValueTextCellTooltip = cssClassVarianceUtilities.cvaMerge(["whitespace-no-wrap", "overflow-hidden", "text-ellipsis"]);
176
221
 
177
222
  /**
178
223
  * The `<MultiValueTextCell>` component is used for displaying the text values with multiple values in a table cell. First element is displayed as a text, the rest of the values are displayed as a number. Icon can be passed as an optional prop.
@@ -580,6 +625,7 @@ exports.IdentityCell = IdentityCell;
580
625
  exports.ImageCell = ImageCell;
581
626
  exports.IndicatorCell = IndicatorCell;
582
627
  exports.LinkCell = LinkCell;
628
+ exports.ListTooltip = ListTooltip;
583
629
  exports.MultiRowTableCell = MultiRowTableCell;
584
630
  exports.MultiValueTextCell = MultiValueTextCell;
585
631
  exports.NoticeCell = NoticeCell;
package/index.esm.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { Button, Icon, Highlight, Heading, DetailsList, Indicator, ExternalLink, Tooltip, Tag, Notice, IconButton, MoreMenu, MenuList, MenuItem, MenuDivider, Spinner } from '@trackunit/react-components';
2
+ import { Button, Icon, Highlight, Heading, DetailsList, Indicator, ExternalLink, Spinner, Tooltip, Tag, Notice, IconButton, MoreMenu, MenuList, MenuItem, MenuDivider } from '@trackunit/react-components';
3
3
  import { twMerge } from 'tailwind-merge';
4
4
  import { Checkbox } from '@trackunit/react-form-components';
5
5
  import { cvaMerge } from '@trackunit/css-class-variance-utilities';
6
6
  import { formatDateUtil, timeSinceAuto, timeSinceInDays } from '@trackunit/date-and-time-utils';
7
- import { useState, isValidElement, cloneElement } from 'react';
7
+ import { isValidElement, useState, cloneElement } from 'react';
8
8
  import { Temporal } from '@js-temporal/polyfill';
9
9
  import { DateTimeFormat } from '@trackunit/shared-utils';
10
10
 
@@ -164,13 +164,58 @@ const MultiRowTableCell = ({ main, secondary, dataTestId, className }) => {
164
164
  return (jsx("div", { className: cvaMultiRowTableCell({ className }), children: jsxs("section", { className: cvaMultiRowTableCellSection(), "data-testid": dataTestId, children: [typeof main === "string" ? jsx("div", { className: cvaMainRowText(), children: main }) : main, secondary && typeof secondary === "string" ? (jsx("div", { className: cvaSecondaryRowText(), children: secondary })) : (secondary)] }) }));
165
165
  };
166
166
 
167
+ /**
168
+ * Generic list to be used as tooltip content.
169
+ * The component is data-shape agnostic. It supports primitives, React elements,
170
+ * and arbitrary objects (with a JSON.stringify fallback).
171
+ *
172
+ * @template TItem Element type of the list.
173
+ * @param {ListTooltipProps<TItem>} props Component props.
174
+ * @returns {ReactNode} Tooltip list markup.
175
+ */
176
+ const ListTooltip = ({ items, dataTestId, getLabel, getKey, loading, }) => {
177
+ const toDisplay = (item, index) => {
178
+ if (getLabel) {
179
+ return getLabel(item, index);
180
+ }
181
+ if (isValidElement(item)) {
182
+ return item;
183
+ }
184
+ const kind = typeof item;
185
+ if (kind === "string" || kind === "number" || kind === "boolean") {
186
+ return String(item);
187
+ }
188
+ if (item === null) {
189
+ return "";
190
+ }
191
+ try {
192
+ return JSON.stringify(item);
193
+ }
194
+ catch {
195
+ return String(item);
196
+ }
197
+ };
198
+ const toKey = (item, index) => {
199
+ if (getKey) {
200
+ return getKey(item, index);
201
+ }
202
+ const val = toDisplay(item, index);
203
+ return typeof val === "string" || typeof val === "number" ? `${val}-${index}` : index;
204
+ };
205
+ if (loading) {
206
+ return jsx(Spinner, { centering: "centered", mode: "dark" });
207
+ }
208
+ return (jsx("ul", { className: "list-inside !ps-1 pl-1", "data-testid": dataTestId, children: items.map((item, index) => {
209
+ const label = toDisplay(item, index);
210
+ if (label === "" || label === null || label === undefined) {
211
+ return null;
212
+ }
213
+ return (jsx("li", { className: "list-disc font-normal", children: label }, toKey(item, index)));
214
+ }) }));
215
+ };
216
+
167
217
  const cvaMultiValueTextCellWrapper = cvaMerge(["flex", "flex-row", "items-center", "gap-1", "overflow-hidden"]);
168
- const cvaMultiValueTextCellTooltip = cvaMerge([
169
- "whitespace-no-wrap",
170
- "overflow-hidden",
171
- "text-ellipsis",
172
- "text-sm",
173
- ]);
218
+ const cvaMultiValueTextCellTooltip = cvaMerge(["whitespace-no-wrap", "overflow-hidden", "text-ellipsis"]);
174
219
 
175
220
  /**
176
221
  * The `<MultiValueTextCell>` component is used for displaying the text values with multiple values in a table cell. First element is displayed as a text, the rest of the values are displayed as a number. Icon can be passed as an optional prop.
@@ -570,4 +615,4 @@ const cvaTr = cvaMerge(["w-full", "h-max", "border-b", "border-neutral-200"], {
570
615
  },
571
616
  });
572
617
 
573
- export { ButtonCell, CheckboxCell, DateTimeCell, HighlightCell, IdentityCell, ImageCell, IndicatorCell, LinkCell, MultiRowTableCell, MultiValueTextCell, NoticeCell, NumberCell, PlainDateCell, ResizeHandle, RowActions, SortIndicator, TableRoot, TagsCell, Tbody, Td, TextCell, Tfoot, Th, Thead, Tr };
618
+ export { ButtonCell, CheckboxCell, DateTimeCell, HighlightCell, IdentityCell, ImageCell, IndicatorCell, LinkCell, ListTooltip, MultiRowTableCell, MultiValueTextCell, NoticeCell, NumberCell, PlainDateCell, ResizeHandle, RowActions, SortIndicator, TableRoot, TagsCell, Tbody, Td, TextCell, Tfoot, Th, Thead, Tr };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-table-base-components",
3
- "version": "1.6.90",
3
+ "version": "1.6.91",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -8,9 +8,9 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "react": "19.0.0",
11
- "@trackunit/react-components": "1.8.38",
11
+ "@trackunit/react-components": "1.8.39",
12
12
  "@trackunit/ui-icons": "1.6.59",
13
- "@trackunit/react-form-components": "1.7.54",
13
+ "@trackunit/react-form-components": "1.7.55",
14
14
  "@trackunit/css-class-variance-utilities": "1.6.60",
15
15
  "@trackunit/date-and-time-utils": "1.6.60",
16
16
  "@trackunit/shared-utils": "1.8.61",
@@ -0,0 +1,34 @@
1
+ import { Key, ReactNode } from "react";
2
+ /**
3
+ * Props for a generic tooltip list component.
4
+ *
5
+ * @template TItem Element type of the list.
6
+ */
7
+ export type ListTooltipProps<TItem = unknown> = {
8
+ /** Items to render inside the tooltip. */
9
+ items: Array<TItem>;
10
+ /** Data test id for testing. */
11
+ dataTestId?: string;
12
+ /**
13
+ * Custom label extractor. If omitted, strings/numbers/booleans are stringified,
14
+ * React elements are returned as-is, and other objects are serialized.
15
+ */
16
+ getLabel?: (item: TItem, index: number) => ReactNode;
17
+ /** Custom key generator for list items. */
18
+ getKey?: (item: TItem, index: number) => Key;
19
+ /**
20
+ * Controls the loading state. When true, the list is replaced with a centered dark Spinner.
21
+ * Useful while data is being fetched. Defaults to false.
22
+ */
23
+ loading?: boolean;
24
+ };
25
+ /**
26
+ * Generic list to be used as tooltip content.
27
+ * The component is data-shape agnostic. It supports primitives, React elements,
28
+ * and arbitrary objects (with a JSON.stringify fallback).
29
+ *
30
+ * @template TItem Element type of the list.
31
+ * @param {ListTooltipProps<TItem>} props Component props.
32
+ * @returns {ReactNode} Tooltip list markup.
33
+ */
34
+ export declare const ListTooltip: <TItem = unknown>({ items, dataTestId, getLabel, getKey, loading, }: ListTooltipProps<TItem>) => import("react/jsx-runtime").JSX.Element;
@@ -1,11 +1,38 @@
1
1
  import { CommonProps } from "@trackunit/react-components";
2
2
  import { MouseEventHandler, ReactElement, ReactNode } from "react";
3
3
  export interface MultiValueTextCellProps extends CommonProps {
4
+ /**
5
+ * Icon rendered to the left of the text.
6
+ * Provides visual context for the primary value.
7
+ */
4
8
  icon?: ReactElement;
9
+ /**
10
+ * Tooltip text for the icon.
11
+ * If omitted, the icon tooltip is disabled.
12
+ */
5
13
  iconTooltip?: string;
14
+ /**
15
+ * The first (primary) value displayed as plain text in the cell.
16
+ * The text is truncated to fit the cell and, when clipped, is shown in a tooltip.
17
+ */
6
18
  content?: string;
19
+ /**
20
+ * Total number of values.
21
+ * - The component renders only when count > 0.
22
+ * - If count > 1, a +N badge is shown where N = count - 1.
23
+ */
7
24
  count?: number | null;
25
+ /**
26
+ * Tooltip content for the +N badge.
27
+ * Accepts strings, React elements, or any ReactNode.
28
+ * If omitted, the badge tooltip is disabled.
29
+ * Recommended: use the `ListTooltip` component to render a list of the remaining items.
30
+ */
8
31
  countTooltip?: ReactNode;
32
+ /**
33
+ * Mouse enter handler for the badge.
34
+ * Useful for lazy-loading tooltip content (e.g., fetching the remaining items).
35
+ */
9
36
  onMouseEnter?: MouseEventHandler<HTMLDivElement>;
10
37
  }
11
38
  /**
@@ -7,3 +7,6 @@ export default meta;
7
7
  export declare const packageName: () => import("react/jsx-runtime").JSX.Element;
8
8
  export declare const Default: Story;
9
9
  export declare const Example: Story;
10
+ export declare const PlusBadgeWithTooltip: Story;
11
+ export declare const LazyLoadedOnHover: Story;
12
+ export declare const WithIcon: Story;
package/src/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from "./components/ImageCell/ImageCell";
7
7
  export * from "./components/IndicatorCell/IndicatorCell";
8
8
  export * from "./components/LinkCell/LinkCell";
9
9
  export * from "./components/MultiRowTableCell/MultiRowTableCell";
10
+ export * from "./components/MultiValueTextCell/ListTooltip";
10
11
  export * from "./components/MultiValueTextCell/MultiValueTextCell";
11
12
  export * from "./components/NoticeCell/NoticeCell";
12
13
  export * from "./components/NumberCell/NumberCell";