@plexui/ui 0.20.14 → 0.20.15

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.
@@ -20,7 +20,7 @@ const textareaProps = (props) => {
20
20
  return rest;
21
21
  };
22
22
  export const FloatingLabelInput = forwardRef(function FloatingLabelInput(props, ref) {
23
- const { label, description, errorMessage, "invalid": invalidProp, disabled = false, readOnly = false, onClear, onAutofill, allowAutofillExtensions = false, startAdornment, endAdornment, revealable: revealableProp, onRevealedChange, multiline = false, rows = 2, className, "id": idProp, name, type = "text", value, defaultValue, onChange, onFocus, onBlur, onAnimationStart, "aria-describedby": ariaDescribedByProp, ...restProps } = props;
23
+ const { label, description, errorMessage, "invalid": invalidProp, disabled = false, readOnly = false, onClear, onAutofill, allowAutofillExtensions = false, startAdornment, endAdornment, revealable: revealableProp, onRevealedChange, multiline = false, rows = 2, labelPlacement = "border", pill = true, className, "id": idProp, name, type = "text", value, defaultValue, onChange, onFocus, onBlur, onAnimationStart, "aria-describedby": ariaDescribedByProp, ...restProps } = props;
24
24
  const inputRef = useRef(null);
25
25
  const generatedId = useId();
26
26
  const inputId = idProp || `floating-label-input-${generatedId}`;
@@ -115,7 +115,7 @@ export const FloatingLabelInput = forwardRef(function FloatingLabelInput(props,
115
115
  return next;
116
116
  });
117
117
  }, [onRevealedChange]);
