@bytebrand/fe-ui-core-autobahn 1.0.151 → 1.0.153
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/cards/CarCard.tsx +384 -384
- package/chrome/Footer.tsx +16 -3
- package/compat/MdField/MdField.tsx +28 -4
- package/locales/de/autobahn.json +2 -1
- package/locales/en/autobahn.json +1 -0
- package/package.json +30 -30
- package/theme/md3.css +14660 -11409
- package/ui/Dropdown.tsx +13 -2
- package/ui/FormCheckbox.tsx +22 -2
- package/ui/FormField.tsx +2 -1
- package/ui/Icon.tsx +6 -0
- package/ui/MfieldCheckIcon.tsx +13 -0
- package/ui/Modal.tsx +73 -4
- package/ui/usePortalMenuPosition.ts +8 -2
- package/vdp/FinanceCalculator.tsx +19 -5
- package/vdp/VdpModules.tsx +4409 -4397
package/chrome/Footer.tsx
CHANGED
|
@@ -86,6 +86,14 @@ export interface FooterProps {
|
|
|
86
86
|
* (VehicleDetailedNextPage), never site-wide, since every other page shows only footnotes 1-4.
|
|
87
87
|
*/
|
|
88
88
|
showCostFootnotes?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Hides the brand blurb + "stay in contact"/social + 3 link columns block (the
|
|
91
|
+
* `.footer-grid`), leaving just the legal disclaimer and copyright/"Nach Oben" bar. Opt-in,
|
|
92
|
+
* off by default — every other caller keeps the full footer. Only CheckoutThankYouPage.tsx
|
|
93
|
+
* (checkout step 6 "Danke") uses this today: that page's own Figma reference (64637:37033)
|
|
94
|
+
* has just the compact legal/copyright strip, not the full site footer.
|
|
95
|
+
*/
|
|
96
|
+
hideBrandColumns?: boolean;
|
|
89
97
|
}
|
|
90
98
|
|
|
91
99
|
/**
|
|
@@ -93,7 +101,7 @@ export interface FooterProps {
|
|
|
93
101
|
* disclaimer block, and a copyright + "Nach Oben" bar. Pure/presentational MD3 chrome — renders
|
|
94
102
|
* correctly only inside a `<div className="md3">` subtree (scoped theme at source/theme/autobahn).
|
|
95
103
|
*/
|
|
96
|
-
const Footer: React.FunctionComponent<FooterProps> = ({ t, showCostFootnotes }) => {
|
|
104
|
+
const Footer: React.FunctionComponent<FooterProps> = ({ t, showCostFootnotes, hideBrandColumns }) => {
|
|
97
105
|
const scrollTop = (): void => window.scroll({ top: 0, left: 0, behavior: 'smooth' });
|
|
98
106
|
const now = new Date();
|
|
99
107
|
const year = now.getFullYear();
|
|
@@ -104,6 +112,7 @@ const Footer: React.FunctionComponent<FooterProps> = ({ t, showCostFootnotes })
|
|
|
104
112
|
|
|
105
113
|
return (
|
|
106
114
|
<footer style={{ background: 'var(--md-sc-low)', borderTop: '1px solid var(--md-outline-variant)' }}>
|
|
115
|
+
{!hideBrandColumns ? (
|
|
107
116
|
<div className="container footer-grid" style={{ padding: '40px 24px 24px' }}>
|
|
108
117
|
<div>
|
|
109
118
|
<img src={logoUrl} height="30" alt="auto.de" />
|
|
@@ -169,10 +178,14 @@ const Footer: React.FunctionComponent<FooterProps> = ({ t, showCostFootnotes })
|
|
|
169
178
|
</div>
|
|
170
179
|
))}
|
|
171
180
|
</div>
|
|
181
|
+
) : null}
|
|
172
182
|
|
|
173
183
|
{/* Legally required disclaimers (PAngV §17a financing example w/ live APR/nominal rate +
|
|
174
|
-
term, DAT CO₂-Leitfaden, MwSt, Streichpreis, image notice). Same text as the legacy footer.
|
|
175
|
-
|
|
184
|
+
term, DAT CO₂-Leitfaden, MwSt, Streichpreis, image notice). Same text as the legacy footer.
|
|
185
|
+
The top border separates this from .footer-grid above — with hideBrandColumns that
|
|
186
|
+
block is gone, so the border would just double up against whatever's already directly
|
|
187
|
+
above the footer on the page (CheckoutThankYouPage.tsx's own header border). */}
|
|
188
|
+
<div style={hideBrandColumns ? undefined : { borderTop: '1px solid var(--md-outline-variant)' }}>
|
|
176
189
|
<div className="container" style={{ padding: '18px 24px' }}>
|
|
177
190
|
<p
|
|
178
191
|
className="md-label-sm"
|
|
@@ -8,6 +8,7 @@ import * as React from 'react';
|
|
|
8
8
|
import classnames from 'classnames';
|
|
9
9
|
|
|
10
10
|
import Icon from '../../ui/Icon';
|
|
11
|
+
import MfieldCheckIcon from '../../ui/MfieldCheckIcon';
|
|
11
12
|
|
|
12
13
|
export interface MdFieldProps {
|
|
13
14
|
className?: string;
|
|
@@ -32,12 +33,21 @@ export interface MdFieldProps {
|
|
|
32
33
|
* when empty and unfocused, then floats up to the normal small-label spot on focus
|
|
33
34
|
* or once a value is typed. Defaults to false — the static above-field label. */
|
|
34
35
|
floatingLabel?: boolean;
|
|
36
|
+
/** opt-in: show a green check + green border when the field is filled and valid (checkout).
|
|
37
|
+
* Same contract/markup as FormField's own showValid (.mfield--valid/.mfield-ok, md3.css). */
|
|
38
|
+
showValid?: boolean;
|
|
35
39
|
onChange: (value: string, name?: string, event?: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
40
|
+
/** fires after the field's own internal blur handling (floating-label state). Callers use
|
|
41
|
+
* this to trigger `field.validate()` (mobx-react-form) on blur — this component only owns
|
|
42
|
+
* the `error` prop's display, not when validation actually runs, so without a caller wiring
|
|
43
|
+
* this in, `field.error` never populates from blur and a required-but-empty field never
|
|
44
|
+
* shows its error text/red border until some other validate() call happens to run. */
|
|
45
|
+
onBlur?: () => void;
|
|
36
46
|
}
|
|
37
47
|
|
|
38
48
|
const MdField: React.FunctionComponent<MdFieldProps> = ({
|
|
39
49
|
className, error, sx, required, disabled, multiline, autoComplete,
|
|
40
|
-
value, type, name, rows, label, placeholder, floatingLabel, maxLength, onChange
|
|
50
|
+
value, type, name, rows, label, placeholder, floatingLabel, maxLength, showValid, onChange, onBlur
|
|
41
51
|
}) => {
|
|
42
52
|
const [reveal, setReveal] = React.useState(false);
|
|
43
53
|
const [focused, setFocused] = React.useState(false);
|
|
@@ -54,6 +64,7 @@ const MdField: React.FunctionComponent<MdFieldProps> = ({
|
|
|
54
64
|
// a value is typed, the real <label> appears in its normal static spot above the
|
|
55
65
|
// field and the native placeholder goes quiet — the two never show at the same time.
|
|
56
66
|
const hasValue = value != null && value !== '';
|
|
67
|
+
const isValid = !!showValid && !disabled && !isPassword && !hasError && hasValue;
|
|
57
68
|
const resting = !!floatingLabel && !focused && !hasValue;
|
|
58
69
|
const effectivePlaceholder = floatingLabel ? (resting ? (label || placeholder || '') : '') : (placeholder || '');
|
|
59
70
|
// The real <label> is skipped entirely while resting (see above), leaving the input with
|
|
@@ -71,7 +82,9 @@ const MdField: React.FunctionComponent<MdFieldProps> = ({
|
|
|
71
82
|
|
|
72
83
|
return (
|
|
73
84
|
<div className={classnames('mfield-group', className)} style={sx as React.CSSProperties}>
|
|
74
|
-
{
|
|
85
|
+
{/* Non-floating fields (FormField's own call sites don't set floatingLabel) keep the
|
|
86
|
+
plain label-above-the-box row — unchanged, still a .mfield-group flex child. */}
|
|
87
|
+
{label && !resting && !floatingLabel ? (
|
|
75
88
|
<label className='md-label-sm mfield-label' htmlFor={generatedId}>
|
|
76
89
|
{label}{required ? ' *' : ''}
|
|
77
90
|
</label>
|
|
@@ -87,8 +100,18 @@ const MdField: React.FunctionComponent<MdFieldProps> = ({
|
|
|
87
100
|
+ (hasError ? ' mfield--error' : '')
|
|
88
101
|
+ (disabled ? ' mfield--disabled' : '')
|
|
89
102
|
+ (floatingLabel ? ' mfield--floating' : '')
|
|
103
|
+
+ (isValid ? ' mfield--valid' : '')
|
|
90
104
|
}
|
|
91
105
|
>
|
|
106
|
+
{/* floatingLabel + floated (focused or has a value): the Material "notched outline"
|
|
107
|
+
treatment — label sits ON the border line, not stacked above it in its own row.
|
|
108
|
+
Lives INSIDE .mfield (not .mfield-group) so it can position against .mfield's own
|
|
109
|
+
edge (.mfield is position:relative already, md3.css) via .mfield-label--notch. */}
|
|
110
|
+
{label && !resting && floatingLabel ? (
|
|
111
|
+
<label className='md-label-sm mfield-label mfield-label--notch' htmlFor={generatedId}>
|
|
112
|
+
{label}{required ? ' *' : ''}
|
|
113
|
+
</label>
|
|
114
|
+
) : null}
|
|
92
115
|
{multiline ? (
|
|
93
116
|
<textarea
|
|
94
117
|
id={generatedId}
|
|
@@ -96,7 +119,7 @@ const MdField: React.FunctionComponent<MdFieldProps> = ({
|
|
|
96
119
|
value={value == null ? '' : value}
|
|
97
120
|
onChange={handleChange}
|
|
98
121
|
onFocus={() => setFocused(true)}
|
|
99
|
-
onBlur={() => setFocused(false)}
|
|
122
|
+
onBlur={() => { setFocused(false); onBlur?.(); }}
|
|
100
123
|
disabled={disabled}
|
|
101
124
|
rows={rows || 3}
|
|
102
125
|
maxLength={maxLength}
|
|
@@ -115,7 +138,7 @@ const MdField: React.FunctionComponent<MdFieldProps> = ({
|
|
|
115
138
|
value={value == null ? '' : value}
|
|
116
139
|
onChange={handleChange}
|
|
117
140
|
onFocus={() => setFocused(true)}
|
|
118
|
-
onBlur={() => setFocused(false)}
|
|
141
|
+
onBlur={() => { setFocused(false); onBlur?.(); }}
|
|
119
142
|
disabled={disabled}
|
|
120
143
|
maxLength={maxLength}
|
|
121
144
|
placeholder={effectivePlaceholder}
|
|
@@ -137,6 +160,7 @@ const MdField: React.FunctionComponent<MdFieldProps> = ({
|
|
|
137
160
|
<Icon name={reveal ? 'eye-off' : 'eye'} size={18} />
|
|
138
161
|
</button>
|
|
139
162
|
) : null}
|
|
163
|
+
{isValid ? <span className="mfield-ok"><MfieldCheckIcon /></span> : null}
|
|
140
164
|
</div>
|
|
141
165
|
{hasError ? (
|
|
142
166
|
// role="alert" announces this to screen readers the moment it enters the DOM (e.g.
|
package/locales/de/autobahn.json
CHANGED
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
"finance": {
|
|
68
68
|
"termSelection": "Laufzeit",
|
|
69
69
|
"termSelectionMonths": "Laufzeit (Monate)",
|
|
70
|
+
"change": "Ändern",
|
|
70
71
|
"headerTitle": "Dein Angebot",
|
|
71
72
|
"adjustRate": "Rate anpassen",
|
|
72
73
|
"secureOffer": "Angebot anfragen",
|
|
@@ -700,7 +701,7 @@
|
|
|
700
701
|
},
|
|
701
702
|
"modal": {
|
|
702
703
|
"leasingDetails": "Leasingdetails",
|
|
703
|
-
"financingDetails": "
|
|
704
|
+
"financingDetails": "Details",
|
|
704
705
|
"close": "Schließen",
|
|
705
706
|
"vehiclePrice": "Fahrzeugpreis ggf. inkl. MwSt.",
|
|
706
707
|
"leasingAmount": "Leasingbetrag",
|
package/locales/en/autobahn.json
CHANGED
package/package.json
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@bytebrand/fe-ui-core-autobahn",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "auto.de md3 (Autobahn) design system — UI primitives, cards, chrome, VDP modules, theme CSS and locales. Ships raw TypeScript source (like fe-ui-core before it); each consumer's bundler compiles it.",
|
|
5
|
-
"main": "index.ts",
|
|
6
|
-
"license": "UNLICENSED",
|
|
7
|
-
"peerDependencies": {
|
|
8
|
-
"react": "^18.0.0",
|
|
9
|
-
"react-dom": "^18.0.0"
|
|
10
|
-
},
|
|
11
|
-
"dependencies": {
|
|
12
|
-
"@bytebrand/car-schema-selectors": "^2.0.7",
|
|
13
|
-
"@bytebrand/fe-financing": "^5.14.20",
|
|
14
|
-
"classnames": "2.2.6",
|
|
15
|
-
"clsx": "^2.1.1",
|
|
16
|
-
"d3-format": "1.4.5",
|
|
17
|
-
"js-cookie": "^2.2.0",
|
|
18
|
-
"lodash": "^4.17.21",
|
|
19
|
-
"lucide-react": "^0.288.0",
|
|
20
|
-
"mobx-react": "^7.6.0",
|
|
21
|
-
"moment": "^2.29.1",
|
|
22
|
-
"qs": "^6.6.0",
|
|
23
|
-
"react-device-detect": "^2.1.2",
|
|
24
|
-
"react-grid-system": "^5.0.2",
|
|
25
|
-
"react-lazyload": "^3.2.0",
|
|
26
|
-
"react-scroll": "^1.9.3",
|
|
27
|
-
"react-slick": "^0.29.0",
|
|
28
|
-
"slick-carousel": "1.8.1"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@bytebrand/fe-ui-core-autobahn",
|
|
3
|
+
"version": "1.0.153",
|
|
4
|
+
"description": "auto.de md3 (Autobahn) design system — UI primitives, cards, chrome, VDP modules, theme CSS and locales. Ships raw TypeScript source (like fe-ui-core before it); each consumer's bundler compiles it.",
|
|
5
|
+
"main": "index.ts",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"peerDependencies": {
|
|
8
|
+
"react": "^18.0.0",
|
|
9
|
+
"react-dom": "^18.0.0"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@bytebrand/car-schema-selectors": "^2.0.7",
|
|
13
|
+
"@bytebrand/fe-financing": "^5.14.20",
|
|
14
|
+
"classnames": "2.2.6",
|
|
15
|
+
"clsx": "^2.1.1",
|
|
16
|
+
"d3-format": "1.4.5",
|
|
17
|
+
"js-cookie": "^2.2.0",
|
|
18
|
+
"lodash": "^4.17.21",
|
|
19
|
+
"lucide-react": "^0.288.0",
|
|
20
|
+
"mobx-react": "^7.6.0",
|
|
21
|
+
"moment": "^2.29.1",
|
|
22
|
+
"qs": "^6.6.0",
|
|
23
|
+
"react-device-detect": "^2.1.2",
|
|
24
|
+
"react-grid-system": "^5.0.2",
|
|
25
|
+
"react-lazyload": "^3.2.0",
|
|
26
|
+
"react-scroll": "^1.9.3",
|
|
27
|
+
"react-slick": "^0.29.0",
|
|
28
|
+
"slick-carousel": "1.8.1"
|
|
29
|
+
}
|
|
30
|
+
}
|