@king-design/vue 3.8.0-beta.0 → 3.8.0-beta.2

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.
Files changed (54) hide show
  1. package/__tests__/__snapshots__/Vue Next Demos.md +74 -74
  2. package/components/bubble/bubble.d.ts +3 -0
  3. package/components/bubble/bubble.vdt.js +6 -2
  4. package/components/bubble/index.spec.js +231 -5
  5. package/components/bubble/styles.js +1 -1
  6. package/components/bubble/useBubbleDisplay.d.ts +1 -0
  7. package/components/bubble/useBubbleDisplay.js +68 -22
  8. package/components/bubbleList/bubbleList.vdt.js +3 -1
  9. package/components/bubbleList/index.spec.js +378 -237
  10. package/components/bubbleList/styles.js +2 -2
  11. package/components/bubbleList/useBubbleList.js +7 -0
  12. package/components/fileCard/fileCard.vdt.js +4 -4
  13. package/components/fileCard/index.spec.js +179 -107
  14. package/components/fileCard/list.d.ts +2 -1
  15. package/components/fileCard/list.vdt.js +7 -5
  16. package/components/fileCard/styles.js +10 -8
  17. package/components/fileCard/useFileCard.d.ts +1 -1
  18. package/components/fileCard/useFileCard.js +6 -35
  19. package/components/media/index.spec.js +774 -585
  20. package/components/media/media.vdt.js +17 -6
  21. package/components/media/mediaAssets.d.ts +2 -0
  22. package/components/media/mediaAssets.js +4 -0
  23. package/components/media/styles.js +5 -3
  24. package/components/media/useMedia.d.ts +6 -2
  25. package/components/media/useMedia.js +28 -6
  26. package/components/sender/index.spec.js +1146 -476
  27. package/components/sender/sender.d.ts +28 -5
  28. package/components/sender/sender.js +17 -6
  29. package/components/sender/sender.vdt.js +121 -49
  30. package/components/sender/styles.js +18 -9
  31. package/components/sender/useAutoResize.js +7 -6
  32. package/components/sender/useSenderDrag.js +12 -3
  33. package/components/sender/useSenderInput.d.ts +3 -0
  34. package/components/sender/useSenderInput.js +20 -3
  35. package/components/sender/useSenderPaste.js +1 -1
  36. package/components/sender/useSenderUpload.js +38 -29
  37. package/components/xmarkdown/index.spec.js +492 -263
  38. package/components/xmarkdown/markdown/streaming.js +41 -8
  39. package/components/xmarkdown/styles.js +2 -2
  40. package/components/xmarkdown/useXMarkdownDisplay.d.ts +1 -0
  41. package/components/xmarkdown/useXMarkdownDisplay.js +69 -24
  42. package/components/xmarkdown/xmarkdown.d.ts +3 -0
  43. package/components/xmarkdown/xmarkdown.vdt.js +6 -2
  44. package/dist/i18n/en-US.js +1 -0
  45. package/dist/i18n/en-US.js.map +1 -1
  46. package/dist/i18n/en-US.min.js +1 -1
  47. package/dist/index.js +795 -512
  48. package/dist/index.js.map +1 -1
  49. package/dist/index.min.js +2 -2
  50. package/i18n/en-US.d.ts +1 -0
  51. package/i18n/en-US.js +1 -0
  52. package/index.d.ts +2 -2
  53. package/index.js +2 -2
  54. package/package.json +1 -1
@@ -5,7 +5,7 @@ import '../../styles/global';
5
5
  import { cache } from '../utils';
