feat(shared): add cn utility for tailwind-aware class merging #38
@@ -61,6 +61,26 @@ const comparisonEngine = new CharacterComparisonEngine();
|
||||
|
||||
let layoutResult = $state<ReturnType<typeof comparisonEngine.layout>>({ lines: [], totalHeight: 0 });
|
||||
|
||||
// Track container width changes (window resize, sidebar toggle, etc.)
|
||||
$effect(() => {
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
const observer = new ResizeObserver(entries => {
|
||||
for (const entry of entries) {
|
||||
// Use borderBoxSize if available, fallback to contentRect
|
||||
const width = entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width;
|
||||
if (width > 0) {
|
||||
containerWidth = width;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(container);
|
||||
return () => observer.disconnect();
|
||||
});
|
||||
|
||||
const sliderSpring = new Spring(50, {
|
||||
stiffness: 0.2,
|
||||
damping: 0.7,
|
||||
@@ -124,25 +144,25 @@ $effect(() => {
|
||||
}
|
||||
});
|
||||
|
||||
// Layout effect — depends on content, settings AND containerWidth
|
||||
$effect(() => {
|
||||
const _text = comparisonStore.text;
|
||||
const _weight = typography.weight;
|
||||
const _size = typography.renderedSize;
|
||||
const _height = typography.height;
|
||||
const _spacing = typography.spacing;
|
||||
const _width = containerWidth;
|
||||
const _isMobile = isMobile;
|
||||
|
||||
if (container && fontA && fontB) {
|
||||
if (container && fontA && fontB && _width > 0) {
|
||||
// PRETEXT API strings: "weight sizepx family"
|
||||
const fontAStr = getPretextFontString(_weight, _size, fontA.name);
|
||||
const fontBStr = getPretextFontString(_weight, _size, fontB.name);
|
||||
|
||||
// Use offsetWidth to avoid transform scaling issues
|
||||
const width = container.offsetWidth;
|
||||
const padding = isMobile ? 48 : 96;
|
||||
const availableWidth = width - padding;
|
||||
const padding = _isMobile ? 48 : 96;
|
||||
const availableWidth = Math.max(0, _width - padding);
|
||||
const lineHeight = _size * _height;
|
||||
|
||||
containerWidth = width;
|
||||
layoutResult = comparisonEngine.layout(
|
||||
_text,
|
||||
fontAStr,
|
||||
@@ -155,30 +175,6 @@ $effect(() => {
|
||||
}
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
const handleResize = () => {
|
||||
if (container && fontA && fontB) {
|
||||
const width = container.offsetWidth;
|
||||
const padding = isMobile ? 48 : 96;
|
||||
containerWidth = width;
|
||||
layoutResult = comparisonEngine.layout(
|
||||
comparisonStore.text,
|
||||
getPretextFontString(typography.weight, typography.renderedSize, fontA.name),
|
||||
getPretextFontString(typography.weight, typography.renderedSize, fontB.name),
|
||||
width - padding,
|
||||
typography.renderedSize * typography.height,
|
||||
typography.spacing,
|
||||
typography.renderedSize,
|
||||
);
|
||||
}
|
||||
};
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
});
|
||||
|
||||
// Dynamic backgroundSize based on isMobile — can't express this in Tailwind.
|
||||
// Color is set to currentColor so it respects dark mode via text color.
|
||||
const gridStyle = $derived(
|
||||
@@ -273,8 +269,8 @@ const scaleClass = $derived(
|
||||
class={cn(
|
||||
'absolute z-10',
|
||||
responsive.isMobileOrTablet
|
||||
? 'bottom-4 right-4 -translate-1/2'
|
||||
: 'bottom-5 left-1/2 right-[unset] -translate-x-1/2',
|
||||
? 'bottom-0 right-0 -translate-1/2'
|
||||
: 'bottom-2.5 left-1/2 -translate-x-1/2',
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user