niuma-ui 2.0.2 → 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 (242) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +2 -0
  3. package/README.zh-CN.md +2 -0
  4. package/dist/components/_shared/src/reka.d.ts +1 -1
  5. package/dist/components/_shared/src/reka.js +2 -2
  6. package/dist/components/anchor/index.d.ts +1 -1
  7. package/dist/components/anchor/src/RsAnchor.css +63 -32
  8. package/dist/components/anchor/src/RsAnchor.d.ts +29 -2
  9. package/dist/components/anchor/src/RsAnchor.impl.js +199 -81
  10. package/dist/components/anchor/src/RsAnchor.js +1 -1
  11. package/dist/components/anchor/src/anchor-utils.d.ts +36 -4
  12. package/dist/components/anchor/src/anchor-utils.js +81 -19
  13. package/dist/components/auto-complete/index.d.ts +2 -0
  14. package/dist/components/auto-complete/src/RsAutoComplete.css +122 -0
  15. package/dist/components/auto-complete/src/RsAutoComplete.d.ts +47 -7
  16. package/dist/components/auto-complete/src/RsAutoComplete.impl.js +180 -72
  17. package/dist/components/auto-complete/src/RsAutoComplete.js +4 -1
  18. package/dist/components/auto-complete/src/auto-complete-utils.d.ts +7 -0
  19. package/dist/components/auto-complete/src/auto-complete-utils.js +17 -0
  20. package/dist/components/avatar/index.d.ts +1 -0
  21. package/dist/components/avatar/src/RsAvatar.css +36 -19
  22. package/dist/components/avatar/src/RsAvatar.d.ts +9 -3
  23. package/dist/components/avatar/src/RsAvatar.impl.js +57 -33
  24. package/dist/components/avatar/src/RsAvatar.js +2 -1
  25. package/dist/components/avatar/src/avatar-utils.d.ts +16 -7
  26. package/dist/components/avatar/src/avatar-utils.js +41 -3
  27. package/dist/components/badge/index.d.ts +1 -0
  28. package/dist/components/badge/src/RsBadge.css +61 -8
  29. package/dist/components/badge/src/RsBadge.d.ts +19 -3
  30. package/dist/components/badge/src/RsBadge.impl.js +46 -3
  31. package/dist/components/badge/src/RsBadge.js +1 -1
  32. package/dist/components/badge/src/badge-utils.d.ts +11 -0
  33. package/dist/components/badge/src/badge-utils.js +32 -0
  34. package/dist/components/breadcrumb/index.d.ts +1 -1
  35. package/dist/components/breadcrumb/src/RsBreadcrumb.css +50 -17
  36. package/dist/components/breadcrumb/src/RsBreadcrumb.d.ts +45 -6
  37. package/dist/components/breadcrumb/src/RsBreadcrumb.impl.js +111 -12
  38. package/dist/components/breadcrumb/src/RsBreadcrumb.js +2 -1
  39. package/dist/components/breadcrumb/src/breadcrumb-utils.d.ts +37 -5
  40. package/dist/components/breadcrumb/src/breadcrumb-utils.js +70 -9
  41. package/dist/components/button/src/RsButton.css +87 -71
  42. package/dist/components/button/src/RsButton.d.ts +7 -3
  43. package/dist/components/button/src/RsButton.impl.js +43 -31
  44. package/dist/components/button/src/RsButton.js +1 -1
  45. package/dist/components/button/src/button-utils.d.ts +17 -0
  46. package/dist/components/button/src/button-utils.js +14 -1
  47. package/dist/components/calendar-grid/index.d.ts +2 -0
  48. package/dist/components/calendar-grid/src/RsCalendarGrid.css +105 -45
  49. package/dist/components/calendar-grid/src/RsCalendarGrid.d.ts +62 -2
  50. package/dist/components/calendar-grid/src/RsCalendarGrid.impl.js +265 -94
  51. package/dist/components/calendar-grid/src/RsCalendarGrid.js +1 -1
  52. package/dist/components/calendar-grid/src/calendar-grid-utils.d.ts +72 -0
  53. package/dist/components/calendar-grid/src/calendar-grid-utils.js +122 -0
  54. package/dist/components/card/index.d.ts +1 -1
  55. package/dist/components/card/src/RsCard.css +108 -98
  56. package/dist/components/card/src/RsCard.d.ts +3 -12
  57. package/dist/components/card/src/RsCard.impl.js +29 -25
  58. package/dist/components/card/src/RsCard.js +2 -1
  59. package/dist/components/card/src/card-utils.d.ts +25 -0
  60. package/dist/components/card/src/card-utils.js +10 -0
  61. package/dist/components/cascader/index.d.ts +1 -0
  62. package/dist/components/cascader/src/RsCascader.css +175 -30
  63. package/dist/components/cascader/src/RsCascader.d.ts +14 -2
  64. package/dist/components/cascader/src/RsCascader.impl.js +277 -48
  65. package/dist/components/cascader/src/RsCascader.js +1 -1
  66. package/dist/components/cascader/src/cascader-utils.d.ts +2 -0
  67. package/dist/components/cascader/src/cascader-utils.js +8 -1
  68. package/dist/components/checkbox/index.d.ts +1 -0
  69. package/dist/components/checkbox/src/RsCheckbox.css +46 -23
  70. package/dist/components/checkbox/src/RsCheckbox.d.ts +11 -1
  71. package/dist/components/checkbox/src/RsCheckbox.impl.js +37 -9
  72. package/dist/components/checkbox/src/RsCheckbox.js +2 -1
  73. package/dist/components/checkbox/src/checkbox-utils.d.ts +4 -0
  74. package/dist/components/checkbox/src/checkbox-utils.js +12 -0
  75. package/dist/components/container/index.d.ts +1 -1
  76. package/dist/components/container/src/RsContainer.css +11 -11
  77. package/dist/components/container/src/RsContainer.d.ts +2 -12
  78. package/dist/components/container/src/RsContainer.impl.js +10 -57
  79. package/dist/components/container/src/RsContainer.js +1 -1
  80. package/dist/components/container/src/container-utils.d.ts +23 -0
  81. package/dist/components/container/src/container-utils.js +51 -0
  82. package/dist/components/date-picker/index.d.ts +4 -2
  83. package/dist/components/date-picker/src/RsDatePicker.css +42 -22
  84. package/dist/components/date-picker/src/RsDatePicker.d.ts +44 -20
  85. package/dist/components/date-picker/src/RsDatePicker.impl.js +484 -222
  86. package/dist/components/date-picker/src/RsDatePicker.js +1 -3
  87. package/dist/components/date-picker/src/RsDateTimePicker.d.ts +33 -6
  88. package/dist/components/date-picker/src/RsDateTimePicker.impl.js +47 -6
  89. package/dist/components/date-picker/src/date-picker-utils.d.ts +19 -0
  90. package/dist/components/date-picker/src/date-picker-utils.js +33 -10
  91. package/dist/components/divider/index.d.ts +1 -0
  92. package/dist/components/divider/src/RsDivider.css +37 -22
  93. package/dist/components/divider/src/RsDivider.d.ts +4 -2
  94. package/dist/components/divider/src/RsDivider.impl.js +26 -12
  95. package/dist/components/divider/src/RsDivider.js +1 -1
  96. package/dist/components/divider/src/divider-utils.d.ts +4 -0
  97. package/dist/components/dynamic-tags/index.d.ts +1 -1
  98. package/dist/components/dynamic-tags/src/RsDynamicTags.css +115 -38
  99. package/dist/components/dynamic-tags/src/RsDynamicTags.d.ts +59 -18
  100. package/dist/components/dynamic-tags/src/RsDynamicTags.impl.js +269 -106
  101. package/dist/components/dynamic-tags/src/RsDynamicTags.js +1 -1
  102. package/dist/components/dynamic-tags/src/dynamic-tags-utils.d.ts +19 -0
  103. package/dist/components/dynamic-tags/src/dynamic-tags-utils.js +60 -0
  104. package/dist/components/fieldset/src/RsFieldset.css +71 -41
  105. package/dist/components/fieldset/src/RsFieldset.d.ts +21 -2
  106. package/dist/components/fieldset/src/RsFieldset.impl.js +93 -26
  107. package/dist/components/fieldset/src/RsFieldset.js +1 -1
  108. package/dist/components/fieldset/src/fieldset-utils.d.ts +4 -0
  109. package/dist/components/fieldset/src/fieldset-utils.js +9 -1
  110. package/dist/components/form/index.d.ts +1 -0
  111. package/dist/components/form/src/RsForm.css +15 -12
  112. package/dist/components/form/src/RsForm.d.ts +20 -22
  113. package/dist/components/form/src/RsForm.impl.js +33 -20
  114. package/dist/components/form/src/RsForm.js +1 -1
  115. package/dist/components/form/src/form-utils.d.ts +7 -0
  116. package/dist/components/form/src/form-utils.js +28 -1
  117. package/dist/components/icon/src/RsIcon.css +9 -4
  118. package/dist/components/icon/src/RsIcon.d.ts +4 -3
  119. package/dist/components/icon/src/RsIcon.impl.js +9 -32
  120. package/dist/components/icon/src/RsIcon.js +1 -1
  121. package/dist/components/icon/src/icon-utils.d.ts +17 -0
  122. package/dist/components/icon/src/icon-utils.js +39 -0
  123. package/dist/components/input/index.d.ts +1 -1
  124. package/dist/components/input/src/RsInput.css +78 -260
  125. package/dist/components/input/src/RsInput.d.ts +5 -3
  126. package/dist/components/input/src/RsInput.impl.js +8 -16
  127. package/dist/components/input/src/RsInput.js +1 -1
  128. package/dist/components/input/src/input-utils.d.ts +11 -0
  129. package/dist/components/input/src/input-utils.js +22 -0
  130. package/dist/components/input-number/index.d.ts +1 -0
  131. package/dist/components/input-number/src/RsInputNumber.css +31 -31
  132. package/dist/components/input-number/src/RsInputNumber.d.ts +15 -13
  133. package/dist/components/input-number/src/RsInputNumber.impl.js +17 -4
  134. package/dist/components/input-number/src/RsInputNumber.js +1 -1
  135. package/dist/components/label/src/RsLabel.css +30 -11
  136. package/dist/components/label/src/RsLabel.d.ts +18 -1
  137. package/dist/components/label/src/RsLabel.impl.js +63 -10
  138. package/dist/components/label/src/RsLabel.js +1 -1
  139. package/dist/components/label/src/label-utils.d.ts +6 -0
  140. package/dist/components/label/src/label-utils.js +16 -0
  141. package/dist/components/link/index.d.ts +1 -0
  142. package/dist/components/link/src/RsLink.css +58 -17
  143. package/dist/components/link/src/RsLink.d.ts +12 -4
  144. package/dist/components/link/src/RsLink.impl.js +26 -25
  145. package/dist/components/link/src/RsLink.js +2 -1
  146. package/dist/components/link/src/link-utils.d.ts +9 -0
  147. package/dist/components/link/src/link-utils.js +15 -0
  148. package/dist/components/loading/src/RsLoading.d.ts +2 -2
  149. package/dist/components/mentions/index.d.ts +2 -1
  150. package/dist/components/mentions/src/RsMentions.css +119 -3
  151. package/dist/components/mentions/src/RsMentions.d.ts +56 -4
  152. package/dist/components/mentions/src/RsMentions.impl.js +298 -79
  153. package/dist/components/mentions/src/RsMentions.js +1 -3
  154. package/dist/components/mentions/src/mentions-utils.d.ts +5 -1
  155. package/dist/components/mentions/src/mentions-utils.js +28 -9
  156. package/dist/components/popover/src/RsPopover.d.ts +1 -1
  157. package/dist/components/radio/index.d.ts +1 -1
  158. package/dist/components/radio/src/RsRadio.css +7 -6
  159. package/dist/components/radio/src/RsRadio.d.ts +8 -5
  160. package/dist/components/radio/src/RsRadio.impl.js +34 -24
  161. package/dist/components/radio/src/RsRadio.js +2 -1
  162. package/dist/components/radio/src/RsRadioItem.css +61 -44
  163. package/dist/components/radio/src/RsRadioItem.d.ts +2 -2
  164. package/dist/components/radio/src/RsRadioItem.impl.js +53 -20
  165. package/dist/components/radio/src/RsRadioItem.js +2 -1
  166. package/dist/components/radio/src/radio-utils.d.ts +12 -1
  167. package/dist/components/radio/src/radio-utils.js +15 -1
  168. package/dist/components/scrollbar/src/RsScrollbar.css +71 -24
  169. package/dist/components/scrollbar/src/RsScrollbar.d.ts +9 -5
  170. package/dist/components/scrollbar/src/RsScrollbar.impl.js +372 -47
  171. package/dist/components/scrollbar/src/RsScrollbar.js +2 -1
  172. package/dist/components/scrollbar/src/scrollbar-utils.d.ts +34 -2
  173. package/dist/components/scrollbar/src/scrollbar-utils.js +64 -1
  174. package/dist/components/select/index.d.ts +1 -0
  175. package/dist/components/select/src/RsSelect.css +54 -42
  176. package/dist/components/select/src/RsSelect.d.ts +19 -2
  177. package/dist/components/select/src/RsSelect.impl.js +727 -312
  178. package/dist/components/select/src/RsSelect.js +1 -1
  179. package/dist/components/select/src/select-utils.d.ts +4 -2
  180. package/dist/components/select/src/select-utils.js +8 -3
  181. package/dist/components/select/src/use-rs-select.d.ts +1 -0
  182. package/dist/components/select/src/use-rs-select.js +23 -17
  183. package/dist/components/switch/index.d.ts +2 -1
  184. package/dist/components/switch/src/RsSwitch.css +36 -18
  185. package/dist/components/switch/src/RsSwitch.d.ts +18 -5
  186. package/dist/components/switch/src/RsSwitch.impl.js +61 -29
  187. package/dist/components/switch/src/RsSwitch.js +2 -1
  188. package/dist/components/switch/src/switch-utils.d.ts +4 -0
  189. package/dist/components/switch/src/switch-utils.js +9 -0
  190. package/dist/components/tag/index.d.ts +1 -1
  191. package/dist/components/tag/src/RsTag.css +42 -38
  192. package/dist/components/tag/src/RsTag.d.ts +3 -2
  193. package/dist/components/tag/src/RsTag.impl.js +18 -9
  194. package/dist/components/tag/src/RsTag.js +1 -1
  195. package/dist/components/tag/src/tag-utils.d.ts +8 -0
  196. package/dist/components/terminal/src/RsTerminal.d.ts +1 -1
  197. package/dist/components/textarea/src/RsTextarea.css +23 -23
  198. package/dist/components/textarea/src/RsTextarea.d.ts +6 -12
  199. package/dist/components/textarea/src/RsTextarea.impl.js +37 -46
  200. package/dist/components/textarea/src/RsTextarea.js +1 -1
  201. package/dist/components/textarea/src/textarea-utils.d.ts +27 -0
  202. package/dist/components/textarea/src/textarea-utils.js +61 -0
  203. package/dist/components/time-picker/index.d.ts +3 -2
  204. package/dist/components/time-picker/src/RsTimePicker.css +41 -24
  205. package/dist/components/time-picker/src/RsTimePicker.d.ts +52 -7
  206. package/dist/components/time-picker/src/RsTimePicker.impl.js +520 -156
  207. package/dist/components/time-picker/src/RsTimePicker.js +1 -3
  208. package/dist/components/time-picker/src/RsTimePickerColumns.css +26 -18
  209. package/dist/components/time-picker/src/RsTimePickerColumns.d.ts +3 -1
  210. package/dist/components/time-picker/src/RsTimePickerColumns.impl.js +62 -9
  211. package/dist/components/time-picker/src/RsTimePickerColumns.js +1 -1
  212. package/dist/components/time-picker/src/time-picker-utils.d.ts +38 -0
  213. package/dist/components/time-picker/src/time-picker-utils.js +97 -5
  214. package/dist/components/toaster/src/RsToaster.d.ts +1 -1
  215. package/dist/components/tooltip/src/RsTooltip.d.ts +1 -1
  216. package/dist/components/tree/src/RsTree.d.ts +3 -3
  217. package/dist/components/tree-select/index.d.ts +2 -0
  218. package/dist/components/tree-select/src/RsTreeSelect.css +100 -25
  219. package/dist/components/tree-select/src/RsTreeSelect.d.ts +91 -7
  220. package/dist/components/tree-select/src/RsTreeSelect.impl.js +464 -79
  221. package/dist/components/tree-select/src/RsTreeSelect.js +1 -1
  222. package/dist/components/tree-select/src/tree-select-utils.d.ts +20 -0
  223. package/dist/components/tree-select/src/tree-select-utils.js +60 -0
  224. package/dist/components/upload/index.d.ts +2 -1
  225. package/dist/components/upload/src/RsUpload.css +223 -75
  226. package/dist/components/upload/src/RsUpload.d.ts +77 -1
  227. package/dist/components/upload/src/RsUpload.impl.js +404 -90
  228. package/dist/components/upload/src/RsUpload.js +1 -1
  229. package/dist/components/upload/src/upload-utils.d.ts +21 -2
  230. package/dist/components/upload/src/upload-utils.js +139 -9
  231. package/dist/index.d.ts +24 -11
  232. package/dist/index.js +6 -0
  233. package/dist/locale/messages.js +46 -2
  234. package/dist/styles.css +518 -154
  235. package/dist/theme/brand.example.css +1 -1
  236. package/package.json +9 -8
  237. package/dist/components/breadcrumb/src/RsBreadcrumbItems.d.ts +0 -8
  238. package/dist/components/breadcrumb/src/RsBreadcrumbItems.impl.js +0 -40
  239. package/dist/components/breadcrumb/src/RsBreadcrumbItems.js +0 -5
  240. package/dist/components/date-picker/src/RsDatePicker-1.css +0 -157
  241. package/dist/components/mentions/src/RsMentions-1.css +0 -29
  242. package/dist/components/time-picker/src/RsTimePicker-1.css +0 -98