6
6
  var defaults = {
7
7
  gap: '12px',
8
- paddingInline: '8px',
8
+ scrollbarGap: '6px',
9
9
  scrollToBottomBg: '#fff',
10
10
  scrollToBottomColor: '#97A3B6',
11
11
  scrollToBottomBorder: "1px solid " + setAlpha(theme.color.border, 0.72),
@@ -29,5 +29,5 @@ setDefault(function () {
29
29
  makeStyles == null || makeStyles.clearCache();
30
30
  });
31
31
  export var makeStyles = cache(function makeStyles(k) {
32
- return /*#__PURE__*/css("position:relative;display:flex;flex-direction:column;gap:", bubbleList.gap, ";width:100%;min-height:0;.", k, "-bubble-list-scroll{position:relative;flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;width:100%;box-sizing:border-box;scrollbar-width:thin;scrollbar-color:", bubbleList.scrollThumb, " ", bubbleList.scrollbarTrack, ";}.", k, "-bubble-list-scroll::-webkit-scrollbar{width:10px;height:10px;}.", k, "-bubble-list-scroll::-webkit-scrollbar-track{background:", bubbleList.scrollbarTrack, ";}.", k, "-bubble-list-scroll::-webkit-scrollbar-thumb{background:", bubbleList.scrollThumb, ";border-radius:999px;border:2px solid transparent;background-clip:content-box;transition:background ", theme.transition.small, ";}.", k, "-bubble-list-scroll::-webkit-scrollbar-thumb:hover{background:", bubbleList.scrollThumbHover, ";background-clip:content-box;}.", k, "-bubble-list-scroll-content{min-height:100%;display:flex;flex-direction:column;box-sizing:border-box;padding-inline:", bubbleList.paddingInline, ";}.", k, "-bubble-list-history{display:flex;justify-content:center;color:", bubbleList.auxiliaryColor, ";font-size:12px;line-height:1.5;padding:4px 0 8px;flex:0 0 auto;}.", k, "-bubble-list-items{display:flex;flex-direction:column;gap:", bubbleList.gap, ";width:100%;}.", k, "-bubble-list-item{width:100%;min-width:0;}.", k, "-bubble-list-empty{min-height:100%;display:flex;align-items:center;justify-content:center;color:", bubbleList.auxiliaryColor, ";padding:24px 16px;text-align:center;box-sizing:border-box;}.", k, "-bubble-list-scroll-to-bottom{position:absolute;right:16px;bottom:16px;z-index:1;}.", k, "-bubble-list-scroll-to-bottom-button{border:", bubbleList.scrollToBottomBorder, ";background:", bubbleList.scrollToBottomBg, ";color:", bubbleList.scrollToBottomColor, ";border-radius:999px;box-shadow:", bubbleList.scrollToBottomShadow, ";width:", bubbleList.scrollToBottomSize, ";height:", bubbleList.scrollToBottomSize, ";display:inline-flex;align-items:center;justify-content:center;padding:0;font-size:18px;line-height:1;cursor:pointer;transition:background ", theme.transition.small, ",border-color ", theme.transition.small, ",color ", theme.transition.small, ",transform ", theme.transition.small, ",box-shadow ", theme.transition.small, ";}.", k, "-bubble-list-scroll-to-bottom-button:hover{background:", bubbleList.scrollToBottomHoverBg, ";color:", bubbleList.scrollToBottomHoverColor, ";border:", bubbleList.scrollToBottomHoverBorder, ";transform:translateY(-1px);box-shadow:0 14px 30px ", setAlpha('#000', 0.16), ";}.", k, "-bubble-list-scroll-to-bottom-button:focus-visible{outline:0;color:", bubbleList.scrollToBottomHoverColor, ";border:", bubbleList.scrollToBottomHoverBorder, ";box-shadow:0 0 0 4px ", setAlpha(theme.color.primary, 0.14), ",0 10px 28px ", setAlpha('#000', 0.12), ";}.", k, "-bubble-list-scroll-to-bottom-icon{pointer-events:none;font-size:", bubbleList.scrollToBottomIconSize, ";}");
32
+ return /*#__PURE__*/css("position:relative;display:flex;flex-direction:column;gap:", bubbleList.gap, ";width:100%;min-height:0;.", k, "-bubble-list-scroll{position:relative;flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;width:100%;box-sizing:border-box;scrollbar-width:thin;scrollbar-color:", bubbleList.scrollThumb, " ", bubbleList.scrollbarTrack, ";}.", k, "-bubble-list-scroll-has-scrollbar{padding-inline-end:", bubbleList.scrollbarGap, ";}.", k, "-bubble-list-scroll::-webkit-scrollbar{width:10px;height:10px;}.", k, "-bubble-list-scroll::-webkit-scrollbar-track{background:", bubbleList.scrollbarTrack, ";}.", k, "-bubble-list-scroll::-webkit-scrollbar-thumb{background:", bubbleList.scrollThumb, ";border-radius:999px;border:2px solid transparent;background-clip:content-box;transition:background ", theme.transition.small, ";}.", k, "-bubble-list-scroll::-webkit-scrollbar-thumb:hover{background:", bubbleList.scrollThumbHover, ";background-clip:content-box;}.", k, "-bubble-list-scroll-content{min-height:100%;display:flex;flex-direction:column;box-sizing:border-box;padding-inline:0;}.", k, "-bubble-list-history{display:flex;justify-content:center;color:", bubbleList.auxiliaryColor, ";font-size:12px;line-height:1.5;padding:4px 0 8px;flex:0 0 auto;}.", k, "-bubble-list-items{display:flex;flex-direction:column;gap:", bubbleList.gap, ";width:100%;}.", k, "-bubble-list-item{width:100%;min-width:0;}.", k, "-bubble-list-empty{min-height:100%;display:flex;align-items:center;justify-content:center;color:", bubbleList.auxiliaryColor, ";padding:24px 16px;text-align:center;box-sizing:border-box;}.", k, "-bubble-list-scroll-to-bottom{position:absolute;right:16px;bottom:16px;z-index:1;}.", k, "-bubble-list-scroll-to-bottom-button{border:", bubbleList.scrollToBottomBorder, ";background:", bubbleList.scrollToBottomBg, ";color:", bubbleList.scrollToBottomColor, ";border-radius:999px;box-shadow:", bubbleList.scrollToBottomShadow, ";width:", bubbleList.scrollToBottomSize, ";height:", bubbleList.scrollToBottomSize, ";display:inline-flex;align-items:center;justify-content:center;padding:0;font-size:18px;line-height:1;cursor:pointer;transition:background ", theme.transition.small, ",border-color ", theme.transition.small, ",color ", theme.transition.small, ",transform ", theme.transition.small, ",box-shadow ", theme.transition.small, ";}.", k, "-bubble-list-scroll-to-bottom-button:hover{background:", bubbleList.scrollToBottomHoverBg, ";color:", bubbleList.scrollToBottomHoverColor, ";border:", bubbleList.scrollToBottomHoverBorder, ";transform:translateY(-1px);box-shadow:0 14px 30px ", setAlpha('#000', 0.16), ";}.", k, "-bubble-list-scroll-to-bottom-button:focus-visible{outline:0;color:", bubbleList.scrollToBottomHoverColor, ";border:", bubbleList.scrollToBottomHoverBorder, ";box-shadow:0 0 0 4px ", setAlpha(theme.color.primary, 0.14), ",0 10px 28px ", setAlpha('#000', 0.12), ";}.", k, "-bubble-list-scroll-to-bottom-icon{pointer-events:none;font-size:", bubbleList.scrollToBottomIconSize, ";}");
33
33
  });
@@ -76,6 +76,11 @@ export function useBubbleList() {
76
76
  if (instance.get(key) === value) return;
77
77
  instance.set(key, value);
78
78
  }
79
+ function syncScrollbarState() {
80
+ var scrollBox = getScrollBox();
81
+ var hasScrollbar = !!scrollBox && scrollBox.scrollHeight - scrollBox.clientHeight > 1;
82
+ setInternalState('$hasScrollbar', hasScrollbar);
83
+ }
79
84
  function setIsAtBottom(value) {
80
85
  if (instance.get('$isAtBottom') === value) return;
81
86
  setInternalState('$isAtBottom', value);
@@ -201,6 +206,7 @@ export function useBubbleList() {
201
206
  scrollBox.scrollTop += delta;
202
207
  }
203
208
  function syncScrollState() {
209
+ syncScrollbarState();
204
210
  var atBottom = isAtBottom();
205
211
  setIsAtBottom(atBottom);
206
212
  setAutoScrollActive(atBottom);
@@ -403,6 +409,7 @@ export function useBubbleList() {
403
409
  function onMountedCallback() {
404
410
  nextTick(function () {
405
411
  mountResizeObserver();
412
+ syncScrollbarState();
406
413
  if (isAutoScrollEnabled()) {
407
414
  scrollToBottom('auto');
408
415
  requestAnimationFrame(function () {
@@ -22,6 +22,7 @@ export default function ($props, $blocks, $__proto__) {
22
22
  onDelete = _this$model.onDelete,
23
23
  getValue = _this$model.getValue,
24
24
  onPreview = _this$model.onPreview,
25
+ isLoading = _this$model.isLoading,
25
26
  isError = _this$model.isError,
26
27
  getMediaLoadingText = _this$model.getMediaLoadingText,
27
28
  getMediaErrorText = _this$model.getMediaErrorText,
@@ -48,7 +49,7 @@ export default function ($props, $blocks, $__proto__) {
48
49
  getFileMediaType = _this$model.getFileMediaType,
49
50
  getMediaStatus = _this$model.getMediaStatus,
50
51
  getMediaShowPreview = _this$model.getMediaShowPreview,
51
- onMediaError = _this$model.onMediaError,
52
+ shouldShowMediaLoadingOverlay = _this$model.shouldShowMediaLoadingOverlay,
52
53
  getMediaSize = _this$model.getMediaSize,
53
54
  getFileMediaSize = _this$model.getFileMediaSize,
54
55
  shouldShowFileMedia = _this$model.shouldShowFileMedia;
@@ -68,7 +69,7 @@ export default function ($props, $blocks, $__proto__) {
68
69
  var value = getValue();
69
70
  var shouldShowFileContent = !isMediaType();
70
71
  var descriptionSlot = shouldShowFileContent && $blocks.description ? $blocks.description(noop, value) : undefined;
71
- var fileMaskSlot = shouldShowFileContent && maskBlock ? maskBlock(noop, value) : undefined;
72
+ var fileMaskSlot = shouldShowFileContent && !isLoading() && maskBlock ? maskBlock(noop, value) : undefined;
72
73
  var hasDescriptionSlot = !isEmptySlot(descriptionSlot);
73
74
  var hasFileMaskSlot = !isEmptySlot(fileMaskSlot);
74
75
  var isMini = (this.get('size') || 'default') === 'mini';
@@ -99,7 +100,6 @@ export default function ($props, $blocks, $__proto__) {
99
100
  'videoProps': this.get('videoProps'),
100
101
  'audioProps': this.get('audioProps'),
101
102
  'ev-preview': onPreview,
102
- 'ev-loadError': onMediaError,
103
103
  '$blocks': function ($blocks) {
104
104
  var _$blocks = {},
105
105
  __$blocks = _$ex({}, $blocks);
@@ -125,7 +125,7 @@ export default function ($props, $blocks, $__proto__) {
125
125
  return block ? block.call($this, callBlock, data) : callBlock();
126
126
  }), __$blocks;
127
127
  }.call($this, _$em)
128
- }), shouldShowMediaStatusLayer() && !shouldUseMediaErrorArtworkLayout() ? _$ce(2, 'div', _$ce(2, 'span', isError() ? getMediaErrorText() : getMediaLoadingText(), 0, _$cn((_$cn2 = {}, _$cn2[k + "-file-card-media-loading-text"] = !isError(), _$cn2[k + "-file-card-error-text"] = isError(), _$cn2))), 2, _$cn(k + "-file-card-media-status-layer")) : undefined, shouldShowVisualMediaProgressText() ? _$ce(2, 'div', getMediaProgressText(), 0, _$cn(k + "-file-card-media-progress-text")) : undefined], 0, _$cn(k + "-file-card-media-shell")) : _$ce(2, 'div', [_$ce(2, 'div', [shouldShowFileMedia() ? _$cc(Media, {
128
+ }), shouldShowMediaLoadingOverlay() ? _$ce(2, 'div', null, 1, _$cn(k + "-file-card-media-loading-overlay")) : undefined, shouldShowMediaStatusLayer() && !shouldUseMediaErrorArtworkLayout() ? _$ce(2, 'div', _$ce(2, 'span', isError() ? getMediaErrorText() : getMediaLoadingText(), 0, _$cn((_$cn2 = {}, _$cn2[k + "-file-card-media-loading-text"] = !isError(), _$cn2[k + "-file-card-error-text"] = isError(), _$cn2))), 2, _$cn(k + "-file-card-media-status-layer")) : undefined, shouldShowVisualMediaProgressText() ? _$ce(2, 'div', getMediaProgressText(), 0, _$cn(k + "-file-card-media-progress-text")) : undefined], 0, _$cn(k + "-file-card-media-shell")) : _$ce(2, 'div', [_$ce(2, 'div', [shouldShowFileMedia() ? _$cc(Media, {
129
129
  'className': _$cn(k + "-file-card-file-media-view"),
130
130
  'name': getFileName(),
131
131
  'type': getFileMediaType(),
@@ -17,12 +17,6 @@ describe('FileCard', function () {
17
17
  }
18
18
  expect(viewer.classList.contains('k-fade-leave-active') || viewer.classList.contains('k-fade-leave-to')).to.be.true;
19
19
  }
20
- function dispatchMediaEvent(target, eventName) {
21
- target.dispatchEvent(new Event(eventName, {
22
- bubbles: false,
23
- cancelable: true
24
- }));
25
- }
26
20
  // 文件卡片和显式媒体卡片走不同外形,媒体内部复用 Media。
27
21
  it('should render file and media card types with Media inside', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
28
22
  var Demo, _mount, element;
@@ -493,10 +487,10 @@ describe('FileCard', function () {
493
487
  }
494
488
  }, _callee13);
495
489
  })));
496
- // 显式图片上传失败且有 src 时,保留媒体画面、禁用预览,错误文案仅在指定 errorText 时展示。
497
- it('should keep visual media visible and show error text only when specified', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee14() {
490
+ // 显式图片/视频上传失败时,有 src 也展示错误占位,错误文案仅在指定 errorText 时展示。
491
+ it('should render media error state with source and show text only when specified', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee14() {
498
492
  var _cards$1$querySelecto3;
499
- var Demo, _mount14, element, cards, image, video;
493
+ var Demo, _mount14, element, cards, artwork, icon;
500
494
  return _regeneratorRuntime.wrap(function _callee14$(_context28) {
501
495
  while (1) switch (_context28.prev = _context28.next) {
502
496
  case 0:
@@ -517,28 +511,30 @@ describe('FileCard', function () {
517
511
  Demo.template = "\n const { FileCard } = this;\n <div>\n <FileCard\n name=\"cover.png\"\n type=\"image\"\n src=\"https://example.com/cover.png\"\n status=\"error\"\n />\n <FileCard\n name=\"clip.mp4\"\n type=\"video\"\n src=\"https://example.com/clip.mp4\"\n status=\"error\"\n errorText=\"\u4E0A\u4F20\u5931\u8D25\"\n />\n </div>\n ";
518
512
  _mount14 = mount(Demo), element = _mount14[1];
519
513
  cards = element.querySelectorAll('.k-file-card');
520
- image = cards[0].querySelector('img.k-media-image');
521
- video = cards[1].querySelector('video.k-media-video');
514
+ artwork = cards[1].querySelector('.k-file-card-media-error-artwork-content');
515
+ icon = artwork.querySelector('.k-file-card-media-error-artwork-icon');
522
516
  expect(cards[0].className).to.contain('k-file-card-error');
523
- expect(cards[0].querySelector('.k-media-error-card')).to.eql(null);
517
+ expect(cards[0].querySelector('img.k-media-image')).to.eql(null);
518
+ expect(cards[1].querySelector('video.k-media-video')).to.eql(null);
519
+ expect(cards[0].querySelector('.k-media-error-card')).not.to.eql(null);
524
520
  expect(cards[1].querySelector('.k-media-error-card')).to.eql(null);
525
- expect(image).not.to.eql(null);
526
- expect(video).not.to.eql(null);
527
521
  expect(cards[0].querySelector('.k-file-card-error-text')).to.eql(null);
528
522
  expect((_cards$1$querySelecto3 = cards[1].querySelector('.k-file-card-error-text')) == null ? void 0 : _cards$1$querySelecto3.textContent).to.contain('上传失败');
523
+ expect(cards[1].className).to.contain('k-file-card-media-error-artwork');
524
+ expect(icon.src).to.contain('ECECEC');
529
525
  expect(getComputedStyle(cards[0]).borderColor).not.to.eql('rgb(237, 64, 64)');
530
526
  expect(element.querySelector('.k-media-placeholder')).to.eql(null);
531
527
  expect(element.querySelector('.k-media-preview-trigger')).to.eql(null);
532
- case 16:
528
+ case 18:
533
529
  case "end":
534
530
  return _context28.stop();
535
531
  }
536
532
  }, _callee14);
537
533
  })));
538
- // 显式图片上传失败但 src 自身加载失败时,回退到上传失败 artwork。
539
- it('should render upload error artwork when visual media src fails to load', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee15() {
540
- var _element$querySelecto11, _artwork$querySelecto;
541
- var Demo, _mount15, element, image, statusLayer, artwork;
534
+ // 显式图片上传失败时,不再等待 src 加载失败,直接展示上传失败 artwork。
535
+ it('should render upload error artwork immediately for visual media with source', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee15() {
536
+ var _artwork$querySelecto;
537
+ var Demo, _mount15, element, artwork;
542
538
  return _regeneratorRuntime.wrap(function _callee15$(_context30) {
543
539
  while (1) switch (_context30.prev = _context30.next) {
544
540
  case 0:
@@ -558,22 +554,12 @@ describe('FileCard', function () {
558
554
  }(Component);
559
555
  Demo.template = "\n const { FileCard } = this;\n <div>\n <FileCard\n name=\"cover.png\"\n type=\"image\"\n src=\"https://example.com/cover.png\"\n status=\"error\"\n errorText=\"\u4E0A\u4F20\u5931\u8D25\"\n />\n </div>\n ";
560
556
  _mount15 = mount(Demo), element = _mount15[1];
561
- image = element.querySelector('img.k-media-image');
562
- statusLayer = element.querySelector('.k-file-card-media-status-layer');
563
- expect(image, 'visual media should be shown before source fails').not.to.eql(null);
564
- expect(statusLayer, 'specified errorText should render status layer while visual media is kept').not.to.eql(null);
565
- dispatchMediaEvent(image, 'error');
566
- _context30.next = 10;
567
- return wait();
568
- case 10:
569
- _context30.next = 12;
570
- return wait();
571
- case 12:
572
557
  artwork = element.querySelector('.k-file-card-media-error-artwork-content');
573
- expect(artwork, "source failure should switch upload error text into artwork layout: " + ((_element$querySelecto11 = element.querySelector('.k-file-card')) == null ? void 0 : _element$querySelecto11.className)).not.to.eql(null);
558
+ expect(artwork).not.to.eql(null);
559
+ expect(element.querySelector('img.k-media-image')).to.eql(null);
574
560
  expect(element.querySelector('.k-file-card-media-status-layer')).to.eql(null);
575
561
  expect((_artwork$querySelecto = artwork.querySelector('.k-file-card-error-text')) == null ? void 0 : _artwork$querySelecto.textContent).to.contain('上传失败');
576
- case 16:
562
+ case 8:
577
563
  case "end":
578
564
  return _context30.stop();
579
565
  }
@@ -634,7 +620,7 @@ describe('FileCard', function () {
634
620
  })));
635
621
  // 显式视频在 mini 尺寸下,percent 仍会展示进度文本。
636
622
  it('should show video progress text in mini size when percent is provided', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee17() {
637
- var _element$querySelecto12;
623
+ var _element$querySelecto11;
638
624
  var Demo, _mount17, element;
639
625
  return _regeneratorRuntime.wrap(function _callee17$(_context34) {
640
626
  while (1) switch (_context34.prev = _context34.next) {
@@ -655,16 +641,15 @@ describe('FileCard', function () {
655
641
  }(Component);
656
642
  Demo.template = "\n const { FileCard } = this;\n <div>\n <FileCard\n name=\"result.mp4\"\n type=\"video\"\n size=\"mini\"\n status=\"loading\"\n percent={56}\n src=\"https://example.com/result.mp4\"\n />\n </div>\n ";
657
643
  _mount17 = mount(Demo), element = _mount17[1];
658
- expect((_element$querySelecto12 = element.querySelector('.k-file-card-media-progress-text')) == null ? void 0 : _element$querySelecto12.textContent).to.contain('56%');
644
+ expect((_element$querySelecto11 = element.querySelector('.k-file-card-media-progress-text')) == null ? void 0 : _element$querySelecto11.textContent).to.contain('56%');
659
645
  case 4:
660
646
  case "end":
661
647
  return _context34.stop();
662
648
  }
663
649
  }, _callee17);
664
650
  })));
665
- // 文件行卡片在 loading 时也允许自定义 mask 插槽渲染。
666
- it('should render file mask slot even when status is loading', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee18() {
667
- var _mask$querySelector;
651
+ // 文件行卡片 loading 时不展示 hover mask,避免和进度/状态层冲突。
652
+ it('should not render file mask slot when status is loading', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee18() {
668
653
  var Demo, _mount18, element, mask;
669
654
  return _regeneratorRuntime.wrap(function _callee18$(_context36) {
670
655
  while (1) switch (_context36.prev = _context36.next) {
@@ -686,8 +671,8 @@ describe('FileCard', function () {
686
671
  Demo.template = "\n const { FileCard } = this;\n <div>\n <FileCard\n name=\"a.pdf\"\n type=\"file\"\n status=\"loading\"\n >\n <b:mask>\n <span class=\"mask-content\">\u64CD\u4F5C\u533A</span>\n </b:mask>\n </FileCard>\n </div>\n ";
687
672
  _mount18 = mount(Demo), element = _mount18[1];
688
673
  mask = element.querySelector('.k-file-card-file-mask');
689
- expect(mask).not.to.eql(null);
690
- expect((_mask$querySelector = mask.querySelector('.mask-content')) == null ? void 0 : _mask$querySelector.textContent).to.contain('操作区');
674
+ expect(mask).to.eql(null);
675
+ expect(element.querySelector('.mask-content')).to.eql(null);
691
676
  case 6:
692
677
  case "end":
693
678
  return _context36.stop();
@@ -768,10 +753,10 @@ describe('FileCard', function () {
768
753
  }
769
754
  }, _callee20);
770
755
  })));
771
- // 显式音频媒体未传 mask 插槽时,loading 文案和进度仍由 FileCard 层展示。
772
- it('should render audio loading status and progress without mask slot', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee21() {
773
- var _element$querySelecto13, _element$querySelecto14;
774
- var Demo, _mount21, element;
756
+ // 显式音频媒体仅在有 loading 文案或进度时展示 loading 蒙层,文案颜色与图片/视频一致。
757
+ it('should render audio loading overlay only when status text or progress is visible', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee21() {
758
+ var _textAudio$querySelec;
759
+ var Demo, _mount21, element, emptyAudio, textAudio, loadingText;
775
760
  return _regeneratorRuntime.wrap(function _callee21$(_context42) {
776
761
  while (1) switch (_context42.prev = _context42.next) {
777
762
  case 0:
@@ -789,13 +774,20 @@ describe('FileCard', function () {
789
774
  }
790
775
  return Demo;
791
776
  }(Component);
792
- Demo.template = "\n const { FileCard } = this;\n <div>\n <FileCard\n name=\"voice.mp3\"\n type=\"audio\"\n status=\"loading\"\n loadingText=\"\u4E0A\u4F20\u4E2D\"\n percent={37}\n src=\"https://example.com/voice.mp3\"\n />\n </div>\n ";
777
+ Demo.template = "\n const { FileCard } = this;\n <div>\n <FileCard\n className=\"audio-loading-empty\"\n name=\"plain.mp3\"\n type=\"audio\"\n status=\"loading\"\n src=\"https://example.com/plain.mp3\"\n />\n <FileCard\n className=\"audio-loading-text\"\n name=\"voice.mp3\"\n type=\"audio\"\n status=\"loading\"\n loadingText=\"\u4E0A\u4F20\u4E2D\"\n percent={37}\n src=\"https://example.com/voice.mp3\"\n />\n </div>\n ";
793
778
  _mount21 = mount(Demo), element = _mount21[1];
794
- expect(element.querySelector('.k-media-loading-indicator')).not.to.eql(null);
795
- expect((_element$querySelecto13 = element.querySelector('.k-file-card-media-loading-text')) == null ? void 0 : _element$querySelecto13.textContent).to.contain('上传中');
796
- expect((_element$querySelecto14 = element.querySelector('.k-file-card-media-progress-text')) == null ? void 0 : _element$querySelecto14.textContent).to.contain('37%');
797
- expect(element.querySelector('.k-media-preview-trigger')).to.eql(null);
798
- case 7:
779
+ emptyAudio = element.querySelector('.audio-loading-empty');
780
+ textAudio = element.querySelector('.audio-loading-text');
781
+ loadingText = textAudio.querySelector('.k-file-card-media-loading-text');
782
+ expect(emptyAudio.querySelector('.k-file-card-media-loading-overlay')).to.eql(null);
783
+ expect(textAudio.querySelector('.k-file-card-media-loading-overlay')).not.to.eql(null);
784
+ expect(textAudio.querySelector('.k-media-loading-overlay')).to.eql(null);
785
+ expect(textAudio.querySelector('.k-media-loading-indicator')).not.to.eql(null);
786
+ expect(loadingText.textContent).to.contain('上传中');
787
+ expect(getComputedStyle(loadingText).color).to.eql('rgb(255, 255, 255)');
788
+ expect((_textAudio$querySelec = textAudio.querySelector('.k-file-card-media-progress-text')) == null ? void 0 : _textAudio$querySelec.textContent).to.contain('37%');
789
+ expect(textAudio.querySelector('.k-media-preview-trigger')).to.eql(null);
790
+ case 14:
799
791
  case "end":
800
792
  return _context42.stop();
801
793
  }
@@ -909,21 +901,22 @@ describe('FileCard', function () {
909
901
  expect(button.className).not.to.contain('k-btn');
910
902
  expect(style.top).to.eql('2px');
911
903
  expect(style.right).to.eql('2px');
904
+ expect(style.zIndex).to.eql('5');
912
905
  expect(style.transform).to.eql('none');
913
906
  expect(calls).to.eql(['delete']);
914
- case 15:
907
+ case 16:
915
908
  case "end":
916
909
  return _context48.stop();
917
910
  }
918
911
  }, _callee24);
919
912
  })));
920
- // 媒体预览由内部 Media 负责,同时 FileCard 继续抛出 preview 事件。
921
- it('should preview media through Media viewer and trigger preview event', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee25() {
922
- var _getElement2;
923
- var Demo, _mount25, instance, element, previewTrigger;
913
+ // 视频卡片的播放触发器覆盖在卡片中间,删除按钮需要保持更高层级。
914
+ it('should keep video delete button above preview trigger and not open preview', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee25() {
915
+ var calls, Demo, _mount25, element, button, previewTrigger;
924
916
  return _regeneratorRuntime.wrap(function _callee25$(_context50) {
925
917
  while (1) switch (_context50.prev = _context50.next) {
926
918
  case 0:
919
+ calls = [];
927
920
  Demo = /*#__PURE__*/function (_Component25) {
928
921
  _inheritsLoose(Demo, _Component25);
929
922
  function Demo() {
@@ -934,34 +927,40 @@ describe('FileCard', function () {
934
927
  }
935
928
  _this25 = _Component25.call.apply(_Component25, _concatInstanceProperty(_context49 = [this]).call(_context49, args)) || this;
936
929
  _this25.FileCard = FileCard;
930
+ _this25.onClick = function () {
931
+ calls.push('click');
932
+ };
933
+ _this25.onPreview = function () {
934
+ calls.push('preview');
935
+ };
936
+ _this25.onDelete = function () {
937
+ calls.push('delete');
938
+ };
937
939
  return _this25;
938
940
  }
939
- Demo.defaults = function defaults() {
940
- return {
941
- previewCount: 0
942
- };
943
- };
944
941
  return Demo;
945
942
  }(Component);
946
- Demo.template = "\n const { FileCard } = this;\n <div>\n <FileCard\n name=\"cover.png\"\n type=\"image\"\n status=\"done\"\n src=\"https://example.com/cover.png\"\n ev-preview={() => this.set('previewCount', this.get('previewCount') + 1)}\n />\n </div>\n ";
947
- _mount25 = mount(Demo), instance = _mount25[0], element = _mount25[1];
948
- previewTrigger = element.querySelector('.k-media-preview-trigger');
949
- previewTrigger.click();
950
- _context50.next = 7;
943
+ Demo.template = "\n const { FileCard } = this;\n <div>\n <FileCard\n name=\"clip.mp4\"\n type=\"video\"\n status=\"done\"\n src=\"https://example.com/clip.mp4\"\n showDelIcon\n ev-click={this.onClick}\n ev-preview={this.onPreview}\n ev-delete={this.onDelete}\n />\n </div>\n ";
944
+ _mount25 = mount(Demo), element = _mount25[1];
945
+ button = element.querySelector('.k-file-card-delete');
946
+ previewTrigger = element.querySelector('.k-media-video-preview-trigger');
947
+ expect(+getComputedStyle(button).zIndex).to.be.greaterThan(+getComputedStyle(previewTrigger).zIndex);
948
+ button.click();
949
+ _context50.next = 10;
951
950
  return wait();
952
- case 7:
953
- expect(instance.get('previewCount')).to.eql(1);
954
- expect(getElement('.k-media-viewer')).not.to.eql(null);
955
- expect((_getElement2 = getElement('.k-media-viewer-title')) == null ? void 0 : _getElement2.textContent).to.contain('cover.png');
956
951
  case 10:
952
+ expect(calls).to.eql(['delete']);
953
+ expectViewerClosed();
954
+ case 12:
957
955
  case "end":
958
956
  return _context50.stop();
959
957
  }
960
958
  }, _callee25);
961
959
  })));
962
- // showPreview=false 会同步关闭显式媒体和文件行媒体缩略图的预览入口。
963
- it('should disable preview for media and file media thumbnail', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee26() {
964
- var Demo, _mount26, element;
960
+ // 媒体预览由内部 Media 负责,同时 FileCard 继续抛出 preview 事件。
961
+ it('should preview media through Media viewer and trigger preview event', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee26() {
962
+ var _getElement2;
963
+ var Demo, _mount26, instance, element, previewTrigger;
965
964
  return _regeneratorRuntime.wrap(function _callee26$(_context52) {
966
965
  while (1) switch (_context52.prev = _context52.next) {
967
966
  case 0:
@@ -977,25 +976,35 @@ describe('FileCard', function () {
977
976
  _this26.FileCard = FileCard;
978
977
  return _this26;
979
978
  }
979
+ Demo.defaults = function defaults() {
980
+ return {
981
+ previewCount: 0
982
+ };
983
+ };
980
984
  return Demo;
981
985
  }(Component);
982
- Demo.template = "\n const { FileCard } = this;\n <div>\n <FileCard name=\"cover.png\" type=\"image\" status=\"done\" showPreview={false} src=\"https://example.com/cover.png\" />\n <FileCard name=\"clip.mp4\" type=\"file\" showPreview={false} src=\"https://example.com/clip.mp4\" />\n </div>\n ";
983
- _mount26 = mount(Demo), element = _mount26[1];
984
- expect(element.querySelector('.k-media-preview-trigger')).to.eql(null);
985
- case 4:
986
+ Demo.template = "\n const { FileCard } = this;\n <div>\n <FileCard\n name=\"cover.png\"\n type=\"image\"\n status=\"done\"\n src=\"https://example.com/cover.png\"\n ev-preview={() => this.set('previewCount', this.get('previewCount') + 1)}\n />\n </div>\n ";
987
+ _mount26 = mount(Demo), instance = _mount26[0], element = _mount26[1];
988
+ previewTrigger = element.querySelector('.k-media-preview-trigger');
989
+ previewTrigger.click();
990
+ _context52.next = 7;
991
+ return wait();
992
+ case 7:
993
+ expect(instance.get('previewCount')).to.eql(1);
994
+ expect(getElement('.k-media-viewer')).not.to.eql(null);
995
+ expect((_getElement2 = getElement('.k-media-viewer-title')) == null ? void 0 : _getElement2.textContent).to.contain('cover.png');
996
+ case 10:
986
997
  case "end":
987
998
  return _context52.stop();
988
999
  }
989
1000
  }, _callee26);
990
1001
  })));
991
- // FileCardList 继承默认尺寸、删除开关,并透传新增的 loadingText。
992
- it('should proxy FileCardList props and events', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee27() {
993
- var _element$querySelecto15;
994
- var calls, Demo, _mount27, element, card, button;
1002
+ // showPreview=false 会同步关闭显式媒体和文件行媒体缩略图的预览入口。
1003
+ it('should disable preview for media and file media thumbnail', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee27() {
1004
+ var Demo, _mount27, element;
995
1005
  return _regeneratorRuntime.wrap(function _callee27$(_context54) {
996
1006
  while (1) switch (_context54.prev = _context54.next) {
997
1007
  case 0:
998
- calls = [];
999
1008
  Demo = /*#__PURE__*/function (_Component27) {
1000
1009
  _inheritsLoose(Demo, _Component27);
1001
1010
  function Demo() {
@@ -1005,37 +1014,28 @@ describe('FileCard', function () {
1005
1014
  args[_key27] = arguments[_key27];
1006
1015
  }
1007
1016
  _this27 = _Component27.call.apply(_Component27, _concatInstanceProperty(_context53 = [this]).call(_context53, args)) || this;
1008
- _this27.FileCardList = FileCardList;
1009
- _this27.onDelete = function (item) {
1010
- calls.push(item.key);
1011
- };
1017
+ _this27.FileCard = FileCard;
1012
1018
  return _this27;
1013
1019
  }
1014
1020
  return Demo;
1015
1021
  }(Component);
1016
- Demo.template = "\n const { FileCardList } = this;\n <FileCardList\n size=\"small\"\n deleteable\n items={[\n {key: 'a', name: 'a.pdf', status: 'loading', percent: 10, loadingText: '\u4E0A\u4F20\u4E2D'},\n ]}\n ev-delete={this.onDelete}\n />\n ";
1022
+ Demo.template = "\n const { FileCard } = this;\n <div>\n <FileCard name=\"cover.png\" type=\"image\" status=\"done\" showPreview={false} src=\"https://example.com/cover.png\" />\n <FileCard name=\"clip.mp4\" type=\"file\" showPreview={false} src=\"https://example.com/clip.mp4\" />\n </div>\n ";
1017
1023
  _mount27 = mount(Demo), element = _mount27[1];
1018
- card = element.querySelector('.k-file-card');
1019
- button = element.querySelector('.k-file-card-delete');
1020
- expect(card.className).to.contain('k-file-card-small');
1021
- expect((_element$querySelecto15 = element.querySelector('.k-file-card-description')) == null ? void 0 : _element$querySelecto15.textContent).to.contain('上传中... 10%');
1022
- button.click();
1023
- _context54.next = 11;
1024
- return wait();
1025
- case 11:
1026
- expect(calls).to.eql(['a']);
1027
- case 12:
1024
+ expect(element.querySelector('.k-media-preview-trigger')).to.eql(null);
1025
+ case 4:
1028
1026
  case "end":
1029
1027
  return _context54.stop();
1030
1028
  }
1031
1029
  }, _callee27);
1032
1030
  })));
1033
- // FileCardList extension 插槽为空时,不保留额外 flex item
1034
- it('should not render extension wrapper when extension slot is empty', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee28() {
1035
- var Demo, _mount28, element;
1031
+ // FileCardList 继承默认尺寸、删除开关,并透传新增的 loadingText
1032
+ it('should proxy FileCardList props and events', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee28() {
1033
+ var _element$querySelecto12;
1034
+ var calls, Demo, _mount28, element, card, button;
1036
1035
  return _regeneratorRuntime.wrap(function _callee28$(_context56) {
1037
1036
  while (1) switch (_context56.prev = _context56.next) {
1038
1037
  case 0:
1038
+ calls = [];
1039
1039
  Demo = /*#__PURE__*/function (_Component28) {
1040
1040
  _inheritsLoose(Demo, _Component28);
1041
1041
  function Demo() {
@@ -1046,22 +1046,33 @@ describe('FileCard', function () {
1046
1046
  }
1047
1047
  _this28 = _Component28.call.apply(_Component28, _concatInstanceProperty(_context55 = [this]).call(_context55, args)) || this;
1048
1048
  _this28.FileCardList = FileCardList;
1049
+ _this28.onDelete = function (item) {
1050
+ calls.push(item.key);
1051
+ };
1049
1052
  return _this28;
1050
1053
  }
1051
1054
  return Demo;
1052
1055
  }(Component);
1053
- Demo.template = "\n const { FileCardList } = this;\n <FileCardList\n items={[{key: 'a', name: 'a.pdf'}]}\n >\n <b:extension>\n <button v-if={false} class=\"empty-extension\" type=\"button\">add</button>\n </b:extension>\n </FileCardList>\n ";
1056
+ Demo.template = "\n const { FileCardList } = this;\n <FileCardList\n size=\"small\"\n deleteable\n items={[\n {key: 'a', name: 'a.pdf', status: 'loading', percent: 10, loadingText: '\u4E0A\u4F20\u4E2D'},\n ]}\n ev-delete={this.onDelete}\n />\n ";
1054
1057
  _mount28 = mount(Demo), element = _mount28[1];
1055
- expect(element.querySelector('.k-file-card-list-extension')).to.eql(null);
1056
- case 4:
1058
+ card = element.querySelector('.k-file-card');
1059
+ button = element.querySelector('.k-file-card-delete');
1060
+ expect(card.className).to.contain('k-file-card-small');
1061
+ expect((_element$querySelecto12 = element.querySelector('.k-file-card-description')) == null ? void 0 : _element$querySelecto12.textContent).to.contain('上传中... 10%');
1062
+ button.click();
1063
+ _context56.next = 11;
1064
+ return wait();
1065
+ case 11:
1066
+ expect(calls).to.eql(['a']);
1067
+ case 12:
1057
1068
  case "end":
1058
1069
  return _context56.stop();
1059
1070
  }
1060
1071
  }, _callee28);
1061
1072
  })));
1062
- // 删除角标回到卡片内后,列表容器不再需要额外顶部留白。
1063
- it('should not add top padding for delete icon in lists', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee29() {
1064
- var Demo, _mount29, element, listWrap, listX, listY;
1073
+ // FileCardList 的 prefix/suffix 插槽为空时,不保留额外 flex item。
1074
+ it('should not render prefix or suffix wrapper when slots are empty', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee29() {
1075
+ var Demo, _mount29, element;
1065
1076
  return _regeneratorRuntime.wrap(function _callee29$(_context58) {
1066
1077
  while (1) switch (_context58.prev = _context58.next) {
1067
1078
  case 0:
@@ -1079,8 +1090,69 @@ describe('FileCard', function () {
1079
1090
  }
1080
1091
  return Demo;
1081
1092
  }(Component);
1082
- Demo.template = "\n const { FileCardList } = this;\n <div>\n <FileCardList\n className=\"wrap-list\"\n overflow=\"wrap\"\n deleteable\n items={[\n {key: 'c', name: 'c.pdf', type: 'file'},\n ]}\n />\n <FileCardList\n className=\"scroll-x-list\"\n overflow=\"scrollX\"\n deleteable\n items={[\n {key: 'a', name: 'a.pdf', type: 'file'},\n ]}\n />\n <FileCardList\n className=\"scroll-y-list\"\n overflow=\"scrollY\"\n deleteable\n items={[\n {key: 'b', name: 'b.pdf', type: 'file'},\n ]}\n />\n </div>\n ";
1093
+ Demo.template = "\n const { FileCardList } = this;\n <FileCardList\n items={[{key: 'a', name: 'a.pdf'}]}\n >\n <b:prefix>\n <button v-if={false} class=\"empty-prefix\" type=\"button\">add</button>\n </b:prefix>\n <b:suffix>\n <button v-if={false} class=\"empty-suffix\" type=\"button\">more</button>\n </b:suffix>\n </FileCardList>\n ";
1083
1094
  _mount29 = mount(Demo), element = _mount29[1];
1095
+ expect(element.querySelector('.k-file-card-list-prefix')).to.eql(null);
1096
+ expect(element.querySelector('.k-file-card-list-suffix')).to.eql(null);
1097
+ case 5:
1098
+ case "end":
1099
+ return _context58.stop();
1100
+ }
1101
+ }, _callee29);
1102
+ })));
1103
+ it('should render prefix before items and suffix after items', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee30() {
1104
+ var Demo, _mount30, element, list;
1105
+ return _regeneratorRuntime.wrap(function _callee30$(_context60) {
1106
+ while (1) switch (_context60.prev = _context60.next) {
1107
+ case 0:
1108
+ Demo = /*#__PURE__*/function (_Component30) {
1109
+ _inheritsLoose(Demo, _Component30);
1110
+ function Demo() {
1111
+ var _context59;
1112
+ var _this30;
1113
+ for (var _len30 = arguments.length, args = new Array(_len30), _key30 = 0; _key30 < _len30; _key30++) {
1114
+ args[_key30] = arguments[_key30];
1115
+ }
1116
+ _this30 = _Component30.call.apply(_Component30, _concatInstanceProperty(_context59 = [this]).call(_context59, args)) || this;
1117
+ _this30.FileCardList = FileCardList;
1118
+ return _this30;
1119
+ }
1120
+ return Demo;
1121
+ }(Component);
1122
+ Demo.template = "\n const { FileCardList } = this;\n <FileCardList\n items={[{key: 'a', name: 'a.pdf'}]}\n >\n <b:prefix>\n <button class=\"prefix-action\" type=\"button\">add</button>\n </b:prefix>\n <b:suffix>\n <button class=\"suffix-action\" type=\"button\">more</button>\n </b:suffix>\n </FileCardList>\n ";
1123
+ _mount30 = mount(Demo), element = _mount30[1];
1124
+ list = element.classList.contains('k-file-card-list') ? element : element.querySelector('.k-file-card-list');
1125
+ expect(list.children[0].className).to.contain('k-file-card-list-prefix');
1126
+ expect(list.children[1].className).to.contain('k-file-card');
1127
+ expect(list.children[2].className).to.contain('k-file-card-list-suffix');
1128
+ case 7:
1129
+ case "end":
1130
+ return _context60.stop();
1131
+ }
1132
+ }, _callee30);
1133
+ })));
1134
+ // 删除角标回到卡片内后,列表容器不再需要额外顶部留白。
1135
+ it('should not add top padding for delete icon in lists', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee31() {
1136
+ var Demo, _mount31, element, listWrap, listX, listY;
1137
+ return _regeneratorRuntime.wrap(function _callee31$(_context62) {
1138
+ while (1) switch (_context62.prev = _context62.next) {
1139
+ case 0:
1140
+ Demo = /*#__PURE__*/function (_Component31) {
1141
+ _inheritsLoose(Demo, _Component31);
1142
+ function Demo() {
1143
+ var _context61;
1144
+ var _this31;
1145
+ for (var _len31 = arguments.length, args = new Array(_len31), _key31 = 0; _key31 < _len31; _key31++) {
1146
+ args[_key31] = arguments[_key31];
1147
+ }
1148
+ _this31 = _Component31.call.apply(_Component31, _concatInstanceProperty(_context61 = [this]).call(_context61, args)) || this;
1149
+ _this31.FileCardList = FileCardList;
1150
+ return _this31;
1151
+ }
1152
+ return Demo;
1153
+ }(Component);
1154
+ Demo.template = "\n const { FileCardList } = this;\n <div>\n <FileCardList\n className=\"wrap-list\"\n overflow=\"wrap\"\n deleteable\n items={[\n {key: 'c', name: 'c.pdf', type: 'file'},\n ]}\n />\n <FileCardList\n className=\"scroll-x-list\"\n overflow=\"scrollX\"\n deleteable\n items={[\n {key: 'a', name: 'a.pdf', type: 'file'},\n ]}\n />\n <FileCardList\n className=\"scroll-y-list\"\n overflow=\"scrollY\"\n deleteable\n items={[\n {key: 'b', name: 'b.pdf', type: 'file'},\n ]}\n />\n </div>\n ";
1155
+ _mount31 = mount(Demo), element = _mount31[1];
1084
1156
  listWrap = element.querySelector('.wrap-list');
1085
1157
  listX = element.querySelector('.scroll-x-list');
1086
1158
  listY = element.querySelector('.scroll-y-list');
@@ -1089,8 +1161,8 @@ describe('FileCard', function () {
1089
1161
  expect(getComputedStyle(listY).paddingTop).to.eql('0px');
1090
1162
  case 9:
1091
1163
  case "end":
1092
- return _context58.stop();
1164
+ return _context62.stop();
1093
1165
  }
1094
- }, _callee29);
1166
+ }, _callee31);
1095
1167
  })));
1096
1168
  });
@@ -12,7 +12,8 @@ export interface FileCardListProps {
12
12
  showNameTooltip?: boolean;
13
13
  }
14
14
  export interface FileCardListBlocks {
15
- extension: null;
15
+ prefix: null;
16
+ suffix: null;
16
17
  }
17
18
  export interface FileCardListEvents {
18
19
  preview: [FileCardListItem, MouseEvent];