niuma-ui 2.0.3 → 2.0.4

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 (202) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/components/_shared/src/reka.d.ts +1 -1
  3. package/dist/components/_shared/src/reka.js +2 -2
  4. package/dist/components/anchor/index.d.ts +1 -1
  5. package/dist/components/anchor/src/RsAnchor.css +63 -32
  6. package/dist/components/anchor/src/RsAnchor.d.ts +29 -2
  7. package/dist/components/anchor/src/RsAnchor.impl.js +199 -81
  8. package/dist/components/anchor/src/RsAnchor.js +1 -1
  9. package/dist/components/anchor/src/anchor-utils.d.ts +36 -4
  10. package/dist/components/anchor/src/anchor-utils.js +81 -19
  11. package/dist/components/auto-complete/index.d.ts +2 -0
  12. package/dist/components/auto-complete/src/RsAutoComplete.css +122 -0
  13. package/dist/components/auto-complete/src/RsAutoComplete.d.ts +47 -7
  14. package/dist/components/auto-complete/src/RsAutoComplete.impl.js +180 -72
  15. package/dist/components/auto-complete/src/RsAutoComplete.js +4 -1
  16. package/dist/components/auto-complete/src/auto-complete-utils.d.ts +7 -0
  17. package/dist/components/auto-complete/src/auto-complete-utils.js +17 -0
  18. package/dist/components/avatar/index.d.ts +1 -0
  19. package/dist/components/avatar/src/RsAvatar.css +36 -19
  20. package/dist/components/avatar/src/RsAvatar.d.ts +9 -3
  21. package/dist/components/avatar/src/RsAvatar.impl.js +57 -33
  22. package/dist/components/avatar/src/RsAvatar.js +2 -1
  23. package/dist/components/avatar/src/avatar-utils.d.ts +16 -7
  24. package/dist/components/avatar/src/avatar-utils.js +41 -3
  25. package/dist/components/breadcrumb/index.d.ts +1 -1
  26. package/dist/components/breadcrumb/src/RsBreadcrumb.css +50 -17
  27. package/dist/components/breadcrumb/src/RsBreadcrumb.d.ts +45 -6
  28. package/dist/components/breadcrumb/src/RsBreadcrumb.impl.js +111 -12
  29. package/dist/components/breadcrumb/src/RsBreadcrumb.js +2 -1
  30. package/dist/components/breadcrumb/src/breadcrumb-utils.d.ts +37 -5
  31. package/dist/components/breadcrumb/src/breadcrumb-utils.js +70 -9
  32. package/dist/components/calendar-grid/index.d.ts +2 -0
  33. package/dist/components/calendar-grid/src/RsCalendarGrid.css +105 -45
  34. package/dist/components/calendar-grid/src/RsCalendarGrid.d.ts +62 -2
  35. package/dist/components/calendar-grid/src/RsCalendarGrid.impl.js +265 -94
  36. package/dist/components/calendar-grid/src/RsCalendarGrid.js +1 -1
  37. package/dist/components/calendar-grid/src/calendar-grid-utils.d.ts +72 -0
  38. package/dist/components/calendar-grid/src/calendar-grid-utils.js +122 -0
  39. package/dist/components/card/index.d.ts +1 -1
  40. package/dist/components/card/src/RsCard.css +108 -98
  41. package/dist/components/card/src/RsCard.d.ts +3 -12
  42. package/dist/components/card/src/RsCard.impl.js +29 -25
  43. package/dist/components/card/src/RsCard.js +2 -1
  44. package/dist/components/card/src/card-utils.d.ts +25 -0
  45. package/dist/components/card/src/card-utils.js +10 -0
  46. package/dist/components/cascader/index.d.ts +1 -0
  47. package/dist/components/cascader/src/RsCascader.css +175 -30
  48. package/dist/components/cascader/src/RsCascader.d.ts +15 -3
  49. package/dist/components/cascader/src/RsCascader.impl.js +277 -48
  50. package/dist/components/cascader/src/RsCascader.js +1 -1
  51. package/dist/components/cascader/src/cascader-utils.d.ts +2 -0
  52. package/dist/components/cascader/src/cascader-utils.js +8 -1
  53. package/dist/components/checkbox/index.d.ts +1 -0
  54. package/dist/components/checkbox/src/RsCheckbox.css +46 -23
  55. package/dist/components/checkbox/src/RsCheckbox.d.ts +11 -1
  56. package/dist/components/checkbox/src/RsCheckbox.impl.js +37 -9
  57. package/dist/components/checkbox/src/RsCheckbox.js +2 -1
  58. package/dist/components/checkbox/src/checkbox-utils.d.ts +4 -0
  59. package/dist/components/checkbox/src/checkbox-utils.js +12 -0
  60. package/dist/components/container/index.d.ts +1 -1
  61. package/dist/components/container/src/RsContainer.css +11 -11
  62. package/dist/components/container/src/RsContainer.d.ts +2 -12
  63. package/dist/components/container/src/RsContainer.impl.js +10 -57
  64. package/dist/components/container/src/RsContainer.js +1 -1
  65. package/dist/components/container/src/container-utils.d.ts +23 -0
  66. package/dist/components/container/src/container-utils.js +51 -0
  67. package/dist/components/date-picker/index.d.ts +4 -2
  68. package/dist/components/date-picker/src/RsDatePicker.css +42 -22
  69. package/dist/components/date-picker/src/RsDatePicker.d.ts +44 -20
  70. package/dist/components/date-picker/src/RsDatePicker.impl.js +484 -222
  71. package/dist/components/date-picker/src/RsDatePicker.js +1 -3
  72. package/dist/components/date-picker/src/RsDateTimePicker.d.ts +33 -6
  73. package/dist/components/date-picker/src/RsDateTimePicker.impl.js +47 -6
  74. package/dist/components/date-picker/src/date-picker-utils.d.ts +19 -0
  75. package/dist/components/date-picker/src/date-picker-utils.js +33 -10
  76. package/dist/components/dynamic-tags/index.d.ts +1 -1
  77. package/dist/components/dynamic-tags/src/RsDynamicTags.css +115 -38
  78. package/dist/components/dynamic-tags/src/RsDynamicTags.d.ts +58 -17
  79. package/dist/components/dynamic-tags/src/RsDynamicTags.impl.js +269 -106
  80. package/dist/components/dynamic-tags/src/RsDynamicTags.js +1 -1
  81. package/dist/components/dynamic-tags/src/dynamic-tags-utils.d.ts +19 -0
  82. package/dist/components/dynamic-tags/src/dynamic-tags-utils.js +60 -0
  83. package/dist/components/fieldset/src/RsFieldset.css +71 -41
  84. package/dist/components/fieldset/src/RsFieldset.d.ts +21 -2
  85. package/dist/components/fieldset/src/RsFieldset.impl.js +93 -26
  86. package/dist/components/fieldset/src/RsFieldset.js +1 -1
  87. package/dist/components/fieldset/src/fieldset-utils.d.ts +4 -0
  88. package/dist/components/fieldset/src/fieldset-utils.js +9 -1
  89. package/dist/components/form/index.d.ts +1 -0
  90. package/dist/components/form/src/RsForm.css +15 -12
  91. package/dist/components/form/src/RsForm.d.ts +20 -22
  92. package/dist/components/form/src/RsForm.impl.js +33 -20
  93. package/dist/components/form/src/RsForm.js +1 -1
  94. package/dist/components/form/src/form-utils.d.ts +7 -0
  95. package/dist/components/form/src/form-utils.js +28 -1
  96. package/dist/components/input/index.d.ts +1 -1
  97. package/dist/components/input/src/RsInput.css +78 -260
  98. package/dist/components/input/src/RsInput.d.ts +5 -3
  99. package/dist/components/input/src/RsInput.impl.js +8 -16
  100. package/dist/components/input/src/RsInput.js +1 -1
  101. package/dist/components/input/src/input-utils.d.ts +11 -0
  102. package/dist/components/input/src/input-utils.js +22 -0
  103. package/dist/components/input-number/index.d.ts +1 -0
  104. package/dist/components/input-number/src/RsInputNumber.css +31 -31
  105. package/dist/components/input-number/src/RsInputNumber.d.ts +15 -13
  106. package/dist/components/input-number/src/RsInputNumber.impl.js +17 -4
  107. package/dist/components/input-number/src/RsInputNumber.js +1 -1
  108. package/dist/components/label/src/RsLabel.css +30 -11
  109. package/dist/components/label/src/RsLabel.d.ts +18 -1
  110. package/dist/components/label/src/RsLabel.impl.js +63 -10
  111. package/dist/components/label/src/RsLabel.js +1 -1
  112. package/dist/components/label/src/label-utils.d.ts +6 -0
  113. package/dist/components/label/src/label-utils.js +16 -0
  114. package/dist/components/link/src/RsLink.d.ts +2 -2
  115. package/dist/components/loading/src/RsLoading.d.ts +1 -1
  116. package/dist/components/mentions/index.d.ts +2 -1
  117. package/dist/components/mentions/src/RsMentions.css +119 -3
  118. package/dist/components/mentions/src/RsMentions.d.ts +56 -4
  119. package/dist/components/mentions/src/RsMentions.impl.js +298 -79
  120. package/dist/components/mentions/src/RsMentions.js +1 -3
  121. package/dist/components/mentions/src/mentions-utils.d.ts +5 -1
  122. package/dist/components/mentions/src/mentions-utils.js +28 -9
  123. package/dist/components/popover/src/RsPopover.d.ts +1 -1
  124. package/dist/components/radio/index.d.ts +1 -1
  125. package/dist/components/radio/src/RsRadio.css +7 -6
  126. package/dist/components/radio/src/RsRadio.d.ts +8 -5
  127. package/dist/components/radio/src/RsRadio.impl.js +34 -24
  128. package/dist/components/radio/src/RsRadio.js +2 -1
  129. package/dist/components/radio/src/RsRadioItem.css +61 -44
  130. package/dist/components/radio/src/RsRadioItem.d.ts +2 -2
  131. package/dist/components/radio/src/RsRadioItem.impl.js +53 -20
  132. package/dist/components/radio/src/RsRadioItem.js +2 -1
  133. package/dist/components/radio/src/radio-utils.d.ts +12 -1
  134. package/dist/components/radio/src/radio-utils.js +15 -1
  135. package/dist/components/scrollbar/src/RsScrollbar.css +71 -24
  136. package/dist/components/scrollbar/src/RsScrollbar.d.ts +9 -5
  137. package/dist/components/scrollbar/src/RsScrollbar.impl.js +372 -47
  138. package/dist/components/scrollbar/src/RsScrollbar.js +2 -1
  139. package/dist/components/scrollbar/src/scrollbar-utils.d.ts +34 -2
  140. package/dist/components/scrollbar/src/scrollbar-utils.js +64 -1
  141. package/dist/components/select/index.d.ts +1 -0
  142. package/dist/components/select/src/RsSelect.css +54 -42
  143. package/dist/components/select/src/RsSelect.d.ts +19 -2
  144. package/dist/components/select/src/RsSelect.impl.js +727 -312
  145. package/dist/components/select/src/RsSelect.js +1 -1
  146. package/dist/components/select/src/select-utils.d.ts +4 -2
  147. package/dist/components/select/src/select-utils.js +8 -3
  148. package/dist/components/select/src/use-rs-select.d.ts +1 -0
  149. package/dist/components/select/src/use-rs-select.js +23 -17
  150. package/dist/components/switch/index.d.ts +2 -1
  151. package/dist/components/switch/src/RsSwitch.css +36 -18
  152. package/dist/components/switch/src/RsSwitch.d.ts +18 -5
  153. package/dist/components/switch/src/RsSwitch.impl.js +61 -29
  154. package/dist/components/switch/src/RsSwitch.js +2 -1
  155. package/dist/components/switch/src/switch-utils.d.ts +4 -0
  156. package/dist/components/switch/src/switch-utils.js +9 -0
  157. package/dist/components/textarea/src/RsTextarea.css +23 -23
  158. package/dist/components/textarea/src/RsTextarea.d.ts +6 -12
  159. package/dist/components/textarea/src/RsTextarea.impl.js +37 -46
  160. package/dist/components/textarea/src/RsTextarea.js +1 -1
  161. package/dist/components/textarea/src/textarea-utils.d.ts +27 -0
  162. package/dist/components/textarea/src/textarea-utils.js +61 -0
  163. package/dist/components/time-picker/index.d.ts +3 -2
  164. package/dist/components/time-picker/src/RsTimePicker.css +41 -24
  165. package/dist/components/time-picker/src/RsTimePicker.d.ts +52 -7
  166. package/dist/components/time-picker/src/RsTimePicker.impl.js +520 -156
  167. package/dist/components/time-picker/src/RsTimePicker.js +1 -3
  168. package/dist/components/time-picker/src/RsTimePickerColumns.css +26 -18
  169. package/dist/components/time-picker/src/RsTimePickerColumns.d.ts +3 -1
  170. package/dist/components/time-picker/src/RsTimePickerColumns.impl.js +62 -9
  171. package/dist/components/time-picker/src/RsTimePickerColumns.js +1 -1
  172. package/dist/components/time-picker/src/time-picker-utils.d.ts +38 -0
  173. package/dist/components/time-picker/src/time-picker-utils.js +97 -5
  174. package/dist/components/toaster/src/RsToaster.d.ts +1 -1
  175. package/dist/components/tooltip/src/RsTooltip.d.ts +1 -1
  176. package/dist/components/tree/src/RsTree.d.ts +3 -3
  177. package/dist/components/tree-select/index.d.ts +2 -0
  178. package/dist/components/tree-select/src/RsTreeSelect.css +100 -25
  179. package/dist/components/tree-select/src/RsTreeSelect.d.ts +91 -7
  180. package/dist/components/tree-select/src/RsTreeSelect.impl.js +464 -79
  181. package/dist/components/tree-select/src/RsTreeSelect.js +1 -1
  182. package/dist/components/tree-select/src/tree-select-utils.d.ts +20 -0
  183. package/dist/components/tree-select/src/tree-select-utils.js +60 -0
  184. package/dist/components/upload/index.d.ts +2 -1
  185. package/dist/components/upload/src/RsUpload.css +223 -75
  186. package/dist/components/upload/src/RsUpload.d.ts +77 -1
  187. package/dist/components/upload/src/RsUpload.impl.js +404 -90
  188. package/dist/components/upload/src/RsUpload.js +1 -1
  189. package/dist/components/upload/src/upload-utils.d.ts +21 -2
  190. package/dist/components/upload/src/upload-utils.js +139 -9
  191. package/dist/index.d.ts +21 -11
  192. package/dist/index.js +6 -0
  193. package/dist/locale/messages.js +46 -2
  194. package/dist/styles.css +518 -154
  195. package/dist/theme/brand.example.css +1 -1
  196. package/package.json +1 -1
  197. package/dist/components/breadcrumb/src/RsBreadcrumbItems.d.ts +0 -8
  198. package/dist/components/breadcrumb/src/RsBreadcrumbItems.impl.js +0 -40
  199. package/dist/components/breadcrumb/src/RsBreadcrumbItems.js +0 -5
  200. package/dist/components/date-picker/src/RsDatePicker-1.css +0 -157
  201. package/dist/components/mentions/src/RsMentions-1.css +0 -29
  202. package/dist/components/time-picker/src/RsTimePicker-1.css +0 -98
