@ai-matrx/design-system 0.61.9 → 0.61.10
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.
- package/CHANGELOG.md +10 -0
- package/dist/index.cjs +32 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.61.10 — the pill guard flags a stretched pill
|
|
4
|
+
|
|
5
|
+
- Pill guard: a capsule whose content box is more than 8px wider than its own ink (text runs plus
|
|
6
|
+
in-flow glyphs) is outlined as STRETCHED — a pill hugs its label; a full-width tappable item is a
|
|
7
|
+
row, never a pill. Measured: /education/overview's metric pills filled their grid columns at 375px
|
|
8
|
+
(label left, up to 103px of empty capsule right). Only measured where the engine reports line
|
|
9
|
+
boxes; `data-matrx-pill="off"` still opts a deliberately wide capsule out. Guard case red on 0.61.9.
|
|
10
|
+
|
|
11
|
+
No consumer action.
|
|
12
|
+
|
|
3
13
|
## 0.61.9
|
|
4
14
|
### a scope lane is never clipped
|
|
5
15
|
|
package/dist/index.cjs
CHANGED
|
@@ -664,6 +664,7 @@ function Badge({ className, variant, children, title, ...props }) {
|
|
|
664
664
|
|
|
665
665
|
// src/pill-guard.ts
|
|
666
666
|
var PILL_MAX_WIDTH_PX = 320;
|
|
667
|
+
var PILL_STRETCH_TOLERANCE_PX = 8;
|
|
667
668
|
var SELECTOR = [
|
|
668
669
|
'[data-slot="badge"]',
|
|
669
670
|
"[data-matrx-pill]",
|
|
@@ -719,8 +720,39 @@ function findPillViolation(el, maxWidth = PILL_MAX_WIDTH_PX) {
|
|
|
719
720
|
if (lines > 1) {
|
|
720
721
|
return `pill wraps to ${lines} lines holding "${describe(el)}" \u2014 a pill is one line: clamp it (Badge, or truncate + max-w + title) or render a list row.`;
|
|
721
722
|
}
|
|
723
|
+
const slack = stretchSlack(el, own, cs, rect.width, view);
|
|
724
|
+
if (slack !== null && slack > PILL_STRETCH_TOLERANCE_PX) {
|
|
725
|
+
return `pill is stretched: ${Math.round(slack)}px of empty capsule beside "${describe(el)}" \u2014 a pill hugs its label; stop the parent stretching it (a grid cell: justify-self-start; drop w-full / flex-1), or render a full-width tappable item as a row, never a pill.`;
|
|
726
|
+
}
|
|
722
727
|
return null;
|
|
723
728
|
}
|
|
729
|
+
function stretchSlack(el, own, cs, width, view) {
|
|
730
|
+
const range = el.ownerDocument.createRange?.();
|
|
731
|
+
if (!range || typeof range.getClientRects !== "function") return null;
|
|
732
|
+
let left = Infinity;
|
|
733
|
+
let right = -Infinity;
|
|
734
|
+
const take = (r) => {
|
|
735
|
+
if (r.width <= 0 || r.height <= 0) return;
|
|
736
|
+
left = Math.min(left, r.left);
|
|
737
|
+
right = Math.max(right, r.right);
|
|
738
|
+
};
|
|
739
|
+
for (const node of own) {
|
|
740
|
+
if (!(node.textContent ?? "").trim()) continue;
|
|
741
|
+
range.selectNodeContents(node);
|
|
742
|
+
Array.from(range.getClientRects()).forEach(take);
|
|
743
|
+
}
|
|
744
|
+
range.detach?.();
|
|
745
|
+
if (!Number.isFinite(left)) return null;
|
|
746
|
+
el.querySelectorAll("svg, img").forEach((g) => {
|
|
747
|
+
for (let p = g; p && p !== el; p = p.parentElement) {
|
|
748
|
+
const pcs = view.getComputedStyle(p);
|
|
749
|
+
if (pcs.position === "absolute" || pcs.position === "fixed" || pcs.display === "none") return;
|
|
750
|
+
}
|
|
751
|
+
take(g.getBoundingClientRect());
|
|
752
|
+
});
|
|
753
|
+
const inner = width - px(cs.paddingLeft) - px(cs.paddingRight) - px(cs.borderLeftWidth) - px(cs.borderRightWidth);
|
|
754
|
+
return inner - (right - left);
|
|
755
|
+
}
|
|
724
756
|
function lineCount(el, own, cs, height) {
|
|
725
757
|
const range = el.ownerDocument.createRange?.();
|
|
726
758
|
if (range && typeof range.getClientRects === "function") {
|