snail.vue 1.0.47 → 1.0.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/snail.vue.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //@ sourceURL=/snail.vue.js
2
- import { defineComponent, createElementBlock, openBlock, normalizeClass, renderSlot, createTextVNode, shallowRef, computed, normalizeStyle, createElementVNode, toDisplayString, Fragment, renderList, unref, mergeModels, useModel, createCommentVNode, createBlock, nextTick, withDirectives, vModelText, createVNode, createApp, Transition, withCtx, normalizeProps, guardReactiveProps, watch, ref, onErrorCaptured, resolveDynamicComponent, mergeProps, createSlots, onMounted, withModifiers, isRef, getCurrentInstance, useTemplateRef, resolveComponent, onBeforeUnmount, getCurrentScope, onScopeDispose } from 'vue';
2
+ import { defineComponent, createElementBlock, openBlock, normalizeClass, renderSlot, createTextVNode, shallowRef, normalizeStyle, createElementVNode, toDisplayString, Fragment, renderList, unref, mergeModels, useModel, computed, createCommentVNode, createBlock, nextTick, withDirectives, vModelText, createVNode, createApp, Transition, withCtx, normalizeProps, guardReactiveProps, watch, ref, onErrorCaptured, resolveDynamicComponent, mergeProps, createSlots, onMounted, withModifiers, isRef, getCurrentInstance, useTemplateRef, resolveComponent, onBeforeUnmount, getCurrentScope, onScopeDispose } from 'vue';
3
3
  import { throwError, isArrayNotEmpty, isStringNotEmpty, isArray, newId, mustFunction, useScope, removeFromArray, mustObject, throwIfFalse, isObject, isNumberNotNaN, mountScope, useScopes, isPromise, wait, script, delay, useTimer, defer, useAsyncScope, useHook, hasAny, throwIfTrue, isFunction, onMountScope } from 'snail.core';
4
4
  import { link, css, useObserver, useAnimation } from 'snail.view';
5
5
 
@@ -27,8 +27,8 @@ var addLink = href => setTimeout(link.register, 0, href);
27
27
 
28
28
  addLink("/styles/snail.vue.vue.css");
29
29
 
