mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-04 07:27:41 +08:00
140 lines
3.6 KiB
TypeScript
140 lines
3.6 KiB
TypeScript
import { defineComponent, ref, unref, computed, PropType } from "vue";
|
|
import resizer from "./resizer";
|
|
import "./index.css";
|
|
|
|
export interface ContextProps {
|
|
minPercent: number;
|
|
defaultPercent: number;
|
|
split: string;
|
|
}
|
|
|
|
export default defineComponent({
|
|
name: "splitPane",
|
|
components: { resizer },
|
|
props: {
|
|
splitSet: {
|
|
type: Object as PropType<ContextProps>,
|
|
require: true,
|
|
},
|
|
},
|
|
emits: ["resize"],
|
|
setup(props, ctx) {
|
|
let active = ref(false);
|
|
let hasMoved = ref(false);
|
|
let percent = ref(props.splitSet?.defaultPercent);
|
|
let type = props.splitSet?.split === "vertical" ? "width" : "height";
|
|
let resizeType = props.splitSet?.split === "vertical" ? "left" : "top";
|
|
|
|
let leftClass = ref([
|
|
"splitter-pane splitter-paneL",
|
|
props.splitSet?.split,
|
|
]);
|
|
|
|
let rightClass = ref([
|
|
"splitter-pane splitter-paneR",
|
|
props.splitSet?.split,
|
|
]);
|
|
|
|
const userSelect = computed(() => {
|
|
return active.value ? "none" : "";
|
|
});
|
|
|
|
const cursor = computed(() => {
|
|
return active.value
|
|
? props.splitSet?.split === "vertical"
|
|
? "col-resize"
|
|
: "row-resize"
|
|
: "";
|
|
});
|
|
|
|
const onClick = (): void => {
|
|
if (!hasMoved.value) {
|
|
percent.value = 50;
|
|
ctx.emit("resize", percent.value);
|
|
}
|
|
};
|
|
|
|
const onMouseDown = (): void => {
|
|
active.value = true;
|
|
hasMoved.value = false;
|
|
};
|
|
|
|
const onMouseUp = (): void => {
|
|
active.value = false;
|
|
};
|
|
|
|
const onMouseMove = (e: any): void => {
|
|
if (e.buttons === 0 || e.which === 0) {
|
|
active.value = false;
|
|
}
|
|
|
|
if (active.value) {
|
|
let offset = 0;
|
|
let target = e.currentTarget;
|
|
if (props.splitSet?.split === "vertical") {
|
|
while (target) {
|
|
offset += target.offsetLeft;
|
|
target = target.offsetParent;
|
|
}
|
|
} else {
|
|
while (target) {
|
|
offset += target.offsetTop;
|
|
target = target.offsetParent;
|
|
}
|
|
}
|
|
|
|
const currentPage =
|
|
props.splitSet?.split === "vertical" ? e.pageX : e.pageY;
|
|
const targetOffset =
|
|
props.splitSet?.split === "vertical"
|
|
? e.currentTarget.offsetWidth
|
|
: e.currentTarget.offsetHeight;
|
|
const percents =
|
|
Math.floor(((currentPage - offset) / targetOffset) * 10000) / 100;
|
|
|
|
if (
|
|
percents > props.splitSet?.minPercent &&
|
|
percents < 100 - props.splitSet?.minPercent
|
|
) {
|
|
percent.value = percents;
|
|
}
|
|
|
|
ctx.emit("resize", percent.value);
|
|
|
|
hasMoved.value = true;
|
|
}
|
|
};
|
|
|
|
return () => (
|
|
<>
|
|
<div
|
|
class="vue-splitter-container clearfix"
|
|
style={(unref(cursor), unref(userSelect))}
|
|
onMouseup={() => onMouseUp()}
|
|
onMousemove={() => onMouseMove(event)}
|
|
>
|
|
<div
|
|
class={unref(leftClass)}
|
|
style={{ [unref(type)]: unref(percent) + "%" }}
|
|
>
|
|
{ctx.slots.paneL()}
|
|
</div>
|
|
<resizer
|
|
style={`${unref([resizeType])}:${unref(percent)}%`}
|
|
split={props.splitSet?.split}
|
|
onMousedown={() => onMouseDown()}
|
|
onClick={() => onClick()}
|
|
></resizer>
|
|
<div
|
|
class={unref(rightClass)}
|
|
style={{ [unref(type)]: 100 - unref(percent) + "%" }}
|
|
>
|
|
{ctx.slots.paneR()}
|
|
</div>
|
|
<div v-show={unref(active)} class="vue-splitter-container-mask"></div>
|
|
</div>
|
|
</>
|
|
);
|
|
},
|
|
});
|