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
@@ -5,27 +5,33 @@ import { isRsFormItemBoundControl, useRsFormContext, useRsFormField, useRsFormIt
5
5
  import { useResolvedRsComponentSize } from "../../_shared/src/resolve-size.js";
6
6
  import { rsRadiusCss, useResolvedRsRadius } from "../../_shared/src/resolve-radius.js";
7
7
  import RsTag_default from "../../tag/src/RsTag.js";
8
- import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeModels, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, ref, renderList, toDisplayString, unref, useModel, vModelText, watch, withCtx, withDirectives, withModifiers } from "vue";
8
+ import { canAcceptRsDynamicTag, coerceRsDynamicTagsValue, draftHasRsDynamicTagsSeparator, normalizeRsDynamicTagsSeparators, parseRsDynamicTag, splitRsDynamicTagsDraft } from "./dynamic-tags-utils.js";
9
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeModels, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, ref, renderList, renderSlot, toDisplayString, unref, useId, useModel, vModelText, watch, withCtx, withDirectives, withModifiers } from "vue";
9
10
  //#region src/components/dynamic-tags/src/RsDynamicTags.vue?vue&type=script&setup=true&lang.ts
10
11
  var _hoisted_1 = { class: "rs-dynamic-tags-field" };
11
12
  var _hoisted_2 = [
12
- "aria-disabled",
13
+ "disabled",
14
+ "aria-readonly",
13
15
  "aria-invalid",
14
- "aria-label"
16
+ "aria-describedby"
15
17
  ];