118
- return (_jsxs("div", { className: clsx(s.Root, className), children: [_jsxs("div", { className: clsx(s.FieldFootprint, {
118
+ return (_jsxs("div", { className: clsx(s.Root, className), "data-label-placement": labelPlacement === "inside" ? "inside" : undefined, "data-pill": pill && labelPlacement !== "inside" ? "" : undefined, children: [_jsxs("div", { className: clsx(s.FieldFootprint, {
119
119
  [s.HasValue]: hasValue || !!startAdornment,
120
120
  }), "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", { ...textareaProps(restProps), ref: mergeRefs([ref, inputRef]), id: inputId, name: name, rows: rows, className: s.Textarea, value: value, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedBy, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur })) : (_jsx("input", { ...restProps, ref: mergeRefs([ref, inputRef]), id: inputId, name: name, type: effectiveType, className: s.Input, value: value, defaultValue: defaultValue, disabled: disabled, readOnly: readOnly, "aria-invalid": ariaInvalid, "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: handleClear, children: _jsx(X, {}) })), showRevealButton && (_jsx("button", { type: "button", "aria-label": revealed ? "Hide" : "Show", className: s.RevealButton, onClick: handleRevealToggle, children: revealed ? _jsx(EyeOff, {}) : _jsx(Eye, {}) }))] }), errorMessage && (_jsx("div", { id: errorId, className: s.ErrorMessage, role: "alert", children: errorMessage })), description && (_jsx("div", { id: descriptionId, className: s.Description, children: description }))] }));
121
121
  });
@@ -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 { Eye, EyeOff, X } from \"../Icon\"\n\nimport s from \"@plexui/styles/components/FloatingLabelInput/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 before the input.\n */\n startAdornment?: React.ReactNode\n /**\n * Content rendered after the input, before the clear button.\n * For password fields the reveal toggle is built in — see `revealable`.\n */\n endAdornment?: React.ReactNode\n /**\n * Render a built-in reveal/hide toggle (eye icon) inside the field.\n * For `type=\"password\"` it swaps the input between `password` and `text`.\n * Defaults to `true` for password inputs that don't supply their own\n * `endAdornment`. Pass it explicitly to add the toggle to other sensitive\n * fields (e.g. a masked SSN) and react to it via `onRevealedChange`.\n * @default true when type=\"password\" and no endAdornment is provided\n */\n revealable?: boolean\n /**\n * Called with the new revealed state each time the reveal toggle is clicked.\n */\n onRevealedChange?: (revealed: boolean) => void\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\n// Attributes that only mean something on <input>; everything else (required,\n// maxLength, placeholder, key and clipboard handlers, aria-*, data-*) also\n// applies to the multiline <textarea>\nconst INPUT_ONLY_PROPS = [\n \"accept\", \"alt\", \"capture\", \"checked\", \"height\", \"list\", \"max\", \"min\", \"multiple\",\n \"pattern\", \"size\", \"src\", \"step\", \"width\", \"formAction\", \"formEncType\",\n \"formMethod\", \"formNoValidate\", \"formTarget\",\n] as const\n\nconst textareaProps = (props: Record<string, unknown>) => {\n const rest = { ...props }\n for (const key of INPUT_ONLY_PROPS) delete rest[key]\n return rest\n}\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 revealable: revealableProp,\n onRevealedChange,\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 const [revealed, setRevealed] = useState(false)\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 // Also resize when a controlled value or rows changes without a keystroke\n useLayoutEffect(() => {\n autoResize()\n }, [autoResize, value, rows])\n\n const invalid = invalidProp ?? !!errorMessage\n\n // Determine if clear button should be shown\n const showClearButton = !!onClear && hasValue && !disabled && !readOnly\n\n // Built-in password reveal toggle\n const isPassword = type === \"password\"\n const revealable = revealableProp ?? (isPassword && !endAdornment)\n const showRevealButton = revealable && !disabled\n const effectiveType = isPassword && revealed ? \"text\" : type\n\n // Merge aria-describedby with error id\n const ariaDescribedBy =\n [ariaDescribedByProp, errorId, descriptionId].filter(Boolean).join(\" \") || undefined\n // An explicit aria-invalid (e.g. from Field) wins over the computed state\n const ariaInvalid = restProps[\"aria-invalid\"] ?? (invalid ? true : 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 // email, number and other types without the selection API throw on setSelectionRange\n if (input.selectionStart === null) return\n const length = input.value.length\n input.setSelectionRange(length, length)\n }, [])\n\n // The clear button unmounts once the value is gone, so keep focus in the field\n const handleClear = useCallback(\n (evt: React.MouseEvent<HTMLButtonElement>) => {\n inputRef.current?.focus()\n ;(onClear as React.MouseEventHandler<HTMLButtonElement> | undefined)?.(evt)\n },\n [onClear],\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 const handleRevealToggle = useCallback(() => {\n setRevealed((prev) => {\n const next = !prev\n onRevealedChange?.(next)\n return next\n })\n }, [onRevealedChange])\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 {...(textareaProps(restProps) as React.TextareaHTMLAttributes<HTMLTextAreaElement>)}\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={ariaInvalid}\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={effectiveType}\n className={s.Input}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={ariaInvalid}\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={handleClear}\n >\n <X />\n </button>\n )}\n {showRevealButton && (\n <button\n type=\"button\"\n aria-label={revealed ? \"Hide\" : \"Show\"}\n className={s.RevealButton}\n onClick={handleRevealToggle}\n >\n {revealed ? <EyeOff /> : <Eye />}\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
+ {"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 { Eye, EyeOff, X } from \"../Icon\"\n\nimport s from \"@plexui/styles/components/FloatingLabelInput/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 before the input.\n */\n startAdornment?: React.ReactNode\n /**\n * Content rendered after the input, before the clear button.\n * For password fields the reveal toggle is built in — see `revealable`.\n */\n endAdornment?: React.ReactNode\n /**\n * Render a built-in reveal/hide toggle (eye icon) inside the field.\n * For `type=\"password\"` it swaps the input between `password` and `text`.\n * Defaults to `true` for password inputs that don't supply their own\n * `endAdornment`. Pass it explicitly to add the toggle to other sensitive\n * fields (e.g. a masked SSN) and react to it via `onRevealedChange`.\n * @default true when type=\"password\" and no endAdornment is provided\n */\n revealable?: boolean\n /**\n * Called with the new revealed state each time the reveal toggle is clicked.\n */\n onRevealedChange?: (revealed: boolean) => void\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 /**\n * Where the label rests once it floats: on the border, or inside the box\n * with the value under it. `inside` always takes the rounded box.\n * @default \"border\"\n */\n labelPlacement?: \"border\" | \"inside\"\n /**\n * Pill shape. `false` takes the rounded box of the other fields.\n * @default true\n */\n pill?: boolean\n} & React.InputHTMLAttributes<HTMLInputElement>\n\n// Attributes that only mean something on <input>; everything else (required,\n// maxLength, placeholder, key and clipboard handlers, aria-*, data-*) also\n// applies to the multiline <textarea>\nconst INPUT_ONLY_PROPS = [\n \"accept\", \"alt\", \"capture\", \"checked\", \"height\", \"list\", \"max\", \"min\", \"multiple\",\n \"pattern\", \"size\", \"src\", \"step\", \"width\", \"formAction\", \"formEncType\",\n \"formMethod\", \"formNoValidate\", \"formTarget\",\n] as const\n\nconst textareaProps = (props: Record<string, unknown>) => {\n const rest = { ...props }\n for (const key of INPUT_ONLY_PROPS) delete rest[key]\n return rest\n}\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 revealable: revealableProp,\n onRevealedChange,\n multiline = false,\n rows = 2,\n labelPlacement = \"border\",\n pill = true,\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 const [revealed, setRevealed] = useState(false)\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 // Also resize when a controlled value or rows changes without a keystroke\n useLayoutEffect(() => {\n autoResize()\n }, [autoResize, value, rows])\n\n const invalid = invalidProp ?? !!errorMessage\n\n // Determine if clear button should be shown\n const showClearButton = !!onClear && hasValue && !disabled && !readOnly\n\n // Built-in password reveal toggle\n const isPassword = type === \"password\"\n const revealable = revealableProp ?? (isPassword && !endAdornment)\n const showRevealButton = revealable && !disabled\n const effectiveType = isPassword && revealed ? \"text\" : type\n\n // Merge aria-describedby with error id\n const ariaDescribedBy =\n [ariaDescribedByProp, errorId, descriptionId].filter(Boolean).join(\" \") || undefined\n // An explicit aria-invalid (e.g. from Field) wins over the computed state\n const ariaInvalid = restProps[\"aria-invalid\"] ?? (invalid ? true : 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 // email, number and other types without the selection API throw on setSelectionRange\n if (input.selectionStart === null) return\n const length = input.value.length\n input.setSelectionRange(length, length)\n }, [])\n\n // The clear button unmounts once the value is gone, so keep focus in the field\n const handleClear = useCallback(\n (evt: React.MouseEvent<HTMLButtonElement>) => {\n inputRef.current?.focus()\n ;(onClear as React.MouseEventHandler<HTMLButtonElement> | undefined)?.(evt)\n },\n [onClear],\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 const handleRevealToggle = useCallback(() => {\n setRevealed((prev) => {\n const next = !prev\n onRevealedChange?.(next)\n return next\n })\n }, [onRevealedChange])\n\n return (\n <div\n className={clsx(s.Root, className)}\n data-label-placement={labelPlacement === \"inside\" ? \"inside\" : undefined}\n data-pill={pill && labelPlacement !== \"inside\" ? \"\" : undefined}\n >\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 {...(textareaProps(restProps) as React.TextareaHTMLAttributes<HTMLTextAreaElement>)}\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={ariaInvalid}\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={effectiveType}\n className={s.Input}\n value={value}\n defaultValue={defaultValue}\n disabled={disabled}\n readOnly={readOnly}\n aria-invalid={ariaInvalid}\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={handleClear}\n >\n <X />\n </button>\n )}\n {showRevealButton && (\n <button\n type=\"button\"\n aria-label={revealed ? \"Hide\" : \"Show\"}\n className={s.RevealButton}\n onClick={handleRevealToggle}\n >\n {revealed ? <EyeOff /> : <Eye />}\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"]}
@@ -6,7 +6,7 @@ import { Button } from "../Button/index.js";
6
6
  import { Dropdown, X } from "../Icon/index.js";
7
7
  import s from "@plexui/styles/components/FloatingLabelSelect/FloatingLabelSelect.module.css";
8
8
  export const FloatingLabelSelect = forwardRef(function FloatingLabelSelect(props, ref) {
9
- const { label, selected = false, errorMessage, "invalid": invalidProp, disabled = false, open = false, onInteract, onClearClick, children, className, "aria-describedby": ariaDescribedByProp, onKeyDown, ...restProps } = props;
9
+ const { label, selected = false, errorMessage, "invalid": invalidProp, disabled = false, open = false, onInteract, onClearClick, labelPlacement = "border", pill = true, children, className, "aria-describedby": ariaDescribedByProp, onKeyDown, ...restProps } = props;
10
10
  const generatedId = useId();
11
11
  const errorId = `floating-label-select-${generatedId}-error`;
12
12
  const invalid = invalidProp ?? !!errorMessage;
@@ -58,7 +58,7 @@ export const FloatingLabelSelect = forwardRef(function FloatingLabelSelect(props
58
58
  evt.preventDefault();
59
59
  onClearClick?.();
60
60
  }, [onClearClick]);
61
- return (_jsxs("div", { className: clsx(s.Root, className), children: [_jsxs("div", {
61
+ return (_jsxs("div", { className: clsx(s.Root, className), "data-label-placement": labelPlacement === "inside" ? "inside" : undefined, "data-pill": pill && labelPlacement !== "inside" ? "" : undefined, children: [_jsxs("div", {
62
62
  // The ref is the focusable field: a wrapping trigger returns focus to it and anchors to it
63
63
  ref: ref, className: clsx(s.FieldFootprint, {
64
64
  [s.HasValue]: selected,
@@ -1 +1 @@
1
- {"version":3,"file":"FloatingLabelSelect.js","sourceRoot":"","sources":["../../../../src/components/FloatingLabelSelect/FloatingLabelSelect.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,CAAC,MAAM,8EAA8E,CAAA;AAmB5F,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAC3C,SAAS,mBAAmB,CAAC,KAAK,EAAE,GAAG;IACrC,MAAM,EACJ,KAAK,EACL,QAAQ,GAAG,KAAK,EAChB,YAAY,EACZ,SAAS,EAAE,WAAW,EACtB,QAAQ,GAAG,KAAK,EAChB,IAAI,GAAG,KAAK,EACZ,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,kBAAkB,EAAE,mBAAmB,EACvC,SAAS,EACT,GAAG,SAAS,EACb,GAAG,KAAK,CAAA;IAET,MAAM,WAAW,GAAG,KAAK,EAAE,CAAA;IAC3B,MAAM,OAAO,GAAG,yBAAyB,WAAW,QAAQ,CAAA;IAE5D,MAAM,OAAO,GAAG,WAAW,IAAI,CAAC,CAAC,YAAY,CAAA;IAE7C,MAAM,eAAe,GAAG,CAAC,CAAC,YAAY,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAA;IAE/D,MAAM,eAAe,GACnB,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACnF,SAAS,CAAA;IAEX,MAAM,iBAAiB,GAAG,WAAW,CACnC,CAAC,GAAuC,EAAE,EAAE;QAC1C,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ;YAAE,OAAM;QACxC,GAAG,CAAC,cAAc,EAAE,CAAA;QACpB,UAAU,EAAE,EAAE,CAAA;IAChB,CAAC,EACD,CAAC,QAAQ,EAAE,UAAU,CAAC,CACvB,CAAA;IAED,MAAM,aAAa,GAAG,WAAW,CAC/B,CAAC,GAAwC,EAAE,EAAE;QAC3C,uEAAuE;QACvE,uEAAuE;QACvE,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,aAAa,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,CAAC,GAAG,KAAK,OAAO,CAAC;YAAE,OAAM;QACxF,SAAS,EAAE,CAAC,GAAG,CAAC,CAAA;QAChB,oEAAoE;QACpE,qEAAqE;QACrE,IAAI,QAAQ,IAAI,GAAG,CAAC,gBAAgB;YAAE,OAAM;QAE5C,QAAQ,GAAG,CAAC,GAAG,EAAE,CAAC;YAChB,KAAK,WAAW,CAAC;YACjB,KAAK,SAAS,CAAC;YACf,KAAK,GAAG,CAAC;YACT,KAAK,OAAO;gBACV,2DAA2D;gBAC3D,sDAAsD;gBACtD,IAAI,GAAG,CAAC,GAAG,KAAK,OAAO,IAAI,UAAU;oBAAE,MAAK;gBAC5C,GAAG,CAAC,eAAe,EAAE,CAAA;gBACrB,GAAG,CAAC,cAAc,EAAE,CAAA;gBACpB,IAAI,UAAU,EAAE,CAAC;oBACf,UAAU,EAAE,CAAA;gBACd,CAAC;qBAAM,CAAC;oBACN,4EAA4E;oBAC5E,GAAG,CAAC,aAAa,CAAC,KAAK,EAAE,CAAA;gBAC3B,CAAC;gBACD,MAAK;QACT,CAAC;IACH,CAAC,EACD,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAClC,CAAA;IAED,MAAM,sBAAsB,GAAG,WAAW,CAAC,CAAC,GAA0C,EAAE,EAAE;QACxF,GAAG,CAAC,eAAe,EAAE,CAAA;IACvB,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,gBAAgB,GAAG,WAAW,CAClC,CAAC,GAAwC,EAAE,EAAE;QAC3C,GAAG,CAAC,eAAe,EAAE,CAAA;QACrB,GAAG,CAAC,cAAc,EAAE,CAAA;QACpB,YAAY,EAAE,EAAE,CAAA;IAClB,CAAC,EACD,CAAC,YAAY,CAAC,CACf,CAAA;IAED,OAAO,CACL,eAAK,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,aACrC;gBACE,2FAA2F;gBAC3F,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE;oBAChC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,QAAQ;iBACvB,CAAC,EACF,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAChB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,kBAClB,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,mBACvB,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,mBACzB,IAAI,mBACL,SAAS,kBACT,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,sBACtB,eAAe,mBAClB,QAAQ,IAAI,SAAS,EACpC,aAAa,EAAE,iBAAiB,EAChC,SAAS,EAAE,aAAa,KACpB,SAAS,aAEb,cAAK,SAAS,EAAE,CAAC,CAAC,aAAa,YAC7B,cAAK,SAAS,EAAE,CAAC,CAAC,eAAe,YAC/B,cAAK,SAAS,EAAE,CAAC,CAAC,SAAS,YAAG,KAAK,GAAO,GACtC,GACF,EACN,eAAM,SAAS,EAAE,CAAC,CAAC,OAAO,YAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAQ,EAC/D,eAAK,SAAS,EAAE,CAAC,CAAC,gBAAgB,aAC/B,eAAe,IAAI,CAClB,KAAC,MAAM,kBACM,iBAAiB,EAC5B,SAAS,EAAE,CAAC,CAAC,KAAK,EAClB,aAAa,EAAE,sBAAsB,EACrC,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAC,WAAW,EACjB,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,KAAK,EACV,OAAO,QACP,IAAI,kBAEJ,KAAC,CAAC,KAAG,GACE,CACV,EACD,KAAC,QAAQ,IAAC,SAAS,EAAE,CAAC,CAAC,YAAY,GAAI,IACnC,IACF,EACL,YAAY,IAAI;YACf,2EAA2E;YAC3E,cAAK,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,YAAY,EAAE,IAAI,EAAC,OAAO,YACtD,YAAY,GACT,CACP,IACG,CACP,CAAA;AACH,CAAC,CACF,CAAA;AAED,mBAAmB,CAAC,WAAW,GAAG,qBAAqB,CAAA","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { forwardRef, useCallback, useId } from \"react\"\n\nimport { Button } from \"../Button\"\nimport { Dropdown, X } from \"../Icon\"\n\nimport s from \"@plexui/styles/components/FloatingLabelSelect/FloatingLabelSelect.module.css\"\n\nexport type FloatingLabelSelectProps = {\n label: string\n selected?: boolean\n errorMessage?: string\n invalid?: boolean\n disabled?: boolean\n open?: boolean\n onInteract?: () => void\n onClearClick?: () => void\n children?: React.ReactNode\n className?: string\n \"aria-describedby\"?: string\n} & Omit<\n React.HTMLAttributes<HTMLDivElement>,\n \"children\" | \"role\" | \"tabIndex\" | \"aria-describedby\"\n>\n\nexport const FloatingLabelSelect = forwardRef<HTMLDivElement, FloatingLabelSelectProps>(\n function FloatingLabelSelect(props, ref) {\n const {\n label,\n selected = false,\n errorMessage,\n \"invalid\": invalidProp,\n disabled = false,\n open = false,\n onInteract,\n onClearClick,\n children,\n className,\n \"aria-describedby\": ariaDescribedByProp,\n onKeyDown,\n ...restProps\n } = props\n\n const generatedId = useId()\n const errorId = `floating-label-select-${generatedId}-error`\n\n const invalid = invalidProp ?? !!errorMessage\n\n const showClearButton = !!onClearClick && selected && !disabled\n\n const ariaDescribedBy =\n [ariaDescribedByProp, errorMessage ? errorId : undefined].filter(Boolean).join(\" \") ||\n undefined\n\n const handlePointerDown = useCallback(\n (evt: React.PointerEvent<HTMLDivElement>) => {\n if (evt.button === 2 || disabled) return\n evt.preventDefault()\n onInteract?.()\n },\n [disabled, onInteract],\n )\n\n const handleKeyDown = useCallback(\n (evt: React.KeyboardEvent<HTMLDivElement>) => {\n // Enter and Space on a nested control (the clear button) activate that\n // control: neither this handler nor a wrapping trigger's may take them\n if (evt.target !== evt.currentTarget && (evt.key === \" \" || evt.key === \"Enter\")) return\n onKeyDown?.(evt)\n // A handler that prevented the default (the caller's, or a wrapping\n // Menu.Trigger's that opened its menu) cancels the built-in handling\n if (disabled || evt.defaultPrevented) return\n\n switch (evt.key) {\n case \"ArrowDown\":\n case \"ArrowUp\":\n case \" \":\n case \"Enter\":\n // Enter activates the field only without onInteract, as it\n // would the button a wrapping trigger usually renders\n if (evt.key === \"Enter\" && onInteract) break\n evt.stopPropagation()\n evt.preventDefault()\n if (onInteract) {\n onInteract()\n } else {\n // A wrapping trigger (Select's `trigger`, a Popover.Trigger) opens on click\n evt.currentTarget.click()\n }\n break\n }\n },\n [disabled, onInteract, onKeyDown],\n )\n\n const handleClearPointerDown = useCallback((evt: React.PointerEvent<HTMLButtonElement>) => {\n evt.stopPropagation()\n }, [])\n\n const handleClearClick = useCallback(\n (evt: React.MouseEvent<HTMLButtonElement>) => {\n evt.stopPropagation()\n evt.preventDefault()\n onClearClick?.()\n },\n [onClearClick],\n )\n\n return (\n <div className={clsx(s.Root, className)}>\n <div\n // The ref is the focusable field: a wrapping trigger returns focus to it and anchors to it\n ref={ref}\n className={clsx(s.FieldFootprint, {\n [s.HasValue]: selected,\n })}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n data-open={open ? \"\" : undefined}\n data-invalid={invalid ? \"\" : undefined}\n data-disabled={disabled ? \"\" : undefined}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-invalid={invalid ? true : undefined}\n aria-describedby={ariaDescribedBy}\n aria-disabled={disabled || undefined}\n onPointerDown={handlePointerDown}\n onKeyDown={handleKeyDown}\n {...restProps}\n >\n <div className={s.TypeableLabel}>\n <div className={s.LabelPositioner}>\n <div className={s.LabelText}>{label}</div>\n </div>\n </div>\n <span className={s.Content}>{selected ? children : null}</span>\n <div className={s.IndicatorWrapper}>\n {showClearButton && (\n <Button\n aria-label=\"Clear selection\"\n className={s.Clear}\n onPointerDown={handleClearPointerDown}\n onClick={handleClearClick}\n color=\"secondary\"\n variant=\"ghost\"\n size=\"3xs\"\n uniform\n pill\n >\n <X />\n </Button>\n )}\n <Dropdown className={s.DropdownIcon} />\n </div>\n </div>\n {errorMessage && (\n // Same plain line as FloatingLabelInput, so the two read alike on one form\n <div id={errorId} className={s.ErrorMessage} role=\"alert\">\n {errorMessage}\n </div>\n )}\n </div>\n )\n },\n)\n\nFloatingLabelSelect.displayName = \"FloatingLabelSelect\"\n"]}
1
+ {"version":3,"file":"FloatingLabelSelect.js","sourceRoot":"","sources":["../../../../src/components/FloatingLabelSelect/FloatingLabelSelect.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport clsx from \"clsx\"\nimport { forwardRef, useCallback, useId } from \"react\"\n\nimport { Button } from \"../Button\"\nimport { Dropdown, X } from \"../Icon\"\n\nimport s from \"@plexui/styles/components/FloatingLabelSelect/FloatingLabelSelect.module.css\"\n\nexport type FloatingLabelSelectProps = {\n label: string\n selected?: boolean\n errorMessage?: string\n invalid?: boolean\n disabled?: boolean\n open?: boolean\n onInteract?: () => void\n onClearClick?: () => void\n /**\n * Where the label rests once it floats: on the border, or inside the box\n * with the value under it. `inside` always takes the rounded box.\n * @default \"border\"\n */\n labelPlacement?: \"border\" | \"inside\"\n /**\n * Pill shape. `false` takes the rounded box of the other fields.\n * @default true\n */\n pill?: boolean\n children?: React.ReactNode\n className?: string\n \"aria-describedby\"?: string\n} & Omit<\n React.HTMLAttributes<HTMLDivElement>,\n \"children\" | \"role\" | \"tabIndex\" | \"aria-describedby\"\n>\n\nexport const FloatingLabelSelect = forwardRef<HTMLDivElement, FloatingLabelSelectProps>(\n function FloatingLabelSelect(props, ref) {\n const {\n label,\n selected = false,\n errorMessage,\n \"invalid\": invalidProp,\n disabled = false,\n open = false,\n onInteract,\n onClearClick,\n labelPlacement = \"border\",\n pill = true,\n children,\n className,\n \"aria-describedby\": ariaDescribedByProp,\n onKeyDown,\n ...restProps\n } = props\n\n const generatedId = useId()\n const errorId = `floating-label-select-${generatedId}-error`\n\n const invalid = invalidProp ?? !!errorMessage\n\n const showClearButton = !!onClearClick && selected && !disabled\n\n const ariaDescribedBy =\n [ariaDescribedByProp, errorMessage ? errorId : undefined].filter(Boolean).join(\" \") ||\n undefined\n\n const handlePointerDown = useCallback(\n (evt: React.PointerEvent<HTMLDivElement>) => {\n if (evt.button === 2 || disabled) return\n evt.preventDefault()\n onInteract?.()\n },\n [disabled, onInteract],\n )\n\n const handleKeyDown = useCallback(\n (evt: React.KeyboardEvent<HTMLDivElement>) => {\n // Enter and Space on a nested control (the clear button) activate that\n // control: neither this handler nor a wrapping trigger's may take them\n if (evt.target !== evt.currentTarget && (evt.key === \" \" || evt.key === \"Enter\")) return\n onKeyDown?.(evt)\n // A handler that prevented the default (the caller's, or a wrapping\n // Menu.Trigger's that opened its menu) cancels the built-in handling\n if (disabled || evt.defaultPrevented) return\n\n switch (evt.key) {\n case \"ArrowDown\":\n case \"ArrowUp\":\n case \" \":\n case \"Enter\":\n // Enter activates the field only without onInteract, as it\n // would the button a wrapping trigger usually renders\n if (evt.key === \"Enter\" && onInteract) break\n evt.stopPropagation()\n evt.preventDefault()\n if (onInteract) {\n onInteract()\n } else {\n // A wrapping trigger (Select's `trigger`, a Popover.Trigger) opens on click\n evt.currentTarget.click()\n }\n break\n }\n },\n [disabled, onInteract, onKeyDown],\n )\n\n const handleClearPointerDown = useCallback((evt: React.PointerEvent<HTMLButtonElement>) => {\n evt.stopPropagation()\n }, [])\n\n const handleClearClick = useCallback(\n (evt: React.MouseEvent<HTMLButtonElement>) => {\n evt.stopPropagation()\n evt.preventDefault()\n onClearClick?.()\n },\n [onClearClick],\n )\n\n return (\n <div\n className={clsx(s.Root, className)}\n data-label-placement={labelPlacement === \"inside\" ? \"inside\" : undefined}\n data-pill={pill && labelPlacement !== \"inside\" ? \"\" : undefined}\n >\n <div\n // The ref is the focusable field: a wrapping trigger returns focus to it and anchors to it\n ref={ref}\n className={clsx(s.FieldFootprint, {\n [s.HasValue]: selected,\n })}\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n data-open={open ? \"\" : undefined}\n data-invalid={invalid ? \"\" : undefined}\n data-disabled={disabled ? \"\" : undefined}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-invalid={invalid ? true : undefined}\n aria-describedby={ariaDescribedBy}\n aria-disabled={disabled || undefined}\n onPointerDown={handlePointerDown}\n onKeyDown={handleKeyDown}\n {...restProps}\n >\n <div className={s.TypeableLabel}>\n <div className={s.LabelPositioner}>\n <div className={s.LabelText}>{label}</div>\n </div>\n </div>\n <span className={s.Content}>{selected ? children : null}</span>\n <div className={s.IndicatorWrapper}>\n {showClearButton && (\n <Button\n aria-label=\"Clear selection\"\n className={s.Clear}\n onPointerDown={handleClearPointerDown}\n onClick={handleClearClick}\n color=\"secondary\"\n variant=\"ghost\"\n size=\"3xs\"\n uniform\n pill\n >\n <X />\n </Button>\n )}\n <Dropdown className={s.DropdownIcon} />\n </div>\n </div>\n {errorMessage && (\n // Same plain line as FloatingLabelInput, so the two read alike on one form\n <div id={errorId} className={s.ErrorMessage} role=\"alert\">\n {errorMessage}\n </div>\n )}\n </div>\n )\n },\n)\n\nFloatingLabelSelect.displayName = \"FloatingLabelSelect\"\n"]}
@@ -72,6 +72,17 @@ export type FloatingLabelInputProps = {
72
72
  * @default 2
73
73
  */
74
74
  rows?: number;
75
+ /**
76
+ * Where the label rests once it floats: on the border, or inside the box
77
+ * with the value under it. `inside` always takes the rounded box.
78
+ * @default "border"
79
+ */
80
+ labelPlacement?: "border" | "inside";
81
+ /**
82
+ * Pill shape. `false` takes the rounded box of the other fields.
83
+ * @default true
84
+ */
85
+ pill?: boolean;
75
86
  } & React.InputHTMLAttributes<HTMLInputElement>;
76
87
  export declare const FloatingLabelInput: import("react").ForwardRefExoticComponent<{
77
88
  /**
@@ -147,4 +158,15 @@ export declare const FloatingLabelInput: import("react").ForwardRefExoticCompone
147
158
  * @default 2
148
159
  */
149
160
  rows?: number;
161
+ /**
162
+ * Where the label rests once it floats: on the border, or inside the box
163
+ * with the value under it. `inside` always takes the rounded box.
164
+ * @default "border"
165
+ */
166
+ labelPlacement?: "border" | "inside";
167
+ /**
168
+ * Pill shape. `false` takes the rounded box of the other fields.
169
+ * @default true
170
+ */
171
+ pill?: boolean;
150
172
  } & import("react").InputHTMLAttributes<HTMLInputElement> & import("react").RefAttributes<HTMLInputElement>>;
@@ -7,6 +7,17 @@ export type FloatingLabelSelectProps = {
7
7
  open?: boolean;
8
8
  onInteract?: () => void;
9
9
  onClearClick?: () => void;
10
+ /**
11
+ * Where the label rests once it floats: on the border, or inside the box
12
+ * with the value under it. `inside` always takes the rounded box.
13
+ * @default "border"
14
+ */
15
+ labelPlacement?: "border" | "inside";
16
+ /**
17
+ * Pill shape. `false` takes the rounded box of the other fields.
18
+ * @default true
19
+ */
20
+ pill?: boolean;
10
21
  children?: React.ReactNode;
11
22
  className?: string;
12
23
  "aria-describedby"?: string;
@@ -20,6 +31,17 @@ export declare const FloatingLabelSelect: import("react").ForwardRefExoticCompon
20
31
  open?: boolean;
21
32
  onInteract?: () => void;
22
33
  onClearClick?: () => void;
34
+ /**
35
+ * Where the label rests once it floats: on the border, or inside the box
36
+ * with the value under it. `inside` always takes the rounded box.
37
+ * @default "border"
38
+ */
39
+ labelPlacement?: "border" | "inside";
40
+ /**
41
+ * Pill shape. `false` takes the rounded box of the other fields.
42
+ * @default true
43
+ */
44
+ pill?: boolean;
23
45
  children?: React.ReactNode;
24
46
  className?: string;
25
47
  "aria-describedby"?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plexui/ui",
3
- "version": "0.20.14",
3
+ "version": "0.20.15",
4
4
  "description": "Modern design system for building high-quality applications",
5
5
  "type": "module",
6
6
  "license": "MIT",