winbox-ui-next
Version:
We Design Vue 2.0: A Vue.js 3 UI Library
221 lines (220 loc) • 7.63 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
import { defineComponent, toRefs, reactive, ref, computed, resolveComponent, openBlock, createBlock, resolveDynamicComponent, mergeProps, withCtx, renderSlot, createElementBlock, Fragment, renderList, normalizeClass, createSlots, createCommentVNode } from "vue";
import ResizeTrigger from "../_components/resize-trigger.js";
import useMergeState from "../_hooks/use-merge-state.js";
import { getPrefixCls } from "../_utils/global-config.js";
import { isNumber } from "../_utils/is.js";
import { on, off } from "../_utils/dom.js";
import _export_sfc from "../_virtual/plugin-vue_export-helper";
const DIRECTION_LEFT = "left";
const DIRECTION_RIGHT = "right";
const DIRECTION_TOP = "top";
const DIRECTION_BOTTOM = "bottom";
const allDirections = [
DIRECTION_LEFT,
DIRECTION_RIGHT,
DIRECTION_TOP,
DIRECTION_BOTTOM
];
function getRealSize(pageSize, padding) {
if (pageSize === 0)
return 0;
const res = pageSize - padding;
return res <= 0 ? 0 : res;
}
function isHorizontal(direction) {
return [DIRECTION_TOP, DIRECTION_BOTTOM].indexOf(direction) > -1;
}
const _sfc_main = defineComponent({
name: "ResizeBox",
components: {
ResizeTrigger
},
inheritAttrs: false,
props: {
width: {
type: Number
},
height: {
type: Number
},
component: {
type: String,
default: "div"
},
directions: {
type: Array,
default: () => ["right"]
}
},
emits: [
"movingStart",
"moving",
"movingEnd",
"update:width",
"update:height"
],
setup(props, { emit }) {
const { height: propHeight, width: propWidth, directions } = toRefs(props);
const [width, setWidth] = useMergeState(null, reactive({
value: propWidth
}));
const [height, setHeight] = useMergeState(null, reactive({
value: propHeight
}));
const wrapperRef = ref();
const paddingStyles = reactive({});
const prefixCls = getPrefixCls("resizebox");
const classNames = computed(() => [prefixCls]);
const styles = computed(() => {
return __spreadValues(__spreadValues(__spreadValues({}, isNumber(width.value) ? { width: `${width.value}px` } : {}), isNumber(height.value) ? { height: `${height.value}px` } : {}), paddingStyles);
});
const allowDirections = computed(() => directions.value.filter((direction) => allDirections.includes(direction)));
const record = {
direction: "",
startPageX: 0,
startPageY: 0,
startWidth: 0,
startHeight: 0,
moving: false,
padding: {
left: 0,
right: 0,
top: 0,
bottom: 0
}
};
function onMoving(e) {
if (!record.moving)
return;
const { startPageX, startPageY, startWidth, startHeight, direction } = record;
let newWidth = startWidth;
let newHeight = startHeight;
const offsetX = e.pageX - startPageX;
const offsetY = e.pageY - startPageY;
switch (direction) {
case DIRECTION_LEFT:
newWidth = startWidth - offsetX;
setWidth(newWidth);
emit("update:width", newWidth);
break;
case DIRECTION_RIGHT:
newWidth = startWidth + offsetX;
setWidth(newWidth);
emit("update:width", newWidth);
break;
case DIRECTION_TOP:
newHeight = startHeight - offsetY;
setHeight(newHeight);
emit("update:height", newHeight);
break;
case DIRECTION_BOTTOM:
newHeight = startHeight + offsetY;
setHeight(newHeight);
emit("update:height", newHeight);
break;
}
emit("moving", {
width: newWidth,
height: newHeight
}, e);
}
function onMoveEnd(e) {
record.moving = false;
off(window, "mousemove", onMoving);
off(window, "mouseup", onMoveEnd);
off(window, "contextmenu", onMoveEnd);
document.body.style.cursor = "default";
emit("movingEnd", e);
}
function onMoveStart(direction, e) {
var _a, _b;
emit("movingStart", e);
record.moving = true;
record.startPageX = e.pageX;
record.startPageY = e.pageY;
record.direction = direction;
const { top, left, right, bottom } = record.padding;
record.startWidth = getRealSize(((_a = wrapperRef.value) == null ? void 0 : _a.clientWidth) || 0, left + right);
record.startHeight = getRealSize(((_b = wrapperRef.value) == null ? void 0 : _b.clientHeight) || 0, top + bottom);
on(window, "mousemove", onMoving);
on(window, "mouseup", onMoveEnd);
on(window, "contextmenu", onMoveEnd);
document.body.style.cursor = isHorizontal(direction) ? "row-resize" : "col-resize";
}
function onTiggerResize(direction, entry) {
const { width: width2, height: height2 } = entry.contentRect;
const size = isHorizontal(direction) ? height2 : width2;
record.padding[direction] = size;
paddingStyles[`padding-${direction}`] = `${size}px`;
}
return {
prefixCls,
classNames,
styles,
wrapperRef,
onMoveStart,
isHorizontal,
allowDirections,
onTiggerResize
};
}
});
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_ResizeTrigger = resolveComponent("ResizeTrigger");
return openBlock(), createBlock(resolveDynamicComponent(_ctx.component), mergeProps({
ref: "wrapperRef",
class: _ctx.classNames
}, _ctx.$attrs, { style: _ctx.styles }), {
default: withCtx(() => [
renderSlot(_ctx.$slots, "default"),
(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.allowDirections, (direction) => {
return openBlock(), createBlock(_component_ResizeTrigger, {
key: direction,
"prefix-cls": `${_ctx.prefixCls}-trigger`,
class: normalizeClass(`${_ctx.prefixCls}-direction-${direction}`),
direction: _ctx.isHorizontal(direction) ? "horizontal" : "vertical",
onMousedown: (e) => {
_ctx.onMoveStart(direction, e);
},
onResize: (entry) => {
_ctx.onTiggerResize(direction, entry);
}
}, createSlots({
default: withCtx(() => [
_ctx.$slots["resize-trigger"] ? renderSlot(_ctx.$slots, "resize-trigger", {
key: 0,
direction
}) : createCommentVNode("v-if", true)
]),
_: 2
}, [
_ctx.$slots["resize-trigger-icon"] ? {
name: "icon",
fn: withCtx(() => [
renderSlot(_ctx.$slots, "resize-trigger-icon", { direction })
])
} : void 0
]), 1032, ["prefix-cls", "class", "direction", "onMousedown", "onResize"]);
}), 128))
]),
_: 3
}, 16, ["class", "style"]);
}
var _ResizeBox = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
export { _ResizeBox as default };