@agilant/toga-blox 1.0.162 → 1.0.163

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.
@@ -1,29 +1,26 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // src/components/TableCell/TableCell.tsx
2
3
  import { useState } from "react";
3
4
  const MAX_CHARS = 30;
4
- const TableCell = ({ cell, isLastCell, hasInfiniteScroll, linkText = "text-purple-500 text-primary ml-1 underline", }) => {
5
+ const TableCell = ({ cell, isLastCell, hasInfiniteScroll, linkText = "text-purple-500 ml-1 underline", }) => {
5
6
  const [expanded, setExpanded] = useState(false);
6
- /* ---------- value helpers ---------- */
7
+ // Determine if we need a toggle
7
8
  const isString = typeof cell.value === "string";
8
9
  const fullText = isString ? cell.value : "";
9
10
  const isLong = isString && fullText.length > MAX_CHARS;
11
+ const hasToggle = hasInfiniteScroll && isLong;
10
12
  const truncated = fullText.slice(0, MAX_CHARS);
11
- /* ---------- class strings ---------- */
12
- const tableDataCls = "relative overflow-hidden font-light text-sm text-left z-0 px-5";
13
- const cellContainerCls = "min-h-[40px] flex items-center group select-none" +
14
- (hasInfiniteScroll && isLong ? " cursor-pointer" : "");
15
- /* ---------- toggle ---------- */
13
+ // Only stop propagation / toggle when hasToggle is true
16
14
  const handleToggle = (e) => {
17
15
  e.stopPropagation();
18
- if (hasInfiniteScroll && isLong)
19
- setExpanded((prev) => !prev);
16
+ setExpanded((prev) => !prev);
20
17
  };
21
- return (_jsx("td", { ...cell.getCellProps(), className: isLastCell ? "" : tableDataCls, children: _jsx("div", { className: cellContainerCls, onClick: handleToggle, children: isString && isLong && hasInfiniteScroll ? (!expanded ? (
22
- /* ---------- COLLAPSED ---------- */
23
- _jsxs("span", { children: [truncated, _jsx("span", { className: "inline group-hover:hidden", children: "\u2026" }), _jsx("span", { className: `hidden group-hover:inline ${linkText}`, children: "Show more" })] })) : (
24
- /* ---------- EXPANDED ---------- */
25
- _jsxs("span", { children: [fullText, _jsx("span", { className: linkText, children: "Show less" })] }))) : (
26
- /* non‑string, short string, or infinite scroll disabled */
18
+ const baseTdCls = "relative overflow-hidden font-light text-sm text-left px-5";
19
+ const cellWrapperCls = "min-h-[40px] flex items-center";
20
+ return (_jsx("td", { ...cell.getCellProps(), className: isLastCell ? "" : baseTdCls, children: _jsx("div", { className: cellWrapperCls, ...(hasToggle
21
+ ? { onClick: handleToggle, style: { cursor: "pointer" } }
22
+ : {}), children: hasToggle ? (!expanded ? (_jsxs(_Fragment, { children: [truncated, _jsx("span", { className: "inline group-hover:hidden", children: "\u2026" }), _jsx("span", { className: linkText, children: "Show more" })] })) : (_jsxs(_Fragment, { children: [fullText, _jsx("span", { className: linkText, children: "Show less" })] }))) : (
23
+ /* no toggle: render normally, clicks bubble to row */
27
24
  cell.render("Cell")) }) }));
28
25
  };
29
26
  export default TableCell;
@@ -8,10 +8,10 @@ export interface TableRowProps<T extends DataWithUUID> {
8
8
  activeRowColor?: string;
9
9
  rowHoverClasses?: string;
10
10
  globalTrimActive?: boolean;
11
- hasInfiniteScroll?: boolean;
11
+ hasInfiniteScroll: boolean;
12
12
  rowUuid?: string;
13
13
  columnInputs?: string[];
14
- onRowClick?: (index: number, rowUuid: string, event: React.MouseEvent<HTMLTableRowElement, MouseEvent>) => void;
14
+ onRowClick: (index: number, rowUuid: string, event: React.MouseEvent<HTMLTableRowElement, MouseEvent>) => void;
15
15
  hasDropDown?: boolean;
16
16
  onFetchRowData?: (uuid: string) => Promise<void> | void;
17
17
  loadingIndicator?: ReactNode;
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // src/components/TableRow/TableRow.tsx
2
3
  import { Fragment, useState } from "react";
3
4
  import { motion, AnimatePresence } from "framer-motion";
4
5
  import TableCell from "../TableCell";
@@ -8,30 +9,29 @@ import TableCell from "../TableCell";
8
9
  const TableRow = ({
9
10
  /* react‑table */
10
11
  row, prepareRow,
11
- /* visual / interaction */
12
- activeIndex, activeRowColor = "bg-pink-100", rowHoverClasses = "hover:bg-red-100 hover:cursor-pointer",
13
- /* cell behaviour */
14
- globalTrimActive, hasInfiniteScroll = false,
15
- /* row meta */
12
+ /* visual */
13
+ activeIndex, activeRowColor = "bg-pink-100", rowHoverClasses = "hover:bg-navy-100 hover:cursor-pointer",
14
+ /* cell props */
15
+ globalTrimActive = false, hasInfiniteScroll,
16
+ /* meta */
16
17
  rowUuid, columnInputs,
17
- /* callbacks */
18
+ /* click handler */
18
19
  onRowClick,
19
- /* expandable row */
20
+ /* dropdown */
20
21
  hasDropDown = false, onFetchRowData, loadingIndicator, errorIndicator, expandedContent, }) => {
21
- /* prepare row for rendering */
22
+ /* prepare react-table row */
22
23
  prepareRow(row);
23
24
  const isActive = activeIndex === row.index;
24
25
  let rowClasses = "border-primary";
25
- if (isActive) {
26
+ if (isActive)
26
27
  rowClasses += ` activeRow ${activeRowColor}`;
27
- }
28
- /* local state for dropdown expansion */
28
+ /* local dropdown state */
29
29
  const [isExpanded, setIsExpanded] = useState(false);
30
30
  const [isLoading, setIsLoading] = useState(false);
31
31
  const [error, setError] = useState(null);
32
- /* handle row click (fires dropdown & optional fetch) */
33
- const handleRowClick = async (event) => {
34
- onRowClick?.(row.index, rowUuid || "", event);
32
+ /* rowclick: call your passed‑in handler, then dropdown logic */
33
+ const handleRowClick = async (e) => {
34
+ onRowClick(row.index, rowUuid ?? "", e);
35
35
  if (hasDropDown) {
36
36
  setIsExpanded((prev) => !prev);
37
37
  if (onFetchRowData && rowUuid) {
@@ -1,16 +1,7 @@
1
- import { Meta } from "@storybook/react";
1
+ import { Meta, StoryFn } from "@storybook/react";
2
2
  import TableRow from "./TableRow";
3
- declare const _default: Meta<typeof TableRow>;
4
- export default _default;
3
+ declare const meta: Meta<typeof TableRow>;
4
+ export default meta;
5
5
  export declare const Default: any;
6
6
  export declare const ExpandableRow: any;
7
- export declare const MultipleRows: {
8
- (): import("react/jsx-runtime").JSX.Element;
9
- parameters: {
10
- docs: {
11
- description: {
12
- story: string;
13
- };
14
- };
15
- };
16
- };
7
+ export declare const MultipleRows: StoryFn;
@@ -58,7 +58,6 @@ const makeCells = (d) => [
58
58
  ];
59
59
  const cellsForRow1 = makeCells(sampleData);
60
60
  const cellsForRow2 = makeCells(sampleData2);
61
- /* react‑table’s Row type is mocked for Storybook preview */
62
61
  const makeMockRow = (d, idx, cells) => ({
63
62
  index: idx,
64
63
  id: String(idx),
@@ -71,37 +70,36 @@ const makeMockRow = (d, idx, cells) => ({
71
70
  });
72
71
  const mockRow = makeMockRow(sampleData, 0, cellsForRow1);
73
72
  const mockRow2 = makeMockRow(sampleData2, 1, cellsForRow2);
74
- const prepareRow = () => { }; // no‑op for the mock
73
+ const prepareRow = () => { }; // no‑op for Storybook
75
74
  /* ------------------------------------------------------------------ */
76
75
  /* STORYBOOK CONFIG */
77
76
  /* ------------------------------------------------------------------ */
78
- export default {
77
+ const meta = {
79
78
  title: "Table/TableRow",
80
79
  component: TableRow,
81
80
  tags: ["autodocs"],
81
+ decorators: [
82
+ (Story) => (_jsx("div", { onClickCapture: (e) => {
83
+ const t = e.target.innerText;
84
+ if (t === "Show more" || t === "Show less") {
85
+ alert("from cell");
86
+ }
87
+ }, children: _jsx(Story, {}) })),
88
+ ],
82
89
  argTypes: {
83
- hasInfiniteScroll: {
84
- control: "boolean",
85
- description: "When **true**, long strings in cells truncate to 30 chars and can expand on click.",
86
- },
87
- hasDropDown: {
88
- control: "boolean",
89
- description: "Whether this row has the sliding dropdown section.",
90
- },
90
+ hasInfiniteScroll: { control: "boolean" },
91
+ hasDropDown: { control: "boolean" },
92
+ onRowClick: { action: "row clicked" },
91
93
  },
92
94
  parameters: {
93
95
  layout: "centered",
94
- docs: {
95
- description: {
96
- component: "Demonstrates the reusable **TableRow** and nested **TableCell**: click a truncated cell to ‘Show more / Show less’, and (optionally) expand the entire row via dropdown.",
97
- },
98
- },
99
96
  },
100
97
  };
98
+ export default meta;
101
99
  /* ------------------------------------------------------------------ */
102
100
  /* TEMPLATE */
103
101
  /* ------------------------------------------------------------------ */
104
- const Template = (args) => (_jsx("table", { className: "min-w-[700px]", children: _jsx("tbody", { children: _jsx(TableRow, { ...args }) }) }));
102
+ const Template = (args) => (_jsx("table", { className: "min-w-[700px]", children: _jsx("tbody", { children: _jsx(TableRow, { ...args, hasInfiniteScroll: args.hasInfiniteScroll ?? true, onRowClick: args.onRowClick ?? (() => alert("from row")) }) }) }));
105
103
  /* ------------------------------------------------------------------ */
106
104
  /* STORIES */
107
105
  /* ------------------------------------------------------------------ */
@@ -109,17 +107,12 @@ export const Default = Template.bind({});
109
107
  Default.args = {
110
108
  row: mockRow,
111
109
  prepareRow,
112
- hasInfiniteScroll: true,
113
- globalTrimActive: false,
114
- hasDropDown: false,
115
- rowUuid: sampleData.uuid,
116
- };
117
- Default.parameters = {
118
- docs: {
119
- description: {
120
- story: "Click the **address** cell to toggle between its truncated preview and the full text.",
121
- },
122
- },
110
+ hasInfiniteScroll: true, // ✅ required
111
+ onRowClick: () => alert("from row"), // ✅ required
112
+ globalTrimActive: false, // optional
113
+ hasDropDown: false, // optional
114
+ rowUuid: sampleData.uuid, // optional
115
+ // (you can omit activeIndex, columnInputs, rowHoverClasses—they’re optional)
123
116
  };
124
117
  export const ExpandableRow = Template.bind({});
125
118
  ExpandableRow.args = {
@@ -127,19 +120,4 @@ ExpandableRow.args = {
127
120
  hasDropDown: true,
128
121
  expandedContent: sampleData.expandedContent,
129
122
  };
130
- ExpandableRow.parameters = {
131
- docs: {
132
- description: {
133
- story: "Row showcasing **both** the cell truncate/expand **and** the sliding dropdown. " +
134
- "Click the address cell for ‘Show more’, and click the row itself for the dropdown.",
135
- },
136
- },
137
- };
138
- export const MultipleRows = () => (_jsx("table", { className: "min-w-[700px]", children: _jsxs("tbody", { children: [_jsx(TableRow, { row: mockRow, prepareRow: prepareRow, hasInfiniteScroll: true, hasDropDown: true, expandedContent: sampleData.expandedContent, rowUuid: sampleData.uuid }), _jsx(TableRow, { row: mockRow2, prepareRow: prepareRow, hasInfiniteScroll: true, hasDropDown: false, rowUuid: sampleData2.uuid })] }) }));
139
- MultipleRows.parameters = {
140
- docs: {
141
- description: {
142
- story: "Two‑row table: the first row includes both cell truncation and a dropdown; the second row is static.",
143
- },
144
- },
145
- };
123
+ export const MultipleRows = () => (_jsx("table", { className: "min-w-[700px]", children: _jsxs("tbody", { children: [_jsx(TableRow, { row: mockRow, prepareRow: prepareRow, hasInfiniteScroll: true, onRowClick: () => alert("from row"), globalTrimActive: false, hasDropDown: true, rowUuid: sampleData.uuid, expandedContent: sampleData.expandedContent }), _jsx(TableRow, { row: mockRow2, prepareRow: prepareRow, hasInfiniteScroll: true, onRowClick: () => alert("from row"), globalTrimActive: false, hasDropDown: false, rowUuid: sampleData2.uuid })] }) }));
@@ -21,16 +21,20 @@ describe("TableRow - Branch Coverage Tests", () => {
21
21
  getRowProps: vi.fn(() => ({ key: "row-props-0" })),
22
22
  };
23
23
  it("covers isActive = true (row is active)", () => {
24
- render(_jsx("table", { children: _jsx("tbody", { children: _jsx(TableRow, { row: { ...baseMockRow, index: 5 }, prepareRow: mockPrepareRow, activeIndex: 5 }) }) }));
24
+ render(_jsx("table", { children: _jsx("tbody", { children: _jsx(TableRow, { row: { ...baseMockRow, index: 5 }, prepareRow: mockPrepareRow, activeIndex: 5, hasInfiniteScroll: false, onRowClick: function (index, rowUuid, event) {
25
+ throw new Error("Function not implemented.");
26
+ } }) }) }));
25
27
  expect(screen.getByTestId("table-row")).toHaveClass("activeRow");
26
28
  });
27
29
  it("covers isActive = false (row is NOT active)", () => {
28
- render(_jsx("table", { children: _jsx("tbody", { children: _jsx(TableRow, { row: { ...baseMockRow, index: 2 }, prepareRow: mockPrepareRow, activeIndex: 5 }) }) }));
30
+ render(_jsx("table", { children: _jsx("tbody", { children: _jsx(TableRow, { row: { ...baseMockRow, index: 2 }, prepareRow: mockPrepareRow, activeIndex: 5, hasInfiniteScroll: false, onRowClick: function (index, rowUuid, event) {
31
+ throw new Error("Function not implemented.");
32
+ } }) }) }));
29
33
  expect(screen.getByTestId("table-row")).not.toHaveClass("activeRow");
30
34
  });
31
35
  it("covers onRowClick = defined + rowUuid = provided", () => {
32
36
  const mockOnRowClick = vi.fn();
33
- render(_jsx("table", { children: _jsx("tbody", { children: _jsx(TableRow, { row: baseMockRow, prepareRow: mockPrepareRow, onRowClick: mockOnRowClick, rowUuid: "some-uuid" }) }) }));
37
+ render(_jsx("table", { children: _jsx("tbody", { children: _jsx(TableRow, { row: baseMockRow, prepareRow: mockPrepareRow, onRowClick: mockOnRowClick, rowUuid: "some-uuid", hasInfiniteScroll: false }) }) }));
34
38
  fireEvent.click(screen.getByTestId("table-row"));
35
39
  expect(mockOnRowClick).toHaveBeenCalledWith(baseMockRow.index, // 0
36
40
  "some-uuid", expect.anything() // Synthetic event
@@ -38,13 +42,15 @@ describe("TableRow - Branch Coverage Tests", () => {
38
42
  });
39
43
  it("covers onRowClick = defined + rowUuid = undefined (so calls empty string)", () => {
40
44
  const mockOnRowClick = vi.fn();
41
- render(_jsx("table", { children: _jsx("tbody", { children: _jsx(TableRow, { row: baseMockRow, prepareRow: mockPrepareRow, onRowClick: mockOnRowClick }) }) }));
45
+ render(_jsx("table", { children: _jsx("tbody", { children: _jsx(TableRow, { row: baseMockRow, prepareRow: mockPrepareRow, onRowClick: mockOnRowClick, hasInfiniteScroll: false }) }) }));
42
46
  fireEvent.click(screen.getByTestId("table-row"));
43
47
  expect(mockOnRowClick).toHaveBeenCalledWith(baseMockRow.index, // 0
44
48
  "", expect.anything());
45
49
  });
46
50
  it("covers onRowClick = NOT defined", () => {
47
- render(_jsx("table", { children: _jsx("tbody", { children: _jsx(TableRow, { row: baseMockRow, prepareRow: mockPrepareRow }) }) }));
51
+ render(_jsx("table", { children: _jsx("tbody", { children: _jsx(TableRow, { row: baseMockRow, prepareRow: mockPrepareRow, hasInfiniteScroll: false, onRowClick: function (index, rowUuid, event) {
52
+ throw new Error("Function not implemented.");
53
+ } }) }) }));
48
54
  // onRowClick not provided; just ensure no crash
49
55
  fireEvent.click(screen.getByTestId("table-row"));
50
56
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agilant/toga-blox",
3
3
  "private": false,
4
- "version": "1.0.162",
4
+ "version": "1.0.163",
5
5
  "description": "",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",