@blueking/bk-user-selector 0.1.5 → 0.1.7

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.
@@ -6,12 +6,13 @@
6
6
  ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.lesscodeCustomComponentLibrary = {}, global.Vue, global.bkui_vue));
7
7
  })(this, function(exports, vue, bkui_vue) {
8
8
  var __vite_style__ = document.createElement("style");
9
- __vite_style__.textContent = "@charset \"UTF-8\";.me-tag[data-v-a1054364] {\n position: absolute;\n top: 50%;\n right: 8px;\n z-index: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n padding: 0 8px;\n font-size: 12px;\n color: #4d4f56;\n white-space: nowrap;\n cursor: pointer;\n background-color: #e1ecff;\n border-radius: 50%;\n transform: translateY(-50%);\n}\n.me-tag[data-v-a1054364]:hover {\n color: #3a84ff;\n background-color: #cddffe;\n}\n.me-tag.disabled[data-v-a1054364] {\n color: #c4c6cc;\n cursor: not-allowed;\n background-color: #f0f1f5;\n}.dropdown-content[data-v-9173accf] {\n min-height: 40px;\n max-height: 300px;\n padding: 5px 0;\n overflow-y: auto;\n}\n.dropdown-content .no-data[data-v-9173accf] {\n padding: 10px;\n color: #979ba5;\n text-align: center;\n}\n.dropdown-content .user-group .group-header[data-v-9173accf] {\n display: flex;\n align-items: center;\n padding: 8px 12px;\n color: #979ba5;\n}\n.dropdown-content .user-group .group-header .group-count[data-v-9173accf] {\n margin-left: 4px;\n}\n.dropdown-content .user-option[data-v-9173accf] {\n display: flex;\n align-items: center;\n height: 32px;\n padding: 8px 12px;\n cursor: pointer;\n}\n.dropdown-content .user-option[data-v-9173accf]:hover, .dropdown-content .user-option.is-highlighted[data-v-9173accf] {\n background-color: #f5f7fa;\n}.user-tag[data-v-d1173d20] {\n height: 24px;\n margin-right: 4px;\n margin-left: 0;\n}\n.user-tag.draggable[data-v-d1173d20] {\n cursor: move;\n}\n.user-tag.active[data-v-d1173d20] {\n background-color: #e1ecff;\n border-color: #3a84ff;\n}\n.user-tag.is-custom[data-v-d1173d20] {\n color: #ea3636;\n background-color: #feebea;\n border-color: rgba(234, 53, 54, 0.3019607843);\n}\n.user-tag.is-custom[data-v-d1173d20]:hover {\n background-color: #fedddc;\n}\n.user-tag .tag-content .user-name[data-v-d1173d20] {\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 12px;\n white-space: nowrap;\n}\n.bk-user-selector[data-v-089550be] {\n position: relative;\n width: 100%;\n height: 32px;\n font-size: 12px;\n}\n.bk-user-selector.is-disabled[data-v-089550be] {\n pointer-events: none;\n cursor: not-allowed;\n background-color: #dcdee5;\n}\n.bk-user-selector.is-textarea[data-v-089550be] {\n height: auto;\n min-height: 32px;\n}\n.bk-user-selector .tags-container[data-v-089550be] {\n position: relative;\n min-height: 32px;\n padding: 3px 10px 3px 8px;\n background-color: #fff;\n border: 1px solid #c4c6cc;\n border-radius: 2px;\n transition: all 0.2s ease;\n}\n.bk-user-selector .tags-container.focused[data-v-089550be] {\n border-color: #3a84ff;\n box-shadow: 0 0 0 2px rgba(58, 132, 255, 0.1);\n}\n.bk-user-selector .tags-container.tags-container-collapsed[data-v-089550be] {\n display: flex;\n flex-wrap: wrap;\n row-gap: 4px;\n align-items: center;\n /* 与 .tag-list 一致:避免默认 stretch 拉高行高后 align-items:center 把首行顶离上边框 */\n align-content: flex-start;\n}\n.bk-user-selector .tag-list[data-v-089550be] {\n display: flex;\n flex-wrap: wrap;\n row-gap: 4px;\n align-items: center;\n align-content: flex-start;\n}\n.bk-user-selector .tag-wrapper[data-v-089550be] {\n display: inline-flex;\n align-items: center;\n max-width: 100%;\n}\n.bk-user-selector .search-input[data-v-089550be] {\n min-width: 20px;\n height: 24px;\n outline: none;\n background: transparent;\n border: none;\n}\n.bk-user-selector .search-input[data-v-089550be]::placeholder {\n color: #c4c6cc;\n}\n.bk-user-selector .search-input.input-inline[data-v-089550be] {\n min-width: 20px;\n}\n.bk-user-selector .search-input.input-last[data-v-089550be], .bk-user-selector .search-input.search-input-collapsed[data-v-089550be] {\n flex: 1;\n}\n.hidden-users[data-v-089550be] {\n padding: 6px 10px;\n}.bk-user-selector-popover {\n padding: 0 !important;\n}\n.bk-user-selector.is-textarea .me-tag {\n top: 4px;\n transform: none;\n}/*$vite$:1*/";
9
+ __vite_style__.textContent = "@charset \"UTF-8\";.me-tag[data-v-a1054364] {\n position: absolute;\n top: 50%;\n right: 8px;\n z-index: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n padding: 0 8px;\n font-size: 12px;\n color: #4d4f56;\n white-space: nowrap;\n cursor: pointer;\n background-color: #e1ecff;\n border-radius: 50%;\n transform: translateY(-50%);\n}\n.me-tag[data-v-a1054364]:hover {\n color: #3a84ff;\n background-color: #cddffe;\n}\n.me-tag.disabled[data-v-a1054364] {\n color: #c4c6cc;\n cursor: not-allowed;\n background-color: #f0f1f5;\n}.dropdown-content[data-v-9173accf] {\n min-height: 40px;\n max-height: 300px;\n padding: 5px 0;\n}\n.dropdown-content .no-data[data-v-9173accf] {\n padding: 10px;\n color: #979ba5;\n text-align: center;\n}\n.dropdown-panels[data-v-9173accf] {\n display: block;\n}\n.dropdown-panel[data-v-9173accf] {\n min-width: 0;\n max-height: 290px;\n overflow-y: auto;\n}\n.dropdown-panels.is-two-column[data-v-9173accf] {\n display: flex;\n}\n.dropdown-panels.is-two-column .dropdown-panel[data-v-9173accf] {\n width: 50%;\n}\n.dropdown-panels.is-two-column .dropdown-panel + .dropdown-panel[data-v-9173accf] {\n border-left: 1px solid #eaebf0;\n}\n.group-header[data-v-9173accf] {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 8px 12px;\n color: #979ba5;\n}\n.group-header .group-name[data-v-9173accf],\n.group-header .group-count[data-v-9173accf] {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.user-group[data-v-9173accf],\n.dropdown-panel-main[data-v-9173accf],\n.dropdown-panel-recent[data-v-9173accf] {\n min-width: 0;\n}\n.user-option[data-v-9173accf] {\n display: flex;\n align-items: center;\n min-width: 0;\n height: 32px;\n padding: 8px 12px;\n cursor: pointer;\n}\n.user-option[data-v-9173accf]:hover, .user-option.is-highlighted[data-v-9173accf] {\n background-color: #f5f7fa;\n}\n.dropdown-panel[data-v-9173accf] .user-render,\n.dropdown-panel[data-v-9173accf] .user-main,\n.dropdown-panel[data-v-9173accf] .user-name,\n.dropdown-panel[data-v-9173accf] .tenant-name,\n.user-option[data-v-9173accf] .user-render,\n.user-option[data-v-9173accf] .user-main,\n.user-option[data-v-9173accf] .user-name,\n.user-option[data-v-9173accf] .tenant-name {\n min-width: 0;\n}\n.dropdown-panel[data-v-9173accf] .user-name,\n.dropdown-panel[data-v-9173accf] .tenant-name,\n.user-option[data-v-9173accf] .user-name,\n.user-option[data-v-9173accf] .tenant-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}.user-tag[data-v-d1173d20] {\n height: 24px;\n margin-right: 4px;\n margin-left: 0;\n}\n.user-tag.draggable[data-v-d1173d20] {\n cursor: move;\n}\n.user-tag.active[data-v-d1173d20] {\n background-color: #e1ecff;\n border-color: #3a84ff;\n}\n.user-tag.is-custom[data-v-d1173d20] {\n color: #ea3636;\n background-color: #feebea;\n border-color: rgba(234, 53, 54, 0.3019607843);\n}\n.user-tag.is-custom[data-v-d1173d20]:hover {\n background-color: #fedddc;\n}\n.user-tag .tag-content .user-name[data-v-d1173d20] {\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: 12px;\n white-space: nowrap;\n}\n.bk-user-selector[data-v-089550be] {\n position: relative;\n width: 100%;\n height: 32px;\n font-size: 12px;\n}\n.bk-user-selector.is-disabled[data-v-089550be] {\n pointer-events: none;\n cursor: not-allowed;\n background-color: #dcdee5;\n}\n.bk-user-selector.is-textarea[data-v-089550be] {\n height: auto;\n min-height: 32px;\n}\n.bk-user-selector .tags-container[data-v-089550be] {\n position: relative;\n min-height: 32px;\n padding: 3px 10px 3px 8px;\n background-color: #fff;\n border: 1px solid #c4c6cc;\n border-radius: 2px;\n transition: all 0.2s ease;\n}\n.bk-user-selector .tags-container.focused[data-v-089550be] {\n border-color: #3a84ff;\n box-shadow: 0 0 0 2px rgba(58, 132, 255, 0.1);\n}\n.bk-user-selector .tags-container.tags-container-collapsed[data-v-089550be] {\n display: flex;\n flex-wrap: wrap;\n row-gap: 4px;\n /* 与 .tag-list 一致:避免默认 stretch 拉高行高后 align-items:center 把首行顶离上边框 */\n align-content: flex-start;\n align-items: center;\n}\n.bk-user-selector .tag-list[data-v-089550be] {\n display: flex;\n flex-wrap: wrap;\n row-gap: 4px;\n align-content: flex-start;\n align-items: center;\n}\n.bk-user-selector .tag-wrapper[data-v-089550be] {\n display: inline-flex;\n align-items: center;\n max-width: 100%;\n}\n.bk-user-selector .search-input[data-v-089550be] {\n min-width: 20px;\n height: 24px;\n outline: none;\n background: transparent;\n border: none;\n}\n.bk-user-selector .search-input[data-v-089550be]::placeholder {\n color: #c4c6cc;\n}\n.bk-user-selector .search-input.input-inline[data-v-089550be] {\n min-width: 20px;\n}\n.bk-user-selector .search-input.input-last[data-v-089550be], .bk-user-selector .search-input.search-input-collapsed[data-v-089550be] {\n flex: 1;\n}\n.hidden-users[data-v-089550be] {\n padding: 6px 10px;\n}.bk-user-selector-popover {\n padding: 0 !important;\n}\n.bk-user-selector.is-textarea .me-tag {\n top: 4px;\n transform: none;\n}/*$vite$:1*/";
10
10
  document.head.appendChild(__vite_style__);
11
11
  Object.defineProperties(exports, {
12
12
  __esModule: { value: true },
13
13
  [Symbol.toStringTag]: { value: "Module" }
14
14
  });
15
+ //#region \0rolldown/runtime.js
15
16
  var __create = Object.create;
16
17
  var __defProp = Object.defineProperty;
17
18
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -33,6 +34,8 @@
33
34
  value: mod,
34
35
  enumerable: true
35
36
  }) : target, mod));
37
+ //#endregion
38
+ //#region src/constants/index.ts
36
39
  var import_Sortable = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
37
40
  /**!
38
41
  * Sortable 1.15.6
@@ -70,11 +73,11 @@
70
73
  }
71
74
  function _typeof(obj) {
72
75
  "@babel/helpers - typeof";
73
- if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") _typeof = function(obj$1) {
74
- return typeof obj$1;
76
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") _typeof = function(obj) {
77
+ return typeof obj;
75
78
  };
76
- else _typeof = function(obj$1) {
77
- return obj$1 && typeof Symbol === "function" && obj$1.constructor === Symbol && obj$1 !== Symbol.prototype ? "symbol" : typeof obj$1;
79
+ else _typeof = function(obj) {
80
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
78
81
  };
79
82
  return _typeof(obj);
80
83
  }
@@ -234,6 +237,15 @@
234
237
  if (scrollingElement) return scrollingElement;
235
238
  else return document.documentElement;
236
239
  }
240
+ /**
241
+ * Returns the "bounding client rect" of given element
242
+ * @param {HTMLElement} el The element whose boundingClientRect is wanted
243
+ * @param {[Boolean]} relativeToContainingBlock Whether the rect should be relative to the containing block of (including) the container
244
+ * @param {[Boolean]} relativeToNonStaticParent Whether the rect should be relative to the relative parent of (including) the contaienr
245
+ * @param {[Boolean]} undoScale Whether the container's scale() should be undone
246
+ * @param {[HTMLElement]} container The parent the element will be placed in
247
+ * @return {Object} The boundingClientRect of el, with specified adjustments
248
+ */
237
249
  function getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) {
238
250
  if (!el.getBoundingClientRect && el !== window) return;
239
251
  var elRect, top, left, bottom, right, height, width;
@@ -286,6 +298,13 @@
286
298
  height
287
299
  };
288
300
  }
301
+ /**
302
+ * Checks if a side of an element is scrolled past a side of its parents
303
+ * @param {HTMLElement} el The element who's side being scrolled out of view is in question
304
+ * @param {String} elSide Side of the element in question ('top', 'left', 'right', 'bottom')
305
+ * @param {String} parentSide Side of the parent in question ('top', 'left', 'right', 'bottom')
306
+ * @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element
307
+ */
289
308
  function isScrolledPast(el, elSide, parentSide) {
290
309
  var parent = getParentAutoScrollElement(el, true), elSideVal = getRect(el)[elSide];
291
310
  while (parent) {
@@ -298,10 +317,18 @@
298
317
  }
299
318
  return false;
300
319
  }
