Event titles style tuning. Larger text etc.
This commit is contained in:
@@ -7,7 +7,6 @@
|
||||
:style="{
|
||||
...segmentStyle(seg),
|
||||
'--segment-row-height': getSegmentRowHeight(seg),
|
||||
'--segment-scale-factor': getSegmentScaleFactor(seg),
|
||||
height: getSegmentTotalHeight(seg)
|
||||
}"
|
||||
>
|
||||
@@ -61,6 +60,46 @@ const justDragged = ref(false)
|
||||
const weekOverlayRef = ref(null)
|
||||
const segmentCompression = ref({}) // key -> boolean
|
||||
|
||||
// Font metrics ratios (ascent/descent relative to 1em) to align baselines and fit ascenders/descenders
|
||||
// Hardcoded from measured values: ascent: 0.9, descent: 0.25, total: 1.15
|
||||
const fmTotal = 1.15
|
||||
|
||||
/*
|
||||
// Measurement function retained for reference; disabled in favor of hardcoded metrics
|
||||
function measureFontMetrics() {
|
||||
try {
|
||||
const root = weekOverlayRef.value || document.documentElement
|
||||
const cs = getComputedStyle(root)
|
||||
const weight = '600'
|
||||
const family = cs.fontFamily || 'system-ui, sans-serif'
|
||||
const refSize = 100
|
||||
const font = `${weight} ${refSize}px ${family}`
|
||||
const canvas = document.createElement('canvas')
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (!ctx) return
|
||||
ctx.font = font
|
||||
const test = 'HgypQgjpq'
|
||||
const m = ctx.measureText(test)
|
||||
const ascPx = (m.fontBoundingBoxAscent ?? m.actualBoundingBoxAscent ?? 0)
|
||||
const descPx = (m.fontBoundingBoxDescent ?? m.actualBoundingBoxDescent ?? 0)
|
||||
let asc = ascPx / refSize
|
||||
let desc = descPx / refSize
|
||||
if (!isFinite(asc) || asc <= 0 || !isFinite(desc) || desc <= 0) {
|
||||
asc = 0.9
|
||||
desc = 0.25
|
||||
}
|
||||
asc = Math.min(Math.max(asc, 0.6), 0.95)
|
||||
desc = Math.min(Math.max(desc, 0.1), 0.4)
|
||||
const total = asc + desc
|
||||
console.log('[EventOverlay] Measured font metrics', { family, weight, ascent: asc, descent: desc, total })
|
||||
fm.value = { asc, desc, total }
|
||||
} catch (e) {
|
||||
fm.value = { asc: 0.9, desc: 0.25, total: 1.15 }
|
||||
try { console.log('[EventOverlay] Using default font metrics fallback', fm.value) } catch {}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Build event segments: each segment is a contiguous day range with at least one bridging event between any adjacent days within it.
|
||||
const eventSegments = computed(() => {
|
||||
// Construct spans across the week
|
||||
@@ -194,11 +233,6 @@ function getSegmentTotalHeight(seg) {
|
||||
return data && typeof data.totalHeight === 'number' ? `${data.totalHeight}px` : 'auto'
|
||||
}
|
||||
|
||||
function getSegmentScaleFactor(seg) {
|
||||
const data = segmentCompression.value[segmentKey(seg)]
|
||||
return data && typeof data.scaleFactor === 'number' ? data.scaleFactor : 1.0
|
||||
}
|
||||
|
||||
function recomputeCompression() {
|
||||
const el = weekOverlayRef.value
|
||||
if (!el) return
|
||||
@@ -210,32 +244,32 @@ function recomputeCompression() {
|
||||
const marginTop = 0 // already applied outside height
|
||||
const usable = Math.max(0, available - marginTop)
|
||||
const nextMap = {}
|
||||
|
||||
for (const seg of eventSegments.value) {
|
||||
const rowCount = seg.rowsCount || 1
|
||||
const gapPx = 2 // gap between grid rows
|
||||
const totalGaps = Math.max(0, rowCount - 1) * gapPx
|
||||
const desired = rowCount * baseRowPx + totalGaps
|
||||
const desired = rowCount * baseRowPx
|
||||
const needsScaling = desired > usable
|
||||
|
||||
// Row height may be reduced to fit segment within available vertical space
|
||||
let finalRowHeight = baseRowPx
|
||||
if (needsScaling) {
|
||||
// Calculate the scaled row height that fits within available space
|
||||
const availableForRows = usable - totalGaps
|
||||
const scaledRowHeight = Math.max(0, availableForRows) / rowCount
|
||||
// Never scale larger than the base size
|
||||
const finalRowHeight = Math.min(scaledRowHeight, baseRowPx)
|
||||
const scaleFactor = finalRowHeight / baseRowPx
|
||||
nextMap[segmentKey(seg)] = {
|
||||
rowHeight: finalRowHeight,
|
||||
totalHeight: finalRowHeight * rowCount + totalGaps,
|
||||
scaleFactor: scaleFactor
|
||||
}
|
||||
} else {
|
||||
// Use base size when there's enough space
|
||||
nextMap[segmentKey(seg)] = {
|
||||
rowHeight: baseRowPx,
|
||||
totalHeight: desired,
|
||||
scaleFactor: 1.0
|
||||
}
|
||||
const scaledRowHeight = usable / rowCount
|
||||
finalRowHeight = Math.min(scaledRowHeight, baseRowPx)
|
||||
}
|
||||
|
||||
// Event-level scaling not applied for horizontal fitting in this task
|
||||
const segmentData = {
|
||||
rowHeight: finalRowHeight,
|
||||
totalHeight: needsScaling ? usable : desired,
|
||||
events: {}
|
||||
}
|
||||
|
||||
// Populate per-event map (reserved for future use)
|
||||
for (const event of seg.events) {
|
||||
segmentData.events[event.id + '-' + (event.n || 0)] = {}
|
||||
}
|
||||
|
||||
nextMap[segmentKey(seg)] = segmentData
|
||||
}
|
||||
segmentCompression.value = nextMap
|
||||
}
|
||||
@@ -576,7 +610,6 @@ function applyRangeDuringDrag(st, startDate, endDate) {
|
||||
}
|
||||
.segment-grid {
|
||||
display: grid;
|
||||
gap: 2px;
|
||||
align-content: start;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
@@ -585,24 +618,32 @@ function applyRangeDuringDrag(st, startDate, endDate) {
|
||||
}
|
||||
|
||||
.event-span {
|
||||
padding: calc(0.1em * var(--segment-scale-factor, 1)) calc(0.3em * var(--segment-scale-factor, 1));
|
||||
border-radius: calc(1em * var(--segment-scale-factor, 1));
|
||||
font-size: calc(clamp(0.45em, 1.8vh, 0.75em) * var(--segment-scale-factor, 1));
|
||||
padding: 0;
|
||||
border-radius: 1rem;
|
||||
/* Font-size so that ascender+descender exactly fills the row height:
|
||||
given total = asc+desc at 1em (hardcoded 1.15), font-size = rowHeight / total */
|
||||
font-size: calc(var(--segment-row-height, 1.5em) / 1.15);
|
||||
font-weight: 600;
|
||||
cursor: grab;
|
||||
pointer-events: auto;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
/* Use unitless 1 so line box = font-size; combined with computed font-size above,
|
||||
this makes the text box (asc+desc) fill the available row height */
|
||||
line-height: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* Vertically anchor to top so baselines align across rows; we'll center text vertically by
|
||||
using cap/descender metrics inside the child */
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
z-index: 10;
|
||||
text-align: center;
|
||||
touch-action: none;
|
||||
backdrop-filter: blur(.05rem);
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.event-span.cont-prev {
|
||||
@@ -615,17 +656,21 @@ function applyRangeDuringDrag(st, startDate, endDate) {
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
/* Inner title wrapper ensures proper ellipsis within flex/grid constraints */
|
||||
.event-title {
|
||||
display: block;
|
||||
flex: 1 1 0%;
|
||||
flex: 0 1 auto;
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 100%;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
/* Resize handles */
|
||||
@@ -633,7 +678,7 @@ function applyRangeDuringDrag(st, startDate, endDate) {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 6px;
|
||||
width: 1rem;
|
||||
background: transparent;
|
||||
z-index: 2;
|
||||
cursor: ew-resize;
|
||||
|
||||
Reference in New Issue
Block a user