@v-c/textarea 0.0.1
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.
- package/LICENSE +21 -0
- package/dist/ResizableTextArea.cjs +137 -0
- package/dist/ResizableTextArea.d.ts +41 -0
- package/dist/ResizableTextArea.js +133 -0
- package/dist/TextArea.cjs +363 -0
- package/dist/TextArea.d.ts +3 -0
- package/dist/TextArea.js +360 -0
- package/dist/_virtual/rolldown_runtime.cjs +21 -0
- package/dist/calculateNodeHeight.cjs +96 -0
- package/dist/calculateNodeHeight.d.ts +9 -0
- package/dist/calculateNodeHeight.js +94 -0
- package/dist/index.cjs +6 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/interface.cjs +0 -0
- package/dist/interface.d.ts +58 -0
- package/dist/interface.js +0 -0
- package/package.json +36 -0
package/dist/TextArea.js
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import ResizableTextArea_default from "./ResizableTextArea.js";
|
|
2
|
+
import { Fragment, computed, createVNode, defineComponent, mergeDefaults, mergeProps, nextTick, shallowRef, watch } from "vue";
|
|
3
|
+
import { classNames } from "@v-c/util";
|
|
4
|
+
import { BaseInput, resolveOnChange, useCount } from "@v-c/input";
|
|
5
|
+
import omit from "@v-c/util/dist/omit";
|
|
6
|
+
var defaults = { prefixCls: "vc-textarea" };
|
|
7
|
+
var TextArea_default = /* @__PURE__ */ defineComponent((props, { attrs, expose, slots, emit }) => {
|
|
8
|
+
const stateValue = shallowRef(props.value ?? props.defaultValue);
|
|
9
|
+
watch(() => props.value, (newValue) => {
|
|
10
|
+
if ("value" in props || {}) stateValue.value = newValue;
|
|
11
|
+
});
|
|
12
|
+
const setValue = (val, callback) => {
|
|
13
|
+
if (stateValue.value === val) return;
|
|
14
|
+
if (props.value === void 0) stateValue.value = val;
|
|
15
|
+
nextTick(() => {
|
|
16
|
+
callback?.();
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
const formatValue = computed(() => stateValue.value === void 0 || stateValue.value === null ? "" : String(stateValue.value));
|
|
20
|
+
const focused = shallowRef(false);
|
|
21
|
+
const compositionRef = shallowRef(false);
|
|
22
|
+
const textareaResized = shallowRef(false);
|
|
23
|
+
const holderRef = shallowRef();
|
|
24
|
+
const resizableTextAreaRef = shallowRef();
|
|
25
|
+
const getTextArea = () => resizableTextAreaRef.value?.textArea();
|
|
26
|
+
const focus = () => {
|
|
27
|
+
getTextArea()?.focus();
|
|
28
|
+
};
|
|
29
|
+
expose({
|
|
30
|
+
resizableTextArea: computed(() => resizableTextAreaRef.value),
|
|
31
|
+
focus,
|
|
32
|
+
blur: () => {
|
|
33
|
+
getTextArea()?.blur();
|
|
34
|
+
},
|
|
35
|
+
nativeElement: computed(() => holderRef.value?.nativeElement || getTextArea() || null)
|
|
36
|
+
});
|
|
37
|
+
watch(() => props.disabled, (newDisabled) => {
|
|
38
|
+
focused.value = !newDisabled && focused.value;
|
|
39
|
+
});
|
|
40
|
+
const selection = shallowRef(null);
|
|
41
|
+
watch(selection, (newSelection) => {
|
|
42
|
+
if (newSelection) getTextArea()?.setSelectionRange(...newSelection);
|
|
43
|
+
});
|
|
44
|
+
const countConfig = useCount(computed(() => props.count), computed(() => props.showCount));
|
|
45
|
+
const mergedMax = computed(() => countConfig.value.max ?? props.maxLength);
|
|
46
|
+
const hasMaxLength = computed(() => Number(mergedMax.value) > 0);
|
|
47
|
+
const valueLength = computed(() => countConfig.value.strategy(formatValue.value));
|
|
48
|
+
const isOutOfRange = computed(() => !!mergedMax.value && valueLength.value > mergedMax.value);
|
|
49
|
+
const onChange = (e) => {
|
|
50
|
+
emit("change", e);
|
|
51
|
+
props.onChange?.(e);
|
|
52
|
+
};
|
|
53
|
+
const triggerChange = (e, currentValue) => {
|
|
54
|
+
let cutValue = currentValue;
|
|
55
|
+
const cfg = countConfig.value;
|
|
56
|
+
if (!compositionRef.value && cfg.exceedFormatter && cfg.max && cfg.strategy(currentValue) > cfg.max) {
|
|
57
|
+
cutValue = cfg.exceedFormatter(currentValue, { max: cfg.max });
|
|
58
|
+
if (currentValue !== cutValue) selection.value = [getTextArea()?.selectionStart || 0, getTextArea()?.selectionEnd || 0];
|
|
59
|
+
}
|
|
60
|
+
setValue(cutValue);
|
|
61
|
+
emit("update:value", cutValue);
|
|
62
|
+
nextTick(() => {
|
|
63
|
+
resizableTextAreaRef.value?.setValue?.(cutValue);
|
|
64
|
+
});
|
|
65
|
+
resolveOnChange(e.currentTarget, e, onChange, cutValue);
|
|
66
|
+
};
|
|
67
|
+
const onInternalCompositionStart = (e) => {
|
|
68
|
+
compositionRef.value = true;
|
|
69
|
+
emit("compositionStart", e);
|
|
70
|
+
props.onCompositionStart?.(e);
|
|
71
|
+
};
|
|
72
|
+
const onInternalCompositionEnd = (e) => {
|
|
73
|
+
compositionRef.value = false;
|
|
74
|
+
triggerChange(e, e.target.value);
|
|
75
|
+
emit("compositionEnd", e);
|
|
76
|
+
props.onCompositionEnd?.(e);
|
|
77
|
+
};
|
|
78
|
+
const onInternalChange = (e) => {
|
|
79
|
+
triggerChange(e, e.target.value);
|
|
80
|
+
};
|
|
81
|
+
const handleKeyDown = (e) => {
|
|
82
|
+
if (e.key === "Enter" && props.onPressEnter && !e.isComposing) {
|
|
83
|
+
emit("pressEnter", e);
|
|
84
|
+
props.onPressEnter?.(e);
|
|
85
|
+
}
|
|
86
|
+
emit("keydown", e);
|
|
87
|
+
props.onKeyDown?.(e);
|
|
88
|
+
};
|
|
89
|
+
const handleFocus = (e) => {
|
|
90
|
+
focused.value = true;
|
|
91
|
+
emit("focus", e);
|
|
92
|
+
props.onFocus?.(e);
|
|
93
|
+
};
|
|
94
|
+
const handleBlur = (e) => {
|
|
95
|
+
focused.value = false;
|
|
96
|
+
emit("blur", e);
|
|
97
|
+
props.onBlur?.(e);
|
|
98
|
+
};
|
|
99
|
+
const handleReset = (e) => {
|
|
100
|
+
resolveOnChange(getTextArea(), e, onChange);
|
|
101
|
+
setValue("", () => focus());
|
|
102
|
+
emit("update:value", "");
|
|
103
|
+
};
|
|
104
|
+
const handleResize = (size) => {
|
|
105
|
+
emit("resize", size);
|
|
106
|
+
props.onResize?.(size);
|
|
107
|
+
if (getTextArea()?.style.height) textareaResized.value = true;
|
|
108
|
+
};
|
|
109
|
+
const mergedAllowClear = computed(() => {
|
|
110
|
+
if (!props.allowClear) return props.allowClear;
|
|
111
|
+
const clearIcon = slots.clearIcon?.();
|
|
112
|
+
if (clearIcon) return {
|
|
113
|
+
...typeof props.allowClear === "object" ? props.allowClear : {},
|
|
114
|
+
clearIcon
|
|
115
|
+
};
|
|
116
|
+
return props.allowClear;
|
|
117
|
+
});
|
|
118
|
+
return () => {
|
|
119
|
+
const { allowClear, maxLength, prefixCls = defaults.prefixCls, showCount, disabled, hidden, classNames: classNames$1, styles, onClear, readOnly, autoSize, suffix } = props;
|
|
120
|
+
const { class: attrClass, style: attrStyle,...restAttrs } = attrs;
|
|
121
|
+
const mergedClassName = props.className || attrClass;
|
|
122
|
+
const mergedStyle = {
|
|
123
|
+
...props.style,
|
|
124
|
+
...attrStyle
|
|
125
|
+
};
|
|
126
|
+
let suffixNode = slots.suffix?.() ?? suffix;
|
|
127
|
+
let dataCount;
|
|
128
|
+
if (countConfig.value.show) {
|
|
129
|
+
if (countConfig.value.showFormatter) dataCount = countConfig.value.showFormatter({
|
|
130
|
+
value: formatValue.value,
|
|
131
|
+
count: valueLength.value,
|
|
132
|
+
maxLength: mergedMax.value
|
|
133
|
+
});
|
|
134
|
+
else dataCount = `${valueLength.value}${hasMaxLength.value ? ` / ${mergedMax.value}` : ""}`;
|
|
135
|
+
suffixNode = createVNode(Fragment, null, [suffixNode, createVNode("span", {
|
|
136
|
+
"class": classNames(`${prefixCls}-data-count`, classNames$1?.count),
|
|
137
|
+
"style": styles?.count
|
|
138
|
+
}, [dataCount])]);
|
|
139
|
+
}
|
|
140
|
+
const isPureTextArea = !autoSize && !showCount && !allowClear;
|
|
141
|
+
const baseInputClassNames = {
|
|
142
|
+
...classNames$1,
|
|
143
|
+
affixWrapper: classNames(classNames$1?.affixWrapper, {
|
|
144
|
+
[`${prefixCls}-show-count`]: showCount,
|
|
145
|
+
[`${prefixCls}-textarea-allow-clear`]: allowClear
|
|
146
|
+
})
|
|
147
|
+
};
|
|
148
|
+
const inputAttrs = omit(restAttrs, [
|
|
149
|
+
"class",
|
|
150
|
+
"style",
|
|
151
|
+
"onFocus",
|
|
152
|
+
"onBlur",
|
|
153
|
+
"onChange",
|
|
154
|
+
"onCompositionstart",
|
|
155
|
+
"onCompositionend",
|
|
156
|
+
"onKeydown",
|
|
157
|
+
"onKeyup",
|
|
158
|
+
"onInput"
|
|
159
|
+
]);
|
|
160
|
+
return createVNode(BaseInput, {
|
|
161
|
+
"ref": holderRef,
|
|
162
|
+
"value": formatValue.value,
|
|
163
|
+
"allowClear": mergedAllowClear.value,
|
|
164
|
+
"handleReset": handleReset,
|
|
165
|
+
"suffix": suffixNode,
|
|
166
|
+
"prefixCls": prefixCls,
|
|
167
|
+
"classNames": baseInputClassNames,
|
|
168
|
+
"disabled": disabled,
|
|
169
|
+
"focused": focused.value,
|
|
170
|
+
"class": classNames([mergedClassName], isOutOfRange.value && `${prefixCls}-out-of-range`),
|
|
171
|
+
"style": {
|
|
172
|
+
...mergedStyle,
|
|
173
|
+
...textareaResized.value && !isPureTextArea ? { height: "auto" } : {}
|
|
174
|
+
},
|
|
175
|
+
"dataAttrs": { affixWrapper: { "data-count": typeof dataCount === "string" ? dataCount : void 0 } },
|
|
176
|
+
"hidden": hidden,
|
|
177
|
+
"readOnly": readOnly,
|
|
178
|
+
"onClear": onClear
|
|
179
|
+
}, { default: () => [createVNode(ResizableTextArea_default, mergeProps(inputAttrs, {
|
|
180
|
+
"value": stateValue.value,
|
|
181
|
+
"autoSize": autoSize,
|
|
182
|
+
"maxLength": maxLength,
|
|
183
|
+
"onKeydown": handleKeyDown,
|
|
184
|
+
"onChange": onInternalChange,
|
|
185
|
+
"onFocus": handleFocus,
|
|
186
|
+
"onBlur": handleBlur,
|
|
187
|
+
"onCompositionstart": onInternalCompositionStart,
|
|
188
|
+
"onCompositionend": onInternalCompositionEnd,
|
|
189
|
+
"class": classNames(classNames$1?.textarea),
|
|
190
|
+
"style": {
|
|
191
|
+
...styles?.textarea,
|
|
192
|
+
resize: attrStyle?.resize
|
|
193
|
+
},
|
|
194
|
+
"disabled": disabled,
|
|
195
|
+
"prefixCls": prefixCls,
|
|
196
|
+
"onResize": handleResize,
|
|
197
|
+
"ref": resizableTextAreaRef,
|
|
198
|
+
"readOnly": readOnly
|
|
199
|
+
}), null)] });
|
|
200
|
+
};
|
|
201
|
+
}, {
|
|
202
|
+
props: /* @__PURE__ */ mergeDefaults({
|
|
203
|
+
value: {
|
|
204
|
+
type: [String, Number],
|
|
205
|
+
required: false,
|
|
206
|
+
default: void 0
|
|
207
|
+
},
|
|
208
|
+
defaultValue: {
|
|
209
|
+
type: [String, Number],
|
|
210
|
+
required: false,
|
|
211
|
+
default: void 0
|
|
212
|
+
},
|
|
213
|
+
prefixCls: {
|
|
214
|
+
type: String,
|
|
215
|
+
required: false,
|
|
216
|
+
default: void 0
|
|
217
|
+
},
|
|
218
|
+
autoSize: {
|
|
219
|
+
type: [Boolean, Object],
|
|
220
|
+
required: false,
|
|
221
|
+
default: void 0
|
|
222
|
+
},
|
|
223
|
+
onPressEnter: {
|
|
224
|
+
type: Function,
|
|
225
|
+
required: false,
|
|
226
|
+
default: void 0
|
|
227
|
+
},
|
|
228
|
+
onResize: {
|
|
229
|
+
type: Function,
|
|
230
|
+
required: false,
|
|
231
|
+
default: void 0
|
|
232
|
+
},
|
|
233
|
+
onClear: {
|
|
234
|
+
type: Function,
|
|
235
|
+
required: false,
|
|
236
|
+
default: void 0
|
|
237
|
+
},
|
|
238
|
+
readOnly: {
|
|
239
|
+
type: Boolean,
|
|
240
|
+
required: false,
|
|
241
|
+
default: void 0
|
|
242
|
+
},
|
|
243
|
+
classNames: {
|
|
244
|
+
type: Object,
|
|
245
|
+
required: false,
|
|
246
|
+
default: void 0
|
|
247
|
+
},
|
|
248
|
+
styles: {
|
|
249
|
+
type: Object,
|
|
250
|
+
required: false,
|
|
251
|
+
default: void 0
|
|
252
|
+
},
|
|
253
|
+
allowClear: {
|
|
254
|
+
type: [Boolean, Object],
|
|
255
|
+
required: false,
|
|
256
|
+
default: void 0
|
|
257
|
+
},
|
|
258
|
+
showCount: {
|
|
259
|
+
type: [Boolean, Object],
|
|
260
|
+
required: false,
|
|
261
|
+
default: void 0
|
|
262
|
+
},
|
|
263
|
+
count: {
|
|
264
|
+
type: Object,
|
|
265
|
+
required: false,
|
|
266
|
+
default: void 0
|
|
267
|
+
},
|
|
268
|
+
maxLength: {
|
|
269
|
+
type: Number,
|
|
270
|
+
required: false,
|
|
271
|
+
default: void 0
|
|
272
|
+
},
|
|
273
|
+
suffix: {
|
|
274
|
+
type: [
|
|
275
|
+
String,
|
|
276
|
+
Number,
|
|
277
|
+
null,
|
|
278
|
+
Boolean,
|
|
279
|
+
Array
|
|
280
|
+
],
|
|
281
|
+
required: false,
|
|
282
|
+
skipCheck: true,
|
|
283
|
+
default: void 0
|
|
284
|
+
},
|
|
285
|
+
disabled: {
|
|
286
|
+
type: Boolean,
|
|
287
|
+
required: false,
|
|
288
|
+
default: void 0
|
|
289
|
+
},
|
|
290
|
+
hidden: {
|
|
291
|
+
type: Boolean,
|
|
292
|
+
required: false,
|
|
293
|
+
default: void 0
|
|
294
|
+
},
|
|
295
|
+
onChange: {
|
|
296
|
+
type: Function,
|
|
297
|
+
required: false,
|
|
298
|
+
default: void 0
|
|
299
|
+
},
|
|
300
|
+
onFocus: {
|
|
301
|
+
type: Function,
|
|
302
|
+
required: false,
|
|
303
|
+
default: void 0
|
|
304
|
+
},
|
|
305
|
+
onBlur: {
|
|
306
|
+
type: Function,
|
|
307
|
+
required: false,
|
|
308
|
+
default: void 0
|
|
309
|
+
},
|
|
310
|
+
onCompositionStart: {
|
|
311
|
+
type: Function,
|
|
312
|
+
required: false,
|
|
313
|
+
default: void 0
|
|
314
|
+
},
|
|
315
|
+
onCompositionEnd: {
|
|
316
|
+
type: Function,
|
|
317
|
+
required: false,
|
|
318
|
+
default: void 0
|
|
319
|
+
},
|
|
320
|
+
onKeyDown: {
|
|
321
|
+
type: Function,
|
|
322
|
+
required: false,
|
|
323
|
+
default: void 0
|
|
324
|
+
},
|
|
325
|
+
className: {
|
|
326
|
+
type: String,
|
|
327
|
+
required: false,
|
|
328
|
+
default: void 0
|
|
329
|
+
},
|
|
330
|
+
class: {
|
|
331
|
+
type: null,
|
|
332
|
+
required: false,
|
|
333
|
+
default: void 0
|
|
334
|
+
},
|
|
335
|
+
style: {
|
|
336
|
+
type: null,
|
|
337
|
+
required: false,
|
|
338
|
+
default: void 0
|
|
339
|
+
},
|
|
340
|
+
placeholder: {
|
|
341
|
+
type: String,
|
|
342
|
+
required: false,
|
|
343
|
+
default: void 0
|
|
344
|
+
}
|
|
345
|
+
}, defaults),
|
|
346
|
+
name: "TextArea",
|
|
347
|
+
inheritAttrs: false,
|
|
348
|
+
emits: [
|
|
349
|
+
"update:value",
|
|
350
|
+
"change",
|
|
351
|
+
"compositionStart",
|
|
352
|
+
"compositionEnd",
|
|
353
|
+
"pressEnter",
|
|
354
|
+
"keydown",
|
|
355
|
+
"focus",
|
|
356
|
+
"blur",
|
|
357
|
+
"resize"
|
|
358
|
+
]
|
|
359
|
+
});
|
|
360
|
+
export { TextArea_default as default };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __copyProps = (to, from, except, desc) => {
|
|
8
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
9
|
+
key = keys[i];
|
|
10
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
11
|
+
get: ((k) => from[k]).bind(null, key),
|
|
12
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
18
|
+
value: mod,
|
|
19
|
+
enumerable: true
|
|
20
|
+
}) : target, mod));
|
|
21
|
+
exports.__toESM = __toESM;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
+
var HIDDEN_TEXTAREA_STYLE = `
|
|
3
|
+
min-height:0 !important;
|
|
4
|
+
max-height:none !important;
|
|
5
|
+
height:0 !important;
|
|
6
|
+
visibility:hidden !important;
|
|
7
|
+
overflow:hidden !important;
|
|
8
|
+
position:absolute !important;
|
|
9
|
+
z-index:-1000 !important;
|
|
10
|
+
top:0 !important;
|
|
11
|
+
right:0 !important;
|
|
12
|
+
pointer-events: none !important;
|
|
13
|
+
`;
|
|
14
|
+
var SIZING_STYLE = [
|
|
15
|
+
"letter-spacing",
|
|
16
|
+
"line-height",
|
|
17
|
+
"padding-top",
|
|
18
|
+
"padding-bottom",
|
|
19
|
+
"font-family",
|
|
20
|
+
"font-weight",
|
|
21
|
+
"font-size",
|
|
22
|
+
"font-variant",
|
|
23
|
+
"text-rendering",
|
|
24
|
+
"text-transform",
|
|
25
|
+
"width",
|
|
26
|
+
"text-indent",
|
|
27
|
+
"padding-left",
|
|
28
|
+
"padding-right",
|
|
29
|
+
"border-width",
|
|
30
|
+
"box-sizing",
|
|
31
|
+
"word-break",
|
|
32
|
+
"white-space"
|
|
33
|
+
];
|
|
34
|
+
var computedStyleCache = {};
|
|
35
|
+
var hiddenTextarea;
|
|
36
|
+
function calculateNodeStyling(node, useCache = false) {
|
|
37
|
+
const nodeRef = node.getAttribute("id") || node.getAttribute("data-id") || node.getAttribute("name");
|
|
38
|
+
if (useCache && computedStyleCache[nodeRef]) return computedStyleCache[nodeRef];
|
|
39
|
+
const style = window.getComputedStyle(node);
|
|
40
|
+
const boxSizing = style.getPropertyValue("box-sizing") || style.getPropertyValue("-moz-box-sizing") || style.getPropertyValue("-webkit-box-sizing");
|
|
41
|
+
const paddingSize = parseFloat(style.getPropertyValue("padding-bottom")) + parseFloat(style.getPropertyValue("padding-top"));
|
|
42
|
+
const borderSize = parseFloat(style.getPropertyValue("border-bottom-width")) + parseFloat(style.getPropertyValue("border-top-width"));
|
|
43
|
+
const nodeInfo = {
|
|
44
|
+
sizingStyle: SIZING_STYLE.map((name) => `${name}:${style.getPropertyValue(name)}`).join(";"),
|
|
45
|
+
paddingSize,
|
|
46
|
+
borderSize,
|
|
47
|
+
boxSizing
|
|
48
|
+
};
|
|
49
|
+
if (useCache && nodeRef) computedStyleCache[nodeRef] = nodeInfo;
|
|
50
|
+
return nodeInfo;
|
|
51
|
+
}
|
|
52
|
+
function calculateAutoSizeStyle(uiTextNode, useCache = false, minRows = null, maxRows = null) {
|
|
53
|
+
if (!hiddenTextarea) {
|
|
54
|
+
hiddenTextarea = document.createElement("textarea");
|
|
55
|
+
hiddenTextarea.setAttribute("tab-index", "-1");
|
|
56
|
+
hiddenTextarea.setAttribute("aria-hidden", "true");
|
|
57
|
+
hiddenTextarea.setAttribute("name", "hiddenTextarea");
|
|
58
|
+
document.body.appendChild(hiddenTextarea);
|
|
59
|
+
}
|
|
60
|
+
if (uiTextNode.getAttribute("wrap")) hiddenTextarea.setAttribute("wrap", uiTextNode.getAttribute("wrap"));
|
|
61
|
+
else hiddenTextarea.removeAttribute("wrap");
|
|
62
|
+
const { paddingSize, borderSize, boxSizing, sizingStyle } = calculateNodeStyling(uiTextNode, useCache);
|
|
63
|
+
hiddenTextarea.setAttribute("style", `${sizingStyle};${HIDDEN_TEXTAREA_STYLE}`);
|
|
64
|
+
hiddenTextarea.value = uiTextNode.value || uiTextNode.placeholder || "";
|
|
65
|
+
let minHeight;
|
|
66
|
+
let maxHeight;
|
|
67
|
+
let overflowY;
|
|
68
|
+
let height = hiddenTextarea.scrollHeight;
|
|
69
|
+
if (boxSizing === "border-box") height += borderSize;
|
|
70
|
+
else if (boxSizing === "content-box") height -= paddingSize;
|
|
71
|
+
if (minRows !== null || maxRows !== null) {
|
|
72
|
+
hiddenTextarea.value = " ";
|
|
73
|
+
const singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;
|
|
74
|
+
if (minRows !== null) {
|
|
75
|
+
minHeight = singleRowHeight * minRows;
|
|
76
|
+
if (boxSizing === "border-box") minHeight = minHeight + paddingSize + borderSize;
|
|
77
|
+
height = Math.max(minHeight, height);
|
|
78
|
+
}
|
|
79
|
+
if (maxRows !== null) {
|
|
80
|
+
maxHeight = singleRowHeight * maxRows;
|
|
81
|
+
if (boxSizing === "border-box") maxHeight = maxHeight + paddingSize + borderSize;
|
|
82
|
+
overflowY = height > maxHeight ? "" : "hidden";
|
|
83
|
+
height = Math.min(maxHeight, height);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const style = {
|
|
87
|
+
height: `${height}px`,
|
|
88
|
+
overflowY,
|
|
89
|
+
resize: "none"
|
|
90
|
+
};
|
|
91
|
+
if (minHeight) style.minHeight = `${minHeight}px`;
|
|
92
|
+
if (maxHeight) style.maxHeight = `${maxHeight}px`;
|
|
93
|
+
return style;
|
|
94
|
+
}
|
|
95
|
+
exports.calculateNodeStyling = calculateNodeStyling;
|
|
96
|
+
exports.default = calculateAutoSizeStyle;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CSSProperties } from 'vue';
|
|
2
|
+
export interface NodeType {
|
|
3
|
+
sizingStyle: string;
|
|
4
|
+
paddingSize: number;
|
|
5
|
+
borderSize: number;
|
|
6
|
+
boxSizing: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function calculateNodeStyling(node: HTMLElement, useCache?: boolean): NodeType;
|
|
9
|
+
export default function calculateAutoSizeStyle(uiTextNode: HTMLTextAreaElement, useCache?: boolean, minRows?: number | null, maxRows?: number | null): CSSProperties;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
var HIDDEN_TEXTAREA_STYLE = `
|
|
2
|
+
min-height:0 !important;
|
|
3
|
+
max-height:none !important;
|
|
4
|
+
height:0 !important;
|
|
5
|
+
visibility:hidden !important;
|
|
6
|
+
overflow:hidden !important;
|
|
7
|
+
position:absolute !important;
|
|
8
|
+
z-index:-1000 !important;
|
|
9
|
+
top:0 !important;
|
|
10
|
+
right:0 !important;
|
|
11
|
+
pointer-events: none !important;
|
|
12
|
+
`;
|
|
13
|
+
var SIZING_STYLE = [
|
|
14
|
+
"letter-spacing",
|
|
15
|
+
"line-height",
|
|
16
|
+
"padding-top",
|
|
17
|
+
"padding-bottom",
|
|
18
|
+
"font-family",
|
|
19
|
+
"font-weight",
|
|
20
|
+
"font-size",
|
|
21
|
+
"font-variant",
|
|
22
|
+
"text-rendering",
|
|
23
|
+
"text-transform",
|
|
24
|
+
"width",
|
|
25
|
+
"text-indent",
|
|
26
|
+
"padding-left",
|
|
27
|
+
"padding-right",
|
|
28
|
+
"border-width",
|
|
29
|
+
"box-sizing",
|
|
30
|
+
"word-break",
|
|
31
|
+
"white-space"
|
|
32
|
+
];
|
|
33
|
+
var computedStyleCache = {};
|
|
34
|
+
var hiddenTextarea;
|
|
35
|
+
function calculateNodeStyling(node, useCache = false) {
|
|
36
|
+
const nodeRef = node.getAttribute("id") || node.getAttribute("data-id") || node.getAttribute("name");
|
|
37
|
+
if (useCache && computedStyleCache[nodeRef]) return computedStyleCache[nodeRef];
|
|
38
|
+
const style = window.getComputedStyle(node);
|
|
39
|
+
const boxSizing = style.getPropertyValue("box-sizing") || style.getPropertyValue("-moz-box-sizing") || style.getPropertyValue("-webkit-box-sizing");
|
|
40
|
+
const paddingSize = parseFloat(style.getPropertyValue("padding-bottom")) + parseFloat(style.getPropertyValue("padding-top"));
|
|
41
|
+
const borderSize = parseFloat(style.getPropertyValue("border-bottom-width")) + parseFloat(style.getPropertyValue("border-top-width"));
|
|
42
|
+
const nodeInfo = {
|
|
43
|
+
sizingStyle: SIZING_STYLE.map((name) => `${name}:${style.getPropertyValue(name)}`).join(";"),
|
|
44
|
+
paddingSize,
|
|
45
|
+
borderSize,
|
|
46
|
+
boxSizing
|
|
47
|
+
};
|
|
48
|
+
if (useCache && nodeRef) computedStyleCache[nodeRef] = nodeInfo;
|
|
49
|
+
return nodeInfo;
|
|
50
|
+
}
|
|
51
|
+
function calculateAutoSizeStyle(uiTextNode, useCache = false, minRows = null, maxRows = null) {
|
|
52
|
+
if (!hiddenTextarea) {
|
|
53
|
+
hiddenTextarea = document.createElement("textarea");
|
|
54
|
+
hiddenTextarea.setAttribute("tab-index", "-1");
|
|
55
|
+
hiddenTextarea.setAttribute("aria-hidden", "true");
|
|
56
|
+
hiddenTextarea.setAttribute("name", "hiddenTextarea");
|
|
57
|
+
document.body.appendChild(hiddenTextarea);
|
|
58
|
+
}
|
|
59
|
+
if (uiTextNode.getAttribute("wrap")) hiddenTextarea.setAttribute("wrap", uiTextNode.getAttribute("wrap"));
|
|
60
|
+
else hiddenTextarea.removeAttribute("wrap");
|
|
61
|
+
const { paddingSize, borderSize, boxSizing, sizingStyle } = calculateNodeStyling(uiTextNode, useCache);
|
|
62
|
+
hiddenTextarea.setAttribute("style", `${sizingStyle};${HIDDEN_TEXTAREA_STYLE}`);
|
|
63
|
+
hiddenTextarea.value = uiTextNode.value || uiTextNode.placeholder || "";
|
|
64
|
+
let minHeight;
|
|
65
|
+
let maxHeight;
|
|
66
|
+
let overflowY;
|
|
67
|
+
let height = hiddenTextarea.scrollHeight;
|
|
68
|
+
if (boxSizing === "border-box") height += borderSize;
|
|
69
|
+
else if (boxSizing === "content-box") height -= paddingSize;
|
|
70
|
+
if (minRows !== null || maxRows !== null) {
|
|
71
|
+
hiddenTextarea.value = " ";
|
|
72
|
+
const singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;
|
|
73
|
+
if (minRows !== null) {
|
|
74
|
+
minHeight = singleRowHeight * minRows;
|
|
75
|
+
if (boxSizing === "border-box") minHeight = minHeight + paddingSize + borderSize;
|
|
76
|
+
height = Math.max(minHeight, height);
|
|
77
|
+
}
|
|
78
|
+
if (maxRows !== null) {
|
|
79
|
+
maxHeight = singleRowHeight * maxRows;
|
|
80
|
+
if (boxSizing === "border-box") maxHeight = maxHeight + paddingSize + borderSize;
|
|
81
|
+
overflowY = height > maxHeight ? "" : "hidden";
|
|
82
|
+
height = Math.min(maxHeight, height);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const style = {
|
|
86
|
+
height: `${height}px`,
|
|
87
|
+
overflowY,
|
|
88
|
+
resize: "none"
|
|
89
|
+
};
|
|
90
|
+
if (minHeight) style.minHeight = `${minHeight}px`;
|
|
91
|
+
if (maxHeight) style.maxHeight = `${maxHeight}px`;
|
|
92
|
+
return style;
|
|
93
|
+
}
|
|
94
|
+
export { calculateNodeStyling, calculateAutoSizeStyle as default };
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
+
const require_ResizableTextArea = require("./ResizableTextArea.cjs");
|
|
3
|
+
const require_TextArea = require("./TextArea.cjs");
|
|
4
|
+
var src_default = require_TextArea.default;
|
|
5
|
+
exports.ResizableTextArea = require_ResizableTextArea.default;
|
|
6
|
+
exports.default = src_default;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
File without changes
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { CountConfig, ShowCountFormatter } from '@v-c/input';
|
|
2
|
+
import { VueNode } from '@v-c/util/dist/type';
|
|
3
|
+
import { CSSProperties } from 'vue';
|
|
4
|
+
export interface AutoSizeType {
|
|
5
|
+
minRows?: number;
|
|
6
|
+
maxRows?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface TextAreaProps {
|
|
9
|
+
value?: string | number;
|
|
10
|
+
defaultValue?: string | number;
|
|
11
|
+
prefixCls?: string;
|
|
12
|
+
autoSize?: boolean | AutoSizeType;
|
|
13
|
+
onPressEnter?: (e: KeyboardEvent) => void;
|
|
14
|
+
onResize?: (size: {
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
}) => void;
|
|
18
|
+
onClear?: () => void;
|
|
19
|
+
readOnly?: boolean;
|
|
20
|
+
classNames?: {
|
|
21
|
+
affixWrapper?: string;
|
|
22
|
+
textarea?: string;
|
|
23
|
+
count?: string;
|
|
24
|
+
};
|
|
25
|
+
styles?: {
|
|
26
|
+
affixWrapper?: CSSProperties;
|
|
27
|
+
textarea?: CSSProperties;
|
|
28
|
+
count?: CSSProperties;
|
|
29
|
+
};
|
|
30
|
+
allowClear?: boolean | {
|
|
31
|
+
clearIcon?: VueNode;
|
|
32
|
+
};
|
|
33
|
+
showCount?: boolean | {
|
|
34
|
+
formatter: ShowCountFormatter;
|
|
35
|
+
};
|
|
36
|
+
count?: CountConfig;
|
|
37
|
+
maxLength?: number;
|
|
38
|
+
suffix?: VueNode;
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
hidden?: boolean;
|
|
41
|
+
onChange?: (e: Event) => void;
|
|
42
|
+
onFocus?: (e: FocusEvent) => void;
|
|
43
|
+
onBlur?: (e: FocusEvent) => void;
|
|
44
|
+
onCompositionStart?: (e: CompositionEvent) => void;
|
|
45
|
+
onCompositionEnd?: (e: CompositionEvent) => void;
|
|
46
|
+
onKeyDown?: (e: KeyboardEvent) => void;
|
|
47
|
+
className?: string;
|
|
48
|
+
class?: any;
|
|
49
|
+
style?: CSSProperties;
|
|
50
|
+
placeholder?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface TextAreaRef {
|
|
53
|
+
resizableTextArea?: any;
|
|
54
|
+
focus: () => void;
|
|
55
|
+
blur: () => void;
|
|
56
|
+
nativeElement: HTMLElement | null;
|
|
57
|
+
}
|
|
58
|
+
export type HTMLTextareaProps = HTMLTextAreaElement;
|
|
File without changes
|