@@ -1,35 +1,68 @@
1
+ import { RS_COMPONENT_SIZE_ICON_PX } from "../../../theme/types.js";
1
2
  import { useRsI18n } from "../../../composables/useRsI18n.js";
2
3
  import RsIcon_default from "../../icon/src/RsIcon.js";
3
- import { downloadUploadFile, formatFileSize, mergeUploadFiles, removeUploadFileAt, resolveUploadFileIcon, validateUploadFiles } from "./upload-utils.js";
4
- import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeModels, normalizeClass, openBlock, ref, renderList, toDisplayString, unref, useModel, withModifiers } from "vue";
4
+ import { useRsFormContext, useRsFormField } from "../../form/src/form-utils.js";
5
+ import { useResolvedRsComponentSize } from "../../_shared/src/resolve-size.js";
6
+ import { collectDroppedFiles, createUploadObjectUrl, downloadUploadFile, droppedDataHasDirectory, formatFileSize, mergeUploadFiles, nextUploadPreviewUrls, pruneBrokenUploadPreview, removeUploadFileAt, resolveUploadCapture, resolveUploadFileIcon, revokeUploadObjectUrl, skipDuplicateUploadFiles, validateUploadFiles } from "./upload-utils.js";
7
+ import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeModels, mergeProps, normalizeClass, onUnmounted, openBlock, renderList, renderSlot, shallowRef, toDisplayString, unref, useId, useModel, watch, withModifiers } from "vue";
5
8
  //#region src/components/upload/src/RsUpload.vue?vue&type=script&setup=true&lang.ts
