niuma-ui 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/components/RsButton.css +119 -61
  3. package/dist/components/RsButton.d.ts +3 -3
  4. package/dist/components/RsButton.impl.js +4 -12
  5. package/dist/components/RsButton.js +1 -1
  6. package/dist/components/RsDialog.css +1 -0
  7. package/dist/components/RsDialog.d.ts +5 -0
  8. package/dist/components/RsDialog.impl.js +4 -0
  9. package/dist/components/RsDrawer.css +1 -0
  10. package/dist/components/RsFieldset.css +92 -0
  11. package/dist/components/RsFieldset.d.ts +61 -0
  12. package/dist/components/RsFieldset.impl.js +78 -0
  13. package/dist/components/RsFieldset.js +8 -0
  14. package/dist/components/RsFormItem.css +19 -19
  15. package/dist/components/RsFormItem.d.ts +6 -4
  16. package/dist/components/RsFormItem.impl.js +12 -2
  17. package/dist/components/RsFormItem.js +1 -1
  18. package/dist/components/RsInput.css +78 -69
  19. package/dist/components/RsInput.js +1 -1
  20. package/dist/components/RsLog.css +198 -0
  21. package/dist/components/RsLog.d.ts +126 -0
  22. package/dist/components/RsLog.impl.js +619 -0
  23. package/dist/components/RsLog.js +8 -0
  24. package/dist/components/RsTable.impl.js +2 -1
  25. package/dist/components/RsTextarea.css +126 -0
  26. package/dist/components/RsTextarea.d.ts +114 -0
  27. package/dist/components/RsTextarea.impl.js +385 -0
  28. package/dist/components/RsTextarea.js +8 -0
  29. package/dist/components/RsTooltip.css +4 -3
  30. package/dist/components/RsTooltip.d.ts +2 -0
  31. package/dist/components/RsTooltip.impl.js +5 -2
  32. package/dist/components/RsVirtualList.css +6 -6
  33. package/dist/components/RsVirtualList.d.ts +1 -1
  34. package/dist/components/RsVirtualList.impl.js +9 -4
  35. package/dist/components/RsVirtualList.js +1 -1
  36. package/dist/components/button-utils.d.ts +19 -10
  37. package/dist/components/button-utils.js +22 -7
  38. package/dist/components/dialog-window.d.ts +2 -0
  39. package/dist/components/dialog-window.js +2 -1
  40. package/dist/components/fieldset-utils.d.ts +29 -0
  41. package/dist/components/fieldset-utils.js +12 -0
  42. package/dist/components/log-utils.d.ts +105 -0
  43. package/dist/components/log-utils.js +354 -0
  44. package/dist/components/table/rs-table-props.d.ts +8 -0
  45. package/dist/components/table/rs-table-props.js +1 -0
  46. package/dist/components/table/rs-table.css +7 -0
  47. package/dist/index.d.ts +10 -2
  48. package/dist/index.js +24 -0
  49. package/dist/lib/rs-dayjs.js +1 -1
  50. package/dist/locale/messages.js +42 -0
  51. package/dist/styles.css +37 -0
  52. package/dist/vite-plugins/niuma-ui-host.d.ts +8 -0
  53. package/dist/vite-plugins/niuma-ui-host.js +47 -9
  54. package/package.json +1 -1