@@ -1,19 +1,18 @@
1
1
  import { useRsI18n } from "../../../composables/useRsI18n.js";
2
- import { computeScrollTopForTarget, flattenAnchorItems, hrefToAnchorId, pickActiveAnchorHref, resolveAnchorContainer, scrollContainerTo, targetTopInContainer } from "./anchor-utils.js";
3
- import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeModels, nextTick, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, ref, renderList, toDisplayString, unref, useModel, watch } from "vue";
2
+ import { collectAnchorTops, computeScrollTopForTarget, flattenAnchorItems, hrefToAnchorId, isAnchorScrolledToEnd, isAnchorWindow, pickActiveAnchorHref, resolveAnchorContainer, scrollContainerTo, writeAnchorHash } from "./anchor-utils.js";
3
+ import { Fragment, computed, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, defineComponent, mergeModels, nextTick, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, ref, renderList, renderSlot, toDisplayString, useModel, watch } from "vue";
4
4
  //#region src/components/anchor/src/RsAnchor.vue?vue&type=script&setup=true&lang.ts
5
- var _hoisted_1 = ["aria-label"];
6
- var _hoisted_2 = {
7
- key: 0,
8
- class: "rs-anchor__rail",
9
- "aria-hidden": "true"
10
- };
11
- var _hoisted_3 = { class: "rs-anchor__list" };
12
- var _hoisted_4 = [
5
+ var _hoisted_1 = ["id", "aria-label"];
6
+ var _hoisted_2 = { class: "rs-anchor__list" };
7
+ var _hoisted_3 = [
13
8
  "href",
14
9
  "data-rs-anchor-href",
10
+ "aria-current",
11
+ "aria-disabled",
15
12
  "onClick"
16
13
  ];
14
+ var CLICK_LOCK_IDLE_MS = 120;
15
+ var CLICK_LOCK_FALLBACK_MS = 360;
17
16
  var RsAnchor_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
18
17
  name: "RsAnchor",
19
18
  __name: "RsAnchor",
@@ -26,6 +25,7 @@ var RsAnchor_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineC
26
25
  type: Boolean,
27
26
  default: true
28
27
  },
