feat: 8 invisible resize handles on whole perimeter (replace native useWindowResize)

This commit is contained in:
Hermes Agent committed 2026-09-09 19:25:38 +02:00
1 parent 8a0bf4d8f3
commit b6c0a58071
2 files changed
+23 -9

No files matched your search

+1 -2
View File
@@ -146,10 +146,9 @@ export default function () {
if (dir.includes('top')) ny = p.y - dy / zoom if (dir.includes('top')) ny = p.y - dy / zoom
figma.ui.reposition(nx, ny) figma.ui.reposition(nx, ny)
} }
// Док-режим во время live-ресайза не трогаем (финальный RESIZE_WINDOW пересчитает).
}) })
// Ресайз окна плагина (drag за угол в UI -> useWindowResize -> RESIZE_WINDOW) // Ресайз окна плагина (кастомные ручки по периметру -> RESIZE_WINDOW по pointerup)
on('RESIZE_WINDOW', function (windowSize: { width: number; height: number }) { on('RESIZE_WINDOW', function (windowSize: { width: number; height: number }) {
const { width, height } = clampWindowSize(windowSize) const { width, height } = clampWindowSize(windowSize)
lastSize = { width, height } lastSize = { width, height }
+22 -7
View File
@@ -62,10 +62,10 @@ function Plugin () {
} | null>(null) } | null>(null)
const [copied, setCopied] = useState(false) const [copied, setCopied] = useState(false)
// Кастомный ресайз по ВСЕМУ периметру (8 ручек: 4 края + 4 угла), а не только // Кастомный ресайз по ВСЕМУ периметру (8 ручек: 4 края + 4 угла). Нативный useWindowResize
// снизу-справа (что даёт нативный useWindowResize). Левый/верхний края двигают окно // давал только bottom-right; здесь handle'ы ловят pointerdown по всему периметру и шлют
// через figma.ui.reposition, чтобы окно не "уезжало" при расширении влево/вверх. // dir + dx/dy в main, который для left/top двигает окно через reposition.
// В процессе драга шлём RESIZE_WINDOW_DRAG (live), по pointerup — финальный RESIZE_WINDOW. // Live-обновление: RESIZE_WINDOW_DRAG во время drag'а, финальный RESIZE_WINDOW по pointerup.
function startResize (e: PointerEvent, dir: string) { function startResize (e: PointerEvent, dir: string) {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
@@ -208,6 +208,22 @@ function Plugin () {
} }
} }
// Обновляем цифры размера и инфо ТОЛЬКО после окончания drag'а (отпускание кнопки).
// К моменту pointerup Figma уже применила новый размер окна.
useEffect(function () {
const handlePointerUp = function () {
setCurrentWindowSize({
width: window.innerWidth,
height: window.innerHeight
})
refreshInfo()
}
window.addEventListener('pointerup', handlePointerUp)
return function () {
window.removeEventListener('pointerup', handlePointerUp)
}
}, [])
// Первичное заполнение инфо при старте плагина. // Первичное заполнение инфо при старте плагина.
useEffect(function () { useEffect(function () {
refreshInfo() refreshInfo()
@@ -353,7 +369,7 @@ function Plugin () {
</div> </div>
</Container> </Container>
{/* Декоративная иконка drag-хендла в правом нижнем углу (как в старом плагине). {/* Декоративная иконка drag-хендла в правом нижнем углу (как в старом плагине).
pointerEvents:none — она не ловит события. */} pointerEvents:none — сам drag ловит невидимый div от useWindowResize. */}
<div <div
style={{ style={{
position: 'fixed', position: 'fixed',
@@ -375,8 +391,7 @@ function Plugin () {
</svg> </svg>
</div> </div>
{/* Невидимые интерактивные области ресайза по всему периметру (8 ручек: 4 края + 4 угла). {/* Невидимые интерактивные области ресайза по всему периметру (8 ручек: 4 края + 4 угла).
Нативный useWindowResize даёт только bottom-right; эти div-ы ловят pointerdown и шлют Каждая ловит pointerdown и шлёт dir в main (через startResize). Сами div-ы прозрачные. */}
dir + dx/dy в main, для left/top main двигает окно через reposition. Сами ручки прозрачные. */}
{[ {[
{ dir: 'top-left', style: { top: -3, left: -3, width: 12, height: 12, cursor: 'nwse-resize' } }, { dir: 'top-left', style: { top: -3, left: -3, width: 12, height: 12, cursor: 'nwse-resize' } },
{ dir: 'top', style: { top: -3, left: '50%', transform: 'translateX(-50%)', width: 32, height: 10, cursor: 'ns-resize' } }, { dir: 'top', style: { top: -3, left: '50%', transform: 'translateX(-50%)', width: 32, height: 10, cursor: 'ns-resize' } },