2025-11-12 18:26:18 +00:00
{{define "zoom-control"}}
2025-11-12 22:54:46 +00:00
<!-- Zoom Control (Fixed Bottom Center, Draggable) - Hyperscript Enhanced -->
2025-11-16 12:48:12 +00:00
< div id = "zoom-control" class = "zoom-control no-print zoom-hidden" role = "group" aria-label = "{{if eq .Lang " es " } } Control de zoom { { else } } Zoom control { { end } } "
2025-11-30 05:58:44 +00:00
_ = "on load call initZoomControl(me)
2025-11-12 22:54:46 +00:00
on mousedown(clientX, clientY)
2025-11-16 12:48:12 +00:00
set target to event.target
2025-11-30 05:58:44 +00:00
set tag to target.tagName
if tag is 'INPUT' or tag is 'BUTTON' then exit end
if target.classList.contains('zoom-slider') or target.classList.contains('zoom-close-btn') or target.classList.contains('zoom-reset-btn') or target.classList.contains('zoom-value') then exit end
if target.closest('.zoom-close-btn') or target.closest('.zoom-reset-btn') then exit end
2025-11-16 12:48:12 +00:00
set :isDragging to true
2025-11-12 22:54:46 +00:00
set my *transition to 'none'
set rect to my getBoundingClientRect()
2025-11-16 12:48:12 +00:00
set :initialX to clientX - rect.left
set :initialY to clientY - rect.top
2025-11-12 22:54:46 +00:00
halt the event
on mousemove(clientX, clientY) from document
2025-11-30 05:58:44 +00:00
if :isDragging is not true then exit end
2025-11-12 22:54:46 +00:00
halt the event
2025-11-16 12:48:12 +00:00
set currentX to clientX - :initialX
set currentY to clientY - :initialY
2025-11-12 22:54:46 +00:00
set maxX to window.innerWidth - my offsetWidth
set maxY to window.innerHeight - my offsetHeight
set currentX to Math.max(0, Math.min(currentX, maxX))
set currentY to Math.max(0, Math.min(currentY, maxY))
set my *left to `${currentX}px`
set my *bottom to `${window.innerHeight - currentY - my offsetHeight}px`
set my *transform to 'none'
on mouseup from document
2025-11-30 05:58:44 +00:00
if :isDragging is not true then exit end
2025-11-16 12:48:12 +00:00
set :isDragging to false
2025-11-12 22:54:46 +00:00
set my *transition to 'all 0.3s ease'
set position to { bottom: my *bottom, left: my *left }
set localStorage['cv-zoom-position'] to JSON.stringify(position)" >
2025-11-12 18:26:18 +00:00
< button
id = "zoom-close"
class = "zoom-close-btn"
aria-label = "{{if eq .Lang " es " } } Cerrar control de zoom { { else } } Close zoom control { { end } } "
2025-11-16 12:48:12 +00:00
title = "{{if eq .Lang " es " } } Cerrar { { else } } Close { { end } } " >
< iconify-icon icon = "mdi:close" width = "16" height = "16" style = "pointer-events: none;" > < / iconify-icon >
2025-11-12 18:26:18 +00:00
< / button >
< span class = "zoom-value zoom-value-min" aria-hidden = "true" > 25< / span >
< input
type = "range"
id = "zoom-slider"
class = "zoom-slider"
min = "25"
2025-11-17 17:03:17 +00:00
max = "300"
2025-11-12 18:26:18 +00:00
step = "1"
value = "100"
aria-label = "{{if eq .Lang " es " } } Ajustar nivel de zoom del CV { { else } } Adjust CV zoom level { { end } } "
aria-valuemin = "25"
2025-11-17 17:03:17 +00:00
aria-valuemax = "300"
2025-11-12 18:26:18 +00:00
aria-valuenow = "100"
2025-11-12 22:54:46 +00:00
aria-valuetext = "100%"
2025-11-30 05:58:44 +00:00
_ = "on input call handleZoomInput(me)" >
2025-11-12 18:26:18 +00:00
2025-11-17 17:03:17 +00:00
< span class = "zoom-value zoom-value-max" aria-hidden = "true" > 300< / span >
2025-11-12 18:26:18 +00:00
< button
id = "zoom-reset"
class = "zoom-reset-btn"
aria-label = "{{if eq .Lang " es " } } Restablecer zoom al 100 % { { else } } Reset zoom to 100 % { { end } } "
title = "{{if eq .Lang " es " } } Restablecer { { else } } Reset { { end } } "
2025-11-12 22:54:46 +00:00
aria-live = "polite"
2025-11-30 05:58:44 +00:00
_ = "on click call handleZoomReset()" >
2025-11-12 18:26:18 +00:00
< span id = "zoom-value-current" > 100< / span >
< / button >
< / div >
{{end}}