6
- var _hoisted_1 = { class: "rs-upload" };
9
+ var _hoisted_1 = ["aria-disabled"];
7
10
  var _hoisted_2 = [
11
+ "id",
8
12
  "accept",
9
13
  "multiple",
10
- "disabled"
14
+ "disabled",
15
+ "aria-label"
11
16
  ];
12
- var _hoisted_3 = {
17
+ var _hoisted_3 = ["for"];
18
+ var _hoisted_4 = {
13
19
  class: "rs-upload__icon",
14
20
  "aria-hidden": "true"
15
21
  };
16
- var _hoisted_4 = { class: "rs-upload__text" };
17
- var _hoisted_5 = { class: "rs-upload__label" };
18
- var _hoisted_6 = { class: "rs-upload__hint" };
19
- var _hoisted_7 = {
20
- key: 1,
21
- class: "rs-upload__list"
22
- };
23
- var _hoisted_8 = { class: "rs-upload__file-meta" };
24
- var _hoisted_9 = { class: "rs-upload__file-name" };
25
- var _hoisted_10 = { class: "rs-upload__file-size" };
22
+ var _hoisted_5 = { class: "rs-upload__text" };
23
+ var _hoisted_6 = { class: "rs-upload__label" };
24
+ var _hoisted_7 = { class: "rs-upload__hint" };
25
+ var _hoisted_8 = ["disabled", "aria-label"];
26
+ var _hoisted_9 = ["id", "aria-label"];
27
+ var _hoisted_10 = [
28
+ "aria-label",
29
+ "title",
30
+ "onClick"
31
+ ];
26
32
  var _hoisted_11 = [
33
+ "src",
34
+ "alt",
35
+ "onError"
36
+ ];
37
+ var _hoisted_12 = {
38
+ key: 2,
39
+ class: "rs-upload__file-meta"
40
+ };
41
+ var _hoisted_13 = { class: "rs-upload__file-name" };
42
+ var _hoisted_14 = { class: "rs-upload__file-size" };
43
+ var _hoisted_15 = {
44
+ key: 3,
45
+ class: "rs-upload__file-name rs-upload__file-name--card"
46
+ };
47
+ var _hoisted_16 = { class: "rs-upload__file-actions" };
48
+ var _hoisted_17 = [
27
49
  "aria-label",
28
50
  "title",
29
51
  "onClick"
30
52
  ];
31
- var _hoisted_12 = ["aria-label", "onClick"];
53
+ var _hoisted_18 = ["aria-label", "onClick"];
54
+ var _hoisted_19 = {
55
+ key: 0,
56
+ class: "rs-upload__file rs-upload__file--card rs-upload__file--add"
57
+ };
58
+ var _hoisted_20 = ["for"];
59
+ var _hoisted_21 = {
60
+ class: "rs-upload__icon",
61
+ "aria-hidden": "true"
62
+ };
63
+ var _hoisted_22 = { class: "rs-upload__label" };
32
64
  var RsUpload_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
65
+ name: "RsUpload",
33
66
  __name: "RsUpload",
34
67
  props: /*@__PURE__*/ mergeModels({
35
68
  accept: {},
@@ -56,7 +89,36 @@ var RsUpload_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineC
56
89
  hideDropzoneWhenFull: {
57
90
  type: Boolean,
58
91
  default: false
59
- }
92
+ },
93
+ size: {},
94
+ id: {},
95
+ name: {},
96
+ ariaLabel: {},
97
+ listType: { default: "text" },
98
+ variant: { default: "dropzone" },
99
+ directory: {
100
+ type: Boolean,
101
+ default: false
102
+ },
103
+ capture: { type: [Boolean, String] },
104
+ replace: {
105
+ type: Boolean,
106
+ default: false
107
+ },
108
+ paste: {
109
+ type: Boolean,
110
+ default: true
111
+ },
112
+ skipDuplicate: {
113
+ type: Boolean,
114
+ default: false
115
+ },
116
+ showPreview: {
117
+ type: Boolean,
118
+ default: false
119
+ },
120
+ beforeSelect: {},
121
+ beforeRemove: {}
60
122
  }, {
61
123
  "modelValue": { default: () => [] },
62
124
  "modelModifiers": {}
@@ -64,30 +126,125 @@ var RsUpload_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineC
64
126
  emits: /*@__PURE__*/ mergeModels([
65
127
  "reject",
66
128
  "download",
67
- "remove"
129
+ "remove",
130
+ "change",
131
+ "preview"
68
132
  ], ["update:modelValue"]),
69
- setup(__props, { emit: __emit }) {
133
+ setup(__props, { expose: __expose, emit: __emit }) {
70
134
  const model = useModel(__props, "modelValue");
71
135
  const props = __props;
72
136
  const emit = __emit;
73
- const { t } = useRsI18n();
74
- const dragging = ref(false);
75
- const dragDepth = ref(0);
137
+ const { t, locale } = useRsI18n();
138
+ const formContext = useRsFormContext();
139
+ const resolvedSize = useResolvedRsComponentSize(() => props.size);
140
+ const autoId = useId();
141
+ const listLabelId = useId();
142
+ const inputRef = shallowRef(null);
143
+ const triggerRef = shallowRef(null);
144
+ const dragging = shallowRef(false);
145
+ const dragDepth = shallowRef(0);
146
+ const previewUrls = shallowRef(/* @__PURE__ */ new Map());
147
+ const brokenPreview = shallowRef(/* @__PURE__ */ new Set());
148
+ let applySeq = 0;
149
+ let removeSeq = 0;
150
+ let dragResetBound = false;
151
+ const inputId = computed(() => props.id || autoId);
152
+ const resolvedDisabled = computed(() => props.disabled || Boolean(formContext?.disabled.value));
153
+ const allowMultiple = computed(() => props.multiple || props.directory);
76
154
  const canAdd = computed(() => !props.maxCount || model.value.length < props.maxCount);
77
- const isDropzoneDisabled = computed(() => props.disabled || !canAdd.value);
155
+ const isDropzoneDisabled = computed(() => resolvedDisabled.value || !canAdd.value);
78
156
  const showDropzone = computed(() => !(props.hideDropzoneWhenFull && props.maxCount != null && model.value.length >= props.maxCount));
157
+ const isPictureCard = computed(() => props.listType === "picture-card");
158
+ const showPicturePreview = computed(() => props.showPreview || props.listType !== "text");
159
+ const showBlockDropzone = computed(() => showDropzone.value && props.variant === "dropzone" && !isPictureCard.value);
160
+ const showAddTile = computed(() => showDropzone.value && props.variant === "dropzone" && isPictureCard.value);
161
+ const showButton = computed(() => props.variant === "button");
79
162
  const resolvedHint = computed(() => {
80
163
  if (dragging.value && !isDropzoneDisabled.value) return t("upload.dropActive");
81
164
  return props.hint ?? t("upload.browse");
82
165
  });
166
+ const resolvedCapture = computed(() => resolveUploadCapture(props.capture));
167
+ const inputExtraAttrs = computed(() => {
168
+ const attrs = {};
169
+ if (props.directory) {
170
+ attrs.webkitdirectory = "";
171
+ attrs.directory = "";
172
+ }
173
+ if (resolvedCapture.value) attrs.capture = resolvedCapture.value;
174
+ return attrs;
175
+ });
176
+ const dropIconPx = computed(() => {
177
+ return {
178
+ ssm: 16,
179
+ sm: 18,
180
+ md: 22,
181
+ lg: 26
182
+ }[resolvedSize.value];
183
+ });
184
+ const fileIconPx = computed(() => RS_COMPONENT_SIZE_ICON_PX[resolvedSize.value]);
185
+ const fileViews = computed(() => model.value.map((file, index) => {
186
+ const icon = resolveUploadFileIcon(file);
187
+ const previewUrl = previewUrls.value.get(file);
188
+ const broken = brokenPreview.value.has(file);
189
+ return {
190
+ file,
191
+ index,
192
+ key: `${file.name}-${file.size}-${file.lastModified}-${index}`,
193
+ icon,
194
+ image: Boolean(previewUrl) && !broken,
195
+ previewUrl,
196
+ sizeText: formatFileSize(file.size, locale.value)
197
+ };
198
+ }));
199
+ const rootClass = computed(() => [
200
+ "rs-upload",
201
+ `rs-upload--${resolvedSize.value}`,
202
+ `rs-upload--${props.variant}`,
203
+ `rs-upload--${props.listType}`,
204
+ {
205
+ "rs-upload--disabled": resolvedDisabled.value,
206
+ "rs-upload--full": !canAdd.value
207
+ }
208
+ ]);
209
+ function setFieldValue(value) {
210
+ model.value = Array.isArray(value) ? value.filter((item) => item instanceof File) : [];
211
+ }
212
+ useRsFormField(() => ({
213
+ get name() {
214
+ return props.name;
215
+ },
216
+ getValue: () => model.value,
217
+ setValue: setFieldValue
218
+ }));
219
+ function commit(next) {
220
+ model.value = next;
221
+ emit("change", next);
222
+ }
83
223
  function applyFiles(files) {
84
224
  if (!files.length || isDropzoneDisabled.value) return;
85
- const result = validateUploadFiles(files, {
225
+ let incoming = props.skipDuplicate ? skipDuplicateUploadFiles(model.value, files) : [...files];
226
+ if (!incoming.length) return;
227
+ const hook = props.beforeSelect;
228
+ if (!hook) {
229
+ commitIncoming(incoming);
230
+ return;
231
+ }
232
+ const seq = applySeq += 1;
233
+ Promise.resolve(hook(incoming)).then((next) => {
234
+ if (seq !== applySeq) return;
235
+ if (next === false) return;
236
+ commitIncoming(Array.isArray(next) ? next : incoming);
237
+ });
238
+ }
239
+ function commitIncoming(incoming) {
240
+ if (!incoming.length || isDropzoneDisabled.value) return;
241
+ const current = props.replace ? [] : model.value;
242
+ const result = validateUploadFiles(incoming, {
86
243
  accept: props.accept,
87
244
  maxSize: props.maxSize,
88
- maxCount: props.maxCount ? props.maxCount - model.value.length : void 0
245
+ maxCount: props.maxCount ? props.maxCount - current.length : void 0
89
246
  });
90
- model.value = mergeUploadFiles(model.value, result.accepted, props.maxCount);
247
+ commit(mergeUploadFiles(current, result.accepted, props.maxCount));
91
248
  if (result.rejected.length) emit("reject", result.rejected);
92
249
  }
93
250
  function onFilesChange(event) {
@@ -95,11 +252,29 @@ var RsUpload_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineC
95
252
  applyFiles(Array.from(input.files ?? []));
96
253
  input.value = "";
97
254
  }
255
+ function resetDrag() {
256
+ dragDepth.value = 0;
257
+ dragging.value = false;
258
+ unbindDragReset();
259
+ }
260
+ function bindDragReset() {
261
+ if (typeof window === "undefined" || dragResetBound) return;
262
+ window.addEventListener("dragend", resetDrag);
263
+ window.addEventListener("blur", resetDrag);
264
+ dragResetBound = true;
265
+ }
266
+ function unbindDragReset() {
267
+ if (typeof window === "undefined" || !dragResetBound) return;
268
+ window.removeEventListener("dragend", resetDrag);
269
+ window.removeEventListener("blur", resetDrag);
270
+ dragResetBound = false;
271
+ }
98
272
  function onDragEnter(event) {
99
273
  event.preventDefault();
100
274
  if (isDropzoneDisabled.value) return;
101
275
  dragDepth.value += 1;
102
276
  dragging.value = true;
277
+ bindDragReset();
103
278
  }
104
279
  function onDragOver(event) {
105
280
  event.preventDefault();
@@ -108,89 +283,228 @@ var RsUpload_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineC
108
283
  function onDragLeave(event) {
109
284
  event.preventDefault();
110
285
  dragDepth.value = Math.max(0, dragDepth.value - 1);
111
- if (dragDepth.value === 0) dragging.value = false;
286
+ if (dragDepth.value === 0) resetDrag();
112
287
  }
113
288
  function onDrop(event) {
114
289
  event.preventDefault();
115
- dragDepth.value = 0;
116
- dragging.value = false;
290
+ resetDrag();
117
291
  if (isDropzoneDisabled.value) return;
118
- applyFiles(Array.from(event.dataTransfer?.files ?? []));
292
+ const data = event.dataTransfer;
293
+ if (droppedDataHasDirectory(data)) {
294
+ collectDroppedFiles(data).then(applyFiles);
295
+ return;
296
+ }
297
+ applyFiles(Array.from(data?.files ?? []));
298
+ }
299
+ function onPaste(event) {
300
+ if (!props.paste || isDropzoneDisabled.value) return;
301
+ const files = Array.from(event.clipboardData?.files ?? []);
302
+ if (!files.length) return;
303
+ event.preventDefault();
304
+ applyFiles(files);
305
+ }
306
+ function commitRemove(file, index) {
307
+ commit(removeUploadFileAt(model.value, index));
308
+ emit("remove", file, index);
119
309
  }
120
310
  function removeFile(index) {
121
311
  const file = model.value[index];
122
- if (!file) return;
123
- model.value = removeUploadFileAt(model.value, index);
124
- emit("remove", file, index);
312
+ if (!file || resolvedDisabled.value) return;
313
+ const hook = props.beforeRemove;
314
+ if (!hook) {
315
+ commitRemove(file, index);
316
+ return;
317
+ }
318
+ const seq = removeSeq += 1;
319
+ Promise.resolve(hook(file, index)).then((ok) => {
320
+ if (seq !== removeSeq) return;
321
+ if (ok === false) return;
322
+ const nextIndex = model.value.indexOf(file);
323
+ if (nextIndex < 0) return;
324
+ commitRemove(file, nextIndex);
325
+ });
125
326
  }
126
327
  function onDownload(file, index) {
127
328
  emit("download", file, index);
128
329
  downloadUploadFile(file);
129
330
  }
130
- function fileIcon(file) {
131
- return resolveUploadFileIcon(file);
331
+ function onPreview(file, index) {
332
+ emit("preview", file, index);
333
+ }
334
+ function markBroken(file) {
335
+ if (brokenPreview.value.has(file)) return;
336
+ const next = new Set(brokenPreview.value);
337
+ next.add(file);
338
+ brokenPreview.value = next;
339
+ }
340
+ function open() {
341
+ if (isDropzoneDisabled.value) return;
342
+ inputRef.value?.click();
343
+ }
344
+ function focus() {
345
+ if (props.variant === "button") {
346
+ triggerRef.value?.focus();
347
+ return;
348
+ }
349
+ inputRef.value?.focus();
350
+ }
351
+ function blur() {
352
+ triggerRef.value?.blur();
353
+ inputRef.value?.blur();
354
+ }
355
+ function clear() {
356
+ if (!model.value.length) return;
357
+ commit([]);
358
+ }
359
+ function syncPreviewUrls(files) {
360
+ const { next, revoked } = nextUploadPreviewUrls(previewUrls.value, files, showPicturePreview.value, createUploadObjectUrl);
361
+ for (const url of revoked) revokeUploadObjectUrl(url);
362
+ previewUrls.value = next;
363
+ brokenPreview.value = pruneBrokenUploadPreview(brokenPreview.value, files);
132
364
  }
365
+ watch([model, showPicturePreview], () => {
366
+ syncPreviewUrls(model.value);
367
+ }, { immediate: true });
368
+ onUnmounted(() => {
369
+ applySeq += 1;
370
+ removeSeq += 1;
371
+ unbindDragReset();
372
+ for (const url of previewUrls.value.values()) revokeUploadObjectUrl(url);
373
+ previewUrls.value = /* @__PURE__ */ new Map();
374
+ brokenPreview.value = /* @__PURE__ */ new Set();
375
+ });
376
+ __expose({
377
+ open,
378
+ focus,
379
+ blur,
380
+ clear
381
+ });
133
382
  return (_ctx, _cache) => {
134
- return openBlock(), createElementBlock("div", _hoisted_1, [showDropzone.value ? (openBlock(), createElementBlock("label", {
135
- key: 0,
136
- class: normalizeClass(["rs-upload__dropzone", {
137
- "rs-upload__dropzone--disabled": isDropzoneDisabled.value,
138
- "rs-upload__dropzone--dragging": dragging.value && !isDropzoneDisabled.value
139
- }]),
140
- onDragenter: onDragEnter,
141
- onDragover: onDragOver,
142
- onDragleave: onDragLeave,
143
- onDrop
383
+ return openBlock(), createElementBlock("div", {
384
+ class: normalizeClass(rootClass.value),
385
+ "aria-disabled": resolvedDisabled.value ? "true" : void 0,
386
+ onPaste
144
387
  }, [
145
- createElementVNode("input", {
388
+ createElementVNode("input", mergeProps({
389
+ id: inputId.value,
390
+ ref_key: "inputRef",
391
+ ref: inputRef,
146
392
  class: "rs-upload__input",
147
393
  type: "file",
148
394
  accept: __props.accept,
149
- multiple: __props.multiple,
395
+ multiple: allowMultiple.value,
396
+ disabled: isDropzoneDisabled.value,
397
+ "aria-label": __props.ariaLabel || __props.label || unref(t)("upload.label")
398
+ }, inputExtraAttrs.value, { onChange: onFilesChange }), null, 16, _hoisted_2),
399
+ showBlockDropzone.value ? (openBlock(), createElementBlock("label", {
400
+ key: 0,
401
+ class: normalizeClass(["rs-upload__dropzone", {
402
+ "rs-upload__dropzone--disabled": isDropzoneDisabled.value,
403
+ "rs-upload__dropzone--dragging": dragging.value && !isDropzoneDisabled.value
404
+ }]),
405
+ for: inputId.value,
406
+ onDragenter: onDragEnter,
407
+ onDragover: onDragOver,
408
+ onDragleave: onDragLeave,
409
+ onDrop
410
+ }, [renderSlot(_ctx.$slots, "default", {}, () => [
411
+ createElementVNode("span", _hoisted_4, [renderSlot(_ctx.$slots, "icon", {}, () => [createVNode(RsIcon_default, {
412
+ name: "cloud-upload",
413
+ size: dropIconPx.value
414
+ }, null, 8, ["size"])], true)]),
415
+ createElementVNode("span", _hoisted_5, [createElementVNode("span", _hoisted_6, toDisplayString(__props.label ?? unref(t)("upload.label")), 1), createElementVNode("span", _hoisted_7, [renderSlot(_ctx.$slots, "hint", {}, () => [createTextVNode(toDisplayString(resolvedHint.value), 1)], true)])]),
416
+ renderSlot(_ctx.$slots, "extra", {}, void 0, true)
417
+ ], true)], 42, _hoisted_3)) : createCommentVNode("", true),
418
+ showButton.value ? (openBlock(), createElementBlock("button", {
419
+ key: 1,
420
+ ref_key: "triggerRef",
421
+ ref: triggerRef,
422
+ type: "button",
423
+ class: "rs-upload__trigger",
150
424
  disabled: isDropzoneDisabled.value,
151
- onChange: onFilesChange
152
- }, null, 40, _hoisted_2),
153
- createElementVNode("span", _hoisted_3, [createVNode(RsIcon_default, {
154
- name: "cloud-upload",
155
- size: 22
156
- })]),
157
- createElementVNode("span", _hoisted_4, [createElementVNode("span", _hoisted_5, toDisplayString(__props.label ?? unref(t)("upload.label")), 1), createElementVNode("span", _hoisted_6, toDisplayString(resolvedHint.value), 1)])
158
- ], 34)) : createCommentVNode("", true), __props.showFileList && model.value.length ? (openBlock(), createElementBlock("ul", _hoisted_7, [(openBlock(true), createElementBlock(Fragment, null, renderList(model.value, (file, index) => {
159
- return openBlock(), createElementBlock("li", {
160
- key: `${file.name}-${file.size}-${index}`,
161
- class: "rs-upload__file"
162
- }, [
163
- createElementVNode("span", {
164
- class: normalizeClass(["rs-upload__file-icon", `rs-upload__file-icon--${fileIcon(file)}`]),
165
- "aria-hidden": "true"
166
- }, [createVNode(RsIcon_default, {
167
- name: fileIcon(file),
168
- size: 16
169
- }, null, 8, ["name"])], 2),
170
- createElementVNode("span", _hoisted_8, [createElementVNode("span", _hoisted_9, toDisplayString(file.name), 1), createElementVNode("span", _hoisted_10, toDisplayString(unref(formatFileSize)(file.size)), 1)]),
171
- __props.showDownload ? (openBlock(), createElementBlock("button", {
172
- key: 0,
173
- type: "button",
174
- class: "rs-upload__file-action",
175
- "aria-label": unref(t)("upload.download"),
176
- title: unref(t)("upload.download"),
177
- onClick: withModifiers(($event) => onDownload(file, index), ["stop"])
178
- }, [createVNode(RsIcon_default, {
179
- name: "download",
180
- size: 14
181
- })], 8, _hoisted_11)) : createCommentVNode("", true),
182
- !__props.disabled ? (openBlock(), createElementBlock("button", {
183
- key: 1,
184
- type: "button",
185
- class: "rs-upload__file-remove",
186
- "aria-label": unref(t)("common.remove"),
187
- onClick: withModifiers(($event) => removeFile(index), ["stop"])
188
- }, [createVNode(RsIcon_default, {
189
- name: "x",
190
- size: 14
191
- })], 8, _hoisted_12)) : createCommentVNode("", true)
192
- ]);
193
- }), 128))])) : createCommentVNode("", true)]);
425
+ "aria-label": __props.ariaLabel || __props.label || unref(t)("upload.button"),
426
+ onClick: open,
427
+ onDragenter: onDragEnter,
428
+ onDragover: onDragOver,
429
+ onDragleave: onDragLeave,
430
+ onDrop
431
+ }, [renderSlot(_ctx.$slots, "default", {}, () => [createVNode(RsIcon_default, {
432
+ name: "upload",
433
+ size: fileIconPx.value
434
+ }, null, 8, ["size"]), createElementVNode("span", null, toDisplayString(__props.label ?? unref(t)("upload.button")), 1)], true)], 40, _hoisted_8)) : createCommentVNode("", true),
435
+ __props.showFileList && (fileViews.value.length || showAddTile.value) ? (openBlock(), createElementBlock("ul", {
436
+ key: 2,
437
+ id: unref(listLabelId),
438
+ class: "rs-upload__list",
439
+ "aria-label": unref(t)("upload.fileList")
440
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(fileViews.value, (view) => {
441
+ return openBlock(), createElementBlock("li", {
442
+ key: view.key,
443
+ class: normalizeClass(["rs-upload__file", { "rs-upload__file--card": isPictureCard.value }])
444
+ }, [renderSlot(_ctx.$slots, "file", {
445
+ file: view.file,
446
+ index: view.index
447
+ }, () => [
448
+ showPicturePreview.value && view.image ? (openBlock(), createElementBlock("button", {
449
+ key: 0,
450
+ type: "button",
451
+ class: "rs-upload__thumb",
452
+ "aria-label": unref(t)("upload.preview"),
453
+ title: unref(t)("upload.preview"),
454
+ onClick: withModifiers(($event) => onPreview(view.file, view.index), ["stop"])
455
+ }, [createElementVNode("img", {
456
+ class: "rs-upload__thumb-img",
457
+ src: view.previewUrl,
458
+ alt: view.file.name,
459
+ onError: ($event) => markBroken(view.file)
460
+ }, null, 40, _hoisted_11)], 8, _hoisted_10)) : (openBlock(), createElementBlock("span", {
461
+ key: 1,
462
+ class: normalizeClass(["rs-upload__file-icon", `rs-upload__file-icon--${view.icon}`]),
463
+ "aria-hidden": "true"
464
+ }, [renderSlot(_ctx.$slots, "file-icon", {
465
+ file: view.file,
466
+ index: view.index
467
+ }, () => [createVNode(RsIcon_default, {
468
+ name: view.icon,
469
+ size: fileIconPx.value
470
+ }, null, 8, ["name", "size"])], true)], 2)),
471
+ !isPictureCard.value ? (openBlock(), createElementBlock("span", _hoisted_12, [createElementVNode("span", _hoisted_13, toDisplayString(view.file.name), 1), createElementVNode("span", _hoisted_14, toDisplayString(view.sizeText), 1)])) : (openBlock(), createElementBlock("span", _hoisted_15, toDisplayString(view.file.name), 1)),
472
+ createElementVNode("span", _hoisted_16, [__props.showDownload ? (openBlock(), createElementBlock("button", {
473
+ key: 0,
474
+ type: "button",
475
+ class: "rs-upload__file-action",
476
+ "aria-label": unref(t)("upload.download"),
477
+ title: unref(t)("upload.download"),
478
+ onClick: withModifiers(($event) => onDownload(view.file, view.index), ["stop"])
479
+ }, [createVNode(RsIcon_default, {
480
+ name: "download",
481
+ size: fileIconPx.value
482
+ }, null, 8, ["size"])], 8, _hoisted_17)) : createCommentVNode("", true), !resolvedDisabled.value ? (openBlock(), createElementBlock("button", {
483
+ key: 1,
484
+ type: "button",
485
+ class: "rs-upload__file-remove",
486
+ "aria-label": unref(t)("common.remove"),
487
+ onClick: withModifiers(($event) => removeFile(view.index), ["stop"])
488
+ }, [createVNode(RsIcon_default, {
489
+ name: "x",
490
+ size: fileIconPx.value
491
+ }, null, 8, ["size"])], 8, _hoisted_18)) : createCommentVNode("", true)])
492
+ ], true)], 2);
493
+ }), 128)), showAddTile.value ? (openBlock(), createElementBlock("li", _hoisted_19, [createElementVNode("label", {
494
+ class: normalizeClass(["rs-upload__dropzone rs-upload__dropzone--tile", {
495
+ "rs-upload__dropzone--disabled": isDropzoneDisabled.value,
496
+ "rs-upload__dropzone--dragging": dragging.value && !isDropzoneDisabled.value
497
+ }]),
498
+ for: inputId.value,
499
+ onDragenter: onDragEnter,
500
+ onDragover: onDragOver,
501
+ onDragleave: onDragLeave,
502
+ onDrop
503
+ }, [renderSlot(_ctx.$slots, "default", {}, () => [createElementVNode("span", _hoisted_21, [renderSlot(_ctx.$slots, "icon", {}, () => [createVNode(RsIcon_default, {
504
+ name: "plus",
505
+ size: dropIconPx.value
506
+ }, null, 8, ["size"])], true)]), createElementVNode("span", _hoisted_22, toDisplayString(__props.label ?? unref(t)("upload.add")), 1)], true)], 42, _hoisted_20)])) : createCommentVNode("", true)], 8, _hoisted_9)) : createCommentVNode("", true)
507
+ ], 42, _hoisted_1);
194
508
  };
195
509
  }
196
510
  });
@@ -3,6 +3,6 @@ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_exp
3
3
  import RsUpload_vue_vue_type_script_setup_true_lang_default from "./RsUpload.impl.js";
4
4
 
5
5
  //#region src/components/upload/src/RsUpload.vue
6
- var RsUpload_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsUpload_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-9d8ef208"]]);
6
+ var RsUpload_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsUpload_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-8c6abb48"]]);
7
7
  //#endregion
8
8
  export { RsUpload_default as default };
@@ -7,7 +7,12 @@ export interface RsUploadValidationError {
7
7
  file: File;
8
8
  reason: 'accept' | 'maxSize' | 'maxCount';
9
9
  }
10
- export declare function formatFileSize(size: number): string;
10
+ export type RsUploadListType = 'text' | 'picture' | 'picture-card';
11
+ export type RsUploadVariant = 'dropzone' | 'button';
12
+ export type RsUploadCapture = boolean | 'user' | 'environment';
13
+ export type RsUploadBeforeSelect = (files: File[]) => boolean | File[] | Promise<boolean | File[]>;
14
+ export type RsUploadBeforeRemove = (file: File, index: number) => boolean | Promise<boolean>;
15
+ export declare function formatFileSize(size: number, locale?: string): string;
11
16
  export declare function isFileAccepted(file: File, accept?: string): boolean;
12
17
  export declare function validateUploadFiles(files: readonly File[], rules?: RsUploadValidationRules): {
13
18
  accepted: File[];
@@ -15,7 +20,21 @@ export declare function validateUploadFiles(files: readonly File[], rules?: RsUp
15
20
  };
16
21
  export declare function mergeUploadFiles(current: readonly File[], next: readonly File[], maxCount?: number): File[];
17
22
  export declare function removeUploadFileAt(files: readonly File[], index: number): File[];
18
- /** 触发浏览器下载指定 File / Blob */
23
+ export declare function isSameUploadFile(left: Pick<File, 'name' | 'size' | 'lastModified' | 'type'>, right: Pick<File, 'name' | 'size' | 'lastModified' | 'type'>): boolean;
24
+ export declare function skipDuplicateUploadFiles(current: readonly File[], incoming: readonly File[]): File[];
25
+ export declare function resolveUploadCapture(capture?: RsUploadCapture): 'user' | 'environment' | undefined;
26
+ export declare function isImageUploadFile(file: Pick<File, 'name' | 'type'>): boolean;
27
+ export declare function droppedDataHasDirectory(data: DataTransfer | null | undefined): boolean;
28
+ /** 读取拖入的 File。文件夹走 webkitGetAsEntry;否则回退 dataTransfer.files。 */
29
+ export declare function collectDroppedFiles(data: DataTransfer | null | undefined): Promise<File[]>;
30
+ export declare function nextUploadPreviewUrls(current: ReadonlyMap<File, string>, files: readonly File[], enabled: boolean, createUrl: (file: Blob) => string): {
31
+ next: Map<File, string>;
32
+ revoked: string[];
33
+ };
34
+ export declare function pruneBrokenUploadPreview(broken: ReadonlySet<File>, files: readonly File[]): Set<File>;
35
+ export declare function createUploadObjectUrl(file: Blob): string;
36
+ export declare function revokeUploadObjectUrl(url: string | undefined | null): void;
37
+ /** 触发浏览器下载指定 File / Blob。无 document 时空操作。延迟 revoke,避免下载被中断。 */
19
38
  export declare function downloadUploadFile(file: File | Blob, filename?: string): void;
20
39
  /** 将文本等内容还原为可回显的 File(编辑态回填) */
21
40
  export declare function createUploadFileFromContent(name: string, content: BlobPart, type?: string): File;