@agilant/toga-blox 1.0.319-beta.78 → 1.0.319-beta.80

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.
@@ -202,7 +202,6 @@
202
202
  justify-content: flex-start;
203
203
  align-items: center;
204
204
  gap: var(--sideNav-navigationItem-gap);
205
- padding: var(--sideNav-navigationItem-padding);
206
205
  border-radius: var(--sideNav-navigationItem-border-radius);
207
206
 
208
207
  &:hover {
@@ -217,14 +216,14 @@
217
216
  background: var(--sideNav-navigationItem-bg-active);
218
217
  }
219
218
 
220
- /* link that's next to the icon within each nav item */
219
+ /* actual link */
221
220
  .navigationItemLink {
222
221
  width: 100%;
223
222
  height: fit-content;
224
- padding: 0;
225
223
  background: transparent;
226
224
  color: inherit;
227
225
  place-content: start;
226
+ padding: var(--sideNav-navigationItem-padding);
228
227
 
229
228
  &:hover,
230
229
  &:focus,
@@ -208,7 +208,7 @@
208
208
  color: var(--primaryTable-header-text-default);
209
209
  box-shadow: inset 0 -1px 0 var(--primaryTable-border-default);
210
210
  text-wrap: nowrap;
211
- padding: 12px 16px;
211
+ padding: 10px 16px;
212
212
  font-size: var(--primaryTable-header-fontSize-default);
213
213
  font-weight: var(--primaryTable-header-fontWeight-default);
214
214
  }
@@ -219,7 +219,7 @@
219
219
  }
220
220
  .headerCell.supply-nested {
221
221
  text-transform: none;
222
- padding: 8px 12px;
222
+ padding: 10px 16px;
223
223
  font-size: var(--primaryTable-header-fontSize-default);
224
224
  }
225
225
 
@@ -386,13 +386,13 @@
386
386
  }
387
387
  .bodyCell.supply,
388
388
  .bodyCell.supply-modal-table {
389
- padding: 8px 12px;
389
+ padding: 10px 16px;
390
390
  }
391
391
  .bodyCell.supply-nested {
392
- padding: 8px 12px;
392
+ padding: 10px 16px;
393
393
  }
394
394
  .bodyCell.desk {
395
- padding: 8px 12px;
395
+ padding: 10px 16px;
396
396
  }
397
397
 
398
398
  /* ── Table wrapper ───────────────────────────────────────────────── */