16
- var _hoisted_3 = [
18
+ var _hoisted_3 = { class: "rs-dynamic-tags-field__sr-only" };
19
+ var _hoisted_4 = [
20
+ "id",
17
21
  "placeholder",
18
22
  "disabled",
23
+ "readonly",
19
24
  "maxlength",
20
- "aria-label"
25
+ "aria-label",
26
+ "aria-invalid",
27
+ "aria-describedby"
21
28
  ];
22
- var _hoisted_4 = ["aria-label"];
23
- var _hoisted_5 = {
24
- key: 0,
25
- class: "rs-dynamic-tags-field__error",
26
- role: "alert"
27
- };
29
+ var _hoisted_5 = ["aria-label"];
30
+ var _hoisted_6 = ["aria-label"];
31
+ var _hoisted_7 = ["id"];
32
+ var _hoisted_8 = ["id"];
28
33
  var RsDynamicTags_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
34
+ name: "RsDynamicTags",
29
35
  __name: "RsDynamicTags",
30
36
  props: /*@__PURE__*/ mergeModels({
31
37
  name: {},
@@ -36,6 +42,10 @@ var RsDynamicTags_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
36
42
  type: Boolean,
37
43
  default: false
38
44
  },
45
+ readonly: {
46
+ type: Boolean,
47
+ default: false
48
+ },
39
49
  required: {
40
50
  type: Boolean,
41
51
  default: false
@@ -51,13 +61,20 @@ var RsDynamicTags_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
51
61
  type: Boolean,
52
62
  default: true
53
63
  },
64
+ separators: {},
65
+ parse: {},
66
+ allowClear: {
67
+ type: Boolean,
68
+ default: false
69
+ },
54
70
  size: {},
55
71
  radius: {},
56
72
  tagVariant: { default: "default" },
57
73
  round: {
58
74
  type: Boolean,
59
75
  default: false
60
- }
76
+ },
77
+ ariaLabel: {}
61
78
  }, {
62
79
  "modelValue": { default: () => [] },
63
80
  "modelModifiers": {}
@@ -65,7 +82,10 @@ var RsDynamicTags_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
65
82
  emits: /*@__PURE__*/ mergeModels([
66
83
  "create",
67
84
  "remove",
68
- "reject"
85
+ "reject",
86
+ "clear",
87
+ "focus",
88
+ "blur"
69
89
  ], ["update:modelValue"]),
70
90
  setup(__props, { expose: __expose, emit: __emit }) {
71
91
  const model = useModel(__props, "modelValue");
@@ -84,20 +104,42 @@ var RsDynamicTags_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
84
104
  const feedback = ref(null);
85
105
  const autoMessage = ref("");
86
106
  const inputRef = ref(null);
107
+ const autoId = useId();
87
108
  let feedbackTimer = null;
109
+ const inputId = computed(() => props.id || autoId);
110
+ const errorId = computed(() => `${inputId.value}-error`);
111
+ const feedbackId = computed(() => `${inputId.value}-feedback`);
88
112
  const resolvedSize = useResolvedRsComponentSize(() => props.size);
89
113
  const resolvedRadius = useResolvedRsRadius(() => props.radius, "md");
114
+ const resolvedDisabled = computed(() => props.disabled || Boolean(formContext?.disabled.value));
115
+ const resolvedReadonly = computed(() => props.readonly);
116
+ const isInteractive = computed(() => !resolvedDisabled.value && !resolvedReadonly.value);
117
+ const resolvedSeparators = computed(() => normalizeRsDynamicTagsSeparators(props.separators));
90
118
  const resolvedPlaceholder = computed(() => props.placeholder ?? t("dynamicTags.placeholder"));
119
+ const groupLabel = computed(() => props.ariaLabel || t("dynamicTags.label"));
91
120
  const canAddMore = computed(() => props.max === void 0 || model.value.length < props.max);
92
- const showInput = computed(() => !props.disabled && canAddMore.value && (props.inputMode === "always" || editing.value));
93
- const showTrigger = computed(() => !props.disabled && canAddMore.value && props.inputMode === "trigger" && !editing.value);
121
+ const showInput = computed(() => isInteractive.value && canAddMore.value && (props.inputMode === "always" || editing.value));
122
+ const showTrigger = computed(() => isInteractive.value && canAddMore.value && props.inputMode === "trigger" && !editing.value);
123
+ const showClear = computed(() => props.allowClear && model.value.length > 0 && isInteractive.value);
94
124
  const hasError = computed(() => Boolean(props.invalid || boundToItem.value && formItem?.invalid.value || autoMessage.value));
95
125
  const visibleMessage = computed(() => boundToItem.value ? "" : autoMessage.value);
126
+ const describedBy = computed(() => {
127
+ if (boundToItem.value) return formItem?.describedBy.value;
128
+ const ids = [visibleMessage.value ? errorId.value : "", feedback.value ? feedbackId.value : ""].filter(Boolean);
129
+ return ids.length ? ids.join(" ") : void 0;
130
+ });
131
+ const feedbackMessage = computed(() => {
132
+ if (feedback.value === "duplicate") return t("dynamicTags.duplicate");
133
+ if (feedback.value === "max") return t("dynamicTags.maxReached");
134
+ if (feedback.value === "invalid") return t("dynamicTags.invalid");
135
+ return "";
136
+ });
96
137
  const rootClass = computed(() => [
97
138
  "rs-dynamic-tags",
98
139
  `rs-dynamic-tags--${resolvedSize.value}`,
99
140
  {
100
- "rs-dynamic-tags--disabled": props.disabled,
141
+ "rs-dynamic-tags--disabled": resolvedDisabled.value,
142
+ "rs-dynamic-tags--readonly": resolvedReadonly.value && !resolvedDisabled.value,
101
143
  "rs-dynamic-tags--editing": showInput.value,
102
144
  "rs-dynamic-tags--feedback": feedback.value != null,
103
145
  "rs-dynamic-tags--invalid": hasError.value
@@ -124,7 +166,7 @@ var RsDynamicTags_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
124
166
  inputRef.value?.focus();
125
167
  }
126
168
  function startEdit() {
127
- if (props.disabled || !canAddMore.value) {
169
+ if (!isInteractive.value || !canAddMore.value) {
128
170
  if (!canAddMore.value) flashFeedback("max", draft.value);
129
171
  return;
130
172
  }
@@ -135,57 +177,127 @@ var RsDynamicTags_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
135
177
  draft.value = "";
136
178
  if (props.inputMode === "trigger") editing.value = false;
137
179
  }
138
- function addTag() {
139
- if (props.disabled) return false;
140
- if (!canAddMore.value) {
141
- flashFeedback("max", draft.value);
180
+ function addParsed(value) {
181
+ const parsed = parseRsDynamicTag(value, props.parse);
182
+ if (parsed === false) {
183
+ if (value.trim()) flashFeedback("invalid", value.trim());
142
184
  return false;
143
185
  }
144
- const value = draft.value.trim();
145
- if (!value) return false;
146
- if (!props.allowDuplicate && model.value.includes(value)) {
147
- flashFeedback("duplicate", value);
148
- draft.value = "";
186
+ const reason = canAcceptRsDynamicTag(model.value, parsed, {
187
+ allowDuplicate: props.allowDuplicate,
188
+ max: props.max
189
+ });
190
+ if (reason !== "ok") {
191
+ flashFeedback(reason, parsed);
149
192
  return false;
150
193
  }
151
- model.value = [...model.value, value];
152
- emit("create", value);
153
- draft.value = "";
154
- runValidate("change");
194
+ model.value = [...model.value, parsed];
195
+ emit("create", parsed);
155
196
  return true;
156
197
  }
198
+ function addMany(values) {
199
+ let added = false;
200
+ for (const value of values) if (addParsed(value)) added = true;
201
+ else if (!canAddMore.value) break;
202
+ if (added) runValidate("change");
203
+ return added;
204
+ }
205
+ function commitDraft(raw, includeRest) {
206
+ if (!raw.trim()) return false;
207
+ if (resolvedSeparators.value.length && draftHasRsDynamicTagsSeparator(raw, resolvedSeparators.value)) {
208
+ const { tokens, rest } = splitRsDynamicTagsDraft(raw, resolvedSeparators.value);
209
+ const added = addMany(includeRest && rest.trim() ? [...tokens, rest.trim()] : tokens);
210
+ draft.value = includeRest ? "" : rest;
211
+ return added;
212
+ }
213
+ const ok = addParsed(raw);
214
+ if (ok) {
215
+ draft.value = "";
216
+ runValidate("change");
217
+ }
218
+ return ok;
219
+ }
157
220
  function commit() {
158
221
  if (composing.value) return;
159
- if (!draft.value.trim()) {
222
+ const value = draft.value;
223
+ if (!value.trim()) {
160
224
  if (props.inputMode === "trigger") stopEdit();
161
225
  return;
162
226
  }
163
- if (addTag()) if (props.inputMode === "trigger" && !canAddMore.value) stopEdit();
227
+ commitDraft(value, true);
228
+ if (props.inputMode === "trigger" && !canAddMore.value) stopEdit();
164
229
  else focusInput();
165
230
  }
231
+ function onDraftInput() {
232
+ if (composing.value) return;
233
+ if (!resolvedSeparators.value.length) return;
234
+ if (!draftHasRsDynamicTagsSeparator(draft.value, resolvedSeparators.value)) return;
235
+ const { tokens, rest } = splitRsDynamicTagsDraft(draft.value, resolvedSeparators.value);
236
+ if (!tokens.length) return;
237
+ addMany(tokens);
238
+ draft.value = rest;
239
+ }
240
+ function onCompositionEnd() {
241
+ composing.value = false;
242
+ onDraftInput();
243
+ }
244
+ function onPaste(event) {
245
+ if (!isInteractive.value || composing.value) return;
246
+ if (!resolvedSeparators.value.length) return;
247
+ const text = event.clipboardData?.getData("text") ?? "";
248
+ if (!text || !draftHasRsDynamicTagsSeparator(text, resolvedSeparators.value)) return;
249
+ event.preventDefault();
250
+ const { tokens, rest } = splitRsDynamicTagsDraft(`${draft.value}${text}`, resolvedSeparators.value);
251
+ const pasted = rest.trim() ? [...tokens, rest.trim()] : tokens;
252
+ if (pasted.length) addMany(pasted);
253
+ draft.value = "";
254
+ }
166
255
  function removeTag(index) {
167
- if (props.disabled) return;
256
+ if (!isInteractive.value) return;
168
257
  const next = [...model.value];
169
258
  const [removed] = next.splice(index, 1);
170
259
  model.value = next;
171
260
  if (removed !== void 0) emit("remove", removed, index);
172
261
  runValidate("change");
173
262
  }
263
+ function clearAll() {
264
+ if (!isInteractive.value || !model.value.length) return;
265
+ model.value = [];
266
+ draft.value = "";
267
+ emit("clear");
268
+ runValidate("change");
269
+ }
174
270
  function onKeydown(event) {
175
271
  if (event.isComposing || composing.value) return;
176
272
  if (event.key === "Enter") {
177
273
  event.preventDefault();
178
274
  commit();
179
- } else if (event.key === "Escape") {
275
+ return;
276
+ }
277
+ if (event.key === "Tab" && draft.value.trim()) {
278
+ event.preventDefault();
279
+ commit();
280
+ return;
281
+ }
282
+ if (event.key === "Escape") {
180
283
  event.preventDefault();
181
284
  stopEdit();
182
- } else if (event.key === "Backspace" && !draft.value && model.value.length > 0) removeTag(model.value.length - 1);
285
+ return;
286
+ }
287
+ if (event.key === "Backspace" && !draft.value && model.value.length > 0) removeTag(model.value.length - 1);
183
288
  }
184
- function onBlur() {
185
- if (composing.value) return;
289
+ function onFocus(event) {
290
+ emit("focus", event);
291
+ }
292
+ function onBlur(event) {
293
+ if (composing.value) {
294
+ emit("blur", event);
295
+ return;
296
+ }
186
297
  if (props.commitOnBlur && draft.value.trim()) commit();
187
298
  else if (props.inputMode === "trigger") stopEdit();
188
299
  runValidate("blur");
300
+ emit("blur", event);
189
301
  }
190
302
  async function runValidate(trigger = "submit") {
191
303
  const formRules = formContext?.getFieldRules(props.name) ?? [];
@@ -207,19 +319,26 @@ var RsDynamicTags_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
207
319
  };
208
320
  }
209
321
  function setValue(value) {
210
- if (Array.isArray(value)) {
211
- model.value = value.map((item) => String(item ?? ""));
212
- return;
213
- }
214
- if (value == null || value === "") {
215
- model.value = [];
216
- return;
217
- }
218
- model.value = [String(value)];
322
+ model.value = coerceRsDynamicTagsValue(value);
323
+ }
324
+ function setError(message) {
325
+ autoMessage.value = message;
219
326
  }
220
327
  function clearValidation() {
221
328
  autoMessage.value = "";
222
329
  }
330
+ function focus() {
331
+ if (resolvedDisabled.value) return;
332
+ if (resolvedReadonly.value) return;
333
+ if (showInput.value) {
334
+ focusInput();
335
+ return;
336
+ }
337
+ if (showTrigger.value) startEdit();
338
+ }
339
+ function blur() {
340
+ inputRef.value?.blur();
341
+ }
223
342
  useRsFormField(() => ({
224
343
  get name() {
225
344
  return props.name;
@@ -228,23 +347,28 @@ var RsDynamicTags_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
228
347
  setValue,
229
348
  validate: (trigger) => runValidate(trigger ?? "submit"),
230
349
  clearValidation,
231
- setError: (message) => {
232
- autoMessage.value = message;
233
- }
350
+ setError
234
351
  }));
235
352
  watch(() => model.value, () => {
236
353
  if (autoMessage.value) runValidate("change");
237
354
  });
355
+ watch(() => props.inputMode, (mode) => {
356
+ editing.value = mode === "always";
357
+ if (mode === "trigger") draft.value = "";
358
+ });
238
359
  __expose({
239
360
  validate: runValidate,
240
361
  clearValidation,
241
- setValue
362
+ setValue,
363
+ setError,
364
+ focus,
365
+ blur
242
366
  });
243
367
  function onRootPointerDown(event) {
244
- if (props.disabled) return;
368
+ if (!isInteractive.value) return;
245
369
  const target = event.target;
246
370
  if (!target) return;
247
- if (target.closest(".rs-tag__close, .rs-dynamic-tags__trigger, .rs-dynamic-tags__input")) return;
371
+ if (target.closest(".rs-tag__close, .rs-dynamic-tags__trigger, .rs-dynamic-tags__input, .rs-dynamic-tags__clear")) return;
248
372
  if (showInput.value) focusInput();
249
373
  else if (showTrigger.value) startEdit();
250
374
  }
@@ -252,60 +376,99 @@ var RsDynamicTags_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
252
376
  clearFeedbackTimer();
253
377
  });
254
378
  return (_ctx, _cache) => {
255
- return openBlock(), createElementBlock("div", _hoisted_1, [createElementVNode("div", {
256
- class: normalizeClass(rootClass.value),
257
- style: normalizeStyle(rootStyle.value),
258
- role: "group",
259
- "aria-disabled": __props.disabled || void 0,
260
- "aria-invalid": hasError.value || void 0,
261
- "aria-label": unref(t)("dynamicTags.label"),
262
- onPointerdown: onRootPointerDown
263
- }, [(openBlock(true), createElementBlock(Fragment, null, renderList(model.value, (tag, index) => {
264
- return openBlock(), createBlock(RsTag_default, {
265
- key: `${tag}-${index}`,
266
- closable: "",
267
- disabled: __props.disabled,
268
- size: unref(resolvedSize),
269
- radius: unref(resolvedRadius),
270
- variant: __props.tagVariant,
271
- round: __props.round,
272
- onClose: ($event) => removeTag(index)
273
- }, {
274
- default: withCtx(() => [createTextVNode(toDisplayString(tag), 1)]),
275
- _: 2
276
- }, 1032, [
277
- "disabled",
278
- "size",
279
- "radius",
280
- "variant",
281
- "round",
282
- "onClose"
283
- ]);
284
- }), 128)), showInput.value ? withDirectives((openBlock(), createElementBlock("input", {
285
- key: 0,
286
- ref_key: "inputRef",
287
- ref: inputRef,
288
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => draft.value = $event),
289
- class: "rs-dynamic-tags__input",
290
- type: "text",
291
- placeholder: resolvedPlaceholder.value,
292
- disabled: __props.disabled,
293
- maxlength: __props.maxlength,
294
- "aria-label": resolvedPlaceholder.value,
295
- onKeydown,
296
- onBlur,
297
- onCompositionstart: _cache[1] || (_cache[1] = ($event) => composing.value = true),
298
- onCompositionend: _cache[2] || (_cache[2] = ($event) => composing.value = false)
299
- }, null, 40, _hoisted_3)), [[vModelText, draft.value]]) : showTrigger.value ? (openBlock(), createElementBlock("button", {
300
- key: 1,
301
- type: "button",
302
- class: "rs-dynamic-tags__trigger",
303
- "aria-label": unref(t)("dynamicTags.add"),
304
- onClick: withModifiers(startEdit, ["stop"])
305
- }, [createVNode(RsIcon_default, {
306
- name: "plus",
307
- size: 14
308
- })], 8, _hoisted_4)) : createCommentVNode("", true)], 46, _hoisted_2), visibleMessage.value ? (openBlock(), createElementBlock("p", _hoisted_5, toDisplayString(visibleMessage.value), 1)) : createCommentVNode("", true)]);
379
+ return openBlock(), createElementBlock("div", _hoisted_1, [
380
+ createElementVNode("fieldset", {
381
+ class: normalizeClass(rootClass.value),
382
+ style: normalizeStyle(rootStyle.value),
383
+ disabled: resolvedDisabled.value || void 0,
384
+ "aria-readonly": resolvedReadonly.value || void 0,
385
+ "aria-invalid": hasError.value || void 0,
386
+ "aria-describedby": describedBy.value,
387
+ onPointerdown: onRootPointerDown
388
+ }, [
389
+ createElementVNode("legend", _hoisted_3, toDisplayString(groupLabel.value), 1),
390
+ (openBlock(true), createElementBlock(Fragment, null, renderList(model.value, (tag, index) => {
391
+ return openBlock(), createBlock(RsTag_default, {
392
+ key: `${tag}-${index}`,
393
+ closable: isInteractive.value,
394
+ size: unref(resolvedSize),
395
+ radius: unref(resolvedRadius),
396
+ variant: __props.tagVariant,
397
+ round: __props.round,
398
+ onClose: ($event) => removeTag(index)
399
+ }, {
400
+ default: withCtx(() => [renderSlot(_ctx.$slots, "tag", {
401
+ tag,
402
+ index
403
+ }, () => [createTextVNode(toDisplayString(tag), 1)], true)]),
404
+ _: 2
405
+ }, 1032, [
406
+ "closable",
407
+ "size",
408
+ "radius",
409
+ "variant",
410
+ "round",
411
+ "onClose"
412
+ ]);
413
+ }), 128)),
414
+ showInput.value ? withDirectives((openBlock(), createElementBlock("input", {
415
+ key: 0,
416
+ id: inputId.value,
417
+ ref_key: "inputRef",
418
+ ref: inputRef,
419
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => draft.value = $event),
420
+ class: "rs-dynamic-tags__input",
421
+ type: "text",
422
+ placeholder: resolvedPlaceholder.value,
423
+ disabled: resolvedDisabled.value,
424
+ readonly: resolvedReadonly.value,
425
+ maxlength: __props.maxlength,
426
+ "aria-label": resolvedPlaceholder.value,
427
+ "aria-invalid": hasError.value || void 0,
428
+ "aria-describedby": describedBy.value,
429
+ onInput: onDraftInput,
430
+ onPaste,
431
+ onKeydown,
432
+ onFocus,
433
+ onBlur,
434
+ onCompositionstart: _cache[1] || (_cache[1] = ($event) => composing.value = true),
435
+ onCompositionend: onCompositionEnd
436
+ }, null, 40, _hoisted_4)), [[vModelText, draft.value]]) : showTrigger.value ? (openBlock(), createElementBlock("button", {
437
+ key: 1,
438
+ type: "button",
439
+ class: "rs-dynamic-tags__trigger",
440
+ "aria-label": unref(t)("dynamicTags.add"),
441
+ onClick: withModifiers(startEdit, ["stop"])
442
+ }, [renderSlot(_ctx.$slots, "trigger", {}, () => [createVNode(RsIcon_default, {
443
+ name: "plus",
444
+ size: 14
445
+ })], true)], 8, _hoisted_5)) : createCommentVNode("", true),
446
+ showClear.value ? (openBlock(), createElementBlock("button", {
447
+ key: 2,
448
+ type: "button",
449
+ class: "rs-dynamic-tags__clear",
450
+ tabindex: "-1",
451
+ "aria-label": unref(t)("dynamicTags.clear"),
452
+ onPointerdown: _cache[2] || (_cache[2] = withModifiers(() => {}, ["prevent"])),
453
+ onClick: withModifiers(clearAll, ["stop"])
454
+ }, [createVNode(RsIcon_default, {
455
+ name: "x",
456
+ size: 14
457
+ })], 40, _hoisted_6)) : createCommentVNode("", true)
458
+ ], 46, _hoisted_2),
459
+ visibleMessage.value ? (openBlock(), createElementBlock("p", {
460
+ key: 0,
461
+ id: errorId.value,
462
+ class: "rs-dynamic-tags-field__error",
463
+ role: "alert"
464
+ }, toDisplayString(visibleMessage.value), 9, _hoisted_7)) : createCommentVNode("", true),
465
+ feedbackMessage.value ? (openBlock(), createElementBlock("span", {
466
+ key: 1,
467
+ id: feedbackId.value,
468
+ class: "rs-dynamic-tags-field__sr-only",
469
+ "aria-live": "polite"
470
+ }, toDisplayString(feedbackMessage.value), 9, _hoisted_8)) : createCommentVNode("", true)
471
+ ]);
309
472
  };
310
473
  }
311
474
  });
@@ -3,6 +3,6 @@ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_exp
3
3
  import RsDynamicTags_vue_vue_type_script_setup_true_lang_default from "./RsDynamicTags.impl.js";
4
4
 
5
5
  //#region src/components/dynamic-tags/src/RsDynamicTags.vue
6
- var RsDynamicTags_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsDynamicTags_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-a441b090"]]);
6
+ var RsDynamicTags_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsDynamicTags_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-2213feb0"]]);
7
7
  //#endregion
8
8
  export { RsDynamicTags_default as default };
@@ -0,0 +1,19 @@
1
+ /** 提交前变换或拒绝草稿。false 表示不写入。 */
2
+ export type RsDynamicTagsParse = (value: string) => string | false;
3
+ export type RsDynamicTagsRejectReason = 'duplicate' | 'max' | 'invalid';
4
+ export declare function normalizeRsDynamicTagsSeparators(separators?: string | readonly string[]): string[];
5
+ /**
6
+ * 按分隔符切开草稿。最后一段是尚未提交的 rest(可能为空)。
7
+ * 多字符分隔符按长度优先匹配。
8
+ */
9
+ export declare function splitRsDynamicTagsDraft(draft: string, separators: readonly string[]): {
10
+ tokens: string[];
11
+ rest: string;
12
+ };
13
+ export declare function draftHasRsDynamicTagsSeparator(draft: string, separators: readonly string[]): boolean;
14
+ export declare function parseRsDynamicTag(value: string, parse?: RsDynamicTagsParse): string | false;
15
+ export declare function canAcceptRsDynamicTag(tags: readonly string[], value: string, options: {
16
+ allowDuplicate?: boolean;
17
+ max?: number;
18
+ }): 'ok' | RsDynamicTagsRejectReason;
19
+ export declare function coerceRsDynamicTagsValue(value: unknown): string[];
@@ -0,0 +1,60 @@
1
+ //#region src/components/dynamic-tags/src/dynamic-tags-utils.ts
2
+ function normalizeRsDynamicTagsSeparators(separators) {
3
+ if (separators == null) return [];
4
+ return (typeof separators === "string" ? [separators] : [...separators]).filter((item) => item.length > 0);
5
+ }
6
+ function escapeRegExp(value) {
7
+ return value.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
8
+ }
9
+ /**
10
+ * 按分隔符切开草稿。最后一段是尚未提交的 rest(可能为空)。
11
+ * 多字符分隔符按长度优先匹配。
12
+ */
13
+ function splitRsDynamicTagsDraft(draft, separators) {
14
+ if (!draft) return {
15
+ tokens: [],
16
+ rest: ""
17
+ };
18
+ if (!separators.length) return {
19
+ tokens: [],
20
+ rest: draft
21
+ };
22
+ const sorted = [...separators].sort((a, b) => b.length - a.length);
23
+ const re = new RegExp(sorted.map(escapeRegExp).join("|"));
24
+ const parts = draft.split(re);
25
+ const rest = parts.pop() ?? "";
26
+ return {
27
+ tokens: parts.map((item) => item.trim()).filter((item) => item.length > 0),
28
+ rest
29
+ };
30
+ }
31
+ function draftHasRsDynamicTagsSeparator(draft, separators) {
32
+ if (!draft || !separators.length) return false;
33
+ return separators.some((item) => draft.includes(item));
34
+ }
35
+ function parseRsDynamicTag(value, parse) {
36
+ const trimmed = value.trim();
37
+ if (!trimmed) return false;
38
+ if (!parse) return trimmed;
39
+ const next = parse(trimmed);
40
+ if (next === false) return false;
41
+ const out = String(next).trim();
42
+ return out.length > 0 ? out : false;
43
+ }
44
+ function canAcceptRsDynamicTag(tags, value, options) {
45
+ if (options.max !== void 0 && tags.length >= options.max) return "max";
46
+ if (!options.allowDuplicate && tags.includes(value)) return "duplicate";
47
+ return "ok";
48
+ }
49
+ function asTagText(value) {
50
+ if (typeof value === "string") return value;
51
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
52
+ return "";
53
+ }
54
+ function coerceRsDynamicTagsValue(value) {
55
+ if (Array.isArray(value)) return value.map(asTagText).filter((item) => item.length > 0);
56
+ const text = asTagText(value).trim();
57
+ return text ? [text] : [];
58
+ }
59
+ //#endregion
60
+ export { canAcceptRsDynamicTag, coerceRsDynamicTagsValue, draftHasRsDynamicTagsSeparator, normalizeRsDynamicTagsSeparators, parseRsDynamicTag, splitRsDynamicTagsDraft };