@pagamio/frontend-commons-lib 0.8.319 → 0.8.321

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,5 +1,13 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  const FilterWrapper = ({ isNarrow, children }) => {
3
- return (_jsx("div", { className: "bg-card shadow-xl rounded-lg p-4 mb-2", children: _jsx("div", { className: isNarrow ? 'flex flex-col w-full gap-3' : 'flex items-start justify-between gap-4 w-full', children: children }) }));
3
+ return (
4
+ // `min-w-0` so this card can shrink inside a flex/grid parent;
5
+ // `overflow-hidden` so wide filter rows never punch out of the toolbar.
6
+ _jsx("div", { className: "bg-card shadow-xl rounded-lg p-4 mb-2 min-w-0 overflow-hidden", children: _jsx("div", { className: isNarrow
7
+ ? 'flex flex-col w-full gap-3'
8
+ : // `flex-wrap` lets the filter pills drop onto a second row instead of
9
+ // overflowing the toolbar; each child group is set to `min-w-0` via its own
10
+ // styles so individual items can shrink too.
11
+ 'flex flex-wrap items-start justify-between gap-4 w-full min-w-0', children: children }) }));
4
12
  };
5
13
  export default FilterWrapper;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { MantineReactTable, useMantineReactTable } from 'mantine-react-table';
3
3
  import { HiPlusSm } from 'react-icons/hi';
4
- import { useMemo, useRef, useState } from 'react';
4
+ import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
5
5
  import { FilterComponent, IconButton } from '../../components';
6
6
  import { cn } from '../../helpers';
7
7
  import { useMediaQueries } from '../../shared';
