mldong-flow-designer-plus
Version:
本项目包含了作者为B站课堂视频[《工作流设计器开发最佳实践》](https://www.bilibili.com/cheese/play/ss24484)的过程源码。教程中开发的组件也可用于实际生产环境中。以下是和使用文档和课程章节说明。 ## 实战项目 [演示地址](https://flow-pro.mldong.com/)
286 lines (285 loc) • 11.4 kB
JavaScript
import { G as toArray, O as watchImmediate, H as tryOnMounted, m as isClient, D as pxValue, j as injectLocal, I as tryOnScopeDispose, B as noop, r as isIOS, C as notNullish, u as isObject } from "./error-DEV4o0cD.js";
import { computed, toValue, shallowRef, watch, watchEffect, hasInjectionContext, getCurrentInstance, onMounted, unref } from "vue";
const defaultWindow = isClient ? window : void 0;
function unrefElement(elRef) {
var _$el;
const plain = toValue(elRef);
return (_$el = plain === null || plain === void 0 ? void 0 : plain.$el) !== null && _$el !== void 0 ? _$el : plain;
}
function useEventListener(...args) {
const register = (el, event, listener, options) => {
el.addEventListener(event, listener, options);
return () => el.removeEventListener(event, listener, options);
};
const firstParamTargets = computed(() => {
const test = toArray(toValue(args[0])).filter((e) => e != null);
return test.every((e) => typeof e !== "string") ? test : void 0;
});
return watchImmediate(() => {
var _firstParamTargets$va, _firstParamTargets$va2;
return [
(_firstParamTargets$va = (_firstParamTargets$va2 = firstParamTargets.value) === null || _firstParamTargets$va2 === void 0 ? void 0 : _firstParamTargets$va2.map((e) => unrefElement(e))) !== null && _firstParamTargets$va !== void 0 ? _firstParamTargets$va : [defaultWindow].filter((e) => e != null),
toArray(toValue(firstParamTargets.value ? args[1] : args[0])),
toArray(unref(firstParamTargets.value ? args[2] : args[1])),
toValue(firstParamTargets.value ? args[3] : args[2])
];
}, ([raw_targets, raw_events, raw_listeners, raw_options], _, onCleanup) => {
if (!(raw_targets === null || raw_targets === void 0 ? void 0 : raw_targets.length) || !(raw_events === null || raw_events === void 0 ? void 0 : raw_events.length) || !(raw_listeners === null || raw_listeners === void 0 ? void 0 : raw_listeners.length)) return;
const optionsClone = isObject(raw_options) ? { ...raw_options } : raw_options;
const cleanups = raw_targets.flatMap((el) => raw_events.flatMap((event) => raw_listeners.map((listener) => register(el, event, listener, optionsClone))));
onCleanup(() => {
cleanups.forEach((fn) => fn());
});
}, { flush: "post" });
}
let _iOSWorkaround = false;
function onClickOutside(target, handler, options = {}) {
const { window: window2 = defaultWindow, ignore = [], capture = true, detectIframe = false, controls = false } = options;
if (!window2) return controls ? {
stop: noop,
cancel: noop,
trigger: noop
} : noop;
if (isIOS && !_iOSWorkaround) {
_iOSWorkaround = true;
const listenerOptions = { passive: true };
Array.from(window2.document.body.children).forEach((el) => el.addEventListener("click", noop, listenerOptions));
window2.document.documentElement.addEventListener("click", noop, listenerOptions);
}
let shouldListen = true;
const shouldIgnore = (event) => {
return toValue(ignore).some((target2) => {
if (typeof target2 === "string") return Array.from(window2.document.querySelectorAll(target2)).some((el) => el === event.target || event.composedPath().includes(el));
else {
const el = unrefElement(target2);
return el && (event.target === el || event.composedPath().includes(el));
}
});
};
function hasMultipleRoots(target2) {
const vm = toValue(target2);
return vm && vm.$.subTree.shapeFlag === 16;
}
function checkMultipleRoots(target2, event) {
const vm = toValue(target2);
const children = vm.$.subTree && vm.$.subTree.children;
if (children == null || !Array.isArray(children)) return false;
return children.some((child) => child.el === event.target || event.composedPath().includes(child.el));
}
const listener = (event) => {
const el = unrefElement(target);
if (event.target == null) return;
if (!(el instanceof Element) && hasMultipleRoots(target) && checkMultipleRoots(target, event)) return;
if (!el || el === event.target || event.composedPath().includes(el)) return;
if ("detail" in event && event.detail === 0) shouldListen = !shouldIgnore(event);
if (!shouldListen) {
shouldListen = true;
return;
}
handler(event);
};
let isProcessingClick = false;
const cleanup = [
useEventListener(window2, "click", (event) => {
if (!isProcessingClick) {
isProcessingClick = true;
setTimeout(() => {
isProcessingClick = false;
}, 0);
listener(event);
}
}, {
passive: true,
capture
}),
useEventListener(window2, "pointerdown", (e) => {
const el = unrefElement(target);
shouldListen = !shouldIgnore(e) && !!(el && !e.composedPath().includes(el));
}, { passive: true }),
detectIframe && useEventListener(window2, "blur", (event) => {
setTimeout(() => {
const el = unrefElement(target);
let activeEl = window2.document.activeElement;
while (activeEl === null || activeEl === void 0 ? void 0 : activeEl.shadowRoot) activeEl = activeEl.shadowRoot.activeElement;
if ((activeEl === null || activeEl === void 0 ? void 0 : activeEl.tagName) === "IFRAME" && !(el === null || el === void 0 ? void 0 : el.contains(window2.document.activeElement))) handler(event);
}, 0);
}, { passive: true })
].filter(Boolean);
const stop = () => cleanup.forEach((fn) => fn());
if (controls) return {
stop,
cancel: () => {
shouldListen = false;
},
trigger: (event) => {
shouldListen = true;
listener(event);
shouldListen = false;
}
};
return stop;
}
// @__NO_SIDE_EFFECTS__
function useMounted() {
const isMounted = shallowRef(false);
const instance = getCurrentInstance();
if (instance) onMounted(() => {
isMounted.value = true;
}, instance);
return isMounted;
}
// @__NO_SIDE_EFFECTS__
function useSupported(callback) {
const isMounted = /* @__PURE__ */ useMounted();
return computed(() => {
isMounted.value;
return Boolean(callback());
});
}
function useMutationObserver(target, callback, options = {}) {
const { window: window2 = defaultWindow, ...mutationOptions } = options;
let observer;
const isSupported = /* @__PURE__ */ useSupported(() => window2 && "MutationObserver" in window2);
const cleanup = () => {
if (observer) {
observer.disconnect();
observer = void 0;
}
};
const stopWatch = watch(computed(() => {
const items = toArray(toValue(target)).map(unrefElement).filter(notNullish);
return new Set(items);
}), (newTargets) => {
cleanup();
if (isSupported.value && newTargets.size) {
observer = new MutationObserver(callback);
newTargets.forEach((el) => observer.observe(el, mutationOptions));
}
}, {
immediate: true,
flush: "post"
});
const takeRecords = () => {
return observer === null || observer === void 0 ? void 0 : observer.takeRecords();
};
const stop = () => {
stopWatch();
cleanup();
};
tryOnScopeDispose(stop);
return {
isSupported,
stop,
takeRecords
};
}
const ssrWidthSymbol = Symbol("vueuse-ssr-width");
// @__NO_SIDE_EFFECTS__
function useSSRWidth() {
const ssrWidth = hasInjectionContext() ? injectLocal(ssrWidthSymbol, null) : null;
return typeof ssrWidth === "number" ? ssrWidth : void 0;
}
function useMediaQuery(query, options = {}) {
const { window: window2 = defaultWindow, ssrWidth = /* @__PURE__ */ useSSRWidth() } = options;
const isSupported = /* @__PURE__ */ useSupported(() => window2 && "matchMedia" in window2 && typeof window2.matchMedia === "function");
const ssrSupport = shallowRef(typeof ssrWidth === "number");
const mediaQuery = shallowRef();
const matches = shallowRef(false);
const handler = (event) => {
matches.value = event.matches;
};
watchEffect(() => {
if (ssrSupport.value) {
ssrSupport.value = !isSupported.value;
matches.value = toValue(query).split(",").some((queryString) => {
const not = queryString.includes("not all");
const minWidth = queryString.match(/\(\s*min-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/);
const maxWidth = queryString.match(/\(\s*max-width:\s*(-?\d+(?:\.\d*)?[a-z]+\s*)\)/);
let res = Boolean(minWidth || maxWidth);
if (minWidth && res) res = ssrWidth >= pxValue(minWidth[1]);
if (maxWidth && res) res = ssrWidth <= pxValue(maxWidth[1]);
return not ? !res : res;
});
return;
}
if (!isSupported.value) return;
mediaQuery.value = window2.matchMedia(toValue(query));
matches.value = mediaQuery.value.matches;
});
useEventListener(mediaQuery, "change", handler, { passive: true });
return computed(() => matches.value);
}
function useResizeObserver(target, callback, options = {}) {
const { window: window2 = defaultWindow, ...observerOptions } = options;
let observer;
const isSupported = /* @__PURE__ */ useSupported(() => window2 && "ResizeObserver" in window2);
const cleanup = () => {
if (observer) {
observer.disconnect();
observer = void 0;
}
};
const stopWatch = watch(computed(() => {
const _targets = toValue(target);
return Array.isArray(_targets) ? _targets.map((el) => unrefElement(el)) : [unrefElement(_targets)];
}), (els) => {
cleanup();
if (isSupported.value && window2) {
observer = new ResizeObserver(callback);
for (const _el of els) if (_el) observer.observe(_el, observerOptions);
}
}, {
immediate: true,
flush: "post"
});
const stop = () => {
cleanup();
stopWatch();
};
tryOnScopeDispose(stop);
return {
isSupported,
stop
};
}
// @__NO_SIDE_EFFECTS__
function useWindowSize(options = {}) {
const { window: window2 = defaultWindow, initialWidth = Number.POSITIVE_INFINITY, initialHeight = Number.POSITIVE_INFINITY, listenOrientation = true, includeScrollbar = true, type = "inner" } = options;
const width = shallowRef(initialWidth);
const height = shallowRef(initialHeight);
const update = () => {
if (window2) if (type === "outer") {
width.value = window2.outerWidth;
height.value = window2.outerHeight;
} else if (type === "visual" && window2.visualViewport) {
const { width: visualViewportWidth, height: visualViewportHeight, scale } = window2.visualViewport;
width.value = Math.round(visualViewportWidth * scale);
height.value = Math.round(visualViewportHeight * scale);
} else if (includeScrollbar) {
width.value = window2.innerWidth;
height.value = window2.innerHeight;
} else {
width.value = window2.document.documentElement.clientWidth;
height.value = window2.document.documentElement.clientHeight;
}
};
update();
tryOnMounted(update);
const listenerOptions = { passive: true };
useEventListener("resize", update, listenerOptions);
if (window2 && type === "visual" && window2.visualViewport) useEventListener(window2.visualViewport, "resize", update, listenerOptions);
if (listenOrientation) watch(useMediaQuery("(orientation: portrait)"), () => update());
return {
width,
height
};
}
export {
useEventListener as a,
useMutationObserver as b,
useResizeObserver as c,
useWindowSize as d,
onClickOutside as o,
unrefElement as u
};
//# sourceMappingURL=index-rPPo0srK.js.map