niuma-ui 2.0.1 → 2.0.3

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 (87) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.en.md +1 -118
  3. package/README.md +60 -62
  4. package/README.zh-CN.md +130 -0
  5. package/dist/components/_shared/src/reka.d.ts +1 -1
  6. package/dist/components/_shared/src/reka.js +2 -2
  7. package/dist/components/avatar/src/RsAvatar.impl.js +1 -1
  8. package/dist/components/badge/index.d.ts +1 -0
  9. package/dist/components/badge/src/RsBadge.css +61 -8
  10. package/dist/components/badge/src/RsBadge.d.ts +19 -3
  11. package/dist/components/badge/src/RsBadge.impl.js +46 -3
  12. package/dist/components/badge/src/RsBadge.js +1 -1
  13. package/dist/components/badge/src/badge-utils.d.ts +11 -0
  14. package/dist/components/badge/src/badge-utils.js +32 -0
  15. package/dist/components/button/src/RsButton.css +87 -71
  16. package/dist/components/button/src/RsButton.d.ts +7 -3
  17. package/dist/components/button/src/RsButton.impl.js +43 -31
  18. package/dist/components/button/src/RsButton.js +1 -1
  19. package/dist/components/button/src/button-utils.d.ts +17 -0
  20. package/dist/components/button/src/button-utils.js +14 -1
  21. package/dist/components/card/src/RsCard.impl.js +1 -1
  22. package/dist/components/cascader/src/RsCascader.d.ts +1 -1
  23. package/dist/components/config-provider/src/RsConfigProvider.css +1 -1
  24. package/dist/components/config-provider/src/RsConfigProvider.d.ts +2 -3
  25. package/dist/components/config-provider/src/RsConfigProvider.impl.js +20 -11
  26. package/dist/components/config-provider/src/RsConfigProvider.js +1 -1
  27. package/dist/components/context-menu/src/RsContextMenuItems.impl.js +1 -1
  28. package/dist/components/date-picker/src/RsDatePicker.impl.js +1 -1
  29. package/dist/components/dialog/src/RsConfirmDialog.impl.js +1 -1
  30. package/dist/components/dialog/src/RsDialog.impl.js +1 -1
  31. package/dist/components/divider/index.d.ts +1 -0
  32. package/dist/components/divider/src/RsDivider.css +37 -22
  33. package/dist/components/divider/src/RsDivider.d.ts +4 -2
  34. package/dist/components/divider/src/RsDivider.impl.js +26 -12
  35. package/dist/components/divider/src/RsDivider.js +1 -1
  36. package/dist/components/divider/src/divider-utils.d.ts +4 -0
  37. package/dist/components/drawer/src/RsDrawer.impl.js +1 -1
  38. package/dist/components/dropdown/src/RsDropdown.impl.js +1 -1
  39. package/dist/components/dynamic-tags/src/RsDynamicTags.css +23 -23
  40. package/dist/components/dynamic-tags/src/RsDynamicTags.d.ts +1 -1
  41. package/dist/components/dynamic-tags/src/RsDynamicTags.js +1 -1
  42. package/dist/components/form/src/form-rules.js +2 -2
  43. package/dist/components/icon/src/RsIcon.css +9 -4
  44. package/dist/components/icon/src/RsIcon.d.ts +4 -3
  45. package/dist/components/icon/src/RsIcon.impl.js +9 -32
  46. package/dist/components/icon/src/RsIcon.js +1 -1
  47. package/dist/components/icon/src/icon-utils.d.ts +17 -0
  48. package/dist/components/icon/src/icon-utils.js +39 -0
  49. package/dist/components/input/src/input-rules.js +3 -3
  50. package/dist/components/link/index.d.ts +1 -0
  51. package/dist/components/link/src/RsLink.css +58 -17
  52. package/dist/components/link/src/RsLink.d.ts +12 -4
  53. package/dist/components/link/src/RsLink.impl.js +26 -25
  54. package/dist/components/link/src/RsLink.js +2 -1
  55. package/dist/components/link/src/link-utils.d.ts +9 -0
  56. package/dist/components/link/src/link-utils.js +15 -0
  57. package/dist/components/loading/src/RsLoading.d.ts +2 -2
  58. package/dist/components/menu/src/RsMenuItems.impl.js +1 -1
  59. package/dist/components/radio/src/RsRadio.impl.js +1 -1
  60. package/dist/components/radio/src/RsRadioItem.impl.js +1 -1
  61. package/dist/components/select/src/RsSelect.impl.js +1 -1
  62. package/dist/components/switch/src/RsSwitch.impl.js +1 -1
  63. package/dist/components/tabs/src/RsTabs.impl.js +1 -1
  64. package/dist/components/tag/index.d.ts +1 -1
  65. package/dist/components/tag/src/RsTag.css +42 -38
  66. package/dist/components/tag/src/RsTag.d.ts +3 -2
  67. package/dist/components/tag/src/RsTag.impl.js +18 -9
  68. package/dist/components/tag/src/RsTag.js +1 -1
  69. package/dist/components/tag/src/tag-utils.d.ts +8 -0
  70. package/dist/components/terminal/src/RsTerminal.d.ts +1 -1
  71. package/dist/components/time-picker/src/RsTimePicker.impl.js +1 -1
  72. package/dist/components/tooltip/src/RsTooltip.impl.js +1 -1
  73. package/dist/composables/createRsDialog.js +3 -3
  74. package/dist/composables/useRsConfig.js +2 -2
  75. package/dist/composables/useRsI18n.d.ts +1 -1
  76. package/dist/composables/useRsI18n.js +3 -3
  77. package/dist/index.d.ts +5 -1
  78. package/dist/index.js +3 -0
  79. package/dist/locale/interpolate.js +15 -3
  80. package/dist/locale/messages.d.ts +2 -0
  81. package/dist/locale/messages.js +3 -1
  82. package/dist/locale/registry-public.d.ts +1 -0
  83. package/dist/locale/resolve-host.d.ts +7 -0
  84. package/dist/locale/resolve-host.js +46 -0
  85. package/dist/locale/types.d.ts +2 -0
  86. package/dist/locale/types.js +2 -0
  87. package/package.json +10 -8
