@plexui/ui 0.7.87 → 0.7.89
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/dist/es/components/FloatingLabelInput/FloatingLabelInput.js +5 -6
- package/dist/es/components/FloatingLabelInput/FloatingLabelInput.js.map +1 -1
- package/dist/es/components/FloatingLabelInput/FloatingLabelInput.module.css +12 -4
- package/dist/types/components/FloatingLabelInput/FloatingLabelInput.d.ts +10 -0
- package/package.json +1 -1
|
@@ -3,15 +3,15 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import clsx from "clsx";
|
|
4
4
|
import { forwardRef, useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
|
|
5
5
|
import { mergeRefs } from "react-merge-refs";
|
|
6
|
-
import { FieldError } from "../FieldError";
|
|
7
6
|
import { X } from "../Icon";
|
|
8
7
|
import s from "./FloatingLabelInput.module.css";
|
|
9
8
|
export const FloatingLabelInput = forwardRef(function FloatingLabelInput(props, ref) {
|
|
10
|
-
const { label, errorMessage, "invalid": invalidProp, disabled = false, readOnly = false, onClear, onAutofill, allowAutofillExtensions = false, startAdornment, endAdornment, multiline = false, rows = 2, className, "id": idProp, name, type = "text", value, defaultValue, onChange, onFocus, onBlur, onAnimationStart, "aria-describedby": ariaDescribedByProp, ...restProps } = props;
|
|
9
|
+
const { label, description, errorMessage, "invalid": invalidProp, disabled = false, readOnly = false, onClear, onAutofill, allowAutofillExtensions = false, startAdornment, endAdornment, multiline = false, rows = 2, className, "id": idProp, name, type = "text", value, defaultValue, onChange, onFocus, onBlur, onAnimationStart, "aria-describedby": ariaDescribedByProp, ...restProps } = props;
|
|
11
10
|
const inputRef = useRef(null);
|
|
12
11
|
const generatedId = useId();
|
|
13
12
|
const inputId = idProp || `floating-label-input-${generatedId}`;
|
|
14
|
-
const
|
|
13
|
+
const descriptionId = description ? `${inputId}-description` : undefined;
|
|
14
|
+
const errorId = errorMessage ? `${inputId}-error` : undefined;
|
|
15
15
|
const [focused, setFocused] = useState(false);
|
|
16
16
|
const [hasValue, setHasValue] = useState(() => {
|
|
17
17
|
return !!(value !== undefined ? value : defaultValue);
|
|
@@ -34,8 +34,7 @@ export const FloatingLabelInput = forwardRef(function FloatingLabelInput(props,
|
|
|
34
34
|
// Determine if clear button should be shown
|
|
35
35
|
const showClearButton = !!onClear && hasValue && !disabled && !readOnly;
|
|
36
36
|
// Merge aria-describedby with error id
|
|
37
|
-
const ariaDescribedBy = [ariaDescribedByProp,
|
|
38
|
-
undefined;
|
|
37
|
+
const ariaDescribedBy = [ariaDescribedByProp, errorId, descriptionId].filter(Boolean).join(" ") || undefined;
|
|
39
38
|
// Handle clicks on the container to focus the input
|
|
40
39
|
const handleContainerMouseDown = useCallback((evt) => {
|
|
41
40
|
const input = inputRef.current;
|
|
@@ -78,7 +77,7 @@ export const FloatingLabelInput = forwardRef(function FloatingLabelInput(props,
|
|
|
78
77
|
}, [onAnimationStart, onAutofill]);
|
|
79
78
|
return (_jsxs("div", { className: clsx(s.Root, className), children: [_jsxs("div", { className: clsx(s.FieldFootprint, {
|
|
80
79
|
[s.HasValue]: hasValue || !!startAdornment,
|
|
81
|
-
}), "data-focused": focused ? "" : undefined, "data-has-value": hasValue ? "" : undefined, "data-invalid": invalid ? "" : undefined, "data-disabled": disabled ? "" : undefined, "data-readonly": readOnly ? "" : undefined, "data-multiline": multiline ? "" : undefined, onMouseDown: handleContainerMouseDown, children: [_jsx("label", { className: s.TypeableLabel, htmlFor: inputId, children: _jsx("div", { className: s.LabelPositioner, children: _jsx("div", { className: s.LabelText, children: label }) }) }), startAdornment && (_jsx("div", { className: s.StartAdornment, children: startAdornment })), multiline ? (_jsx("textarea", { ref: mergeRefs([ref, inputRef]), id: inputId, name: name, rows: rows, className: s.Textarea, value: value, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, "aria-invalid": invalid ? true : undefined, "aria-describedby": ariaDescribedBy, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur })) : (_jsx("input", { ...restProps, ref: mergeRefs([ref, inputRef]), id: inputId, name: name, type: type, className: s.Input, value: value, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, "aria-invalid": invalid ? true : undefined, "aria-describedby": ariaDescribedBy, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, onAnimationStart: handleAnimationStart, "data-lpignore": allowAutofillExtensions ? undefined : true, "data-1p-ignore": allowAutofillExtensions ? undefined : true })), endAdornment && (_jsx("div", { className: s.EndAdornment, children: endAdornment })), showClearButton && (_jsx("button", { type: "button", "aria-label": "Clear input", className: s.ClearButton, onClick: onClear, children: _jsx(X, {}) }))] }), errorMessage && (_jsx(
|
|
80
|
+
}), "data-focused": focused ? "" : undefined, "data-has-value": hasValue ? "" : undefined, "data-invalid": invalid ? "" : undefined, "data-disabled": disabled ? "" : undefined, "data-readonly": readOnly ? "" : undefined, "data-multiline": multiline ? "" : undefined, onMouseDown: handleContainerMouseDown, children: [_jsx("label", { className: s.TypeableLabel, htmlFor: inputId, children: _jsx("div", { className: s.LabelPositioner, children: _jsx("div", { className: s.LabelText, children: label }) }) }), startAdornment && (_jsx("div", { className: s.StartAdornment, children: startAdornment })), multiline ? (_jsx("textarea", { ref: mergeRefs([ref, inputRef]), id: inputId, name: name, rows: rows, className: s.Textarea, value: value, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, "aria-invalid": invalid ? true : undefined, "aria-describedby": ariaDescribedBy, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur })) : (_jsx("input", { ...restProps, ref: mergeRefs([ref, inputRef]), id: inputId, name: name, type: type, className: s.Input, value: value, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, "aria-invalid": invalid ? true : undefined, "aria-describedby": ariaDescribedBy, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, onAnimationStart: handleAnimationStart, "data-lpignore": allowAutofillExtensions ? undefined : true, "data-1p-ignore": allowAutofillExtensions ? undefined : true })), endAdornment && (_jsx("div", { className: s.EndAdornment, children: endAdornment })), showClearButton && (_jsx("button", { type: "button", "aria-label": "Clear input", className: s.ClearButton, onClick: onClear, children: _jsx(X, {}) }))] }), errorMessage && (_jsx("div", { id: errorId, className: s.ErrorMessage, role: "alert", children: errorMessage })), description && (_jsx("div", { id: descriptionId, className: s.Description, children: description }))] }));
|
|
82
81
|
});
|
|
83
82
|
FloatingLabelInput.displayName = "FloatingLabelInput";
|
|
84
83
|
//# sourceMappingURL=FloatingLabelInput.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FloatingLabelInput.js","sourceRoot":"","sources":["../../../../src/components/FloatingLabelInput/FloatingLabelInput.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { forwardRef, useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from \"react\"\nimport { mergeRefs } from \"react-merge-refs\"\n\nimport { FieldError } from \"../FieldError\"\nimport { X } from \"../Icon\"\n\nimport s from \"./FloatingLabelInput.module.css\"\n\nexport type FloatingLabelInputProps = {\n /**\n * Label text for the floating label\n */\n label: string\n /**\n * Error message to display below the input\n */\n errorMessage?: string\n /**\n * Mark the input as invalid\n * @default false (or true if errorMessage is provided)\n */\n invalid?: boolean\n /**\n * Disables the input visually and from interactions\n * @default false\n */\n disabled?: boolean\n /**\n * Makes the input read-only\n * @default false\n */\n readOnly?: boolean\n /**\n * Callback invoked when the clear button is clicked\n */\n onClear?: () => void\n /**\n * Callback invoked when the input is autofilled by the browser\n */\n onAutofill?: () => void\n /**\n * Allow autofill extensions to appear in the input\n * @default false\n */\n allowAutofillExtensions?: boolean\n /**\n * Content rendered after the input, before the clear button.\n * Useful for toggle buttons (e.g. password visibility), icons, or other interactive elements.\n */\n startAdornment?: React.ReactNode\n endAdornment?: React.ReactNode\n /**\n * Render as a multi-line textarea instead of a single-line input.\n * @default false\n */\n multiline?: boolean\n /**\n * Number of visible text lines when `multiline` is true.\n * @default 2\n */\n rows?: number\n} & React.InputHTMLAttributes<HTMLInputElement>\n\nexport const FloatingLabelInput = forwardRef<HTMLInputElement, FloatingLabelInputProps>(\n function FloatingLabelInput(props, ref) {\n const {\n label,\n errorMessage,\n \"invalid\": invalidProp,\n disabled = false,\n readOnly = false,\n onClear,\n onAutofill,\n allowAutofillExtensions = false,\n startAdornment,\n endAdornment,\n multiline = false,\n rows = 2,\n className,\n \"id\": idProp,\n name,\n type = \"text\",\n value,\n defaultValue,\n onChange,\n onFocus,\n onBlur,\n onAnimationStart,\n \"aria-describedby\": ariaDescribedByProp,\n ...restProps\n } = props\n\n const inputRef = useRef<HTMLInputElement | null>(null)\n const generatedId = useId()\n const inputId = idProp || `floating-label-input-${generatedId}`\n const errorId = `${inputId}-error`\n\n const [focused, setFocused] = useState(false)\n const [hasValue, setHasValue] = useState(() => {\n return !!(value !== undefined ? value : defaultValue)\n })\n\n // Sync hasValue with controlled value prop\n useEffect(() => {\n if (value !== undefined) {\n setHasValue(!!value)\n }\n }, [value])\n\n const autoResize = useCallback(() => {\n const el = inputRef.current\n if (!multiline || !el) return\n el.style.height = \"auto\"\n el.style.height = `${el.scrollHeight}px`\n }, [multiline])\n\n useLayoutEffect(autoResize, [autoResize])\n\n const invalid = invalidProp ?? !!errorMessage\n\n // Determine if clear button should be shown\n const showClearButton = !!onClear && hasValue && !disabled && !readOnly\n\n // Merge aria-describedby with error id\n const ariaDescribedBy =\n [ariaDescribedByProp, errorMessage ? errorId : undefined].filter(Boolean).join(\" \") ||\n undefined\n\n // Handle clicks on the container to focus the input\n const handleContainerMouseDown = useCallback((evt: React.MouseEvent<HTMLDivElement>) => {\n const input = inputRef.current\n if (!evt.target || !(evt.target instanceof Element) || !input) {\n return\n }\n if (input.contains(evt.target)) {\n return\n }\n if (evt.target.closest(\"button, [type='button'], [role='button']\")) {\n return\n }\n evt.preventDefault()\n if (document.activeElement !== input) {\n input.focus()\n }\n const length = input.value.length\n input.setSelectionRange(length, length)\n }, [])\n\n const handleFocus = useCallback(\n (evt: React.FocusEvent<HTMLInputElement>) => {\n setFocused(true)\n onFocus?.(evt)\n },\n [onFocus],\n )\n\n const handleBlur = useCallback(\n (evt: React.FocusEvent<HTMLInputElement>) => {\n setFocused(false)\n onBlur?.(evt)\n },\n [onBlur],\n )\n\n const handleChange = useCallback(\n (evt: React.ChangeEvent<HTMLInputElement>) => {\n setHasValue(!!evt.currentTarget.value)\n onChange?.(evt)\n autoResize()\n },\n [onChange, autoResize],\n )\n\n const handleAnimationStart = useCallback(\n (evt: React.AnimationEvent<HTMLInputElement>) => {\n onAnimationStart?.(evt)\n // Detect browser autofill\n if (evt.animationName === \"native-autofill-in\") {\n setHasValue(true)\n onAutofill?.()\n }\n },\n [onAnimationStart, onAutofill],\n )\n\n return (\n <div className={clsx(s.Root, className)}>\n <div\n className={clsx(s.FieldFootprint, {\n [s.HasValue]: hasValue || !!startAdornment,\n })}\n data-focused={focused ? \"\" : undefined}\n data-has-value={hasValue ? \"\" : undefined}\n data-invalid={invalid ? \"\" : undefined}\n data-disabled={disabled ? \"\" : undefined}\n data-readonly={readOnly ? \"\" : undefined}\n data-multiline={multiline ? \"\" : undefined}\n onMouseDown={handleContainerMouseDown}\n >\n <label className={s.TypeableLabel} htmlFor={inputId}>\n <div className={s.LabelPositioner}>\n <div className={s.LabelText}>{label}</div>\n </div>\n </label>\n {startAdornment && (\n <div className={s.StartAdornment}>{startAdornment}</div>\n )}\n {multiline ? (\n <textarea\n ref={mergeRefs([ref, inputRef]) as React.Ref<HTMLTextAreaElement>}\n id={inputId}\n name={name}\n rows={rows}\n className={s.Textarea}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={invalid ? true : undefined}\n aria-describedby={ariaDescribedBy}\n onChange={handleChange as unknown as React.ChangeEventHandler<HTMLTextAreaElement>}\n onFocus={handleFocus as unknown as React.FocusEventHandler<HTMLTextAreaElement>}\n onBlur={handleBlur as unknown as React.FocusEventHandler<HTMLTextAreaElement>}\n />\n ) : (\n <input\n {...restProps}\n ref={mergeRefs([ref, inputRef])}\n id={inputId}\n name={name}\n type={type}\n className={s.Input}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={invalid ? true : undefined}\n aria-describedby={ariaDescribedBy}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onAnimationStart={handleAnimationStart}\n data-lpignore={allowAutofillExtensions ? undefined : true}\n data-1p-ignore={allowAutofillExtensions ? undefined : true}\n />\n )}\n {endAdornment && (\n <div className={s.EndAdornment}>\n {endAdornment}\n </div>\n )}\n {showClearButton && (\n <button\n type=\"button\"\n aria-label=\"Clear input\"\n className={s.ClearButton}\n onClick={onClear}\n >\n <X />\n </button>\n )}\n </div>\n {errorMessage && (\n <FieldError id={errorId} className={s.ErrorMessage}>\n {errorMessage}\n </FieldError>\n )}\n </div>\n )\n },\n)\n\nFloatingLabelInput.displayName = \"FloatingLabelInput\"\n"]}
|
|
1
|
+
{"version":3,"file":"FloatingLabelInput.js","sourceRoot":"","sources":["../../../../src/components/FloatingLabelInput/FloatingLabelInput.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { forwardRef, useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from \"react\"\nimport { mergeRefs } from \"react-merge-refs\"\n\nimport { X } from \"../Icon\"\n\nimport s from \"./FloatingLabelInput.module.css\"\n\nexport type FloatingLabelInputProps = {\n /**\n * Label text for the floating label\n */\n label: string\n /**\n * Error message to display below the input\n */\n errorMessage?: string\n /**\n * Mark the input as invalid\n * @default false (or true if errorMessage is provided)\n */\n invalid?: boolean\n /**\n * Disables the input visually and from interactions\n * @default false\n */\n disabled?: boolean\n /**\n * Makes the input read-only\n * @default false\n */\n readOnly?: boolean\n /**\n * Callback invoked when the clear button is clicked\n */\n onClear?: () => void\n /**\n * Callback invoked when the input is autofilled by the browser\n */\n onAutofill?: () => void\n /**\n * Allow autofill extensions to appear in the input\n * @default false\n */\n allowAutofillExtensions?: boolean\n /**\n * Helper/description text displayed below the input.\n * Shown alongside the error message when both are present.\n */\n description?: React.ReactNode\n /**\n * Content rendered after the input, before the clear button.\n * Useful for toggle buttons (e.g. password visibility), icons, or other interactive elements.\n */\n startAdornment?: React.ReactNode\n endAdornment?: React.ReactNode\n /**\n * Render as a multi-line textarea instead of a single-line input.\n * @default false\n */\n multiline?: boolean\n /**\n * Number of visible text lines when `multiline` is true.\n * @default 2\n */\n rows?: number\n} & React.InputHTMLAttributes<HTMLInputElement>\n\nexport const FloatingLabelInput = forwardRef<HTMLInputElement, FloatingLabelInputProps>(\n function FloatingLabelInput(props, ref) {\n const {\n label,\n description,\n errorMessage,\n \"invalid\": invalidProp,\n disabled = false,\n readOnly = false,\n onClear,\n onAutofill,\n allowAutofillExtensions = false,\n startAdornment,\n endAdornment,\n multiline = false,\n rows = 2,\n className,\n \"id\": idProp,\n name,\n type = \"text\",\n value,\n defaultValue,\n onChange,\n onFocus,\n onBlur,\n onAnimationStart,\n \"aria-describedby\": ariaDescribedByProp,\n ...restProps\n } = props\n\n const inputRef = useRef<HTMLInputElement | null>(null)\n const generatedId = useId()\n const inputId = idProp || `floating-label-input-${generatedId}`\n const descriptionId = description ? `${inputId}-description` : undefined\n const errorId = errorMessage ? `${inputId}-error` : undefined\n\n const [focused, setFocused] = useState(false)\n const [hasValue, setHasValue] = useState(() => {\n return !!(value !== undefined ? value : defaultValue)\n })\n\n // Sync hasValue with controlled value prop\n useEffect(() => {\n if (value !== undefined) {\n setHasValue(!!value)\n }\n }, [value])\n\n const autoResize = useCallback(() => {\n const el = inputRef.current\n if (!multiline || !el) return\n el.style.height = \"auto\"\n el.style.height = `${el.scrollHeight}px`\n }, [multiline])\n\n useLayoutEffect(autoResize, [autoResize])\n\n const invalid = invalidProp ?? !!errorMessage\n\n // Determine if clear button should be shown\n const showClearButton = !!onClear && hasValue && !disabled && !readOnly\n\n // Merge aria-describedby with error id\n const ariaDescribedBy =\n [ariaDescribedByProp, errorId, descriptionId].filter(Boolean).join(\" \") || undefined\n\n // Handle clicks on the container to focus the input\n const handleContainerMouseDown = useCallback((evt: React.MouseEvent<HTMLDivElement>) => {\n const input = inputRef.current\n if (!evt.target || !(evt.target instanceof Element) || !input) {\n return\n }\n if (input.contains(evt.target)) {\n return\n }\n if (evt.target.closest(\"button, [type='button'], [role='button']\")) {\n return\n }\n evt.preventDefault()\n if (document.activeElement !== input) {\n input.focus()\n }\n const length = input.value.length\n input.setSelectionRange(length, length)\n }, [])\n\n const handleFocus = useCallback(\n (evt: React.FocusEvent<HTMLInputElement>) => {\n setFocused(true)\n onFocus?.(evt)\n },\n [onFocus],\n )\n\n const handleBlur = useCallback(\n (evt: React.FocusEvent<HTMLInputElement>) => {\n setFocused(false)\n onBlur?.(evt)\n },\n [onBlur],\n )\n\n const handleChange = useCallback(\n (evt: React.ChangeEvent<HTMLInputElement>) => {\n setHasValue(!!evt.currentTarget.value)\n onChange?.(evt)\n autoResize()\n },\n [onChange, autoResize],\n )\n\n const handleAnimationStart = useCallback(\n (evt: React.AnimationEvent<HTMLInputElement>) => {\n onAnimationStart?.(evt)\n // Detect browser autofill\n if (evt.animationName === \"native-autofill-in\") {\n setHasValue(true)\n onAutofill?.()\n }\n },\n [onAnimationStart, onAutofill],\n )\n\n return (\n <div className={clsx(s.Root, className)}>\n <div\n className={clsx(s.FieldFootprint, {\n [s.HasValue]: hasValue || !!startAdornment,\n })}\n data-focused={focused ? \"\" : undefined}\n data-has-value={hasValue ? \"\" : undefined}\n data-invalid={invalid ? \"\" : undefined}\n data-disabled={disabled ? \"\" : undefined}\n data-readonly={readOnly ? \"\" : undefined}\n data-multiline={multiline ? \"\" : undefined}\n onMouseDown={handleContainerMouseDown}\n >\n <label className={s.TypeableLabel} htmlFor={inputId}>\n <div className={s.LabelPositioner}>\n <div className={s.LabelText}>{label}</div>\n </div>\n </label>\n {startAdornment && (\n <div className={s.StartAdornment}>{startAdornment}</div>\n )}\n {multiline ? (\n <textarea\n ref={mergeRefs([ref, inputRef]) as React.Ref<HTMLTextAreaElement>}\n id={inputId}\n name={name}\n rows={rows}\n className={s.Textarea}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={invalid ? true : undefined}\n aria-describedby={ariaDescribedBy}\n onChange={handleChange as unknown as React.ChangeEventHandler<HTMLTextAreaElement>}\n onFocus={handleFocus as unknown as React.FocusEventHandler<HTMLTextAreaElement>}\n onBlur={handleBlur as unknown as React.FocusEventHandler<HTMLTextAreaElement>}\n />\n ) : (\n <input\n {...restProps}\n ref={mergeRefs([ref, inputRef])}\n id={inputId}\n name={name}\n type={type}\n className={s.Input}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={invalid ? true : undefined}\n aria-describedby={ariaDescribedBy}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onAnimationStart={handleAnimationStart}\n data-lpignore={allowAutofillExtensions ? undefined : true}\n data-1p-ignore={allowAutofillExtensions ? undefined : true}\n />\n )}\n {endAdornment && (\n <div className={s.EndAdornment}>\n {endAdornment}\n </div>\n )}\n {showClearButton && (\n <button\n type=\"button\"\n aria-label=\"Clear input\"\n className={s.ClearButton}\n onClick={onClear}\n >\n <X />\n </button>\n )}\n </div>\n {errorMessage && (\n <div id={errorId} className={s.ErrorMessage} role=\"alert\">\n {errorMessage}\n </div>\n )}\n {description && (\n <div id={descriptionId} className={s.Description}>\n {description}\n </div>\n )}\n </div>\n )\n },\n)\n\nFloatingLabelInput.displayName = \"FloatingLabelInput\"\n"]}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
@layer components {.Root {
|
|
2
2
|
position: relative;
|
|
3
|
-
--field-error-padding-inline: 0;
|
|
4
|
-
--field-error-margin-top: 0.25rem;
|
|
5
3
|
}.Root:has(:disabled) {
|
|
6
4
|
--cursor: not-allowed;
|
|
7
5
|
opacity: 0.5;
|
|
@@ -132,8 +130,18 @@
|
|
|
132
130
|
flex-shrink: 0;
|
|
133
131
|
position: relative;
|
|
134
132
|
z-index: 1;
|
|
135
|
-
}
|
|
136
|
-
|
|
133
|
+
}.ErrorMessage {
|
|
134
|
+
color: var(--field-error-color);
|
|
135
|
+
font-size: var(--field-error-font-size);
|
|
136
|
+
line-height: var(--field-error-line-height);
|
|
137
|
+
margin-top: 0.25rem;
|
|
138
|
+
padding-inline-start: var(--floating-input-gutter);
|
|
139
|
+
}.Description {
|
|
140
|
+
color: var(--color-text-secondary);
|
|
141
|
+
font-size: var(--field-error-font-size);
|
|
142
|
+
line-height: var(--field-error-line-height);
|
|
143
|
+
margin-top: 0.25rem;
|
|
144
|
+
padding-inline-start: var(--floating-input-gutter);
|
|
137
145
|
}/* =============================================
|
|
138
146
|
Multiline (textarea) variant
|
|
139
147
|
============================================= */.FieldFootprint[data-multiline] {
|
|
@@ -35,6 +35,11 @@ export type FloatingLabelInputProps = {
|
|
|
35
35
|
* @default false
|
|
36
36
|
*/
|
|
37
37
|
allowAutofillExtensions?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Helper/description text displayed below the input.
|
|
40
|
+
* Shown alongside the error message when both are present.
|
|
41
|
+
*/
|
|
42
|
+
description?: React.ReactNode;
|
|
38
43
|
/**
|
|
39
44
|
* Content rendered after the input, before the clear button.
|
|
40
45
|
* Useful for toggle buttons (e.g. password visibility), icons, or other interactive elements.
|
|
@@ -89,6 +94,11 @@ export declare const FloatingLabelInput: import("react").ForwardRefExoticCompone
|
|
|
89
94
|
* @default false
|
|
90
95
|
*/
|
|
91
96
|
allowAutofillExtensions?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Helper/description text displayed below the input.
|
|
99
|
+
* Shown alongside the error message when both are present.
|
|
100
|
+
*/
|
|
101
|
+
description?: React.ReactNode;
|
|
92
102
|
/**
|
|
93
103
|
* Content rendered after the input, before the clear button.
|
|
94
104
|
* Useful for toggle buttons (e.g. password visibility), icons, or other interactive elements.
|