28
+ affixOffset: {},
29
29
  lineless: {
30
30
  type: Boolean,
31
31
  default: false
@@ -34,153 +34,271 @@ var RsAnchor_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineC
34
34
  type: Boolean,
35
35
  default: true
36
36
  },
37
- getContainer: {}
37
+ replace: {
38
+ type: Boolean,
39
+ default: true
40
+ },
41
+ direction: { default: "vertical" },
42
+ scrollBehavior: {},
43
+ getCurrentAnchor: {},
44
+ getContainer: {},
45
+ id: {},
46
+ ariaLabel: {}
38
47
  }, {
39
48
  "modelValue": { default: "" },
40
49
  "modelModifiers": {}
41
50
  }),
42
51
  emits: /*@__PURE__*/ mergeModels(["change", "click"], ["update:modelValue"]),
43
- setup(__props, { emit: __emit }) {
52
+ setup(__props, { expose: __expose, emit: __emit }) {
44
53
  const props = __props;
45
54
  const activeHref = useModel(__props, "modelValue");
46
55
  const emit = __emit;
47
56
  const { t } = useRsI18n();
48
57
  const rootRef = ref(null);
58
+ const railRef = ref(null);
49
59
  const inkStyle = ref({});
60
+ const linkRefs = /* @__PURE__ */ new Map();
50
61
  const flatItems = computed(() => flattenAnchorItems(props.items));
51
62
  const resolvedTargetOffset = computed(() => props.targetOffset ?? props.offset);
63
+ const navLabel = computed(() => props.ariaLabel || t("anchor.label"));
64
+ const rootStyle = computed(() => {
65
+ if (props.affixOffset == null) return void 0;
66
+ return { "--rs-anchor-affix-top": `${props.affixOffset}px` };
67
+ });
68
+ const targetCache = /* @__PURE__ */ new Map();
52
69
  let scrollTarget = null;
53
- let ticking = false;
70
+ let rafId = 0;
71
+ let resizeObserver = null;
72
+ let clickLockHref = "";
73
+ let clickLockTimer = 0;
54
74
  function findTarget(href) {
75
+ const cached = targetCache.get(href);
76
+ if (cached?.isConnected) return cached;
55
77
  const id = hrefToAnchorId(href);
56
78
  if (!id || typeof document === "undefined") return null;
57
- return document.getElementById(id);
79
+ const el = document.getElementById(id);
80
+ if (el) targetCache.set(href, el);
81
+ else targetCache.delete(href);
82
+ return el;
58
83
  }
59
- function findLinkByHref(root, href) {
60
- const links = root.querySelectorAll("[data-rs-anchor-href]");
61
- for (const link of links) if (link.dataset.rsAnchorHref === href) return link;
62
- return null;
63
- }
64
- function collectTops(container) {
65
- return flatItems.value.map((item) => {
66
- const el = findTarget(item.href);
67
- if (!el) return null;
68
- return {
69
- href: item.href,
70
- top: targetTopInContainer(el, container)
71
- };
72
- }).filter((entry) => Boolean(entry));
84
+ function setLinkRef(href, el) {
85
+ if (el instanceof HTMLElement) {
86
+ linkRefs.set(href, el);
87
+ return;
88
+ }
89
+ linkRefs.delete(href);
73
90
  }
74
91
  function setActive(href) {
75
- if (!href || href === activeHref.value) return;
76
- activeHref.value = href;
77
- emit("change", href);
92
+ const next = props.getCurrentAnchor?.(href) ?? href;
93
+ if (!next || next === activeHref.value) return;
94
+ activeHref.value = next;
95
+ emit("change", next);
78
96
  }
79
97
  function syncInk() {
80
- const root = rootRef.value;
81
- if (!root || props.lineless) return;
82
- const current = activeHref.value || flatItems.value[0]?.href;
98
+ if (props.lineless) return;
99
+ const current = activeHref.value || flatItems.value.find((item) => !item.disabled)?.href;
83
100
  if (!current) {
84
101
  inkStyle.value = { opacity: "0" };
85
102
  return;
86
103
  }
87
- const link = findLinkByHref(root, current);
88
- if (!link) {
104
+ const link = linkRefs.get(current);
105
+ const rail = railRef.value;
106
+ if (!link || !rail) {
89
107
  inkStyle.value = { opacity: "0" };
90
108
  return;
91
109
  }
110
+ const linkRect = link.getBoundingClientRect();
111
+ const railRect = rail.getBoundingClientRect();
112
+ if (props.direction === "horizontal") {
113
+ inkStyle.value = {
114
+ opacity: "1",
115
+ width: `${Math.max(0, linkRect.width)}px`,
116
+ height: "100%",
117
+ transform: `translate3d(${linkRect.left - railRect.left}px, 0, 0)`
118
+ };
119
+ return;
120
+ }
92
121
  inkStyle.value = {
93
122
  opacity: "1",
94
- transform: `translateY(${link.offsetTop}px)`,
95
- height: `${link.offsetHeight}px`
123
+ width: "100%",
124
+ height: `${Math.max(0, linkRect.height)}px`,
125
+ transform: `translate3d(0, ${linkRect.top - railRect.top}px, 0)`
96
126
  };
97
127
  }
128
+ function releaseClickLock() {
129
+ clickLockHref = "";
130
+ if (clickLockTimer) {
131
+ window.clearTimeout(clickLockTimer);
132
+ clickLockTimer = 0;
133
+ }
134
+ syncFromScroll();
135
+ }
136
+ function armClickLock(href) {
137
+ clickLockHref = href;
138
+ if (clickLockTimer) window.clearTimeout(clickLockTimer);
139
+ if (typeof window === "undefined") return;
140
+ clickLockTimer = window.setTimeout(releaseClickLock, CLICK_LOCK_FALLBACK_MS);
141
+ }
142
+ function bumpClickLock() {
143
+ if (!clickLockHref || typeof window === "undefined") return;
144
+ if (clickLockTimer) window.clearTimeout(clickLockTimer);
145
+ clickLockTimer = window.setTimeout(releaseClickLock, CLICK_LOCK_IDLE_MS);
146
+ }
98
147
  function syncFromScroll() {
99
- if (!scrollTarget) return;
100
- const next = pickActiveAnchorHref(collectTops(scrollTarget), props.offset + props.bounds);
148
+ if (!scrollTarget || clickLockHref) return;
149
+ const next = pickActiveAnchorHref(collectAnchorTops(flatItems.value, scrollTarget, findTarget), props.offset + props.bounds, { atEnd: isAnchorScrolledToEnd(scrollTarget) });
101
150
  if (next) setActive(next);
102
- nextTick(syncInk);
151
+ }
152
+ function cancelScrollFrame() {
153
+ if (!rafId) return;
154
+ cancelAnimationFrame(rafId);
155
+ rafId = 0;
103
156
  }
104
157
  function onScroll() {
105
- if (ticking) return;
106
- ticking = true;
107
- requestAnimationFrame(() => {
108
- ticking = false;
158
+ if (clickLockHref) {
159
+ bumpClickLock();
160
+ return;
161
+ }
162
+ if (rafId) return;
163
+ rafId = requestAnimationFrame(() => {
164
+ rafId = 0;
109
165
  syncFromScroll();
110
166
  });
111
167
  }
168
+ function unbindContainer() {
169
+ cancelScrollFrame();
170
+ clickLockHref = "";
171
+ if (clickLockTimer) {
172
+ window.clearTimeout(clickLockTimer);
173
+ clickLockTimer = 0;
174
+ }
175
+ scrollTarget?.removeEventListener("scroll", onScroll);
176
+ scrollTarget = null;
177
+ resizeObserver?.disconnect();
178
+ resizeObserver = null;
179
+ }
112
180
  function bindContainer() {
113
- unbindContainer();
114
- try {
115
- scrollTarget = resolveAnchorContainer(props.getContainer);
116
- } catch {
117
- scrollTarget = null;
181
+ const next = resolveAnchorContainer(props.getContainer);
182
+ if (next === scrollTarget && scrollTarget) {
183
+ syncFromScroll();
118
184
  return;
119
185
  }
186
+ unbindContainer();
187
+ scrollTarget = next;
188
+ if (!scrollTarget) return;
120
189
  scrollTarget.addEventListener("scroll", onScroll, { passive: true });
190
+ if (typeof ResizeObserver !== "undefined") {
191
+ resizeObserver = new ResizeObserver(() => {
192
+ if (clickLockHref) return;
193
+ onScroll();
194
+ nextTick(syncInk);
195
+ });
196
+ if (!isAnchorWindow(scrollTarget)) resizeObserver.observe(scrollTarget);
197
+ if (rootRef.value) resizeObserver.observe(rootRef.value);
198
+ }
121
199
  syncFromScroll();
122
200
  }
123
- function unbindContainer() {
124
- scrollTarget?.removeEventListener("scroll", onScroll);
125
- scrollTarget = null;
126
- }
127
- function onSelect(href, event) {
128
- event.preventDefault();
129
- emit("click", href, event);
201
+ function scrollToHref(href) {
202
+ if (flatItems.value.find((entry) => entry.href === href)?.disabled) return;
130
203
  const target = findTarget(href);
131
204
  const container = scrollTarget ?? resolveAnchorContainer(props.getContainer);
132
- if (target) scrollContainerTo(container, computeScrollTopForTarget(target, container, resolvedTargetOffset.value));
205
+ if (target && container) scrollContainerTo(container, computeScrollTopForTarget(target, container, resolvedTargetOffset.value), props.scrollBehavior);
133
206
  setActive(href);
134
- if (props.changeHash && typeof history !== "undefined") {
135
- const id = hrefToAnchorId(href);
136
- const url = new URL(window.location.href);
137
- url.hash = id;
138
- history.replaceState(history.state, "", `${url.pathname}${url.search}#${id}`);
139
- }
207
+ armClickLock(href);
208
+ if (props.changeHash) writeAnchorHash(href, props.replace);
209
+ nextTick(syncInk);
210
+ }
211
+ function onSelect(href, event, disabled) {
212
+ event.preventDefault();
213
+ emit("click", href, event);
214
+ if (disabled) return;
215
+ scrollToHref(href);
216
+ }
217
+ function onWindowResize() {
218
+ if (clickLockHref) bumpClickLock();
219
+ else onScroll();
140
220
  nextTick(syncInk);
141
221
  }
142
222
  onMounted(() => {
143
223
  bindContainer();
144
- window.addEventListener("resize", onScroll, { passive: true });
224
+ nextTick(bindContainer);
225
+ if (typeof window !== "undefined") window.addEventListener("resize", onWindowResize, { passive: true });
145
226
  });
146
227
  onUnmounted(() => {
147
228
  unbindContainer();
148
- window.removeEventListener("resize", onScroll);
229
+ targetCache.clear();
230
+ linkRefs.clear();
231
+ if (typeof window !== "undefined") window.removeEventListener("resize", onWindowResize);
232
+ });
233
+ watch(() => props.getContainer?.() ?? null, (next, prev) => {
234
+ if (next === prev) return;
235
+ nextTick(bindContainer);
236
+ });
237
+ watch(() => flatItems.value.map((item) => `${item.href}\0${item.title}\0${item.depth}\0${item.disabled ? 1 : 0}`).join("\n"), (signature) => {
238
+ targetCache.clear();
239
+ if (!signature) {
240
+ unbindContainer();
241
+ return;
242
+ }
243
+ nextTick(bindContainer);
149
244
  });
150
245
  watch(() => [
151
- props.items,
152
- props.getContainer,
153
246
  props.offset,
154
- props.bounds
247
+ props.bounds,
248
+ props.direction,
249
+ props.lineless
155
250
  ], () => {
156
- nextTick(bindContainer);
157
- }, { deep: true });
251
+ nextTick(syncFromScroll);
252
+ });
158
253
  watch(activeHref, () => {
159
254
  nextTick(syncInk);
160
255
  });
256
+ __expose({ scrollTo: scrollToHref });
161
257
  return (_ctx, _cache) => {
162
258
  return flatItems.value.length ? (openBlock(), createElementBlock("nav", {
163
259
  key: 0,
260
+ id: __props.id,
164
261
  ref_key: "rootRef",
165
262
  ref: rootRef,
166
263
  class: normalizeClass(["rs-anchor", {
167
264
  "rs-anchor--affix": __props.affix,
168
- "rs-anchor--lineless": __props.lineless
265
+ "rs-anchor--lineless": __props.lineless,
266
+ "rs-anchor--horizontal": __props.direction === "horizontal"
169
267
  }]),
170
- "aria-label": unref(t)("anchor.label")
171
- }, [!__props.lineless ? (openBlock(), createElementBlock("div", _hoisted_2, [createElementVNode("span", {
268
+ style: normalizeStyle(rootStyle.value),
269
+ "aria-label": navLabel.value
270
+ }, [!__props.lineless ? (openBlock(), createElementBlock("div", {
271
+ key: 0,
272
+ ref_key: "railRef",
273
+ ref: railRef,
274
+ class: "rs-anchor__rail",
275
+ "aria-hidden": "true"
276
+ }, [createElementVNode("span", {
172
277
  class: "rs-anchor__ink",
173
278
  style: normalizeStyle(inkStyle.value)
174
- }, null, 4)])) : createCommentVNode("", true), createElementVNode("div", _hoisted_3, [(openBlock(true), createElementBlock(Fragment, null, renderList(flatItems.value, (item) => {
175
- return openBlock(), createElementBlock("a", {
279
+ }, null, 4)], 512)) : createCommentVNode("", true), createElementVNode("ul", _hoisted_2, [(openBlock(true), createElementBlock(Fragment, null, renderList(flatItems.value, (item) => {
280
+ return openBlock(), createElementBlock("li", {
176
281
  key: item.href,
177
- class: normalizeClass(["rs-anchor__link", { "rs-anchor__link--active": item.href === activeHref.value }]),
178
- style: normalizeStyle({ paddingInlineStart: `${.7 + item.depth * .75}rem` }),
282
+ class: "rs-anchor__item"
283
+ }, [createElementVNode("a", {
284
+ class: normalizeClass(["rs-anchor__link", {
285
+ "rs-anchor__link--active": item.href === activeHref.value,
286
+ "rs-anchor__link--disabled": item.disabled
287
+ }]),
288
+ style: normalizeStyle(__props.direction === "vertical" ? { paddingInlineStart: `calc(var(--rs-anchor-link-pad-inline) + ${item.depth} * var(--rs-anchor-indent))` } : void 0),
179
289
  href: item.href,
290
+ ref_for: true,
291
+ ref: (el) => setLinkRef(item.href, el),
180
292
  "data-rs-anchor-href": item.href,
181
- onClick: ($event) => onSelect(item.href, $event)
182
- }, toDisplayString(item.title), 15, _hoisted_4);
183
- }), 128))])], 10, _hoisted_1)) : createCommentVNode("", true);
293
+ "aria-current": item.href === activeHref.value ? "location" : void 0,
294
+ "aria-disabled": item.disabled ? "true" : void 0,
295
+ onClick: ($event) => onSelect(item.href, $event, item.disabled)
296
+ }, [renderSlot(_ctx.$slots, "item", {
297
+ item,
298
+ active: item.href === activeHref.value,
299
+ href: item.href
300
+ }, () => [createTextVNode(toDisplayString(item.title), 1)], true)], 14, _hoisted_3)]);
301
+ }), 128))])], 14, _hoisted_1)) : createCommentVNode("", true);
184
302
  };
185
303
  }
186
304
  });