320
+ /**
321
+ * Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible)
322
+ * and non-draggable elements
323
+ * @param {HTMLElement} el The parent element
324
+ * @param {Number} childNum The index of the child
325
+ * @param {Object} options Parent Sortable's options
326
+ * @return {HTMLElement} The child at index childNum, or null if not found
327
+ */
301
328
  function getChild(el, childNum, options, includeDragEl) {
302
329
  var currentChild = 0, i = 0, children = el.children;
303
330
  while (i < children.length) {
304
- if (children[i].style.display !== "none" && children[i] !== Sortable$1.ghost && (includeDragEl || children[i] !== Sortable$1.dragged) && closest(children[i], options.draggable, el, false)) {
331
+ if (children[i].style.display !== "none" && children[i] !== Sortable.ghost && (includeDragEl || children[i] !== Sortable.dragged) && closest(children[i], options.draggable, el, false)) {
305
332
  if (currentChild === childNum) return children[i];
306
333
  currentChild++;
307
334
  }
@@ -309,17 +336,36 @@
309
336
  }
310
337
  return null;
311
338
  }
339
+ /**
340
+ * Gets the last child in the el, ignoring ghostEl or invisible elements (clones)
341
+ * @param {HTMLElement} el Parent element
342
+ * @param {selector} selector Any other elements that should be ignored
343
+ * @return {HTMLElement} The last child, ignoring ghostEl
344
+ */
312
345
  function lastChild(el, selector) {
313
346
  var last = el.lastElementChild;
314
- while (last && (last === Sortable$1.ghost || css(last, "display") === "none" || selector && !matches(last, selector))) last = last.previousElementSibling;
347
+ while (last && (last === Sortable.ghost || css(last, "display") === "none" || selector && !matches(last, selector))) last = last.previousElementSibling;
315
348
  return last || null;
316
349
  }
350
+ /**
351
+ * Returns the index of an element within its parent for a selected set of
352
+ * elements
353
+ * @param {HTMLElement} el
354
+ * @param {selector} selector
355
+ * @return {number}
356
+ */
317
357
  function index(el, selector) {
318
- var index$1 = 0;
358
+ var index = 0;
319
359
  if (!el || !el.parentNode) return -1;
320
- while (el = el.previousElementSibling) if (el.nodeName.toUpperCase() !== "TEMPLATE" && el !== Sortable$1.clone && (!selector || matches(el, selector))) index$1++;
321
- return index$1;
360
+ while (el = el.previousElementSibling) if (el.nodeName.toUpperCase() !== "TEMPLATE" && el !== Sortable.clone && (!selector || matches(el, selector))) index++;
361
+ return index;
322
362
  }
363
+ /**
364
+ * Returns the scroll offset of the given element, added with all the scroll offsets of parent elements.
365
+ * The value is returned in real pixels.
366
+ * @param {HTMLElement} el
367
+ * @return {Array} Offsets in the format of [left, top]
368
+ */
323
369
  function getRelativeScrollOffset(el) {
324
370
  var offsetLeft = 0, offsetTop = 0, winScroller = getWindowScrollingElement();
325
371
  if (el) do {
@@ -329,6 +375,12 @@
329
375
  } while (el !== winScroller && (el = el.parentNode));
330
376
  return [offsetLeft, offsetTop];
331
377
  }
378
+ /**
379
+ * Returns the index of the object within the given array
380
+ * @param {Array} arr Array that may or may not hold the object
381
+ * @param {Object} obj An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find
382
+ * @return {Number} The index of the object in the array, or -1
383
+ */
332
384
  function indexOfObject(arr, obj) {
333
385
  for (var i in arr) {
334
386
  if (!arr.hasOwnProperty(i)) continue;
@@ -403,11 +455,11 @@
403
455
  css(el, "width", "");
404
456
  css(el, "height", "");
405
457
  }
406
- function getChildContainingRectFromElement(container, options, ghostEl$1) {
458
+ function getChildContainingRectFromElement(container, options, ghostEl) {
407
459
  var rect = {};
408
460
  Array.from(container.children).forEach(function(child) {
409
461
  var _rect$left, _rect$top, _rect$right, _rect$bottom;
410
- if (!closest(child, options.draggable, container, false) || child.animated || child === ghostEl$1) return;
462
+ if (!closest(child, options.draggable, container, false) || child.animated || child === ghostEl) return;
411
463
  var childRect = getRect(child);
412
464
  rect.left = Math.min((_rect$left = rect.left) !== null && _rect$left !== void 0 ? _rect$left : Infinity, childRect.left);
413
465
  rect.top = Math.min((_rect$top = rect.top) !== null && _rect$top !== void 0 ? _rect$top : Infinity, childRect.top);
@@ -428,7 +480,7 @@
428
480
  animationStates = [];
429
481
  if (!this.options.animation) return;
430
482
  [].slice.call(this.el.children).forEach(function(child) {
431
- if (css(child, "display") === "none" || child === Sortable$1.ghost) return;
483
+ if (css(child, "display") === "none" || child === Sortable.ghost) return;
432
484
  animationStates.push({
433
485
  target: child,
434
486
  rect: getRect(child)
@@ -535,7 +587,7 @@
535
587
  });
536
588
  plugins.push(plugin);
537
589
  },
538
- pluginEvent: function pluginEvent$1(eventName, sortable, evt) {
590
+ pluginEvent: function pluginEvent(eventName, sortable, evt) {
539
591
  var _this = this;
540
592
  this.eventCanceled = false;
541
593
  evt.cancel = function() {
@@ -548,7 +600,7 @@
548
600
  if (sortable.options[plugin.pluginName] && sortable[plugin.pluginName][eventName]) sortable[plugin.pluginName][eventName](_objectSpread2({ sortable }, evt));
549
601
  });
550
602
  },
551
- initializePlugins: function initializePlugins(sortable, el, defaults$1, options) {
603
+ initializePlugins: function initializePlugins(sortable, el, defaults, options) {
552
604
  plugins.forEach(function(plugin) {
553
605
  var pluginName = plugin.pluginName;
554
606
  if (!sortable.options[pluginName] && !plugin.initializeByDefault) return;
@@ -556,7 +608,7 @@
556
608
  initialized.sortable = sortable;
557
609
  initialized.options = sortable.options;
558
610
  sortable[pluginName] = initialized;
559
- _extends(defaults$1, initialized.defaults);
611
+ _extends(defaults, initialized.defaults);
560
612
  });
561
613
  for (var option in sortable.options) {
562
614
  if (!sortable.options.hasOwnProperty(option)) continue;
@@ -582,8 +634,8 @@
582
634
  }
583
635
  };
584
636
  function dispatchEvent(_ref) {
585
- var sortable = _ref.sortable, rootEl$1 = _ref.rootEl, name = _ref.name, targetEl = _ref.targetEl, cloneEl$1 = _ref.cloneEl, toEl = _ref.toEl, fromEl = _ref.fromEl, oldIndex$1 = _ref.oldIndex, newIndex$1 = _ref.newIndex, oldDraggableIndex$1 = _ref.oldDraggableIndex, newDraggableIndex$1 = _ref.newDraggableIndex, originalEvent = _ref.originalEvent, putSortable$1 = _ref.putSortable, extraEventProperties = _ref.extraEventProperties;
586
- sortable = sortable || rootEl$1 && rootEl$1[expando];
637
+ var sortable = _ref.sortable, rootEl = _ref.rootEl, name = _ref.name, targetEl = _ref.targetEl, cloneEl = _ref.cloneEl, toEl = _ref.toEl, fromEl = _ref.fromEl, oldIndex = _ref.oldIndex, newIndex = _ref.newIndex, oldDraggableIndex = _ref.oldDraggableIndex, newDraggableIndex = _ref.newDraggableIndex, originalEvent = _ref.originalEvent, putSortable = _ref.putSortable, extraEventProperties = _ref.extraEventProperties;
638
+ sortable = sortable || rootEl && rootEl[expando];
587
639
  if (!sortable) return;
588
640
  var evt, options = sortable.options, onName = "on" + name.charAt(0).toUpperCase() + name.substr(1);
589
641
  if (window.CustomEvent && !IE11OrLess && !Edge) evt = new CustomEvent(name, {
@@ -594,25 +646,25 @@
594
646
  evt = document.createEvent("Event");
595
647
  evt.initEvent(name, true, true);
596
648
  }
597
- evt.to = toEl || rootEl$1;
598
- evt.from = fromEl || rootEl$1;
599
- evt.item = targetEl || rootEl$1;
600
- evt.clone = cloneEl$1;
601
- evt.oldIndex = oldIndex$1;
602
- evt.newIndex = newIndex$1;
603
- evt.oldDraggableIndex = oldDraggableIndex$1;
604
- evt.newDraggableIndex = newDraggableIndex$1;
649
+ evt.to = toEl || rootEl;
650
+ evt.from = fromEl || rootEl;
651
+ evt.item = targetEl || rootEl;
652
+ evt.clone = cloneEl;
653
+ evt.oldIndex = oldIndex;
654
+ evt.newIndex = newIndex;
655
+ evt.oldDraggableIndex = oldDraggableIndex;
656
+ evt.newDraggableIndex = newDraggableIndex;
605
657
  evt.originalEvent = originalEvent;
606
- evt.pullMode = putSortable$1 ? putSortable$1.lastPutMode : void 0;
658
+ evt.pullMode = putSortable ? putSortable.lastPutMode : void 0;
607
659
  var allEventProperties = _objectSpread2(_objectSpread2({}, extraEventProperties), PluginManager.getEventProperties(name, sortable));
608
660
  for (var option in allEventProperties) evt[option] = allEventProperties[option];
609
- if (rootEl$1) rootEl$1.dispatchEvent(evt);
661
+ if (rootEl) rootEl.dispatchEvent(evt);
610
662
  if (options[onName]) options[onName].call(sortable, evt);
611
663
  }
612
664
  var _excluded = ["evt"];
613
- var pluginEvent = function pluginEvent$1(eventName, sortable) {
665
+ var pluginEvent = function pluginEvent(eventName, sortable) {
614
666
  var _ref = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}, originalEvent = _ref.evt, data = _objectWithoutProperties(_ref, _excluded);
615
- PluginManager.pluginEvent.bind(Sortable$1)(eventName, sortable, _objectSpread2({
667
+ PluginManager.pluginEvent.bind(Sortable)(eventName, sortable, _objectSpread2({
616
668
  dragEl,
617
669
  parentEl,
618
670
  ghostEl,
@@ -623,7 +675,7 @@
623
675
  cloneHidden,
624
676
  dragStarted: moved,
625
677
  putSortable,
626
- activeSortable: Sortable$1.active,
678
+ activeSortable: Sortable.active,
627
679
  originalEvent,
628
680
  oldIndex,
629
681
  oldDraggableIndex,
@@ -659,13 +711,14 @@
659
711
  }, info));
660
712
  }
661
713
  var dragEl, parentEl, ghostEl, rootEl, nextEl, lastDownEl, cloneEl, cloneHidden, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, activeGroup, putSortable, awaitingDragStarted = false, ignoreNextClick = false, sortables = [], tapEvt, touchEvt, lastDx, lastDy, tapDistanceLeft, tapDistanceTop, moved, lastTarget, lastDirection, pastFirstInvertThresh = false, isCircumstantialInvert = false, targetMoveDistance, ghostRelativeParent, ghostRelativeParentInitialScroll = [], _silent = false, savedInputChecked = [];
714
+ /** @const */
662
715
  var documentExists = typeof document !== "undefined", PositionGhostAbsolutely = IOS, CSSFloatProperty = Edge || IE11OrLess ? "cssFloat" : "float", supportDraggable = documentExists && !ChromeForAndroid && !IOS && "draggable" in document.createElement("div"), supportCssPointerEvents = function() {
663
716
  if (!documentExists) return;
664
717
  if (IE11OrLess) return false;
665
718
  var el = document.createElement("x");
666
719
  el.style.cssText = "pointer-events:auto";
667
720
  return el.style.pointerEvents === "auto";
668
- }(), _detectDirection = function _detectDirection$1(el, options) {
721
+ }(), _detectDirection = function _detectDirection(el, options) {
669
722
  var elCSS = css(el), elWidth = parseInt(elCSS.width) - parseInt(elCSS.paddingLeft) - parseInt(elCSS.paddingRight) - parseInt(elCSS.borderLeftWidth) - parseInt(elCSS.borderRightWidth), child1 = getChild(el, 0, options), child2 = getChild(el, 1, options), firstChildCSS = child1 && css(child1), secondChildCSS = child2 && css(child2), firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + getRect(child1).width, secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + getRect(child2).width;
670
723
  if (elCSS.display === "flex") return elCSS.flexDirection === "column" || elCSS.flexDirection === "column-reverse" ? "vertical" : "horizontal";
671
724
  if (elCSS.display === "grid") return elCSS.gridTemplateColumns.split(" ").length <= 1 ? "vertical" : "horizontal";
@@ -674,10 +727,10 @@
674
727
  return child2 && (secondChildCSS.clear === "both" || secondChildCSS.clear === touchingSideChild2) ? "vertical" : "horizontal";
675
728
  }
676
729
  return child1 && (firstChildCSS.display === "block" || firstChildCSS.display === "flex" || firstChildCSS.display === "table" || firstChildCSS.display === "grid" || firstChildWidth >= elWidth && elCSS[CSSFloatProperty] === "none" || child2 && elCSS[CSSFloatProperty] === "none" && firstChildWidth + secondChildWidth > elWidth) ? "vertical" : "horizontal";
677
- }, _dragElInRowColumn = function _dragElInRowColumn$1(dragRect, targetRect, vertical) {
730
+ }, _dragElInRowColumn = function _dragElInRowColumn(dragRect, targetRect, vertical) {
678
731
  var dragElS1Opp = vertical ? dragRect.left : dragRect.top, dragElS2Opp = vertical ? dragRect.right : dragRect.bottom, dragElOppLength = vertical ? dragRect.width : dragRect.height, targetS1Opp = vertical ? targetRect.left : targetRect.top, targetS2Opp = vertical ? targetRect.right : targetRect.bottom, targetOppLength = vertical ? targetRect.width : targetRect.height;
679
732
  return dragElS1Opp === targetS1Opp || dragElS2Opp === targetS2Opp || dragElS1Opp + dragElOppLength / 2 === targetS1Opp + targetOppLength / 2;
680
- }, _detectNearestEmptySortable = function _detectNearestEmptySortable$1(x, y) {
733
+ }, _detectNearestEmptySortable = function _detectNearestEmptySortable(x, y) {
681
734
  var ret;
682
735
  sortables.some(function(sortable) {
683
736
  var threshold = sortable[expando].options.emptyInsertThreshold;
@@ -686,14 +739,14 @@
686
739
  if (insideHorizontally && insideVertically) return ret = sortable;
687
740
  });
688
741
  return ret;
689
- }, _prepareGroup = function _prepareGroup$1(options) {
742
+ }, _prepareGroup = function _prepareGroup(options) {
690
743
  function toFn(value, pull) {
691
- return function(to, from, dragEl$2, evt) {
744
+ return function(to, from, dragEl, evt) {
692
745
  var sameGroup = to.options.group.name && from.options.group.name && to.options.group.name === from.options.group.name;
693
746
  if (value == null && (pull || sameGroup)) return true;
694
747
  else if (value == null || value === false) return false;
695
748
  else if (pull && value === "clone") return value;
696
- else if (typeof value === "function") return toFn(value(to, from, dragEl$2, evt), pull)(to, from, dragEl$2, evt);
749
+ else if (typeof value === "function") return toFn(value(to, from, dragEl, evt), pull)(to, from, dragEl, evt);
697
750
  else {
698
751
  var otherGroup = (pull ? to : from).options.group.name;
699
752
  return value === true || typeof value === "string" && value === otherGroup || value.join && value.indexOf(otherGroup) > -1;
@@ -708,9 +761,9 @@
708
761
  group.checkPut = toFn(originalGroup.put);
709
762
  group.revertClone = originalGroup.revertClone;
710
763
  options.group = group;
711
- }, _hideGhostForTarget = function _hideGhostForTarget$1() {
764
+ }, _hideGhostForTarget = function _hideGhostForTarget() {
712
765
  if (!supportCssPointerEvents && ghostEl) css(ghostEl, "display", "none");
713
- }, _unhideGhostForTarget = function _unhideGhostForTarget$1() {
766
+ }, _unhideGhostForTarget = function _unhideGhostForTarget() {
714
767
  if (!supportCssPointerEvents && ghostEl) css(ghostEl, "display", "");
715
768
  };
716
769
  if (documentExists && !ChromeForAndroid) document.addEventListener("click", function(evt) {
@@ -722,7 +775,7 @@
722
775
  return false;
723
776
  }
724
777
  }, true);
725
- var nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent$1(evt) {
778
+ var nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent(evt) {
726
779
  if (dragEl) {
727
780
  evt = evt.touches ? evt.touches[0] : evt;
728
781
  var nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY);
@@ -736,15 +789,20 @@
736
789
  }
737
790
  }
738
791
  };
739
- var _checkOutsideTargetEl = function _checkOutsideTargetEl$1(evt) {
792
+ var _checkOutsideTargetEl = function _checkOutsideTargetEl(evt) {
740
793
  if (dragEl) dragEl.parentNode[expando]._isOutsideThisEl(evt.target);
741
794
  };
742
- function Sortable$1(el, options) {
795
+ /**
796
+ * @class Sortable
797
+ * @param {HTMLElement} el
798
+ * @param {Object} [options]
799
+ */
800
+ function Sortable(el, options) {
743
801
  if (!(el && el.nodeType && el.nodeType === 1)) throw "Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(el));
744
802
  this.el = el;
745
803
  this.options = options = _extends({}, options);
746
804
  el[expando] = this;
747
- var defaults$1 = {
805
+ var defaults = {
748
806
  group: null,
749
807
  sort: true,
750
808
  disabled: false,
@@ -766,8 +824,8 @@
766
824
  preventOnFilter: true,
767
825
  animation: 0,
768
826
  easing: null,
769
- setData: function setData(dataTransfer, dragEl$2) {
770
- dataTransfer.setData("Text", dragEl$2.textContent);
827
+ setData: function setData(dataTransfer, dragEl) {
828
+ dataTransfer.setData("Text", dragEl.textContent);
771
829
  },
772
830
  dropBubble: false,
773
831
  dragoverBubble: false,
@@ -783,11 +841,11 @@
783
841
  x: 0,
784
842
  y: 0
785
843
  },
786
- supportPointer: Sortable$1.supportPointer !== false && "PointerEvent" in window && (!Safari || IOS),
844
+ supportPointer: Sortable.supportPointer !== false && "PointerEvent" in window && (!Safari || IOS),
787
845
  emptyInsertThreshold: 5
788
846
  };
789
- PluginManager.initializePlugins(this, el, defaults$1);
790
- for (var name in defaults$1) !(name in options) && (options[name] = defaults$1[name]);
847
+ PluginManager.initializePlugins(this, el, defaults);
848
+ for (var name in defaults) !(name in options) && (options[name] = defaults[name]);
791
849
  _prepareGroup(options);
792
850
  for (var fn in this) if (fn.charAt(0) === "_" && typeof this[fn] === "function") this[fn] = this[fn].bind(this);
793
851
  this.nativeDraggable = options.forceFallback ? false : supportDraggable;
@@ -805,8 +863,8 @@
805
863
  options.store && options.store.get && this.sort(options.store.get(this) || []);
806
864
  _extends(this, AnimationStateManager());
807
865
  }
808
- Sortable$1.prototype = {
809
- constructor: Sortable$1,
866
+ Sortable.prototype = ( /** @lends Sortable.prototype */ {
867
+ constructor: Sortable,
810
868
  _isOutsideThisEl: function _isOutsideThisEl(target) {
811
869
  if (!this.el.contains(target) && target !== this.el) lastTarget = null;
812
870
  },
@@ -874,7 +932,7 @@
874
932
  nextEl = dragEl.nextSibling;
875
933
  lastDownEl = target;
876
934
  activeGroup = options.group;
877
- Sortable$1.dragged = dragEl;
935
+ Sortable.dragged = dragEl;
878
936
  tapEvt = {
879
937
  target: dragEl,
880
938
  clientX: (touch || evt).clientX,
@@ -885,9 +943,9 @@
885
943
  this._lastX = (touch || evt).clientX;
886
944
  this._lastY = (touch || evt).clientY;
887
945
  dragEl.style["will-change"] = "all";
888
- dragStartFn = function dragStartFn$1() {
946
+ dragStartFn = function dragStartFn() {
889
947
  pluginEvent("delayEnded", _this, { evt });
890
- if (Sortable$1.eventCanceled) {
948
+ if (Sortable.eventCanceled) {
891
949
  _this._onDrop();
892
950
  return;
893
951
  }
@@ -921,7 +979,7 @@
921
979
  }
922
980
  pluginEvent("delayStart", this, { evt });
923
981
  if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) {
924
- if (Sortable$1.eventCanceled) {
982
+ if (Sortable.eventCanceled) {
925
983
  this._onDrop();
926
984
  return;
927
985
  }
@@ -984,7 +1042,7 @@
984
1042
  var options = this.options;
985
1043
  !fallback && toggleClass(dragEl, options.dragClass, false);
986
1044
  toggleClass(dragEl, options.ghostClass, true);
987
- Sortable$1.active = this;
1045
+ Sortable.active = this;
988
1046
  fallback && this._appendGhost();
989
1047
  _dispatchEvent({
990
1048
  sortable: this,
@@ -1025,7 +1083,7 @@
1025
1083
  _onTouchMove: function _onTouchMove(evt) {
1026
1084
  if (tapEvt) {
1027
1085
  var options = this.options, fallbackTolerance = options.fallbackTolerance, fallbackOffset = options.fallbackOffset, touch = evt.touches ? evt.touches[0] : evt, ghostMatrix = ghostEl && matrix(ghostEl, true), scaleX = ghostEl && ghostMatrix && ghostMatrix.a, scaleY = ghostEl && ghostMatrix && ghostMatrix.d, relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent), dx = (touch.clientX - tapEvt.clientX + fallbackOffset.x) / (scaleX || 1) + (relativeScrollOffset ? relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0] : 0) / (scaleX || 1), dy = (touch.clientY - tapEvt.clientY + fallbackOffset.y) / (scaleY || 1) + (relativeScrollOffset ? relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1] : 0) / (scaleY || 1);
1028
- if (!Sortable$1.active && !awaitingDragStarted) {
1086
+ if (!Sortable.active && !awaitingDragStarted) {
1029
1087
  if (fallbackTolerance && Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance) return;
1030
1088
  this._onDragStart(evt, true);
1031
1089
  }
@@ -1082,7 +1140,7 @@
1082
1140
  css(ghostEl, "position", PositionGhostAbsolutely ? "absolute" : "fixed");
1083
1141
  css(ghostEl, "zIndex", "100000");
1084
1142
  css(ghostEl, "pointerEvents", "none");
1085
- Sortable$1.ghost = ghostEl;
1143
+ Sortable.ghost = ghostEl;
1086
1144
  container.appendChild(ghostEl);
1087
1145
  css(ghostEl, "transform-origin", tapDistanceLeft / parseInt(ghostEl.style.width) * 100 + "% " + tapDistanceTop / parseInt(ghostEl.style.height) * 100 + "%");
1088
1146
  }
@@ -1092,23 +1150,23 @@
1092
1150
  var dataTransfer = evt.dataTransfer;
1093
1151
  var options = _this.options;
1094
1152
  pluginEvent("dragStart", this, { evt });
1095
- if (Sortable$1.eventCanceled) {
1153
+ if (Sortable.eventCanceled) {
1096
1154
  this._onDrop();
1097
1155
  return;
1098
1156
  }
1099
1157
  pluginEvent("setupClone", this);
1100
- if (!Sortable$1.eventCanceled) {
1158
+ if (!Sortable.eventCanceled) {
1101
1159
  cloneEl = clone(dragEl);
1102
1160
  cloneEl.removeAttribute("id");
1103
1161
  cloneEl.draggable = false;
1104
1162
  cloneEl.style["will-change"] = "";
1105
1163
  this._hideClone();
1106
1164
  toggleClass(cloneEl, this.options.chosenClass, false);
1107
- Sortable$1.clone = cloneEl;
1165
+ Sortable.clone = cloneEl;
1108
1166
  }
1109
1167
  _this.cloneId = _nextTick(function() {
1110
1168
  pluginEvent("clone", _this);
1111
- if (Sortable$1.eventCanceled) return;
1169
+ if (Sortable.eventCanceled) return;
1112
1170
  if (!_this.options.removeCloneOnHide) rootEl.insertBefore(cloneEl, dragEl);
1113
1171
  _this._hideClone();
1114
1172
  _dispatchEvent({
@@ -1139,7 +1197,7 @@
1139
1197
  if (Safari) css(document.body, "user-select", "none");
1140
1198
  },
1141
1199
  _onDragOver: function _onDragOver(evt) {
1142
- var el = this.el, target = evt.target, dragRect, targetRect, revert, options = this.options, group = options.group, activeSortable = Sortable$1.active, isOwner = activeGroup === group, canSort = options.sort, fromSortable = putSortable || activeSortable, vertical, _this = this, completedFired = false;
1200
+ var el = this.el, target = evt.target, dragRect, targetRect, revert, options = this.options, group = options.group, activeSortable = Sortable.active, isOwner = activeGroup === group, canSort = options.sort, fromSortable = putSortable || activeSortable, vertical, _this = this, completedFired = false;
1143
1201
  if (_silent) return;
1144
1202
  function dragOverEvent(name, extra) {
1145
1203
  pluginEvent(name, _this, _objectSpread2({
@@ -1153,8 +1211,8 @@
1153
1211
  fromSortable,
1154
1212
  target,
1155
1213
  completed,
1156
- onMove: function onMove(target$1, after$1) {
1157
- return _onMove(rootEl, el, dragEl, dragRect, target$1, getRect(target$1), evt, after$1);
1214
+ onMove: function onMove(target, after) {
1215
+ return _onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after);
1158
1216
  },
1159
1217
  changed
1160
1218
  }, extra));
@@ -1173,8 +1231,8 @@
1173
1231
  toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false);
1174
1232
  toggleClass(dragEl, options.ghostClass, true);
1175
1233
  }
1176
- if (putSortable !== _this && _this !== Sortable$1.active) putSortable = _this;
1177
- else if (_this === Sortable$1.active && putSortable) putSortable = null;
1234
+ if (putSortable !== _this && _this !== Sortable.active) putSortable = _this;
1235
+ else if (_this === Sortable.active && putSortable) putSortable = null;
1178
1236
  if (fromSortable === _this) _this._ignoreWhileAnimating = target;
1179
1237
  _this.animateAll(function() {
1180
1238
  dragOverEvent("dragOverAnimationComplete");
@@ -1208,20 +1266,20 @@
1208
1266
  if (evt.preventDefault !== void 0) evt.cancelable && evt.preventDefault();
1209
1267
  target = closest(target, options.draggable, el, true);
1210
1268
  dragOverEvent("dragOver");
1211
- if (Sortable$1.eventCanceled) return completedFired;
1269
+ if (Sortable.eventCanceled) return completedFired;
1212
1270
  if (dragEl.contains(evt.target) || target.animated && target.animatingX && target.animatingY || _this._ignoreWhileAnimating === target) return completed(false);
1213
1271
  ignoreNextClick = false;
1214
1272
  if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = parentEl !== rootEl) : putSortable === this || (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && group.checkPut(this, activeSortable, dragEl, evt))) {
1215
1273
  vertical = this._getDirection(evt, target) === "vertical";
1216
1274
  dragRect = getRect(dragEl);
1217
1275
  dragOverEvent("dragOverValid");
1218
- if (Sortable$1.eventCanceled) return completedFired;
1276
+ if (Sortable.eventCanceled) return completedFired;
1219
1277
  if (revert) {
1220
1278
  parentEl = rootEl;
1221
1279
  capture();
1222
1280
  this._hideClone();
1223
1281
  dragOverEvent("revert");
1224
- if (!Sortable$1.eventCanceled) if (nextEl) rootEl.insertBefore(dragEl, nextEl);
1282
+ if (!Sortable.eventCanceled) if (nextEl) rootEl.insertBefore(dragEl, nextEl);
1225
1283
  else rootEl.appendChild(dragEl);
1226
1284
  return completed(true);
1227
1285
  }
@@ -1317,7 +1375,7 @@
1317
1375
  parentEl = dragEl && dragEl.parentNode;
1318
1376
  newIndex = index(dragEl);
1319
1377
  newDraggableIndex = index(dragEl, options.draggable);
1320
- if (Sortable$1.eventCanceled) {
1378
+ if (Sortable.eventCanceled) {
1321
1379
  this._nulling();
1322
1380
  return;
1323
1381
  }
@@ -1403,7 +1461,7 @@
1403
1461
  });
1404
1462
  }
1405
1463
  }
1406
- if (Sortable$1.active) {
1464
+ if (Sortable.active) {
1407
1465
  if (newIndex == null || newIndex === -1) {
1408
1466
  newIndex = oldIndex;
1409
1467
  newDraggableIndex = oldDraggableIndex;
@@ -1422,7 +1480,7 @@
1422
1480
  },
1423
1481
  _nulling: function _nulling() {
1424
1482
  pluginEvent("nulling", this);
1425
- rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable$1.dragged = Sortable$1.ghost = Sortable$1.clone = Sortable$1.active = null;
1483
+ rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable.dragged = Sortable.ghost = Sortable.clone = Sortable.active = null;
1426
1484
  savedInputChecked.forEach(function(el) {
1427
1485
  el.checked = true;
1428
1486
  });
@@ -1455,16 +1513,16 @@
1455
1513
  return order;
1456
1514
  },
1457
1515
  sort: function sort(order, useAnimation) {
1458
- var items = {}, rootEl$1 = this.el;
1516
+ var items = {}, rootEl = this.el;
1459
1517
  this.toArray().forEach(function(id, i) {
1460
- var el = rootEl$1.children[i];
1461
- if (closest(el, this.options.draggable, rootEl$1, false)) items[id] = el;
1518
+ var el = rootEl.children[i];
1519
+ if (closest(el, this.options.draggable, rootEl, false)) items[id] = el;
1462
1520
  }, this);
1463
1521
  useAnimation && this.captureAnimationState();
1464
1522
  order.forEach(function(id) {
1465
1523
  if (items[id]) {
1466
- rootEl$1.removeChild(items[id]);
1467
- rootEl$1.appendChild(items[id]);
1524
+ rootEl.removeChild(items[id]);
1525
+ rootEl.appendChild(items[id]);
1468
1526
  }
1469
1527
  });
1470
1528
  useAnimation && this.animateAll();
@@ -1497,8 +1555,8 @@
1497
1555
  off(el, "dragover", this);
1498
1556
  off(el, "dragenter", this);
1499
1557
  }
1500
- Array.prototype.forEach.call(el.querySelectorAll("[draggable]"), function(el$1) {
1501
- el$1.removeAttribute("draggable");
1558
+ Array.prototype.forEach.call(el.querySelectorAll("[draggable]"), function(el) {
1559
+ el.removeAttribute("draggable");
1502
1560
  });
1503
1561
  this._onDrop();
1504
1562
  this._disableDelayedDragEvents();
@@ -1508,20 +1566,20 @@
1508
1566
  _hideClone: function _hideClone() {
1509
1567
  if (!cloneHidden) {
1510
1568
  pluginEvent("hideClone", this);
1511
- if (Sortable$1.eventCanceled) return;
1569
+ if (Sortable.eventCanceled) return;
1512
1570
  css(cloneEl, "display", "none");
1513
1571
  if (this.options.removeCloneOnHide && cloneEl.parentNode) cloneEl.parentNode.removeChild(cloneEl);
1514
1572
  cloneHidden = true;
1515
1573
  }
1516
1574
  },
1517
- _showClone: function _showClone(putSortable$1) {
1518
- if (putSortable$1.lastPutMode !== "clone") {
1575
+ _showClone: function _showClone(putSortable) {
1576
+ if (putSortable.lastPutMode !== "clone") {
1519
1577
  this._hideClone();
1520
1578
  return;
1521
1579
  }
1522
1580
  if (cloneHidden) {
1523
1581
  pluginEvent("showClone", this);
1524
- if (Sortable$1.eventCanceled) return;
1582
+ if (Sortable.eventCanceled) return;
1525
1583
  if (dragEl.parentNode == rootEl && !this.options.group.revertClone) rootEl.insertBefore(cloneEl, dragEl);
1526
1584
  else if (nextEl) rootEl.insertBefore(cloneEl, nextEl);
1527
1585
  else rootEl.appendChild(cloneEl);
@@ -1530,12 +1588,12 @@
1530
1588
  cloneHidden = false;
1531
1589
  }
1532
1590
  }
1533
- };
1591
+ });
1534
1592
  function _globalDragOver(evt) {
1535
1593
  if (evt.dataTransfer) evt.dataTransfer.dropEffect = "move";
1536
1594
  evt.cancelable && evt.preventDefault();
1537
1595
  }
1538
- function _onMove(fromEl, toEl, dragEl$2, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) {
1596
+ function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) {
1539
1597
  var evt, sortable = fromEl[expando], onMoveFn = sortable.options.onMove, retVal;
1540
1598
  if (window.CustomEvent && !IE11OrLess && !Edge) evt = new CustomEvent("move", {
1541
1599
  bubbles: true,
@@ -1547,7 +1605,7 @@
1547
1605
  }
1548
1606
  evt.to = toEl;
1549
1607
  evt.from = fromEl;
1550
- evt.dragged = dragEl$2;
1608
+ evt.dragged = dragEl;
1551
1609
  evt.draggedRect = dragRect;
1552
1610
  evt.related = targetEl || toEl;
1553
1611
  evt.relatedRect = targetRect || getRect(toEl);
@@ -1591,10 +1649,22 @@
1591
1649
  }
1592
1650
  return 0;
1593
1651
  }
1652
+ /**
1653
+ * Gets the direction dragEl must be swapped relative to target in order to make it
1654
+ * seem that dragEl has been "inserted" into that element's position
1655
+ * @param {HTMLElement} target The target whose position dragEl is being inserted at
1656
+ * @return {Number} Direction dragEl must be swapped
1657
+ */
1594
1658
  function _getInsertDirection(target) {
1595
1659
  if (index(dragEl) < index(target)) return 1;
1596
1660
  else return -1;
1597
1661
  }
1662
+ /**
1663
+ * Generate id
1664
+ * @param {HTMLElement} el
1665
+ * @returns {String}
1666
+ * @private
1667
+ */
1598
1668
  function _generateId(el) {
1599
1669
  var str = el.tagName + el.className + el.src + el.href + el.textContent, i = str.length, sum = 0;
1600
1670
  while (i--) sum += str.charCodeAt(i);
@@ -1616,9 +1686,9 @@
1616
1686
  return clearTimeout(id);
1617
1687
  }
1618
1688
  if (documentExists) on(document, "touchmove", function(evt) {
1619
- if ((Sortable$1.active || awaitingDragStarted) && evt.cancelable) evt.preventDefault();
1689
+ if ((Sortable.active || awaitingDragStarted) && evt.cancelable) evt.preventDefault();
1620
1690
  });
1621
- Sortable$1.utils = {
1691
+ Sortable.utils = {
1622
1692
  on,
1623
1693
  off,
1624
1694
  css,
@@ -1638,22 +1708,36 @@
1638
1708
  getChild,
1639
1709
  expando
1640
1710
  };
1641
- Sortable$1.get = function(element) {
1711
+ /**
1712
+ * Get the Sortable instance of an element
1713
+ * @param {HTMLElement} element The element
1714
+ * @return {Sortable|undefined} The instance of Sortable
1715
+ */
1716
+ Sortable.get = function(element) {
1642
1717
  return element[expando];
1643
1718
  };
1644
- Sortable$1.mount = function() {
1645
- for (var _len = arguments.length, plugins$1 = new Array(_len), _key = 0; _key < _len; _key++) plugins$1[_key] = arguments[_key];
1646
- if (plugins$1[0].constructor === Array) plugins$1 = plugins$1[0];
1647
- plugins$1.forEach(function(plugin) {
1719
+ /**
1720
+ * Mount a plugin to Sortable
1721
+ * @param {...SortablePlugin|SortablePlugin[]} plugins Plugins being mounted
1722
+ */
1723
+ Sortable.mount = function() {
1724
+ for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) plugins[_key] = arguments[_key];
1725
+ if (plugins[0].constructor === Array) plugins = plugins[0];
1726
+ plugins.forEach(function(plugin) {
1648
1727
  if (!plugin.prototype || !plugin.prototype.constructor) throw "Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(plugin));
1649
- if (plugin.utils) Sortable$1.utils = _objectSpread2(_objectSpread2({}, Sortable$1.utils), plugin.utils);
1728
+ if (plugin.utils) Sortable.utils = _objectSpread2(_objectSpread2({}, Sortable.utils), plugin.utils);
1650
1729
  PluginManager.mount(plugin);
1651
1730
  });
1652
1731
  };
1653
- Sortable$1.create = function(el, options) {
1654
- return new Sortable$1(el, options);
1732
+ /**
1733
+ * Create sortable instance
1734
+ * @param {HTMLElement} el
1735
+ * @param {Object} [options]
1736
+ */
1737
+ Sortable.create = function(el, options) {
1738
+ return new Sortable(el, options);
1655
1739
  };
1656
- Sortable$1.version = version;
1740
+ Sortable.version = version;
1657
1741
  var autoScrolls = [], scrollEl, scrollRootEl, scrolling = false, lastAutoScrollX, lastAutoScrollY, touchEvt$1, pointerElemChangedInterval;
1658
1742
  function AutoScrollPlugin() {
1659
1743
  function AutoScroll() {
@@ -1667,7 +1751,7 @@
1667
1751
  for (var fn in this) if (fn.charAt(0) === "_" && typeof this[fn] === "function") this[fn] = this[fn].bind(this);
1668
1752
  }
1669
1753
  AutoScroll.prototype = {
1670
- dragStarted: function dragStarted$1(_ref) {
1754
+ dragStarted: function dragStarted(_ref) {
1671
1755
  var originalEvent = _ref.originalEvent;
1672
1756
  if (this.sortable.nativeDraggable) on(document, "dragover", this._handleAutoScroll);
1673
1757
  else if (this.options.supportPointer) on(document, "pointermove", this._handleFallbackAutoScroll);
@@ -1678,7 +1762,7 @@
1678
1762
  var originalEvent = _ref2.originalEvent;
1679
1763
  if (!this.options.dragOverBubble && !originalEvent.rootEl) this._handleAutoScroll(originalEvent);
1680
1764
  },
1681
- drop: function drop$1() {
1765
+ drop: function drop() {
1682
1766
  if (this.sortable.nativeDraggable) off(document, "dragover", this._handleAutoScroll);
1683
1767
  else {
1684
1768
  off(document, "pointermove", this._handleFallbackAutoScroll);
@@ -1731,24 +1815,24 @@
1731
1815
  });
1732
1816
  }
1733
1817
  function clearAutoScrolls() {
1734
- autoScrolls.forEach(function(autoScroll$1) {
1735
- clearInterval(autoScroll$1.pid);
1818
+ autoScrolls.forEach(function(autoScroll) {
1819
+ clearInterval(autoScroll.pid);
1736
1820
  });
1737
1821
  autoScrolls = [];
1738
1822
  }
1739
1823
  function clearPointerElemChangedInterval() {
1740
1824
  clearInterval(pointerElemChangedInterval);
1741
1825
  }
1742
- var autoScroll = throttle(function(evt, options, rootEl$1, isFallback) {
1826
+ var autoScroll = throttle(function(evt, options, rootEl, isFallback) {
1743
1827
  if (!options.scroll) return;
1744
1828
  var x = (evt.touches ? evt.touches[0] : evt).clientX, y = (evt.touches ? evt.touches[0] : evt).clientY, sens = options.scrollSensitivity, speed = options.scrollSpeed, winScroller = getWindowScrollingElement();
1745
1829
  var scrollThisInstance = false, scrollCustomFn;
1746
- if (scrollRootEl !== rootEl$1) {
1747
- scrollRootEl = rootEl$1;
1830
+ if (scrollRootEl !== rootEl) {
1831
+ scrollRootEl = rootEl;
1748
1832
  clearAutoScrolls();
1749
1833
  scrollEl = options.scroll;
1750
1834
  scrollCustomFn = options.scrollFn;
1751
- if (scrollEl === true) scrollEl = getParentAutoScrollElement(rootEl$1, true);
1835
+ if (scrollEl === true) scrollEl = getParentAutoScrollElement(rootEl, true);
1752
1836
  }
1753
1837
  var layersOut = 0;
1754
1838
  var currentParent = scrollEl;
@@ -1774,11 +1858,11 @@
1774
1858
  if (vx != 0 || vy != 0) {
1775
1859
  scrollThisInstance = true;
1776
1860
  autoScrolls[layersOut].pid = setInterval(function() {
1777
- if (isFallback && this.layer === 0) Sortable$1.active._onTouchMove(touchEvt$1);
1861
+ if (isFallback && this.layer === 0) Sortable.active._onTouchMove(touchEvt$1);
1778
1862
  var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0;
1779
1863
  var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0;
1780
1864
  if (typeof scrollCustomFn === "function") {
1781
- if (scrollCustomFn.call(Sortable$1.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== "continue") return;
1865
+ if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== "continue") return;
1782
1866
  }
1783
1867
  scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY);
1784
1868
  }.bind({ layer: layersOut }), 24);
@@ -1788,10 +1872,10 @@
1788
1872
  } while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false)));
1789
1873
  scrolling = scrollThisInstance;
1790
1874
  }, 30);
1791
- var drop = function drop$1(_ref) {
1792
- var originalEvent = _ref.originalEvent, putSortable$1 = _ref.putSortable, dragEl$2 = _ref.dragEl, activeSortable = _ref.activeSortable, dispatchSortableEvent = _ref.dispatchSortableEvent, hideGhostForTarget = _ref.hideGhostForTarget, unhideGhostForTarget = _ref.unhideGhostForTarget;
1875
+ var drop = function drop(_ref) {
1876
+ var originalEvent = _ref.originalEvent, putSortable = _ref.putSortable, dragEl = _ref.dragEl, activeSortable = _ref.activeSortable, dispatchSortableEvent = _ref.dispatchSortableEvent, hideGhostForTarget = _ref.hideGhostForTarget, unhideGhostForTarget = _ref.unhideGhostForTarget;
1793
1877
  if (!originalEvent) return;
1794
- var toSortable = putSortable$1 || activeSortable;
1878
+ var toSortable = putSortable || activeSortable;
1795
1879
  hideGhostForTarget();
1796
1880
  var touch = originalEvent.changedTouches && originalEvent.changedTouches.length ? originalEvent.changedTouches[0] : originalEvent;
1797
1881
  var target = document.elementFromPoint(touch.clientX, touch.clientY);
@@ -1799,8 +1883,8 @@
1799
1883
  if (toSortable && !toSortable.el.contains(target)) {
1800
1884
  dispatchSortableEvent("spill");
1801
1885
  this.onSpill({
1802
- dragEl: dragEl$2,
1803
- putSortable: putSortable$1
1886
+ dragEl,
1887
+ putSortable
1804
1888
  });
1805
1889
  }
1806
1890
  };
@@ -1811,14 +1895,14 @@
1811
1895
  this.startIndex = _ref2.oldDraggableIndex;
1812
1896
  },
1813
1897
  onSpill: function onSpill(_ref3) {
1814
- var dragEl$2 = _ref3.dragEl, putSortable$1 = _ref3.putSortable;
1898
+ var dragEl = _ref3.dragEl, putSortable = _ref3.putSortable;
1815
1899
  this.sortable.captureAnimationState();
1816
- if (putSortable$1) putSortable$1.captureAnimationState();
1900
+ if (putSortable) putSortable.captureAnimationState();
1817
1901
  var nextSibling = getChild(this.sortable.el, this.startIndex, this.options);
1818
- if (nextSibling) this.sortable.el.insertBefore(dragEl$2, nextSibling);
1819
- else this.sortable.el.appendChild(dragEl$2);
1902
+ if (nextSibling) this.sortable.el.insertBefore(dragEl, nextSibling);
1903
+ else this.sortable.el.appendChild(dragEl);
1820
1904
  this.sortable.animateAll();
1821
- if (putSortable$1) putSortable$1.animateAll();
1905
+ if (putSortable) putSortable.animateAll();
1822
1906
  },
1823
1907
  drop
1824
1908
  };
@@ -1826,10 +1910,10 @@
1826
1910
  function Remove() {}
1827
1911
  Remove.prototype = {
1828
1912
  onSpill: function onSpill(_ref4) {
1829
- var dragEl$2 = _ref4.dragEl;
1913
+ var dragEl = _ref4.dragEl;
1830
1914
  var parentSortable = _ref4.putSortable || this.sortable;
1831
1915
  parentSortable.captureAnimationState();
1832
- dragEl$2.parentNode && dragEl$2.parentNode.removeChild(dragEl$2);
1916
+ dragEl.parentNode && dragEl.parentNode.removeChild(dragEl);
1833
1917
  parentSortable.animateAll();
1834
1918
  },
1835
1919
  drop
@@ -1860,16 +1944,16 @@
1860
1944
  completed(true);
1861
1945
  cancel();
1862
1946
  },
1863
- drop: function drop$1(_ref3) {
1864
- var activeSortable = _ref3.activeSortable, putSortable$1 = _ref3.putSortable, dragEl$2 = _ref3.dragEl;
1865
- var toSortable = putSortable$1 || this.sortable;
1947
+ drop: function drop(_ref3) {
1948
+ var activeSortable = _ref3.activeSortable, putSortable = _ref3.putSortable, dragEl = _ref3.dragEl;
1949
+ var toSortable = putSortable || this.sortable;
1866
1950
  var options = this.options;
1867
1951
  lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false);
1868
- if (lastSwapEl && (options.swap || putSortable$1 && putSortable$1.options.swap)) {
1869
- if (dragEl$2 !== lastSwapEl) {
1952
+ if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) {
1953
+ if (dragEl !== lastSwapEl) {
1870
1954
  toSortable.captureAnimationState();
1871
1955
  if (toSortable !== activeSortable) activeSortable.captureAnimationState();
1872
- swapNodes(dragEl$2, lastSwapEl);
1956
+ swapNodes(dragEl, lastSwapEl);
1873
1957
  toSortable.animateAll();
1874
1958
  if (toSortable !== activeSortable) activeSortable.animateAll();
1875
1959
  }
@@ -1910,12 +1994,12 @@
1910
1994
  selectedClass: "sortable-selected",
1911
1995
  multiDragKey: null,
1912
1996
  avoidImplicitDeselect: false,
1913
- setData: function setData(dataTransfer, dragEl$2) {
1997
+ setData: function setData(dataTransfer, dragEl) {
1914
1998
  var data = "";
1915
1999
  if (multiDragElements.length && multiDragSortable === sortable) multiDragElements.forEach(function(multiDragElement, i) {
1916
2000
  data += (!i ? "" : ", ") + multiDragElement.textContent;
1917
2001
  });
1918
- else data = dragEl$2.textContent;
2002
+ else data = dragEl.textContent;
1919
2003
  dataTransfer.setData("Text", data);
1920
2004
  }
1921
2005
  };
@@ -1943,23 +2027,23 @@
1943
2027
  sortable._hideClone();
1944
2028
  cancel();
1945
2029
  },
1946
- clone: function clone$1(_ref3) {
1947
- var sortable = _ref3.sortable, rootEl$1 = _ref3.rootEl, dispatchSortableEvent = _ref3.dispatchSortableEvent, cancel = _ref3.cancel;
2030
+ clone: function clone(_ref3) {
2031
+ var sortable = _ref3.sortable, rootEl = _ref3.rootEl, dispatchSortableEvent = _ref3.dispatchSortableEvent, cancel = _ref3.cancel;
1948
2032
  if (!this.isMultiDrag) return;
1949
2033
  if (!this.options.removeCloneOnHide) {
1950
2034
  if (multiDragElements.length && multiDragSortable === sortable) {
1951
- insertMultiDragClones(true, rootEl$1);
2035
+ insertMultiDragClones(true, rootEl);
1952
2036
  dispatchSortableEvent("clone");
1953
2037
  cancel();
1954
2038
  }
1955
2039
  }
1956
2040
  },
1957
2041
  showClone: function showClone(_ref4) {
1958
- var cloneNowShown = _ref4.cloneNowShown, rootEl$1 = _ref4.rootEl, cancel = _ref4.cancel;
2042
+ var cloneNowShown = _ref4.cloneNowShown, rootEl = _ref4.rootEl, cancel = _ref4.cancel;
1959
2043
  if (!this.isMultiDrag) return;
1960
- insertMultiDragClones(false, rootEl$1);
1961
- multiDragClones.forEach(function(clone$1) {
1962
- css(clone$1, "display", "");
2044
+ insertMultiDragClones(false, rootEl);
2045
+ multiDragClones.forEach(function(clone) {
2046
+ css(clone, "display", "");
1963
2047
  });
1964
2048
  cloneNowShown();
1965
2049
  clonesHidden = false;
@@ -1970,9 +2054,9 @@
1970
2054
  _ref5.sortable;
1971
2055
  var cloneNowHidden = _ref5.cloneNowHidden, cancel = _ref5.cancel;
1972
2056
  if (!this.isMultiDrag) return;
1973
- multiDragClones.forEach(function(clone$1) {
1974
- css(clone$1, "display", "none");
1975
- if (_this.options.removeCloneOnHide && clone$1.parentNode) clone$1.parentNode.removeChild(clone$1);
2057
+ multiDragClones.forEach(function(clone) {
2058
+ css(clone, "display", "none");
2059
+ if (_this.options.removeCloneOnHide && clone.parentNode) clone.parentNode.removeChild(clone);
1976
2060
  });
1977
2061
  cloneNowHidden();
1978
2062
  clonesHidden = true;
@@ -1989,7 +2073,7 @@
1989
2073
  });
1990
2074
  dragStarted = true;
1991
2075
  },
1992
- dragStarted: function dragStarted$1(_ref7) {
2076
+ dragStarted: function dragStarted(_ref7) {
1993
2077
  var _this2 = this;
1994
2078
  var sortable = _ref7.sortable;
1995
2079
  if (!this.isMultiDrag) return;
@@ -2026,7 +2110,7 @@
2026
2110
  }
2027
2111
  },
2028
2112
  revert: function revert(_ref9) {
2029
- var fromSortable = _ref9.fromSortable, rootEl$1 = _ref9.rootEl, sortable = _ref9.sortable, dragRect = _ref9.dragRect;
2113
+ var fromSortable = _ref9.fromSortable, rootEl = _ref9.rootEl, sortable = _ref9.sortable, dragRect = _ref9.dragRect;
2030
2114
  if (multiDragElements.length > 1) {
2031
2115
  multiDragElements.forEach(function(multiDragElement) {
2032
2116
  sortable.addAnimationState({
@@ -2038,21 +2122,21 @@
2038
2122
  fromSortable.removeAnimationState(multiDragElement);
2039
2123
  });
2040
2124
  folding = false;
2041
- insertMultiDragElements(!this.options.removeCloneOnHide, rootEl$1);
2125
+ insertMultiDragElements(!this.options.removeCloneOnHide, rootEl);
2042
2126
  }
2043
2127
  },
2044
2128
  dragOverCompleted: function dragOverCompleted(_ref10) {
2045
- var sortable = _ref10.sortable, isOwner = _ref10.isOwner, insertion = _ref10.insertion, activeSortable = _ref10.activeSortable, parentEl$1 = _ref10.parentEl, putSortable$1 = _ref10.putSortable;
2129
+ var sortable = _ref10.sortable, isOwner = _ref10.isOwner, insertion = _ref10.insertion, activeSortable = _ref10.activeSortable, parentEl = _ref10.parentEl, putSortable = _ref10.putSortable;
2046
2130
  var options = this.options;
2047
2131
  if (insertion) {
2048
2132
  if (isOwner) activeSortable._hideClone();
2049
2133
  initialFolding = false;
2050
- if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable$1)) {
2134
+ if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable)) {
2051
2135
  var dragRectAbsolute = getRect(dragEl$1, false, true, true);
2052
2136
  multiDragElements.forEach(function(multiDragElement) {
2053
2137
  if (multiDragElement === dragEl$1) return;
2054
2138
  setRect(multiDragElement, dragRectAbsolute);
2055
- parentEl$1.appendChild(multiDragElement);
2139
+ parentEl.appendChild(multiDragElement);
2056
2140
  });
2057
2141
  folding = true;
2058
2142
  }
@@ -2061,13 +2145,13 @@
2061
2145
  if (multiDragElements.length > 1) {
2062
2146
  var clonesHiddenBefore = clonesHidden;
2063
2147
  activeSortable._showClone(sortable);
2064
- if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) multiDragClones.forEach(function(clone$1) {
2148
+ if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) multiDragClones.forEach(function(clone) {
2065
2149
  activeSortable.addAnimationState({
2066
- target: clone$1,
2150
+ target: clone,
2067
2151
  rect: clonesFromRect
2068
2152
  });
2069
- clone$1.fromRect = clonesFromRect;
2070
- clone$1.thisAnimationDuration = null;
2153
+ clone.fromRect = clonesFromRect;
2154
+ clone.thisAnimationDuration = null;
2071
2155
  });
2072
2156
  } else activeSortable._showClone(sortable);
2073
2157
  }
@@ -2091,11 +2175,11 @@
2091
2175
  removeMultiDragElements();
2092
2176
  }
2093
2177
  },
2094
- drop: function drop$1(_ref12) {
2095
- var evt = _ref12.originalEvent, rootEl$1 = _ref12.rootEl, parentEl$1 = _ref12.parentEl, sortable = _ref12.sortable, dispatchSortableEvent = _ref12.dispatchSortableEvent, oldIndex$1 = _ref12.oldIndex, putSortable$1 = _ref12.putSortable;
2096
- var toSortable = putSortable$1 || this.sortable;
2178
+ drop: function drop(_ref12) {
2179
+ var evt = _ref12.originalEvent, rootEl = _ref12.rootEl, parentEl = _ref12.parentEl, sortable = _ref12.sortable, dispatchSortableEvent = _ref12.dispatchSortableEvent, oldIndex = _ref12.oldIndex, putSortable = _ref12.putSortable;
2180
+ var toSortable = putSortable || this.sortable;
2097
2181
  if (!evt) return;
2098
- var options = this.options, children = parentEl$1.children;
2182
+ var options = this.options, children = parentEl.children;
2099
2183
  if (!dragStarted) {
2100
2184
  if (options.multiDragKey && !this.multiDragKeyDown) this._deselectMultiDrag();
2101
2185
  toggleClass(dragEl$1, options.selectedClass, !~multiDragElements.indexOf(dragEl$1));
@@ -2103,7 +2187,7 @@
2103
2187
  multiDragElements.push(dragEl$1);
2104
2188
  dispatchEvent({
2105
2189
  sortable,
2106
- rootEl: rootEl$1,
2190
+ rootEl,
2107
2191
  name: "select",
2108
2192
  targetEl: dragEl$1,
2109
2193
  originalEvent: evt
@@ -2122,15 +2206,15 @@
2122
2206
  var filter = options.filter;
2123
2207
  for (; i < n; i++) {
2124
2208
  if (~multiDragElements.indexOf(children[i])) continue;
2125
- if (!closest(children[i], options.draggable, parentEl$1, false)) continue;
2209
+ if (!closest(children[i], options.draggable, parentEl, false)) continue;
2126
2210
  if (filter && (typeof filter === "function" ? filter.call(sortable, evt, children[i], sortable) : filter.split(",").some(function(criteria) {
2127
- return closest(children[i], criteria.trim(), parentEl$1, false);
2211
+ return closest(children[i], criteria.trim(), parentEl, false);
2128
2212
  }))) continue;
2129
2213
  toggleClass(children[i], options.selectedClass, true);
2130
2214
  multiDragElements.push(children[i]);
2131
2215
  dispatchEvent({
2132
2216
  sortable,
2133
- rootEl: rootEl$1,
2217
+ rootEl,
2134
2218
  name: "select",
2135
2219
  targetEl: children[i],
2136
2220
  originalEvent: evt
@@ -2144,7 +2228,7 @@
2144
2228
  lastMultiDragSelect = null;
2145
2229
  dispatchEvent({
2146
2230
  sortable,
2147
- rootEl: rootEl$1,
2231
+ rootEl,
2148
2232
  name: "deselect",
2149
2233
  targetEl: dragEl$1,
2150
2234
  originalEvent: evt
@@ -2153,7 +2237,7 @@
2153
2237
  }
2154
2238
  if (dragStarted && this.isMultiDrag) {
2155
2239
  folding = false;
2156
- if ((parentEl$1[expando].options.sort || parentEl$1 !== rootEl$1) && multiDragElements.length > 1) {
2240
+ if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) {
2157
2241
  var dragRect = getRect(dragEl$1), multiDragIndex = index(dragEl$1, ":not(." + this.options.selectedClass + ")");
2158
2242
  if (!initialFolding && options.animation) dragEl$1.thisAnimationDuration = null;
2159
2243
  toSortable.captureAnimationState();
@@ -2174,11 +2258,11 @@
2174
2258
  }
2175
2259
  removeMultiDragElements();
2176
2260
  multiDragElements.forEach(function(multiDragElement) {
2177
- if (children[multiDragIndex]) parentEl$1.insertBefore(multiDragElement, children[multiDragIndex]);
2178
- else parentEl$1.appendChild(multiDragElement);
2261
+ if (children[multiDragIndex]) parentEl.insertBefore(multiDragElement, children[multiDragIndex]);
2262
+ else parentEl.appendChild(multiDragElement);
2179
2263
  multiDragIndex++;
2180
2264
  });
2181
- if (oldIndex$1 === index(dragEl$1)) {
2265
+ if (oldIndex === index(dragEl$1)) {
2182
2266
  var update = false;
2183
2267
  multiDragElements.forEach(function(multiDragElement) {
2184
2268
  if (multiDragElement.sortableIndex !== index(multiDragElement)) {
@@ -2199,8 +2283,8 @@
2199
2283
  }
2200
2284
  multiDragSortable = toSortable;
2201
2285
  }
2202
- if (rootEl$1 === parentEl$1 || putSortable$1 && putSortable$1.lastPutMode !== "clone") multiDragClones.forEach(function(clone$1) {
2203
- clone$1.parentNode && clone$1.parentNode.removeChild(clone$1);
2286
+ if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== "clone") multiDragClones.forEach(function(clone) {
2287
+ clone.parentNode && clone.parentNode.removeChild(clone);
2204
2288
  });
2205
2289
  },
2206
2290
  nullingGlobal: function nullingGlobal() {
@@ -2254,10 +2338,10 @@
2254
2338
  multiDragElements.push(el);
2255
2339
  },
2256
2340
  deselect: function deselect(el) {
2257
- var sortable = el.parentNode[expando], index$1 = multiDragElements.indexOf(el);
2258
- if (!sortable || !sortable.options.multiDrag || !~index$1) return;
2341
+ var sortable = el.parentNode[expando], index = multiDragElements.indexOf(el);
2342
+ if (!sortable || !sortable.options.multiDrag || !~index) return;
2259
2343
  toggleClass(el, sortable.options.selectedClass, false);
2260
- multiDragElements.splice(index$1, 1);
2344
+ multiDragElements.splice(index, 1);
2261
2345
  }
2262
2346
  },
2263
2347
  eventProperties: function eventProperties() {
@@ -2268,13 +2352,13 @@
2268
2352
  multiDragElement,
2269
2353
  index: multiDragElement.sortableIndex
2270
2354
  });
2271
- var newIndex$1;
2272
- if (folding && multiDragElement !== dragEl$1) newIndex$1 = -1;
2273
- else if (folding) newIndex$1 = index(multiDragElement, ":not(." + _this3.options.selectedClass + ")");
2274
- else newIndex$1 = index(multiDragElement);
2355
+ var newIndex;
2356
+ if (folding && multiDragElement !== dragEl$1) newIndex = -1;
2357
+ else if (folding) newIndex = index(multiDragElement, ":not(." + _this3.options.selectedClass + ")");
2358
+ else newIndex = index(multiDragElement);
2275
2359
  newIndicies.push({
2276
2360
  multiDragElement,
2277
- index: newIndex$1
2361
+ index: newIndex
2278
2362
  });
2279
2363
  });
2280
2364
  return {
@@ -2292,18 +2376,23 @@
2292
2376
  } }
2293
2377
  });
2294
2378
  }
2295
- function insertMultiDragElements(clonesInserted, rootEl$1) {
2379
+ function insertMultiDragElements(clonesInserted, rootEl) {
2296
2380
  multiDragElements.forEach(function(multiDragElement, i) {
2297
- var target = rootEl$1.children[multiDragElement.sortableIndex + (clonesInserted ? Number(i) : 0)];
2298
- if (target) rootEl$1.insertBefore(multiDragElement, target);
2299
- else rootEl$1.appendChild(multiDragElement);
2381
+ var target = rootEl.children[multiDragElement.sortableIndex + (clonesInserted ? Number(i) : 0)];
2382
+ if (target) rootEl.insertBefore(multiDragElement, target);
2383
+ else rootEl.appendChild(multiDragElement);
2300
2384
  });
2301
2385
  }
2302
- function insertMultiDragClones(elementsInserted, rootEl$1) {
2303
- multiDragClones.forEach(function(clone$1, i) {
2304
- var target = rootEl$1.children[clone$1.sortableIndex + (elementsInserted ? Number(i) : 0)];
2305
- if (target) rootEl$1.insertBefore(clone$1, target);
2306
- else rootEl$1.appendChild(clone$1);
2386
+ /**
2387
+ * Insert multi-drag clones
2388
+ * @param {[Boolean]} elementsInserted Whether the multi-drag elements are inserted
2389
+ * @param {HTMLElement} rootEl
2390
+ */
2391
+ function insertMultiDragClones(elementsInserted, rootEl) {
2392
+ multiDragClones.forEach(function(clone, i) {
2393
+ var target = rootEl.children[clone.sortableIndex + (elementsInserted ? Number(i) : 0)];
2394
+ if (target) rootEl.insertBefore(clone, target);
2395
+ else rootEl.appendChild(clone);
2307
2396
  });
2308
2397
  }
2309
2398
  function removeMultiDragElements() {
@@ -2312,24 +2401,128 @@
2312
2401
  multiDragElement.parentNode && multiDragElement.parentNode.removeChild(multiDragElement);
2313
2402
  });
2314
2403
  }
2315
- Sortable$1.mount(new AutoScrollPlugin());
2316
- Sortable$1.mount(Remove, Revert);
2317
- Sortable$1.mount(new SwapPlugin());
2318
- Sortable$1.mount(new MultiDragPlugin());
2319
- return Sortable$1;
2404
+ Sortable.mount(new AutoScrollPlugin());
2405
+ Sortable.mount(Remove, Revert);
2406
+ Sortable.mount(new SwapPlugin());
2407
+ Sortable.mount(new MultiDragPlugin());
2408
+ return Sortable;
2320
2409
  }));
2321
2410
  })))());
2322
- const DEFAULT_EXACT_SEARCH_KEY = "bk_username";
2323
- const USER_TYPE = {
2411
+ /** 默认精确搜索字段 */
2412
+ var DEFAULT_EXACT_SEARCH_KEY = "bk_username";
2413
+ /** 用户类型 */
2414
+ var USER_TYPE = {
2324
2415
  USER: "user",
2325
2416
  VIRTUAL: "virtual",
2326
2417
  CUSTOM: "custom",
2327
2418
  USER_GROUP: "userGroup"
2328
2419
  };
2420
+ //#endregion
2421
+ //#region src/hooks/use-api-config.ts
2422
+ var API_CONFIG_KEY = Symbol("bkUserSelectorApiConfig");
2423
+ var TENANT_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
2424
+ var globalApiConfig = {
2425
+ apiBaseUrl: "",
2426
+ tenantId: "",
2427
+ allowedApiOrigins: [],
2428
+ allowPrivateApiHost: false,
2429
+ allowCrossOriginCredentials: false
2430
+ };
2431
+ var getCurrentOrigin = () => {
2432
+ if (typeof window === "undefined" || !window.location?.origin) return "http://localhost";
2433
+ return window.location.origin;
2434
+ };
2435
+ var isPrivateIpv4 = (hostname) => {
2436
+ const segments = hostname.split(".").map(Number);
2437
+ if (segments.length !== 4 || segments.some(Number.isNaN)) return false;
2438
+ const [a, b] = segments;
2439
+ if (a === 10 || a === 127) return true;
2440
+ if (a === 172 && b >= 16 && b <= 31) return true;
2441
+ if (a === 192 && b === 168) return true;
2442
+ if (a === 169 && b === 254) return true;
2443
+ if (a === 100 && b >= 64 && b <= 127) return true;
2444
+ return false;
2445
+ };
2446
+ var isPrivateHost = (hostname) => {
2447
+ const normalizedHost = hostname.toLowerCase();
2448
+ if (normalizedHost === "localhost" || normalizedHost === "[::1]" || normalizedHost === "::1") return true;
2449
+ if (isPrivateIpv4(normalizedHost)) return true;
2450
+ if (normalizedHost.startsWith("fc") || normalizedHost.startsWith("fd")) return true;
2451
+ return false;
2452
+ };
2453
+ var normalizeAllowedOrigins = (allowedApiOrigins = []) => {
2454
+ const currentOrigin = getCurrentOrigin();
2455
+ return Array.from(new Set(allowedApiOrigins.map((origin) => {
2456
+ try {
2457
+ const parsed = new URL(origin, currentOrigin);
2458
+ if (!["http:", "https:"].includes(parsed.protocol)) return "";
2459
+ return parsed.origin;
2460
+ } catch {
2461
+ return "";
2462
+ }
2463
+ }).filter(Boolean)));
2464
+ };
2465
+ var sanitizeApiBaseUrl = (apiBaseUrl, allowedApiOrigins = [], allowPrivateApiHost = false) => {
2466
+ if (!apiBaseUrl) return "";
2467
+ try {
2468
+ const parsed = new URL(apiBaseUrl, getCurrentOrigin());
2469
+ if (!["http:", "https:"].includes(parsed.protocol)) {
2470
+ console.warn("[bk-user-selector] apiBaseUrl 仅支持 http/https 协议");
2471
+ return "";
2472
+ }
2473
+ if (!allowPrivateApiHost && isPrivateHost(parsed.hostname)) {
2474
+ console.warn("[bk-user-selector] apiBaseUrl 指向私网或 localhost,已被安全策略拦截");
2475
+ return "";
2476
+ }
2477
+ const normalizedAllowedOrigins = normalizeAllowedOrigins(allowedApiOrigins);
2478
+ if (normalizedAllowedOrigins.length > 0 && !normalizedAllowedOrigins.includes(parsed.origin)) {
2479
+ console.warn("[bk-user-selector] apiBaseUrl 未命中 allowedApiOrigins 白名单,已被安全策略拦截");
2480
+ return "";
2481
+ }
2482
+ const normalizedPath = parsed.pathname.replace(/\/+$/, "");
2483
+ return `${parsed.origin}${normalizedPath}`;
2484
+ } catch {
2485
+ console.warn("[bk-user-selector] apiBaseUrl 格式非法,已被安全策略拦截");
2486
+ return "";
2487
+ }
2488
+ };
2489
+ var sanitizeTenantId = (tenantId) => {
2490
+ const normalizedTenantId = String(tenantId || "").trim();
2491
+ if (!normalizedTenantId) return "";
2492
+ if (!TENANT_ID_PATTERN.test(normalizedTenantId)) {
2493
+ console.warn("[bk-user-selector] tenantId 格式非法,已被安全策略拦截");
2494
+ return "";
2495
+ }
2496
+ return normalizedTenantId;
2497
+ };
2498
+ var getApiConfig = () => {
2499
+ return globalApiConfig;
2500
+ };
2501
+ var provideApiConfig = (apiBaseUrl, tenantId, allowedApiOrigins = [], allowPrivateApiHost = false, allowCrossOriginCredentials = false, callbacks = {}) => {
2502
+ const normalizedAllowedOrigins = normalizeAllowedOrigins(allowedApiOrigins);
2503
+ globalApiConfig = {
2504
+ apiBaseUrl: sanitizeApiBaseUrl(apiBaseUrl, normalizedAllowedOrigins, allowPrivateApiHost),
2505
+ tenantId: sanitizeTenantId(tenantId),
2506
+ allowedApiOrigins: normalizedAllowedOrigins,
2507
+ allowPrivateApiHost,
2508
+ allowCrossOriginCredentials,
2509
+ onError: callbacks.onError,
2510
+ onUnauthorized: callbacks.onUnauthorized
2511
+ };
2512
+ (0, vue.provide)(API_CONFIG_KEY, globalApiConfig);
2513
+ };
2514
+ //#endregion
2515
+ //#region src/hooks/use-jsonp.ts
2516
+ /**
2517
+ * 生成回调函数名
2518
+ */
2329
2519
  var generateCallbackName = () => {
2330
2520
  return `__jsonp_callback_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
2331
2521
  };
2332
- const jsonpRequest = (requestUrl, options = {}) => {
2522
+ /**
2523
+ * JSONP 请求函数
2524
+ */
2525
+ var jsonpRequest = (requestUrl, options = {}) => {
2333
2526
  return new Promise((resolve, reject) => {
2334
2527
  const url = (0, vue.unref)(requestUrl);
2335
2528
  const { timeout = 1e3 * 60 * 2, params } = options;
@@ -2358,6 +2551,8 @@
2358
2551
  document.head.appendChild(script);
2359
2552
  });
2360
2553
  };
2554
+ //#endregion
2555
+ //#region src/utils/logger.ts
2361
2556
  var PREFIX = "[BkUserSelector]";
2362
2557
  var LOG_LEVELS = {
2363
2558
  debug: 0,
@@ -2369,10 +2564,16 @@
2369
2564
  enabled: true,
2370
2565
  level: "warn"
2371
2566
  };
2567
+ /**
2568
+ * 检查是否应该输出日志
2569
+ */
2372
2570
  var shouldLog = (level) => {
2373
2571
  return config.enabled && LOG_LEVELS[level] >= LOG_LEVELS[config.level];
2374
2572
  };
2375
- const logger = {
2573
+ /**
2574
+ * 日志工具
2575
+ */
2576
+ var logger = {
2376
2577
  debug: (message, ...args) => {
2377
2578
  if (shouldLog("debug")) console.debug(`${PREFIX} ${message}`, ...args);
2378
2579
  },
@@ -2386,32 +2587,132 @@
2386
2587
  if (shouldLog("error")) console.error(`${PREFIX} ${message}`, error);
2387
2588
  }
2388
2589
  };
2389
- const handleApiError = (operation, error) => {
2390
- logger.error(`${operation}失败:`, error);
2590
+ /**
2591
+ * 安全调用用户回调
2592
+ * 用户回调如果抛错不应影响组件正常流程
2593
+ */
2594
+ var safeInvoke = (handler, error) => {
2595
+ if (!handler) return;
2596
+ try {
2597
+ handler(error);
2598
+ } catch (err) {
2599
+ console.error(`${PREFIX} error handler threw:`, err);
2600
+ }
2391
2601
  };
2392
- const warnMissingParams = (operation, params) => {
2602
+ /**
2603
+ * 构造 ApiError 对象
2604
+ */
2605
+ var buildApiError = (scene, cause, status, isUnauthorized = false) => ({
2606
+ scene,
2607
+ cause,
2608
+ status,
2609
+ isUnauthorized
2610
+ });
2611
+ /**
2612
+ * API 错误处理
2613
+ * - 打印错误日志(兜底)
2614
+ * - 触发 apiConfig.onError 回调
2615
+ * - 如果是 401,额外触发 apiConfig.onUnauthorized 回调
2616
+ */
2617
+ var handleApiError = (operation, error, apiConfig, status, isUnauthorized = false) => {
2618
+ if (isUnauthorized) logger.warn(`${operation}: 登录态已失效,请重新登录`);
2619
+ else logger.error(`${operation}失败:`, error);
2620
+ const apiError = buildApiError(operation, error, status, isUnauthorized);
2621
+ if (isUnauthorized) safeInvoke(apiConfig?.onUnauthorized, apiError);
2622
+ safeInvoke(apiConfig?.onError, apiError);
2623
+ };
2624
+ /**
2625
+ * 参数校验警告
2626
+ */
2627
+ var warnMissingParams = (operation, params) => {
2393
2628
  logger.warn(`${operation}需要提供有效的参数: ${params.join(", ")}`);
2394
2629
  };
2395
- const getTenants = async (apiBaseUrl, tenantId) => {
2396
- if (!apiBaseUrl || !tenantId) {
2630
+ //#endregion
2631
+ //#region src/api/user.ts
2632
+ /**
2633
+ * 用户选择器相关API
2634
+ * @module api/user
2635
+ */
2636
+ var UNAUTHORIZED_STATUS = 401;
2637
+ var resolveRequestCredentials = (url, allowCrossOriginCredentials) => {
2638
+ if (typeof window === "undefined" || !window.location?.origin) return "same-origin";
2639
+ try {
2640
+ if (new URL(url, window.location.origin).origin === window.location.origin) return "include";
2641
+ return allowCrossOriginCredentials ? "include" : "omit";
2642
+ } catch {
2643
+ return "same-origin";
2644
+ }
2645
+ };
2646
+ var resolveApiSecurityConfig = (apiBaseUrl, tenantId) => {
2647
+ const globalConfig = getApiConfig();
2648
+ const resolvedAllowPrivateApiHost = globalConfig.allowPrivateApiHost;
2649
+ const resolvedAllowedApiOrigins = globalConfig.allowedApiOrigins;
2650
+ return {
2651
+ allowCrossOriginCredentials: globalConfig.allowCrossOriginCredentials,
2652
+ apiBaseUrl: sanitizeApiBaseUrl(globalConfig.apiBaseUrl || apiBaseUrl, resolvedAllowedApiOrigins, resolvedAllowPrivateApiHost),
2653
+ tenantId: sanitizeTenantId(globalConfig.tenantId || tenantId),
2654
+ apiConfig: globalConfig
2655
+ };
2656
+ };
2657
+ /**
2658
+ * 统一处理响应状态码,401 时构造 ApiError 并触发回调,然后抛出错误
2659
+ */
2660
+ var ensureResponseOk = (response, scene, apiConfig) => {
2661
+ if (response.ok) return;
2662
+ if (response.status === UNAUTHORIZED_STATUS) {
2663
+ const error = /* @__PURE__ */ new Error(`${scene}失败: 登录态已失效`);
2664
+ handleApiError(scene, error, apiConfig, response.status, true);
2665
+ throw error;
2666
+ }
2667
+ throw new Error(`${response.status} ${response.statusText}`);
2668
+ };
2669
+ /**
2670
+ * 从抛出的错误中尽力提取 HTTP 状态码
2671
+ */
2672
+ var extractStatus = (error) => {
2673
+ if (typeof error === "object" && error !== null && "status" in error) {
2674
+ const status = error.status;
2675
+ return typeof status === "number" ? status : void 0;
2676
+ }
2677
+ if (error instanceof Error) {
2678
+ const match = /^(\d{3})\s/.exec(error.message);
2679
+ if (match) return Number(match[1]);
2680
+ }
2681
+ };
2682
+ /**
2683
+ * 获取本租户所有数据来源的租户信息
2684
+ * @param apiBaseUrl - API基础URL
2685
+ * @param tenantId - 租户ID
2686
+ * @returns 租户列表Promise
2687
+ */
2688
+ var getTenants = async (apiBaseUrl, tenantId) => {
2689
+ const resolvedConfig = resolveApiSecurityConfig(apiBaseUrl, tenantId);
2690
+ if (!resolvedConfig.apiBaseUrl || !resolvedConfig.tenantId) {
2397
2691
  warnMissingParams("获取租户信息", ["apiBaseUrl", "tenantId"]);
2398
2692
  return [];
2399
2693
  }
2400
2694
  try {
2401
- const url = `${apiBaseUrl}/api/v3/open-web/tenant/data-source-owner-tenants/`;
2695
+ const url = `${resolvedConfig.apiBaseUrl}/api/v3/open-web/tenant/data-source-owner-tenants/`;
2696
+ const requestCredentials = resolveRequestCredentials(url, resolvedConfig.allowCrossOriginCredentials);
2402
2697
  const response = await fetch(url, {
2403
2698
  method: "GET",
2404
- headers: { "x-bk-tenant-id": tenantId },
2405
- credentials: "include"
2699
+ headers: { "x-bk-tenant-id": resolvedConfig.tenantId },
2700
+ credentials: requestCredentials
2406
2701
  });
2407
- if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
2702
+ ensureResponseOk(response, "获取租户信息", resolvedConfig.apiConfig);
2408
2703
  return (await response.json()).data || [];
2409
2704
  } catch (error) {
2410
- handleApiError("获取租户信息", error);
2705
+ const status = extractStatus(error);
2706
+ if (status !== UNAUTHORIZED_STATUS) handleApiError("获取租户信息", error, resolvedConfig.apiConfig, status, false);
2411
2707
  return [];
2412
2708
  }
2413
2709
  };
2414
- const searchUsers = async (params) => {
2710
+ /**
2711
+ * 模糊搜索用户
2712
+ * @param params - 搜索参数
2713
+ * @returns 用户列表Promise
2714
+ */
2715
+ var searchUsers = async (params) => {
2415
2716
  const { apiBaseUrl, tenantId, keyword, enableMultiTenantMode = true } = params;
2416
2717
  if (!enableMultiTenantMode) try {
2417
2718
  return await getUserList(apiBaseUrl, {
@@ -2422,7 +2723,8 @@
2422
2723
  } catch {
2423
2724
  return [];
2424
2725
  }
2425
- if (!keyword || !apiBaseUrl || !tenantId) {
2726
+ const resolvedConfig = resolveApiSecurityConfig(apiBaseUrl, tenantId);
2727
+ if (!keyword || !resolvedConfig.apiBaseUrl || !resolvedConfig.tenantId) {
2426
2728
  warnMissingParams("搜索用户", [
2427
2729
  "apiBaseUrl",
2428
2730
  "tenantId",
@@ -2431,20 +2733,27 @@
2431
2733
  return [];
2432
2734
  }
2433
2735
  try {
2434
- const url = `${apiBaseUrl}/api/v3/open-web/tenant/users/-/search/?keyword=${encodeURIComponent(keyword)}`;
2736
+ const url = `${resolvedConfig.apiBaseUrl}/api/v3/open-web/tenant/users/-/search/?keyword=${encodeURIComponent(keyword)}`;
2737
+ const requestCredentials = resolveRequestCredentials(url, resolvedConfig.allowCrossOriginCredentials);
2435
2738
  const response = await fetch(url, {
2436
2739
  method: "GET",
2437
- headers: { "x-bk-tenant-id": tenantId },
2438
- credentials: "include"
2740
+ headers: { "x-bk-tenant-id": resolvedConfig.tenantId },
2741
+ credentials: requestCredentials
2439
2742
  });
2440
- if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
2743
+ ensureResponseOk(response, "搜索用户", resolvedConfig.apiConfig);
2441
2744
  return (await response.json()).data || [];
2442
2745
  } catch (error) {
2443
- handleApiError("搜索用户", error);
2746
+ const status = extractStatus(error);
2747
+ if (status !== UNAUTHORIZED_STATUS) handleApiError("搜索用户", error, resolvedConfig.apiConfig, status, false);
2444
2748
  return [];
2445
2749
  }
2446
2750
  };
2447
- const lookupUsers = async (params) => {
2751
+ /**
2752
+ * 批量精准查找用户
2753
+ * @param params - 查找参数
2754
+ * @returns 查找到的用户列表Promise
2755
+ */
2756
+ var lookupUsers = async (params) => {
2448
2757
  const { apiBaseUrl, tenantId, exactSearchKey = "bk_username", usersList = [], enableMultiTenantMode = true } = params;
2449
2758
  const users = usersList.filter(Boolean).map((user) => typeof user === "string" ? user.trim() : String(user).trim());
2450
2759
  if (!enableMultiTenantMode) try {
@@ -2453,7 +2762,8 @@
2453
2762
  } catch {
2454
2763
  return [];
2455
2764
  }
2456
- if (users.length === 0 || !apiBaseUrl || !tenantId) {
2765
+ const resolvedConfig = resolveApiSecurityConfig(apiBaseUrl, tenantId);
2766
+ if (users.length === 0 || !resolvedConfig.apiBaseUrl || !resolvedConfig.tenantId) {
2457
2767
  warnMissingParams("批量查找用户", [
2458
2768
  "apiBaseUrl",
2459
2769
  "tenantId",
@@ -2462,20 +2772,27 @@
2462
2772
  return [];
2463
2773
  }
2464
2774
  try {
2465
- const url = `${apiBaseUrl}/api/v3/open-web/tenant/users/-/lookup/?lookups=${users.join(",")}&lookup_fields=${exactSearchKey}`;
2775
+ const url = `${resolvedConfig.apiBaseUrl}/api/v3/open-web/tenant/users/-/lookup/?lookups=${users.join(",")}&lookup_fields=${exactSearchKey}`;
2776
+ const requestCredentials = resolveRequestCredentials(url, resolvedConfig.allowCrossOriginCredentials);
2466
2777
  const response = await fetch(url, {
2467
2778
  method: "GET",
2468
- headers: { "x-bk-tenant-id": tenantId },
2469
- credentials: "include"
2779
+ headers: { "x-bk-tenant-id": resolvedConfig.tenantId },
2780
+ credentials: requestCredentials
2470
2781
  });
2471
- if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
2782
+ ensureResponseOk(response, "批量查找用户", resolvedConfig.apiConfig);
2472
2783
  return (await response.json()).data || [];
2473
2784
  } catch (error) {
2474
- handleApiError("批量查找用户", error);
2785
+ const status = extractStatus(error);
2786
+ if (status !== UNAUTHORIZED_STATUS) handleApiError("批量查找用户", error, resolvedConfig.apiConfig, status, false);
2475
2787
  return [];
2476
2788
  }
2477
2789
  };
2478
- const formatUsers = (users, enableMultiTenantMode = true) => {
2790
+ /**
2791
+ * 将API返回的用户数据格式化为组件所需格式
2792
+ * @param users - API返回的用户列表
2793
+ * @returns 格式化后的用户列表
2794
+ */
2795
+ var formatUsers = (users, enableMultiTenantMode = true) => {
2479
2796
  if (!users || !Array.isArray(users)) return [];
2480
2797
  if (!enableMultiTenantMode) return users.map((user) => ({
2481
2798
  ...user,
@@ -2492,7 +2809,13 @@
2492
2809
  ...user
2493
2810
  }));
2494
2811
  };
2495
- const getUserList = async (url, params) => {
2812
+ /**
2813
+ * 获取用户列表(兼容旧版本的人员选择器)
2814
+ * @param url - 请求的 URL
2815
+ * @param params - 请求参数
2816
+ * @returns 用户列表
2817
+ */
2818
+ var getUserList = async (url, params) => {
2496
2819
  const { userIds, keyword, pageSize = 20, page = 1, appCode = "bk-magicbox" } = params;
2497
2820
  return (await jsonpRequest(url, { params: {
2498
2821
  exact_lookups: userIds?.join(",") || void 0,
@@ -2502,9 +2825,23 @@
2502
2825
  app_code: appCode
2503
2826
  } }))?.results || [];
2504
2827
  };
2505
- const useCurrentUser = (options) => {
2828
+ //#endregion
2829
+ //#region src/hooks/use-current-user.ts
2830
+ /**
2831
+ * 当前用户处理 Hook
2832
+ * @module hooks/useCurrentUser
2833
+ */
2834
+ /**
2835
+ * 当前用户处理 Hook
2836
+ * @param options - 配置选项
2837
+ * @returns 当前用户相关方法
2838
+ */
2839
+ var useCurrentUser = (options) => {
2506
2840
  const { apiBaseUrl, tenantId, currentUserId, exactSearchKey = DEFAULT_EXACT_SEARCH_KEY, enableMultiTenantMode = true } = options;
2507
2841
  const loading = (0, vue.ref)(false);
2842
+ /**
2843
+ * 获取当前用户信息
2844
+ */
2508
2845
  const fetchCurrentUser = async () => {
2509
2846
  if (!currentUserId) return null;
2510
2847
  loading.value = true;
@@ -2529,6 +2866,9 @@
2529
2866
  fetchCurrentUser
2530
2867
  };
2531
2868
  };
2869
+ //#endregion
2870
+ //#region ../../node_modules/.pnpm/js-cookie@3.0.5/node_modules/js-cookie/dist/js.cookie.mjs
2871
+ /*! js-cookie v3.0.5 | MIT */
2532
2872
  function assign(target) {
2533
2873
  for (var i = 1; i < arguments.length; i++) {
2534
2874
  var source = arguments[i];
@@ -2585,8 +2925,8 @@
2585
2925
  withAttributes: function(attributes) {
2586
2926
  return init(this.converter, assign({}, this.attributes, attributes));
2587
2927
  },
2588
- withConverter: function(converter$1) {
2589
- return init(assign({}, this.converter, converter$1), this.attributes);
2928
+ withConverter: function(converter) {
2929
+ return init(assign({}, this.converter, converter), this.attributes);
2590
2930
  }
2591
2931
  }, {
2592
2932
  attributes: { value: Object.freeze(defaultAttributes) },
@@ -2594,22 +2934,30 @@
2594
2934
  });
2595
2935
  }
2596
2936
  var api = init(defaultConverter, { path: "/" });
2937
+ //#endregion
2938
+ //#region src/locale/en-us.ts
2597
2939
  var en_us_default = {
2598
2940
  我: "Me",
2599
2941
  请输入人员名称搜索: "Please enter the name of the user to search",
2942
+ 最近选择: "Recent selections",
2600
2943
  用户群组: "User Group",
2601
2944
  无匹配人员: "No matching users",
2602
2945
  虚拟账号: "Virtual Account",
2603
2946
  用户: "User"
2604
2947
  };
2948
+ //#endregion
2949
+ //#region src/locale/zh-cn.ts
2605
2950
  var zh_cn_default = {
2606
2951
  我: "我",
2607
2952
  请输入人员名称搜索: "请输入人员名称搜索",
2953
+ 最近选择: "最近选择",
2608
2954
  用户群组: "用户群组",
2609
2955
  无匹配人员: "无匹配人员",
2610
2956
  虚拟账号: "虚拟账号",
2611
2957
  用户: "用户"
2612
2958
  };
2959
+ //#endregion
2960
+ //#region src/hooks/use-i18n.ts
2613
2961
  var BLUEKINNG_LANGUAGE = "blueking_language";
2614
2962
  var languageMap = {
2615
2963
  "en-US": en_us_default,
@@ -2648,9 +2996,28 @@
2648
2996
  t
2649
2997
  };
2650
2998
  };
2651
- const useInputHandler = (options) => {
2999
+ //#endregion
3000
+ //#region src/hooks/use-input-handler.ts
3001
+ /**
3002
+ * 输入处理公共逻辑 Hook
3003
+ * @module hooks/useInputHandler
3004
+ */
3005
+ /**
3006
+ * 输入处理公共逻辑 Hook
3007
+ * @param options - 配置选项
3008
+ * @returns 输入处理相关方法
3009
+ */
3010
+ var useInputHandler = (options) => {
2652
3011
  const { apiBaseUrl, tenantId, searchQuery, selectedUsers, allowCreate = false, freePaste = false, enableMultiTenantMode = true, maxCount = 0, onAddUser, onBatchAddUsers } = options;
2653
3012
  const isPasting = (0, vue.ref)(false);
3013
+ /** 单次粘贴最多处理数量(后端限制) */
3014
+ const MAX_PASTE_USERS = 100;
3015
+ /** 批量查询每批数量(不超过后端限制) */
3016
+ const LOOKUP_BATCH_SIZE = 100;
3017
+ /**
3018
+ * 创建自定义用户对象
3019
+ * @param loginName - 用户登录名
3020
+ */
2654
3021
  const createCustomUser = (loginName) => ({
2655
3022
  id: loginName,
2656
3023
  name: loginName,
@@ -2658,19 +3025,47 @@
2658
3025
  tenantId: "",
2659
3026
  login_name: loginName
2660
3027
  });
3028
+ /**
3029
+ * 解析粘贴文本为用户列表
3030
+ * @param text - 粘贴的文本
3031
+ */
2661
3032
  const parsePastedText = (text) => {
2662
- return text.split(/[,,;\n\s]+/).filter(Boolean).map((user) => user.trim().replace(/\s*\(.*?\)\s*/, "")).filter(Boolean);
3033
+ const normalizedUsers = text.split(/[,,;\n\s]+/).filter(Boolean).map((user) => user.trim().replace(/\s*\(.*?\)\s*/, "")).filter(Boolean);
3034
+ return Array.from(new Set(normalizedUsers)).slice(0, MAX_PASTE_USERS);
2663
3035
  };
3036
+ /**
3037
+ * 将用户列表按指定大小分批
3038
+ * @param usersList - 用户列表
3039
+ * @param batchSize - 每批大小
3040
+ */
3041
+ const chunkUsersList = (usersList, batchSize) => {
3042
+ const chunks = [];
3043
+ for (let i = 0; i < usersList.length; i += batchSize) chunks.push(usersList.slice(i, i + batchSize));
3044
+ return chunks;
3045
+ };
3046
+ /**
3047
+ * 合并用户列表并去重
3048
+ * @param existingUsers - 现有用户列表
3049
+ * @param newUsers - 新用户列表
3050
+ */
2664
3051
  const mergeUsers = (existingUsers, newUsers) => {
2665
3052
  const userMap = /* @__PURE__ */ new Map();
2666
3053
  for (const user of [...existingUsers, ...newUsers]) if (!userMap.has(user.id)) userMap.set(user.id, user);
2667
3054
  return Array.from(userMap.values());
2668
3055
  };
3056
+ /**
3057
+ * 处理 Enter 键创建自定义用户
3058
+ * @param event - 键盘事件
3059
+ */
2669
3060
  const handleEnterCreate = (event) => {
2670
3061
  if (event.key !== "Enter" || !allowCreate || !searchQuery.value.trim()) return;
2671
3062
  const customUser = createCustomUser(searchQuery.value.trim());
2672
3063
  if (!selectedUsers.value.some((user) => user.id === customUser.id)) onAddUser(customUser);
2673
3064
  };
3065
+ /**
3066
+ * 处理粘贴事件
3067
+ * @param event - 粘贴事件
3068
+ */
2674
3069
  const handlePaste = async (event) => {
2675
3070
  event.preventDefault();
2676
3071
  const pastedText = event.clipboardData?.getData("text")?.trim();
@@ -2679,13 +3074,19 @@
2679
3074
  try {
2680
3075
  const usersList = parsePastedText(pastedText);
2681
3076
  if (usersList.length === 0) return;
2682
- const formattedUsers = formatUsers(await lookupUsers({
2683
- apiBaseUrl,
2684
- tenantId,
2685
- exactSearchKey: "login_name",
2686
- usersList,
2687
- enableMultiTenantMode
2688
- }), enableMultiTenantMode);
3077
+ const lookupBatches = chunkUsersList(usersList, LOOKUP_BATCH_SIZE);
3078
+ const lookupResults = [];
3079
+ for (const batch of lookupBatches) {
3080
+ const result = await lookupUsers({
3081
+ apiBaseUrl,
3082
+ tenantId,
3083
+ exactSearchKey: "login_name",
3084
+ usersList: batch,
3085
+ enableMultiTenantMode
3086
+ });
3087
+ lookupResults.push(...result);
3088
+ }
3089
+ const formattedUsers = formatUsers(lookupResults, enableMultiTenantMode);
2689
3090
  if (onBatchAddUsers) {
2690
3091
  let mergedUsers = mergeUsers(selectedUsers.value, formattedUsers);
2691
3092
  if (freePaste) {
@@ -2708,7 +3109,20 @@
2708
3109
  handlePaste
2709
3110
  };
2710
3111
  };
2711
- const useResizeObserver = (target, callback, options = {}) => {
3112
+ //#endregion
3113
+ //#region src/hooks/use-resize-observer.ts
3114
+ /**
3115
+ * ResizeObserver Hook
3116
+ * @module hooks/useResizeObserver
3117
+ */
3118
+ /**
3119
+ * 监听元素大小变化的 Hook
3120
+ * @param target - 目标元素引用
3121
+ * @param callback - 大小变化时的回调函数
3122
+ * @param options - 配置选项
3123
+ * @returns 停止观察的函数
3124
+ */
3125
+ var useResizeObserver = (target, callback, options = {}) => {
2712
3126
  const { immediate = true } = options;
2713
3127
  let observer = null;
2714
3128
  const cleanup = () => {
@@ -2748,9 +3162,25 @@
2748
3162
  (0, vue.onUnmounted)(cleanup);
2749
3163
  return cleanup;
2750
3164
  };
2751
- const useTenantData = (apiBaseUrl, tenantId, enableMultiTenantMode = true) => {
3165
+ //#endregion
3166
+ //#region src/hooks/use-tenant-data.ts
3167
+ /**
3168
+ * 租户数据处理 Hook
3169
+ * @module hooks/useTenantData
3170
+ */
3171
+ /**
3172
+ * 使用租户数据的Hook
3173
+ * @param apiBaseUrl - API基础URL
3174
+ * @param tenantId - 租户ID
3175
+ * @param enableMultiTenantMode - 是否启用多租户模式
3176
+ * @returns 租户数据和加载状态
3177
+ */
3178
+ var useTenantData = (apiBaseUrl, tenantId, enableMultiTenantMode = true) => {
2752
3179
  const tenants = (0, vue.ref)({});
2753
3180
  const loading = (0, vue.ref)(false);
3181
+ /**
3182
+ * 获取租户数据
3183
+ */
2754
3184
  const fetchTenants = async () => {
2755
3185
  if (!apiBaseUrl || !tenantId) {
2756
3186
  console.warn("获取租户需要提供有效的API基础URL和租户ID");
@@ -2779,7 +3209,15 @@
2779
3209
  fetchTenants
2780
3210
  };
2781
3211
  };
2782
- const debounce = (fn, delay) => {
3212
+ //#endregion
3213
+ //#region src/utils/common.ts
3214
+ /**
3215
+ * 防抖函数
3216
+ * @param fn - 需要防抖的函数
3217
+ * @param delay - 延迟时间(毫秒)
3218
+ * @returns 防抖后的函数
3219
+ */
3220
+ var debounce = (fn, delay) => {
2783
3221
  let timer = null;
2784
3222
  return function(...args) {
2785
3223
  if (timer) clearTimeout(timer);
@@ -2789,7 +3227,14 @@
2789
3227
  }, delay);
2790
3228
  };
2791
3229
  };
2792
- const calculateVisibleTags = (container, items, containerWidth) => {
3230
+ /**
3231
+ * 计算标签容器可见数量
3232
+ * @param container - 容器元素
3233
+ * @param items - 项目元素列表
3234
+ * @param containerWidth - 容器宽度
3235
+ * @returns 可见项目数量
3236
+ */
3237
+ var calculateVisibleTags = (container, items, containerWidth) => {
2793
3238
  if (!container || !items.length) return 0;
2794
3239
  let totalWidth = 0;
2795
3240
  let visibleCount = 0;
@@ -2806,10 +3251,27 @@
2806
3251
  }
2807
3252
  return Math.max(1, visibleCount);
2808
3253
  };
2809
- const useUserSearch = (apiBaseUrl, tenantId, enableMultiTenantMode = true) => {
3254
+ //#endregion
3255
+ //#region src/hooks/use-user-search.ts
3256
+ /**
3257
+ * 用户搜索 Hook
3258
+ * @module hooks/useUserSearch
3259
+ */
3260
+ /**
3261
+ * 使用用户搜索的Hook
3262
+ * @param apiBaseUrl - API基础URL
3263
+ * @param tenantId - 租户ID
3264
+ * @param enableMultiTenantMode - 是否启用多租户模式
3265
+ * @returns 用户搜索相关状态和方法
3266
+ */
3267
+ var useUserSearch = (apiBaseUrl, tenantId, enableMultiTenantMode = true) => {
2810
3268
  const searchResults = (0, vue.ref)([]);
2811
3269
  const loading = (0, vue.ref)(false);
2812
3270
  const searchQuery = (0, vue.ref)("");
3271
+ /**
3272
+ * 执行用户搜索
3273
+ * @param keyword - 搜索关键词
3274
+ */
2813
3275
  const performSearch = async (keyword) => {
2814
3276
  if (!keyword?.length) {
2815
3277
  searchResults.value = [];
@@ -2837,11 +3299,18 @@
2837
3299
  }
2838
3300
  };
2839
3301
  const debouncedSearch = debounce(performSearch, 300);
3302
+ /**
3303
+ * 处理输入变化
3304
+ * @param value - 输入值
3305
+ */
2840
3306
  const handleSearchInput = (value) => {
2841
3307
  loading.value = true;
2842
3308
  searchQuery.value = value.trim();
2843
3309
  debouncedSearch(searchQuery.value);
2844
3310
  };
3311
+ /**
3312
+ * 清空搜索
3313
+ */
2845
3314
  const clearSearch = () => {
2846
3315
  searchQuery.value = "";
2847
3316
  searchResults.value = [];
@@ -2856,8 +3325,23 @@
2856
3325
  clearSearch
2857
3326
  };
2858
3327
  };
2859
- const useUserSelection = (options) => {
3328
+ //#endregion
3329
+ //#region src/hooks/use-user-selection.ts
3330
+ /**
3331
+ * 用户选择公共逻辑 Hook
3332
+ * @module hooks/useUserSelection
3333
+ */
3334
+ /**
3335
+ * 用户选择公共逻辑 Hook
3336
+ * @param options - 配置选项
3337
+ * @returns 用户选择相关方法
3338
+ */
3339
+ var useUserSelection = (options) => {
2860
3340
  const { selectedUserIds, excludeUserIds, userGroup, searchQuery } = options;
3341
+ /**
3342
+ * 创建自定义用户对象
3343
+ * @param loginName - 用户登录名
3344
+ */
2861
3345
  const createCustomUser = (loginName) => ({
2862
3346
  id: loginName,
2863
3347
  name: loginName,
@@ -2865,11 +3349,19 @@
2865
3349
  tenantId: "",
2866
3350
  login_name: loginName
2867
3351
  });
3352
+ /**
3353
+ * 检查用户是否已选中
3354
+ * @param userId - 用户ID
3355
+ */
2868
3356
  const isUserSelected = (userId) => {
2869
3357
  return selectedUserIds.value.includes(userId);
2870
3358
  };
2871
- const filterOptions = (options$1) => {
2872
- return options$1.filter((user) => !isUserSelected(user.id)).filter((user) => !excludeUserIds?.value?.includes(user.id));
3359
+ /**
3360
+ * 过滤选项(排除已选和排除列表)
3361
+ * @param options - 原始选项列表
3362
+ */
3363
+ const filterOptions = (options) => {
3364
+ return options.filter((user) => !isUserSelected(user.id)).filter((user) => !excludeUserIds?.value?.includes(user.id));
2873
3365
  };
2874
3366
  return {
2875
3367
  createCustomUser,
@@ -2886,6 +3378,8 @@
2886
3378
  })
2887
3379
  };
2888
3380
  };
3381
+ //#endregion
3382
+ //#region src/components/me-tag.vue?vue&type=script&setup=true&lang.ts
2889
3383
  var me_tag_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
2890
3384
  name: "MeTag",
2891
3385
  __name: "me-tag",
@@ -2904,9 +3398,21 @@
2904
3398
  emits: ["click"],
2905
3399
  setup(__props, { expose: __expose, emit: __emit }) {
2906
3400
  __expose();
3401
+ /**
3402
+ * "我"标签组件
3403
+ */
2907
3404
  const { t } = use_i18n_default();
3405
+ /**
3406
+ * 组件属性
3407
+ */
2908
3408
  const props = __props;
3409
+ /**
3410
+ * 组件事件
3411
+ */
2909
3412
  const emit = __emit;
3413
+ /**
3414
+ * 处理点击事件
3415
+ */
2910
3416
  const handleClick = () => {
2911
3417
  if (props.isDisabled) return;
2912
3418
  emit("click");
@@ -2924,11 +3430,15 @@
2924
3430
  return __returned__;
2925
3431
  }
2926
3432
  });
2927
- var __plugin_vue_export_helper_default = (sfc, props) => {
3433
+ //#endregion
3434
+ //#region \0plugin-vue:export-helper
3435
+ var _plugin_vue_export_helper_default = (sfc, props) => {
2928
3436
  const target = sfc.__vccOpts || sfc;
2929
3437
  for (const [key, val] of props) target[key] = val;
2930
3438
  return target;
2931
3439
  };
3440
+ //#endregion
3441
+ //#region src/components/me-tag.vue
2932
3442
  function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) {
2933
3443
  return $props.currentUserId ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
2934
3444
  key: 0,
@@ -2936,14 +3446,22 @@
2936
3446
  onClick: (0, vue.withModifiers)($setup.handleClick, ["stop"])
2937
3447
  }, (0, vue.toDisplayString)($setup.t("我")), 3)) : (0, vue.createCommentVNode)("v-if", true);
2938
3448
  }
2939
- var me_tag_default = /* @__PURE__ */ __plugin_vue_export_helper_default(me_tag_vue_vue_type_script_setup_true_lang_default, [
3449
+ var me_tag_default = /* @__PURE__ */ _plugin_vue_export_helper_default(me_tag_vue_vue_type_script_setup_true_lang_default, [
2940
3450
  ["render", _sfc_render$3],
2941
3451
  ["__scopeId", "data-v-a1054364"],
2942
3452
  ["__file", "/Users/brooklin/project/bkui-monorepo/packages/bk-user-selector/src/components/me-tag.vue"]
2943
3453
  ]);
3454
+ //#endregion
3455
+ //#region src/assets/user-group.svg
2944
3456
  var user_group_default = "data:image/svg+xml,%3csvg%20viewBox='0%200%201024%201024'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20style='fill:%20%23A3C5FD;'%3e%3cpath%20fill-rule='evenodd'%20d='M405.7858816%20162.66256256C416.4461344%20160.6535248%20439.8986944%20159.44810208%20457.3815104%20160.25171712%20484.2453504%20161.05533248%20494.052784%20163.4661776%20516.226112%20174.7167888%20567.8217376%20200.43247136%20597.670448%20242.22045568%20606.6250624%20301.28616416%20617.711728%20374.415136%20593.4063488%20443.5260352%20535.8409792%20500.180896%20509.8299584%20525.8965792%20505.565856%20537.5489984%20514.0940608%20557.237568%20521.3430336%20572.9080608%20546.0748224%20586.5695168%20629.2248%20620.3213504%20691.054272%20645.2334208%20760.985536%20687.4232096%20767.8080992%20703.8973216%20774.6306624%20720.3714304%20784.8645056%20752.114224%20791.6870688%20777.4280992%20799.7888608%20807.1618592%20793.3927072%20818.8142784%20761.8383584%20832.4757344%20720.4765728%20850.155264%20669.3073536%20857.3878016%20546.9276416%20862.2094912%20392.9935776%20868.2366048%20227.12002944%20858.5932224%20162.30568672%20840.1100768%20134.5890272%20832.4757344%20108.15159776%20815.1980096%20100.47621504%20799.5275136%2093.6536528%20786.2678656%2094.08006304%20784.2588288%20105.59313696%20746.4889184%20116.67980096%20709.924432%20119.23826176%20705.5045504%20141.41158944%20685.4141728%20143.84821888%20683.2001312%20146.05397248%20681.2036448%20148.2232096%20679.3252416L152.13038144%20676.0501632C159.5946992%20670.0236288%20167.98497088%20664.6722176%20184.94031712%20656.0863296L191.29263904%20652.915344C215.97973152%20640.7492736%20256.51622304%20622.3959904%20329.458464%20589.3821696%20359.7335872%20575.3189056%20371.2466592%20563.6664896%20375.084352%20542.772496%20377.2164032%20530.316464%20374.6579424%20526.7001952%20345.2356416%20496.9664352%20295.34565344%20446.338688%20274.02514592%20396.9163584%20273.59873568%20331.0199232%20273.59873568%20291.24097568%20282.12693888%20265.52529312%20307.71154784%20228.15719168%20332.8697472%20191.19089792%20365.703328%20169.49329056%20405.7858816%20162.66256256ZM668.7713728%20226.60405184C756.683056%20211.50282816%20820.4190272%20263.09867616%20827.0124032%20354.9644544%20831.8475456%20416.6277856%20815.1443264%20461.931456%20770.3093664%20510.1714752%20752.287472%20529.4674848%20747.891888%20536.5986176%20748.3314464%20548.344016%20748.7710048%20555.8946272%20751.4083552%20565.123152%20754.485264%20568.8984576%20757.5621728%20572.2542848%20788.331264%20588.1944672%20823.0563776%20604.1346464%20944.3745024%20659.92528%20966.791984%20682.996592%20958.4403712%20744.6599232%20954.923904%20771.9260224%20956.6821376%20771.0870656%20890.308816%20787.0272448%20867.4517792%20792.8999456%20845.0343008%20798.3531648%20841.0782752%20799.6116%20835.3640128%20801.2895136%20833.1662208%20797.9336864%20830.5288704%20781.5740256%20824.3750528%20739.6261824%20812.0674176%20710.6821696%20790.0894976%20687.6108576%20752.287472%20647.3409248%20703.9360448%20619.6553504%20624.3759712%20593.6476864%20597.5629088%20584.4191616%20560.64%20550.8608864%20560.64%20534.920704%20560.64%20527.7895712%20569.8707264%20514.7857408%20589.6508544%20494.6507744%20620.859504%20461.931456%20639.7605152%20429.631616%20648.5516832%20394.8149056%20655.5846208%20366.7098496%20652.0681504%20283.23364096%20642.837424%20254.7091072%20635.3649312%20231.63779328%20634.4858144%20232.47675008%20668.7713728%20226.60405184Z'%3e%3c/path%3e%3c/svg%3e";
3457
+ //#endregion
3458
+ //#region src/assets/user.svg
2945
3459
  var user_default = "data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'?%3e%3csvg%20width='32px'%20height='32px'%20viewBox='0%200%2032%2032'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3ctitle%3eIcon/用户%3c/title%3e%3cg%20id='Icon/用户'%20stroke='none'%20stroke-width='1'%20fill='none'%20fill-rule='evenodd'%3e%3cg%20id='user-(1)'%20transform='translate(3,%202)'%20fill='%23A3C5FD'%20fill-rule='nonzero'%3e%3cpath%20d='M13.0077612,27.9989067%20C10.3002732,27.9989067%207.59285518,28.0018792%204.88515705,27.997455%20C3.95018807,27.9959342%203.05044678,27.8282323%202.22816433,27.3628696%20C0.998627601,26.6672451%200.29953695,25.6114692%200.0864200465,24.2387462%20C-0.0656962495,23.259079%200.0147040645,22.4675755%200.0874005263,21.4879775%20C0.187970957,20.13461%200.423078914,19.3321844%200.863249688,18.0430358%20C1.22365046,16.9873982%201.73014453,16.0067633%202.49702917,15.175719%20C3.42254341,14.1726178%204.6014447,13.7297906%205.9255989,13.6440041%20C6.33292322,13.6073668%206.66741099,13.712025%206.9979768,13.9263185%20C7.58886318,14.3094892%208.17393665,14.7060014%208.79220674,15.0421658%20C10.1097776,15.758321%2011.5447274,16.1099698%2013.0616182,16.0930337%20C14.6806203,16.0750607%2016.2142496,15.63963%2017.592821,14.8169502%20C18.0555431,14.5407189%2018.5150436,14.256538%2018.9569652,13.9491996%20C19.3610679,13.6681294%2019.7808585,13.5749462%2020.274326,13.6337733%20C21.462472,13.7340074%2022.3872158,14.1103345%2023.2340106,14.8851094%20C23.902636,15.496952%2024.3685096,16.2520257%2024.7518119,17.0611566%20C25.272453,18.1598604%2025.5462904,18.7976948%2025.7441396,19.9861253%20C25.9499728,21.2233595%2026.0256808,22.2792045%2025.9924842,23.5308171%20C25.9627193,24.6543374%2025.6405577,25.6840525%2024.8535729,26.5307194%20C24.1686994,27.2671979%2023.3129402,27.7090574%2022.3211027,27.8808379%20C21.9232331,27.9495501%2021.5154185,27.9922014%2021.1120162,27.9935148%20C18.4104811,28.0036073%2015.7090862,27.9989067%2013.0077612,27.9989067%20L13.0077612,27.9989067%20Z%20M5.91775495,6.98479749%20C5.84814002,3.25685016%209.08684454,-0.00255470186%2013.0162355,1.5025268e-06%20C16.9117994,0.00256071584%2020.1304739,3.23452217%2020.1095656,7.04113598%20C20.0884528,10.8082092%2016.8998935,14.015354%2013.0058002,14.0149393%20C9.10134181,14.0145245%205.83322254,10.7695672%205.91775495,6.98479749%20Z'%20id='形状'%3e%3c/path%3e%3c/g%3e%3c/g%3e%3c/svg%3e";
3460
+ //#endregion
3461
+ //#region src/assets/virtual.svg
2946
3462
  var virtual_default = "data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'?%3e%3csvg%20width='32px'%20height='32px'%20viewBox='0%200%2032%2032'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3ctitle%3eIcon/虚拟icon%3c/title%3e%3cg%20id='Icon/虚拟icon'%20stroke='none'%20stroke-width='1'%20fill='none'%20fill-rule='evenodd'%3e%3cpath%20d='M27.4705882,3%20C28.315259,3%2029,3.68474098%2029,4.52941178%20L29,22.4623054%20C29,23.3069762%2028.315259,23.9917172%2027.4705882,23.9917172%20L20.5882353,23.9917172%20L20.5882353,27.0244081%20L24.0294118,27.0244081%20C24.2405794,27.0244081%2024.4117647,27.1955933%2024.4117647,27.406761%20L24.4117647,28.617647%20C24.4117647,28.8288148%2024.2405795,29%2024.0294118,29%20L7.97058824,29%20C7.75942054,29%207.58823529,28.8288148%207.58823529,28.617647%20L7.58823529,27.406761%20C7.58823531,27.1955933%207.75942055,27.0244081%207.97058824,27.0244081%20L11.4117647,27.0244081%20L11.4117647,23.9917172%20L4.52941178,23.9917172%20C3.68474098,23.9917172%203,23.3069762%203,22.4623054%20L3,4.52941178%20C3,3.68474098%203.68474098,3%204.52941178,3%20L27.4705882,3%20Z%20M19,24%20L13,24%20L13,27%20L19,27%20L19,24%20Z%20M23.4117647,7%20L8.58823529,7%20C8.03595054,7%207.58823529,7.44771525%207.58823529,8%20L7.58823529,19%20C7.58823529,19.5522847%208.03595054,20%208.58823529,20%20L23.4117647,20%20C23.9640495,20%2024.4117647,19.5522847%2024.4117647,19%20L24.4117647,8%20C24.4117647,7.44771525%2023.9640495,7%2023.4117647,7%20Z%20M12,10%20C12.5522847,10%2013,10.4477153%2013,11%20L13,13%20C13,13.5522847%2012.5522847,14%2012,14%20C11.4477153,14%2011,13.5522847%2011,13%20L11,11%20C11,10.4477153%2011.4477153,10%2012,10%20Z%20M20,10%20C20.5522847,10%2021,10.4477153%2021,11%20L21,13%20C21,13.5522847%2020.5522847,14%2020,14%20C19.4477153,14%2019,13.5522847%2019,13%20L19,11%20C19,10.4477153%2019.4477153,10%2020,10%20Z%20M26,5%20C25.4477153,5%2025,5.44771525%2025,6%20C25,6.55228475%2025.4477153,7%2026,7%20C26.5522847,7%2027,6.55228475%2027,6%20C27,5.44771525%2026.5522847,5%2026,5%20Z'%20id='蒙版'%20fill='%23A3C5FD'%20fill-rule='nonzero'%3e%3c/path%3e%3c/g%3e%3c/svg%3e";
3463
+ //#endregion
3464
+ //#region src/components/user-render.ts
2947
3465
  var user_render_default = (0, vue.defineComponent)({
2948
3466
  name: "UserRender",
2949
3467
  props: {
@@ -2980,13 +3498,13 @@
2980
3498
  const loginName = user.login_name || user.bk_username || user.id;
2981
3499
  return `${props.avatarBaseUrl}${loginName}.png?default_when_absent=true`;
2982
3500
  };
2983
- const defaultRender = (h$1, props$1) => {
2984
- return h$1("div", { style: {
3501
+ const defaultRender = (h, props) => {
3502
+ return h("div", { style: {
2985
3503
  display: "flex",
2986
3504
  alignItems: "center"
2987
3505
  } }, [
2988
- props$1.hasAvatar ? h$1("img", {
2989
- src: getAvatarUrl(props$1.user),
3506
+ props.hasAvatar ? h("img", {
3507
+ src: getAvatarUrl(props.user),
2990
3508
  style: {
2991
3509
  width: "20px",
2992
3510
  height: "20px",
@@ -2995,11 +3513,11 @@
2995
3513
  flexShrink: 0
2996
3514
  }
2997
3515
  }) : null,
2998
- h$1("span", props$1.user.name),
2999
- props$1.user.tenantId !== props$1.tenantId && props$1.user.tenantId ? h$1("span", { style: {
3516
+ h("span", props.user.name),
3517
+ props.user.tenantId !== props.tenantId && props.user.tenantId ? h("span", { style: {
3000
3518
  color: "#f59500",
3001
3519
  marginLeft: "4px"
3002
- } }, `@${props$1.tenants[props$1.user.tenantId] || props$1.user.tenantId}`) : null
3520
+ } }, `@${props.tenants[props.user.tenantId] || props.user.tenantId}`) : null
3003
3521
  ]);
3004
3522
  };
3005
3523
  return () => {
@@ -3012,6 +3530,8 @@
3012
3530
  };
3013
3531
  }
3014
3532
  });
3533
+ //#endregion
3534
+ //#region src/components/selection-popover.vue?vue&type=script&setup=true&lang.ts
3015
3535
  var selection_popover_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
3016
3536
  name: "SelectionPopover",
3017
3537
  __name: "selection-popover",
@@ -3061,6 +3581,16 @@
3061
3581
  required: false,
3062
3582
  default: () => []
3063
3583
  },
3584
+ recentUsers: {
3585
+ type: Array,
3586
+ required: false,
3587
+ default: () => []
3588
+ },
3589
+ recentUsersName: {
3590
+ type: String,
3591
+ required: false,
3592
+ default: ""
3593
+ },
3064
3594
  renderListItem: {
3065
3595
  type: Function,
3066
3596
  required: false
@@ -3094,11 +3624,23 @@
3094
3624
  emits: ["click-outside", "select-user"],
3095
3625
  setup(__props, { expose: __expose, emit: __emit }) {
3096
3626
  __expose();
3627
+ /**
3628
+ * 用户选择器下拉菜单组件
3629
+ */
3097
3630
  const { t } = use_i18n_default();
3098
3631
  const slotContainerRef = (0, vue.ref)(null);
3099
3632
  const contentContainerRef = (0, vue.ref)(null);
3633
+ /**
3634
+ * 组件属性
3635
+ */
3100
3636
  const props = __props;
3637
+ /**
3638
+ * 组件事件
3639
+ */
3101
3640
  const emit = __emit;
3641
+ /**
3642
+ * 按分组整理用户列表,如果有 userGroup, 则在最前面增加用户群组 userGroup
3643
+ */
3102
3644
  const groupedUsers = (0, vue.computed)(() => {
3103
3645
  const groups = {};
3104
3646
  if (Array.isArray(props.userGroup) && props.userGroup.length > 0) groups[props.userGroupName] = props.userGroup.map((group) => ({
@@ -3113,25 +3655,41 @@
3113
3655
  });
3114
3656
  return groups;
3115
3657
  });
3658
+ const hasMainOptions = (0, vue.computed)(() => Object.values(groupedUsers.value).some((group) => group.length > 0));
3659
+ const hasRecentUsers = (0, vue.computed)(() => props.recentUsers.length > 0);
3660
+ const hasDropdownOptions = (0, vue.computed)(() => hasMainOptions.value || hasRecentUsers.value);
3661
+ /**
3662
+ * 判断用户是否为当前高亮项
3663
+ */
3116
3664
  const isHighlighted = (user) => {
3117
3665
  if (props.highlightedIndex < 0 || !props.flatOptions.length) return false;
3118
- return props.flatOptions[props.highlightedIndex]?.id === user.id;
3666
+ return props.flatOptions[props.highlightedIndex] === user;
3119
3667
  };
3668
+ /**
3669
+ * 选择用户
3670
+ */
3120
3671
  const selectUser = (user) => {
3121
3672
  emit("select-user", user);
3122
3673
  };
3674
+ /**
3675
+ * 点击外部
3676
+ */
3123
3677
  const handleClickOutside = ({ event }) => {
3124
3678
  const target = event.target;
3125
3679
  if (slotContainerRef.value?.contains(target)) return;
3126
3680
  if (contentContainerRef.value?.contains(target)) return;
3127
3681
  emit("click-outside", event);
3128
3682
  };
3683
+ /**
3684
+ * 监听高亮索引变化,自动滚动到高亮项
3685
+ */
3129
3686
  (0, vue.watch)(() => props.highlightedIndex, (newIndex) => {
3130
3687
  if (newIndex < 0 || !contentContainerRef.value) return;
3131
3688
  (0, vue.nextTick)(() => {
3132
3689
  const highlightedElement = contentContainerRef.value?.querySelector(".user-option.is-highlighted");
3133
3690
  if (highlightedElement) highlightedElement.scrollIntoView({
3134
3691
  block: "nearest",
3692
+ inline: "nearest",
3135
3693
  behavior: "auto"
3136
3694
  });
3137
3695
  });
@@ -3143,6 +3701,9 @@
3143
3701
  props,
3144
3702
  emit,
3145
3703
  groupedUsers,
3704
+ hasMainOptions,
3705
+ hasRecentUsers,
3706
+ hasDropdownOptions,
3146
3707
  isHighlighted,
3147
3708
  selectUser,
3148
3709
  handleClickOutside,
@@ -3163,15 +3724,28 @@
3163
3724
  return __returned__;
3164
3725
  }
3165
3726
  });
3727
+ //#endregion
3728
+ //#region src/components/selection-popover.vue
3166
3729
  var _hoisted_1$1 = { ref: "contentContainerRef" };
3167
3730
  var _hoisted_2$1 = {
3168
3731
  key: 0,
3169
3732
  class: "no-data"
3170
3733
  };
3171
- var _hoisted_3$1 = { class: "group-name" };
3172
- var _hoisted_4$1 = { class: "group-count" };
3173
- var _hoisted_5 = ["onClick"];
3174
- var _hoisted_6 = { ref: "slotContainerRef" };
3734
+ var _hoisted_3$1 = {
3735
+ key: 0,
3736
+ class: "dropdown-panel dropdown-panel-main"
3737
+ };
3738
+ var _hoisted_4$1 = { class: "group-name" };
3739
+ var _hoisted_5 = { class: "group-count" };
3740
+ var _hoisted_6 = ["onClick"];
3741
+ var _hoisted_7 = {
3742
+ key: 1,
3743
+ class: "dropdown-panel dropdown-panel-recent"
3744
+ };
3745
+ var _hoisted_8 = { class: "group-name" };
3746
+ var _hoisted_9 = { class: "group-count" };
3747
+ var _hoisted_10 = ["onClick"];
3748
+ var _hoisted_11 = { ref: "slotContainerRef" };
3175
3749
  function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
3176
3750
  return (0, vue.openBlock)(), (0, vue.createBlock)($setup["Popover"], {
3177
3751
  arrow: false,
@@ -3190,7 +3764,10 @@
3190
3764
  mode: "spin",
3191
3765
  size: "mini"
3192
3766
  }, {
3193
- default: (0, vue.withCtx)(() => [$props.options.length === 0 && $props.userGroup.length === 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$1, [(0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)($props.emptyText), 1)])) : ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, (0, vue.renderList)($setup.groupedUsers, (group, groupName) => {
3767
+ default: (0, vue.withCtx)(() => [!$setup.hasDropdownOptions ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_2$1, [(0, vue.createElementVNode)("span", null, (0, vue.toDisplayString)($props.emptyText), 1)])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
3768
+ key: 1,
3769
+ class: (0, vue.normalizeClass)(["dropdown-panels", { "is-two-column": $setup.hasMainOptions && $setup.hasRecentUsers }])
3770
+ }, [$setup.hasMainOptions ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_3$1, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)($setup.groupedUsers, (group, groupName) => {
3194
3771
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
3195
3772
  key: groupName,
3196
3773
  class: "user-group"
@@ -3198,7 +3775,7 @@
3198
3775
  key: 0,
3199
3776
  class: "group-header",
3200
3777
  onClick: _cache[0] || (_cache[0] = (0, vue.withModifiers)(() => {}, ["prevent"]))
3201
- }, [(0, vue.createElementVNode)("span", _hoisted_3$1, (0, vue.toDisplayString)(groupName), 1), (0, vue.createElementVNode)("span", _hoisted_4$1, "(" + (0, vue.toDisplayString)(group.length) + ")", 1)])) : (0, vue.createCommentVNode)("v-if", true), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(group, (user) => {
3778
+ }, [(0, vue.createElementVNode)("span", _hoisted_4$1, (0, vue.toDisplayString)(groupName), 1), (0, vue.createElementVNode)("span", _hoisted_5, "(" + (0, vue.toDisplayString)(group.length) + ")", 1)])) : (0, vue.createCommentVNode)("v-if", true), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(group, (user) => {
3202
3779
  return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
3203
3780
  key: user.id,
3204
3781
  class: (0, vue.normalizeClass)(["user-option", { "is-highlighted": $setup.isHighlighted(user) }]),
@@ -3218,20 +3795,50 @@
3218
3795
  "tenant-id",
3219
3796
  "tenants",
3220
3797
  "user"
3221
- ])], 42, _hoisted_5);
3798
+ ])], 42, _hoisted_6);
3222
3799
  }), 128))]);
3223
- }), 128))]),
3800
+ }), 128))])) : (0, vue.createCommentVNode)("v-if", true), $setup.hasRecentUsers ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_7, [$props.recentUsersName ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
3801
+ key: 0,
3802
+ class: "group-header",
3803
+ onClick: _cache[2] || (_cache[2] = (0, vue.withModifiers)(() => {}, ["prevent"]))
3804
+ }, [(0, vue.createElementVNode)("span", _hoisted_8, (0, vue.toDisplayString)($props.recentUsersName), 1), (0, vue.createElementVNode)("span", _hoisted_9, "(" + (0, vue.toDisplayString)($props.recentUsers.length) + ")", 1)])) : (0, vue.createCommentVNode)("v-if", true), ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)($props.recentUsers, (user) => {
3805
+ return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
3806
+ key: user.id,
3807
+ class: (0, vue.normalizeClass)(["user-option", { "is-highlighted": $setup.isHighlighted(user) }]),
3808
+ onClick: (0, vue.withModifiers)(($event) => $setup.selectUser(user), ["prevent"]),
3809
+ onMousedown: _cache[3] || (_cache[3] = (0, vue.withModifiers)(() => {}, ["prevent"]))
3810
+ }, [(0, vue.createVNode)($setup["UserRender"], {
3811
+ "avatar-base-url": $props.avatarBaseUrl,
3812
+ "has-avatar": $props.hasAvatar,
3813
+ render: $props.renderListItem,
3814
+ "tenant-id": $props.tenantId,
3815
+ tenants: $props.tenants,
3816
+ user
3817
+ }, null, 8, [
3818
+ "avatar-base-url",
3819
+ "has-avatar",
3820
+ "render",
3821
+ "tenant-id",
3822
+ "tenants",
3823
+ "user"
3824
+ ])], 42, _hoisted_10);
3825
+ }), 128))])) : (0, vue.createCommentVNode)("v-if", true)], 2))]),
3224
3826
  _: 1
3225
3827
  }, 8, ["loading"])], 512)]),
3226
- default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", _hoisted_6, [(0, vue.renderSlot)(_ctx.$slots, "default", {}, void 0, true)], 512)]),
3828
+ default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", _hoisted_11, [(0, vue.renderSlot)(_ctx.$slots, "default", {}, void 0, true)], 512)]),
3227
3829
  _: 3
3228
3830
  }, 8, ["is-show", "width"]);
3229
3831
  }
3230
- var selection_popover_default = /* @__PURE__ */ __plugin_vue_export_helper_default(selection_popover_vue_vue_type_script_setup_true_lang_default, [
3832
+ var selection_popover_default = /* @__PURE__ */ _plugin_vue_export_helper_default(selection_popover_vue_vue_type_script_setup_true_lang_default, [
3231
3833
  ["render", _sfc_render$2],
3232
3834
  ["__scopeId", "data-v-9173accf"],
3233
3835
  ["__file", "/Users/brooklin/project/bkui-monorepo/packages/bk-user-selector/src/components/selection-popover.vue"]
3234
3836
  ]);
3837
+ //#endregion
3838
+ //#region src/components/user-tag.vue?vue&type=script&setup=true&lang.ts
3839
+ /**
3840
+ * 用户标签组件
3841
+ */
3235
3842
  var user_tag_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
3236
3843
  name: "UserTag",
3237
3844
  __name: "user-tag",
@@ -3276,10 +3883,22 @@
3276
3883
  emits: ["click", "close"],
3277
3884
  setup(__props, { expose: __expose, emit: __emit }) {
3278
3885
  __expose();
3886
+ /**
3887
+ * 组件属性
3888
+ */
3889
+ /**
3890
+ * 组件事件
3891
+ */
3279
3892
  const emit = __emit;
3893
+ /**
3894
+ * 处理点击事件
3895
+ */
3280
3896
  const handleClick = () => {
3281
3897
  emit("click");
3282
3898
  };
3899
+ /**
3900
+ * 处理关闭事件
3901
+ */
3283
3902
  const handleClose = () => {
3284
3903
  emit("close");
3285
3904
  };
@@ -3301,6 +3920,8 @@
3301
3920
  return __returned__;
3302
3921
  }
3303
3922
  });
3923
+ //#endregion
3924
+ //#region src/components/user-tag.vue
3304
3925
  function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
3305
3926
  return (0, vue.openBlock)(), (0, vue.createBlock)($setup["Tag"], {
3306
3927
  class: (0, vue.normalizeClass)(["user-tag", {
@@ -3331,15 +3952,22 @@
3331
3952
  _: 1
3332
3953
  }, 8, ["class"]);
3333
3954
  }
3334
- var user_tag_default = /* @__PURE__ */ __plugin_vue_export_helper_default(user_tag_vue_vue_type_script_setup_true_lang_default, [
3955
+ var user_tag_default = /* @__PURE__ */ _plugin_vue_export_helper_default(user_tag_vue_vue_type_script_setup_true_lang_default, [
3335
3956
  ["render", _sfc_render$1],
3336
3957
  ["__scopeId", "data-v-d1173d20"],
3337
3958
  ["__file", "/Users/brooklin/project/bkui-monorepo/packages/bk-user-selector/src/components/user-tag.vue"]
3338
3959
  ]);
3960
+ //#endregion
3961
+ //#region src/components/user-selector.vue?vue&type=script&setup=true&lang.ts
3339
3962
  var user_selector_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({
3340
3963
  name: "BkUserSelector",
3341
3964
  __name: "user-selector",
3342
3965
  props: {
3966
+ autoFocus: {
3967
+ type: Boolean,
3968
+ required: false,
3969
+ default: false
3970
+ },
3343
3971
  draggable: {
3344
3972
  type: Boolean,
3345
3973
  required: false,
@@ -3380,6 +4008,21 @@
3380
4008
  required: false,
3381
4009
  default: false
3382
4010
  },
4011
+ allowCrossOriginCredentials: {
4012
+ type: Boolean,
4013
+ required: false,
4014
+ default: true
4015
+ },
4016
+ allowedApiOrigins: {
4017
+ type: Array,
4018
+ required: false,
4019
+ default: () => []
4020
+ },
4021
+ allowPrivateApiHost: {
4022
+ type: Boolean,
4023
+ required: false,
4024
+ default: true
4025
+ },
3383
4026
  apiBaseUrl: {
3384
4027
  type: String,
3385
4028
  required: true,
@@ -3435,6 +4078,11 @@
3435
4078
  required: false,
3436
4079
  default: ""
3437
4080
  },
4081
+ recentUserIds: {
4082
+ type: Array,
4083
+ required: false,
4084
+ default: () => []
4085
+ },
3438
4086
  renderListItem: {
3439
4087
  type: Function,
3440
4088
  required: false
@@ -3464,17 +4112,47 @@
3464
4112
  "change",
3465
4113
  "dragEnd",
3466
4114
  "dragStart",
4115
+ "error",
3467
4116
  "focus",
4117
+ "unauthorized",
3468
4118
  "update:modelValue"
3469
4119
  ],
3470
4120
  setup(__props, { expose: __expose, emit: __emit }) {
3471
- __expose();
4121
+ /**
4122
+ * 蓝鲸用户选择器组件
4123
+ * @module components/UserSelector
4124
+ */
3472
4125
  const { t } = use_i18n_default();
3473
4126
  (0, bkui_vue.provideGlobalConfig)({ prefix: "bk" });
4127
+ /**
4128
+ * 组件属性
4129
+ */
3474
4130
  const props = __props;
4131
+ /**
4132
+ * 组件事件
4133
+ */
3475
4134
  const emit = __emit;
3476
- const { tenants = {} } = useTenantData(props.apiBaseUrl, props.tenantId, props.enableMultiTenantMode);
4135
+ const handleApiError = (error) => {
4136
+ emit("error", error);
4137
+ };
4138
+ const handleApiUnauthorized = (error) => {
4139
+ emit("unauthorized", error);
4140
+ };
4141
+ provideApiConfig(props.apiBaseUrl, props.tenantId, props.allowedApiOrigins, props.allowPrivateApiHost, props.allowCrossOriginCredentials, {
4142
+ onError: handleApiError,
4143
+ onUnauthorized: handleApiUnauthorized
4144
+ });
4145
+ /**
4146
+ * 获取租户数据
4147
+ */
4148
+ const { tenants } = useTenantData(props.apiBaseUrl, props.tenantId, props.enableMultiTenantMode);
4149
+ /**
4150
+ * 用户搜索
4151
+ */
3477
4152
  const { searchResults, loading: searchLoading, searchQuery, clearSearch, handleSearchInput } = useUserSearch(props.apiBaseUrl, props.tenantId, props.enableMultiTenantMode);
4153
+ /**
4154
+ * 当前用户处理
4155
+ */
3478
4156
  const { fetchCurrentUser } = useCurrentUser({
3479
4157
  apiBaseUrl: props.apiBaseUrl,
3480
4158
  tenantId: props.tenantId,
@@ -3482,18 +4160,30 @@
3482
4160
  exactSearchKey: props.exactSearchKey,
3483
4161
  enableMultiTenantMode: props.enableMultiTenantMode
3484
4162
  });
4163
+ /**
4164
+ * DOM 引用
4165
+ */
3485
4166
  const containerRef = (0, vue.ref)(null);
3486
4167
  const sortableContainerRef = (0, vue.ref)(null);
3487
4168
  const collapsedContainerRef = (0, vue.ref)(null);
3488
4169
  const frontInputRef = (0, vue.ref)(null);
3489
4170
  const inlineInputRef = (0, vue.ref)(null);
3490
4171
  const lastInputRef = (0, vue.ref)(null);
4172
+ /**
4173
+ * 组件状态
4174
+ */
3491
4175
  const isFocused = (0, vue.ref)(false);
3492
4176
  const activeTagIndex = (0, vue.ref)(-1);
3493
4177
  const sortableInstance = (0, vue.ref)(null);
3494
4178
  const visibleUsers = (0, vue.ref)([]);
3495
4179
  const hiddenCount = (0, vue.ref)(0);
3496
4180
  const highlightedIndex = (0, vue.ref)(-1);
4181
+ const recentUsers = (0, vue.ref)([]);
4182
+ let recentUsersRequestId = 0;
4183
+ let recentUserIdsSnapshot = [];
4184
+ /**
4185
+ * 已选用户列表 (内部状态)
4186
+ */
3497
4187
  const selectedUsers = (0, vue.ref)([]);
3498
4188
  const isTextareaMode = (0, vue.computed)(() => props.type === "textarea");
3499
4189
  const textareaHeight = (0, vue.ref)(props.rows * 32);
@@ -3505,38 +4195,112 @@
3505
4195
  overflowY: "auto"
3506
4196
  };
3507
4197
  });
4198
+ /**
4199
+ * 未聚焦状态下展示的用户列表:textarea 模式展示全部,input 模式展示折叠后的
4200
+ */
3508
4201
  const collapsedDisplayUsers = (0, vue.computed)(() => {
3509
4202
  return isTextareaMode.value ? selectedUsers.value : visibleUsers.value;
3510
4203
  });
3511
- const showDropdown = (0, vue.computed)(() => {
3512
- return isFocused.value && (props.userGroup.length > 0 || searchQuery.value.trim() !== "");
3513
- });
4204
+ /**
4205
+ * 模型值 ID 列表
4206
+ */
3514
4207
  const modelValueIds = (0, vue.computed)(() => {
3515
4208
  if (props.multiple) return Array.isArray(props.modelValue) ? props.modelValue : [];
3516
4209
  return props.modelValue ? [props.modelValue] : [];
3517
4210
  });
4211
+ /**
4212
+ * 用 computed 处理国际化
4213
+ */
3518
4214
  const computedPlaceholder = (0, vue.computed)(() => props.placeholder || t("请输入人员名称搜索"));
3519
4215
  const computedUserGroupName = (0, vue.computed)(() => props.userGroupName || t("用户群组"));
3520
4216
  const computedEmptyText = (0, vue.computed)(() => props.emptyText || t("无匹配人员"));
4217
+ const computedRecentUsersName = (0, vue.computed)(() => t("最近选择"));
4218
+ /**
4219
+ * 已选用户ID列表
4220
+ */
3521
4221
  const selectedUserIds = (0, vue.computed)(() => selectedUsers.value.map((user) => user.id));
4222
+ const isUserMatchedByQuery = (user, query) => {
4223
+ if (!query) return true;
4224
+ return [
4225
+ user.id,
4226
+ user.name,
4227
+ user.bk_username,
4228
+ user.username,
4229
+ user.login_name,
4230
+ user.display_name,
4231
+ user.full_name
4232
+ ].some((field) => String(field || "").includes(query));
4233
+ };
4234
+ const getLookupFields = (exactSearchKey) => {
4235
+ return exactSearchKey.split(",").map((field) => field.trim()).filter(Boolean);
4236
+ };
4237
+ const findUserByLookupId = (users, lookupId, lookupFields) => {
4238
+ return users.find((user) => {
4239
+ if (user.id === lookupId) return true;
4240
+ const indexedUser = user;
4241
+ return lookupFields.some((field) => String(indexedUser[field] || "") === lookupId);
4242
+ });
4243
+ };
4244
+ const sortUsersByLookupIds = (users, lookupIds, lookupFields) => {
4245
+ return lookupIds.map((lookupId) => findUserByLookupId(users, lookupId, lookupFields)).filter(Boolean);
4246
+ };
4247
+ const lookupFormattedUsersByIds = async (lookupIds) => {
4248
+ const primaryLookupFields = getLookupFields(props.exactSearchKey);
4249
+ const formattedUsers = formatUsers(await lookupUsers({
4250
+ apiBaseUrl: props.apiBaseUrl,
4251
+ tenantId: props.tenantId,
4252
+ exactSearchKey: props.exactSearchKey,
4253
+ usersList: lookupIds,
4254
+ enableMultiTenantMode: props.enableMultiTenantMode
4255
+ }), props.enableMultiTenantMode);
4256
+ const unresolvedIds = lookupIds.filter((lookupId) => !findUserByLookupId(formattedUsers, lookupId, primaryLookupFields));
4257
+ if (unresolvedIds.length === 0 || props.exactSearchKey === "bk_username") return sortUsersByLookupIds(formattedUsers, lookupIds, primaryLookupFields);
4258
+ const fallbackUsers = formatUsers(await lookupUsers({
4259
+ apiBaseUrl: props.apiBaseUrl,
4260
+ tenantId: props.tenantId,
4261
+ exactSearchKey: DEFAULT_EXACT_SEARCH_KEY,
4262
+ usersList: unresolvedIds,
4263
+ enableMultiTenantMode: props.enableMultiTenantMode
4264
+ }), props.enableMultiTenantMode);
4265
+ const mergedUsers = [...formattedUsers];
4266
+ fallbackUsers.forEach((user) => {
4267
+ if (!mergedUsers.some((item) => item.id === user.id)) mergedUsers.push(user);
4268
+ });
4269
+ return sortUsersByLookupIds(mergedUsers, lookupIds, [...new Set([...primaryLookupFields, DEFAULT_EXACT_SEARCH_KEY])]);
4270
+ };
4271
+ /**
4272
+ * 是否已达到最大选择数量
4273
+ */
3522
4274
  const isMaxCountReached = (0, vue.computed)(() => {
3523
4275
  if (!props.maxCount || props.maxCount <= 0) return false;
3524
4276
  return selectedUsers.value.length >= props.maxCount;
3525
4277
  });
4278
+ /**
4279
+ * "我"标签是否禁用(已选中当前用户时禁用,或已达到最大数量)
4280
+ */
3526
4281
  const isMeTagDisabled = (0, vue.computed)(() => isMaxCountReached.value || !!props.currentUserId && selectedUsers.value.some((user) => user[props.exactSearchKey] === props.currentUserId));
4282
+ /**
4283
+ * UserTag 公共属性
4284
+ */
3527
4285
  const userTagCommonProps = (0, vue.computed)(() => ({
3528
4286
  avatarBaseUrl: props.avatarBaseUrl,
3529
4287
  currentTenantId: props.tenantId,
3530
4288
  hasAvatar: props.hasAvatar,
3531
4289
  renderTag: props.renderTag,
3532
- tenants
4290
+ tenants: tenants.value
3533
4291
  }));
4292
+ /**
4293
+ * 使用用户选择公共逻辑 hook
4294
+ */
3534
4295
  const { filteredUserGroup, filterOptions, createCustomUser } = useUserSelection({
3535
4296
  selectedUserIds,
3536
4297
  excludeUserIds: (0, vue.toRef)(props, "excludeUserIds"),
3537
4298
  userGroup: (0, vue.toRef)(props, "userGroup"),
3538
4299
  searchQuery
3539
4300
  });
4301
+ /**
4302
+ * 使用输入处理公共逻辑 hook
4303
+ */
3540
4304
  const { handlePaste } = useInputHandler({
3541
4305
  apiBaseUrl: props.apiBaseUrl,
3542
4306
  tenantId: props.tenantId,
@@ -3549,8 +4313,11 @@
3549
4313
  onAddUser: addUser,
3550
4314
  onBatchAddUsers: props.multiple ? updateSelectedUsers : void 0
3551
4315
  });
4316
+ /**
4317
+ * 显示的选项(过滤后的搜索结果)
4318
+ */
3552
4319
  const displayOptions = (0, vue.computed)(() => filterOptions(searchResults.value));
3553
- const flatOptions = (0, vue.computed)(() => {
4320
+ const mainNavigableUsers = (0, vue.computed)(() => {
3554
4321
  const userGroupOptions = filteredUserGroup.value.map((group) => ({
3555
4322
  ...group,
3556
4323
  tenantId: "",
@@ -3564,6 +4331,27 @@
3564
4331
  ...virtualUsers
3565
4332
  ];
3566
4333
  });
4334
+ const filteredRecentUsers = (0, vue.computed)(() => {
4335
+ const query = searchQuery.value.trim();
4336
+ return recentUsers.value.filter((user) => !selectedUserIds.value.includes(user.id)).filter((user) => !props.excludeUserIds.includes(user.id)).filter((user) => isUserMatchedByQuery(user, query));
4337
+ });
4338
+ /**
4339
+ * 下拉框显示状态
4340
+ */
4341
+ const showDropdown = (0, vue.computed)(() => {
4342
+ return isFocused.value && (filteredUserGroup.value.length > 0 || filteredRecentUsers.value.length > 0 || searchQuery.value.trim() !== "");
4343
+ });
4344
+ /**
4345
+ * 扁平化的选项列表(合并 userGroup 和 displayOptions,用于键盘导航)
4346
+ * 顺序与 selection-popover.vue 中 groupedUsers 的渲染顺序保持一致:
4347
+ * 用户群组 → 普通用户 → 虚拟账号 → 最近选择
4348
+ */
4349
+ const flatOptions = (0, vue.computed)(() => {
4350
+ return [...mainNavigableUsers.value, ...filteredRecentUsers.value];
4351
+ });
4352
+ /**
4353
+ * 输入框宽度(根据输入内容动态计算)
4354
+ */
3567
4355
  const inputWidth = (0, vue.computed)(() => {
3568
4356
  const query = searchQuery.value;
3569
4357
  if (!query) return "20px";
@@ -3572,6 +4360,9 @@
3572
4360
  }, 0);
3573
4361
  return `${Math.max(20, charWidth + 4)}px`;
3574
4362
  });
4363
+ /**
4364
+ * 初始化已选用户数据
4365
+ */
3575
4366
  const initSelectedUsers = async () => {
3576
4367
  const ids = modelValueIds.value;
3577
4368
  if (ids.length === 0) {
@@ -3585,26 +4376,43 @@
3585
4376
  type: USER_TYPE.USER_GROUP
3586
4377
  }));
3587
4378
  try {
3588
- const result = await lookupUsers({
3589
- apiBaseUrl: props.apiBaseUrl,
3590
- tenantId: props.tenantId,
3591
- exactSearchKey: "bk_username",
3592
- usersList: ids,
3593
- enableMultiTenantMode: props.enableMultiTenantMode
3594
- });
3595
- const selectedList = [...userGroupSelected, ...formatUsers(result, props.enableMultiTenantMode)];
3596
- if (props.allowCreate) selectedList.push(...ids.filter((id) => !selectedList.some((user) => user.id === id)).map((id) => ({
3597
- id,
3598
- name: id,
3599
- type: USER_TYPE.CUSTOM,
3600
- tenantId: ""
3601
- })));
3602
- selectedUsers.value = ids.map((id) => selectedList.find((user) => user.id === id)).filter(Boolean);
4379
+ const selectedList = [...userGroupSelected, ...await lookupFormattedUsersByIds(ids)];
4380
+ if (props.allowCreate) {
4381
+ const lookupFields = [...new Set([...getLookupFields(props.exactSearchKey), DEFAULT_EXACT_SEARCH_KEY])];
4382
+ selectedList.push(...ids.filter((id) => !findUserByLookupId(selectedList, id, lookupFields)).map((id) => ({
4383
+ id,
4384
+ name: id,
4385
+ type: USER_TYPE.CUSTOM,
4386
+ tenantId: ""
4387
+ })));
4388
+ }
4389
+ selectedUsers.value = sortUsersByLookupIds(selectedList, ids, [...new Set([...getLookupFields(props.exactSearchKey), DEFAULT_EXACT_SEARCH_KEY])]);
3603
4390
  } catch (error) {
3604
4391
  console.error("获取选中用户信息失败:", error);
3605
4392
  selectedUsers.value = [];
3606
4393
  }
3607
4394
  };
4395
+ const initRecentUsers = async () => {
4396
+ const ids = props.recentUserIds.filter(Boolean);
4397
+ const requestId = ++recentUsersRequestId;
4398
+ recentUserIdsSnapshot = [...ids];
4399
+ if (ids.length === 0) {
4400
+ recentUsers.value = [];
4401
+ return;
4402
+ }
4403
+ try {
4404
+ const formattedUsers = (await lookupFormattedUsersByIds(ids)).filter((user) => user.data_source_type !== USER_TYPE.VIRTUAL && user.type !== USER_TYPE.USER_GROUP);
4405
+ if (requestId !== recentUsersRequestId) return;
4406
+ recentUsers.value = formattedUsers;
4407
+ } catch (error) {
4408
+ if (requestId !== recentUsersRequestId) return;
4409
+ console.error("获取最近选择用户信息失败:", error);
4410
+ recentUsers.value = [];
4411
+ }
4412
+ };
4413
+ /**
4414
+ * 更新选中用户并触发事件
4415
+ */
3608
4416
  function updateSelectedUsers(users) {
3609
4417
  selectedUsers.value = users;
3610
4418
  if (props.multiple) {
@@ -3616,6 +4424,9 @@
3616
4424
  emit("change", user);
3617
4425
  }
3618
4426
  }
4427
+ /**
4428
+ * 初始化排序功能
4429
+ */
3619
4430
  const initSortable = () => {
3620
4431
  if (!props.draggable || !props.multiple || !sortableContainerRef.value) return;
3621
4432
  if (sortableInstance.value) sortableInstance.value.destroy();
@@ -3636,6 +4447,9 @@
3636
4447
  }
3637
4448
  });
3638
4449
  };
4450
+ /**
4451
+ * 计算可见用户
4452
+ */
3639
4453
  const calculateVisibleUsers = () => {
3640
4454
  if (!selectedUsers.value.length) {
3641
4455
  visibleUsers.value = [];
@@ -3659,18 +4473,24 @@
3659
4473
  visibleUsers.value = selectedUsers.value.slice(0, visibleCount);
3660
4474
  hiddenCount.value = Math.max(0, selectedUsers.value.length - visibleCount);
3661
4475
  };
4476
+ /**
4477
+ * 处理聚焦
4478
+ */
3662
4479
  const handleFocus = () => {
3663
4480
  isFocused.value = true;
3664
4481
  activeTagIndex.value = selectedUsers.value.length - 1;
3665
4482
  (0, vue.nextTick)(() => focusCurrentInput());
3666
4483
  };
4484
+ /**
4485
+ * 延迟计算可见用户
4486
+ */
3667
4487
  const scheduleVisibleUsersCalculation = () => {
3668
4488
  if (!isFocused.value) (0, vue.nextTick)(calculateVisibleUsers);
3669
4489
  };
3670
- const handleClickOutside = (event) => {
3671
- const target = event.target;
3672
- const container = containerRef.value;
3673
- if (container?.contains(target) || container === target) return;
4490
+ /**
4491
+ * 主动失焦(供外部调用或内部复用)
4492
+ */
4493
+ const blur = () => {
3674
4494
  if (isFocused.value) emit("blur");
3675
4495
  isFocused.value = false;
3676
4496
  activeTagIndex.value = selectedUsers.value.length - 1;
@@ -3678,26 +4498,56 @@
3678
4498
  highlightedIndex.value = -1;
3679
4499
  scheduleVisibleUsersCalculation();
3680
4500
  };
4501
+ /**
4502
+ * 处理失焦
4503
+ */
4504
+ const handleClickOutside = (event) => {
4505
+ const target = event.target;
4506
+ const container = containerRef.value;
4507
+ if (container?.contains(target) || container === target) return;
4508
+ blur();
4509
+ };
4510
+ /**
4511
+ * 处理容器点击
4512
+ */
3681
4513
  const handleContainerClick = () => {
3682
4514
  activeTagIndex.value = selectedUsers.value.length - 1;
3683
4515
  (0, vue.nextTick)(() => focusCurrentInput());
3684
4516
  };
4517
+ /**
4518
+ * 聚焦当前光标位置的输入框
4519
+ * activeTagIndex 语义:
4520
+ * -1 = 最前面(第一个标签之前)
4521
+ * 0 ~ length-1 = 对应标签后面
4522
+ */
3685
4523
  const focusCurrentInput = () => {
3686
4524
  if (activeTagIndex.value === -1 && selectedUsers.value.length > 0) frontInputRef.value?.focus();
3687
4525
  else if (activeTagIndex.value >= selectedUsers.value.length - 1) lastInputRef.value?.focus();
3688
4526
  else inlineInputRef.value?.[0]?.focus();
3689
4527
  };
4528
+ /**
4529
+ * 处理标签点击
4530
+ */
3690
4531
  const handleTagClick = (index) => {
3691
4532
  activeTagIndex.value = index;
3692
4533
  (0, vue.nextTick)(() => focusCurrentInput());
3693
4534
  };
4535
+ /**
4536
+ * 处理输入框聚焦
4537
+ */
3694
4538
  const handleInputFocus = () => {
3695
4539
  emit("focus");
3696
4540
  isFocused.value = true;
3697
4541
  };
4542
+ /**
4543
+ * 处理输入变化
4544
+ */
3698
4545
  const handleInput = () => {
3699
4546
  handleSearchInput(searchQuery.value);
3700
4547
  };
4548
+ /**
4549
+ * 添加当前用户("我")
4550
+ */
3701
4551
  const addCurrentUser = async () => {
3702
4552
  if (!props.currentUserId || selectedUsers.value.some((user) => user[props.exactSearchKey] === props.currentUserId)) return;
3703
4553
  if (props.multiple && isMaxCountReached.value) return;
@@ -3712,11 +4562,17 @@
3712
4562
  (0, vue.nextTick)(() => focusCurrentInput());
3713
4563
  }
3714
4564
  };
4565
+ /**
4566
+ * 处理粘贴事件
4567
+ */
3715
4568
  const onPaste = async (event) => {
3716
4569
  await handlePaste(event);
3717
4570
  activeTagIndex.value = selectedUsers.value.length - 1;
3718
4571
  (0, vue.nextTick)(() => focusCurrentInput());
3719
4572
  };
4573
+ /**
4574
+ * 处理键盘事件
4575
+ */
3720
4576
  const handleKeyDown = (event) => {
3721
4577
  if (event.key === "Backspace" && !searchQuery.value && selectedUsers.value.length > 0) {
3722
4578
  if (activeTagIndex.value >= 0) {
@@ -3760,6 +4616,12 @@
3760
4616
  return;
3761
4617
  }
3762
4618
  };
4619
+ /**
4620
+ * 添加用户
4621
+ * activeTagIndex 语义:
4622
+ * -1 = 在最前面插入
4623
+ * 0 ~ length-1 = 在对应标签后面插入
4624
+ */
3763
4625
  function addUser(user) {
3764
4626
  if (!user?.id) return;
3765
4627
  if (props.multiple && isMaxCountReached.value) {
@@ -3792,6 +4654,9 @@
3792
4654
  isFocused.value = true;
3793
4655
  (0, vue.nextTick)(() => focusCurrentInput());
3794
4656
  }
4657
+ /**
4658
+ * 移除用户(通过 x 按钮删除)
4659
+ */
3795
4660
  const removeUser = (user) => {
3796
4661
  if (!user?.id) return;
3797
4662
  const removedIndex = selectedUsers.value.findIndex((item) => item.id === user.id);
@@ -3802,9 +4667,15 @@
3802
4667
  else if (activeTagIndex.value >= updatedUsers.length) activeTagIndex.value = updatedUsers.length - 1;
3803
4668
  scheduleVisibleUsersCalculation();
3804
4669
  };
4670
+ /**
4671
+ * 监听选中用户变化
4672
+ */
3805
4673
  (0, vue.watch)(selectedUsers, () => {
3806
4674
  scheduleVisibleUsersCalculation();
3807
4675
  }, { deep: true });
4676
+ /**
4677
+ * 监听聚焦状态变化
4678
+ */
3808
4679
  (0, vue.watch)(isFocused, (newVal) => {
3809
4680
  if (isTextareaMode.value) {
3810
4681
  const prevContainer = newVal ? collapsedContainerRef.value : containerRef.value?.querySelector(".tags-container.focused");
@@ -3812,35 +4683,73 @@
3812
4683
  }
3813
4684
  if (newVal) (0, vue.nextTick)(() => initSortable());
3814
4685
  });
4686
+ /**
4687
+ * 监听 flatOptions 变化,重置高亮索引到第一项
4688
+ */
3815
4689
  (0, vue.watch)(flatOptions, (newOptions) => {
3816
4690
  if (newOptions.length > 0 && showDropdown.value) highlightedIndex.value = 0;
3817
4691
  else highlightedIndex.value = -1;
3818
4692
  });
4693
+ /**
4694
+ * 监听用户群组变化
4695
+ */
3819
4696
  (0, vue.watch)(() => props.userGroup, () => {
3820
4697
  initSelectedUsers();
3821
4698
  });
4699
+ (0, vue.watch)(() => props.recentUserIds, () => {
4700
+ const newIds = props.recentUserIds.filter(Boolean);
4701
+ if (recentUserIdsSnapshot.length === newIds.length && recentUserIdsSnapshot.every((id, index) => id === newIds[index])) return;
4702
+ initRecentUsers();
4703
+ }, { deep: true });
4704
+ /**
4705
+ * 监听 modelValue 变化
4706
+ */
3822
4707
  (0, vue.watch)(() => props.modelValue, () => {
3823
4708
  const currentIds = selectedUsers.value.map((u) => u.id);
3824
4709
  const newIds = modelValueIds.value;
3825
4710
  if (currentIds.length !== newIds.length || !currentIds.every((id, index) => id === newIds[index])) initSelectedUsers();
3826
4711
  }, { deep: true });
4712
+ /**
4713
+ * 使用 ResizeObserver 监听容器大小变化
4714
+ */
3827
4715
  useResizeObserver(containerRef, () => {
3828
4716
  scheduleVisibleUsersCalculation();
3829
4717
  });
4718
+ let initPromise;
4719
+ /**
4720
+ * 组件挂载前初始化
4721
+ */
3830
4722
  (0, vue.onBeforeMount)(() => {
3831
- initSelectedUsers();
4723
+ initPromise = Promise.all([initSelectedUsers(), initRecentUsers()]).then(() => void 0);
3832
4724
  });
3833
- (0, vue.onMounted)(() => {
4725
+ /**
4726
+ * 组件挂载后初始化
4727
+ */
4728
+ (0, vue.onMounted)(async () => {
3834
4729
  initSortable();
3835
4730
  (0, vue.nextTick)(calculateVisibleUsers);
4731
+ if (props.autoFocus && !props.disabled) {
4732
+ await initPromise;
4733
+ await (0, vue.nextTick)();
4734
+ handleFocus();
4735
+ }
3836
4736
  });
4737
+ /**
4738
+ * 组件卸载前清理
4739
+ */
3837
4740
  (0, vue.onUnmounted)(() => {
3838
4741
  sortableInstance.value?.destroy();
3839
4742
  });
4743
+ __expose({
4744
+ focus: handleFocus,
4745
+ blur
4746
+ });
3840
4747
  const __returned__ = {
3841
4748
  t,
3842
4749
  props,
3843
4750
  emit,
4751
+ handleApiError,
4752
+ handleApiUnauthorized,
3844
4753
  tenants,
3845
4754
  searchResults,
3846
4755
  searchLoading,
@@ -3860,17 +4769,35 @@
3860
4769
  visibleUsers,
3861
4770
  hiddenCount,
3862
4771
  highlightedIndex,
4772
+ recentUsers,
4773
+ get recentUsersRequestId() {
4774
+ return recentUsersRequestId;
4775
+ },
4776
+ set recentUsersRequestId(v) {
4777
+ recentUsersRequestId = v;
4778
+ },
4779
+ get recentUserIdsSnapshot() {
4780
+ return recentUserIdsSnapshot;
4781
+ },
4782
+ set recentUserIdsSnapshot(v) {
4783
+ recentUserIdsSnapshot = v;
4784
+ },
3863
4785
  selectedUsers,
3864
4786
  isTextareaMode,
3865
4787
  textareaHeight,
3866
4788
  textareaStyle,
3867
4789
  collapsedDisplayUsers,
3868
- showDropdown,
3869
4790
  modelValueIds,
3870
4791
  computedPlaceholder,
3871
4792
  computedUserGroupName,
3872
4793
  computedEmptyText,
4794
+ computedRecentUsersName,
3873
4795
  selectedUserIds,
4796
+ isUserMatchedByQuery,
4797
+ getLookupFields,
4798
+ findUserByLookupId,
4799
+ sortUsersByLookupIds,
4800
+ lookupFormattedUsersByIds,
3874
4801
  isMaxCountReached,
3875
4802
  isMeTagDisabled,
3876
4803
  userTagCommonProps,
@@ -3879,14 +4806,19 @@
3879
4806
  createCustomUser,
3880
4807
  handlePaste,
3881
4808
  displayOptions,
4809
+ mainNavigableUsers,
4810
+ filteredRecentUsers,
4811
+ showDropdown,
3882
4812
  flatOptions,
3883
4813
  inputWidth,
3884
4814
  initSelectedUsers,
4815
+ initRecentUsers,
3885
4816
  updateSelectedUsers,
3886
4817
  initSortable,
3887
4818
  calculateVisibleUsers,
3888
4819
  handleFocus,
3889
4820
  scheduleVisibleUsersCalculation,
4821
+ blur,
3890
4822
  handleClickOutside,
3891
4823
  handleContainerClick,
3892
4824
  focusCurrentInput,
@@ -3898,6 +4830,12 @@
3898
4830
  handleKeyDown,
3899
4831
  addUser,
3900
4832
  removeUser,
4833
+ get initPromise() {
4834
+ return initPromise;
4835
+ },
4836
+ set initPromise(v) {
4837
+ initPromise = v;
4838
+ },
3901
4839
  get Popover() {
3902
4840
  return bkui_vue.Popover;
3903
4841
  },
@@ -3918,6 +4856,8 @@
3918
4856
  return __returned__;
3919
4857
  }
3920
4858
  });
4859
+ //#endregion
4860
+ //#region src/components/user-selector.vue
3921
4861
  var _hoisted_1 = {
3922
4862
  ref: "sortableContainerRef",
3923
4863
  class: "tag-list"
@@ -3942,6 +4882,8 @@
3942
4882
  "is-show": $setup.showDropdown,
3943
4883
  loading: $setup.searchLoading,
3944
4884
  options: $setup.displayOptions,
4885
+ "recent-users": $setup.filteredRecentUsers,
4886
+ "recent-users-name": $setup.computedRecentUsersName,
3945
4887
  "render-list-item": $props.renderListItem,
3946
4888
  "search-query": $setup.searchQuery,
3947
4889
  "tenant-id": $props.tenantId,
@@ -4093,6 +5035,8 @@
4093
5035
  "is-show",
4094
5036
  "loading",
4095
5037
  "options",
5038
+ "recent-users",
5039
+ "recent-users-name",
4096
5040
  "render-list-item",
4097
5041
  "search-query",
4098
5042
  "tenant-id",
@@ -4101,12 +5045,15 @@
4101
5045
  "user-group-name"
4102
5046
  ])], 2);
4103
5047
  }
4104
- var user_selector_default = /* @__PURE__ */ __plugin_vue_export_helper_default(user_selector_vue_vue_type_script_setup_true_lang_default, [
5048
+ var user_selector_default = /* @__PURE__ */ _plugin_vue_export_helper_default(user_selector_vue_vue_type_script_setup_true_lang_default, [
4105
5049
  ["render", _sfc_render],
4106
5050
  ["__scopeId", "data-v-089550be"],
4107
5051
  ["__file", "/Users/brooklin/project/bkui-monorepo/packages/bk-user-selector/src/components/user-selector.vue"]
4108
5052
  ]);
5053
+ //#endregion
5054
+ //#region src/vue3.ts
4109
5055
  var vue3_default = user_selector_default;
5056
+ //#endregion
4110
5057
  exports.BkUserSelector = user_selector_default;
4111
5058
  exports.default = vue3_default;
4112
5059
  });