@@ -104,18 +104,81 @@ function CustomToolbar({ filters, appliedFilters, onFilterChange, onApply, onCle
104
104
  const PagamioTable = ({ columns, data, isLoading = false, rowCount, sorting, pagination, filtering, search, onRowClick, rowClassName, expandable = false, renderDetailPanel, toolbar, toolbarMode = 'custom', enableColumnResizing, enableColumnPinning, enableColumnOrdering, enableColumnFilters, enableHiding, enableRowSelection, enableRowActions, enableRowVirtualization, enableGrouping, enableEditing, enableDensityToggle, enableFullScreenToggle, enableClickToCopy, enableRowNumbers, enableMultiSort, enableStickyHeader, enableStickyFooter, editDisplayMode, onEditingRowSave, onEditingRowCancel, renderRowActions, renderRowActionMenuItems, positionActionsColumn, renderTopToolbarCustomActions, renderBottomToolbarCustomActions, layoutMode, defaultColumn, mantineTableOptions, }) => {
105
105
  const [expanded, setExpanded] = useState({});
106
106
  const tableRef = useRef(null);
107
- // Note: previously this component force-applied
108
- // max-height: calc(100vh - {tableTop + 68}px)
109
- // to the inner mantine table container. That produced a "squeezed" table
110
- // whenever the table sat below other content (e.g. nested in tabs on the
111
- // event details page) — the table's own top was already far down the
112
- // viewport, so the leftover max-height was tiny and only ~3 rows showed
113
- // before an internal scroll kicked in.
107
+ // ── Internal max-height ─────────────────────────────────────────────
108
+ // The mantine table container is height-capped to `viewportHeight - tableTop`
109
+ // so that the table is the only scrolling element when its parent layout
110
+ // is fixed (page header + sidebar stay put). Without this, large datasets
111
+ // would push the page itself into a scroll, breaking the toolbar/header
112
+ // sticky behaviour that the rest of the app relies on.
114
113
  //
115
- // We now let the table render its natural height. Pagination caps the row
116
- // count, and the parent route layout already scrolls when the page is
117
- // taller than the viewport, so the user gets one continuous scroll instead
118
- // of a nested mini-scroll.
114
+ // Bottom margin reserves space for the bottom toolbar (pagination, ~52px)
115
+ // plus a small gap so the table doesn't sit flush against page edges.
116
+ const TABLE_BOTTOM_MARGIN = 68;
117
+ /**
118
+ * Walk up the DOM looking for the closest scrollable ancestor (i.e. an
119
+ * element with overflow-y: auto/scroll AND scrollHeight > clientHeight).
120
+ * If we find one, the *page* is what's scrolling — we should NOT cap the
121
+ * table's height because that would create a confusing nested scroll
122
+ * (page scroll + table scroll). Returns true when the table itself
123
+ * should manage its own scroll.
124
+ */
125
+ const tableShouldOwnScroll = (el) => {
126
+ let node = el.parentElement;
127
+ while (node && node !== document.body) {
128
+ const style = window.getComputedStyle(node);
129
+ const overflowY = style.overflowY;
130
+ const isScrollable = (overflowY === 'auto' || overflowY === 'scroll') && node.scrollHeight > node.clientHeight + 1;
131
+ if (isScrollable)
132
+ return false;
133
+ node = node.parentElement;
134
+ }
135
+ return true;
136
+ };
137
+ const applyTableHeight = (el) => {
138
+ const mrtContainer = el.querySelector('.mrt-table-container');
139
+ if (!mrtContainer)
140
+ return;
141
+ // If a parent is already handling the scroll, let the table render at
142
+ // its natural height — the user gets one continuous page scroll.
143
+ if (!tableShouldOwnScroll(el)) {
144
+ mrtContainer.style.removeProperty('max-height');
145
+ return;
146
+ }
147
+ const containerTop = mrtContainer.getBoundingClientRect().top;
148
+ const newMax = Math.round(Math.max(240, window.innerHeight - containerTop - TABLE_BOTTOM_MARGIN));
149
+ const newMaxStr = `${newMax}px`;
150
+ // Skip the write if the value hasn't changed — avoids re-layout loops
151
+ // with ResizeObserver where mutating the cell's max-height would refire
152
+ // the observer on the next frame.
153
+ if (mrtContainer.style.maxHeight === newMaxStr)
154
+ return;
155
+ mrtContainer.style.setProperty('max-height', newMaxStr, 'important');
156
+ };
157
+ // Runs once on mount + whenever the *window* resizes. We deliberately do
158
+ // NOT run on every render or use a ResizeObserver on the document — both
159
+ // produce loop conditions: applyTableHeight mutates layout, which fires
160
+ // the observer, which calls applyTableHeight again. The window-resize
161
+ // signal is sufficient because tableTop changes during a render get
162
+ // re-applied by useLayoutEffect-on-mount when the table remounts.
163
+ useLayoutEffect(() => {
164
+ if (tableRef.current)
165
+ applyTableHeight(tableRef.current);
166
+ }, []);
167
+ useEffect(() => {
168
+ const el = tableRef.current;
169
+ if (!el)
170
+ return;
171
+ let frame = 0;
172
+ const handler = () => {
173
+ cancelAnimationFrame(frame);
174
+ frame = requestAnimationFrame(() => applyTableHeight(el));
175
+ };
176
+ window.addEventListener('resize', handler);
177
+ return () => {
178
+ cancelAnimationFrame(frame);
179
+ window.removeEventListener('resize', handler);
180
+ };
181
+ }, []);
119
182
  // Process columns (handle showHeader: false)
120
183
  const processedColumns = useMemo(() => processColumns(columns), [columns]);
121
184
  // Convert our SortConfig to MRT's SortingState
package/lib/styles.css CHANGED
@@ -1551,6 +1551,9 @@ video {
1551
1551
  .flex-shrink-0 {
1552
1552
  flex-shrink: 0;
1553
1553
  }
1554
+ .shrink {
1555
+ flex-shrink: 1;
1556
+ }
1554
1557
  .shrink-0 {
1555
1558
  flex-shrink: 0;
1556
1559
  }
@@ -3889,14 +3892,25 @@ video {
3889
3892
  text-overflow: clip !important;
3890
3893
  }
3891
3894
 
3892
- /* MRT semantic mode: the explicit `width: <n>px` on each cell prevents the
3893
- table from filling its container — leftover space becomes dead gap on the
3894
- right. Treat the inline width as a minimum hint instead by overriding it
3895
- to `auto`; the browser's table-layout: auto then distributes width based
3896
- on content + min-width while filling 100% of the table width. */
3895
+ /* MRT semantic mode column sizing.
3896
+ *
3897
+ * MRT inlines `width: calc(--col-X-size * 1px)` and
3898
+ * `min-width: max(calc(--col-X-size * 1px), 50px)` on every cell. With
3899
+ * `table-layout: auto`, those fixed values cause two problems:
3900
+ * 1. Cells can't shrink below their min-width, leaving dead gaps when
3901
+ * content is short.
3902
+ * 2. The combined widths can exceed the container, leaving a horizontal
3903
+ * gap on the right.
3904
+ *
3905
+ * We override both: cells get `width: auto` and `min-width: 0` so the
3906
+ * browser sizes columns by content, then distributes remaining row space
3907
+ * proportionally. `whiteSpace: normal` (set above) lets long content wrap
3908
+ * instead of being crushed.
3909
+ */
3897
3910
  .mantine-Table-table > thead > tr > .mantine-Table-th,
3898
3911
  .mantine-Table-table > tbody > tr > .mantine-Table-td {
3899
3912
  width: auto !important;
3913
+ min-width: 0 !important;
3900
3914
  }
3901
3915
  .file\:-ms-4::file-selector-button {
3902
3916
  margin-inline-start: -1rem;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pagamio/frontend-commons-lib",
3
3
  "description": "Pagamio library for Frontend reusable components like the form engine and table container",
4
- "version": "0.8.319",
4
+ "version": "0.8.321",
5
5
  "publishConfig": {
6
6
  "access": "public",
7
7
  "provenance": false