import getAgent from "@egjs/agent"; import { IObject } from "@daybrush/utils"; import { MoveableInterface } from "./types"; export const DIRECTIONS4 = ["n", "w", "s", "e"]; export const DIRECTIONS = ["n", "w", "s", "e", "nw", "ne", "sw", "se"]; function getSVGCursor(scale: number, degree: number) { return `data:image/svg+xml;utf8,`; } function getCursorCSS(degree: number) { const x1 = getSVGCursor(1, degree); // const x2 = getSVGCursor(2, degree); const degree45 = (Math.round(degree / 45) * 45) % 180; let defaultCursor = "ns-resize"; if (degree45 === 135) { defaultCursor = "nwse-resize"; } else if (degree45 === 45) { defaultCursor = "nesw-resize"; } else if (degree45 === 90) { defaultCursor = "ew-resize"; } // tslint:disable-next-line: max-line-length return `cursor:${defaultCursor};cursor: url('${x1}') 16 16, ${defaultCursor};`; } export const agent = getAgent(); export const IS_WEBKIT = agent.browser.webkit; export const IS_WEBKIT605 = IS_WEBKIT && (() => { const navi = typeof window === "undefined" ? { userAgent: "" } : window.navigator; const res = /applewebkit\/([^\s]+)/g.exec(navi.userAgent.toLowerCase()); return res ? parseFloat(res[1]) < 605 : false; })(); const browserName = agent.browser.name; const browserVersion = parseInt(agent.browser.version, 10); const IS_CHROME = browserName === "chrome"; const IS_CHROMIUM = agent.browser.chromium; const chromiumVersion = parseInt(agent.browser.chromiumVersion, 10) || 0; export const IS_CHROMIUM109 = (IS_CHROME && browserVersion >= 109) || (IS_CHROMIUM && chromiumVersion >= 109); export const IS_FIREFOX = browserName === "firefox"; export const IS_SAFARI_ABOVE15 = parseInt(agent.browser.webkitVersion, 10) >= 612 || browserVersion >= 15; export const PREFIX = "moveable-"; const directionCSS = DIRECTIONS.map(dir => { let top = ""; let left = ""; let originX = "center"; let originY = "center"; const offset = `calc(var(--moveable-control-padding, 20) * -1px)`; if (dir.indexOf("n") > -1) { top = `top: ${offset};`; originY = `bottom`; } if (dir.indexOf(`s`) > -1) { top = `top: 0px;`; originY = `top`; } if (dir.indexOf(`w`) > -1) { left = `left: ${offset};`; originX = `right`; } if (dir.indexOf(`e`) > -1) { left = `left: 0px;`; originX = `left`; } return `.around-control[data-direction*="${dir}"] { ${left}${top} transform-origin: ${originX} ${originY}; }`; }).join("\n"); export const MOVEABLE_CSS = ` { position: absolute; width: 1px; height: 1px; left: 0; top: 0; z-index: 3000; --moveable-color: #4af; --zoom: 1; --zoompx: 1px; --moveable-line-padding: 0; --moveable-control-padding: 0; will-change: transform; outline: 1px solid transparent; } .control-box { z-index: 0; } .line, .control { position: absolute; left: 0; top: 0; will-change: transform; } .control { width: 14px; height: 14px; border-radius: 50%; border: 2px solid #fff; box-sizing: border-box; background: #4af; background: var(--moveable-color); margin-top: -7px; margin-left: -7px; border: 2px solid #fff; z-index: 10; } .around-control { position: absolute; will-change: transform; width: calc(var(--moveable-control-padding, 20) * 1px); height: calc(var(--moveable-control-padding, 20) * 1px); left: calc(var(--moveable-control-padding, 20) * -0.5px); top: calc(var(--moveable-control-padding, 20) * -0.5px); box-sizing: border-box; background: transparent; z-index: 8; cursor: alias; transform-origin: center center; } ${directionCSS} .padding { position: absolute; top: 0px; left: 0px; width: 100px; height: 100px; transform-origin: 0 0; } .line { width: 1px; height: 1px; background: #4af; background: var(--moveable-color); transform-origin: 0px 50%; } .line.edge { z-index: 1; background: transparent; } .line.dashed { box-sizing: border-box; background: transparent; } .line.dashed.horizontal { border-top: 1px dashed #4af; border-top-color: #4af; border-top-color: var(--moveable-color); } .line.dashed.vertical { border-left: 1px dashed #4af; border-left-color: #4af; border-left-color: var(--moveable-color); } .line.vertical { transform: translateX(-50%); } .line.horizontal { transform: translateY(-50%); } .line.vertical.bold { width: 2px; } .line.horizontal.bold { height: 2px; } .control.origin { border-color: #f55; background: #fff; width: 12px; height: 12px; margin-top: -6px; margin-left: -6px; pointer-events: none; } ${[0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165].map(degree => ` .direction[data-rotation="${degree}"], :global .view-control-rotation${degree} { ${getCursorCSS(degree)} } `).join("\n")} .line.direction:before { content: ""; position: absolute; width: 100%; height: calc(var(--moveable-line-padding, 0) * 1px); bottom: 0; left: 0; } .group { z-index: -1; } .area { position: absolute; } .area-pieces { position: absolute; top: 0; left: 0; display: none; } .area.avoid, .area.pass { pointer-events: none; } .area.avoid+.area-pieces { display: block; } .area-piece { position: absolute; } ${IS_WEBKIT605 ? `:global svg *:before { content:""; transform-origin: inherit; }` : ""} `; export const NEARBY_POS = [ [0, 1, 2], [1, 0, 3], [2, 0, 3], [3, 1, 2], ]; export const FLOAT_POINT_NUM = 0.0001; export const TINY_NUM = 0.0000001; export const MIN_SCALE = 0.000000001; export const MAX_NUM = Math.pow(10, 10); export const MIN_NUM = -MAX_NUM; export const DIRECTION_REGION_TO_DIRECTION: Record = { n: [0, -1], e: [1, 0], s: [0, 1], w: [-1, 0], nw: [-1, -1], ne: [1, -1], sw: [-1, 1], se: [1, 1], }; export const DIRECTION_INDEXES: IObject = { n: [0, 1], e: [1, 3], s: [3, 2], w: [2, 0], nw: [0], ne: [1], sw: [2], se: [3], }; export const DIRECTION_ROTATIONS: IObject = { n: 0, s: 180, w: 270, e: 90, nw: 315, ne: 45, sw: 225, se: 135, }; export const MOVEABLE_METHODS: Array = [ "isMoveableElement", "updateRect", "updateTarget", "destroy", "dragStart", "isInside", "hitTest", "setState", "getRect", "request", "isDragging", "getManager", "forceUpdate", "waitToChangeTarget", "updateSelectors", "getTargets", "stopDrag", "getControlBoxElement", "getMoveables", "getDragElement", ];