@@ -1,17 +1,17 @@
1
1
 
2
- .rs-dynamic-tags-field[data-v-6ce33b85] {
2
+ .rs-dynamic-tags-field[data-v-a441b090] {
3
3
  display: flex;
4
4
  flex-direction: column;
5
5
  width: 100%;
6
6
  min-width: 0;
7
7
  }
8
- .rs-dynamic-tags-field__error[data-v-6ce33b85] {
8
+ .rs-dynamic-tags-field__error[data-v-a441b090] {
9
9
  margin: 0.25rem 0 0;
10
10
  font-size: var(--rs-font-size-xs);
11
11
  line-height: var(--rs-line-height-tight);
12
12
  color: var(--rs-danger);
13
13
  }
14
- .rs-dynamic-tags[data-v-6ce33b85] {
14
+ .rs-dynamic-tags[data-v-a441b090] {
15
15
  --rs-dynamic-tags-chip-height: 1.5rem;
16
16
  display: flex;
17
17
  flex-wrap: wrap;
@@ -37,43 +37,43 @@
37
37
  box-shadow var(--rs-transition-fast),
38
38
  background-color var(--rs-transition-fast);
39
39
  }
40
- .rs-dynamic-tags[data-v-6ce33b85]:hover:not(.rs-dynamic-tags--disabled) {
40
+ .rs-dynamic-tags[data-v-a441b090]:hover:not(.rs-dynamic-tags--disabled) {
41
41
  border-color: var(
42
42
  --rs-dynamic-tags-border-hover,
43
43
  var(--rs-input-border-hover, var(--rs-border))
44
44
  );
45
45
  }
46
- .rs-dynamic-tags--ssm[data-v-6ce33b85] {
46
+ .rs-dynamic-tags--ssm[data-v-a441b090] {
47
47
  --rs-dynamic-tags-chip-height: 1.125rem;
48
48
  }
49
- .rs-dynamic-tags--sm[data-v-6ce33b85] {
49
+ .rs-dynamic-tags--sm[data-v-a441b090] {
50
50
  --rs-dynamic-tags-chip-height: 1.25rem;
51
51
  }
52
- .rs-dynamic-tags--md[data-v-6ce33b85] {
52
+ .rs-dynamic-tags--md[data-v-a441b090] {
53
53
  --rs-dynamic-tags-chip-height: 1.5rem;
54
54
  }
55
- .rs-dynamic-tags--lg[data-v-6ce33b85] {
55
+ .rs-dynamic-tags--lg[data-v-a441b090] {
56
56
  --rs-dynamic-tags-chip-height: 1.75rem;
57
57
  }
58
- .rs-dynamic-tags--editing[data-v-6ce33b85]:not(.rs-dynamic-tags--disabled),
59
- .rs-dynamic-tags[data-v-6ce33b85]:focus-within:not(.rs-dynamic-tags--disabled) {
58
+ .rs-dynamic-tags--editing[data-v-a441b090]:not(.rs-dynamic-tags--disabled),
59
+ .rs-dynamic-tags[data-v-a441b090]:focus-within:not(.rs-dynamic-tags--disabled) {
60
60
  border-color: var(--rs-focus-border, var(--rs-primary));
61
61
  box-shadow:
62
62
  var(--rs-dynamic-tags-shadow, var(--rs-input-shadow, none)),
63
63
  0 0 0 var(--rs-focus-ring-width, 2px) var(--rs-focus-ring);
64
64
  }
65
- .rs-dynamic-tags--feedback[data-v-6ce33b85],
66
- .rs-dynamic-tags--invalid[data-v-6ce33b85] {
65
+ .rs-dynamic-tags--feedback[data-v-a441b090],
66
+ .rs-dynamic-tags--invalid[data-v-a441b090] {
67
67
  border-color: var(--rs-danger);
68
68
  }
69
- .rs-dynamic-tags--feedback[data-v-6ce33b85] {
70
- animation: rs-dynamic-tags-shake-6ce33b85 0.45s ease;
69
+ .rs-dynamic-tags--feedback[data-v-a441b090] {
70
+ animation: rs-dynamic-tags-shake-a441b090 0.45s ease;
71
71
  }
72
- .rs-dynamic-tags--disabled[data-v-6ce33b85] {
72
+ .rs-dynamic-tags--disabled[data-v-a441b090] {
73
73
  opacity: 0.55;
74
74
  cursor: not-allowed;
75
75
  }
76
- .rs-dynamic-tags__input[data-v-6ce33b85] {
76
+ .rs-dynamic-tags__input[data-v-a441b090] {
77
77
  flex: 1 1 6rem;
78
78
  min-width: 4rem;
79
79
  width: 0;
@@ -91,15 +91,15 @@
91
91
  box-shadow: none;
92
92
  appearance: none;
93
93
  }
94
- .rs-dynamic-tags--ssm .rs-dynamic-tags__input[data-v-6ce33b85],
95
- .rs-dynamic-tags--sm .rs-dynamic-tags__input[data-v-6ce33b85] {
94
+ .rs-dynamic-tags--ssm .rs-dynamic-tags__input[data-v-a441b090],
95
+ .rs-dynamic-tags--sm .rs-dynamic-tags__input[data-v-a441b090] {
96
96
  font-size: var(--rs-font-size-xs);
97
97
  }
98
- .rs-dynamic-tags__input[data-v-6ce33b85]::placeholder {
98
+ .rs-dynamic-tags__input[data-v-a441b090]::placeholder {
99
99
  color: var(--rs-placeholder);
100
100
  line-height: var(--rs-dynamic-tags-chip-height);
101
101
  }
102
- .rs-dynamic-tags__trigger[data-v-6ce33b85] {
102
+ .rs-dynamic-tags__trigger[data-v-a441b090] {
103
103
  display: inline-flex;
104
104
  flex-shrink: 0;
105
105
  align-items: center;
@@ -120,15 +120,15 @@
120
120
  border-color var(--rs-transition-fast),
121
121
  background-color var(--rs-transition-fast);
122
122
  }
123
- .rs-dynamic-tags__trigger[data-v-6ce33b85]:hover {
123
+ .rs-dynamic-tags__trigger[data-v-a441b090]:hover {
124
124
  color: var(--rs-primary);
125
125
  border-color: var(--rs-primary);
126
126
  background: color-mix(in srgb, var(--rs-primary) 8%, transparent);
127
127
  }
128
- .rs-dynamic-tags__trigger[data-v-6ce33b85]:focus-visible {
128
+ .rs-dynamic-tags__trigger[data-v-a441b090]:focus-visible {
129
129
  box-shadow: 0 0 0 var(--rs-focus-ring-width, 2px) var(--rs-focus-ring);
130
130
  }
131
- @keyframes rs-dynamic-tags-shake-6ce33b85 {
131
+ @keyframes rs-dynamic-tags-shake-a441b090 {
132
132
  0%,
133
133
  100% {
134
134
  transform: translateX(0);
@@ -1,6 +1,6 @@
1
1
  import type { RsComponentSize, RsRadius } from '../../../theme/types';
2
2
  import { type RsFormRuleTrigger } from '../../form/src/form-rules';
3
- import type { RsTagVariant } from '../../tag/src/RsTag.js';
3
+ import type { RsTagVariant } from '../../tag';
4
4
  export type RsDynamicTagsInputMode = 'trigger' | 'always';
5
5
  export type RsDynamicTagsRejectReason = 'duplicate' | 'max';
6
6
  type __VLS_Props = {
@@ -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-6ce33b85"]]);
6
+ var RsDynamicTags_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsDynamicTags_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-a441b090"]]);
7
7
  //#endregion
8
8
  export { RsDynamicTags_default as default };
@@ -1,5 +1,5 @@
1
1
  import { interpolateRsMessage } from "../../../locale/interpolate.js";
2
- import "../../../locale/types.js";
2
+ import { resolveHostLocale } from "../../../locale/resolve-host.js";
3
3
  import { createTranslator } from "../../../composables/useRsI18n.js";
4
4
  import { getInputRuleMessage, validateInputRule } from "../../input/src/input-rules.js";
5
5
  //#region src/components/form/src/form-rules.ts
@@ -106,7 +106,7 @@ async function evaluateFormRule(value, rule, tr, options) {
106
106
  * 按顺序执行字段规则,首条失败即返回。
107
107
  */
108
108
  async function runFormFieldRules(value, rules, options) {
109
- const tr = options?.t ?? createTranslator("zh-CN");
109
+ const tr = options?.t ?? createTranslator(resolveHostLocale());
110
110
  const trigger = options?.trigger;
111
111
  for (const rule of rules) {
112
112
  if (!matchFormRuleTrigger(rule, trigger)) continue;
@@ -1,14 +1,19 @@
1
1
 
2
- .rs-icon[data-v-ba79ea00] {
2
+ .rs-icon[data-v-260b0681] {
3
3
  display: inline-block;
4
4
  flex-shrink: 0;
5
5
  vertical-align: middle;
6
6
  }
7
- .rs-icon--spin[data-v-ba79ea00] {
8
- animation: rs-icon-spin-ba79ea00 0.8s linear infinite;
7
+ .rs-icon--spin[data-v-260b0681] {
8
+ animation: rs-icon-spin-260b0681 0.8s linear infinite;
9
9
  }
10
- @keyframes rs-icon-spin-ba79ea00 {
10
+ @keyframes rs-icon-spin-260b0681 {
11
11
  to {
12
12
  transform: rotate(360deg);
13
13
  }
14
14
  }
15
+ @media (prefers-reduced-motion: reduce) {
16
+ .rs-icon--spin[data-v-260b0681] {
17
+ animation: none;
18
+ }
19
+ }
@@ -1,8 +1,9 @@
1
1
  import type { RsComponentSize } from '../../../theme/types';
2
+ import { type RsIconFlip } from './icon-utils';
2
3
  type __VLS_Props = {
3
- /** Lucide 图标名(kebab-case,如 `house`、`trash-2`) */
4
+ /** Lucide kebab-case 名称(如 `house`、`trash-2`),或内置品牌 mark */
4
5
  name: string;
5
- /** 数字 px、CSS 长度或 sm / md / lg 预设 */
6
+ /** 数字 px、CSS 长度,或与控件同一套 ssm / sm / md / lg */
6
7
  size?: number | string | RsComponentSize;
7
8
  /** 无障碍名称;有值时作为语义图标,无值时为装饰性图标 */
8
9
  label?: string;
@@ -10,7 +11,7 @@ type __VLS_Props = {
10
11
  /** 覆盖颜色,默认继承 currentColor */
11
12
  color?: string;
12
13
  /** 水平 / 垂直 / 双向翻转 */
13
- flip?: 'horizontal' | 'vertical' | 'both';
14
+ flip?: RsIconFlip;
14
15
  /** 旋转角度(度),与 spin 不宜同时使用 */
15
16
  rotate?: number;
16
17
  /** 旋转动画,适合 loader 等加载态 */
@@ -1,8 +1,10 @@
1
1
  import { resolveLucideIcon } from "../../../icons/lucide.js";
2
2
  import { isRsBrandIconName } from "../../../icons/brand.js";
3
+ import { buildRsIconStyle, resolveRsIconPixelSize } from "./icon-utils.js";
3
4
  import { computed, createBlock, createCommentVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, resolveDynamicComponent } from "vue";
4
5
  //#region src/components/icon/src/RsIcon.vue?vue&type=script&setup=true&lang.ts
5
6
  var RsIcon_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
7
+ name: "RsIcon",
6
8
  __name: "RsIcon",
7
9
  props: {
8
10
  name: {},
@@ -15,41 +17,16 @@ var RsIcon_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCom
15
17
  spin: { type: Boolean }
16
18
  },
17
19
  setup(__props) {
18
- const SIZE_PRESET = {
19
- ssm: 12,
20
- sm: 14,
21
- md: 16,
22
- lg: 20
23
- };
24
20
  const props = __props;
25
21
  const iconComponent = computed(() => resolveLucideIcon(props.name));
26
- const usesCustomSize = computed(() => {
27
- const { size } = props;
28
- return typeof size === "string" && !(size in SIZE_PRESET) && !/^\d+$/.test(size);
29
- });
30
- const lucideSize = computed(() => {
31
- if (usesCustomSize.value) return void 0;
32
- const { size } = props;
33
- if (typeof size === "number") return size;
34
- if (size in SIZE_PRESET) return SIZE_PRESET[size];
35
- return Number.parseInt(String(size), 10) || SIZE_PRESET.md;
36
- });
22
+ const lucideSize = computed(() => resolveRsIconPixelSize(props.size));
37
23
  const isBrand = computed(() => isRsBrandIconName(props.name));
38
- const iconStyle = computed(() => {
39
- const style = {};
40
- if (props.color) style.color = props.color;
41
- const transforms = [];
42
- if (props.flip === "horizontal") transforms.push("scaleX(-1)");
43
- else if (props.flip === "vertical") transforms.push("scaleY(-1)");
44
- else if (props.flip === "both") transforms.push("scale(-1)");
45
- if (props.rotate) transforms.push(`rotate(${props.rotate}deg)`);
46
- if (transforms.length) style.transform = transforms.join(" ");
47
- if (usesCustomSize.value && typeof props.size === "string") {
48
- style.width = props.size;
49
- style.height = props.size;
50
- }
51
- return Object.keys(style).length ? style : void 0;
52
- });
24
+ const iconStyle = computed(() => buildRsIconStyle({
25
+ color: props.color,
26
+ flip: props.flip,
27
+ rotate: props.rotate,
28
+ size: props.size
29
+ }));
53
30
  const isSemantic = computed(() => Boolean(props.label));
54
31
  return (_ctx, _cache) => {
55
32
  return iconComponent.value ? (openBlock(), createBlock(resolveDynamicComponent(iconComponent.value), {
@@ -3,6 +3,6 @@ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_exp
3
3
  import RsIcon_vue_vue_type_script_setup_true_lang_default from "./RsIcon.impl.js";
4
4
 
5
5
  //#region src/components/icon/src/RsIcon.vue
6
- var RsIcon_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsIcon_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-ba79ea00"]]);
6
+ var RsIcon_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsIcon_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-260b0681"]]);
7
7
  //#endregion
8
8
  export { RsIcon_default as default };
@@ -0,0 +1,17 @@
1
+ import { type RsComponentSize } from '../../../theme/types';
2
+ export type RsIconFlip = 'horizontal' | 'vertical' | 'both';
3
+ /** 数字 px、CSS 长度,或 ssm / sm / md / lg 档位字符串。 */
4
+ export type RsIconSize = number | string;
5
+ /** 与控件档位同一套边长(ssm 12 / sm 14 / md 16 / lg 18)。 */
6
+ export declare function isRsIconSizePreset(size: unknown): size is RsComponentSize;
7
+ /** CSS 长度(如 `1.5rem`)不走 Lucide 的 size 数字。 */
8
+ export declare function rsIconUsesCssSize(size: RsIconSize | undefined): boolean;
9
+ /** 解析成 Lucide / 自定义 mark 的像素边长;CSS 长度返回 undefined。 */
10
+ export declare function resolveRsIconPixelSize(size: RsIconSize | undefined): number | undefined;
11
+ export declare function buildRsIconTransform(flip?: RsIconFlip, rotate?: number): string | undefined;
12
+ export declare function buildRsIconStyle(options: {
13
+ color?: string;
14
+ flip?: RsIconFlip;
15
+ rotate?: number;
16
+ size?: RsIconSize;
17
+ }): Record<string, string> | undefined;
@@ -0,0 +1,39 @@
1
+ import { RS_COMPONENT_SIZE_ICON_PX } from "../../../theme/types.js";
2
+ //#region src/components/icon/src/icon-utils.ts
3
+ /** 与控件档位同一套边长(ssm 12 / sm 14 / md 16 / lg 18)。 */
4
+ function isRsIconSizePreset(size) {
5
+ return typeof size === "string" && size in RS_COMPONENT_SIZE_ICON_PX;
6
+ }
7
+ /** CSS 长度(如 `1.5rem`)不走 Lucide 的 size 数字。 */
8
+ function rsIconUsesCssSize(size) {
9
+ return typeof size === "string" && !isRsIconSizePreset(size) && !/^\d+$/.test(size);
10
+ }
11
+ /** 解析成 Lucide / 自定义 mark 的像素边长;CSS 长度返回 undefined。 */
12
+ function resolveRsIconPixelSize(size) {
13
+ if (size == null) return RS_COMPONENT_SIZE_ICON_PX.md;
14
+ if (rsIconUsesCssSize(size)) return void 0;
15
+ if (typeof size === "number" && Number.isFinite(size)) return size;
16
+ if (isRsIconSizePreset(size)) return RS_COMPONENT_SIZE_ICON_PX[size];
17
+ return Number.parseInt(String(size), 10) || RS_COMPONENT_SIZE_ICON_PX.md;
18
+ }
19
+ function buildRsIconTransform(flip, rotate) {
20
+ const transforms = [];
21
+ if (flip === "horizontal") transforms.push("scaleX(-1)");
22
+ else if (flip === "vertical") transforms.push("scaleY(-1)");
23
+ else if (flip === "both") transforms.push("scale(-1)");
24
+ if (rotate) transforms.push(`rotate(${rotate}deg)`);
25
+ return transforms.length ? transforms.join(" ") : void 0;
26
+ }
27
+ function buildRsIconStyle(options) {
28
+ const style = {};
29
+ if (options.color) style.color = options.color;
30
+ const transform = buildRsIconTransform(options.flip, options.rotate);
31
+ if (transform) style.transform = transform;
32
+ if (rsIconUsesCssSize(options.size) && typeof options.size === "string") {
33
+ style.width = options.size;
34
+ style.height = options.size;
35
+ }
36
+ return Object.keys(style).length ? style : void 0;
37
+ }
38
+ //#endregion
39
+ export { buildRsIconStyle, buildRsIconTransform, isRsIconSizePreset, resolveRsIconPixelSize, rsIconUsesCssSize };
@@ -1,4 +1,4 @@
1
- import "../../../locale/types.js";
1
+ import { resolveHostLocale } from "../../../locale/resolve-host.js";
2
2
  import { createTranslator } from "../../../composables/useRsI18n.js";
3
3
  //#region src/components/input/src/input-rules.ts
4
4
  var inputRuleMessageKeys = {
@@ -29,10 +29,10 @@ function validateInputRule(value, rule) {
29
29
  }
30
30
  function getInputRuleMessage(rule, t) {
31
31
  const key = inputRuleMessageKeys[rule];
32
- return (t ?? createTranslator("zh-CN"))(key);
32
+ return (t ?? createTranslator(resolveHostLocale()))(key);
33
33
  }
34
34
  function runInputValidation(value, options, t) {
35
- const tr = t ?? createTranslator("zh-CN");
35
+ const tr = t ?? createTranslator(resolveHostLocale());
36
36
  if (options.required && value.trim() === "") return {
37
37
  valid: false,
38
38
  message: tr("input.required")
@@ -1 +1,2 @@
1
1
  export { default as RsLink } from './src/RsLink.js';
2
+ export type { RsLinkTone, RsLinkUnderline } from './src/link-utils';
@@ -1,45 +1,86 @@
1
1
 
2
- .rs-link {
3
- color: var(--rs-primary);
4
- font-size: var(--rs-font-size-sm);
2
+ .rs-link[data-v-78d8e4b3] {
3
+ display: inline;
4
+ color: var(--rs-link-tone, var(--rs-primary));
5
+ font-size: inherit;
5
6
  font-weight: var(--rs-font-weight-medium);
6
7
  line-height: var(--rs-line-height-tight);
7
8
  text-underline-offset: 0.18em;
8
9
  text-decoration-thickness: 1px;
10
+ cursor: pointer;
9
11
  transition:
10
12
  color var(--rs-transition-fast),
11
13
  text-decoration-color var(--rs-transition-fast);
12
14
  }
13
- .rs-link:visited {
14
- color: var(--rs-primary);
15
+ .rs-link--has-icon[data-v-78d8e4b3] {
16
+ display: inline-flex;
17
+ align-items: center;
18
+ gap: 0.3em;
15
19
  }
16
- .rs-link:hover {
17
- color: var(--rs-primary-hover);
20
+ .rs-link[data-v-78d8e4b3]:visited {
21
+ color: var(--rs-link-tone, var(--rs-primary));
18
22
  }
19
- .rs-link:active {
20
- color: var(--rs-primary-hover);
23
+ .rs-link[data-v-78d8e4b3]:hover,
24
+ .rs-link[data-v-78d8e4b3]:active {
25
+ color: var(--rs-link-tone-hover, var(--rs-primary-hover));
21
26
  }
22
- .rs-link:focus-visible {
27
+ .rs-link[data-v-78d8e4b3]:focus-visible {
23
28
  outline: none;
24
29
  border-radius: var(--rs-radius-xs);
25
30
  box-shadow: 0 0 0 var(--rs-focus-ring-width, 2px) var(--rs-focus-ring);
26
31
  }
27
- .rs-link--underline-always {
32
+ .rs-link--underline-always[data-v-78d8e4b3] {
28
33
  text-decoration: underline;
29
34
  }
30
- .rs-link--underline-hover {
35
+ .rs-link--underline-hover[data-v-78d8e4b3] {
31
36
  text-decoration: none;
32
37
  }
33
- .rs-link--underline-hover:hover,
34
- .rs-link--underline-hover:focus-visible {
38
+ .rs-link--underline-hover[data-v-78d8e4b3]:hover,
39
+ .rs-link--underline-hover[data-v-78d8e4b3]:focus-visible {
35
40
  text-decoration: underline;
36
41
  }
37
- .rs-link--underline-none {
42
+ .rs-link--underline-none[data-v-78d8e4b3],
43
+ .rs-link--underline-none[data-v-78d8e4b3]:hover,
44
+ .rs-link--underline-none[data-v-78d8e4b3]:focus-visible {
38
45
  text-decoration: none;
39
46
  }
40
- .rs-link--disabled {
47
+ .rs-link--tone-primary[data-v-78d8e4b3] {
48
+ --rs-link-tone: var(--rs-primary);
49
+ --rs-link-tone-hover: var(--rs-primary-hover);
50
+ }
51
+ .rs-link--tone-neutral[data-v-78d8e4b3] {
52
+ --rs-link-tone: var(--rs-text);
53
+ --rs-link-tone-hover: var(--rs-primary);
54
+ }
55
+ .rs-link--tone-success[data-v-78d8e4b3] {
56
+ --rs-link-tone: var(--rs-success, #18a058);
57
+ --rs-link-tone-hover: var(--rs-success, #18a058);
58
+ }
59
+ .rs-link--tone-warning[data-v-78d8e4b3] {
60
+ --rs-link-tone: var(--rs-warning, #f0a020);
61
+ --rs-link-tone-hover: var(--rs-warning, #f0a020);
62
+ }
63
+ .rs-link--tone-danger[data-v-78d8e4b3] {
64
+ --rs-link-tone: var(--rs-danger);
65
+ --rs-link-tone-hover: var(--rs-danger);
66
+ }
67
+ .rs-link--tone-info[data-v-78d8e4b3] {
68
+ --rs-link-tone: var(--rs-info, #2080f0);
69
+ --rs-link-tone-hover: var(--rs-info, #2080f0);
70
+ }
71
+ .rs-link__icon[data-v-78d8e4b3] {
72
+ color: inherit;
73
+ }
74
+ .rs-link--disabled[data-v-78d8e4b3],
75
+ .rs-link--disabled[data-v-78d8e4b3]:visited,
76
+ .rs-link--disabled[data-v-78d8e4b3]:hover,
77
+ .rs-link--disabled[data-v-78d8e4b3]:active {
41
78
  color: var(--rs-muted);
42
79
  cursor: not-allowed;
43
80
  text-decoration: none;
44
- pointer-events: auto;
81
+ }
82
+ @media (prefers-reduced-motion: reduce) {
83
+ .rs-link[data-v-78d8e4b3] {
84
+ transition: none;
85
+ }
45
86
  }
@@ -1,19 +1,27 @@
1
+ import { type RsLinkTone, type RsLinkUnderline } from './link-utils';
2
+ export type { RsLinkTone, RsLinkUnderline };
1
3
  type __VLS_Props = {
2
4
  href: string;
3
5
  target?: '_self' | '_blank' | '_parent' | '_top' | (string & {});
4
6
  rel?: string;
5
7
  disabled?: boolean;
6
- underline?: 'always' | 'hover' | 'none';
8
+ underline?: RsLinkUnderline;
9
+ /** 语义色。默认 primary。不要用业务 CSS 改颜色。 */
10
+ tone?: RsLinkTone;
11
+ /** 前缀图标,Lucide kebab-case。装饰性,名称走默认插槽。 */
12
+ icon?: string;
7
13
  };
8
- declare var __VLS_10: {};
14
+ declare var __VLS_6: {};
9
15
  type __VLS_Slots = {} & {
10
- default?: (props: typeof __VLS_10) => any;
16
+ default?: (props: typeof __VLS_6) => any;
11
17
  };
12
18
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
19
+ tone: RsLinkTone;
13
20
  disabled: boolean;
21
+ icon: string;
14
22
  target: "_self" | "_blank" | "_parent" | "_top" | (string & {});
15
23
  rel: string;
16
- underline: "always" | "hover" | "none";
24
+ underline: RsLinkUnderline;
17
25
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
26
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
19
27
  declare const _default: typeof __VLS_export;
@@ -1,7 +1,16 @@
1
- import { Primitive } from "../../_shared/src/reka.js";
2
- import { computed, createBlock, defineComponent, normalizeClass, openBlock, renderSlot, unref, withCtx } from "vue";
1
+ import RsIcon_default from "../../icon/src/RsIcon.js";
2
+ import { mergeRsLinkRel, resolveRsLinkTone } from "./link-utils.js";
3
+ import { computed, createBlock, createCommentVNode, createElementBlock, defineComponent, normalizeClass, openBlock, renderSlot } from "vue";
3
4
  //#region src/components/link/src/RsLink.vue?vue&type=script&setup=true&lang.ts
5
+ var _hoisted_1 = [
6
+ "href",
7
+ "target",
8
+ "rel",
9
+ "aria-disabled",
10
+ "tabindex"
11
+ ];
4
12
  var RsLink_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
13
+ name: "RsLink",
5
14
  __name: "RsLink",
6
15
  props: {
7
16
  href: {},
@@ -11,47 +20,39 @@ var RsLink_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCom
11
20
  type: Boolean,
12
21
  default: false
13
22
  },
14
- underline: { default: "hover" }
23
+ underline: { default: "hover" },
24
+ tone: { default: void 0 },
25
+ icon: { default: void 0 }
15
26
  },
16
27
  setup(__props) {
17
28
  const props = __props;
18
- const mergedRel = computed(() => {
19
- const relParts = (props.rel ?? "").split(/\s+/).map((item) => item.trim()).filter(Boolean);
20
- if (props.target === "_blank") {
21
- if (!relParts.includes("noopener")) relParts.push("noopener");
22
- if (!relParts.includes("noreferrer")) relParts.push("noreferrer");
23
- }
24
- return relParts.length > 0 ? relParts.join(" ") : void 0;
25
- });
29
+ const resolvedTone = computed(() => resolveRsLinkTone(props.tone));
30
+ const mergedRel = computed(() => mergeRsLinkRel(props.rel, props.target));
26
31
  function onClick(event) {
27
32
  if (!props.disabled) return;
28
33
  event.preventDefault();
29
34
  event.stopPropagation();
30
35
  }
31
36
  return (_ctx, _cache) => {
32
- return openBlock(), createBlock(unref(Primitive), {
33
- as: "a",
37
+ return openBlock(), createElementBlock("a", {
34
38
  href: __props.disabled ? void 0 : __props.href,
35
39
  target: __props.disabled ? void 0 : __props.target,
36
40
  rel: __props.disabled ? void 0 : mergedRel.value,
37
41
  class: normalizeClass(["rs-link", {
38
42
  "rs-link--disabled": __props.disabled,
39
- [`rs-link--underline-${__props.underline}`]: true
43
+ "rs-link--has-icon": Boolean(__props.icon),
44
+ [`rs-link--underline-${__props.underline}`]: true,
45
+ [`rs-link--tone-${resolvedTone.value}`]: true
40
46
  }]),
41
47
  "aria-disabled": __props.disabled ? "true" : void 0,
42
48
  tabindex: __props.disabled ? -1 : void 0,
43
49
  onClick
44
- }, {
45
- default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
46
- _: 3
47
- }, 8, [
48
- "href",
49
- "target",
50
- "rel",
51
- "class",
52
- "aria-disabled",
53
- "tabindex"
54
- ]);
50
+ }, [__props.icon ? (openBlock(), createBlock(RsIcon_default, {
51
+ key: 0,
52
+ class: "rs-link__icon",
53
+ name: __props.icon,
54
+ size: "1em"
55
+ }, null, 8, ["name"])) : createCommentVNode("", true), renderSlot(_ctx.$slots, "default", {}, void 0, true)], 10, _hoisted_1);
55
56
  };
56
57
  }
57
58
  });
@@ -1,7 +1,8 @@
1
1
  import './RsLink.css'
2
+ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_export-helper.js";
2
3
  import RsLink_vue_vue_type_script_setup_true_lang_default from "./RsLink.impl.js";
3
4
 
4
5
  //#region src/components/link/src/RsLink.vue
5
- var RsLink_default = RsLink_vue_vue_type_script_setup_true_lang_default;
6
+ var RsLink_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsLink_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-78d8e4b3"]]);
6
7
  //#endregion
7
8
  export { RsLink_default as default };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * RsLink 语义色(色相)。链接没有形态轴,默认 primary。
3
+ * 操作按钮请用 RsButton variant="link",不要用本组件冒充按钮。
4
+ */
5
+ export type RsLinkTone = 'primary' | 'neutral' | 'success' | 'warning' | 'danger' | 'info';
6
+ export type RsLinkUnderline = 'always' | 'hover' | 'none';
7
+ export declare function resolveRsLinkTone(tone?: RsLinkTone): RsLinkTone;
8
+ /** `_blank` 时补上 noopener / noreferrer,并保留调用方已有 rel。 */
9
+ export declare function mergeRsLinkRel(rel: string | undefined, target: string | undefined): string | undefined;
@@ -0,0 +1,15 @@
1
+ //#region src/components/link/src/link-utils.ts
2
+ function resolveRsLinkTone(tone) {
3
+ return tone ?? "primary";
4
+ }
5
+ /** `_blank` 时补上 noopener / noreferrer,并保留调用方已有 rel。 */
6
+ function mergeRsLinkRel(rel, target) {
7
+ const parts = (rel ?? "").split(/\s+/).map((item) => item.trim()).filter(Boolean);
8
+ if (target === "_blank") {
9
+ if (!parts.includes("noopener")) parts.push("noopener");
10
+ if (!parts.includes("noreferrer")) parts.push("noreferrer");
11
+ }
12
+ return parts.length > 0 ? parts.join(" ") : void 0;
13
+ }
14
+ //#endregion
15
+ export { mergeRsLinkRel, resolveRsLinkTone };
@@ -12,12 +12,12 @@ type __VLS_Props = {
12
12
  };
13
13
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
14
14
  variant: RsLoadingVariant;
15
+ overlay: boolean;
15
16
  size: RsLoadingSize;
16
17
  tone: RsLoadingTone;
17
18
  loading: boolean;
18
- block: boolean;
19
19
  showLabel: boolean;
20
- overlay: boolean;
20
+ block: boolean;
21
21
  skeletonLines: number;
22
22
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
23
23
  declare const _default: typeof __VLS_export;
@@ -1,6 +1,6 @@
1
+ import { CollapsibleContent, CollapsibleRoot, CollapsibleTrigger, PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from "../../_shared/src/reka.js";
1
2
  import { useRsI18n } from "../../../composables/useRsI18n.js";
2
3
  import RsIcon_default from "../../icon/src/RsIcon.js";
3
- import { CollapsibleContent, CollapsibleRoot, CollapsibleTrigger, PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from "../../_shared/src/reka.js";
4
4
  import { menuItemContainsKey } from "./menu-utils.js";
5
5
  import RsMenuItems_default from "./RsMenuItems.js";
6
6
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, ref, renderList, toDisplayString, unref, withCtx } from "vue";
@@ -1,5 +1,5 @@
1
- import { useResolvedRsComponentSize } from "../../_shared/src/resolve-size.js";
2
1
  import { RadioGroupRoot } from "../../_shared/src/reka.js";
2
+ import { useResolvedRsComponentSize } from "../../_shared/src/resolve-size.js";
3
3
  import { RS_RADIO_GROUP_KEY } from "./radio-utils.js";
4
4
  import { computed, createBlock, defineComponent, mergeModels, normalizeClass, openBlock, provide, renderSlot, unref, useModel, withCtx } from "vue";
5
5
  //#region src/components/radio/src/RsRadio.vue?vue&type=script&setup=true&lang.ts
@@ -1,5 +1,5 @@
1
- import { useResolvedRsComponentSize } from "../../_shared/src/resolve-size.js";
2
1
  import { RadioGroupIndicator, RadioGroupItem } from "../../_shared/src/reka.js";
2
+ import { useResolvedRsComponentSize } from "../../_shared/src/resolve-size.js";
3
3
  import { RS_RADIO_GROUP_KEY } from "./radio-utils.js";
4
4
  import { computed, createCommentVNode, createElementBlock, createVNode, defineComponent, inject, normalizeClass, openBlock, renderSlot, unref, useId, withCtx } from "vue";
5
5
  //#region src/components/radio/src/RsRadioItem.vue?vue&type=script&setup=true&lang.ts