@threadlabs/looma 0.19.0 → 0.19.1

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.
@@ -324,7 +324,7 @@
324
324
  padding: var(--_ui-tree-item-label-padding-block, var(--ui-space-1)) var(--_ui-tree-item-label-padding-inline, var(--ui-space-2));
325
325
  /* The length of the fade before the controls. The label's one flex child lays out no gap; this
326
326
  is where the controller reads the length in pixels to stop a sliding name before the fade. */
327
- column-gap: var(--ui-space-3);
327
+ column-gap: var(--ui-space-1);
328
328
  }
329
329
 
330
330
  /* Slotted label content fills the cell, so a link is the row's hit area rather than sizing to
@@ -352,7 +352,7 @@
352
352
  text-overflow: clip;
353
353
  mask-image: linear-gradient(
354
354
  to right,
355
- #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
355
+ #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-1)),
356
356
  transparent calc(100% - var(--_tree-actions-width, 1.75rem))
357
357
  );
358
358
  }
@@ -361,7 +361,7 @@
361
361
  .row:focus-within > .label:dir(rtl) {
362
362
  mask-image: linear-gradient(
363
363
  to left,
364
- #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
364
+ #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-1)),
365
365
  transparent calc(100% - var(--_tree-actions-width, 1.75rem))
366
366
  );
367
367
  }
@@ -388,7 +388,7 @@
388
388
  to right,
389
389
  transparent var(--_marquee-icon-width, 0px),
390
390
  #000 calc(var(--_marquee-lead, 0px) + var(--_ui-tree-item-label-padding-inline, var(--ui-space-2))),
391
- #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
391
+ #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-1)),
392
392
  transparent calc(100% - var(--_tree-actions-width, 1.75rem))
393
393
  );
394
394
  }
@@ -398,7 +398,7 @@
398
398
  to left,
399
399
  transparent var(--_marquee-icon-width, 0px),
400
400
  #000 calc(var(--_marquee-lead, 0px) + var(--_ui-tree-item-label-padding-inline, var(--ui-space-2))),
401
- #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-3)),
401
+ #000 calc(100% - var(--_tree-actions-width, 1.75rem) - var(--ui-space-1)),
402
402
  transparent calc(100% - var(--_tree-actions-width, 1.75rem))
403
403
  );
404
404
  }
@@ -112,17 +112,34 @@ export default function controller(host) {
112
112
  // The tree sets this for its items; an item's own prop overrides it either way.
113
113
  const marqueeWanted = () => host.state.marquee
114
114
  || getComputedStyle(element).getPropertyValue("--_ui-default-tree-item-marquee").trim() === "1";
115
+ // A slotted link may fill the row and have padding past its name. Measure the rendered letters,
116
+ // since moving that link's box to the actions would send a short name too far (or move it at all).
117
+ const textEdge = (rightToLeft) => {
118
+ const walker = element.ownerDocument.createTreeWalker(labelText, NodeFilter.SHOW_TEXT);
119
+ const range = element.ownerDocument.createRange();
120
+ let edge = rightToLeft ? Infinity : -Infinity;
121
+ while (walker.nextNode()) {
122
+ if (!walker.currentNode.textContent?.trim()) continue;
123
+ range.selectNodeContents(walker.currentNode);
124
+ for (const rect of range.getClientRects()) {
125
+ if (rect.width === 0 || rect.height === 0) continue;
126
+ edge = rightToLeft ? Math.min(edge, rect.left) : Math.max(edge, rect.right);
127
+ }
128
+ }
129
+ return Number.isFinite(edge) ? edge : rightToLeft
130
+ ? labelText.getBoundingClientRect().left : labelText.getBoundingClientRect().right;
131
+ };
115
132
  const startMarquee = () => {
116
133
  if (!labelText || !label || !marqueeWanted()) return;
117
134
  labelText.style.flex = "none";
118
135
  labelText.style.inlineSize = "max-content";
119
- const text = labelText.getBoundingClientRect();
136
+ const rightToLeft = getComputedStyle(element).direction === "rtl";
137
+ const end = textEdge(rightToLeft);
120
138
  labelText.style.flex = labelText.style.inlineSize = "";
121
139
  const cell = label.getBoundingClientRect();
122
140
  const icon = leading?.getBoundingClientRect();
123
141
  const stop = (actions?.offsetWidth ?? 0) + parseFloat(getComputedStyle(label).columnGap);
124
- const rightToLeft = getComputedStyle(element).direction === "rtl";
125
- const distance = Math.ceil(rightToLeft ? cell.left + stop - text.left : text.right - (cell.right - stop));
142
+ const distance = Math.ceil(rightToLeft ? cell.left + stop - end : end - (cell.right - stop));
126
143
  if (distance <= 0) return;
127
144
  const lead = icon?.width ? (rightToLeft ? icon.right - cell.right : cell.left - icon.left) : 0;
128
145
  row.style.setProperty("--_marquee-lead", `${Math.max(0, lead)}px`);