@sytechui/input 2.4.33
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/README.md +26 -0
- package/dist/chunk-6SGLJYRO.mjs +442 -0
- package/dist/chunk-PPYXCOZH.mjs +105 -0
- package/dist/chunk-ZTVVBFTB.mjs +102 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +667 -0
- package/dist/index.mjs +15 -0
- package/dist/input.d.mts +11 -0
- package/dist/input.d.ts +11 -0
- package/dist/input.js +553 -0
- package/dist/input.mjs +8 -0
- package/dist/textarea.d.mts +44 -0
- package/dist/textarea.d.ts +44 -0
- package/dist/textarea.js +560 -0
- package/dist/textarea.mjs +8 -0
- package/dist/use-input.d.mts +105 -0
- package/dist/use-input.d.ts +105 -0
- package/dist/use-input.js +458 -0
- package/dist/use-input.mjs +7 -0
- package/package.json +65 -0
package/dist/input.d.mts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as _sytechui_system from '@sytechui/system';
|
|
2
|
+
import { UseInputProps } from './use-input.mjs';
|
|
3
|
+
import 'react';
|
|
4
|
+
import '@sytechui/theme';
|
|
5
|
+
import '@react-types/textfield';
|
|
6
|
+
|
|
7
|
+
interface InputProps extends Omit<UseInputProps, "isMultiline"> {
|
|
8
|
+
}
|
|
9
|
+
declare const Input: _sytechui_system.InternalForwardRefRenderFunction<"input", InputProps, never>;
|
|
10
|
+
|
|
11
|
+
export { type InputProps, Input as default };
|
package/dist/input.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as _sytechui_system from '@sytechui/system';
|
|
2
|
+
import { UseInputProps } from './use-input.js';
|
|
3
|
+
import 'react';
|
|
4
|
+
import '@sytechui/theme';
|
|
5
|
+
import '@react-types/textfield';
|
|
6
|
+
|
|
7
|
+
interface InputProps extends Omit<UseInputProps, "isMultiline"> {
|
|
8
|
+
}
|
|
9
|
+
declare const Input: _sytechui_system.InternalForwardRefRenderFunction<"input", InputProps, never>;
|
|
10
|
+
|
|
11
|
+
export { type InputProps, Input as default };
|
package/dist/input.js
ADDED
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/input.tsx
|
|
22
|
+
var input_exports = {};
|
|
23
|
+
__export(input_exports, {
|
|
24
|
+
default: () => input_default
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(input_exports);
|
|
27
|
+
var import_shared_icons = require("@sytechui/shared-icons");
|
|
28
|
+
var import_react2 = require("react");
|
|
29
|
+
var import_system2 = require("@sytechui/system");
|
|
30
|
+
|
|
31
|
+
// src/use-input.ts
|
|
32
|
+
var import_system = require("@sytechui/system");
|
|
33
|
+
var import_use_safe_layout_effect = require("@sytechui/use-safe-layout-effect");
|
|
34
|
+
var import_focus = require("@react-aria/focus");
|
|
35
|
+
var import_theme = require("@sytechui/theme");
|
|
36
|
+
var import_react_utils = require("@sytechui/react-utils");
|
|
37
|
+
var import_interactions = require("@react-aria/interactions");
|
|
38
|
+
var import_shared_utils = require("@sytechui/shared-utils");
|
|
39
|
+
var import_utils = require("@react-stately/utils");
|
|
40
|
+
var import_react = require("react");
|
|
41
|
+
var import_textfield = require("@react-aria/textfield");
|
|
42
|
+
var import_form = require("@sytechui/form");
|
|
43
|
+
function useInput(originalProps) {
|
|
44
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
45
|
+
const globalContext = (0, import_system.useProviderContext)();
|
|
46
|
+
const { validationBehavior: formValidationBehavior } = (0, import_form.useSlottedContext)(import_form.FormContext) || {};
|
|
47
|
+
const [props, variantProps] = (0, import_system.mapPropsVariants)(originalProps, import_theme.input.variantKeys);
|
|
48
|
+
const {
|
|
49
|
+
ref,
|
|
50
|
+
as,
|
|
51
|
+
type,
|
|
52
|
+
label,
|
|
53
|
+
baseRef,
|
|
54
|
+
wrapperRef,
|
|
55
|
+
description,
|
|
56
|
+
className,
|
|
57
|
+
classNames,
|
|
58
|
+
autoFocus,
|
|
59
|
+
startContent,
|
|
60
|
+
endContent,
|
|
61
|
+
onClear,
|
|
62
|
+
onChange,
|
|
63
|
+
validationState,
|
|
64
|
+
validationBehavior = (_a = formValidationBehavior != null ? formValidationBehavior : globalContext == null ? void 0 : globalContext.validationBehavior) != null ? _a : "native",
|
|
65
|
+
innerWrapperRef: innerWrapperRefProp,
|
|
66
|
+
onValueChange = () => {
|
|
67
|
+
},
|
|
68
|
+
...otherProps
|
|
69
|
+
} = props;
|
|
70
|
+
const handleValueChange = (0, import_react.useCallback)(
|
|
71
|
+
(value) => {
|
|
72
|
+
onValueChange(value != null ? value : "");
|
|
73
|
+
},
|
|
74
|
+
[onValueChange]
|
|
75
|
+
);
|
|
76
|
+
const [isFocusWithin, setFocusWithin] = (0, import_react.useState)(false);
|
|
77
|
+
const Component = as || "div";
|
|
78
|
+
const disableAnimation = (_c = (_b = originalProps.disableAnimation) != null ? _b : globalContext == null ? void 0 : globalContext.disableAnimation) != null ? _c : false;
|
|
79
|
+
const domRef = (0, import_react_utils.useDOMRef)(ref);
|
|
80
|
+
const baseDomRef = (0, import_react_utils.useDOMRef)(baseRef);
|
|
81
|
+
const inputWrapperRef = (0, import_react_utils.useDOMRef)(wrapperRef);
|
|
82
|
+
const innerWrapperRef = (0, import_react_utils.useDOMRef)(innerWrapperRefProp);
|
|
83
|
+
const [inputValue, setInputValue] = (0, import_utils.useControlledState)(
|
|
84
|
+
props.value,
|
|
85
|
+
(_d = props.defaultValue) != null ? _d : "",
|
|
86
|
+
handleValueChange
|
|
87
|
+
);
|
|
88
|
+
const isFileTypeInput = type === "file";
|
|
89
|
+
const hasUploadedFiles = ((_g = (_f = (_e = domRef == null ? void 0 : domRef.current) == null ? void 0 : _e.files) == null ? void 0 : _f.length) != null ? _g : 0) > 0;
|
|
90
|
+
const isFilledByDefault = ["date", "time", "month", "week", "range"].includes(type);
|
|
91
|
+
const isFilled = !(0, import_shared_utils.isEmpty)(inputValue) || isFilledByDefault || hasUploadedFiles;
|
|
92
|
+
const isFilledWithin = isFilled || isFocusWithin;
|
|
93
|
+
const isHiddenType = type === "hidden";
|
|
94
|
+
const isMultiline = originalProps.isMultiline;
|
|
95
|
+
const baseStyles = (0, import_theme.cn)(classNames == null ? void 0 : classNames.base, className, isFilled ? "is-filled" : "");
|
|
96
|
+
const handleClear = (0, import_react.useCallback)(() => {
|
|
97
|
+
var _a2;
|
|
98
|
+
if (isFileTypeInput) {
|
|
99
|
+
domRef.current.value = "";
|
|
100
|
+
} else {
|
|
101
|
+
setInputValue("");
|
|
102
|
+
}
|
|
103
|
+
onClear == null ? void 0 : onClear();
|
|
104
|
+
(_a2 = domRef.current) == null ? void 0 : _a2.focus();
|
|
105
|
+
}, [setInputValue, onClear, isFileTypeInput]);
|
|
106
|
+
(0, import_use_safe_layout_effect.useSafeLayoutEffect)(() => {
|
|
107
|
+
if (!domRef.current) return;
|
|
108
|
+
setInputValue(domRef.current.value);
|
|
109
|
+
}, [domRef.current]);
|
|
110
|
+
const {
|
|
111
|
+
labelProps,
|
|
112
|
+
inputProps,
|
|
113
|
+
isInvalid: isAriaInvalid,
|
|
114
|
+
validationErrors,
|
|
115
|
+
validationDetails,
|
|
116
|
+
descriptionProps,
|
|
117
|
+
errorMessageProps
|
|
118
|
+
} = (0, import_textfield.useTextField)(
|
|
119
|
+
{
|
|
120
|
+
...originalProps,
|
|
121
|
+
validationBehavior,
|
|
122
|
+
autoCapitalize: originalProps.autoCapitalize,
|
|
123
|
+
value: inputValue,
|
|
124
|
+
"aria-label": originalProps.label ? originalProps["aria-label"] : (0, import_shared_utils.safeAriaLabel)(originalProps["aria-label"], originalProps.placeholder),
|
|
125
|
+
inputElementType: isMultiline ? "textarea" : "input",
|
|
126
|
+
onChange: setInputValue
|
|
127
|
+
},
|
|
128
|
+
domRef
|
|
129
|
+
);
|
|
130
|
+
if (isFileTypeInput) {
|
|
131
|
+
delete inputProps.value;
|
|
132
|
+
delete inputProps.onChange;
|
|
133
|
+
}
|
|
134
|
+
const { isFocusVisible, isFocused, focusProps } = (0, import_focus.useFocusRing)({
|
|
135
|
+
autoFocus,
|
|
136
|
+
isTextInput: true
|
|
137
|
+
});
|
|
138
|
+
const { isHovered, hoverProps } = (0, import_interactions.useHover)({ isDisabled: !!(originalProps == null ? void 0 : originalProps.isDisabled) });
|
|
139
|
+
const { isHovered: isLabelHovered, hoverProps: labelHoverProps } = (0, import_interactions.useHover)({
|
|
140
|
+
isDisabled: !!(originalProps == null ? void 0 : originalProps.isDisabled)
|
|
141
|
+
});
|
|
142
|
+
const { focusProps: clearFocusProps, isFocusVisible: isClearButtonFocusVisible } = (0, import_focus.useFocusRing)();
|
|
143
|
+
const { focusWithinProps } = (0, import_interactions.useFocusWithin)({
|
|
144
|
+
onFocusWithinChange: setFocusWithin
|
|
145
|
+
});
|
|
146
|
+
const { pressProps: clearPressProps } = (0, import_interactions.usePress)({
|
|
147
|
+
isDisabled: !!(originalProps == null ? void 0 : originalProps.isDisabled) || !!(originalProps == null ? void 0 : originalProps.isReadOnly),
|
|
148
|
+
onPress: handleClear
|
|
149
|
+
});
|
|
150
|
+
const isInvalid = validationState === "invalid" || isAriaInvalid;
|
|
151
|
+
const labelPlacement = (0, import_system.useLabelPlacement)({
|
|
152
|
+
labelPlacement: originalProps.labelPlacement,
|
|
153
|
+
label
|
|
154
|
+
});
|
|
155
|
+
const errorMessage = typeof props.errorMessage === "function" ? props.errorMessage({ isInvalid, validationErrors, validationDetails }) : props.errorMessage || (validationErrors == null ? void 0 : validationErrors.join(" "));
|
|
156
|
+
const isClearable = !!onClear || originalProps.isClearable;
|
|
157
|
+
const hasElements = !!label || !!description || !!errorMessage;
|
|
158
|
+
const hasPlaceholder = !!props.placeholder;
|
|
159
|
+
const hasLabel = !!label;
|
|
160
|
+
const hasHelper = !!description || !!errorMessage;
|
|
161
|
+
const isOutsideLeft = labelPlacement === "outside-left";
|
|
162
|
+
const isOutsideTop = labelPlacement === "outside-top";
|
|
163
|
+
const shouldLabelBeOutside = (
|
|
164
|
+
// label is outside only when some placeholder is there
|
|
165
|
+
labelPlacement === "outside" || // label is outside regardless of placeholder
|
|
166
|
+
isOutsideLeft || isOutsideTop
|
|
167
|
+
);
|
|
168
|
+
const shouldLabelBeInside = labelPlacement === "inside";
|
|
169
|
+
const isPlaceholderShown = domRef.current ? (!domRef.current.value || domRef.current.value === "" || !inputValue || inputValue === "") && hasPlaceholder : false;
|
|
170
|
+
const hasStartContent = !!startContent;
|
|
171
|
+
const isLabelOutside = shouldLabelBeOutside ? isOutsideLeft || isOutsideTop || hasPlaceholder || labelPlacement === "outside" && hasStartContent : false;
|
|
172
|
+
const isLabelOutsideAsPlaceholder = labelPlacement === "outside" && !hasPlaceholder && !hasStartContent;
|
|
173
|
+
const slots = (0, import_react.useMemo)(
|
|
174
|
+
() => (0, import_theme.input)({
|
|
175
|
+
...variantProps,
|
|
176
|
+
isInvalid,
|
|
177
|
+
labelPlacement,
|
|
178
|
+
isClearable,
|
|
179
|
+
disableAnimation
|
|
180
|
+
}),
|
|
181
|
+
[
|
|
182
|
+
(0, import_shared_utils.objectToDeps)(variantProps),
|
|
183
|
+
isInvalid,
|
|
184
|
+
labelPlacement,
|
|
185
|
+
isClearable,
|
|
186
|
+
hasStartContent,
|
|
187
|
+
disableAnimation
|
|
188
|
+
]
|
|
189
|
+
);
|
|
190
|
+
const getBaseProps = (0, import_react.useCallback)(
|
|
191
|
+
(props2 = {}) => {
|
|
192
|
+
return {
|
|
193
|
+
ref: baseDomRef,
|
|
194
|
+
className: slots.base({ class: baseStyles }),
|
|
195
|
+
"data-slot": "base",
|
|
196
|
+
"data-filled": (0, import_shared_utils.dataAttr)(
|
|
197
|
+
isFilled || hasPlaceholder || hasStartContent || isPlaceholderShown || isFileTypeInput
|
|
198
|
+
),
|
|
199
|
+
"data-filled-within": (0, import_shared_utils.dataAttr)(
|
|
200
|
+
isFilledWithin || hasPlaceholder || hasStartContent || isPlaceholderShown || isFileTypeInput
|
|
201
|
+
),
|
|
202
|
+
"data-focus-within": (0, import_shared_utils.dataAttr)(isFocusWithin),
|
|
203
|
+
"data-focus-visible": (0, import_shared_utils.dataAttr)(isFocusVisible),
|
|
204
|
+
"data-readonly": (0, import_shared_utils.dataAttr)(originalProps.isReadOnly),
|
|
205
|
+
"data-focus": (0, import_shared_utils.dataAttr)(isFocused),
|
|
206
|
+
"data-hover": (0, import_shared_utils.dataAttr)(isHovered || isLabelHovered),
|
|
207
|
+
"data-required": (0, import_shared_utils.dataAttr)(originalProps.isRequired),
|
|
208
|
+
"data-invalid": (0, import_shared_utils.dataAttr)(isInvalid),
|
|
209
|
+
"data-disabled": (0, import_shared_utils.dataAttr)(originalProps.isDisabled),
|
|
210
|
+
"data-has-elements": (0, import_shared_utils.dataAttr)(hasElements),
|
|
211
|
+
"data-has-helper": (0, import_shared_utils.dataAttr)(hasHelper),
|
|
212
|
+
"data-has-label": (0, import_shared_utils.dataAttr)(hasLabel),
|
|
213
|
+
"data-has-value": (0, import_shared_utils.dataAttr)(!isPlaceholderShown),
|
|
214
|
+
"data-hidden": (0, import_shared_utils.dataAttr)(isHiddenType),
|
|
215
|
+
...focusWithinProps,
|
|
216
|
+
...props2
|
|
217
|
+
};
|
|
218
|
+
},
|
|
219
|
+
[
|
|
220
|
+
slots,
|
|
221
|
+
baseStyles,
|
|
222
|
+
isFilled,
|
|
223
|
+
isFocused,
|
|
224
|
+
isHovered,
|
|
225
|
+
isLabelHovered,
|
|
226
|
+
isInvalid,
|
|
227
|
+
hasHelper,
|
|
228
|
+
hasLabel,
|
|
229
|
+
hasElements,
|
|
230
|
+
isPlaceholderShown,
|
|
231
|
+
hasStartContent,
|
|
232
|
+
isFocusWithin,
|
|
233
|
+
isFocusVisible,
|
|
234
|
+
isFilledWithin,
|
|
235
|
+
hasPlaceholder,
|
|
236
|
+
focusWithinProps,
|
|
237
|
+
isHiddenType,
|
|
238
|
+
originalProps.isReadOnly,
|
|
239
|
+
originalProps.isRequired,
|
|
240
|
+
originalProps.isDisabled
|
|
241
|
+
]
|
|
242
|
+
);
|
|
243
|
+
const getLabelProps = (0, import_react.useCallback)(
|
|
244
|
+
(props2 = {}) => {
|
|
245
|
+
return {
|
|
246
|
+
"data-slot": "label",
|
|
247
|
+
className: slots.label({ class: classNames == null ? void 0 : classNames.label }),
|
|
248
|
+
...(0, import_shared_utils.mergeProps)(labelProps, labelHoverProps, props2)
|
|
249
|
+
};
|
|
250
|
+
},
|
|
251
|
+
[slots, isLabelHovered, labelProps, classNames == null ? void 0 : classNames.label]
|
|
252
|
+
);
|
|
253
|
+
const handleKeyDown = (0, import_react.useCallback)(
|
|
254
|
+
(e) => {
|
|
255
|
+
if (e.key === "Escape" && inputValue && (isClearable || onClear) && !originalProps.isReadOnly) {
|
|
256
|
+
setInputValue("");
|
|
257
|
+
onClear == null ? void 0 : onClear();
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
[inputValue, setInputValue, onClear, isClearable, originalProps.isReadOnly]
|
|
261
|
+
);
|
|
262
|
+
const getInputProps = (0, import_react.useCallback)(
|
|
263
|
+
(props2 = {}) => {
|
|
264
|
+
return {
|
|
265
|
+
"data-slot": "input",
|
|
266
|
+
"data-filled": (0, import_shared_utils.dataAttr)(isFilled),
|
|
267
|
+
"data-filled-within": (0, import_shared_utils.dataAttr)(isFilledWithin),
|
|
268
|
+
"data-has-start-content": (0, import_shared_utils.dataAttr)(hasStartContent),
|
|
269
|
+
"data-has-end-content": (0, import_shared_utils.dataAttr)(!!endContent),
|
|
270
|
+
"data-type": type,
|
|
271
|
+
className: slots.input({
|
|
272
|
+
class: (0, import_theme.cn)(
|
|
273
|
+
classNames == null ? void 0 : classNames.input,
|
|
274
|
+
isFilled ? "is-filled" : "",
|
|
275
|
+
isMultiline ? "pe-0" : "",
|
|
276
|
+
type === "password" ? "[&::-ms-reveal]:hidden" : ""
|
|
277
|
+
)
|
|
278
|
+
}),
|
|
279
|
+
...(0, import_shared_utils.mergeProps)(
|
|
280
|
+
focusProps,
|
|
281
|
+
inputProps,
|
|
282
|
+
(0, import_react_utils.filterDOMProps)(otherProps, {
|
|
283
|
+
enabled: true,
|
|
284
|
+
labelable: true,
|
|
285
|
+
omitEventNames: new Set(Object.keys(inputProps))
|
|
286
|
+
}),
|
|
287
|
+
props2
|
|
288
|
+
),
|
|
289
|
+
"aria-readonly": (0, import_shared_utils.dataAttr)(originalProps.isReadOnly),
|
|
290
|
+
onChange: (0, import_shared_utils.chain)(inputProps.onChange, onChange),
|
|
291
|
+
onKeyDown: (0, import_shared_utils.chain)(inputProps.onKeyDown, props2.onKeyDown, handleKeyDown),
|
|
292
|
+
ref: domRef
|
|
293
|
+
};
|
|
294
|
+
},
|
|
295
|
+
[
|
|
296
|
+
slots,
|
|
297
|
+
inputValue,
|
|
298
|
+
focusProps,
|
|
299
|
+
inputProps,
|
|
300
|
+
otherProps,
|
|
301
|
+
isFilled,
|
|
302
|
+
isFilledWithin,
|
|
303
|
+
hasStartContent,
|
|
304
|
+
endContent,
|
|
305
|
+
classNames == null ? void 0 : classNames.input,
|
|
306
|
+
originalProps.isReadOnly,
|
|
307
|
+
originalProps.isRequired,
|
|
308
|
+
onChange,
|
|
309
|
+
handleKeyDown
|
|
310
|
+
]
|
|
311
|
+
);
|
|
312
|
+
const getInputWrapperProps = (0, import_react.useCallback)(
|
|
313
|
+
(props2 = {}) => {
|
|
314
|
+
return {
|
|
315
|
+
ref: inputWrapperRef,
|
|
316
|
+
"data-slot": "input-wrapper",
|
|
317
|
+
"data-hover": (0, import_shared_utils.dataAttr)(isHovered || isLabelHovered),
|
|
318
|
+
"data-focus-visible": (0, import_shared_utils.dataAttr)(isFocusVisible),
|
|
319
|
+
"data-focus": (0, import_shared_utils.dataAttr)(isFocused),
|
|
320
|
+
className: slots.inputWrapper({
|
|
321
|
+
class: (0, import_theme.cn)(classNames == null ? void 0 : classNames.inputWrapper, isFilled ? "is-filled" : "")
|
|
322
|
+
}),
|
|
323
|
+
...(0, import_shared_utils.mergeProps)(props2, hoverProps),
|
|
324
|
+
onClick: (e) => {
|
|
325
|
+
if (domRef.current && e.currentTarget === e.target) {
|
|
326
|
+
domRef.current.focus();
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
style: {
|
|
330
|
+
cursor: "text",
|
|
331
|
+
...props2.style
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
},
|
|
335
|
+
[
|
|
336
|
+
slots,
|
|
337
|
+
isHovered,
|
|
338
|
+
isLabelHovered,
|
|
339
|
+
isFocusVisible,
|
|
340
|
+
isFocused,
|
|
341
|
+
inputValue,
|
|
342
|
+
classNames == null ? void 0 : classNames.inputWrapper
|
|
343
|
+
]
|
|
344
|
+
);
|
|
345
|
+
const getInnerWrapperProps = (0, import_react.useCallback)(
|
|
346
|
+
(props2 = {}) => {
|
|
347
|
+
return {
|
|
348
|
+
...props2,
|
|
349
|
+
ref: innerWrapperRef,
|
|
350
|
+
"data-slot": "inner-wrapper",
|
|
351
|
+
onClick: (e) => {
|
|
352
|
+
if (domRef.current && e.currentTarget === e.target) {
|
|
353
|
+
domRef.current.focus();
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
className: slots.innerWrapper({
|
|
357
|
+
class: (0, import_theme.cn)(classNames == null ? void 0 : classNames.innerWrapper, props2 == null ? void 0 : props2.className)
|
|
358
|
+
})
|
|
359
|
+
};
|
|
360
|
+
},
|
|
361
|
+
[slots, classNames == null ? void 0 : classNames.innerWrapper]
|
|
362
|
+
);
|
|
363
|
+
const getMainWrapperProps = (0, import_react.useCallback)(
|
|
364
|
+
(props2 = {}) => {
|
|
365
|
+
return {
|
|
366
|
+
...props2,
|
|
367
|
+
"data-slot": "main-wrapper",
|
|
368
|
+
className: slots.mainWrapper({
|
|
369
|
+
class: (0, import_theme.cn)(classNames == null ? void 0 : classNames.mainWrapper, props2 == null ? void 0 : props2.className)
|
|
370
|
+
})
|
|
371
|
+
};
|
|
372
|
+
},
|
|
373
|
+
[slots, classNames == null ? void 0 : classNames.mainWrapper]
|
|
374
|
+
);
|
|
375
|
+
const getHelperWrapperProps = (0, import_react.useCallback)(
|
|
376
|
+
(props2 = {}) => {
|
|
377
|
+
return {
|
|
378
|
+
...props2,
|
|
379
|
+
"data-slot": "helper-wrapper",
|
|
380
|
+
className: slots.helperWrapper({
|
|
381
|
+
class: (0, import_theme.cn)(classNames == null ? void 0 : classNames.helperWrapper, props2 == null ? void 0 : props2.className)
|
|
382
|
+
})
|
|
383
|
+
};
|
|
384
|
+
},
|
|
385
|
+
[slots, classNames == null ? void 0 : classNames.helperWrapper]
|
|
386
|
+
);
|
|
387
|
+
const getDescriptionProps = (0, import_react.useCallback)(
|
|
388
|
+
(props2 = {}) => {
|
|
389
|
+
return {
|
|
390
|
+
...props2,
|
|
391
|
+
...descriptionProps,
|
|
392
|
+
"data-slot": "description",
|
|
393
|
+
className: slots.description({ class: (0, import_theme.cn)(classNames == null ? void 0 : classNames.description, props2 == null ? void 0 : props2.className) })
|
|
394
|
+
};
|
|
395
|
+
},
|
|
396
|
+
[slots, classNames == null ? void 0 : classNames.description]
|
|
397
|
+
);
|
|
398
|
+
const getErrorMessageProps = (0, import_react.useCallback)(
|
|
399
|
+
(props2 = {}) => {
|
|
400
|
+
return {
|
|
401
|
+
...props2,
|
|
402
|
+
...errorMessageProps,
|
|
403
|
+
"data-slot": "error-message",
|
|
404
|
+
className: slots.errorMessage({ class: (0, import_theme.cn)(classNames == null ? void 0 : classNames.errorMessage, props2 == null ? void 0 : props2.className) })
|
|
405
|
+
};
|
|
406
|
+
},
|
|
407
|
+
[slots, errorMessageProps, classNames == null ? void 0 : classNames.errorMessage]
|
|
408
|
+
);
|
|
409
|
+
const getClearButtonProps = (0, import_react.useCallback)(
|
|
410
|
+
(props2 = {}) => {
|
|
411
|
+
return {
|
|
412
|
+
...props2,
|
|
413
|
+
type: "button",
|
|
414
|
+
tabIndex: -1,
|
|
415
|
+
disabled: originalProps.isDisabled,
|
|
416
|
+
"aria-label": "clear input",
|
|
417
|
+
"data-slot": "clear-button",
|
|
418
|
+
"data-focus-visible": (0, import_shared_utils.dataAttr)(isClearButtonFocusVisible),
|
|
419
|
+
className: slots.clearButton({
|
|
420
|
+
class: (0, import_theme.cn)(classNames == null ? void 0 : classNames.clearButton, props2 == null ? void 0 : props2.className)
|
|
421
|
+
}),
|
|
422
|
+
...(0, import_shared_utils.mergeProps)(clearPressProps, clearFocusProps)
|
|
423
|
+
};
|
|
424
|
+
},
|
|
425
|
+
[slots, isClearButtonFocusVisible, clearPressProps, clearFocusProps, classNames == null ? void 0 : classNames.clearButton]
|
|
426
|
+
);
|
|
427
|
+
return {
|
|
428
|
+
Component,
|
|
429
|
+
classNames,
|
|
430
|
+
domRef,
|
|
431
|
+
label,
|
|
432
|
+
description,
|
|
433
|
+
startContent,
|
|
434
|
+
endContent,
|
|
435
|
+
labelPlacement,
|
|
436
|
+
isClearable,
|
|
437
|
+
hasHelper,
|
|
438
|
+
hasStartContent,
|
|
439
|
+
isLabelOutside,
|
|
440
|
+
isOutsideLeft,
|
|
441
|
+
isOutsideTop,
|
|
442
|
+
isLabelOutsideAsPlaceholder,
|
|
443
|
+
shouldLabelBeOutside,
|
|
444
|
+
shouldLabelBeInside,
|
|
445
|
+
hasPlaceholder,
|
|
446
|
+
isInvalid,
|
|
447
|
+
errorMessage,
|
|
448
|
+
getBaseProps,
|
|
449
|
+
getLabelProps,
|
|
450
|
+
getInputProps,
|
|
451
|
+
getMainWrapperProps,
|
|
452
|
+
getInputWrapperProps,
|
|
453
|
+
getInnerWrapperProps,
|
|
454
|
+
getHelperWrapperProps,
|
|
455
|
+
getDescriptionProps,
|
|
456
|
+
getErrorMessageProps,
|
|
457
|
+
getClearButtonProps
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// src/input.tsx
|
|
462
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
463
|
+
var Input = (0, import_system2.forwardRef)((props, ref) => {
|
|
464
|
+
const {
|
|
465
|
+
Component,
|
|
466
|
+
label,
|
|
467
|
+
description,
|
|
468
|
+
isClearable,
|
|
469
|
+
startContent,
|
|
470
|
+
endContent,
|
|
471
|
+
labelPlacement,
|
|
472
|
+
hasHelper,
|
|
473
|
+
isOutsideLeft,
|
|
474
|
+
isOutsideTop,
|
|
475
|
+
shouldLabelBeOutside,
|
|
476
|
+
errorMessage,
|
|
477
|
+
isInvalid,
|
|
478
|
+
getBaseProps,
|
|
479
|
+
getLabelProps,
|
|
480
|
+
getInputProps,
|
|
481
|
+
getInnerWrapperProps,
|
|
482
|
+
getInputWrapperProps,
|
|
483
|
+
getMainWrapperProps,
|
|
484
|
+
getHelperWrapperProps,
|
|
485
|
+
getDescriptionProps,
|
|
486
|
+
getErrorMessageProps,
|
|
487
|
+
getClearButtonProps
|
|
488
|
+
} = useInput({ ...props, ref });
|
|
489
|
+
const labelContent = label ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { ...getLabelProps(), children: label }) : null;
|
|
490
|
+
const end = (0, import_react2.useMemo)(() => {
|
|
491
|
+
if (isClearable) {
|
|
492
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { ...getClearButtonProps(), children: endContent || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_shared_icons.CloseFilledIcon, {}) });
|
|
493
|
+
}
|
|
494
|
+
return endContent;
|
|
495
|
+
}, [isClearable, getClearButtonProps]);
|
|
496
|
+
const helperWrapper = (0, import_react2.useMemo)(() => {
|
|
497
|
+
const shouldShowError = isInvalid && errorMessage;
|
|
498
|
+
const hasContent = shouldShowError || description;
|
|
499
|
+
if (!hasHelper || !hasContent) return null;
|
|
500
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...getHelperWrapperProps(), children: shouldShowError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...getErrorMessageProps(), children: errorMessage }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...getDescriptionProps(), children: description }) });
|
|
501
|
+
}, [
|
|
502
|
+
hasHelper,
|
|
503
|
+
isInvalid,
|
|
504
|
+
errorMessage,
|
|
505
|
+
description,
|
|
506
|
+
getHelperWrapperProps,
|
|
507
|
+
getErrorMessageProps,
|
|
508
|
+
getDescriptionProps
|
|
509
|
+
]);
|
|
510
|
+
const innerWrapper = (0, import_react2.useMemo)(() => {
|
|
511
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ...getInnerWrapperProps(), children: [
|
|
512
|
+
startContent,
|
|
513
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { ...getInputProps() }),
|
|
514
|
+
end
|
|
515
|
+
] });
|
|
516
|
+
}, [startContent, end, getInputProps, getInnerWrapperProps]);
|
|
517
|
+
const mainWrapper = (0, import_react2.useMemo)(() => {
|
|
518
|
+
if (shouldLabelBeOutside) {
|
|
519
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ...getMainWrapperProps(), children: [
|
|
520
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ...getInputWrapperProps(), children: [
|
|
521
|
+
!isOutsideLeft && !isOutsideTop ? labelContent : null,
|
|
522
|
+
innerWrapper
|
|
523
|
+
] }),
|
|
524
|
+
helperWrapper
|
|
525
|
+
] });
|
|
526
|
+
}
|
|
527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
528
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ...getInputWrapperProps(), children: [
|
|
529
|
+
labelContent,
|
|
530
|
+
innerWrapper
|
|
531
|
+
] }),
|
|
532
|
+
helperWrapper
|
|
533
|
+
] });
|
|
534
|
+
}, [
|
|
535
|
+
labelPlacement,
|
|
536
|
+
helperWrapper,
|
|
537
|
+
shouldLabelBeOutside,
|
|
538
|
+
labelContent,
|
|
539
|
+
innerWrapper,
|
|
540
|
+
errorMessage,
|
|
541
|
+
description,
|
|
542
|
+
getMainWrapperProps,
|
|
543
|
+
getInputWrapperProps,
|
|
544
|
+
getErrorMessageProps,
|
|
545
|
+
getDescriptionProps
|
|
546
|
+
]);
|
|
547
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Component, { ...getBaseProps(), children: [
|
|
548
|
+
isOutsideLeft || isOutsideTop ? labelContent : null,
|
|
549
|
+
mainWrapper
|
|
550
|
+
] });
|
|
551
|
+
});
|
|
552
|
+
Input.displayName = "HeroUI.Input";
|
|
553
|
+
var input_default = Input;
|
package/dist/input.mjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as _sytechui_system from '@sytechui/system';
|
|
2
|
+
import { UseInputProps } from './use-input.mjs';
|
|
3
|
+
import 'react';
|
|
4
|
+
import '@sytechui/theme';
|
|
5
|
+
import '@react-types/textfield';
|
|
6
|
+
|
|
7
|
+
type OmittedInputProps = "isClearButtonFocusVisible" | "isLabelPlaceholder" | "isTextarea";
|
|
8
|
+
type TextareaHeightChangeMeta = {
|
|
9
|
+
rowHeight: number;
|
|
10
|
+
};
|
|
11
|
+
interface TextAreaProps extends Omit<UseInputProps<HTMLTextAreaElement>, OmittedInputProps> {
|
|
12
|
+
/**
|
|
13
|
+
* Whether the textarea should automatically grow vertically to accommodate content.
|
|
14
|
+
* @default false
|
|
15
|
+
*/
|
|
16
|
+
disableAutosize?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Minimum number of rows to show for textarea
|
|
19
|
+
* @default 3
|
|
20
|
+
*/
|
|
21
|
+
minRows?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Maximum number of rows up to which the textarea can grow
|
|
24
|
+
* @default 8
|
|
25
|
+
*/
|
|
26
|
+
maxRows?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Reuse previously computed measurements when computing height of textarea.
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
cacheMeasurements?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Function invoked on textarea height change, with height as first argument.
|
|
34
|
+
* The second function argument is an object containing additional information that
|
|
35
|
+
* might be useful for custom behaviors. Current options include `{ rowHeight: number }`.
|
|
36
|
+
*
|
|
37
|
+
* @param height - The height of the textarea
|
|
38
|
+
* @param meta - Additional information about the height change
|
|
39
|
+
*/
|
|
40
|
+
onHeightChange?: (height: number, meta: TextareaHeightChangeMeta) => void;
|
|
41
|
+
}
|
|
42
|
+
declare const Textarea: _sytechui_system.InternalForwardRefRenderFunction<"textarea", TextAreaProps, never>;
|
|
43
|
+
|
|
44
|
+
export { type TextAreaProps, type TextareaHeightChangeMeta, Textarea as default };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as _sytechui_system from '@sytechui/system';
|
|
2
|
+
import { UseInputProps } from './use-input.js';
|
|
3
|
+
import 'react';
|
|
4
|
+
import '@sytechui/theme';
|
|
5
|
+
import '@react-types/textfield';
|
|
6
|
+
|
|
7
|
+
type OmittedInputProps = "isClearButtonFocusVisible" | "isLabelPlaceholder" | "isTextarea";
|
|
8
|
+
type TextareaHeightChangeMeta = {
|
|
9
|
+
rowHeight: number;
|
|
10
|
+
};
|
|
11
|
+
interface TextAreaProps extends Omit<UseInputProps<HTMLTextAreaElement>, OmittedInputProps> {
|
|
12
|
+
/**
|
|
13
|
+
* Whether the textarea should automatically grow vertically to accommodate content.
|
|
14
|
+
* @default false
|
|
15
|
+
*/
|
|
16
|
+
disableAutosize?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Minimum number of rows to show for textarea
|
|
19
|
+
* @default 3
|
|
20
|
+
*/
|
|
21
|
+
minRows?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Maximum number of rows up to which the textarea can grow
|
|
24
|
+
* @default 8
|
|
25
|
+
*/
|
|
26
|
+
maxRows?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Reuse previously computed measurements when computing height of textarea.
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
cacheMeasurements?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Function invoked on textarea height change, with height as first argument.
|
|
34
|
+
* The second function argument is an object containing additional information that
|
|
35
|
+
* might be useful for custom behaviors. Current options include `{ rowHeight: number }`.
|
|
36
|
+
*
|
|
37
|
+
* @param height - The height of the textarea
|
|
38
|
+
* @param meta - Additional information about the height change
|
|
39
|
+
*/
|
|
40
|
+
onHeightChange?: (height: number, meta: TextareaHeightChangeMeta) => void;
|
|
41
|
+
}
|
|
42
|
+
declare const Textarea: _sytechui_system.InternalForwardRefRenderFunction<"textarea", TextAreaProps, never>;
|
|
43
|
+
|
|
44
|
+
export { type TextAreaProps, type TextareaHeightChangeMeta, Textarea as default };
|