@bonprix-ds/react-base-input-field 1.0.3 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { HTMLInputAutoCompleteAttribute, RefObject } from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { IconOrElement } from "@bonprix-ds/react-icon";
|
|
3
3
|
export interface HTMLInputAttributes {
|
|
4
4
|
/** <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inputmode" target="_blank">HTML input mode attribute.</a> */
|
|
5
5
|
inputMode?: HTMLInputInputModeAttribute;
|
|
@@ -39,7 +39,7 @@ interface BaseProps extends HTMLInputAttributes {
|
|
|
39
39
|
error?: boolean;
|
|
40
40
|
hideClear?: boolean;
|
|
41
41
|
describedBy?: string;
|
|
42
|
-
buttonIcon?:
|
|
42
|
+
buttonIcon?: IconOrElement;
|
|
43
43
|
onIconButtonClick?: () => void;
|
|
44
44
|
iconButtonType?: "button" | "submit";
|
|
45
45
|
iconButtonLabel?: string;
|
|
@@ -2,6 +2,7 @@ import { useId as e, useRef as t, useState as n } from "react";
|
|
|
2
2
|
import { tv as r } from "tailwind-variants";
|
|
3
3
|
import { InputWrapper as i } from "@bonprix-ds/internal-components";
|
|
4
4
|
import a from "@bonprix-ds/react-icon-button";
|
|
5
|
+
import { CloserIcon as ee } from "@bonprix-ds/react-icon/icons";
|
|
5
6
|
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
6
7
|
//#region src/BaseInputField.tsx
|
|
7
8
|
var c = r({
|
|
@@ -40,7 +41,7 @@ var c = r({
|
|
|
40
41
|
error: !0,
|
|
41
42
|
class: { input: "text-clr-primary [-webkit-text-fill-color:var(--bpds-color-fg-error)]" }
|
|
42
43
|
}]
|
|
43
|
-
}), l = ({ type: r, onFocus: l, onBlur: u, onKeyDown: d, onKeyUp: f, inputRef: p, label: m, name: h, id: g, helperText: _ = "", errorText: v = "", disabled: y = !1, required: b = !1, error: x = !1, inputMode:
|
|
44
|
+
}), l = ({ type: r, onFocus: l, onBlur: u, onKeyDown: d, onKeyUp: f, inputRef: p, label: m, name: h, id: g, helperText: _ = "", errorText: v = "", disabled: y = !1, required: b = !1, error: x = !1, inputMode: te, pattern: S, autoComplete: C, autoCorrect: w, spellCheck: ne, minLength: T, maxLength: E, hideClear: D = !1, describedBy: O, buttonIcon: k, iconButtonType: A = "button", onIconButtonClick: j, iconButtonLabel: M, componentName: N, ...P }) => {
|
|
44
45
|
let F = e(), I = g ?? F, L = e(), R = e(), z;
|
|
45
46
|
z = P.value === void 0 ? !!P.defaultValue : !!P.value;
|
|
46
47
|
let [B, V] = n(!1), [H, U] = n(z), W = H || B, G = t(null), K = p ?? G, { root: q, container: J, input: Y, buttonSection: X, clearButton: Z, iconSeparator: Q } = c({
|
|
@@ -48,16 +49,16 @@ var c = r({
|
|
|
48
49
|
hasValue: H,
|
|
49
50
|
hideClear: D,
|
|
50
51
|
error: x
|
|
51
|
-
}),
|
|
52
|
+
}), re = () => {
|
|
52
53
|
V(!0), l && l();
|
|
53
|
-
},
|
|
54
|
+
}, ie = () => {
|
|
54
55
|
V(!1), u && u();
|
|
55
|
-
},
|
|
56
|
+
}, ae = (e) => {
|
|
56
57
|
let t = e.currentTarget.value;
|
|
57
58
|
P.onChange?.(t), H !== !!t && U(!!t);
|
|
58
|
-
},
|
|
59
|
+
}, oe = () => {
|
|
59
60
|
P.value ? P.onChange("") : K.current && (K.current.value = ""), U(!1), K.current?.focus();
|
|
60
|
-
},
|
|
61
|
+
}, se = k && !D, ce = !D || k, $;
|
|
61
62
|
return _ && ($ = L), !y && x && v && ($ = $ ? $ + " " + R : R), O && ($ = $ ? $ + " " + O : O), /* @__PURE__ */ o("div", {
|
|
62
63
|
className: q(),
|
|
63
64
|
"data-fix-chrome-page-load-autofill": !0,
|
|
@@ -81,25 +82,25 @@ var c = r({
|
|
|
81
82
|
className: Y(),
|
|
82
83
|
id: I,
|
|
83
84
|
name: h,
|
|
84
|
-
onChange:
|
|
85
|
-
onFocus:
|
|
86
|
-
onBlur:
|
|
85
|
+
onChange: ae,
|
|
86
|
+
onFocus: re,
|
|
87
|
+
onBlur: ie,
|
|
87
88
|
onKeyDown: d,
|
|
88
89
|
onKeyUp: f,
|
|
89
|
-
inputMode:
|
|
90
|
-
pattern:
|
|
90
|
+
inputMode: te,
|
|
91
|
+
pattern: S,
|
|
91
92
|
autoComplete: C,
|
|
92
93
|
autoCorrect: w,
|
|
93
|
-
spellCheck:
|
|
94
|
+
spellCheck: ne,
|
|
94
95
|
ref: K,
|
|
95
|
-
minLength:
|
|
96
|
+
minLength: T,
|
|
96
97
|
maxLength: E,
|
|
97
98
|
required: b,
|
|
98
99
|
"aria-describedby": $,
|
|
99
100
|
"aria-invalid": x ? "true" : void 0,
|
|
100
101
|
disabled: y,
|
|
101
102
|
"data-bpds-hide-clear": D
|
|
102
|
-
}),
|
|
103
|
+
}), ce && /* @__PURE__ */ s("div", {
|
|
103
104
|
className: X(),
|
|
104
105
|
children: [
|
|
105
106
|
!D && /* @__PURE__ */ o("div", {
|
|
@@ -108,12 +109,12 @@ var c = r({
|
|
|
108
109
|
variant: "tertiary",
|
|
109
110
|
size: "small",
|
|
110
111
|
type: "button",
|
|
111
|
-
icon:
|
|
112
|
-
onClick:
|
|
112
|
+
icon: /* @__PURE__ */ o(ee, {}),
|
|
113
|
+
onClick: oe,
|
|
113
114
|
label: "Eingabe löschen"
|
|
114
115
|
})
|
|
115
116
|
}),
|
|
116
|
-
|
|
117
|
+
se && /* @__PURE__ */ o("span", { className: Q() }),
|
|
117
118
|
k && /* @__PURE__ */ o(a, {
|
|
118
119
|
variant: "tertiary",
|
|
119
120
|
size: "small",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseInputField.js","names":["IconButton","generateClasses","tv","BaseInputField","unionProps","generatedId","useId","calculatedId","id","helperTextId","errorTextId","initialHasValue","focused","setFocused","useState","hasValue","setHasValue","labelFloated","innerRef","useRef","ref","inputRef","handleFocus","onFocus","handleBlur","onBlur","handleChange","newValue","handleClear","showSeparator","buttonIcon","hideClear","showButtonSection","ariaDescribedBy","helperText","disabled","error","errorText","describedBy","root","InputWrapper","container","input","buttonSection","clearButton","iconSeparator","iconButtonType","onIconButtonClick","iconButtonLabel"],"sources":["../../src/BaseInputField.tsx"],"sourcesContent":["import React, { HTMLInputAutoCompleteAttribute, RefObject, useId, useRef, useState } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { InputWrapper } from \"@bonprix-ds/internal-components\";\nimport type { IconType } from \"@bonprix-ds/react-icon\";\nimport IconButton from \"@bonprix-ds/react-icon-button\";\n\nconst generateClasses = tv({\n slots: {\n root: \"preflight group w-full\",\n container: \"input flex gap-3 px-3 py-[0.6875rem]\",\n input: \"typography-input-text w-full flex-grow text-ellipsis bg-transparent text-inherit outline-none\",\n buttonSection: \"flex items-center gap-2\",\n clearButton: \"invisible\",\n iconSeparator: \"invisible h-5 w-0.25 bg-clr-on-bg-low\",\n },\n variants: {\n hasValue: {\n true: \"\",\n false: \"\",\n },\n disabled: {\n true: \"\",\n false: \"\",\n },\n hideClear: {\n true: {\n input: \"h-6\", // preserve 24px height without buttons\n },\n },\n error: {\n true: \"\",\n false: \"\",\n },\n },\n compoundVariants: [\n {\n hasValue: true,\n disabled: false,\n class: {\n clearButton: \"group-focus-within:visible group-hover:visible\",\n iconSeparator: \"group-focus-within:visible group-hover:visible\",\n },\n },\n {\n disabled: false,\n error: true,\n class: {\n // This makes sure the calendar icon is black-ish in Firefox even when the value is marked red.\n // Without this, the icon in Firefox would take the red color as well, which is inconsistent with Chrome and not what we want design-wise.\n // This is a known limitation within Firefox, and we do our best to make the native inputs align, s.: https://bugzilla.mozilla.org/show_bug.cgi?id=1817839\n input: \"text-clr-primary [-webkit-text-fill-color:var(--bpds-color-fg-error)]\",\n },\n },\n ],\n});\n\nexport interface HTMLInputAttributes {\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inputmode\" target=\"_blank\">HTML input mode attribute.</a> */\n inputMode?: HTMLInputInputModeAttribute;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/pattern\" target=\"_blank\">HTML pattern attribute.</a> */\n pattern?: HTMLInputPatternAttribute;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete\" target=\"_blank\">HTML autocomplete attribute.</a> */\n autoComplete?: HTMLInputAutoCompleteAttribute;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/autocorrect\" target=\"_blank\">HTML autocorrect attribute.</a> */\n autoCorrect?: HTMLInputAutoCorrectAttribute;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/spellcheck\" target=\"_blank\">HTML spellcheck attribute.</a> */\n spellCheck?: HTMLInputSpellCheckAttribute;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/minlength\" target=\"_blank\">HTML minLength attribute.</a> */\n minLength?: number;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/maxlength\" target=\"_blank\">HTML maxlength attribute.</a> */\n maxLength?: number;\n /** Callback, that is triggered on key down. */\n onKeyDown?: () => void;\n /** Callback that is triggered on key up. */\n onKeyUp?: () => void;\n}\n\ntype HTMLInputInputModeAttribute = \"none\" | \"text\" | \"tel\" | \"url\" | \"email\" | \"numeric\" | \"decimal\" | \"search\";\ntype HTMLInputPatternAttribute = HTMLInputElement[\"pattern\"];\ntype HTMLInputAutoCorrectAttribute = \"on\" | \"off\";\ntype HTMLInputSpellCheckAttribute = HTMLInputElement[\"spellcheck\"];\n\ninterface BaseProps extends HTMLInputAttributes {\n type: \"text\" | \"password\" | \"email\";\n onFocus?: () => void;\n onBlur?: () => void;\n inputRef?: RefObject<HTMLInputElement | null>;\n label?: string;\n name?: string;\n id?: string;\n helperText?: string;\n errorText?: string;\n disabled?: boolean;\n required?: boolean;\n error?: boolean;\n hideClear?: boolean;\n describedBy?: string;\n buttonIcon?: IconType;\n onIconButtonClick?: () => void;\n iconButtonType?: \"button\" | \"submit\";\n iconButtonLabel?: string;\n componentName: \"password-field\" | \"text-field\" | \"search-field\" | \"email-field\";\n}\n\ninterface ControlledInputProps extends BaseProps {\n value: string;\n onChange: (value: string) => void;\n}\n\ninterface UncontrolledInputProps extends BaseProps {\n value?: never;\n defaultValue: string;\n onChange?: (value: string) => void;\n}\n\ntype Props = ControlledInputProps | UncontrolledInputProps;\n\nconst BaseInputField = ({\n type,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n inputRef,\n label,\n name,\n id,\n helperText = \"\",\n errorText = \"\",\n disabled = false,\n required = false,\n error = false,\n inputMode,\n pattern,\n autoComplete,\n autoCorrect,\n spellCheck,\n minLength,\n maxLength,\n hideClear = false,\n describedBy,\n buttonIcon,\n iconButtonType = \"button\",\n onIconButtonClick,\n iconButtonLabel,\n componentName,\n ...unionProps\n}: Props) => {\n const generatedId = useId();\n const calculatedId = id ?? generatedId;\n const helperTextId = useId();\n const errorTextId = useId();\n let initialHasValue: boolean;\n if (unionProps.value !== undefined) {\n initialHasValue = Boolean(unionProps.value);\n } else {\n initialHasValue = Boolean(unionProps.defaultValue);\n }\n\n const [focused, setFocused] = useState(false);\n const [hasValue, setHasValue] = useState(initialHasValue);\n\n const labelFloated = hasValue || focused;\n\n const innerRef = useRef<HTMLInputElement>(null);\n const ref = inputRef ?? innerRef;\n\n const { root, container, input, buttonSection, clearButton, iconSeparator } = generateClasses({\n disabled,\n hasValue,\n hideClear,\n error,\n });\n\n const handleFocus = () => {\n setFocused(true);\n if (onFocus) {\n onFocus();\n }\n };\n\n const handleBlur = () => {\n setFocused(false);\n if (onBlur) {\n onBlur();\n }\n };\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.currentTarget.value;\n unionProps.onChange?.(newValue);\n if (hasValue !== Boolean(newValue)) {\n setHasValue(Boolean(newValue));\n }\n };\n\n const clearLabel = \"Eingabe löschen\";\n const handleClear = () => {\n if (unionProps.value) {\n unionProps.onChange(\"\");\n } else {\n if (ref.current) {\n ref.current.value = \"\";\n }\n }\n setHasValue(false);\n ref.current?.focus();\n };\n\n const showSeparator = buttonIcon && !hideClear;\n const showButtonSection = !hideClear || buttonIcon;\n\n let ariaDescribedBy;\n if (helperText) {\n ariaDescribedBy = helperTextId;\n }\n if (!disabled && error && errorText) {\n ariaDescribedBy = ariaDescribedBy ? ariaDescribedBy + \" \" + errorTextId : errorTextId;\n }\n if (describedBy) {\n ariaDescribedBy = ariaDescribedBy ? ariaDescribedBy + \" \" + describedBy : describedBy;\n }\n\n return (\n // The data-attribute is used to reliably select this element to fix a bug with autofill in Chrome,\n // where labels wouldn't float to the top when autofilling on initial page load.\n // We need to ensure this CSS is present early on in the rendering process,\n // so we can't keep it alongside our component and must move it to global CSS, hence the data-attribute.\n <div className={root()} data-fix-chrome-page-load-autofill>\n <InputWrapper\n label={label}\n id={calculatedId}\n labelFloated={labelFloated}\n disabled={disabled}\n required={required}\n helperText={helperText}\n helperTextId={helperTextId}\n error={error}\n errorText={errorText}\n errorTextId={errorTextId}\n componentName={componentName}\n >\n <div className={container()}>\n <input\n {...unionProps}\n type={type}\n className={input()}\n id={calculatedId}\n name={name}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n inputMode={inputMode}\n pattern={pattern}\n autoComplete={autoComplete}\n autoCorrect={autoCorrect}\n spellCheck={spellCheck}\n ref={ref}\n minLength={minLength}\n maxLength={maxLength}\n required={required}\n aria-describedby={ariaDescribedBy}\n aria-invalid={error ? \"true\" : undefined}\n disabled={disabled}\n data-bpds-hide-clear={hideClear}\n />\n {showButtonSection && (\n <div className={buttonSection()}>\n {!hideClear && (\n <div className={clearButton()}>\n <IconButton variant=\"tertiary\" size=\"small\" type=\"button\" icon=\"closer\" onClick={handleClear} label={clearLabel} />\n </div>\n )}\n {showSeparator && <span className={iconSeparator()}></span>}\n {buttonIcon && (\n <IconButton\n variant=\"tertiary\"\n size=\"small\"\n type={iconButtonType}\n icon={buttonIcon}\n onClick={onIconButtonClick}\n label={iconButtonLabel!}\n disabled={disabled}\n />\n )}\n </div>\n )}\n </div>\n </InputWrapper>\n </div>\n );\n};\n\nexport default BaseInputField;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BaseInputField.js","names":["IconButton","generateClasses","tv","BaseInputField","unionProps","generatedId","useId","calculatedId","id","helperTextId","errorTextId","initialHasValue","focused","setFocused","useState","hasValue","setHasValue","labelFloated","innerRef","useRef","ref","inputRef","handleFocus","onFocus","handleBlur","onBlur","handleChange","newValue","handleClear","showSeparator","buttonIcon","hideClear","showButtonSection","ariaDescribedBy","helperText","disabled","error","errorText","describedBy","root","InputWrapper","container","input","buttonSection","clearButton","CloserIcon","iconSeparator","iconButtonType","onIconButtonClick","iconButtonLabel"],"sources":["../../src/BaseInputField.tsx"],"sourcesContent":["import React, { HTMLInputAutoCompleteAttribute, RefObject, useId, useRef, useState } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { InputWrapper } from \"@bonprix-ds/internal-components\";\nimport type { IconOrElement } from \"@bonprix-ds/react-icon\";\nimport IconButton from \"@bonprix-ds/react-icon-button\";\nimport { CloserIcon } from \"@bonprix-ds/react-icon/icons\";\n\nconst generateClasses = tv({\n slots: {\n root: \"preflight group w-full\",\n container: \"input flex gap-3 px-3 py-[0.6875rem]\",\n input: \"typography-input-text w-full flex-grow text-ellipsis bg-transparent text-inherit outline-none\",\n buttonSection: \"flex items-center gap-2\",\n clearButton: \"invisible\",\n iconSeparator: \"invisible h-5 w-0.25 bg-clr-on-bg-low\",\n },\n variants: {\n hasValue: {\n true: \"\",\n false: \"\",\n },\n disabled: {\n true: \"\",\n false: \"\",\n },\n hideClear: {\n true: {\n input: \"h-6\", // preserve 24px height without buttons\n },\n },\n error: {\n true: \"\",\n false: \"\",\n },\n },\n compoundVariants: [\n {\n hasValue: true,\n disabled: false,\n class: {\n clearButton: \"group-focus-within:visible group-hover:visible\",\n iconSeparator: \"group-focus-within:visible group-hover:visible\",\n },\n },\n {\n disabled: false,\n error: true,\n class: {\n // This makes sure the calendar icon is black-ish in Firefox even when the value is marked red.\n // Without this, the icon in Firefox would take the red color as well, which is inconsistent with Chrome and not what we want design-wise.\n // This is a known limitation within Firefox, and we do our best to make the native inputs align, s.: https://bugzilla.mozilla.org/show_bug.cgi?id=1817839\n input: \"text-clr-primary [-webkit-text-fill-color:var(--bpds-color-fg-error)]\",\n },\n },\n ],\n});\n\nexport interface HTMLInputAttributes {\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inputmode\" target=\"_blank\">HTML input mode attribute.</a> */\n inputMode?: HTMLInputInputModeAttribute;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/pattern\" target=\"_blank\">HTML pattern attribute.</a> */\n pattern?: HTMLInputPatternAttribute;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete\" target=\"_blank\">HTML autocomplete attribute.</a> */\n autoComplete?: HTMLInputAutoCompleteAttribute;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/autocorrect\" target=\"_blank\">HTML autocorrect attribute.</a> */\n autoCorrect?: HTMLInputAutoCorrectAttribute;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/spellcheck\" target=\"_blank\">HTML spellcheck attribute.</a> */\n spellCheck?: HTMLInputSpellCheckAttribute;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/minlength\" target=\"_blank\">HTML minLength attribute.</a> */\n minLength?: number;\n /** <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/maxlength\" target=\"_blank\">HTML maxlength attribute.</a> */\n maxLength?: number;\n /** Callback, that is triggered on key down. */\n onKeyDown?: () => void;\n /** Callback that is triggered on key up. */\n onKeyUp?: () => void;\n}\n\ntype HTMLInputInputModeAttribute = \"none\" | \"text\" | \"tel\" | \"url\" | \"email\" | \"numeric\" | \"decimal\" | \"search\";\ntype HTMLInputPatternAttribute = HTMLInputElement[\"pattern\"];\ntype HTMLInputAutoCorrectAttribute = \"on\" | \"off\";\ntype HTMLInputSpellCheckAttribute = HTMLInputElement[\"spellcheck\"];\n\ninterface BaseProps extends HTMLInputAttributes {\n type: \"text\" | \"password\" | \"email\";\n onFocus?: () => void;\n onBlur?: () => void;\n inputRef?: RefObject<HTMLInputElement | null>;\n label?: string;\n name?: string;\n id?: string;\n helperText?: string;\n errorText?: string;\n disabled?: boolean;\n required?: boolean;\n error?: boolean;\n hideClear?: boolean;\n describedBy?: string;\n buttonIcon?: IconOrElement;\n onIconButtonClick?: () => void;\n iconButtonType?: \"button\" | \"submit\";\n iconButtonLabel?: string;\n componentName: \"password-field\" | \"text-field\" | \"search-field\" | \"email-field\";\n}\n\ninterface ControlledInputProps extends BaseProps {\n value: string;\n onChange: (value: string) => void;\n}\n\ninterface UncontrolledInputProps extends BaseProps {\n value?: never;\n defaultValue: string;\n onChange?: (value: string) => void;\n}\n\ntype Props = ControlledInputProps | UncontrolledInputProps;\n\nconst BaseInputField = ({\n type,\n onFocus,\n onBlur,\n onKeyDown,\n onKeyUp,\n inputRef,\n label,\n name,\n id,\n helperText = \"\",\n errorText = \"\",\n disabled = false,\n required = false,\n error = false,\n inputMode,\n pattern,\n autoComplete,\n autoCorrect,\n spellCheck,\n minLength,\n maxLength,\n hideClear = false,\n describedBy,\n buttonIcon,\n iconButtonType = \"button\",\n onIconButtonClick,\n iconButtonLabel,\n componentName,\n ...unionProps\n}: Props) => {\n const generatedId = useId();\n const calculatedId = id ?? generatedId;\n const helperTextId = useId();\n const errorTextId = useId();\n let initialHasValue: boolean;\n if (unionProps.value !== undefined) {\n initialHasValue = Boolean(unionProps.value);\n } else {\n initialHasValue = Boolean(unionProps.defaultValue);\n }\n\n const [focused, setFocused] = useState(false);\n const [hasValue, setHasValue] = useState(initialHasValue);\n\n const labelFloated = hasValue || focused;\n\n const innerRef = useRef<HTMLInputElement>(null);\n const ref = inputRef ?? innerRef;\n\n const { root, container, input, buttonSection, clearButton, iconSeparator } = generateClasses({\n disabled,\n hasValue,\n hideClear,\n error,\n });\n\n const handleFocus = () => {\n setFocused(true);\n if (onFocus) {\n onFocus();\n }\n };\n\n const handleBlur = () => {\n setFocused(false);\n if (onBlur) {\n onBlur();\n }\n };\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.currentTarget.value;\n unionProps.onChange?.(newValue);\n if (hasValue !== Boolean(newValue)) {\n setHasValue(Boolean(newValue));\n }\n };\n\n const clearLabel = \"Eingabe löschen\";\n const handleClear = () => {\n if (unionProps.value) {\n unionProps.onChange(\"\");\n } else {\n if (ref.current) {\n ref.current.value = \"\";\n }\n }\n setHasValue(false);\n ref.current?.focus();\n };\n\n const showSeparator = buttonIcon && !hideClear;\n const showButtonSection = !hideClear || buttonIcon;\n\n let ariaDescribedBy;\n if (helperText) {\n ariaDescribedBy = helperTextId;\n }\n if (!disabled && error && errorText) {\n ariaDescribedBy = ariaDescribedBy ? ariaDescribedBy + \" \" + errorTextId : errorTextId;\n }\n if (describedBy) {\n ariaDescribedBy = ariaDescribedBy ? ariaDescribedBy + \" \" + describedBy : describedBy;\n }\n\n return (\n // The data-attribute is used to reliably select this element to fix a bug with autofill in Chrome,\n // where labels wouldn't float to the top when autofilling on initial page load.\n // We need to ensure this CSS is present early on in the rendering process,\n // so we can't keep it alongside our component and must move it to global CSS, hence the data-attribute.\n <div className={root()} data-fix-chrome-page-load-autofill>\n <InputWrapper\n label={label}\n id={calculatedId}\n labelFloated={labelFloated}\n disabled={disabled}\n required={required}\n helperText={helperText}\n helperTextId={helperTextId}\n error={error}\n errorText={errorText}\n errorTextId={errorTextId}\n componentName={componentName}\n >\n <div className={container()}>\n <input\n {...unionProps}\n type={type}\n className={input()}\n id={calculatedId}\n name={name}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n inputMode={inputMode}\n pattern={pattern}\n autoComplete={autoComplete}\n autoCorrect={autoCorrect}\n spellCheck={spellCheck}\n ref={ref}\n minLength={minLength}\n maxLength={maxLength}\n required={required}\n aria-describedby={ariaDescribedBy}\n aria-invalid={error ? \"true\" : undefined}\n disabled={disabled}\n data-bpds-hide-clear={hideClear}\n />\n {showButtonSection && (\n <div className={buttonSection()}>\n {!hideClear && (\n <div className={clearButton()}>\n <IconButton\n variant=\"tertiary\"\n size=\"small\"\n type=\"button\"\n icon={<CloserIcon />}\n onClick={handleClear}\n label={clearLabel}\n />\n </div>\n )}\n {showSeparator && <span className={iconSeparator()}></span>}\n {buttonIcon && (\n <IconButton\n variant=\"tertiary\"\n size=\"small\"\n type={iconButtonType}\n icon={buttonIcon}\n onClick={onIconButtonClick}\n label={iconButtonLabel!}\n disabled={disabled}\n />\n )}\n </div>\n )}\n </div>\n </InputWrapper>\n </div>\n );\n};\n\nexport default BaseInputField;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bonprix-ds/react-base-input-field",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "BaseInputField component, implemented in React, for the Bonprix Design System.",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"provenance": true
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@bonprix-ds/internal-components": "0.2.
|
|
36
|
-
"@bonprix-ds/react-icon": "1.
|
|
37
|
-
"@bonprix-ds/react-icon-button": "1.2.
|
|
38
|
-
"@bonprix-ds/utils": "0.
|
|
35
|
+
"@bonprix-ds/internal-components": "0.2.4",
|
|
36
|
+
"@bonprix-ds/react-icon": "1.3.1",
|
|
37
|
+
"@bonprix-ds/react-icon-button": "1.2.4",
|
|
38
|
+
"@bonprix-ds/utils": "0.5.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/react": "19.3.0",
|