@holyer-lib/ui 0.0.9 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ui.cjs.js CHANGED
@@ -14,7 +14,319 @@ function __$styleInject(css) {
14
14
  return css;
15
15
  }
16
16
 
17
- function __$styleInject(css) {
17
+ function __$styleInject$2(css) {
18
+ if (!css) return;
19
+
20
+ if (typeof window == 'undefined') return;
21
+ var style = document.createElement('style');
22
+ style.setAttribute('media', 'screen');
23
+
24
+ style.innerHTML = css;
25
+ document.head.appendChild(style);
26
+ return css;
27
+ }
28
+
29
+ __$styleInject$2(".hi-expand-text {\n display: flex;\n width: 100%;\n line-height: 1.5;\n}\n.hi-expand-text--content {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n overflow: hidden;\n text-overflow: ellipsis;\n word-break: break-word;\n -webkit-line-clamp: var(--hi-expand-text-line-clamp);\n line-clamp: var(--hi-expand-text-line-clamp);\n}\n.hi-expand-text--content.hi-expand-text--content__show-toggle::before {\n content: '';\n float: right;\n height: 100%;\n margin-bottom: calc(-1em * 1.5);\n}\n.hi-expand-text--content__expanded {\n display: block;\n overflow: visible;\n -webkit-line-clamp: unset;\n line-clamp: unset;\n}\n.hi-expand-text--toggle {\n color: var(--td-brand-color);\n float: right;\n clear: both;\n cursor: pointer;\n}\n");
30
+
31
+ //
32
+
33
+ var script$2 = {
34
+ name: 'HiExpandText',
35
+ props: {
36
+ content: {
37
+ type: String,
38
+ default: ''
39
+ },
40
+
41
+ /**
42
+ * [0]: 展开时显示的文本,[1]: 收起时显示的文本
43
+ */
44
+ label: {
45
+ type: Array,
46
+ default: () => ['展开', '收起'],
47
+ validator: arr => {
48
+ return arr.length === 2 && arr.every(s => typeof s === 'string');
49
+ }
50
+ },
51
+
52
+ lineClamp: {
53
+ type: Number,
54
+ default: 2
55
+ }
56
+ },
57
+ data() {
58
+ return {
59
+ showToggle: false,
60
+ isExpanded: false,
61
+ resizeTimer: null,
62
+ resizeObserver: null
63
+ };
64
+ },
65
+ computed: {
66
+ expandText() {
67
+ return this.isExpanded ? this.label[1] : this.label[0];
68
+ },
69
+
70
+ textClass() {
71
+ return {
72
+ 'hi-expand-text--content': true,
73
+ 'hi-expand-text--content__show-toggle': this.showToggle,
74
+ 'hi-expand-text--content__expanded': this.isExpanded
75
+ };
76
+ }
77
+ },
78
+
79
+ watch: {
80
+ content() {
81
+ this.$nextTick(this.checkEllipsis);
82
+ }
83
+ },
84
+ mounted() {
85
+ this.checkEllipsis();
86
+ window.addEventListener('resize', this.handleResize);
87
+ if (window.ResizeObserver && this.$el) {
88
+ this.resizeObserver = new ResizeObserver(() => {
89
+ this.handleResize();
90
+ });
91
+ this.resizeObserver.observe(this.$el);
92
+ }
93
+ },
94
+ beforeDestroy() {
95
+ window.removeEventListener('resize', this.handleResize);
96
+ if (this.resizeObserver) this.resizeObserver.disconnect();
97
+ if (this.resizeTimer) clearTimeout(this.resizeTimer);
98
+ },
99
+
100
+ methods: {
101
+ handleResize() {
102
+ if (this.resizeTimer) clearTimeout(this.resizeTimer);
103
+ this.resizeTimer = setTimeout(() => {
104
+ this.checkEllipsis();
105
+ }, 100);
106
+ },
107
+
108
+ /**
109
+ * @Description 检查是否存在溢出情况,兼容展开和收起两种状态
110
+ * @Author holyer
111
+ * @Date 2026/02/08 17:01:51
112
+ */
113
+ checkEllipsis() {
114
+ const textEl = this.$refs.textRef;
115
+ if (!textEl || !textEl.offsetParent) {
116
+ this.showToggle = false;
117
+ return;
118
+ }
119
+
120
+ if (this.isExpanded) {
121
+ // 展开状态下:模拟收起状态,检测是否需要 toggle
122
+ this.showToggle = this.wouldOverflowIfCollapsed(textEl);
123
+ } else {
124
+ // 收起状态下:直接检测是否溢出
125
+ this.showToggle = textEl.scrollHeight - textEl.clientHeight > 2;
126
+ }
127
+ },
128
+
129
+ /**
130
+ * 模拟收起状态,检测内容是否会溢出
131
+ */
132
+ wouldOverflowIfCollapsed(el) {
133
+ // 1. 保存原始状态
134
+ const originalDisplay = el.style.display;
135
+ const originalWebkitLineClamp = el.style.webkitLineClamp;
136
+ const originalClassList = el.className;
137
+
138
+ try {
139
+ // 2. 临时应用“收起”样式,移除 --expanded 和 --show-toggle
140
+ el.className = 'hi-expand-text--content';
141
+ el.style.display = '-webkit-box';
142
+ el.style.webkitBoxOrient = 'vertical';
143
+ el.style.overflow = 'hidden';
144
+ el.style.webkitLineClamp = this.lineClamp;
145
+
146
+ // 3. 强制 reflow(触发 layout)
147
+ const { scrollHeight, clientHeight } = el;
148
+
149
+ // 4. 判断是否溢出
150
+ return scrollHeight - clientHeight > 2;
151
+ } finally {
152
+ // 5. 恢复原始状态(确保无副作用)
153
+ el.className = originalClassList;
154
+ el.style.display = originalDisplay;
155
+ el.style.webkitLineClamp = originalWebkitLineClamp;
156
+ }
157
+ },
158
+
159
+ handleToggle() {
160
+ this.isExpanded = !this.isExpanded;
161
+ this.$emit('toggle', this.isExpanded);
162
+ },
163
+
164
+ // 供外部手动更新
165
+ update() {
166
+ this.$nextTick(this.checkEllipsis);
167
+ }
168
+ }
169
+ };
170
+
171
+ function normalizeComponent$2(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
172
+ if (typeof shadowMode !== 'boolean') {
173
+ createInjectorSSR = createInjector;
174
+ createInjector = shadowMode;
175
+ shadowMode = false;
176
+ }
177
+ // Vue.extend constructor export interop.
178
+ const options = typeof script === 'function' ? script.options : script;
179
+ // render functions
180
+ if (template && template.render) {
181
+ options.render = template.render;
182
+ options.staticRenderFns = template.staticRenderFns;
183
+ options._compiled = true;
184
+ // functional template
185
+ if (isFunctionalTemplate) {
186
+ options.functional = true;
187
+ }
188
+ }
189
+ // scopedId
190
+ if (scopeId) {
191
+ options._scopeId = scopeId;
192
+ }
193
+ let hook;
194
+ if (moduleIdentifier) {
195
+ // server build
196
+ hook = function (context) {
197
+ // 2.3 injection
198
+ context =
199
+ context || // cached call
200
+ (this.$vnode && this.$vnode.ssrContext) || // stateful
201
+ (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
202
+ // 2.2 with runInNewContext: true
203
+ if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
204
+ context = __VUE_SSR_CONTEXT__;
205
+ }
206
+ // inject component styles
207
+ if (style) {
208
+ style.call(this, createInjectorSSR(context));
209
+ }
210
+ // register component module identifier for async chunk inference
211
+ if (context && context._registeredComponents) {
212
+ context._registeredComponents.add(moduleIdentifier);
213
+ }
214
+ };
215
+ // used by ssr in case component is cached and beforeCreate
216
+ // never gets called
217
+ options._ssrRegister = hook;
218
+ }
219
+ else if (style) {
220
+ hook = shadowMode
221
+ ? function (context) {
222
+ style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
223
+ }
224
+ : function (context) {
225
+ style.call(this, createInjector(context));
226
+ };
227
+ }
228
+ if (hook) {
229
+ if (options.functional) {
230
+ // register for functional component in vue file
231
+ const originalRender = options.render;
232
+ options.render = function renderWithStyleInjection(h, context) {
233
+ hook.call(context);
234
+ return originalRender(h, context);
235
+ };
236
+ }
237
+ else {
238
+ // inject component registration as beforeCreate hook
239
+ const existing = options.beforeCreate;
240
+ options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
241
+ }
242
+ }
243
+ return script;
244
+ }
245
+
246
+ /* script */
247
+ const __vue_script__$2 = script$2;
248
+
249
+ /* template */
250
+ var __vue_render__$2 = function () {
251
+ var _vm = this;
252
+ var _h = _vm.$createElement;
253
+ var _c = _vm._self._c || _h;
254
+ return _c(
255
+ "div",
256
+ {
257
+ staticClass: "hi-expand-text",
258
+ style: { "--hi-expand-text-line-clamp": _vm.lineClamp },
259
+ },
260
+ [
261
+ _c(
262
+ "div",
263
+ { ref: "textRef", class: _vm.textClass },
264
+ [
265
+ _vm.showToggle
266
+ ? _c(
267
+ "div",
268
+ {
269
+ staticClass: "hi-expand-text--toggle",
270
+ on: { click: _vm.handleToggle },
271
+ },
272
+ [
273
+ _vm._t("toggleText", function () {
274
+ return [_vm._v(_vm._s(_vm.expandText))]
275
+ }),
276
+ ],
277
+ 2
278
+ )
279
+ : _vm._e(),
280
+ _vm._v(" "),
281
+ _vm._t("default", function () {
282
+ return [_vm._v(_vm._s(_vm.content))]
283
+ }),
284
+ ],
285
+ 2
286
+ ),
287
+ ]
288
+ )
289
+ };
290
+ var __vue_staticRenderFns__$2 = [];
291
+ __vue_render__$2._withStripped = true;
292
+
293
+ /* style */
294
+ const __vue_inject_styles__$2 = undefined;
295
+ /* scoped */
296
+ const __vue_scope_id__$2 = undefined;
297
+ /* module identifier */
298
+ const __vue_module_identifier__$2 = undefined;
299
+ /* functional template */
300
+ const __vue_is_functional_template__$2 = false;
301
+ /* style inject */
302
+
303
+ /* style inject SSR */
304
+
305
+ /* style inject shadow dom */
306
+
307
+
308
+
309
+ const __vue_component__$2 = /*#__PURE__*/normalizeComponent$2(
310
+ { render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 },
311
+ __vue_inject_styles__$2,
312
+ __vue_script__$2,
313
+ __vue_scope_id__$2,
314
+ __vue_is_functional_template__$2,
315
+ __vue_module_identifier__$2,
316
+ false,
317
+ undefined,
318
+ undefined,
319
+ undefined
320
+ );
321
+
322
+ __vue_component__$2.name = 'HiExpandText';
323
+
324
+ // 添加 install
325
+ __vue_component__$2.install = Vue => {
326
+ Vue.component(__vue_component__$2.name, __vue_component__$2);
327
+ };
328
+
329
+ function __$styleInject$1(css) {
18
330
  if (!css) return;
19
331
 
20
332
  if (typeof window == 'undefined') return;
@@ -26,7 +338,7 @@ function __$styleInject(css) {
26
338
  return css;
27
339
  }
28
340
 
29
- __$styleInject(".hi-title {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.hi-title--small {\n gap: 2px;\n}\n.hi-title--large {\n gap: 6px;\n}\n.hi-title__header {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n.hi-title__prefix {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n}\n.hi-title__bar {\n width: 4px;\n background-color: var(--td-brand-color);\n flex-shrink: 0;\n}\n.hi-title__icon {\n flex-shrink: 0;\n line-height: 1;\n}\n.hi-title__text {\n margin: 0;\n font-weight: 600;\n color: var(--td-text-color-primary);\n}\n.hi-title__description {\n margin: 0;\n font-size: 12px;\n color: var(--td-text-color-secondary);\n}\n");
341
+ __$styleInject$1(".hi-title {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.hi-title--small {\n gap: 2px;\n}\n.hi-title--large {\n gap: 6px;\n}\n.hi-title__header {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n.hi-title__prefix {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n}\n.hi-title__bar {\n width: 4px;\n background-color: var(--td-brand-color);\n flex-shrink: 0;\n}\n.hi-title__icon {\n flex-shrink: 0;\n line-height: 1;\n}\n.hi-title__text {\n margin: 0;\n font-weight: 600;\n color: var(--td-text-color-primary);\n}\n.hi-title__description {\n margin: 0;\n font-size: 12px;\n color: var(--td-text-color-secondary);\n}\n");
30
342
 
31
343
  //
32
344
  const TITILE_SIZE_MAP = {
@@ -34,7 +346,7 @@ const TITILE_SIZE_MAP = {
34
346
  medium: '16px',
35
347
  large: '18px'
36
348
  };
37
- var script = {
349
+ var script$1 = {
38
350
  name: 'HiTitle',
39
351
  inheritAttrs: false,
40
352
  props: {
@@ -113,7 +425,7 @@ var script = {
113
425
  }
114
426
  };
115
427
 
116
- function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
428
+ function normalizeComponent$1(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
117
429
  if (typeof shadowMode !== 'boolean') {
118
430
  createInjectorSSR = createInjector;
119
431
  createInjector = shadowMode;
@@ -189,10 +501,10 @@ function normalizeComponent(template, style, script, scopeId, isFunctionalTempla
189
501
  }
190
502
 
191
503
  /* script */
192
- const __vue_script__ = script;
504
+ const __vue_script__$1 = script$1;
193
505
 
194
506
  /* template */
195
- var __vue_render__ = function () {
507
+ var __vue_render__$1 = function () {
196
508
  var _vm = this;
197
509
  var _h = _vm.$createElement;
198
510
  var _c = _vm._self._c || _h;
@@ -258,6 +570,435 @@ var __vue_render__ = function () {
258
570
  ]
259
571
  )
260
572
  };
573
+ var __vue_staticRenderFns__$1 = [];
574
+ __vue_render__$1._withStripped = true;
575
+
576
+ /* style */
577
+ const __vue_inject_styles__$1 = undefined;
578
+ /* scoped */
579
+ const __vue_scope_id__$1 = undefined;
580
+ /* module identifier */
581
+ const __vue_module_identifier__$1 = undefined;
582
+ /* functional template */
583
+ const __vue_is_functional_template__$1 = false;
584
+ /* style inject */
585
+
586
+ /* style inject SSR */
587
+
588
+ /* style inject shadow dom */
589
+
590
+
591
+
592
+ const __vue_component__$1 = /*#__PURE__*/normalizeComponent$1(
593
+ { render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 },
594
+ __vue_inject_styles__$1,
595
+ __vue_script__$1,
596
+ __vue_scope_id__$1,
597
+ __vue_is_functional_template__$1,
598
+ __vue_module_identifier__$1,
599
+ false,
600
+ undefined,
601
+ undefined,
602
+ undefined
603
+ );
604
+
605
+ // 显式设置 name(避免 .vue 丢失)
606
+ __vue_component__$1.name = 'HiTitle';
607
+
608
+ // 添加 install
609
+ __vue_component__$1.install = Vue => {
610
+ Vue.component(__vue_component__$1.name, __vue_component__$1);
611
+ };
612
+
613
+ function __$styleInject(css) {
614
+ if (!css) return;
615
+
616
+ if (typeof window == 'undefined') return;
617
+ var style = document.createElement('style');
618
+ style.setAttribute('media', 'screen');
619
+
620
+ style.innerHTML = css;
621
+ document.head.appendChild(style);
622
+ return css;
623
+ }
624
+
625
+ __$styleInject(".hi-virtual-list {\n overflow-y: auto;\n overflow-x: hidden;\n position: relative;\n will-change: scroll-position;\n}\n.hi-virtual-list--placeholder {\n pointer-events: none;\n}\n.hi-virtual-list--item-wrapper {\n box-sizing: border-box;\n}\n");
626
+
627
+ /**
628
+ * 类型判断工具
629
+ */
630
+
631
+ /**
632
+ * 将数值或字符串转换为合法的 CSS 长度值(用于 style 绑定)
633
+ * - 若为 number,自动追加 'px' 单位
634
+ * - 若为 string,原样返回(假定用户已提供合法 CSS 长度值)
635
+ * @param {number|string} value - 输入值(如 100, '100%', '50vh', 'auto')
636
+ * @returns {string} 合法的 CSS 长度字符串 默认值为 0
637
+ * @example
638
+ * formatSize(100) // '100px'
639
+ * formatSize('100%') // '100%'
640
+ * formatSize('50vh') // '50vh'
641
+ * formatSize(null) // 0
642
+ * formatSize(undefined) // 0
643
+ */
644
+ function formatSize(value) {
645
+ if (typeof value === 'number') {
646
+ return `${value}px`;
647
+ }
648
+ if (typeof value === 'string') {
649
+ if (value.trim() === '') {
650
+ return 0;
651
+ }
652
+ return value;
653
+ }
654
+ return 0;
655
+ }
656
+
657
+ //
658
+
659
+ var script = {
660
+ name: 'HiVirtualList',
661
+ props: {
662
+ items: {
663
+ type: Array,
664
+ required: true,
665
+ default: () => []
666
+ },
667
+ itemHeight: {
668
+ type: Number,
669
+ required: true,
670
+ validator(value) {
671
+ if (value <= 0) {
672
+ // eslint-disable-next-line no-console
673
+ console.error('[HiVirtualList] itemHeight must be a positive number.');
674
+ return false;
675
+ }
676
+ return true;
677
+ }
678
+ },
679
+ height: {
680
+ type: [Number, String],
681
+ required: true
682
+ },
683
+ buffer: {
684
+ type: Number,
685
+ default: 50
686
+ },
687
+ nodeKey: {
688
+ type: String,
689
+ default: undefined
690
+ }
691
+ },
692
+ data() {
693
+ return {
694
+ scrollTop: 0,
695
+ clientHeight: 0,
696
+ resizeObserver: null,
697
+ resizeTimer: null
698
+ };
699
+ },
700
+ computed: {
701
+ styles() {
702
+ return {
703
+ height: formatSize(this.height)
704
+ };
705
+ },
706
+ renderItemHeight() {
707
+ return formatSize(this.itemHeight);
708
+ },
709
+ total() {
710
+ return this.items.length;
711
+ },
712
+ visibleCount() {
713
+ if (!this.clientHeight || !this.itemHeight) return 20;
714
+ return Math.ceil(this.clientHeight / this.itemHeight) + this.buffer * 2;
715
+ },
716
+ startIndex() {
717
+ return Math.max(0, Math.floor(this.scrollTop / this.itemHeight));
718
+ },
719
+ endIndex() {
720
+ return Math.min(this.total, this.startIndex + this.visibleCount);
721
+ },
722
+ visibleItems() {
723
+ return this.items.slice(this.startIndex, this.endIndex);
724
+ },
725
+ topPlaceholderHeight() {
726
+ return formatSize(this.startIndex * this.itemHeight);
727
+ },
728
+ bottomPlaceholderHeight() {
729
+ return formatSize((this.total - this.endIndex) * this.itemHeight);
730
+ }
731
+ },
732
+ mounted() {
733
+ this.updateClientHeight();
734
+ this.setupResizeListener();
735
+ },
736
+ beforeDestroy() {
737
+ this.cleanupResizeListener();
738
+ },
739
+ methods: {
740
+ /**
741
+ * 判断是否应使用 nodeKey 字段
742
+ */
743
+ _shouldUseNodeKey() {
744
+ return this.nodeKey && typeof this.nodeKey === 'string' && this.nodeKey.trim() !== '';
745
+ },
746
+
747
+ /**
748
+ * 获取 item 的唯一 key(用于 v-for)
749
+ */
750
+ getNodeKey(item, index) {
751
+ if (this._shouldUseNodeKey() && item != null && typeof item === 'object') {
752
+ const key = item[this.nodeKey];
753
+ if (key != null) {
754
+ return key;
755
+ }
756
+ }
757
+ return index;
758
+ },
759
+
760
+ updateClientHeight() {
761
+ if (this.$refs.rootRef) {
762
+ this.clientHeight = this.$refs.rootRef.clientHeight;
763
+ }
764
+ },
765
+
766
+ setupResizeListener() {
767
+ if (typeof ResizeObserver !== 'undefined') {
768
+ this.resizeObserver = new ResizeObserver(() => {
769
+ this.updateClientHeight();
770
+ });
771
+ this.resizeObserver.observe(this.$refs.rootRef);
772
+ } else {
773
+ window.addEventListener('resize', this.handleWindowResize);
774
+ }
775
+ },
776
+
777
+ cleanupResizeListener() {
778
+ if (this.resizeObserver) {
779
+ this.resizeObserver.disconnect();
780
+ this.resizeObserver = null;
781
+ }
782
+ if (this.resizeTimer) {
783
+ clearTimeout(this.resizeTimer);
784
+ this.resizeTimer = null;
785
+ }
786
+ window.removeEventListener('resize', this.handleWindowResize);
787
+ },
788
+
789
+ handleWindowResize() {
790
+ if (this.resizeTimer) {
791
+ clearTimeout(this.resizeTimer);
792
+ }
793
+ this.resizeTimer = setTimeout(() => {
794
+ this.updateClientHeight();
795
+ }, 100);
796
+ },
797
+
798
+ handleScroll(e) {
799
+ this.scrollTop = e.target.scrollTop;
800
+ this.$emit('scroll', e);
801
+
802
+ const { scrollHeight, clientHeight, scrollTop } = e.target;
803
+ if (scrollTop === 0) this.$emit('reach-top');
804
+ if (scrollHeight - clientHeight - scrollTop < 100) this.$emit('reach-bottom');
805
+ this.$emit('visible-change', { startIndex: this.startIndex, endIndex: this.endIndex });
806
+ },
807
+
808
+ refresh() {
809
+ this.updateClientHeight();
810
+ },
811
+
812
+ /**
813
+ * 内部滚动方法(仅设置 DOM scrollTop,状态由 handleScroll 同步)
814
+ */
815
+ _setScrollTop(scrollTop) {
816
+ if (this.$refs.rootRef) {
817
+ this.$refs.rootRef.scrollTop = scrollTop;
818
+ }
819
+ },
820
+
821
+ /**
822
+ * 滚动到指定目标
823
+ * - 若启用了有效的 nodeKey,则 target 视为 keyValue
824
+ * - 否则,target 必须是 number(index)
825
+ */
826
+ scrollTo(target) {
827
+ if (target == null) {
828
+ // eslint-disable-next-line no-console
829
+ console.warn('[HiVirtualList] scrollTo: target cannot be null or undefined');
830
+ return;
831
+ }
832
+
833
+ let index = -1;
834
+
835
+ // 使用 getNodeKey 生成的 key 进行匹配(严格对齐)
836
+ if (this._shouldUseNodeKey()) {
837
+ index = this.items.findIndex((item, i) => {
838
+ return this.getNodeKey(item, i) === target;
839
+ });
840
+ } else {
841
+ // 降级到 index 模式
842
+ if (typeof target === 'number' && target >= 0 && target < this.total) {
843
+ index = target;
844
+ } else {
845
+ // eslint-disable-next-line no-console
846
+ console.warn(
847
+ '[HiVirtualList] scrollTo: when nodeKey is not provided, target must be a valid index (number).'
848
+ );
849
+ return;
850
+ }
851
+ }
852
+
853
+ if (index < 0 || index >= this.total) {
854
+ if (this._shouldUseNodeKey()) {
855
+ // eslint-disable-next-line no-console
856
+ console.warn(`[HiVirtualList] scrollTo: item with key "${target}" not found`);
857
+ } else {
858
+ // eslint-disable-next-line no-console
859
+ console.warn(`[HiVirtualList] scrollTo: index ${target} is out of range [0, ${this.total})`);
860
+ }
861
+ return;
862
+ }
863
+
864
+ this._setScrollTop(index * this.itemHeight);
865
+ },
866
+
867
+ scrollToTop() {
868
+ this._setScrollTop(0);
869
+ },
870
+
871
+ scrollToBottom() {
872
+ this._setScrollTop(this.total * this.itemHeight);
873
+ },
874
+
875
+ getVisibleRange() {
876
+ return {
877
+ startIndex: this.startIndex,
878
+ endIndex: this.endIndex
879
+ };
880
+ }
881
+ }
882
+ };
883
+
884
+ function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) {
885
+ if (typeof shadowMode !== 'boolean') {
886
+ createInjectorSSR = createInjector;
887
+ createInjector = shadowMode;
888
+ shadowMode = false;
889
+ }
890
+ // Vue.extend constructor export interop.
891
+ const options = typeof script === 'function' ? script.options : script;
892
+ // render functions
893
+ if (template && template.render) {
894
+ options.render = template.render;
895
+ options.staticRenderFns = template.staticRenderFns;
896
+ options._compiled = true;
897
+ // functional template
898
+ if (isFunctionalTemplate) {
899
+ options.functional = true;
900
+ }
901
+ }
902
+ // scopedId
903
+ if (scopeId) {
904
+ options._scopeId = scopeId;
905
+ }
906
+ let hook;
907
+ if (moduleIdentifier) {
908
+ // server build
909
+ hook = function (context) {
910
+ // 2.3 injection
911
+ context =
912
+ context || // cached call
913
+ (this.$vnode && this.$vnode.ssrContext) || // stateful
914
+ (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional
915
+ // 2.2 with runInNewContext: true
916
+ if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
917
+ context = __VUE_SSR_CONTEXT__;
918
+ }
919
+ // inject component styles
920
+ if (style) {
921
+ style.call(this, createInjectorSSR(context));
922
+ }
923
+ // register component module identifier for async chunk inference
924
+ if (context && context._registeredComponents) {
925
+ context._registeredComponents.add(moduleIdentifier);
926
+ }
927
+ };
928
+ // used by ssr in case component is cached and beforeCreate
929
+ // never gets called
930
+ options._ssrRegister = hook;
931
+ }
932
+ else if (style) {
933
+ hook = shadowMode
934
+ ? function (context) {
935
+ style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot));
936
+ }
937
+ : function (context) {
938
+ style.call(this, createInjector(context));
939
+ };
940
+ }
941
+ if (hook) {
942
+ if (options.functional) {
943
+ // register for functional component in vue file
944
+ const originalRender = options.render;
945
+ options.render = function renderWithStyleInjection(h, context) {
946
+ hook.call(context);
947
+ return originalRender(h, context);
948
+ };
949
+ }
950
+ else {
951
+ // inject component registration as beforeCreate hook
952
+ const existing = options.beforeCreate;
953
+ options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
954
+ }
955
+ }
956
+ return script;
957
+ }
958
+
959
+ /* script */
960
+ const __vue_script__ = script;
961
+
962
+ /* template */
963
+ var __vue_render__ = function () {
964
+ var _vm = this;
965
+ var _h = _vm.$createElement;
966
+ var _c = _vm._self._c || _h;
967
+ return _c(
968
+ "div",
969
+ {
970
+ ref: "rootRef",
971
+ staticClass: "hi-virtual-list",
972
+ style: _vm.styles,
973
+ on: { scroll: _vm.handleScroll },
974
+ },
975
+ [
976
+ _c("div", {
977
+ staticClass: "hi-virtual-list--placeholder",
978
+ style: { height: _vm.topPlaceholderHeight },
979
+ }),
980
+ _vm._v(" "),
981
+ _vm._l(_vm.visibleItems, function (item, i) {
982
+ return _c(
983
+ "div",
984
+ {
985
+ key: _vm.getNodeKey(item, _vm.startIndex + i),
986
+ staticClass: "hi-virtual-list--item-wrapper",
987
+ style: { height: _vm.renderItemHeight },
988
+ },
989
+ [_vm._t("default", null, { item: item, index: _vm.startIndex + i })],
990
+ 2
991
+ )
992
+ }),
993
+ _vm._v(" "),
994
+ _c("div", {
995
+ staticClass: "hi-virtual-list--placeholder",
996
+ style: { height: _vm.bottomPlaceholderHeight },
997
+ }),
998
+ ],
999
+ 2
1000
+ )
1001
+ };
261
1002
  var __vue_staticRenderFns__ = [];
262
1003
  __vue_render__._withStripped = true;
263
1004
 
@@ -291,14 +1032,19 @@ __vue_render__._withStripped = true;
291
1032
  );
292
1033
 
293
1034
  // 显式设置 name(避免 .vue 丢失)
294
- __vue_component__.name = 'HiTitle';
1035
+ __vue_component__.name = 'HiVirtualList';
295
1036
 
296
1037
  // 添加 install
297
1038
  __vue_component__.install = Vue => {
298
1039
  Vue.component(__vue_component__.name, __vue_component__);
299
1040
  };
300
1041
 
301
- const components = [__vue_component__];
1042
+ // eslint-disable-next-line prettier/prettier
1043
+ const components = [
1044
+ __vue_component__$2,
1045
+ __vue_component__$1,
1046
+ __vue_component__
1047
+ ];
302
1048
 
303
1049
  const install = function (Vue) {
304
1050
  components.forEach(component => {
@@ -306,6 +1052,11 @@ const install = function (Vue) {
306
1052
  });
307
1053
  };
308
1054
 
309
- var index = { install, HiTitle: __vue_component__ };
1055
+ var index = {
1056
+ install,
1057
+ HiExpandText: __vue_component__$2,
1058
+ HiTitle: __vue_component__$1,
1059
+ HiVirtualList: __vue_component__
1060
+ };
310
1061
 
311
1062
  module.exports = index;