@@ -94,16 +94,15 @@ export const PrimaryTable = (props) => {
94
94
  // configured getSize(), losing the content-based sizing (e.g. a long
95
95
  // Description column collapsing to the default width).
96
96
  //
97
- // So we keep auto-layout for the first paint (columns size to content
98
- // exactly as before), measure the resulting column widths, then pin
99
- // those exact pixel widths via a <colgroup> + table-layout: fixed. The
100
- // content-based widths are preserved and frozen, so scrolling can no
101
- // longer reflow them. Non-virtualized modal tables render every row, so
102
- // they never jitter and stay on plain auto-layout.
103
- // Modal tables normally stay on auto-layout (they render every row, so
104
- // they never jitter). But resizing needs a measured pixel baseline +
105
- // table-layout: fixed, so opt them into freezing when resize is enabled.
106
- const shouldFreeze = skin !== "supply-modal-table" || !!resizableColumns || !!shrinkColumns;
97
+ // So we keep auto-layout for the first paint, measure the natural content
98
+ // width of each column (header label + controls vs. widest body value),
99
+ // then pin those exact pixel widths via a <colgroup> + table-layout: fixed.
100
+ // The content-based widths are preserved and frozen, so scrolling can no
101
+ // longer reflow them. Non-virtualized modal tables don't jitter, but they
102
+ // freeze too so they get the same content-fit sizing (and so resize has a
103
+ // measured pixel baseline) only an empty table (no rows to measure) stays
104
+ // on plain auto-layout.
105
+ const shouldFreeze = true;
107
106
  const leafColumnKey = (table?.getAllLeafColumns() ?? [])
108
107
  .map((c) => c.id)
109
108
  .join("|");
@@ -134,37 +133,51 @@ export const PrimaryTable = (props) => {
134
133
  const cells = Array.from(leafRow.children);
135
134
  if (cells.length === 0)
136
135
  return;
137
- const widths = cells.map((c) => c.getBoundingClientRect().width);
138
- // Skip a pre-layout pass where the table hasn't been measured yet.
139
- if (widths.every((w) => w === 0))
136
+ // Bail on a pre-layout pass where nothing has been laid out yet.
137
+ if (cells.every((c) => c.getBoundingClientRect().width === 0))
140
138
  return;
141
- setFrozenWidths(widths);
142
- // Floor each column at its widest *body* cell so the longest value never
143
- // truncates — and only the body, not the header. Seeding with the header
144
- // would pin header-dominated columns (e.g. a short NUMBER/CURRENCY value
145
- // under a longer label like "Qty Fulfilled") to their full header width,
146
- // leaving no slack to shrink. So we measure body cells only and let the
147
- // header label ellipsize. The header is a per-column fallback used only
148
- // where a column has no measurable body content (empty cells / no rows).
149
- const bodyFloors = new Array(cells.length).fill(0);
139
+ // Widest *body* content per column (the full pre-ellipsis width each
140
+ // value wants). Virtualizer spacer rows have a different cell count and
141
+ // are skipped.
142
+ const bodyContent = new Array(cells.length).fill(0);
150
143
  const body = head.parentElement?.querySelector("tbody");
151
144
  if (body) {
152
145
  const bodyRows = Array.from(body.querySelectorAll(":scope > tr"));
153
146
  for (const tr of bodyRows) {
154
147
  const tds = Array.from(tr.children);
155
- // Skip virtualizer spacer rows — they have no leaf cells.
156
148
  if (tds.length !== cells.length)
157
149
  continue;
158
150
  tds.forEach((td, i) => {
159
151
  const w = measureCellContentWidth(td);
160
- if (w > bodyFloors[i])
161
- bodyFloors[i] = w;
152
+ if (w > bodyContent[i])
153
+ bodyContent[i] = w;
162
154
  });
163
155
  }
164
156
  }
165
- const floors = cells.map((c, i) => bodyFloors[i] > 0 ? bodyFloors[i] : measureCellContentWidth(c));
157
+ // Freeze each column to its natural content width = the larger of the
158
+ // header (its label plus the sort/filter controls) and the widest body
159
+ // value, so neither the header nor any cell value truncates. This
160
+ // replaces the old behavior of freezing the rendered cell width, which
161
+ // was pinned to the configured size/minSize (≥120/≥200) on first paint —
162
+ // columns now shrink to fit their content instead of a flat floor. A
163
+ // column with an explicitly assigned width (size === minSize, set from
164
+ // columnWidths) keeps that exact width.
165
+ const leafColumns = table?.getAllLeafColumns() ?? [];
166
+ const widths = cells.map((c, i) => {
167
+ const def = leafColumns[i]?.columnDef;
168
+ if (def?.size != null && def.size === def.minSize)
169
+ return def.size;
170
+ return Math.max(measureCellContentWidth(c), bodyContent[i]);
171
+ });
172
+ setFrozenWidths(widths);
173
+ // Shrink floor (used only by shrinkColumns): the widest *body* cell so
174
+ // the longest value never truncates when columns are squeezed to fit a
175
+ // narrow container, while the header label is allowed to ellipsize. The
176
+ // header is a per-column fallback used only where a column has no
177
+ // measurable body content (empty cells / no rows).
178
+ const floors = cells.map((c, i) => bodyContent[i] > 0 ? bodyContent[i] : measureCellContentWidth(c));
166
179
  setContentFloors(floors);
167
- }, [shouldFreeze, frozenWidths, rows.length, leafColumnKey]);
180
+ }, [shouldFreeze, frozenWidths, rows.length, leafColumnKey, table]);
168
181
  // ── Shrink-to-fit (modal tables) ────────────────────────────────────
169
182
  // When shrinkColumns is on we don't render the table at its frozen
170
183
  // content widths; we scale those widths down to the visible container so
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agilant/toga-blox",
3
3
  "private": false,
4
- "version": "1.0.319-beta.78",
4
+ "version": "1.0.319-beta.80",
5
5
  "description": "Toga-Blox is a comprehensive and reusable React component library",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",