@@ -0,0 +1,126 @@
1
+
2
+ .rs-textarea[data-v-f75ef1a0] {
3
+ width: 100%;
4
+ }
5
+ .rs-textarea__shell[data-v-f75ef1a0] {
6
+ position: relative;
7
+ box-sizing: border-box;
8
+ width: 100%;
9
+ border: 1px solid var(--rs-input-border, var(--rs-border));
10
+ border-radius: var(--rs-input-radius, var(--rs-radius-sm));
11
+ background: var(--rs-input-bg);
12
+ box-shadow: var(--rs-input-shadow, none);
13
+ transition:
14
+ border-color var(--rs-transition-fast),
15
+ box-shadow var(--rs-transition-fast);
16
+ }
17
+ .rs-textarea__shell[data-v-f75ef1a0]:hover:not(.is-disabled):not(.is-readonly):not(:focus-within) {
18
+ border-color: var(--rs-input-border-hover, var(--rs-border));
19
+ }
20
+ .rs-textarea__shell[data-v-f75ef1a0]:focus-within {
21
+ border-color: var(--rs-focus-border, var(--rs-primary));
22
+ box-shadow:
23
+ var(--rs-input-shadow, none),
24
+ 0 0 0 var(--rs-focus-ring-width, 2px) var(--rs-focus-ring);
25
+ }
26
+ .rs-textarea__shell.is-invalid[data-v-f75ef1a0] {
27
+ border-color: var(--rs-danger);
28
+ }
29
+ .rs-textarea__shell.is-invalid[data-v-f75ef1a0]:focus-within {
30
+ box-shadow:
31
+ var(--rs-input-shadow, none),
32
+ 0 0 0 var(--rs-focus-ring-width, 2px) color-mix(in srgb, var(--rs-danger) 14%, transparent);
33
+ }
34
+ .rs-textarea__shell.is-disabled[data-v-f75ef1a0] {
35
+ opacity: 0.38;
36
+ cursor: not-allowed;
37
+ background: var(--rs-surface-hover);
38
+ }
39
+ .rs-textarea__shell.is-readonly[data-v-f75ef1a0] {
40
+ background: var(--rs-surface-hover);
41
+ }
42
+ .rs-textarea__control[data-v-f75ef1a0] {
43
+ display: block;
44
+ box-sizing: border-box;
45
+ width: 100%;
46
+ min-height: 4.5rem;
47
+ padding: 0.55rem 0.75rem;
48
+ border: 0;
49
+ outline: none;
50
+ background: transparent;
51
+ color: var(--rs-text);
52
+ font: inherit;
53
+ font-size: var(--rs-font-size-sm);
54
+ line-height: 1.5;
55
+ }
56
+ .rs-textarea__shell.is-autosize .rs-textarea__control[data-v-f75ef1a0] {
57
+ min-height: 0;
58
+ }
59
+ .rs-textarea__shell.has-count .rs-textarea__control[data-v-f75ef1a0] {
60
+ padding-bottom: 1.55rem;
61
+ }
62
+ .rs-textarea__shell.has-clear .rs-textarea__control[data-v-f75ef1a0] {
63
+ padding-right: 1.85rem;
64
+ }
65
+ .rs-input-field--sm .rs-textarea__control[data-v-f75ef1a0] {
66
+ min-height: 3.5rem;
67
+ padding: 0.4rem 0.6rem;
68
+ font-size: var(--rs-font-size-xs);
69
+ }
70
+ .rs-input-field--sm .rs-textarea__shell.has-count .rs-textarea__control[data-v-f75ef1a0] {
71
+ padding-bottom: 1.4rem;
72
+ }
73
+ .rs-input-field--lg .rs-textarea__control[data-v-f75ef1a0] {
74
+ min-height: 5.5rem;
75
+ padding: 0.7rem 0.9rem;
76
+ }
77
+ .rs-textarea__control[data-v-f75ef1a0]::placeholder {
78
+ color: var(--rs-placeholder);
79
+ }
80
+ .rs-textarea__control[data-v-f75ef1a0]:disabled {
81
+ cursor: not-allowed;
82
+ }
83
+ .rs-textarea__control[data-v-f75ef1a0]:read-only {
84
+ cursor: default;
85
+ }
86
+ .rs-textarea__clear[data-v-f75ef1a0] {
87
+ position: absolute;
88
+ top: 0.45rem;
89
+ right: 0.45rem;
90
+ display: inline-flex;
91
+ align-items: center;
92
+ justify-content: center;
93
+ width: 1.25rem;
94
+ height: 1.25rem;
95
+ padding: 0;
96
+ border: none;
97
+ border-radius: var(--rs-radius-xs);
98
+ background: transparent;
99
+ color: var(--rs-muted);
100
+ cursor: pointer;
101
+ transition:
102
+ color var(--rs-transition-fast),
103
+ background var(--rs-transition-fast);
104
+ }
105
+ .rs-textarea__clear[data-v-f75ef1a0]:hover {
106
+ color: var(--rs-text);
107
+ background: var(--rs-item-hover);
108
+ }
109
+ .rs-textarea__count[data-v-f75ef1a0] {
110
+ position: absolute;
111
+ right: 0.65rem;
112
+ bottom: 0.3rem;
113
+ margin: 0;
114
+ pointer-events: none;
115
+ font-size: var(--rs-font-size-xs);
116
+ font-variant-numeric: tabular-nums;
117
+ line-height: 1;
118
+ color: var(--rs-muted);
119
+ }
120
+ .rs-textarea__count.is-limit[data-v-f75ef1a0] {
121
+ color: var(--rs-danger);
122
+ }
123
+ .rs-field--label-left .rs-textarea[data-v-f75ef1a0] {
124
+ grid-column: 2;
125
+ min-width: 0;
126
+ }
@@ -0,0 +1,114 @@
1
+ import type { RsComponentSize, RsRadius } from '../theme/types';
2
+ import { type RsFormLabelPosition } from './form-utils';
3
+ import { type RsFormRuleTrigger } from './form-rules';
4
+ import type { RsInputRule, RsInputValidateTrigger } from './input-rules';
5
+ /** 原生 resize;autosize 开启时强制 none,与 Element Plus 一致。 */
6
+ export type RsTextareaResize = 'none' | 'horizontal' | 'vertical' | 'both';
7
+ /**
8
+ * 自适应高度。true 从 rows 起往下长;对象可锁 minRows / maxRows。
9
+ * 对齐 Ant Design autoSize、Element Plus autosize。
10
+ */
11
+ export type RsTextareaAutosize = boolean | {
12
+ minRows?: number;
13
+ maxRows?: number;
14
+ };
15
+ /**
16
+ * RsTextarea 模板 ref 请用此类型。
17
+ * 不要写 InstanceType<typeof RsTextarea>:组件实例类型过深,vue-tsc 会报 Excessive stack depth。
18
+ */
19
+ export interface RsTextareaExpose {
20
+ validate: (trigger?: RsFormRuleTrigger) => Promise<boolean>;
21
+ clearValidation: () => void;
22
+ setValue: (value: unknown) => void;
23
+ setError: (message: string) => void;
24
+ focus: () => void;
25
+ blur: () => void;
26
+ }
27
+ /** 模板 ref 实例:expose + 根节点 */
28
+ export type RsTextareaInstance = RsTextareaExpose & {
29
+ $el: HTMLElement;
30
+ };
31
+ type __VLS_Props = {
32
+ id?: string;
33
+ placeholder?: string;
34
+ disabled?: boolean;
35
+ readonly?: boolean;
36
+ invalid?: boolean;
37
+ errorMessage?: string;
38
+ size?: RsComponentSize;
39
+ radius?: RsRadius;
40
+ rows?: number;
41
+ resize?: RsTextareaResize;
42
+ /** true 或 { minRows, maxRows };开启后不可拖拽改高 */
43
+ autosize?: RsTextareaAutosize;
44
+ rule?: RsInputRule;
45
+ validator?: (value: string) => boolean | string;
46
+ required?: boolean;
47
+ validateTrigger?: RsInputValidateTrigger;
48
+ name?: string;
49
+ minlength?: number;
50
+ maxlength?: number;
51
+ showCount?: boolean;
52
+ clearable?: boolean;
53
+ showValidateMessage?: boolean;
54
+ label?: string;
55
+ hint?: string;
56
+ labelPosition?: RsFormLabelPosition;
57
+ };
58
+ type __VLS_ModelProps = {
59
+ modelValue?: string;
60
+ };
61
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
62
+ declare var __VLS_6: {
63
+ value: string;
64
+ count: number;
65
+ maxlength: number | undefined;
66
+ }, __VLS_8: {
67
+ message: string;
68
+ };
69
+ type __VLS_Slots = {} & {
70
+ count?: (props: typeof __VLS_6) => any;
71
+ } & {
72
+ error?: (props: typeof __VLS_8) => any;
73
+ };
74
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, RsTextareaExpose, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
75
+ blur: (event: FocusEvent) => any;
76
+ focus: (event: FocusEvent) => any;
77
+ clear: () => any;
78
+ "update:modelValue": (value: string) => any;
79
+ validate: (payload: {
80
+ valid: boolean;
81
+ message?: string;
82
+ }) => any;
83
+ pressEnter: (event: KeyboardEvent) => any;
84
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
85
+ onBlur?: ((event: FocusEvent) => any) | undefined;
86
+ onFocus?: ((event: FocusEvent) => any) | undefined;
87
+ onClear?: (() => any) | undefined;
88
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
89
+ onValidate?: ((payload: {
90
+ valid: boolean;
91
+ message?: string;
92
+ }) => any) | undefined;
93
+ onPressEnter?: ((event: KeyboardEvent) => any) | undefined;
94
+ }>, {
95
+ invalid: boolean;
96
+ resize: RsTextareaResize;
97
+ required: boolean;
98
+ disabled: boolean;
99
+ readonly: boolean;
100
+ validateTrigger: RsInputValidateTrigger;
101
+ clearable: boolean;
102
+ showCount: boolean;
103
+ showValidateMessage: boolean;
104
+ rows: number;
105
+ autosize: RsTextareaAutosize;
106
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
107
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
108
+ declare const _default: typeof __VLS_export;
109
+ export default _default;
110
+ type __VLS_WithSlots<T, S> = T & {
111
+ new (): {
112
+ $slots: S;
113
+ };
114
+ };
@@ -0,0 +1,385 @@
1
+ import { useRsI18n } from "../composables/useRsI18n.js";
2
+ import RsIcon_default from "./RsIcon.js";
3
+ import { buildLocalInputRules, runFormFieldRules } from "./form-rules.js";
4
+ import { isRsFormItemBoundControl, useRsFormContext, useRsFormField, useRsFormItemContext } from "./form-utils.js";
5
+ import { useResolvedRsComponentSize } from "./resolve-size.js";
6
+ import { rsRadiusCss, useResolvedRsRadius } from "./resolve-radius.js";
7
+ import { computed, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeModels, mergeProps, nextTick, normalizeClass, normalizeStyle, onMounted, openBlock, ref, renderSlot, toDisplayString, unref, useAttrs, useId, useModel, watch, withModifiers } from "vue";
8
+ //#region src/components/RsTextarea.vue?vue&type=script&setup=true&lang.ts
9
+ var _hoisted_1 = {
10
+ key: 0,
11
+ class: "rs-field__label"
12
+ };
13
+ var _hoisted_2 = ["for"];
14
+ var _hoisted_3 = {
15
+ key: 0,
16
+ class: "rs-field__required",
17
+ "aria-hidden": "true"
18
+ };
19
+ var _hoisted_4 = { class: "rs-textarea" };
20
+ var _hoisted_5 = [
21
+ "id",
22
+ "value",
23
+ "rows",
24
+ "placeholder",
25
+ "disabled",
26
+ "readonly",
27
+ "minlength",
28
+ "maxlength",
29
+ "aria-invalid",
30
+ "aria-describedby"
31
+ ];
32
+ var _hoisted_6 = ["aria-label"];
33
+ var _hoisted_7 = ["id"];
34
+ var _hoisted_8 = {
35
+ key: 1,
36
+ class: "rs-field__hint"
37
+ };
38
+ var RsTextarea_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
39
+ inheritAttrs: false,
40
+ __name: "RsTextarea",
41
+ props: /*@__PURE__*/ mergeModels({
42
+ id: {},
43
+ placeholder: {},
44
+ disabled: {
45
+ type: Boolean,
46
+ default: false
47
+ },
48
+ readonly: {
49
+ type: Boolean,
50
+ default: false
51
+ },
52
+ invalid: {
53
+ type: Boolean,
54
+ default: false
55
+ },
56
+ errorMessage: {},
57
+ size: {},
58
+ radius: {},
59
+ rows: { default: 3 },
60
+ resize: { default: "vertical" },
61
+ autosize: {
62
+ type: [Boolean, Object],
63
+ default: false
64
+ },
65
+ rule: {},
66
+ validator: {},
67
+ required: {
68
+ type: Boolean,
69
+ default: false
70
+ },
71
+ validateTrigger: { default: "blur" },
72
+ name: {},
73
+ minlength: {},
74
+ maxlength: {},
75
+ showCount: {
76
+ type: Boolean,
77
+ default: false
78
+ },
79
+ clearable: {
80
+ type: Boolean,
81
+ default: false
82
+ },
83
+ showValidateMessage: {
84
+ type: Boolean,
85
+ default: true
86
+ },
87
+ label: {},
88
+ hint: {},
89
+ labelPosition: {}
90
+ }, {
91
+ "modelValue": { default: "" },
92
+ "modelModifiers": {}
93
+ }),
94
+ emits: /*@__PURE__*/ mergeModels([
95
+ "validate",
96
+ "blur",
97
+ "focus",
98
+ "pressEnter",
99
+ "clear"
100
+ ], ["update:modelValue"]),
101
+ setup(__props, { expose: __expose, emit: __emit }) {
102
+ const { t } = useRsI18n();
103
+ const model = useModel(__props, "modelValue", {
104
+ get(value) {
105
+ return value == null ? "" : String(value);
106
+ },
107
+ set(value) {
108
+ return value == null ? "" : String(value);
109
+ }
110
+ });
111
+ const props = __props;
112
+ const emit = __emit;
113
+ const attrs = useAttrs();
114
+ const formContext = useRsFormContext();
115
+ const formItem = useRsFormItemContext();
116
+ const boundToItem = computed(() => isRsFormItemBoundControl(formItem, {
117
+ id: props.id,
118
+ name: props.name
119
+ }));
120
+ const fieldId = useId();
121
+ const textareaRef = ref(null);
122
+ const touched = ref(false);
123
+ const autoInvalid = ref(false);
124
+ const autoMessage = ref("");
125
+ const composing = ref(false);
126
+ const resolvedId = computed(() => props.id ?? fieldId);
127
+ const resolvedLabelPosition = computed(() => props.labelPosition ?? formContext?.labelPosition.value ?? "top");
128
+ const resolvedLabelAlign = computed(() => formContext?.labelAlign.value ?? "start");
129
+ const errorId = computed(() => `${resolvedId.value}-error`);
130
+ const displayMessage = computed(() => {
131
+ if (boundToItem.value) return "";
132
+ if (props.errorMessage) return props.errorMessage;
133
+ if (props.showValidateMessage && autoInvalid.value) return autoMessage.value;
134
+ return "";
135
+ });
136
+ const isInvalid = computed(() => {
137
+ if (boundToItem.value) return Boolean(formItem?.invalid.value || props.invalid);
138
+ return props.invalid || autoInvalid.value;
139
+ });
140
+ const describedBy = computed(() => {
141
+ if (boundToItem.value) return formItem?.describedBy.value;
142
+ return displayMessage.value ? errorId.value : void 0;
143
+ });
144
+ const resolvedDisabled = computed(() => props.disabled || formContext?.disabled.value || false);
145
+ const resolvedSize = useResolvedRsComponentSize(() => props.size);
146
+ const resolvedRadius = useResolvedRsRadius(() => props.radius, "sm");
147
+ const radiusStyle = computed(() => ({ "--rs-input-radius": rsRadiusCss(resolvedRadius.value) }));
148
+ const fieldStyle = computed(() => {
149
+ if (resolvedLabelPosition.value !== "left") return void 0;
150
+ const labelWidth = formContext?.labelWidth.value;
151
+ if (!labelWidth) return void 0;
152
+ return { "--rs-field-label-width": labelWidth };
153
+ });
154
+ const autosizeEnabled = computed(() => Boolean(props.autosize));
155
+ const autosizeSpec = computed(() => typeof props.autosize === "object" && props.autosize ? props.autosize : {});
156
+ const displayRows = computed(() => autosizeSpec.value.minRows ?? props.rows);
157
+ const resolvedResize = computed(() => autosizeEnabled.value ? "none" : props.resize);
158
+ const countText = computed(() => {
159
+ const n = model.value.length;
160
+ return props.maxlength != null ? `${n} / ${props.maxlength}` : String(n);
161
+ });
162
+ const countLimitReached = computed(() => props.maxlength != null && model.value.length >= props.maxlength);
163
+ const showClearButton = computed(() => props.clearable && !resolvedDisabled.value && !props.readonly && model.value.length > 0);
164
+ function parseLineHeight(el) {
165
+ const style = getComputedStyle(el);
166
+ const lh = Number.parseFloat(style.lineHeight);
167
+ if (Number.isFinite(lh) && lh > 0) return lh;
168
+ return (Number.parseFloat(style.fontSize) || 14) * 1.5;
169
+ }
170
+ function autosizePadding(el) {
171
+ const style = getComputedStyle(el);
172
+ const pad = Number.parseFloat(style.paddingTop) + Number.parseFloat(style.paddingBottom);
173
+ if (style.boxSizing !== "border-box") return 0;
174
+ const border = Number.parseFloat(style.borderTopWidth) + Number.parseFloat(style.borderBottomWidth);
175
+ return (Number.isFinite(pad) ? pad : 0) + (Number.isFinite(border) ? border : 0);
176
+ }
177
+ function adjustHeight() {
178
+ const el = textareaRef.value;
179
+ if (!el) return;
180
+ if (!autosizeEnabled.value) {
181
+ el.style.height = "";
182
+ el.style.overflowY = "";
183
+ return;
184
+ }
185
+ el.style.height = "auto";
186
+ el.style.overflowY = "hidden";
187
+ const lineHeight = parseLineHeight(el);
188
+ const extra = autosizePadding(el);
189
+ const minRows = autosizeSpec.value.minRows ?? props.rows;
190
+ const maxRows = autosizeSpec.value.maxRows;
191
+ const min = lineHeight * minRows + extra;
192
+ const max = maxRows != null ? lineHeight * maxRows + extra : void 0;
193
+ let height = el.scrollHeight;
194
+ if (height < min) height = min;
195
+ if (max != null && height > max) {
196
+ height = max;
197
+ el.style.overflowY = "auto";
198
+ }
199
+ el.style.height = `${height}px`;
200
+ }
201
+ function scheduleAdjustHeight() {
202
+ nextTick(adjustHeight);
203
+ }
204
+ async function runValidate(trigger = "submit") {
205
+ const formRules = formContext?.getFieldRules(props.name) ?? [];
206
+ const localRules = buildLocalInputRules({
207
+ required: props.required,
208
+ rule: props.rule,
209
+ validator: props.validator
210
+ });
211
+ const rules = [...formRules, ...localRules];
212
+ if (!rules.length) {
213
+ autoInvalid.value = false;
214
+ autoMessage.value = "";
215
+ emit("validate", { valid: true });
216
+ return true;
217
+ }
218
+ const result = await runFormFieldRules(model.value, rules, {
219
+ trigger,
220
+ t
221
+ });
222
+ autoInvalid.value = !result.valid;
223
+ autoMessage.value = result.message ?? "";
224
+ emit("validate", result);
225
+ return result.valid;
226
+ }
227
+ function setError(message) {
228
+ autoInvalid.value = true;
229
+ autoMessage.value = message;
230
+ }
231
+ function setValue(value) {
232
+ model.value = String(value ?? "");
233
+ scheduleAdjustHeight();
234
+ }
235
+ function clearValidation() {
236
+ touched.value = false;
237
+ autoInvalid.value = false;
238
+ autoMessage.value = "";
239
+ }
240
+ function focus() {
241
+ textareaRef.value?.focus();
242
+ }
243
+ function blur() {
244
+ textareaRef.value?.blur();
245
+ }
246
+ function onNativeInput(event) {
247
+ const el = event.target;
248
+ model.value = el?.value ?? "";
249
+ scheduleAdjustHeight();
250
+ if (composing.value) return;
251
+ if (touched.value && (props.validateTrigger === "input" || props.validateTrigger === "both")) runValidate("change");
252
+ }
253
+ function onCompositionStart() {
254
+ composing.value = true;
255
+ }
256
+ function onCompositionEnd(event) {
257
+ composing.value = false;
258
+ onNativeInput(event);
259
+ }
260
+ function onBlur(event) {
261
+ touched.value = true;
262
+ if (props.validateTrigger === "blur" || props.validateTrigger === "both") runValidate("blur");
263
+ emit("blur", event);
264
+ }
265
+ function onKeydown(event) {
266
+ if (event.key !== "Enter" || composing.value) return;
267
+ emit("pressEnter", event);
268
+ }
269
+ function onClear() {
270
+ if (resolvedDisabled.value || props.readonly) return;
271
+ model.value = "";
272
+ emit("clear");
273
+ nextTick(() => {
274
+ textareaRef.value?.focus();
275
+ adjustHeight();
276
+ if (props.validateTrigger === "input" || props.validateTrigger === "both") runValidate("change");
277
+ });
278
+ }
279
+ watch([
280
+ model,
281
+ () => props.autosize,
282
+ () => props.rows,
283
+ () => props.size,
284
+ () => props.showCount
285
+ ], scheduleAdjustHeight);
286
+ onMounted(adjustHeight);
287
+ useRsFormField(() => ({
288
+ get name() {
289
+ return props.name;
290
+ },
291
+ getValue: () => model.value,
292
+ setValue,
293
+ validate: async (trigger) => {
294
+ return {
295
+ valid: await runValidate(trigger ?? "submit"),
296
+ message: autoMessage.value || void 0,
297
+ name: props.name
298
+ };
299
+ },
300
+ clearValidation,
301
+ setError
302
+ }));
303
+ __expose({
304
+ validate: runValidate,
305
+ clearValidation,
306
+ setValue,
307
+ setError,
308
+ focus,
309
+ blur
310
+ });
311
+ return (_ctx, _cache) => {
312
+ return openBlock(), createElementBlock("div", {
313
+ class: normalizeClass(["rs-field", [
314
+ `rs-field--label-${resolvedLabelPosition.value}`,
315
+ resolvedLabelPosition.value === "left" && resolvedLabelAlign.value === "end" ? "rs-field--label-align-end" : void 0,
316
+ `rs-input-field--${unref(resolvedSize)}`
317
+ ]]),
318
+ style: normalizeStyle([fieldStyle.value, radiusStyle.value])
319
+ }, [__props.label ? (openBlock(), createElementBlock("span", _hoisted_1, [createElementVNode("label", { for: resolvedId.value }, toDisplayString(__props.label), 9, _hoisted_2), __props.required ? (openBlock(), createElementBlock("span", _hoisted_3, "*")) : createCommentVNode("", true)])) : createCommentVNode("", true), createElementVNode("div", _hoisted_4, [
320
+ createElementVNode("div", { class: normalizeClass(["rs-textarea__shell", {
321
+ "is-invalid": isInvalid.value,
322
+ "is-disabled": resolvedDisabled.value,
323
+ "is-readonly": __props.readonly,
324
+ "is-autosize": autosizeEnabled.value,
325
+ "has-count": __props.showCount,
326
+ "has-clear": showClearButton.value
327
+ }]) }, [
328
+ createElementVNode("textarea", mergeProps({
329
+ ref_key: "textareaRef",
330
+ ref: textareaRef
331
+ }, unref(attrs), {
332
+ id: resolvedId.value,
333
+ value: model.value,
334
+ class: "rs-textarea__control",
335
+ rows: displayRows.value,
336
+ style: { resize: resolvedResize.value },
337
+ placeholder: __props.placeholder,
338
+ disabled: resolvedDisabled.value,
339
+ readonly: __props.readonly,
340
+ minlength: __props.minlength,
341
+ maxlength: __props.maxlength,
342
+ "aria-invalid": isInvalid.value || void 0,
343
+ "aria-describedby": describedBy.value,
344
+ onInput: onNativeInput,
345
+ onCompositionstart: onCompositionStart,
346
+ onCompositionend: onCompositionEnd,
347
+ onKeydown,
348
+ onBlur,
349
+ onFocus: _cache[0] || (_cache[0] = ($event) => emit("focus", $event))
350
+ }), null, 16, _hoisted_5),
351
+ showClearButton.value ? (openBlock(), createElementBlock("button", {
352
+ key: 0,
353
+ type: "button",
354
+ class: "rs-textarea__clear",
355
+ tabindex: "-1",
356
+ "aria-label": unref(t)("input.clear"),
357
+ onPointerdown: _cache[1] || (_cache[1] = withModifiers(() => {}, ["prevent"])),
358
+ onClick: onClear
359
+ }, [createVNode(RsIcon_default, {
360
+ name: "x",
361
+ size: 14
362
+ })], 40, _hoisted_6)) : createCommentVNode("", true),
363
+ __props.showCount ? (openBlock(), createElementBlock("span", {
364
+ key: 1,
365
+ class: normalizeClass(["rs-textarea__count", { "is-limit": countLimitReached.value }]),
366
+ "aria-hidden": "true"
367
+ }, [renderSlot(_ctx.$slots, "count", {
368
+ value: model.value,
369
+ count: model.value.length,
370
+ maxlength: __props.maxlength
371
+ }, () => [createTextVNode(toDisplayString(countText.value), 1)], true)], 2)) : createCommentVNode("", true)
372
+ ], 2),
373
+ displayMessage.value ? (openBlock(), createElementBlock("p", {
374
+ key: 0,
375
+ id: errorId.value,
376
+ class: "rs-field__error",
377
+ role: "alert"
378
+ }, [renderSlot(_ctx.$slots, "error", { message: displayMessage.value }, () => [createTextVNode(toDisplayString(displayMessage.value), 1)], true)], 8, _hoisted_7)) : createCommentVNode("", true),
379
+ __props.hint ? (openBlock(), createElementBlock("span", _hoisted_8, toDisplayString(__props.hint), 1)) : createCommentVNode("", true)
380
+ ])], 6);
381
+ };
382
+ }
383
+ });
384
+ //#endregion
385
+ export { RsTextarea_vue_vue_type_script_setup_true_lang_default as default };
@@ -0,0 +1,8 @@
1
+ import './RsTextarea.css'
2
+ import _plugin_vue_export_helper_default from "../_virtual/_plugin-vue_export-helper.js";
3
+ import RsTextarea_vue_vue_type_script_setup_true_lang_default from "./RsTextarea.impl.js";
4
+
5
+ //#region src/components/RsTextarea.vue
6
+ var RsTextarea_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsTextarea_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-f75ef1a0"]]);
7
+ //#endregion
8
+ export { RsTextarea_default as default };
@@ -1,15 +1,16 @@
1
1
 