@@ -3,6 +3,6 @@ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_exp
3
3
  import RsAnchor_vue_vue_type_script_setup_true_lang_default from "./RsAnchor.impl.js";
4
4
 
5
5
  //#region src/components/anchor/src/RsAnchor.vue
6
- var RsAnchor_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsAnchor_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-c95cbe5f"]]);
6
+ var RsAnchor_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsAnchor_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-ad557668"]]);
7
7
  //#endregion
8
8
  export { RsAnchor_default as default };
@@ -1,26 +1,58 @@
1
1
  export interface RsAnchorItem {
2
2
  href: string;
3
3
  title: string;
4
+ disabled?: boolean;
4
5
  children?: RsAnchorItem[];
5
6
  }
6
7
  export interface RsAnchorFlatItem {
7
8
  href: string;
8
9
  title: string;
9
10
  depth: number;
11
+ disabled?: boolean;
10
12
  }
11
- /** `#overview` / `path#overview` → `overview` */
13
+ export type RsAnchorDirection = 'vertical' | 'horizontal';
14
+ export type RsAnchorScrollBehavior = 'smooth' | 'auto';
15
+ export interface RsAnchorExpose {
16
+ /** 滚到对应章节并激活。禁用项或找不到目标时不滚动。 */
17
+ scrollTo: (href: string) => void;
18
+ }
19
+ /** 模板 ref 实例:expose + 根节点 */
20
+ export type RsAnchorInstance = RsAnchorExpose & {
21
+ $el: HTMLElement;
22
+ };
23
+ /** `#overview` / `path#overview` / `#%E6%A6%82%E8%BF%B0` → `overview` / `概述` */
12
24
  export declare function hrefToAnchorId(href: string): string;
