@deot/vc-components 1.0.46 → 1.0.48

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.
@@ -92,6 +92,38 @@
92
92
 
93
93
  const MActionSheet = ActionSheet;
94
94
 
95
+ const props$1s = {
96
+ modelValue: {
97
+ type: Boolean,
98
+ default: false
99
+ },
100
+ zIndex: {
101
+ type: [Number, String],
102
+ default: 1
103
+ },
104
+ // TODO: left/right
105
+ placement: {
106
+ type: String,
107
+ default: "top"
108
+ },
109
+ disabled: {
110
+ type: Boolean,
111
+ default: false
112
+ },
113
+ fixed: {
114
+ type: Boolean,
115
+ default: true
116
+ },
117
+ offset: {
118
+ type: Number,
119
+ default: 0
120
+ },
121
+ // -> 固钉始终保持在容器内, 超过范围则隐藏(请注意容器避免出现滚动条) 仅fixed为true有效
122
+ target: {
123
+ type: String
124
+ }
125
+ };
126
+
95
127
  const IS_SERVER$3 = typeof window === "undefined";
96
128
 
97
129
  const hasClass = (el, cls) => {
@@ -189,7 +221,7 @@
189
221
  return !!(overflow.match(/(scroll|auto)/) || className?.test(el.className));
190
222
  };
191
223
 