2
2
  .rs-tooltip__with-icon {
3
3
  display: inline-flex;
4
+ flex-wrap: nowrap;
4
5
  align-items: center;
5
6
  gap: 0.25rem;
7
+ width: max-content;
6
8
  max-width: 100%;
7
- vertical-align: baseline;
9
+ vertical-align: middle;
8
10
  }
9
11
  .rs-tooltip__label {
10
- display: inline-flex;
12
+ display: inline;
11
13
  min-width: 0;
12
- max-width: 100%;
13
14
  }
14
15
  .rs-tooltip__icon-trigger {
15
16
  display: inline-flex;
@@ -18,6 +18,8 @@ type __VLS_Props = {
18
18
  icon?: boolean;
19
19
  /** 后缀图标名,默认 info(问号/说明圆标;对齐表单帮助惯用) */
20
20
  iconName?: string;
21
+ /** 帮助图标的无障碍名称;缺省用 content,再回退 locale `tooltip.help` */
22
+ ariaLabel?: string;
21
23
  };
22
24
  declare var __VLS_8: {}, __VLS_27: {}, __VLS_41: {};
23
25
  type __VLS_Slots = {} & {
@@ -1,3 +1,4 @@
1
+ import { useRsI18n } from "../composables/useRsI18n.js";
1
2
  import RsIcon_default from "./RsIcon.js";
2
3
  import { TooltipContent, TooltipPortal, TooltipRoot, TooltipTrigger } from "./reka.js";
3
4
  import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, renderSlot, toDisplayString, unref, useSlots, withCtx } from "vue";
@@ -34,13 +35,15 @@ var RsTooltip_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
34
35
  type: Boolean,
35
36
  default: false
36
37
  },
37
- iconName: { default: "info" }
38
+ iconName: { default: "info" },
39
+ ariaLabel: {}
38
40
  },
39
41
  setup(__props) {
40
42
  const props = __props;
41
43
  const slots = useSlots();
44
+ const { t } = useRsI18n();
42
45
  const hasLabelSlot = computed(() => Boolean(slots.default));
43
- const iconAriaLabel = computed(() => props.content?.trim() || "Help");
46
+ const iconAriaLabel = computed(() => props.ariaLabel?.trim() || props.content?.trim() || t("tooltip.help", "Help"));
44
47
  return (_ctx, _cache) => {
45
48
  return openBlock(), createBlock(unref(TooltipRoot), {
46
49
  disabled: __props.disabled,