13
25
  export declare function flattenAnchorItems(items: RsAnchorItem[], depth?: number): RsAnchorFlatItem[];
14
26
  /**
15
27
  * 滚动监听:取最后一个 top <= offset 的标题。
16
28
  * entries 须按文档顺序(与 DOM 一致),top 为相对滚动容器顶部的距离。
29
+ * atEnd:容器已贴底时最后一节往往到不了判定线,仍应高亮最后一项。
17
30
  */
18
31
  export declare function pickActiveAnchorHref(entries: ReadonlyArray<{
19
32
  href: string;
20
33
  top: number;
21
- }>, offset: number): string;
22
- export declare function resolveAnchorContainer(getContainer?: () => HTMLElement | Window | null | undefined): HTMLElement | Window;
34
+ }>, offset: number, options?: {
35
+ atEnd?: boolean;
36
+ }): string;
37
+ /** 用 scrollY / nodeType 判断,避免跨 iframe 的 `instanceof Window`。 */
38
+ export declare function isAnchorWindow(container: unknown): container is Window;
39
+ export declare function resolveAnchorContainer(getContainer?: () => HTMLElement | Window | null | undefined): HTMLElement | Window | null;
23
40
  export declare function readContainerScrollTop(container: HTMLElement | Window): number;
41
+ export declare function readContainerScrollExtent(container: HTMLElement | Window): {
42
+ top: number;
43
+ max: number;
44
+ };
45
+ /** 贴底判定。slack 吃掉亚像素,避免最后一项永远亮不起来。 */
46
+ export declare function isAnchorScrolledToEnd(container: HTMLElement | Window, slack?: number): boolean;
24
47
  export declare function targetTopInContainer(target: HTMLElement, container: HTMLElement | Window): number;
