vue3-treeview
Version:
A simple vue js 3 treeview component
1,432 lines (1,431 loc) • 42.6 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 { inject, ref, computed, defineAsyncComponent, resolveComponent, openBlock, createElementBlock, normalizeStyle, Fragment, renderList, createBlock, withCtx, renderSlot, toRefs, provide, onUnmounted, createVNode, mergeProps, watch, nextTick, normalizeClass, createElementVNode, createCommentVNode, onMounted, withKeys, withModifiers, withDirectives, vModelText, toDisplayString, Transition } from "vue";
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
function isNil(value) {
return value == null;
}
var lodash_isnil = isNil;
var INFINITY$1 = 1 / 0, MAX_INTEGER = 17976931348623157e292, NAN = 0 / 0;
var symbolTag$1 = "[object Symbol]";
var reTrim = /^\s+|\s+$/g;
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
var reIsBinary = /^0b[01]+$/i;
var reIsOctal = /^0o[0-7]+$/i;
var freeParseInt = parseInt;
var objectProto$1 = Object.prototype;
var objectToString$1 = objectProto$1.toString;
function isObject(value) {
var type = typeof value;
return !!value && (type == "object" || type == "function");
}
function isObjectLike$1(value) {
return !!value && typeof value == "object";
}
function isSymbol$1(value) {
return typeof value == "symbol" || isObjectLike$1(value) && objectToString$1.call(value) == symbolTag$1;
}
function toFinite(value) {
if (!value) {
return value === 0 ? value : 0;
}
value = toNumber(value);
if (value === INFINITY$1 || value === -INFINITY$1) {
var sign = value < 0 ? -1 : 1;
return sign * MAX_INTEGER;
}
return value === value ? value : 0;
}
function toInteger(value) {
var result = toFinite(value), remainder = result % 1;
return result === result ? remainder ? result - remainder : result : 0;
}
function toNumber(value) {
if (typeof value == "number") {
return value;
}
if (isSymbol$1(value)) {
return NAN;
}
if (isObject(value)) {
var other = typeof value.valueOf == "function" ? value.valueOf() : value;
value = isObject(other) ? other + "" : other;
}
if (typeof value != "string") {
return value === 0 ? value : +value;
}
value = value.replace(reTrim, "");
var isBinary = reIsBinary.test(value);
return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
}
var lodash_tointeger = toInteger;
const defaultSize = 8;
const defaultDisabledClass = "disabled";
const defaultFocusClass = "focused";
const defaultDragClass = "draggable";
const defaultDropClass = "droppable";
const defaultOverClass = "node-over";
const defaultInClass = "node-in";
const defaultUnderClass = "node-under";
const defaultViewBox = "0 0 123.958 123.959";
const defaultOpenDraw = `M117.979,28.017h-112c-5.3,0-8,6.4-4.2,10.2l56,56c2.3,2.3,6.1,2.3,8.401,0l56-56C125.979,34.417,123.279,28.017,117.979,28.017z`;
const defaultCloseDraw = `M38.217,1.779c-3.8-3.8-10.2-1.1-10.2,4.2v112c0,5.3,6.4,8,10.2,4.2l56-56c2.3-2.301,2.3-6.101,0-8.401L38.217,1.779z`;
const defaultColor = "black";
function createDefaultIcon(draw) {
return {
type: "shape",
width: defaultSize,
height: defaultSize,
viewBox: defaultViewBox,
stroke: defaultColor,
fill: defaultColor,
draw,
name: null,
src: null,
alt: null,
style: null,
class: null
};
}
const defaultConfig = {
roots: [],
padding: 16,
editable: false,
editing: null,
checkboxes: false,
dragAndDrop: false,
keyboardNavigation: false,
openedIcon: createDefaultIcon(defaultOpenDraw),
closedIcon: createDefaultIcon(defaultCloseDraw)
};
function useLevel(props) {
const state = inject("state");
const config = state.config;
const nodes = state.nodes;
const depth = ref(props.depth);
const parent = ref(props.parentId);
const level = computed(() => {
const res = [];
if (lodash_isnil(parent.value) && config.value.roots && depth.value === 0) {
for (const id2 of config.value.roots) {
addNode(id2, res);
}
return res;
}
if (!lodash_isnil(parent.value)) {
const node = nodes.value[parent.value];
if (node && node.children && node.children.length > 0) {
for (const id2 of node.children) {
addNode(id2, res);
}
}
return res;
}
return [];
});
const addNode = (id2, a) => {
if (nodes.value[id2]) {
nodes.value[id2].id = id2;
nodes.value[id2].parent = parent.value;
a.push(nodes.value[id2]);
}
};
const id = computed(() => {
return new Date().valueOf();
});
const padding = computed(() => {
if (depth.value === 0) {
return 0;
}
if (lodash_isnil(config.value.padding)) {
return defaultConfig.padding;
}
const p = lodash_tointeger(config.value.padding);
return p >= 0 ? p : 0;
});
const style = computed(() => {
return {
"padding-left": `${padding.value}px`,
"list-style": "none"
};
});
return {
id,
level,
padding,
style
};
}
var _export_sfc = (sfc, props) => {
for (const [key, val] of props) {
sfc[key] = val;
}
return sfc;
};
const _sfc_main$4 = {
components: {
TreeNode: defineAsyncComponent(() => Promise.resolve().then(function() {
return TreeNode$1;
}))
},
props: {
depth: {
required: true,
type: Number,
default: null
},
parentId: {
type: String,
default: null
}
},
setup(props) {
return __spreadValues({}, useLevel(props));
}
};
const _hoisted_1$2 = ["id"];
function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
const _component_TreeNode = resolveComponent("TreeNode");
return openBlock(), createElementBlock("ul", {
class: "tree-level",
id: _ctx.id,
style: normalizeStyle(_ctx.style)
}, [
(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.level, (item, index) => {
return openBlock(), createBlock(_component_TreeNode, {
key: item.id,
node: item,
depth: $props.depth,
index,
"parent-id": $props.parentId
}, {
"loading-slot": withCtx((props) => [
renderSlot(_ctx.$slots, "loading-slot", {
node: props.node
})
]),
"before-input": withCtx((props) => [
renderSlot(_ctx.$slots, "before-input", {
node: props.node
})
]),
"after-input": withCtx((props) => [
renderSlot(_ctx.$slots, "after-input", {
node: props.node
})
]),
_: 2
}, 1032, ["node", "depth", "index", "parent-id"]);
}), 128))
], 12, _hoisted_1$2);
}
var TreeLevel = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$4]]);
var TreeLevel$1 = /* @__PURE__ */ Object.freeze({
__proto__: null,
[Symbol.toStringTag]: "Module",
"default": TreeLevel
});
var INFINITY = 1 / 0;
var symbolTag = "[object Symbol]";
var freeGlobal = typeof commonjsGlobal == "object" && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
var freeSelf = typeof self == "object" && self && self.Object === Object && self;
var root = freeGlobal || freeSelf || Function("return this")();
var objectProto = Object.prototype;
var idCounter = 0;
var objectToString = objectProto.toString;
var Symbol$1 = root.Symbol;
var symbolProto = Symbol$1 ? Symbol$1.prototype : void 0, symbolToString = symbolProto ? symbolProto.toString : void 0;
function baseToString(value) {
if (typeof value == "string") {
return value;
}
if (isSymbol(value)) {
return symbolToString ? symbolToString.call(value) : "";
}
var result = value + "";
return result == "0" && 1 / value == -INFINITY ? "-0" : result;
}
function isObjectLike(value) {
return !!value && typeof value == "object";
}
function isSymbol(value) {
return typeof value == "symbol" || isObjectLike(value) && objectToString.call(value) == symbolTag;
}
function toString(value) {
return value == null ? "" : baseToString(value);
}
function uniqueId(prefix) {
var id = ++idCounter;
return toString(prefix) + id;
}
var lodash_uniqueid = uniqueId;
const states = new Map();
function createState(props) {
const { nodes, config } = toRefs(props);
const state = {
id: lodash_uniqueid(),
nodes: computed(() => nodes.value),
config: computed(() => config.value),
focusable: ref(null),
focusFunc: new Map(),
dragged: ref({
node: null,
element: null,
wrapper: null,
parentId: null
})
};
states.set(state.id, state);
return state.id;
}
function useTree(props, emit) {
const element = ref(null);
const id = createState(props);
const state = states.get(id);
provide("emitter", emit);
provide("state", state);
const style = computed(() => {
return {
"display": "flex",
"align-items": "center"
};
});
onUnmounted(() => {
states.delete(id);
});
return {
element,
style
};
}
var material_css_vue_type_style_index_0_src_lang = "";
const _sfc_main$3 = {
components: {
TreeLevel
},
props: {
nodes: {
required: true,
type: Object,
default: () => {
}
},
config: {
required: true,
type: Object,
default: () => {
}
}
},
setup(props, { emit }) {
return __spreadValues({}, useTree(props, emit));
},
methods: {
setElementRef(elt) {
this.element = elt;
}
}
};
function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
const _component_TreeLevel = resolveComponent("TreeLevel");
return openBlock(), createElementBlock("div", {
class: "tree",
ref: $options.setElementRef,
style: normalizeStyle(_ctx.style)
}, [
createVNode(_component_TreeLevel, mergeProps({
depth: 0,
"parent-id": null
}, _ctx.$attrs), {
"loading-slot": withCtx((props) => [
renderSlot(_ctx.$slots, "loading-slot", {
node: props.node
})
]),
"before-input": withCtx((props) => [
renderSlot(_ctx.$slots, "before-input", {
node: props.node
})
]),
"after-input": withCtx((props) => [
renderSlot(_ctx.$slots, "after-input", {
node: props.node
})
]),
_: 3
}, 16)
], 4);
}
var Tree = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render$3]]);
function eq(value, other) {
return value === other || value !== value && other !== other;
}
var lodash_eq = eq;
const nodeEvents = {
opened: "nodeOpened",
closed: "nodeClosed",
focus: "nodeFocus",
toggle: "nodeToggle",
blur: "nodeBlur",
edit: "nodeEdit"
};
const checkboxEvents = {
checked: "nodeChecked",
unchecked: "nodeUnchecked"
};
const dragEvents = {
start: "nodeDragstart",
end: "nodeDragend",
enter: "nodeDragenter",
leave: "nodeDragleave",
over: "nodeOver",
drop: "nodeDrop"
};
function useInput(cmn) {
const node = cmn.node;
const config = cmn.config;
const wrapper = cmn.wrapper;
const editable = cmn.editable;
const editing = cmn.editing;
const input = ref(null);
const text = computed({
get: () => node.value.text,
set: (val) => node.value.text = val
});
const editableClass = computed(() => {
if (!cmn.editable.value) {
return null;
}
return config.value.editableClass ? config.value.editableClass : "editable";
});
watch(editing, (nv, ov) => {
if (!lodash_eq(nv, ov) && nv) {
nextTick(() => {
input.value.focus();
});
}
});
const focusInput = () => {
if (editable.value && !cmn.disabled.value) {
config.value.editing = node.value.id;
cmn.root.emit(nodeEvents.edit, node.value);
}
};
const esc = (event) => {
if (editable.value && config.value.keyboardNavigation) {
cmn.blur(event);
wrapper.value.focus();
}
};
const enter = () => {
if (editable.value && !cmn.disabled.value && config.value.keyboardNavigation) {
focusInput();
}
};
return {
text,
input,
editing,
editable,
editableClass,
focusInput,
esc,
enter
};
}
function useIcon(props) {
const { isLeaf } = toRefs(props);
const state = inject("state");
const config = state.config;
const openedIcon = computed(() => {
return config.value.openedIcon || defaultConfig.openedIcon;
});
const closedIcon = computed(() => {
return config.value.closedIcon || defaultConfig.closedIcon;
});
const hasIcons = computed(() => {
return !lodash_isnil(closedIcon.value) && !lodash_isnil(openedIcon.value);
});
const useIcons = computed(() => {
return !isLeaf.value && hasIcons.value;
});
const fakeNodeStyle = computed(() => {
return {
width: `${defaultSize}px`,
height: `${defaultSize}px`
};
});
return {
hasIcons,
openedIcon,
closedIcon,
useIcons,
fakeNodeStyle
};
}
const _sfc_main$2 = {
props: {
icon: {
required: true,
type: Object
}
}
};
const _hoisted_1$1 = ["width", "height", "viewBox"];
const _hoisted_2$1 = ["d", "fill", "stroke", "stroke-width"];
const _hoisted_3$1 = ["src", "alt", "width", "height"];
function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
return $props.icon.type === "shape" ? (openBlock(), createElementBlock("svg", {
key: 0,
xmlns: "http://www.w3.org/2000/svg",
width: $props.icon.width,
height: $props.icon.height,
class: normalizeClass($props.icon.class),
style: normalizeStyle($props.icon.style),
viewBox: $props.icon.viewBox
}, [
createElementVNode("path", {
d: $props.icon.draw,
fill: $props.icon.fill,
stroke: $props.icon.stroke,
"stroke-width": $props.icon.strokeWidth
}, null, 8, _hoisted_2$1)
], 14, _hoisted_1$1)) : $props.icon.type === "class" ? (openBlock(), createElementBlock("i", {
key: 1,
class: normalizeClass($props.icon.class),
style: normalizeStyle($props.icon.style)
}, null, 6)) : $props.icon.type === "img" ? (openBlock(), createElementBlock("img", {
key: 2,
src: $props.icon.src,
alt: $props.icon.alt,
width: $props.icon.width,
height: $props.icon.height,
class: normalizeClass($props.icon.class),
style: normalizeStyle($props.icon.style)
}, null, 14, _hoisted_3$1)) : createCommentVNode("", true);
}
var Icon = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["render", _sfc_render$2]]);
const _sfc_main$1 = {
components: {
Icon
},
props: {
isLeaf: {
type: Boolean
},
opened: {
type: Boolean
}
},
setup(props) {
return useIcon(props);
},
computed: {
fakeIcon() {
return createDefaultIcon(null);
}
}
};
function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
const _component_Icon = resolveComponent("Icon");
return _ctx.useIcons ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
$props.opened ? (openBlock(), createBlock(_component_Icon, {
key: 0,
icon: _ctx.openedIcon
}, null, 8, ["icon"])) : (openBlock(), createBlock(_component_Icon, {
key: 1,
icon: _ctx.closedIcon
}, null, 8, ["icon"]))
], 64)) : (openBlock(), createBlock(_component_Icon, {
key: 1,
icon: $options.fakeIcon
}, null, 8, ["icon"]));
}
var TreeIcons = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render$1]]);
function useNode(cmn, props) {
const state = cmn.state;
const node = cmn.node;
const config = cmn.config;
const wrapper = cmn.wrapper;
const editing = cmn.editing;
const level = ref(null);
const depth = ref(props.depth);
const index = ref(props.index);
if (!node.value.children) {
node.value.children = ref([]).value;
}
const id = computed(() => {
return hasNode.value && node.value.id;
});
const hasNode = computed(() => {
return !lodash_isnil(node);
});
const hasState = computed(() => {
return hasNode.value && !lodash_isnil(node.value.state);
});
const roots = computed(() => {
return config.value.roots || [];
});
const children = computed(() => {
return lodash_isnil(node.value.children) ? [] : node.value.children;
});
const nbChildren = computed(() => {
return children.value.length;
});
const hasChildren = computed(() => {
return nbChildren.value > 0;
});
const opened = computed(() => {
return hasState.value && node.value.state.opened || false;
});
const isLoading = computed(() => {
return hasState.value && node.value.state.isLoading || false;
});
const displayLoading = computed(() => {
return isLoading.value && !hasChildren.value && opened.value;
});
const displayLevel = computed(() => {
return !isLoading.value && hasChildren.value && opened.value;
});
const style = computed(() => {
return {
display: "flex"
};
});
const disabledClass = computed(() => {
if (!cmn.disabled.value) {
return null;
}
return config.value.disabledClass ? config.value.disabledClass : defaultDisabledClass;
});
const hideIcons = computed(() => {
for (const id2 of roots.value) {
const node2 = state.nodes.value[id2];
if (node2.children && node2.children.length > 0) {
return false;
}
}
return true;
});
const isLeaf = computed(() => {
if (config.value.leaves instanceof Array) {
const arr = config.value.leaves;
const idx = arr.indexOf(id.value);
return Number.isFinite(idx) && idx >= 0;
}
return !hasChildren.value;
});
const isFocusable = computed(() => {
return state.focusable.value === node.value.id;
});
const tabIndex = computed(() => {
if (depth.value === 0 && index.value === 0 && lodash_isnil(state.focusable.value)) {
return 0;
}
return isFocusable.value ? 0 : -1;
});
const focusClass = computed(() => {
if (!cmn.focused.value) {
return null;
}
return config.value.focusClass ? config.value.focusClass : defaultFocusClass;
});
watch(opened, (nv) => {
nv ? cmn.root.emit(nodeEvents.opened, node.value) : cmn.root.emit(nodeEvents.closed, node.value);
});
const focus = () => {
state.focusable.value = node.value.id;
nextTick(() => {
wrapper.value.focus();
cmn.focused.value = true;
cmn.root.emit(nodeEvents.focus, node.value);
});
};
const toggle = () => {
node.value.state.opened = !node.value.state.opened;
cmn.root.emit(nodeEvents.toggle, node.value);
};
const right = () => {
if (!editing.value && config.value.keyboardNavigation) {
node.value.state.opened = true;
}
};
const left = () => {
if (!editing.value && config.value.keyboardNavigation) {
node.value.state.opened = false;
}
};
const move = (getFunc) => {
const id2 = getFunc(node.value.id);
if (!lodash_isnil(id2) && config.value.keyboardNavigation) {
const f = state.focusFunc.get(id2);
if (f) {
f();
}
}
};
const up = () => move(prevVisible);
const prev = (id2) => {
const n = state.nodes.value[id2];
if (n.children && n.children.length > 0) {
const idx = n.children.indexOf(node.value.id);
const prev2 = n.children[idx - 1];
if (!lodash_isnil(prev2)) {
return lastChild(prev2);
}
}
return n.id;
};
const prevVisible = (id2) => {
const n = state.nodes.value[id2];
const p = state.nodes.value[n.parent];
if (!p) {
const idx = roots.value.indexOf(id2);
return lastChild(roots.value[idx - 1]) || null;
}
return prev(p.id);
};
const lastChild = (id2) => {
const n = state.nodes.value[id2];
if (!n) {
return null;
}
if (n.children && n.children.length > 0 && n.state.opened) {
const last = n.children[n.children.length - 1];
if (!lodash_isnil(last)) {
return lastChild(last);
}
}
return n.id;
};
const down = () => move(nextVisible);
const nextRoot = (id2) => {
const idx = roots.value.indexOf(id2);
return roots.value[idx + 1] || null;
};
const next = (p, id2) => {
const idx = p.children.indexOf(id2);
if (p.children[idx + 1]) {
return p.children[idx + 1];
}
if (p.parent) {
return next(state.nodes.value[p.parent], p.id);
}
return nextRoot(p.id);
};
const nextVisible = (id2) => {
const n = state.nodes.value[id2];
if (n.children && n.children.length > 0 && n.state.opened) {
return n.children[0];
}
const p = state.nodes.value[n.parent];
return p ? next(p, id2) : nextRoot(id2);
};
onMounted(() => {
state.focusFunc.set(node.value.id, focus);
});
onUnmounted(() => {
state.focusFunc.delete(node.value.id);
});
return {
id,
level,
style,
opened,
hasNode,
hideIcons,
hasChildren,
tabIndex,
focusClass,
disabledClass,
isLeaf,
isLoading,
displayLoading,
displayLevel,
right,
left,
up,
down,
toggle,
focus,
prevVisible,
nextVisible
};
}
function ensureState(node) {
if (lodash_isnil(node.state)) {
node.state = {};
node.state.checked = false;
}
}
function auto(node, nodes) {
const check = (v) => {
node.value.state.checked = v;
};
const setIndeterminate = (v) => {
node.value.state.indeterminate = v;
};
const ensureCheck = () => {
ensureState(node.value);
if (node.value.state.checked || !hasChildren.value) {
setIndeterminate(false);
}
};
const children = computed(() => {
return node.value.children;
});
const hasChildren = computed(() => {
return !lodash_isnil(children.value) && children.value.length > 0 || false;
});
const states2 = computed(() => {
if (!hasChildren.value) {
return [];
}
const res = [];
for (const c of children.value) {
const child = nodes.value[c];
if (!lodash_isnil(child)) {
ensureState(child);
res.push(child.state);
}
}
return res;
});
const checked = computed(() => {
return node.value.state.checked;
});
const indeterminate = computed(() => {
return node.value.state.indeterminate;
});
const allChecked = computed(() => {
return states2.value.every((x) => x.checked);
});
const noneChecked = computed(() => {
return states2.value.every((x) => !x.checked);
});
const someChecked = computed(() => {
return !allChecked.value && !noneChecked.value;
});
const someIndeterminate = computed(() => {
return states2.value.some((x) => x.indeterminate);
});
const recurseDown = (n) => {
if (!lodash_isnil(n.state) && !lodash_isnil(n.children)) {
for (const id of n.children) {
const child = nodes.value[id];
if (!lodash_isnil(child)) {
ensureState(child);
child.state.indeterminate = false;
child.state.checked = n.state.checked;
recurseDown(child);
}
}
}
};
const updateState = () => {
if (!hasChildren.value) {
return;
}
if (noneChecked.value && !someIndeterminate.value) {
setIndeterminate(false);
check(false);
return;
}
if (allChecked.value) {
setIndeterminate(false);
check(true);
return;
}
setIndeterminate(true);
check(false);
};
const rebuild = () => {
ensureCheck();
recurseDown(node.value);
updateState();
};
const click = () => {
setIndeterminate(false);
check(!node.value.state.checked);
};
return {
checked,
indeterminate,
noneChecked,
someChecked,
allChecked,
someIndeterminate,
click,
rebuild,
updateState,
recurseDown
};
}
function manual(node) {
const checked = computed(() => {
return node.value.state.checked;
});
const indeterminate = computed(() => {
return node.value.state.indeterminate || false;
});
const noneChecked = computed(() => {
return false;
});
const someChecked = computed(() => {
return false;
});
const allChecked = computed(() => {
return false;
});
const someIndeterminate = computed(() => {
return false;
});
const click = () => {
node.value.state.checked = !node.value.state.checked;
};
const rebuild = () => {
};
const updateState = () => {
};
const recurseDown = () => {
};
return {
checked,
indeterminate,
noneChecked,
someChecked,
allChecked,
someIndeterminate,
click,
rebuild,
updateState,
recurseDown
};
}
var checkMode;
(function(checkMode2) {
checkMode2[checkMode2["auto"] = 0] = "auto";
checkMode2[checkMode2["manual"] = 1] = "manual";
})(checkMode || (checkMode = {}));
function useCheckBox(cmn) {
const node = cmn.node;
const config = cmn.config;
const nodes = cmn.state.nodes;
const mode = computed(() => {
return config.value.checkMode === checkMode.auto ? checkMode.auto : checkMode.manual;
});
const factory = computed(() => {
return mode.value === checkMode.auto ? auto(node, nodes) : manual(node);
});
watch(mode, (nv, ov) => {
if (!lodash_eq(nv, ov)) {
factory.value.rebuild();
}
});
const checked = computed(() => {
return factory.value.checked.value;
});
const indeterminate = computed(() => {
return factory.value.indeterminate.value;
});
const hasCheckbox = computed(() => {
return config.value.checkboxes || defaultConfig.checkboxes;
});
const checkedClass = computed(() => {
return [
factory.value.checked.value ? config.value.checkedClass ? config.value.checkedClass : "checked" : null,
factory.value.indeterminate.value ? config.value.indeterminateClass ? config.value.indeterminateClass : "indeterminate" : null
];
});
const allChecked = computed(() => {
return factory.value.allChecked.value;
});
const noneChecked = computed(() => {
return factory.value.noneChecked.value;
});
const someChecked = computed(() => {
return factory.value.someChecked.value;
});
const someIndeterminate = computed(() => {
return factory.value.someIndeterminate.value;
});
watch([allChecked, noneChecked, someChecked], ([ov1, ov2, ov3]) => {
if (ov1 || ov2 || ov3) {
factory.value.updateState();
}
}, { deep: true });
watch(someIndeterminate, (nv, ov) => {
if (!lodash_eq(nv, ov)) {
factory.value.updateState();
}
}, { deep: true });
const clickCheckbox = () => {
if (!cmn.disabled.value) {
factory.value.click();
factory.value.recurseDown(node.value);
cmn.root.emit(checked.value ? checkboxEvents.checked : checkboxEvents.unchecked, node.value);
}
};
const space = () => {
if (!cmn.editing.value && config.value.checkboxes && config.value.keyboardNavigation) {
clickCheckbox();
}
};
return {
checked,
hasCheckbox,
indeterminate,
checkedClass,
space,
clickCheckbox
};
}
var DragPosition;
(function(DragPosition2) {
DragPosition2[DragPosition2["over"] = 0] = "over";
DragPosition2[DragPosition2["in"] = 1] = "in";
DragPosition2[DragPosition2["under"] = 2] = "under";
})(DragPosition || (DragPosition = {}));
function useDragAndDrop(cmn, props) {
const node = cmn.node;
const state = cmn.state;
const parentId = ref(props.parentId);
const config = cmn.config;
const nodes = state.nodes;
const dragged = ref(state.dragged);
const wrapper = cmn.wrapper;
const element = ref(null);
const pos = ref(null);
const draggable = computed(() => {
return !cmn.disabled.value && config.value.dragAndDrop && node.value.state.draggable !== false;
});
const droppable = computed(() => {
return config.value.dragAndDrop && node.value.state.droppable !== false;
});
const isDragging = computed(() => {
return !lodash_isnil(dragged.value) && !lodash_isnil(dragged.value.node);
});
const isSameNode = computed(() => {
return isDragging.value && dragged.value.node.id === node.value.id;
});
const isSameParent = computed(() => {
return targetParent.value === draggedParent.value;
});
const draggedParent = computed(() => {
return !isDragging.value || !dragged.value.parentId ? null : getParent(dragged.value.parentId);
});
const draggedLvl = computed(() => {
return getLevel(draggedParent.value);
});
const targetParent = computed(() => {
return !lodash_isnil(parentId.value) ? getParent(parentId.value) : null;
});
const targetLvl = computed(() => {
return getLevel(targetParent.value);
});
const dragContain = computed(() => {
if (!isDragging.value || !dragged.value.wrapper) {
return false;
}
return dragged.value.element.contains(element.value);
});
const context = computed(() => {
return {
dragged: dragged.value,
target: {
node: node.value.id,
element: element.value,
wrapper: wrapper.value,
parentId: parentId.value
}
};
});
const dragClass = computed(() => {
return [
draggable.value ? defaultDragClass : null,
droppable.value ? defaultDropClass : null,
pos.value === 0 ? defaultOverClass : null,
pos.value === 1 ? defaultInClass : null,
pos.value === 2 ? defaultUnderClass : null
];
});
const getParent = (id) => {
return !lodash_isnil(id) ? nodes.value[id] : null;
};
const getLevel = (node2) => {
return !lodash_isnil(node2) ? node2.children : config.value.roots;
};
const getDataTransfer = (evt) => {
if (!evt || !evt.dataTransfer)
return null;
const jsonPayload = evt.dataTransfer.getData("application/json");
if (jsonPayload)
return JSON.parse(jsonPayload);
return evt.dataTransfer.getData("text/plain");
};
const isExternalSrc = (evt) => {
var _a, _b;
return ((_b = (_a = evt == null ? void 0 : evt.dataTransfer) == null ? void 0 : _a.items) == null ? void 0 : _b.length) > 0;
};
const dragstart = (evt) => {
if (draggable.value) {
dragged.value = {
node: node.value,
element: element.value,
wrapper: wrapper.value,
parentId: parentId.value
};
cmn.root.emit(dragEvents.start, __spreadValues(__spreadValues({}, context.value), eventContext(evt)));
}
};
const eventContext = (evt) => {
return {
evt,
external: isExternalSrc(evt),
dataTransfer: getDataTransfer(evt)
};
};
const dragend = (evt) => {
cmn.root.emit(dragEvents.end, __spreadValues(__spreadValues({}, context.value), eventContext(evt)));
dragged.value = null;
};
const dragenter = (evt) => {
cmn.root.emit(dragEvents.enter, __spreadValues(__spreadValues({}, context.value), eventContext(evt)));
};
const dragleave = (evt) => {
cmn.root.emit(dragEvents.leave, __spreadValues(__spreadValues({}, context.value), eventContext(evt)));
pos.value = null;
};
const dragover = (evt) => {
if (!isSameNode.value && !dragContain.value) {
const external = isExternalSrc(evt);
if (!isDragging.value && !external)
return;
cmn.root.emit(dragEvents.over, __spreadValues(__spreadValues({}, context.value), eventContext(evt)));
if (!external && wrapper.value) {
const factor = 0.3;
const y = evt.pageY;
const r = wrapper.value.getBoundingClientRect();
const midPoint = r.top + r.height / 2;
const midRange = [
midPoint - r.height * factor,
midPoint + r.height * factor
];
const idx = draggedLvl.value.indexOf(node.value.id);
const idxDrag = draggedLvl.value.indexOf(dragged.value.node.id);
if (y < midRange[0] && (!isSameParent.value || isSameParent.value && idx !== idxDrag + 1)) {
pos.value = 0;
} else if (y > midRange[1] && (!isSameParent.value || isSameParent.value && idx !== idxDrag - 1)) {
pos.value = 2;
} else {
pos.value = 1;
}
}
}
};
const drop = (evt) => {
if (!isSameNode.value && !dragContain.value) {
switch (pos.value) {
case 0: {
insertAt(0);
break;
}
case 2: {
insertAt(1);
break;
}
case 1: {
insertIn();
}
}
}
cmn.root.emit(dragEvents.drop, __spreadValues(__spreadValues({}, context.value), eventContext(evt)));
pos.value = null;
};
const insertAt = (i) => {
if (isDragging.value) {
const dragId = dragged.value.node.id;
const dragIdx = draggedLvl.value.indexOf(dragId);
draggedLvl.value.splice(dragIdx, 1);
const targetId = node.value.id;
const idx = targetLvl.value.indexOf(targetId);
targetLvl.value.splice(idx + i, 0, dragId);
}
};
const insertIn = () => {
if (isDragging.value && droppable.value) {
const dragId = dragged.value.node.id;
if (draggedLvl.value) {
const idx = draggedLvl.value.indexOf(dragId);
draggedLvl.value.splice(idx, 1);
}
node.value.children.unshift(dragId);
}
};
return {
pos,
element,
dragClass,
draggable,
droppable,
dragstart,
dragend,
dragenter,
dragleave,
dragover,
drop
};
}
function useCommon(props) {
const { node } = toRefs(props);
const state = inject("state");
const config = state.config;
const wrapper = ref(null);
const focused = ref(false);
const root2 = {
emit: inject("emitter")
};
ensureState(node.value);
const hasNode = computed(() => {
return !lodash_isnil(node);
});
const hasConfig = computed(() => {
return !lodash_isnil(config.value);
});
const hasState = computed(() => {
return hasNode.value && !lodash_isnil(node.value.state);
});
const disabled = computed(() => {
return config.value.disabled || node.value.state.disabled;
});
const editable = computed(() => {
return config.value.editable && (!lodash_isnil(node.value.state.editable) ? node.value.state.editable : true) || defaultConfig.editable;
});
const editing = computed(() => {
return editable.value && config.value.editing === node.value.id;
});
const blur = (e) => {
if (e.type === "blur") {
const current = e.currentTarget;
const related = e.relatedTarget;
if (!current.contains(related)) {
config.value.editing = null;
focused.value = false;
root2.emit(nodeEvents.blur, e, node.value);
}
}
};
return {
state,
node,
config,
hasNode,
hasState,
hasConfig,
disabled,
wrapper,
editable,
editing,
focused,
blur,
root: root2
};
}
const _sfc_main = {
components: {
TreeLevel: defineAsyncComponent(() => Promise.resolve().then(function() {
return TreeLevel$1;
})),
TreeIcons
},
emits: [
...Object.values(nodeEvents),
...Object.values(checkboxEvents),
...Object.values(dragEvents)
],
props: {
depth: {
required: true,
type: Number
},
index: {
required: true,
type: Number
},
node: {
required: true,
type: Object
},
parentId: {
default: null,
type: String
}
},
setup(props) {
const cmn = useCommon(props);
return __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, cmn), useInput(cmn)), useCheckBox(cmn)), useNode(cmn, props)), useDragAndDrop(cmn, props));
},
computed: {
nodeClass() {
return [
this.focusClass,
this.disabledClass,
this.checkedClass,
this.editableClass,
this.dragClass
];
}
},
methods: {
setWrapperRef(e) {
this.wrapper = e;
},
setLevelRef(e) {
this.level = e;
},
setElementRef(e) {
this.element = e;
},
setInputRef(e) {
this.input = e;
}
}
};
const _hoisted_1 = ["aria-expanded"];
const _hoisted_2 = ["draggable", "tabindex"];
const _hoisted_3 = ["checked", "disabled", ".indeterminate"];
const _hoisted_4 = { class: "input-wrapper" };
const _hoisted_5 = ["disabled"];
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_TreeIcons = resolveComponent("TreeIcons");
const _component_TreeLevel = resolveComponent("TreeLevel");
return _ctx.hasNode ? (openBlock(), createElementBlock("li", {
key: 0,
class: "tree-node",
ref: $options.setElementRef,
"aria-expanded": _ctx.opened,
onKeydown: [
_cache[13] || (_cache[13] = withKeys(withModifiers((...args) => _ctx.enter && _ctx.enter(...args), ["stop"]), ["enter"])),
_cache[14] || (_cache[14] = withKeys(withModifiers((...args) => _ctx.esc && _ctx.esc(...args), ["stop"]), ["esc"])),
_cache[15] || (_cache[15] = withKeys(withModifiers((...args) => _ctx.space && _ctx.space(...args), ["stop"]), ["space"])),
_cache[16] || (_cache[16] = withKeys(withModifiers((...args) => _ctx.left && _ctx.left(...args), ["stop"]), ["left"])),
_cache[17] || (_cache[17] = withKeys(withModifiers((...args) => _ctx.right && _ctx.right(...args), ["stop"]), ["right"])),
_cache[18] || (_cache[18] = withKeys(withModifiers((...args) => _ctx.up && _ctx.up(...args), ["stop"]), ["up"])),
_cache[19] || (_cache[19] = withKeys(withModifiers((...args) => _ctx.down && _ctx.down(...args), ["stop"]), ["down"]))
]
}, [
createElementVNode("div", {
class: normalizeClass(["node-wrapper", $options.nodeClass]),
style: normalizeStyle(_ctx.style),
ref: $options.setWrapperRef,
draggable: _ctx.draggable,
tabindex: _ctx.tabIndex,
onBlur: _cache[5] || (_cache[5] = (...args) => _ctx.blur && _ctx.blur(...args)),
onClick: _cache[6] || (_cache[6] = withModifiers((...args) => _ctx.focus && _ctx.focus(...args), ["stop"])),
onDragstart: _cache[7] || (_cache[7] = withModifiers((...args) => _ctx.dragstart && _ctx.dragstart(...args), ["stop"])),
onDragend: _cache[8] || (_cache[8] = withModifiers((...args) => _ctx.dragend && _ctx.dragend(...args), ["stop"])),
onDragenter: _cache[9] || (_cache[9] = withModifiers((...args) => _ctx.dragenter && _ctx.dragenter(...args), ["prevent", "stop"])),
onDragleave: _cache[10] || (_cache[10] = withModifiers((...args) => _ctx.dragleave && _ctx.dragleave(...args), ["prevent", "stop"])),
onDragover: _cache[11] || (_cache[11] = withModifiers((...args) => _ctx.dragover && _ctx.dragover(...args), ["prevent", "stop"])),
onDrop: _cache[12] || (_cache[12] = withModifiers((...args) => _ctx.drop && _ctx.drop(...args), ["prevent", "stop"]))
}, [
!_ctx.hideIcons ? (openBlock(), createElementBlock("div", {
key: 0,
class: "icon-wrapper",
onClick: _cache[0] || (_cache[0] = withModifiers((...args) => _ctx.toggle && _ctx.toggle(...args), ["stop"]))
}, [
createVNode(_component_TreeIcons, {
"is-leaf": _ctx.isLeaf,
opened: _ctx.opened
}, null, 8, ["is-leaf", "opened"])
])) : createCommentVNode("", true),
_ctx.hasCheckbox ? (openBlock(), createElementBlock("div", {
key: 1,
class: normalizeClass(["checkbox-wrapper", _ctx.checkedClass]),
onClick: _cache[1] || (_cache[1] = withModifiers((...args) => _ctx.clickCheckbox && _ctx.clickCheckbox(...args), ["stop"]))
}, [
createElementVNode("input", {
type: "checkbox",
tabindex: "-1",
class: "node-checkbox",
checked: _ctx.checked,
disabled: _ctx.disabled,
".indeterminate": _ctx.indeterminate
}, null, 40, _hoisted_3)
], 2)) : createCommentVNode("", true),
renderSlot(_ctx.$slots, "before-input", { node: $props.node }),
createElementVNode("div", _hoisted_4, [
_ctx.editing ? withDirectives((openBlock(), createElementBlock("input", {
key: 0,
type: "text",
tabindex: "0",
class: "node-input",
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => _ctx.text = $event),
ref: $options.setInputRef,
disabled: _ctx.disabled,
onBlur: _cache[3] || (_cache[3] = (...args) => _ctx.blur && _ctx.blur(...args))
}, null, 40, _hoisted_5)), [
[vModelText, _ctx.text]
]) : (openBlock(), createElementBlock("span", {
key: 1,
class: "node-text",
onDblclick: _cache[4] || (_cache[4] = (...args) => _ctx.focusInput && _ctx.focusInput(...args))
}, toDisplayString(_ctx.text), 33))
]),
renderSlot(_ctx.$slots, "after-input", { node: $props.node })
], 46, _hoisted_2),
_ctx.displayLoading ? renderSlot(_ctx.$slots, "loading-slot", {
key: 0,
node: $props.node
}) : createCommentVNode("", true),
createVNode(Transition, { name: "level" }, {
default: withCtx(() => [
_ctx.displayLevel ? (openBlock(), createBlock(_component_TreeLevel, {
key: 0,
"parent-id": _ctx.id,
depth: $props.depth + 1,
ref: $options.setLevelRef
}, {
"loading-slot": withCtx((props) => [
renderSlot(_ctx.$slots, "loading-slot", {
node: props.node
})
]),
"before-input": withCtx((props) => [
renderSlot(_ctx.$slots, "before-input", {
node: props.node
})
]),
"after-input": withCtx((props) => [
renderSlot(_ctx.$slots, "after-input", {
node: props.node
})
]),
_: 3
}, 8, ["parent-id", "depth"])) : createCommentVNode("", true)
]),
_: 3
})
], 40, _hoisted_1)) : createCommentVNode("", true);
}
var TreeNode = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
var TreeNode$1 = /* @__PURE__ */ Object.freeze({
__proto__: null,
[Symbol.toStringTag]: "Module",
"default": TreeNode
});
export { Tree as default };