192
- const getScroller = (el, options) => {
224
+ const getScroller$1 = (el, options) => {
193
225
  if (IS_SERVER$3 || !el) return null;
194
226
  let parent = el;
195
227
  while (parent) {
@@ -308,44 +340,45 @@
308
340
  return target;
309
341
  };
310
342
 
311
- const props$1s = {
312
- zIndex: {
313
- type: [Number, String],
314
- default: 1
315
- },
316
- // TODO: left/right
317
- placement: {
318
- type: String,
319
- default: "top"
320
- },
321
- disabled: {
322
- type: Boolean,
323
- default: false
324
- },
325
- fixed: {
326
- type: Boolean,
327
- default: true
328
- },
329
- offset: {
330
- type: Number,
331
- default: 0
332
- },
333
- // -> 固钉始终保持在容器内, 超过范围则隐藏(请注意容器避免出现滚动条) 仅fixed为true有效
334
- target: {
335
- type: String
336
- }
343
+ let scrollBarWidth;
344
+ const getScrollBarWidth = () => {
345
+ if (scrollBarWidth !== void 0) return scrollBarWidth;
346
+ const outer = document.createElement("div");
347
+ outer.className = "vc-scrollbar__wrap";
348
+ outer.style.visibility = "hidden";
349
+ outer.style.width = "100px";
350
+ outer.style.position = "absolute";
351
+ outer.style.top = "-9999px";
352
+ document.body.appendChild(outer);
353
+ const widthNoScroll = outer.offsetWidth;
354
+ outer.style.overflow = "scroll";
355
+ const inner = document.createElement("div");
356
+ inner.style.width = "100%";
357
+ outer.appendChild(inner);
358
+ const widthWithScroll = inner.offsetWidth;
359
+ outer.parentNode?.removeChild?.(outer);
360
+ scrollBarWidth = widthNoScroll - widthWithScroll;
361
+ return scrollBarWidth;
362
+ };
363
+ const SCROLLER_WHEEL_REG = /vc-scroller-wheel/;
364
+ const getScroller = (el) => {
365
+ return getScroller$1(el, { className: SCROLLER_WHEEL_REG });
366
+ };
367
+ const isWheel = (el) => {
368
+ return SCROLLER_WHEEL_REG.test(el?.className || "");
337
369
  };
338
370
 
339
371
  /** @jsxImportSource vue */
340
372
 
341
373
  const COMPONENT_NAME$27 = 'vc-affix';
342
- const SCROLLER_WHEEL_REG = /vc-scroller-wheel/;
343
374
  const Affix = /* @__PURE__ */ vue.defineComponent({
344
375
  name: COMPONENT_NAME$27,
376
+ emits: ['update:modelValue'],
345
377
  props: props$1s,
346
378
  setup(props, {
347
379
  slots,
348
- expose
380
+ expose,
381
+ emit
349
382
  }) {
350
383
  const scrollerInstance = vue.inject('vc-scroller', null);
351
384
  const scroller = vue.shallowRef(); // 当前元素所在的滚动容器
@@ -361,9 +394,7 @@
361
394
  const isActive = vue.ref(false);
362
395
  const transformY = vue.ref(0);
363
396
  const windowHeight = vue.ref(window.innerHeight);
364
- const isVcScrollerWheel = vue.computed(() => {
365
- return SCROLLER_WHEEL_REG.test(scroller.value?.className || '');
366
- });
397
+ const isVcScrollerWheel = vue.computed(() => isWheel(scroller.value));
367
398
  const currentStyle = vue.computed(() => {
368
399
  if (!isActive.value) return {};
369
400
  return {
@@ -384,7 +415,8 @@
384
415
  };
385
416
  });
386
417
  const setCurrentRect = () => {
387
- const rect = current.value.getBoundingClientRect();
418
+ const rect = current.value?.getBoundingClientRect?.();
419
+ if (!rect) return;
388
420
  Object.assign(currentRect, {
389
421
  top: rect.top,
390
422
  bottom: rect.bottom,
@@ -411,7 +443,7 @@
411
443
  transformY.value = Math.min(containerRect.bottom - currentHeightOffset, 0) + transformOffsetY;
412
444
  } else {
413
445
  isActive.value = currentRect.bottom - containerRect.top >= containerRect.height - props.offset;
414
- transformY.value = Math.max(containerRect.height - containerRect.top - currentHeightOffset, 0) + transformOffsetY;
446
+ transformY.value = transformOffsetY;
415
447
  }
416
448
  };
417
449
  const setFixedStatus = () => {
@@ -438,36 +470,58 @@
438
470
  }
439
471
  }
440
472
  };
473
+ const offScroll = handler => {
474
+ if (isVcScrollerWheel.value) {
475
+ scrollerInstance?.off(handler);
476
+ } else {
477
+ scroller.value?.removeEventListener('scroll', handler);
478
+ }
479
+ };
480
+ const onScroll = (handler, options) => {
481
+ // nextTick目的在与onMounted后执行
482
+ vue.nextTick(() => {
483
+ if (isVcScrollerWheel.value) {
484
+ scrollerInstance?.on(handler);
485
+ } else {
486
+ scroller.value?.addEventListener('scroll', handler);
487
+ }
488
+ options?.first && handler();
489
+ });
490
+ return () => offScroll(handler);
491
+ };
441
492
  const refresh = () => {
493
+ if (props.disabled) return;
442
494
  setCurrentRect();
443
495
  scroller.value instanceof Window || props.fixed ? setFixedStatus() : setAbsoluteStatus();
496
+ emit('update:modelValue', isActive.value);
444
497
  };
445
498
  vue.onMounted(() => {
446
499
  if (typeof props.target === 'string') {
447
500
  base.value = document.querySelector(props.target) ?? void 0;
448
501
  }
449
502
  !base.value && (base.value = document.documentElement);
450
- scroller.value = getScroller(current.value, {
451
- className: SCROLLER_WHEEL_REG
503
+ scroller.value = getScroller(current.value);
504
+ onScroll(refresh, {
505
+ first: true
452
506
  });
453
- if (isVcScrollerWheel.value) {
454
- scrollerInstance?.on(refresh);
455
- } else {
456
- scroller.value?.addEventListener('scroll', refresh);
457
- }
458
- refresh();
459
- });
460
- vue.onBeforeUnmount(() => {
461
- if (isVcScrollerWheel.value) {
462
- scrollerInstance?.off(refresh);
463
- } else {
464
- scroller.value?.removeEventListener('scroll', refresh);
465
- }
466
507
  });
508
+ vue.onBeforeUnmount(() => offScroll(refresh));
467
509
  expose({
468
- refresh
510
+ refresh,
511
+ onScroll,
512
+ offScroll
513
+ });
514
+ vue.provide('vc-affix', {
515
+ props,
516
+ isActive,
517
+ refresh,
518
+ onScroll,
519
+ offScroll
469
520
  });
470
521
  return () => {
522
+ if (props.disabled) return slots?.default?.({
523
+ active: false
524
+ });
471
525
  return vue.createVNode("div", {
472
526
  "ref": current,
473
527
  "class": "vc-affix",
@@ -9281,7 +9335,8 @@
9281
9335
  nullValue: {
9282
9336
  type: [Number, String, Object],
9283
9337
  default: void 0
9284
- }
9338
+ },
9339
+ label: String
9285
9340
  };
9286
9341
 
9287
9342
  const props$18 = {
@@ -14393,27 +14448,6 @@
14393
14448
  }
14394
14449
  };
14395
14450
 
14396
- let scrollBarWidth;
14397
- const getScrollBarWidth = () => {
14398
- if (scrollBarWidth !== void 0) return scrollBarWidth;
14399
- const outer = document.createElement("div");
14400
- outer.className = "vc-scrollbar__wrap";
14401
- outer.style.visibility = "hidden";
14402
- outer.style.width = "100px";
14403
- outer.style.position = "absolute";
14404
- outer.style.top = "-9999px";
14405
- document.body.appendChild(outer);
14406
- const widthNoScroll = outer.offsetWidth;
14407
- outer.style.overflow = "scroll";
14408
- const inner = document.createElement("div");
14409
- inner.style.width = "100%";
14410
- outer.appendChild(inner);
14411
- const widthWithScroll = inner.offsetWidth;
14412
- outer.parentNode?.removeChild?.(outer);
14413
- scrollBarWidth = widthNoScroll - widthWithScroll;
14414
- return scrollBarWidth;
14415
- };
14416
-
14417
14451
  const barKeys$1 = [
14418
14452
  "always",
14419
14453
  "thumbMinSize",
@@ -21130,7 +21164,7 @@
21130
21164
  } else if (typeof wrapper === 'string') {
21131
21165
  scroller.value = document.querySelector(wrapper);
21132
21166
  } else {
21133
- scroller.value = getScroller(instance.vnode.el);
21167
+ scroller.value = getScroller$1(instance.vnode.el);
21134
21168
  }
21135
21169
  };
21136
21170
  const initPlaceholder = () => {
@@ -23250,7 +23284,7 @@
23250
23284
  "style": its.value.style,
23251
23285
  "animation": "y",
23252
23286
  "onMouseenter": () => isHover.value = true,
23253
- "onMuseleave": () => isHover.value = false,
23287
+ "onMouseleave": () => isHover.value = false,
23254
23288
  "onReady": () => emit('ready'),
23255
23289
  "onClose": () => emit('close'),
23256
23290
  "onVisibleChange": () => emit('visible-change', isActive.value),
@@ -23266,6 +23300,13 @@
23266
23300
  "readonly": true,
23267
23301
  "placeholder": its.value.attrs?.placeholder || '请选择'
23268
23302
  }, {
23303
+ prepend: slots.prepend || props.label ? () => {
23304
+ slots.prepend ? slots.prepend() : vue.createVNode("div", {
23305
+ "class": "vc-select__prepend"
23306
+ }, [vue.createVNode("span", {
23307
+ "class": "vc-select__label"
23308
+ }, [props.label])]);
23309
+ } : null,
23269
23310
  content: multiple.value && currentValue.value && currentValue.value.length > 0 ? () => {
23270
23311
  return vue.createVNode("div", {
23271
23312
  "class": [classes.value, 'vc-select__tags']
@@ -23287,7 +23328,7 @@
23287
23328
  }, [vue.createVNode(Icon, {
23288
23329
  "type": showClear.value ? 'clear' : icon.value,
23289
23330
  "class": [{
23290
- 'is-arrow': !showClear
23331
+ 'is-arrow': !showClear.value
23291
23332
  }, 'vc-select__icon'],
23292
23333
  "onClick": handleClear
23293
23334
  }, null)]);
@@ -29021,10 +29062,13 @@
29021
29062
  barStyle: [Object, String],
29022
29063
  contentStyle: [Object, String],
29023
29064
  barClass: [Object, String],
29024
- contentClass: [Object, String]
29065
+ contentClass: [Object, String],
29066
+ affixable: Boolean,
29067
+ affixOptions: Object
29025
29068
  };
29026
29069
 
29027
29070
  const useTabs = (options = {}) => {
29071
+ const affix = vue.inject("vc-affix", null);
29028
29072
  const instance = vue.getCurrentInstance();
29029
29073
  const { props, emit } = instance;
29030
29074
  const tabsId = vue.ref(getUid("tabs"));
@@ -29066,10 +29110,56 @@
29066
29110
  [`is-${props.theme}`]: !!props.theme
29067
29111
  };
29068
29112
  });
29113
+ const hasAnchor = vue.computed(() => {
29114
+ return list.value.some((item) => !!item.anchor);
29115
+ });
29069
29116
  const refresh = () => {
29070
29117
  options?.refreshAfloat?.();
29071
29118
  };
29072
- const handleChange = (index) => {
29119
+ let scrollToAnchorTimer;
29120
+ const scrollToAnchor = (anchor) => {
29121
+ if (!anchor) return;
29122
+ const el = document.querySelector(anchor);
29123
+ if (!el) return;
29124
+ const scroller = getScroller(instance.vnode.el);
29125
+ scrollIntoView(scroller, {
29126
+ duration: 250,
29127
+ from: scroller.scrollTop,
29128
+ to: scroller.scrollTop + el.getBoundingClientRect().top - scroller.getBoundingClientRect().top - (!affix || affix.props.placement !== "bottom" ? instance.vnode.el.offsetHeight : 0) - (affix && affix.props.placement !== "bottom" ? affix.props.offset : 0)
29129
+ });
29130
+ scrollToAnchorTimer && clearTimeout(scrollToAnchorTimer);
29131
+ scrollToAnchorTimer = setTimeout(() => scrollToAnchorTimer = null, 300);
29132
+ };
29133
+ const handleAffixScroll = () => {
29134
+ if (!hasAnchor.value || scrollToAnchorTimer) return;
29135
+ const scroller = getScroller(instance.vnode.el);
29136
+ const scrollTop = scroller?.scrollTop;
29137
+ if (typeof scrollTop !== "number") return;
29138
+ for (let i = 0; i < list.value.length; i++) {
29139
+ const nav = list.value[i];
29140
+ const anchor = nav.anchor;
29141
+ if (!anchor) continue;
29142
+ const el = document.querySelector(anchor);
29143
+ if (!el) continue;
29144
+ const elTop = el.getBoundingClientRect().top - scroller.getBoundingClientRect().top + scroller.scrollTop;
29145
+ const nextNav = list.value[i + 1];
29146
+ let nextElTop;
29147
+ if (nextNav && nextNav.anchor) {
29148
+ const nextEl = document.querySelector(nextNav.anchor);
29149
+ if (nextEl) {
29150
+ nextElTop = nextEl.getBoundingClientRect().top - scroller.getBoundingClientRect().top + scroller.scrollTop;
29151
+ }
29152
+ }
29153
+ const allowDistance = 2;
29154
+ if (scrollTop >= elTop - allowDistance && (typeof nextElTop === "undefined" || scrollTop < nextElTop - allowDistance)) {
29155
+ if (getTabIndex(currentValue.value) !== i) {
29156
+ handleChange(i, false);
29157
+ }
29158
+ break;
29159
+ }
29160
+ }
29161
+ };
29162
+ const handleChange = (index, scrollTo = true) => {
29073
29163
  if (timer.value) return;
29074
29164
  timer.value = setTimeout(() => timer.value = null, 300);
29075
29165
  const nav = list.value[index];
@@ -29078,7 +29168,7 @@
29078
29168
  emit("update:modelValue", currentValue.value);
29079
29169
  emit("change", currentValue.value);
29080
29170
  emit("click", currentValue.value);
29081
- nav.anchor && document.querySelector(nav.anchor)?.scrollIntoView?.({ behavior: "smooth" });
29171
+ scrollTo && scrollToAnchor(nav.anchor);
29082
29172
  };
29083
29173
  const handleResize = () => {
29084
29174
  if (instance.isUnmounted) return;
@@ -29088,10 +29178,13 @@
29088
29178
  vue.onMounted(() => {
29089
29179
  Resize.on(options.wrapper.value, handleResize);
29090
29180
  options.scrollToActive && vue.nextTick(options.scrollToActive);
29181
+ affix?.onScroll?.(handleAffixScroll);
29091
29182
  });
29092
29183
  vue.onBeforeUnmount(() => {
29093
29184
  Resize.off(options.wrapper.value, handleResize);
29094
29185
  timer.value && clearTimeout(timer.value);
29186
+ affix?.offScroll?.(handleAffixScroll);
29187
+ scrollToAnchorTimer && clearTimeout(scrollToAnchorTimer);
29095
29188
  });
29096
29189
  const add = (item, setValue) => {
29097
29190
  if (!item) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deot/vc-components",
3
- "version": "1.0.46",
3
+ "version": "1.0.48",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",