25
- export declare function scrollContainerTo(container: HTMLElement | Window, top: number): void;
48
+ export declare function prefersAnchorReducedMotion(): boolean;
49
+ export declare function resolveAnchorScrollBehavior(behavior?: RsAnchorScrollBehavior): ScrollBehavior;
50
+ export declare function scrollContainerTo(container: HTMLElement | Window, top: number, behavior?: RsAnchorScrollBehavior): void;
26
51
  export declare function computeScrollTopForTarget(target: HTMLElement, container: HTMLElement | Window, targetOffset: number): number;
52
+ export declare function collectAnchorTops(items: ReadonlyArray<{
53
+ href: string;
54
+ }>, container: HTMLElement | Window, findTarget: (href: string) => HTMLElement | null): Array<{
55
+ href: string;
56
+ top: number;
57
+ }>;
58
+ export declare function writeAnchorHash(href: string, replace: boolean): void;
@@ -1,8 +1,14 @@
1
1
  //#region src/components/anchor/src/anchor-utils.ts
2
- /** `#overview` / `path#overview` → `overview` */
2
+ /** `#overview` / `path#overview` / `#%E6%A6%82%E8%BF%B0` → `overview` / `概述` */
3
3
  function hrefToAnchorId(href) {
4
4
  const raw = href.trim();
5
- return (raw.includes("#") ? raw.slice(raw.indexOf("#") + 1) : raw).replace(/^#/, "");
5
+ const id = (raw.includes("#") ? raw.slice(raw.indexOf("#") + 1) : raw).replace(/^#/, "");
6
+ if (!id) return "";
7
+ try {
8
+ return decodeURIComponent(id);
9
+ } catch {
10
+ return id;
11
+ }
6
12
  }
7
13
  function flattenAnchorItems(items, depth = 0) {
8
14
  const out = [];
@@ -10,7 +16,8 @@ function flattenAnchorItems(items, depth = 0) {
10
16
  out.push({
11
17
  href: item.href,
12
18
  title: item.title,
13
- depth
19
+ depth,
20
+ disabled: item.disabled
14
21
  });
15
22
  if (item.children?.length) out.push(...flattenAnchorItems(item.children, depth + 1));
16
23
  }
@@ -19,39 +26,67 @@ function flattenAnchorItems(items, depth = 0) {
19
26
  /**
20
27
  * 滚动监听:取最后一个 top <= offset 的标题。
21
28
  * entries 须按文档顺序(与 DOM 一致),top 为相对滚动容器顶部的距离。
29
+ * atEnd:容器已贴底时最后一节往往到不了判定线,仍应高亮最后一项。
22
30
  */
23
- function pickActiveAnchorHref(entries, offset) {
31
+ function pickActiveAnchorHref(entries, offset, options) {
24
32
  if (entries.length === 0) return "";
33
+ if (options?.atEnd) return entries[entries.length - 1]?.href ?? "";
25
34
  let active = entries[0]?.href ?? "";
26
35
  for (const entry of entries) if (entry.top <= offset) active = entry.href;
27
36
  return active;
28
37
  }
38
+ /** 用 scrollY / nodeType 判断,避免跨 iframe 的 `instanceof Window`。 */
39
+ function isAnchorWindow(container) {
40
+ return Boolean(container && typeof container === "object" && "scrollY" in container && !("nodeType" in container));
41
+ }
29
42
  function resolveAnchorContainer(getContainer) {
30
- const resolved = getContainer?.();
31
- if (resolved) return resolved;
43
+ try {
44
+ const resolved = getContainer?.();
45
+ if (resolved) return resolved;
46
+ } catch {}
32
47
  if (typeof window !== "undefined") return window;
33
- throw new Error("RsAnchor: no scroll container");
48
+ return null;
34
49
  }
35
50
  function readContainerScrollTop(container) {
36
- if (container instanceof Window) return container.scrollY;
51
+ if (isAnchorWindow(container)) return container.scrollY;
37
52
  return container.scrollTop;
38
53
  }
54
+ function readContainerScrollExtent(container) {
55
+ if (isAnchorWindow(container)) {
56
+ const root = typeof document === "undefined" ? null : document.scrollingElement || document.documentElement;
57
+ return {
58
+ top: container.scrollY,
59
+ max: root ? Math.max(0, root.scrollHeight - container.innerHeight) : 0
60
+ };
61
+ }
62
+ return {
63
+ top: container.scrollTop,
64
+ max: Math.max(0, container.scrollHeight - container.clientHeight)
65
+ };
66
+ }
67
+ /** 贴底判定。slack 吃掉亚像素,避免最后一项永远亮不起来。 */
68
+ function isAnchorScrolledToEnd(container, slack = 4) {
69
+ const { top, max } = readContainerScrollExtent(container);
70
+ return max > 0 && top >= max - slack;
71
+ }
39
72
  function targetTopInContainer(target, container) {
40
73
  const targetRect = target.getBoundingClientRect();
41
- if (container instanceof Window) return targetRect.top;
74
+ if (isAnchorWindow(container)) return targetRect.top;
42
75
  return targetRect.top - container.getBoundingClientRect().top;
43
76
  }
44
- function scrollContainerTo(container, top) {
45
- if (container instanceof Window) {
46
- container.scrollTo({
47
- top,
48
- behavior: "smooth"
49
- });
50
- return;
51
- }
77
+ function prefersAnchorReducedMotion() {
78
+ if (typeof matchMedia === "undefined") return false;
79
+ return matchMedia("(prefers-reduced-motion: reduce)").matches;
80
+ }
81
+ function resolveAnchorScrollBehavior(behavior) {
82
+ if (behavior) return behavior;
83
+ return prefersAnchorReducedMotion() ? "auto" : "smooth";
84
+ }
85
+ function scrollContainerTo(container, top, behavior) {
86
+ const resolved = resolveAnchorScrollBehavior(behavior);
52
87
  container.scrollTo({
53
88
  top,
54
- behavior: "smooth"
89
+ behavior: resolved
55
90
  });
56
91
  }
57
92
  function computeScrollTopForTarget(target, container, targetOffset) {
@@ -59,5 +94,32 @@ function computeScrollTopForTarget(target, container, targetOffset) {
59
94
  const relativeTop = targetTopInContainer(target, container);
60
95
  return Math.max(0, current + relativeTop - targetOffset);
61
96
  }
97
+ function collectAnchorTops(items, container, findTarget) {
98
+ const windowLike = isAnchorWindow(container);
99
+ const containerTop = windowLike ? 0 : container.getBoundingClientRect().top;
100
+ const out = [];
101
+ for (const item of items) {
102
+ const el = findTarget(item.href);
103
+ if (!el) continue;
104
+ const top = windowLike ? el.getBoundingClientRect().top : el.getBoundingClientRect().top - containerTop;
105
+ out.push({
106
+ href: item.href,
107
+ top
108
+ });
109
+ }
110
+ return out;
111
+ }
112
+ function writeAnchorHash(href, replace) {
113
+ if (typeof history === "undefined" || typeof window === "undefined") return;
114
+ const id = hrefToAnchorId(href);
115
+ if (!id) return;
116
+ const url = new URL(window.location.href);
117
+ const next = `${url.pathname}${url.search}#${id}`;
118
+ if (replace) {
119
+ history.replaceState(history.state, "", next);
120
+ return;
121
+ }
122
+ history.pushState(history.state, "", next);
123
+ }
62
124
  //#endregion
63
- export { computeScrollTopForTarget, flattenAnchorItems, hrefToAnchorId, pickActiveAnchorHref, readContainerScrollTop, resolveAnchorContainer, scrollContainerTo, targetTopInContainer };
125
+ export { collectAnchorTops, computeScrollTopForTarget, flattenAnchorItems, hrefToAnchorId, isAnchorScrolledToEnd, isAnchorWindow, pickActiveAnchorHref, prefersAnchorReducedMotion, readContainerScrollExtent, readContainerScrollTop, resolveAnchorContainer, resolveAnchorScrollBehavior, scrollContainerTo, targetTopInContainer, writeAnchorHash };
@@ -1 +1,3 @@
1
1
  export { default as RsAutoComplete } from './src/RsAutoComplete.js';
2
+ export type { RsAutoCompleteExpose, RsAutoCompleteInstance, } from './src/RsAutoComplete.js';
3
+ export type { RsAutoCompleteFilterOption, RsAutoCompleteOption, RsAutoCompleteOptionInput, } from './src/auto-complete-utils';