@@ -20446,11 +20446,11 @@ class ClaudeOrchestrator {
2044620446 <div class="task-card-meta">${escapeHtml(meta)}</div>
2044720447 <div class="task-card-top-right">${quickLaunchHtml}</div>
2044820448 </div>
20449- <div class="task-card-title">${title}</div>
20450- </div>
20451- `;
20452- })
20453- .join('')}
20449+ <div class="task-card-title" title="${escapeHtml(String(c?.name || ''))} ">${title}</div>
20450+ </div>
20451+ `;
20452+ })
20453+ .join('')}
2045420454 </div>
2045520455 </div>
2045620456 `;
@@ -20482,41 +20482,91 @@ class ClaudeOrchestrator {
2048220482 return;
2048320483 }
2048420484
20485- const containerHeight = cardsContainer.clientHeight;
20486- if (!containerHeight || containerHeight < 40) return;
20485+ const containerHeight = cardsContainer.clientHeight;
20486+ if (!containerHeight || containerHeight < 40) {
20487+ col.style.setProperty('--tasks-card-columns', '1');
20488+ col.style.setProperty('--tasks-card-rows', '1');
20489+ col.style.width = '';
20490+ col.style.minWidth = '';
20491+
20492+ const tries = Number(col.dataset.tasksWrapExpandRetry || '0') || 0;
20493+ if (tries < 4) {
20494+ col.dataset.tasksWrapExpandRetry = String(tries + 1);
20495+ window.requestAnimationFrame(() => computeForColumn(col));
20496+ } else {
20497+ delete col.dataset.tasksWrapExpandRetry;
20498+ }
20499+ return;
20500+ }
20501+ delete col.dataset.tasksWrapExpandRetry;
20502+
20503+ const styles = window.getComputedStyle(cardsContainer);
20504+ const rowGap = Number.parseFloat(styles.rowGap || styles.gap || '0') || 0;
20505+ const columnGap = Number.parseFloat(styles.columnGap || styles.gap || '0') || 0;
20506+ const padLeft = Number.parseFloat(styles.paddingLeft || '0') || 0;
20507+ const padRight = Number.parseFloat(styles.paddingRight || '0') || 0;
20508+
20509+ const measureSampleHeights = () => {
20510+ const maxSamples = Math.min(24, cardCount);
20511+ if (maxSamples <= 0) return [];
20512+ const step = Math.max(1, Math.floor(cardCount / maxSamples));
20513+ const heights = [];
20514+ for (let i = 0; i < cardCount && heights.length < maxSamples; i += step) {
20515+ const h = cards[i]?.getBoundingClientRect?.().height;
20516+ if (h) heights.push(h);
20517+ }
20518+ return heights;
20519+ };
2048720520
20488- const styles = window.getComputedStyle(cardsContainer);
20489- const rowGap = Number.parseFloat(styles.rowGap || styles.gap || '0') || 0;
20490- const sample = cards.slice(0, Math.min(6, cardCount));
20491- const heights = sample.map(el => el.getBoundingClientRect().height).filter(Boolean);
20492- const avg = heights.length ? (heights.reduce((a, b) => a + b, 0) / heights.length) : 80;
20493- const denom = Math.max(1, avg + rowGap);
20494- let rowsFit = Math.max(1, Math.floor((containerHeight + rowGap) / denom));
20495- rowsFit = Math.min(rowsFit, 12);
20521+ const heights = measureSampleHeights().sort((a, b) => a - b);
20522+ const median = heights.length ? heights[Math.floor(heights.length / 2)] : 80;
20523+ const denom = Math.max(1, median + rowGap);
20524+ let rowsFit = Math.max(1, Math.floor((containerHeight + rowGap) / denom));
20525+ rowsFit = Math.min(rowsFit, cardCount);
2049620526
2049720527 const apply = (rows) => {
2049820528 const r = Math.max(1, Number(rows) || 1);
2049920529 const cols = Math.max(1, Math.ceil(cardCount / r));
2050020530 col.style.setProperty('--tasks-card-rows', String(r));
2050120531 col.style.setProperty('--tasks-card-columns', String(cols));
20502- if (cols <= 1) {
20503- col.style.width = '';
20504- col.style.minWidth = '';
20505- } else {
20506- const target = Math.max(baseWidth, baseWidth * cols);
20507- col.style.width = `${Math.round(target)}px`;
20508- col.style.minWidth = `${Math.round(target)}px`;
20509- }
20510- };
20532+ if (cols <= 1) {
20533+ col.style.width = '';
20534+ col.style.minWidth = '';
20535+ } else {
20536+ // Match CSS `minmax(180px, 1fr)` for card columns; expand only as much as needed.
20537+ const minCardWidth = 180;
20538+ const cardsWidth = (cols * minCardWidth) + Math.max(0, cols - 1) * columnGap;
20539+ const target = Math.max(baseWidth, cardsWidth + padLeft + padRight);
20540+ col.style.width = `${Math.round(target)}px`;
20541+ col.style.minWidth = `${Math.round(target)}px`;
20542+ }
20543+ };
2051120544
20512- apply(rowsFit);
20513- for (let attempt = 0; attempt < 6; attempt++) {
20514- void cardsContainer.offsetHeight;
20515- if (cardsContainer.scrollHeight <= cardsContainer.clientHeight + 1) break;
20516- rowsFit = Math.max(1, rowsFit - 1);
20517- apply(rowsFit);
20518- }
20519- };
20545+ apply(rowsFit);
20546+ const fits = () => (cardsContainer.scrollHeight <= cardsContainer.clientHeight + 1);
20547+
20548+ // If we overflow vertically, reduce rows (creating more columns) until we fit.
20549+ for (let attempt = 0; attempt < 24; attempt++) {
20550+ void cardsContainer.offsetHeight;
20551+ if (fits()) break;
20552+ rowsFit = Math.max(1, rowsFit - 1);
20553+ apply(rowsFit);
20554+ }
20555+
20556+ // If we fit, try to maximize rows (minimize columns) by filling vertically first.
20557+ for (let attempt = 0; attempt < 24; attempt++) {
20558+ if (rowsFit >= cardCount) break;
20559+ const next = rowsFit + 1;
20560+ apply(next);
20561+ void cardsContainer.offsetHeight;
20562+ if (fits()) {
20563+ rowsFit = next;
20564+ continue;
20565+ }
20566+ apply(rowsFit);
20567+ break;
20568+ }
20569+ };
2052020570
2052120571 window.requestAnimationFrame(() => {
2052220572 columns.forEach(computeForColumn);
@@ -20929,11 +20979,11 @@ class ClaudeOrchestrator {
2092920979 </div>
2093020980 </div>
2093120981 </div>
20932- <div class="task-card-title">${title}</div>
20933- <div class="task-card-meta">${due ? `<span class="task-card-due" title="Due">${escapeHtml(due)}</span> • ` : ''}${last}</div>
20934- </div>
20935- `;
20936- }).join('')}
20982+ <div class="task-card-title" title="${escapeHtml(String(c?.name || ''))} ">${title}</div>
20983+ <div class="task-card-meta">${due ? `<span class="task-card-due" title="Due">${escapeHtml(due)}</span> • ` : ''}${last}</div>
20984+ </div>
20985+ `;
20986+ }).join('')}
2093720987 </div>
2093820988 </div>
2093920989 `;
@@ -20978,24 +21028,51 @@ class ClaudeOrchestrator {
2097821028 col.style.setProperty('--tasks-card-columns', '1');
2097921029 col.style.setProperty('--tasks-card-rows', '1');
2098021030 return;
20981- }
21031+ }
21032+
21033+ const containerHeight = cardsContainer.clientHeight;
21034+ if (!containerHeight || containerHeight < 40) {
21035+ col.style.setProperty('--tasks-card-columns', '1');
21036+ col.style.setProperty('--tasks-card-rows', '1');
21037+ col.style.width = '';
21038+ col.style.minWidth = '';
21039+
21040+ const tries = Number(col.dataset.tasksWrapExpandRetry || '0') || 0;
21041+ if (tries < 4) {
21042+ col.dataset.tasksWrapExpandRetry = String(tries + 1);
21043+ window.requestAnimationFrame(() => computeForColumn(col));
21044+ } else {
21045+ delete col.dataset.tasksWrapExpandRetry;
21046+ }
21047+ return;
21048+ }
21049+ delete col.dataset.tasksWrapExpandRetry;
21050+
21051+ const styles = window.getComputedStyle(cardsContainer);
21052+ const rowGap = Number.parseFloat(styles.rowGap || styles.gap || '0') || 0;
21053+ const columnGap = Number.parseFloat(styles.columnGap || styles.gap || '0') || 0;
21054+ const padLeft = Number.parseFloat(styles.paddingLeft || '0') || 0;
21055+ const padRight = Number.parseFloat(styles.paddingRight || '0') || 0;
21056+
21057+ const measureSampleHeights = () => {
21058+ const maxSamples = Math.min(24, cardCount);
21059+ if (maxSamples <= 0) return [];
21060+ const step = Math.max(1, Math.floor(cardCount / maxSamples));
21061+ const heights = [];
21062+ for (let i = 0; i < cardCount && heights.length < maxSamples; i += step) {
21063+ const h = cards[i]?.getBoundingClientRect?.().height;
21064+ if (h) heights.push(h);
21065+ }
21066+ return heights;
21067+ };
2098221068
20983- const containerHeight = cardsContainer.clientHeight;
20984- if (!containerHeight || containerHeight < 40) return;
20985-
20986- const styles = window.getComputedStyle(cardsContainer);
20987- const rowGap = Number.parseFloat(styles.rowGap || styles.gap || '0') || 0;
20988- const columnGap = Number.parseFloat(styles.columnGap || styles.gap || '0') || 0;
20989- const padLeft = Number.parseFloat(styles.paddingLeft || '0') || 0;
20990- const padRight = Number.parseFloat(styles.paddingRight || '0') || 0;
20991- const sample = cards.slice(0, Math.min(6, cardCount));
20992- const heights = sample.map(el => el.getBoundingClientRect().height).filter(Boolean);
20993- const avg = heights.length ? (heights.reduce((a, b) => a + b, 0) / heights.length) : 80;
20994- const denom = Math.max(1, avg + rowGap);
20995- let rowsFit = Math.max(1, Math.floor((containerHeight + rowGap) / denom));
20996- // In wrap+expand mode, prefer minimizing the number of columns by filling vertically first
20997- // (as long as we still avoid vertical scrolling).
20998- rowsFit = Math.min(rowsFit, cardCount);
21069+ const heights = measureSampleHeights().sort((a, b) => a - b);
21070+ const median = heights.length ? heights[Math.floor(heights.length / 2)] : 80;
21071+ const denom = Math.max(1, median + rowGap);
21072+ let rowsFit = Math.max(1, Math.floor((containerHeight + rowGap) / denom));
21073+ // In wrap+expand mode, prefer minimizing the number of columns by filling vertically first
21074+ // (as long as we still avoid vertical scrolling).
21075+ rowsFit = Math.min(rowsFit, cardCount);
2099921076
2100021077 const apply = (rows) => {
2100121078 const r = Math.max(1, Number(rows) || 1);
@@ -21015,18 +21092,33 @@ class ClaudeOrchestrator {
2101521092 col.style.minWidth = `${Math.round(target)}px`;
2101621093 }
2101721094 };
21095+
21096+ apply(rowsFit);
21097+ const fits = () => (cardsContainer.scrollHeight <= cardsContainer.clientHeight + 1);
21098+
21099+ // If we still overflow vertically, reduce rows (creating more columns) until we fit.
21100+ for (let attempt = 0; attempt < 24; attempt++) {
21101+ // Force reflow and then check overflow.
21102+ void cardsContainer.offsetHeight;
21103+ if (fits()) break;
21104+ rowsFit = Math.max(1, rowsFit - 1);
21105+ apply(rowsFit);
21106+ }
2101821107
21019- apply(rowsFit);
21020-
21021- // If we still overflow vertically, reduce rows (creating more columns) until we fit.
21022- for (let attempt = 0; attempt < 24; attempt++) {
21023- // Force reflow and then check overflow.
21024- void cardsContainer.offsetHeight;
21025- if (cardsContainer.scrollHeight <= cardsContainer.clientHeight + 1) break;
21026- rowsFit = Math.max(1, rowsFit - 1);
21027- apply(rowsFit);
21028- }
21029- };
21108+ // If we fit, try to maximize rows (minimize columns) by filling vertically first.
21109+ for (let attempt = 0; attempt < 24; attempt++) {
21110+ if (rowsFit >= cardCount) break;
21111+ const next = rowsFit + 1;
21112+ apply(next);
21113+ void cardsContainer.offsetHeight;
21114+ if (fits()) {
21115+ rowsFit = next;
21116+ continue;
21117+ }
21118+ apply(rowsFit);
21119+ break;
21120+ }
21121+ };
2103021122
2103121123 // Clear variables for collapsed columns to avoid stale widths.
2103221124 for (const col of columns) {
0 commit comments