feat: edge fix-size editable via manual resize; center one-shot; corners keep size

This commit is contained in:
Hermes Agent committed 2026-09-09 19:10:48 +02:00
1 parent 61577b01cd
commit ab6a2e879f
1 file changed
+30 -12
+30 -12
View File
@@ -26,12 +26,13 @@ export default function () {
const PLUGIN_HEADER_PX = 38
// Вычислить целевое состояние окна для позиции докинга:
// - Лево/Право: ширина 320px, высота = макс (весь viewport по вертикали минус шапка)
// - Верх/Низ: высота 320px, ширина = макс (весь viewport по горизонтали)
// - Углы: НЕ меняют размер, только прижимают к соответствующему углу viewport
// - Центр: размер = 50% viewport (по ширине и высоте), центрируется
// - Лево/Право: ширина = dockEdgeSize (редактируемая, по умолч. 320), высота = макс (весь viewport по вертикали минус шапка)
// - Верх/Низ: высота = dockEdgeSize, ширина = макс (весь viewport по горизонтали)
// - Углы: размер НЕ фиксируется (редактируется вручную), только прижимают к углу (с клампом в пределах viewport)
// - Центр: размер = 50% viewport (по ширине и высоте), центрируется (one-shot, не удерживает)
// Возвращает размер (экранные px) и позицию (canvas-space, прижатую к нужному краю).
const DOCK_EDGE_SIZE = 320
const DEFAULT_DOCK_EDGE = 320
let dockEdgeSize = DEFAULT_DOCK_EDGE // редактируемая фикс-сторона для edge-позиций (320 по умолч.)
function computeDock (position: DockPosition, currentWidth: number, currentHeight: number) {
const b = figma.viewport.bounds
const zoom = figma.viewport.zoom || 1
@@ -39,22 +40,25 @@ export default function () {
const maxH = Math.round(b.height * zoom) - PLUGIN_HEADER_PX
const isLeftRight = position === 'center-left' || position === 'center-right'
const isTopBottom = position === 'top-center' || position === 'bottom-center'
const isCorner = position === 'top-left' || position === 'top-right' || position === 'bottom-left' || position === 'bottom-right'
const isCenter = position === 'center'
let targetW = currentWidth
let targetH = currentHeight
if (isLeftRight) {
targetW = DOCK_EDGE_SIZE
targetW = dockEdgeSize
targetH = maxH
} else if (isTopBottom) {
targetW = maxW
targetH = DOCK_EDGE_SIZE
targetH = dockEdgeSize
} else if (isCenter) {
targetW = Math.round(maxW / 2)
targetH = Math.round(maxH / 2)
} else if (isCorner) {
// размер редактируется вручную, только клампим в пределы viewport
targetW = Math.min(currentWidth, maxW)
targetH = Math.min(currentHeight, maxH)
}
// Углы (top-left/right, bottom-left/right): размер НЕ меняем (targetW/targetH = current),
// только позиция прижимается к соответствующему углу viewport.
// canvas-units от целевого размера
const wCanvas = targetW / zoom
const hCanvas = (PLUGIN_HEADER_PX + targetH) / zoom
@@ -117,18 +121,32 @@ export default function () {
const { width, height } = clampWindowSize(windowSize)
lastSize = { width, height }
figma.ui.resize(width, height)
// Если окно задокено — держим прижатым к краю при смене размера
// Если окно задокено — держим прижатым к краю при смене размера.
// При этом фикс-сторона edge-позиции (dockEdgeSize) ОБНОВЛЯЕТСЯ из ручного
// ресайза, чтобы пользователь мог менять её (а не была заблокирована на 320).
if (dockedPosition !== null) {
const isLeftRight = dockedPosition === 'center-left' || dockedPosition === 'center-right'
const isTopBottom = dockedPosition === 'top-center' || dockedPosition === 'bottom-center'
if (isLeftRight) dockEdgeSize = width
else if (isTopBottom) dockEdgeSize = height
applyDock(dockedPosition, width, height)
}
})
// Эмуляция докинга: растянуть окно на зону и прижать к её краю (9 позиций).
on('DOCK_WINDOW', function (payload: { position: DockPosition; width: number; height: number }) {
const { position } = payload
const { position, width, height } = payload
// Центр — это one-shot: применяем 50% по центру ОДИН раз, НЕ включаем поллинг
// (окно не "приклеено", ручной ресайз/драг работают свободно после).
if (position === 'center') {
dockedPosition = null
applyDock('center', width, height)
return
}
// Остальные позиции — удерживаем прижатым (поллинг пересчитывает при зуме/пане).
dockedPosition = position
lastBoundsKey = '' // форсируем пересчёт на ближайшем тике
applyDock(position, payload.width, payload.height)
applyDock(position, width, height)
})
// Останавливаем поллинг при закрытии плагина, чтобы не висел в памяти.