mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-03-26 11:21:24 +01:00
feat: improve calculator animations, fix it moving up when result is displayed
This commit is contained in:
@@ -137,7 +137,7 @@
|
||||
<li class="nav-item text-center w-100">
|
||||
<a class="nav-item tw-text-2xl tw-cursor-pointer me-lg-4"
|
||||
data-bs-toggle="tooltip" data-bs-placement="left" data-bs-title="{% trans "Calculator" %}"
|
||||
_="on click toggle .tw-hidden on #calculator then trigger show on #calculator">
|
||||
_="on click trigger show on #calculator">
|
||||
<i class="fa-solid fa-calculator"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
104
app/templates/includes/tools/calculator.html
Normal file
104
app/templates/includes/tools/calculator.html
Normal file
@@ -0,0 +1,104 @@
|
||||
{% load formats %}
|
||||
<div class="tw-hidden tw-w-[60vw] lg:tw-w-[30vw] xl:tw-w-[20vw] position-fixed shadow rounded-3 bg-body tw-border-gray-700 tw-border tw-border-solid tw-text-center tw-align-middle tw-z-[2000] tw-touch-none user-select-none"
|
||||
id="calculator"
|
||||
hx-preserve
|
||||
_="
|
||||
on load
|
||||
-- Get localized separators from Django
|
||||
set window.decimalSeparator to '{% get_decimal_separator %}'
|
||||
set window.thousandSeparator to '{% get_thousand_separator %}'
|
||||
set window.argSeparator to ';'
|
||||
end
|
||||
|
||||
on focusin halt the event end -- this prevents bootstrap's static offcanvas from hijacking the focus from the input when open end
|
||||
|
||||
on show
|
||||
if my.classList.contains('tw-hidden')
|
||||
remove .tw-hidden from me
|
||||
measure my width, height
|
||||
set xoff to (window.innerWidth/2) - (width/2)
|
||||
set yoff to (window.innerHeight/2) - (height)
|
||||
add { left: ${xoff}px; top: ${yoff}px; }
|
||||
add .scale-in-center to me then wait for animationend then remove .scale-in-center from me
|
||||
then call #calculator-input.focus()
|
||||
else
|
||||
add .scale-out-center to me then wait for animationend then remove .scale-out-center from me
|
||||
add .tw-hidden to me
|
||||
end
|
||||
end
|
||||
|
||||
on pointerdown(screenX, screenY)
|
||||
if event.target.closest('#calculator-handle')
|
||||
halt the event
|
||||
measure my x, y, width, height
|
||||
set xoff to screenX - x
|
||||
set yoff to screenY - y
|
||||
repeat until event pointerup from document
|
||||
wait for pointermove(screenX, screenY) or
|
||||
pointerup(screenX, screenY) from document
|
||||
-- Calculate new position
|
||||
set newX to screenX - xoff
|
||||
set newY to screenY - yoff
|
||||
-- Constrain to viewport
|
||||
set newX to Math.max(5, Math.min(newX, window.innerWidth - (width + 10)))
|
||||
set newY to Math.max(20, Math.min(newY, window.innerHeight - (height + 5)))
|
||||
add { left: ${newX}px; top: ${newY}px; transform: none }
|
||||
end
|
||||
end
|
||||
end">
|
||||
|
||||
<div id="calculator-handle"
|
||||
class="position-absolute bg-secondary rounded-top-2 tw-cursor-move d-flex align-items-center justify-content-center tw-top-[-20px] tw-left-[3px] tw-w-[2em] tw-h-[20px]">
|
||||
<i class="fa-solid fa-grip"></i>
|
||||
</div>
|
||||
|
||||
<input type="search"
|
||||
class="form-control"
|
||||
id="calculator-input"
|
||||
_="on click me.focus()
|
||||
on input or search
|
||||
js(my)
|
||||
return my.value.replace(new RegExp('\\' + window.decimalSeparator + '|\\' + window.argSeparator + '|\\' + window.thousandSeparator, 'g'),
|
||||
match => {
|
||||
if (match === window.decimalSeparator) return '.';
|
||||
if (match === window.argSeparator) return ',';
|
||||
return ''; // This will remove the thousandSeparator
|
||||
})
|
||||
end
|
||||
then set expr to it
|
||||
then call math.evaluate(expr)
|
||||
if result exists and result is a Number
|
||||
js(result)
|
||||
return result.toString().replace(new RegExp(',|\\.', 'g'),
|
||||
match => match === '.' ? window.decimalSeparator : window.argSeparator)
|
||||
end
|
||||
then set localizedResult to it
|
||||
set #calculator-result.innerText to localizedResult
|
||||
then remove .tw-hidden from #calculator-result-container
|
||||
then add .swing-in-top-fwd to #calculator-result-container
|
||||
then settle
|
||||
then remove .swing-in-top-fwd from #calculator-result-container
|
||||
else
|
||||
add .swing-out-top-bck to #calculator-result-container
|
||||
then settle
|
||||
then add .tw-hidden to #calculator-result-container
|
||||
then remove .swing-out-top-bck from #calculator-result-container
|
||||
end
|
||||
catch e
|
||||
add .swing-out-top-bck to #calculator-result-container
|
||||
then settle
|
||||
then add .tw-hidden to #calculator-result-container
|
||||
then remove .swing-out-top-bck from #calculator-result-container
|
||||
end"
|
||||
placeholder="2 + 2">
|
||||
<div class="tw-hidden" id="calculator-result-container">
|
||||
<div class="d-flex flex-row p-2 justify-content-between">
|
||||
<div class="tw-text-gray-400">=</div>
|
||||
<div id="calculator-result" class="user-select-all"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="position-absolute tw-cursor-pointer top-0 start-100 translate-middle tw-p-0 text-bg-primary border border-light rounded-circle tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5"
|
||||
_="on click trigger show on #calculator">
|
||||
<i class="fa-solid fa-xmark tw-flex tw-items-center tw-justify-center tw-w-full tw-h-full"></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -37,97 +37,8 @@
|
||||
{% include 'includes/toasts.html' %}
|
||||
</div>
|
||||
|
||||
<div class="tw-hidden tw-w-[60vw] lg:tw-w-[30vw] xl:tw-w-[20vw] position-fixed shadow rounded-3 bg-body tw-border-gray-700 tw-border tw-border-solid tw-text-center tw-align-middle tw-z-[2000] tw-touch-none user-select-none"
|
||||
id="calculator"
|
||||
hx-preserve
|
||||
_="on load
|
||||
-- Get localized separators from Django
|
||||
set window.decimalSeparator to '{% get_decimal_separator %}'
|
||||
set window.thousandSeparator to '{% get_thousand_separator %}'
|
||||
set window.argSeparator to ';'
|
||||
end
|
||||
{% include 'includes/tools/calculator.html' %}
|
||||
|
||||
on focusin halt the event -- this prevents bootstrap's static offcanvas from hijacking the focus from the input when open end
|
||||
|
||||
on show if not I.classList.contains('tw-hidden') add { left: 50vw; top: 50vh; transform: translate(-50%, -50%); } then call #calculator-input.focus() end
|
||||
|
||||
on pointerdown(screenX, screenY)
|
||||
if event.target.closest('#calculator-handle')
|
||||
log event
|
||||
halt the event
|
||||
measure my x, y, width, height
|
||||
set xoff to screenX - x
|
||||
set yoff to screenY - y
|
||||
repeat until event pointerup from document
|
||||
wait for pointermove(screenX, screenY) or
|
||||
pointerup(screenX, screenY) from document
|
||||
-- Calculate new position
|
||||
set newX to screenX - xoff
|
||||
set newY to screenY - yoff
|
||||
-- Constrain to viewport
|
||||
set newX to Math.max(5, Math.min(newX, window.innerWidth - (width + 10)))
|
||||
set newY to Math.max(20, Math.min(newY, window.innerHeight - (height + 5)))
|
||||
add { left: ${newX}px; top: ${newY}px; transform: none }
|
||||
end
|
||||
end
|
||||
end">
|
||||
|
||||
<div id="calculator-handle"
|
||||
class="position-absolute bg-secondary rounded-top-2 tw-cursor-move d-flex align-items-center justify-content-center tw-top-[-20px] tw-left-[3px] tw-w-[2em] tw-h-[20px]">
|
||||
<i class="fa-solid fa-grip"></i>
|
||||
</div>
|
||||
|
||||
<input type="search"
|
||||
class="form-control"
|
||||
id="calculator-input"
|
||||
_="on click me.focus()
|
||||
on input or search
|
||||
js(my)
|
||||
return my.value.replace(new RegExp('\\' + window.decimalSeparator + '|\\' + window.argSeparator + '|\\' + window.thousandSeparator, 'g'),
|
||||
match => {
|
||||
if (match === window.decimalSeparator) return '.';
|
||||
if (match === window.argSeparator) return ',';
|
||||
return ''; // This will remove the thousandSeparator
|
||||
})
|
||||
end
|
||||
then set expr to it
|
||||
then call math.evaluate(expr)
|
||||
then log result
|
||||
if result exists and result is a Number
|
||||
js(result)
|
||||
return result.toString().replace(new RegExp(',|\\.', 'g'),
|
||||
match => match === '.' ? window.decimalSeparator : window.argSeparator)
|
||||
end
|
||||
then set localizedResult to it
|
||||
set #calculator-result.innerText to localizedResult
|
||||
then remove .tw-hidden from #calculator-result-container
|
||||
then add .swing-in-top-fwd to #calculator-result-container
|
||||
then settle
|
||||
then remove .swing-in-top-fwd from #calculator-result-container
|
||||
else
|
||||
add .swing-out-top-bck to #calculator-result-container
|
||||
then settle
|
||||
then add .tw-hidden to #calculator-result-container
|
||||
then remove .swing-out-top-bck from #calculator-result-container
|
||||
end
|
||||
catch e
|
||||
add .swing-out-top-bck to #calculator-result-container
|
||||
then settle
|
||||
then add .tw-hidden to #calculator-result-container
|
||||
then remove .swing-out-top-bck from #calculator-result-container
|
||||
end"
|
||||
placeholder="2 + 2">
|
||||
<div class="tw-hidden" id="calculator-result-container">
|
||||
<div class="d-flex flex-row p-2 justify-content-between">
|
||||
<div class="tw-text-gray-400">=</div>
|
||||
<div id="calculator-result" class="user-select-all"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="position-absolute tw-cursor-pointer top-0 start-100 translate-middle tw-p-0 text-bg-primary border border-light rounded-circle tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5"
|
||||
_="on click toggle .tw-hidden on #calculator">
|
||||
<i class="fa-solid fa-xmark tw-flex tw-items-center tw-justify-center tw-w-full tw-h-full"></i>
|
||||
</div>
|
||||
</div>
|
||||
{% block extra_js_body %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -130,3 +130,57 @@
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------
|
||||
* Generated by Animista on 2024-12-21 0:6:39
|
||||
* Licensed under FreeBSD License.
|
||||
* See http://animista.net/license for more info.
|
||||
* w: http://animista.net, t: @cssanimista
|
||||
* ---------------------------------------------- */
|
||||
|
||||
/**
|
||||
* ----------------------------------------
|
||||
* animation scale-in-center
|
||||
* ----------------------------------------
|
||||
*/
|
||||
@keyframes scale-in-center {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.scale-in-center {
|
||||
animation: scale-in-center 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------
|
||||
* Generated by Animista on 2024-12-21 0:8:10
|
||||
* Licensed under FreeBSD License.
|
||||
* See http://animista.net/license for more info.
|
||||
* w: http://animista.net, t: @cssanimista
|
||||
* ---------------------------------------------- */
|
||||
|
||||
/**
|
||||
* ----------------------------------------
|
||||
* animation scale-out-center
|
||||
* ----------------------------------------
|
||||
*/
|
||||
@keyframes scale-out-center {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.scale-out-center {
|
||||
animation: scale-out-center 0.5s cubic-bezier(0.550, 0.085, 0.680, 0.530) both;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user