30
- function getSvgDraw(options) {
31
- switch (options.type) {
30
+ function getSvgDraw(iconType, draw) {
31
+ switch (iconType) {
32
32
  case "success":
33
33
  return ["M 102.272 613.285 a 48.9258 48.9258 0 0 1 -1.34967 -62.8444 l 26.0656 -31.2113 a 50.6129 50.6129 0 0 1 62.6756 -11.2192 l 199.583 121.218 c 19.4859 11.8097 49.0102 8.26677 65.9655 -8.01371 l 540.714 -519.625 a 40.3216 40.3216 0 0 1 57.9518 1.6871 l 37.9597 43.3583 a 47.5762 47.5762 0 0 1 -0.843545 62.4226 L 452.766 920.675 a 38.4658 38.4658 0 0 1 -56.8553 1.18097 L 102.272 613.285 Z"];
34
34
  case "error":
@@ -47,19 +47,23 @@ function getSvgDraw(options) {
47
47
  return ["M 780.8 366.933 c 34.1333 -34.1333 34.1333 -93.8667 0 -128 c -38.4 -34.1333 -93.8667 -34.1333 -132.267 0 l -68.2667 68.2667 l 132.267 128 l 68.2667 -68.2667 Z M 541.867 349.867 l -277.333 277.333 L 213.333 806.4 l 179.2 -51.2 l 281.6 -277.333 Z M 469.333 768 h 341.333 v 42.6667 h -341.333 Z"];
48
48
  case "arrow":
49
49
  return ["M651.3 514.2c0 8.2-3.1 16.4-9.4 22.6L426.4 752.4c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L574 514.2 381.1 321.4c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l215.5 215.5c6.2 6.3 9.4 14.5 9.4 22.6z"];
50
+ case "plus":
51
+ return ["M 768 469.333 h -213.333 V 256 c 0 -25.6 -17.0667 -42.6667 -42.6667 -42.6667 s -42.6667 17.0667 -42.6667 42.6667 v 213.333 H 256 c -25.6 0 -42.6667 17.0667 -42.6667 42.6667 s 17.0667 42.6667 42.6667 42.6667 h 213.333 v 213.333 c 0 25.6 17.0667 42.6667 42.6667 42.6667 s 42.6667 -17.0667 42.6667 -42.6667 v -213.333 h 213.333 c 25.6 0 42.6667 -17.0667 42.6667 -42.6667 s -17.0667 -42.6667 -42.6667 -42.6667 Z"];
52
+ case "subtract":
53
+ return ["M768 554.666667H256c-25.6 0-42.666667-17.066667-42.666667-42.666667s17.066667-42.666667 42.666667-42.666667h512c25.6 0 42.666667 17.066667 42.666667 42.666667s-17.066667 42.666667-42.666667 42.666667z"];
50
54
  case "grip":
51
55
  return ["M 384 256 m -42.6667 0 a 42.6667 42.6667 0 1 0 85.3333 0 a 42.6667 42.6667 0 1 0 -85.3333 0 Z", "M 384 426.667 m -42.6667 0 a 42.6667 42.6667 0 1 0 85.3333 0 a 42.6667 42.6667 0 1 0 -85.3333 0 Z", "M 384 597.333 m -42.6667 0 a 42.6667 42.6667 0 1 0 85.3333 0 a 42.6667 42.6667 0 1 0 -85.3333 0 Z", "M 384 768 m -42.6667 0 a 42.6667 42.6667 0 1 0 85.3333 0 a 42.6667 42.6667 0 1 0 -85.3333 0 Z", "M 640 256 m -42.6667 0 a 42.6667 42.6667 0 1 0 85.3333 0 a 42.6667 42.6667 0 1 0 -85.3333 0 Z", "M 640 426.667 m -42.6667 0 a 42.6667 42.6667 0 1 0 85.3333 0 a 42.6667 42.6667 0 1 0 -85.3333 0 Z", "M 640 597.333 m -42.6667 0 a 42.6667 42.6667 0 1 0 85.3333 0 a 42.6667 42.6667 0 1 0 -85.3333 0 Z", "M 640 768 m -42.6667 0 a 42.6667 42.6667 0 1 0 85.3333 0 a 42.6667 42.6667 0 1 0 -85.3333 0 Z"];
52
56
  case "custom":
53
- return isArrayNotEmpty(options.draw) ? options.draw : isStringNotEmpty(options.draw) ? [options.draw] : throwError("options.draw must be a non-empty string or string array");
57
+ return isArrayNotEmpty(draw) ? draw : isStringNotEmpty(draw) ? [draw] : throwError("options.draw must be a non-empty string or string array");
54
58
  default:
55
- throwError(`not support icon type: ${options.type}.`);
59
+ throwError(`not support icon type: ${iconType}.`);
56
60
  break;
57
61
  }
58
62
  }
59
63
 
60
64
  const _hoisted_1$f = ["width", "height"];
61
65
  const _hoisted_2$a = ["textContent"];
62
- const _hoisted_3$6 = ["d", "fill"];
66
+ const _hoisted_3$7 = ["fill", "stroke", "stroke-width", "d"];
63
67
  var _sfc_main$s = defineComponent({
64
68
  ...{
65
69
  name: "Icon",
@@ -72,36 +76,31 @@ var _sfc_main$s = defineComponent({
72
76
  color: {},
73
77
  hoverColor: {},
74
78
  size: {},
79
+ stroke: {},
80
+ strokeWidth: {},
75
81
  draw: {},
76
82
  rotate: {}
77
83
  },
78
84
  setup(__props) {
79
- const props = __props;
80
- const paths = getSvgDraw(props || {});
81
- const colorRef = shallowRef(props.color);
82
- const styleRef = computed(() => props.rotate ? `transform: rotate(${props.rotate}deg);` : "");
83
- function onMouseEnter() {
84
- colorRef.value = props.hoverColor || props.color;
85
- }
86
- function onMouseLeave() {
87
- colorRef.value = props.color;
88
- }
85
+ const isMouseEnterRef = shallowRef(false);
89
86
  return (_ctx, _cache) => {
90
87
  return openBlock(), createElementBlock("svg", {
91
88
  class: normalizeClass(["snail-icon", _ctx.type]),
92
89
  viewBox: "0 0 1024 1024",
93
- width: props.size || 24,
94
- height: props.size || 24,
95
- style: normalizeStyle(styleRef.value),
96
- onMouseenter: onMouseEnter,
97
- onMouseleave: onMouseLeave
90
+ style: normalizeStyle(_ctx.rotate ? `transform: rotate(${_ctx.rotate}deg);` : ""),
91
+ width: _ctx.size || 24,
92
+ height: _ctx.size || 24,
93
+ onMouseenter: _cache[0] || (_cache[0] = $event => isMouseEnterRef.value = true),
94
+ onMouseleave: _cache[1] || (_cache[1] = $event => isMouseEnterRef.value = false)
98
95
  }, [createElementVNode("title", {
99
- textContent: toDisplayString(props.title || "")
100
- }, null, 8, _hoisted_2$a), (openBlock(true), createElementBlock(Fragment, null, renderList(unref(paths), draw => {
96
+ textContent: toDisplayString(_ctx.title || "")
97
+ }, null, 8, _hoisted_2$a), (openBlock(true), createElementBlock(Fragment, null, renderList(unref(getSvgDraw)(_ctx.type, _ctx.draw), draw => {
101
98
  return openBlock(), createElementBlock("path", {
102
- d: draw,
103
- fill: colorRef.value
104
- }, null, 8, _hoisted_3$6);
99
+ fill: isMouseEnterRef.value ? _ctx.hoverColor || _ctx.color : _ctx.color,
100
+ stroke: _ctx.stroke,
101
+ "stroke-width": _ctx.strokeWidth,
102
+ d: draw
103
+ }, null, 8, _hoisted_3$7);
105
104
  }), 256))], 46, _hoisted_1$f);
106
105
  };
107
106
  }
@@ -109,7 +108,7 @@ var _sfc_main$s = defineComponent({
109
108
 
110
109
  const _hoisted_1$e = ["onClick"];
111
110
  const _hoisted_2$9 = ["type", "checked"];
112
- const _hoisted_3$5 = ["textContent"];
111
+ const _hoisted_3$6 = ["textContent"];
113
112
  const _hoisted_4$4 = ["textContent"];
114
113
  var _sfc_main$r = defineComponent({
115
114
  ...{
@@ -191,7 +190,7 @@ var _sfc_main$r = defineComponent({
191
190
  key: 2,
192
191
  class: "item-text",
193
192
  textContent: toDisplayString(item.text)
194
- }, null, 8, _hoisted_3$5)) : createCommentVNode("", true), item.description ? (openBlock(), createElementBlock("span", {
193
+ }, null, 8, _hoisted_3$6)) : createCommentVNode("", true), item.description ? (openBlock(), createElementBlock("span", {
195
194
  key: 3,
196
195
  class: "item-des",
197
196
  textContent: toDisplayString(item.description)
@@ -480,23 +479,11 @@ function checkFollow(options) {
480
479
  function calcFollowX(options, target, width) {
481
480
  const space = isNumberNotNaN(options.spaceX) ? options.spaceX : 0;
482
481
  const spaceClient = isNumberNotNaN(options.spaceClient) ? options.spaceClient : 0;
483
- if (target.left < spaceClient || target.right + spaceClient > window.innerWidth) {
484
- return {
485
- strategy: void 0,
486
- start: -width
487
- };
488
- }
489
482
  return electPosition(getFollowStrategy(options.followX) || ["start", "end", "after", "before", "center", "ratio"], target.left, target.right, width, window.innerWidth, space, spaceClient);
490
483
  }
491
484
  function calcFollowY(options, target, height) {
492
485
  const space = isNumberNotNaN(options.spaceY) ? options.spaceY : 0;
493
486
  const spaceClient = isNumberNotNaN(options.spaceClient) ? options.spaceClient : 0;
494
- if (target.top < spaceClient || target.bottom + spaceClient > window.innerHeight) {
495
- return {
496
- strategy: void 0,
497
- start: -height
498
- };
499
- }
500
487
  return electPosition(getFollowStrategy(options.followY) || ["after", "before", "start", "end", "center", "ratio"], target.top, target.bottom, height, window.innerHeight, space, spaceClient);
501
488
  }
502
489
  function getFollowStrategy(strategy) {
@@ -877,7 +864,8 @@ var _sfc_main$j = defineComponent({
877
864
  const {
878
865
  onClient,
879
866
  onSize,
880
- onEvent
867
+ onEvent,
868
+ onMutation
881
869
  } = useObserver();
882
870
  const {
883
871
  onTimeout
@@ -900,9 +888,7 @@ var _sfc_main$j = defineComponent({
900
888
  if (__props.popupStatus.value == "closed") {
901
889
  return;
902
890
  }
903
- console.group("%cstart run buildFollow:", "color:red");
904
891
  const targetRect = __props.extOptions.target.getBoundingClientRect();
905
- console.log("-- target:", targetRect, __props.extOptions.target);
906
892
  css.operate(rootDom.value, "add", {
907
893
  style: {
908
894
  width: __props.options.followWidth ? `${targetRect.width}px` : "",
@@ -915,14 +901,12 @@ var _sfc_main$j = defineComponent({
915
901
  const rootRect = rootDom.value.getBoundingClientRect();
916
902
  {
917
903
  const xResult = calcFollowX(__props.options, targetRect, rootRect.width);
918
- console.log("-- follow x:", xResult);
919
904
  followStyle.left = `${xResult.start}px`;
920
905
  xResult.size != void 0 && (followStyle.width = `${xResult.size}px`);
921
906
  followExt.followX.value = xResult.strategy;
922
907
  }
923
908
  {
924
909
  const yResult = calcFollowY(__props.options, targetRect, rootRect.height);
925
- console.log("-- follow y: ", yResult);
926
910
  followStyle.top = `${yResult.start}px`;
927
911
  yResult.size != void 0 && (followStyle.height = `${yResult.size}px`);
928
912
  followExt.followY.value = yResult.strategy;
@@ -940,9 +924,7 @@ var _sfc_main$j = defineComponent({
940
924
  height: rootRect.height
941
925
  });
942
926
  rootDom.value.classList.remove("initial");
943
- console.log("-- content rect: ", rootRect, rootDom.value);
944
927
  }
945
- console.groupEnd();
946
928
  }
947
929
  function onRootSize(size) {
948
930
  const isChange = preSize.width != size.width || preSize.height != size.height;
@@ -958,7 +940,14 @@ var _sfc_main$j = defineComponent({
958
940
  onTimeout(function () {
959
941
  onEvent(window, "resize", () => __props.options.closeOnResize ? closePopup(void 0) : rootDom.value && buildFollow());
960
942
  onEvent(window, "keyup", evet => __props.options.closeOnEscape && evet.key === "Escape" && followExt.pinned.value != true && closePopup(void 0));
961
- onEvent(window, "click", event => __props.options.closeOnMask && rootDom.value != event.target && rootDom.value.contains(event.target) == false && followExt.pinned.value != true && closePopup(void 0));
943
+ onEvent(window, "click", event => {
944
+ __props.options.closeOnMask && followExt.pinned.value != true && rootDom.value != event.target && rootDom.value.contains(event.target) == false && closePopup(void 0);
945
+ });
946
+ onMutation(rootDom.value, {
947
+ childList: true,
948
+ attributes: false,
949
+ subtree: true
950
+ }, buildFollow);
962
951
  }, 100);
963
952
  });
964
953
  });
@@ -1151,7 +1140,7 @@ function usePopup() {
1151
1140
  });
1152
1141
  }
1153
1142
  function toast(type, message, options) {
1154
- popupInCustomContainer(_sfc_main$h, {
1143
+ return popupInCustomContainer(_sfc_main$h, {
1155
1144
  url: "#ToastContainer",
1156
1145
  props: {
1157
1146
  ...(options || Object.create(null)),
@@ -1212,7 +1201,7 @@ const _hoisted_1$9 = {
1212
1201
  class: "snail-empty"
1213
1202
  };
1214
1203
  const _hoisted_2$6 = ["src"];
1215
- const _hoisted_3$4 = ["textContent"];
1204
+ const _hoisted_3$5 = ["textContent"];
1216
1205
  var _sfc_main$g = defineComponent({
1217
1206
  ...{
1218
1207
  name: "Empty",
@@ -1232,13 +1221,17 @@ var _sfc_main$g = defineComponent({
1232
1221
  }, null, 8, _hoisted_2$6), renderSlot(_ctx.$slots, "default", {}, () => [createElementVNode("div", {
1233
1222
  class: "message",
1234
1223
  textContent: toDisplayString(props.message || "无数据")
1235
- }, null, 8, _hoisted_3$4)])]);
1224
+ }, null, 8, _hoisted_3$5)])]);
1236
1225
  };
1237
1226
  }
1238
1227
  });
1239
1228
 
1240
1229
  const _hoisted_1$8 = ["title"];
1241
1230
  const _hoisted_2$5 = ["textContent"];
1231
+ const _hoisted_3$4 = {
1232
+ key: 1,
1233
+ class: "select-status"
1234
+ };
1242
1235
  var _sfc_main$f = defineComponent({
1243
1236
  ...{
1244
1237
  name: "SelectNode",
@@ -1288,11 +1281,15 @@ var _sfc_main$f = defineComponent({
1288
1281
  key: 0,
1289
1282
  type: "arrow",
1290
1283
  color: "#8a9099"
1291
- })) : createCommentVNode("", true)], 42, _hoisted_1$8)) : createCommentVNode("", true), showRef.value ? (openBlock(true), createElementBlock(Fragment, {
1284
+ })) : _ctx.multiple == true ? (openBlock(), createElementBlock("div", _hoisted_3$4, [createVNode(_sfc_main$s, {
1285
+ type: "success",
1286
+ color: "white",
1287
+ size: 12
1288
+ })])) : createCommentVNode("", true)], 42, _hoisted_1$8)) : createCommentVNode("", true), showRef.value ? (openBlock(true), createElementBlock(Fragment, {
1292
1289
  key: 1
1293
1290
  }, renderList(unref(showChildrenRef), child => {
1294
1291
  return openBlock(), createBlock(_component_SelectNode, {
1295
- key: child.id || unref(newId)(),
1292
+ key: _ctx.context.getKey(child),
1296
1293
  multiple: _ctx.multiple,
1297
1294
  item: child,
1298
1295
  context: _ctx.context,
@@ -1320,6 +1317,9 @@ var _sfc_main$e = defineComponent({
1320
1317
  showPath: {
1321
1318
  type: Boolean
1322
1319
  },
1320
+ showClear: {
1321
+ type: Boolean
1322
+ },
1323
1323
  popupStyle: {},
1324
1324
  context: {},
1325
1325
  level: {},
@@ -1335,7 +1335,7 @@ var _sfc_main$e = defineComponent({
1335
1335
  followY: {},
1336
1336
  pinned: {}
1337
1337
  },
1338
- emits: ["change"],
1338
+ emits: ["clear", "click"],
1339
1339
  setup(__props, _ref) {
1340
1340
  let {
1341
1341
  emit: __emit
@@ -1364,10 +1364,33 @@ var _sfc_main$e = defineComponent({
1364
1364
  "text-tips": itemsRef.value.length == 0,
1365
1365
  "has-group": itemsRef.value.find(node => node.type == "group") != void 0
1366
1366
  }));
1367
+ const needClearButton = props.multiple == true ? props.level == 1 : props.level == 1 && isStringNotEmpty(context.selectedText(false, props.showPath));
1368
+ const showClearButtonRef = computed(() => needClearButton && props.showClear && (props.multiple ? context.selectedText(true, props.showPath) : true));
1367
1369
  const childDestroyTimerRef = shallowRef(void 0);
1368
1370
  var mouseStatus = "Leave";
1369
1371
  var childFollowTargetDom = void 0;
1370
1372
  var childFollowScope = void 0;
1373
+ function watchOptionsChange() {
1374
+ const inValid = props.multiple == true && itemsRef.value && itemsRef.value.some(item => item.children && item.children.length > 0);
1375
+ if (inValid == true) {
1376
+ const message = "select-popup.vue: select item cannot be multi-level when multiple == true";
1377
+ onTimeout(() => {
1378
+ props.closePopup();
1379
+ alert(message);
1380
+ throw new Error(message);
1381
+ }, 0);
1382
+ }
1383
+ }
1384
+ function emitClickEvent() {
1385
+ for (var _len = arguments.length, path = new Array(_len), _key = 0; _key < _len; _key++) {
1386
+ path[_key] = arguments[_key];
1387
+ }
1388
+ if (popupStatus.value != "closed") {
1389
+ path = path.filter(item => item != void 0);
1390
+ emits("click", path);
1391
+ props.multiple || props.closePopup(path);
1392
+ }
1393
+ }
1371
1394
  function destroyChildFollow(onlyTimer) {
1372
1395
  childDestroyTimerRef.value && childDestroyTimerRef.value.destroy();
1373
1396
  childDestroyTimerRef.value = void 0;
@@ -1392,16 +1415,6 @@ var _sfc_main$e = defineComponent({
1392
1415
  destroyChildFollow();
1393
1416
  context.doSearch(text);
1394
1417
  }
1395
- function onSelected() {
1396
- if (popupStatus.value != "closed") {
1397
- for (var _len = arguments.length, path = new Array(_len), _key = 0; _key < _len; _key++) {
1398
- path[_key] = arguments[_key];
1399
- }
1400
- const values = path.filter(item => item != void 0);
1401
- emits("change", values);
1402
- props.multiple || props.closePopup(values);
1403
- }
1404
- }
1405
1418
  async function onEnterSelectNode(target, node, parent) {
1406
1419
  if (popupStatus.value == "closed") {
1407
1420
  return;
@@ -1424,6 +1437,7 @@ var _sfc_main$e = defineComponent({
1424
1437
  items: node.children,
1425
1438
  context,
1426
1439
  search: void 0,
1440
+ multiple: props.multiple,
1427
1441
  level: props.level + 1,
1428
1442
  popupStyle: props.popupStyle,
1429
1443
  childDestroyTimer: childDestroyTimerRef,
@@ -1431,35 +1445,43 @@ var _sfc_main$e = defineComponent({
1431
1445
  })
1432
1446
  });
1433
1447
  const datas = await childFollowScope;
1434
- isArrayNotEmpty(datas) && onSelected(parent ? parent : void 0, node, ...datas);
1448
+ isArrayNotEmpty(datas) && emitClickEvent(parent ? parent : void 0, node, ...datas);
1435
1449
  popupStatus.value == "open" && onTimeout(() => mouseStatus != "Enter" && onLeavePopup(), 10);
1436
1450
  }
1437
1451
  }
1438
1452
  function onClickSelectNode(node, parent) {
1439
- if (node.clickable == true) {
1440
- onSelected(parent ? parent : void 0, node);
1441
- }
1453
+ node.clickable && emitClickEvent(parent ? parent : void 0, node);
1454
+ }
1455
+ function onClearAllClick() {
1456
+ emits("clear");
1457
+ props.closePopup([]);
1458
+ }
1459
+ {
1460
+ watcher(() => props.multiple, watchOptionsChange);
1461
+ watcher(itemsRef, watchOptionsChange);
1462
+ watchOptionsChange();
1442
1463
  }
1443
1464
  watcher(pinned, newValue => newValue == true && parentPinned && (parentPinned.value = true));
1444
1465
  watcher(popupStatus, newValue => newValue == "closed" && childFollowScope && childFollowScope.destroy());
1445
1466
  return (_ctx, _cache) => {
1446
1467
  return openBlock(), createElementBlock("div", {
1447
1468
  class: normalizeClass(classRef.value),
1448
- style: normalizeStyle(props.popupStyle),
1469
+ style: normalizeStyle(_ctx.popupStyle),
1449
1470
  onMouseenter: onEnterPopup,
1450
1471
  onMouseleave: onLeavePopup
1451
1472
  }, [classRef.value["child-popup"] && classRef.value["text-tips"] ? (openBlock(), createElementBlock(Fragment, {
1452
1473
  key: 0
1453
1474
  }, [createTextVNode(" 暂无选项 ")], 64)) : (openBlock(), createElementBlock(Fragment, {
1454
1475
  key: 1
1455
- }, [props.search ? (openBlock(), createBlock(_sfc_main$o, mergeProps({
1476
+ }, [_ctx.search ? (openBlock(), createBlock(_sfc_main$o, mergeProps({
1456
1477
  key: 0
1457
- }, props.search, {
1458
- onSearch
1478
+ }, _ctx.search, {
1479
+ onSearch,
1480
+ key: "select-search"
1459
1481
  }), null, 16)) : createCommentVNode("", true), (openBlock(true), createElementBlock(Fragment, null, renderList(itemsRef.value, item => {
1460
1482
  return openBlock(), createBlock(_sfc_main$f, {
1461
- key: item.id || unref(newId)(),
1462
- multiple: props.multiple,
1483
+ key: unref(context).getKey(item),
1484
+ multiple: _ctx.multiple,
1463
1485
  item,
1464
1486
  context: unref(context),
1465
1487
  "show-children": true,
@@ -1469,20 +1491,28 @@ var _sfc_main$e = defineComponent({
1469
1491
  }), 128)), itemsRef.value.length == 0 ? (openBlock(), createBlock(_sfc_main$g, {
1470
1492
  key: 1,
1471
1493
  message: "无结果"
1472
- })) : createCommentVNode("", true)], 64))], 38);
1494
+ })) : createCommentVNode("", true), showClearButtonRef.value ? (openBlock(), createElementBlock("div", {
1495
+ key: 2,
1496
+ class: "clear-all",
1497
+ onClick: onClearAllClick
1498
+ }, " 清空已选 ")) : createCommentVNode("", true)], 64))], 38);
1473
1499
  };
1474
1500
  }
1475
1501
  });
1476
1502
 
1477
- function useTreeContext(nodes) {
1503
+ function useTreeContext(nodes, activeNodeRef) {
1478
1504
  const failed = shallowRef();
1479
1505
  const patched = shallowRef();
1506
+ const nodeKeyMap = new Map();
1480
1507
  function doSearch(text) {
1481
1508
  text = isStringNotEmpty(text) ? text.toLowerCase() : void 0;
1482
1509
  const result = searchTree(nodes, text);
1483
1510
  failed.value = result.failed;
1484
1511
  patched.value = result.patched;
1485
1512
  }
1513
+ function isActived(node) {
1514
+ return activeNodeRef && activeNodeRef.value == node;
1515
+ }
1486
1516
  function isPatched(node) {
1487
1517
  return patched.value ? patched.value.includes(node) : false;
1488
1518
  }
@@ -1501,12 +1531,18 @@ function useTreeContext(nodes) {
1501
1531
  function getPath(node) {
1502
1532
  return searchPath(nodes, node);
1503
1533
  }
1534
+ function getKey(node) {
1535
+ nodeKeyMap.has(node) || nodeKeyMap.set(node, newId());
1536
+ return nodeKeyMap.get(node);
1537
+ }
1504
1538
  const context = mountScope({
1505
1539
  doSearch,
1540
+ isActived,
1506
1541
  isPatched,
1507
1542
  isShow,
1508
1543
  isShowChildren,
1509
- getPath
1544
+ getPath,
1545
+ getKey
1510
1546
  }, "ITreeBaseContext");
1511
1547
  context.onDestroy(() => {
1512
1548
  failed.value = void 0;
@@ -1558,7 +1594,7 @@ function useSelectContext(items, selectsRef) {
1558
1594
  return false;
1559
1595
  }
1560
1596
  function selectedText(multiple, showPath) {
1561
- if (selectsRef.value) {
1597
+ if (selectsRef.value && selectsRef.value.length) {
1562
1598
  return multiple == true || showPath == true ? selectsRef.value.map(item => item.text).join(multiple ? "、" : " / ") : selectsRef.value[selectsRef.value.length - 1].text;
1563
1599
  }
1564
1600
  return "";
@@ -1609,11 +1645,15 @@ var _sfc_main$d = defineComponent({
1609
1645
  showPath: {
1610
1646
  type: Boolean
1611
1647
  },
1612
- popupStyle: {}
1613
- }, {
1614
- "modelValue": {
1615
- default: []
1648
+ showClear: {
1649
+ type: Boolean
1616
1650
  },
1651
+ popupStyle: {},
1652
+ valuePathDisabled: {
1653
+ type: Boolean
1654
+ }
1655
+ }, {
1656
+ "modelValue": {},
1617
1657
  "modelModifiers": {}
1618
1658
  }),
1619
1659
  emits: mergeModels(["change"], ["update:modelValue"]),
@@ -1631,13 +1671,23 @@ var _sfc_main$d = defineComponent({
1631
1671
  onTimeout
1632
1672
  } = useTimer();
1633
1673
  const rootDom = useTemplateRef("select");
1634
- const context = useSelectContext(props.items, valuesModel);
1635
- const selectTextRef = computed(() => context.selectedText(props.multiple, props.showPath));
1674
+ const selectedItemsRef = computed(() => valuesModel.value ? Array.isArray(valuesModel.value) ? valuesModel.value : [valuesModel.value] : []);
1675
+ const context = useSelectContext(props.items, selectedItemsRef);
1676
+ const selectedTextRef = computed(() => context.selectedText(props.multiple, props.showPath));
1636
1677
  const slotOptions = Object.freeze({
1637
1678
  clear
1638
1679
  });
1639
1680
  var followScope = void 0;
1640
1681
  var stopPropagationScope = void 0;
1682
+ function updateModelValue(newValue, eventValues) {
1683
+ if (valuesModel.value != newValue) {
1684
+ valuesModel.value = newValue;
1685
+ nextTick(() => emits("change", eventValues));
1686
+ }
1687
+ }
1688
+ function isSingleValue() {
1689
+ return props.multiple != true && props.valuePathDisabled == true;
1690
+ }
1641
1691
  function destroyFollow() {
1642
1692
  if (followScope != void 0) {
1643
1693
  followScope.destroy();
@@ -1647,19 +1697,19 @@ var _sfc_main$d = defineComponent({
1647
1697
  return false;
1648
1698
  }
1649
1699
  function clear(closeFollow, stopPropagation) {
1650
- valuesModel.value = [];
1651
1700
  closeFollow && destroyFollow();
1652
1701
  stopPropagationScope && stopPropagationScope.destroy();
1653
1702
  stopPropagationScope = stopPropagation ? onTimeout(() => stopPropagationScope = void 0, 200) : void 0;
1703
+ updateModelValue(isSingleValue() ? void 0 : [], []);
1654
1704
  }
1655
1705
  async function onClick() {
1656
- if (props.readonly == true || rootDom.value == void 0) {
1706
+ if (props.readonly == true || rootDom.value == void 0 || isArrayNotEmpty(props.items) == false) {
1657
1707
  return;
1658
1708
  }
1659
1709
  if (destroyFollow() == true || stopPropagationScope != void 0) {
1660
1710
  return;
1661
1711
  }
1662
- const values = valuesModel.value && valuesModel.value.length > 0 ? [...valuesModel.value] : [];
1712
+ const values = [...selectedItemsRef.value];
1663
1713
  props.multiple != true && values.length > 1 && values.splice(0, values.length - 1);
1664
1714
  context.doSearch(void 0);
1665
1715
  followScope = follow(rootDom.value, {
@@ -1677,17 +1727,28 @@ var _sfc_main$d = defineComponent({
1677
1727
  level: 1,
1678
1728
  search: props.search,
1679
1729
  multiple: props.multiple,
1730
+ showClear: props.showClear,
1680
1731
  popupStyle: props.popupStyle,
1681
- onChange: onSelectItemChange
1732
+ onClick: onSelectItemClick,
1733
+ onClear: () => clear(true, false)
1682
1734
  }
1683
1735
  });
1684
1736
  await followScope;
1685
1737
  followScope = void 0;
1686
1738
  }
1687
- function onSelectItemChange(items) {
1688
- items = hasAny(items) ? [...items] : [];
1689
- valuesModel.value = items;
1690
- nextTick(() => emits("change", items));
1739
+ function onSelectItemClick(path) {
1740
+ path = hasAny(path) ? [...path] : [];
1741
+ if (props.multiple == true) {
1742
+ const node = path[path.length - 1];
1743
+ if (node) {
1744
+ path = [...selectedItemsRef.value];
1745
+ removeFromArray(path, node) == -1 && path.push(node);
1746
+ updateModelValue(path, path);
1747
+ }
1748
+ } else {
1749
+ const newValue = isSingleValue() ? path[path.length - 1] : path;
1750
+ updateModelValue(newValue, path);
1751
+ }
1691
1752
  }
1692
1753
  return (_ctx, _cache) => {
1693
1754
  return openBlock(), createElementBlock("div", {
@@ -1698,10 +1759,10 @@ var _sfc_main$d = defineComponent({
1698
1759
  ref: "select"
1699
1760
  }, [props.items && props.items.length > 0 ? (openBlock(), createElementBlock(Fragment, {
1700
1761
  key: 0
1701
- }, [valuesModel.value.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_1$7, [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(unref(slotOptions))), () => [createElementVNode("div", {
1762
+ }, [selectedItemsRef.value.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_1$7, [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(unref(slotOptions))), () => [createElementVNode("div", {
1702
1763
  class: "select-text",
1703
- title: selectTextRef.value,
1704
- textContent: toDisplayString(selectTextRef.value)
1764
+ title: selectedTextRef.value,
1765
+ textContent: toDisplayString(selectedTextRef.value)
1705
1766
  }, null, 8, _hoisted_2$4)])])) : (openBlock(), createElementBlock("div", {
1706
1767
  key: 1,
1707
1768
  class: "select-result text-tips",
@@ -1884,6 +1945,7 @@ var _sfc_main$a = defineComponent({
1884
1945
  emits: ["xbar", "left", "right", "ybar", "top", "bottom"],
1885
1946
  setup(__props, _ref) {
1886
1947
  let {
1948
+ expose: __expose,
1887
1949
  emit: __emit
1888
1950
  } = _ref;
1889
1951
  const props = __props;
@@ -1900,6 +1962,18 @@ var _sfc_main$a = defineComponent({
1900
1962
  "scroll-y": props.scrollY == true
1901
1963
  }));
1902
1964
  var preStatus = void 0;
1965
+ __expose({
1966
+ scroll,
1967
+ scrollTo
1968
+ });
1969
+ function scroll(left, top) {
1970
+ left == void 0 || (rootDom.value.scrollLeft += left);
1971
+ top == void 0 || (rootDom.value.scrollTop += top);
1972
+ }
1973
+ function scrollTo(left, top) {
1974
+ left == void 0 || (rootDom.value.scrollLeft = left);
1975
+ top == void 0 || (rootDom.value.scrollTop = top);
1976
+ }
1903
1977
  function refreshScrollInfo() {
1904
1978
  const status = {
1905
1979
  xbar: rootDom.value.scrollWidth > rootDom.value.clientWidth,
@@ -1984,7 +2058,7 @@ var _sfc_main$9 = defineComponent({
1984
2058
  }, props.scroll), {
1985
2059
  default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
1986
2060
  _: 3
1987
- }, 16), _ctx.$slots.end ? (openBlock(), createElementBlock("div", _hoisted_2$2, [renderSlot(_ctx.$slots, "end")])) : createCommentVNode("", true), _cache[0] || (_cache[0] = createTextVNode(' " '))], 2);
2061
+ }, 16), _ctx.$slots.end ? (openBlock(), createElementBlock("div", _hoisted_2$2, [renderSlot(_ctx.$slots, "end")])) : createCommentVNode("", true)], 2);
1988
2062
  };
1989
2063
  }
1990
2064
  });
@@ -2194,7 +2268,7 @@ const _hoisted_3$1 = {
2194
2268
  };
2195
2269
  const _hoisted_4$1 = {
2196
2270
  key: 1,
2197
- class: "snail-tree-children",
2271
+ class: "snail-tree-children hidden",
2198
2272
  ref: "children"
2199
2273
  };
2200
2274
  var _sfc_main$4 = defineComponent({
@@ -2222,13 +2296,13 @@ var _sfc_main$4 = defineComponent({
2222
2296
  const {
2223
2297
  transition
2224
2298
  } = useAnimation();
2299
+ const {
2300
+ watcher
2301
+ } = useReactive();
2302
+ const treeNodeDom = useTemplateRef("tree-node");
2303
+ const isHoveredRef = shallowRef(false);
2225
2304
  const showRef = computed(() => __props.context.isShow(__props.node, true));
2226
2305
  const showChildrenRef = computed(() => __props.context.isShowChildren(__props.node, true));
2227
- const classRef = computed(() => {
2228
- const array = [`level-${__props.level}`];
2229
- __props.node.clickable && array.push("clickable");
2230
- return array;
2231
- });
2232
2306
  const slotOptions = Object.freeze({
2233
2307
  node: __props.node,
2234
2308
  parent: __props.parent,
@@ -2239,7 +2313,9 @@ var _sfc_main$4 = defineComponent({
2239
2313
  const statusRef = shallowRef("expand");
2240
2314
  const nextLevel = __props.level + 1;
2241
2315
  const childrenDom = useTemplateRef("children");
2316
+ var nodeEmitsDisabled = false;
2242
2317
  function toggleFold() {
2318
+ nodeEmitsDisabled = true;
2243
2319
  switch (statusRef.value) {
2244
2320
  case "expand":
2245
2321
  statusRef.value = "fold";
@@ -2253,7 +2329,7 @@ var _sfc_main$4 = defineComponent({
2253
2329
  const maxHeight = childrenDom.value.scrollHeight;
2254
2330
  transition(childrenDom.value, {
2255
2331
  from: {
2256
- transition: "height 0.2s ease",
2332
+ transition: `height 0.2s ease`,
2257
2333
  overflow: "hidden",
2258
2334
  height: `${statusRef.value == "fold" ? maxHeight : minHeight}px`
2259
2335
  },
@@ -2268,7 +2344,10 @@ var _sfc_main$4 = defineComponent({
2268
2344
  }
2269
2345
  }
2270
2346
  function onNodeClick(node) {
2271
- node.clickable == true && emits("click", node, __props.parent ? [__props.parent] : void 0);
2347
+ if (node.clickable == true && nodeEmitsDisabled != true) {
2348
+ emits("click", node, __props.parent ? [__props.parent] : void 0);
2349
+ }
2350
+ nodeEmitsDisabled = false;
2272
2351
  }
2273
2352
  function onNodeDoubleClick() {
2274
2353
  __props.options.foldDisabled != true && toggleFold();
@@ -2277,17 +2356,36 @@ var _sfc_main$4 = defineComponent({
2277
2356
  parents = __props.parent ? [__props.parent, ...parents] : parents;
2278
2357
  emits("click", child, parents);
2279
2358
  }
2359
+ watcher(isHoveredRef, newValue => {
2360
+ treeNodeDom.value.classList.remove("hovered");
2361
+ newValue && treeNodeDom.value.classList.add("hovered");
2362
+ });
2363
+ watcher(() => __props.context.isActived(__props.node), newValue => {
2364
+ treeNodeDom.value.classList.remove("actived");
2365
+ newValue && treeNodeDom.value.classList.add("actived");
2366
+ });
2367
+ onMounted(() => {
2368
+ if (childrenDom.value) {
2369
+ __props.options.expandLevel != void 0 && __props.options.expandLevel < nextLevel && toggleFold();
2370
+ childrenDom.value && childrenDom.value.classList.remove("hidden");
2371
+ nodeEmitsDisabled = false;
2372
+ }
2373
+ });
2280
2374
  return (_ctx, _cache) => {
2281
2375
  const _component_TreeNode = resolveComponent("TreeNode", true);
2282
2376
  return openBlock(), createElementBlock(Fragment, null, [showRef.value ? (openBlock(), createElementBlock("div", {
2283
2377
  key: 0,
2284
- class: normalizeClass(["snail-tree-node", classRef.value]),
2378
+ class: normalizeClass(["snail-tree-node", _ctx.node.clickable ? "clickable" : "", `level-${_ctx.level}`]),
2379
+ ref: "tree-node",
2380
+ onMouseenter: _cache[0] || (_cache[0] = $event => isHoveredRef.value = true),
2381
+ onMouseleave: _cache[1] || (_cache[1] = $event => isHoveredRef.value = false),
2382
+ onClick: _cache[2] || (_cache[2] = $event => onNodeClick(_ctx.node)),
2285
2383
  onDblclick: onNodeDoubleClick
2286
2384
  }, [_ctx.options.rewrite == true ? renderSlot(_ctx.$slots, "default", normalizeProps(mergeProps({
2287
2385
  key: 0
2288
2386
  }, unref(slotOptions)))) : (openBlock(), createElementBlock(Fragment, {
2289
2387
  key: 1
2290
- }, [_cache[2] || (_cache[2] = createElementVNode("div", {
2388
+ }, [_cache[4] || (_cache[4] = createElementVNode("div", {
2291
2389
  class: "indent"
2292
2390
  }, null, -1)), _ctx.options.foldDisabled != true ? (openBlock(), createElementBlock("div", _hoisted_1$3, [showChildrenRef.value ? (openBlock(), createBlock(_sfc_main$s, {
2293
2391
  key: 0,
@@ -2300,17 +2398,16 @@ var _sfc_main$4 = defineComponent({
2300
2398
  }, null, 8, ["class"])) : createCommentVNode("", true)])) : createCommentVNode("", true), createElementVNode("div", {
2301
2399
  class: "node-text",
2302
2400
  title: _ctx.node.text,
2303
- textContent: toDisplayString(_ctx.node.text),
2304
- onClick: _cache[0] || (_cache[0] = $event => onNodeClick(_ctx.node))
2401
+ textContent: toDisplayString(_ctx.node.text)
2305
2402
  }, null, 8, _hoisted_2$1), createElementVNode("div", _hoisted_3$1, [renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(unref(slotOptions))))])], 64))], 34)) : createCommentVNode("", true), showRef.value && showChildrenRef.value ? (openBlock(), createElementBlock("div", _hoisted_4$1, [(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.node.children, child => {
2306
2403
  return openBlock(), createBlock(_component_TreeNode, {
2307
- key: child.id || unref(newId)(),
2404
+ key: _ctx.context.getKey(child),
2308
2405
  node: child,
2309
2406
  parent: _ctx.node,
2310
2407
  level: nextLevel,
2311
2408
  options: _ctx.options,
2312
2409
  context: _ctx.context,
2313
- onClick: _cache[1] || (_cache[1] = (node, parents) => onChildNodeClick(node, parents))
2410
+ onClick: _cache[3] || (_cache[3] = (node, parents) => onChildNodeClick(node, parents))
2314
2411
  }, {
2315
2412
  default: withCtx(slotProps => [renderSlot(_ctx.$slots, "default", mergeProps({
2316
2413
  ref_for: true
@@ -2344,14 +2441,20 @@ var _sfc_main$3 = defineComponent({
2344
2441
  } = _ref;
2345
2442
  const props = __props;
2346
2443
  const emits = __emit;
2347
- const context = useTreeContext(props.nodes);
2444
+ const activedNodeRef = shallowRef(void 0);
2445
+ const context = useTreeContext(props.nodes, activedNodeRef);
2348
2446
  __expose({
2349
- context
2447
+ context,
2448
+ onTreeNodeClick
2350
2449
  });
2351
2450
  function onSearch(text) {
2352
2451
  context.doSearch(text);
2353
2452
  emits("searched", text);
2354
2453
  }
2454
+ function onTreeNodeClick(node, parents) {
2455
+ activedNodeRef.value = node;
2456
+ emits("click", node, parents);
2457
+ }
2355
2458
  return (_ctx, _cache) => {
2356
2459
  return openBlock(), createElementBlock("div", _hoisted_1$2, [props.search ? (openBlock(), createBlock(_sfc_main$o, mergeProps({
2357
2460
  key: 0
@@ -2362,19 +2465,19 @@ var _sfc_main$3 = defineComponent({
2362
2465
  }, {
2363
2466
  default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(props.nodes || [], node => {
2364
2467
  return openBlock(), createBlock(_sfc_main$4, {
2365
- key: node.id || unref(newId)(),
2468
+ key: unref(context).getKey(node),
2366
2469
  node,
2367
2470
  parent: void 0,
2368
2471
  level: 1,
2369
2472
  options: props.nodeOptions,
2370
2473
  context: unref(context),
2371
- onClick: (node2, parents) => emits("click", node2, parents)
2474
+ onClick: onTreeNodeClick
2372
2475
  }, {
2373
2476
  default: withCtx(slotProps => [renderSlot(_ctx.$slots, "default", mergeProps({
2374
2477
  ref_for: true
2375
2478
  }, slotProps))]),
2376
2479
  _: 2
2377
- }, 1032, ["node", "options", "context", "onClick"]);
2480
+ }, 1032, ["node", "options", "context"]);
2378
2481
  }), 128))]),
2379
2482
  _: 3
2380
2483
  })]);