@bytebrand/fe-ui-core-autobahn 1.0.0
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/assets/autode-logo.svg +7 -0
- package/cards/CarCard.tsx +174 -0
- package/cards/CarRow.tsx +182 -0
- package/cards/cardParts.tsx +489 -0
- package/cards/index.ts +35 -0
- package/cards/types.ts +114 -0
- package/chrome/Footer.tsx +189 -0
- package/chrome/TopBar.tsx +405 -0
- package/chrome/index.ts +20 -0
- package/chrome/svg.d.ts +11 -0
- package/compat/AccardionSection/AccardionSection.styl +45 -0
- package/compat/AccardionSection/AccardionSection.tsx +56 -0
- package/compat/AccordionWidget/AccordionWidget.styl +221 -0
- package/compat/AccordionWidget/AccordionWidget.tsx +257 -0
- package/compat/AccordionWrapper/AccordionItem/AccordionItem.styl +34 -0
- package/compat/AccordionWrapper/AccordionItem/AccordionItem.tsx +64 -0
- package/compat/AccordionWrapper/AccordionWrapper.tsx +34 -0
- package/compat/AdvantageItem/AdvantageItem.styl +47 -0
- package/compat/AdvantageItem/AdvantageItem.tsx +26 -0
- package/compat/Alternative/DealerInfo.styl +116 -0
- package/compat/Alternative/DealerInfo.tsx +171 -0
- package/compat/Badge/Badge.styl +44 -0
- package/compat/Badge/Badge.tsx +25 -0
- package/compat/BodyTypeIcons/Audi.tsx +9 -0
- package/compat/BodyTypeIcons/Bmw.tsx +860 -0
- package/compat/BodyTypeIcons/Ford.tsx +31 -0
- package/compat/BodyTypeIcons/IconsConfig.tsx +44 -0
- package/compat/BodyTypeIcons/IconsConfigCompact.tsx +30 -0
- package/compat/BodyTypeIcons/Mazda.tsx +44 -0
- package/compat/BodyTypeIcons/MercedesBenz.tsx +38 -0
- package/compat/BodyTypeIcons/Opel.tsx +19 -0
- package/compat/BodyTypeIcons/Search.tsx +19 -0
- package/compat/BodyTypeIcons/SelectorCategoryCombi.tsx +68 -0
- package/compat/BodyTypeIcons/SelectorCategoryCompact.tsx +20 -0
- package/compat/BodyTypeIcons/SelectorCategoryConvertible.tsx +68 -0
- package/compat/BodyTypeIcons/SelectorCategoryCoupe.tsx +60 -0
- package/compat/BodyTypeIcons/SelectorCategoryMinibus.tsx +64 -0
- package/compat/BodyTypeIcons/SelectorCategorySedan.tsx +69 -0
- package/compat/BodyTypeIcons/SelectorCategorySuv.tsx +77 -0
- package/compat/BodyTypeIcons/SelectorCategoryTransporter.tsx +68 -0
- package/compat/BodyTypeIcons/SelectorCategoryVan.tsx +72 -0
- package/compat/BodyTypeIcons/Volkswagen.tsx +330 -0
- package/compat/BodyTypeIcons/index.ts +17 -0
- package/compat/Button/Button.tsx +65 -0
- package/compat/ButtonOld/Button.styl +65 -0
- package/compat/ButtonOld/Button.tsx +84 -0
- package/compat/Checkbox/Checkbox.styl +120 -0
- package/compat/Checkbox/Checkbox.tsx +151 -0
- package/compat/Checkbox/FormCheckbox.styl +22 -0
- package/compat/Checkbox/FormCheckbox.tsx +86 -0
- package/compat/Co2Widget/CO2Efficiency.styl +219 -0
- package/compat/Co2Widget/CO2Efficiency.tsx +93 -0
- package/compat/ContactInfo/ContactInfo.styl +22 -0
- package/compat/ContactInfo/ContactInfo.tsx +161 -0
- package/compat/ContactInfo/TemporaryTranslation.ts +11 -0
- package/compat/CookieModal/CookieModal.tsx +49 -0
- package/compat/CookieModal/Modal.tsx +43 -0
- package/compat/CookieModal/ModalsConfig.tsx +23 -0
- package/compat/CookieModal/modals/ManageCookieModal/ManageCookieModal.styl +87 -0
- package/compat/CookieModal/modals/ManageCookieModal/ManageCookieModal.tsx +184 -0
- package/compat/CookieModal/modals/PreviewCookieModal/PreviewCookieModal.styl +67 -0
- package/compat/CookieModal/modals/PreviewCookieModal/PreviewCookieModal.tsx +51 -0
- package/compat/CookieModal/modals/TestModal.tsx +7 -0
- package/compat/CookieModal/useModal.ts +13 -0
- package/compat/CustomerQuote/CustomerQuote.styl +80 -0
- package/compat/CustomerQuote/CustomerQuote.tsx +68 -0
- package/compat/CustomerQuotesSlider/CustomerQuotesSlider.styl +46 -0
- package/compat/CustomerQuotesSlider/CustomerQuotesSlider.tsx +79 -0
- package/compat/CustomerQuotesSlider/SliderArrow.tsx +20 -0
- package/compat/CustomerQuotesSlider/slider.global.styl +2 -0
- package/compat/ExpansionPanel/ExpansionPanel.tsx +68 -0
- package/compat/FirstInfoBlock/FirstInfoBlock.styl +33 -0
- package/compat/FirstInfoBlock/FirstInfoBlock.tsx +49 -0
- package/compat/FirstInfoBlock/FirstInfoBlockItem/FirstInfoBlockItem.styl +66 -0
- package/compat/FirstInfoBlock/FirstInfoBlockItem/FirstInfoBlockItem.tsx +21 -0
- package/compat/FormattedNumber/FormattedNumber.styl +2 -0
- package/compat/FormattedNumber/FormattedNumber.tsx +90 -0
- package/compat/IconContainer/IconContainer.styl +23 -0
- package/compat/IconContainer/IconContainer.tsx +34 -0
- package/compat/Image/Image.styl +109 -0
- package/compat/Image/Image.tsx +302 -0
- package/compat/ImageSettings/EditableOptionsTable/CustomCheckbox/CustomCheckbox.styl +7 -0
- package/compat/ImageSettings/EditableOptionsTable/CustomCheckbox/CustomCheckbox.tsx +30 -0
- package/compat/ImageSettings/EditableOptionsTable/EditableOptionsTable.styl +122 -0
- package/compat/ImageSettings/EditableOptionsTable/EditableOptionsTable.tsx +199 -0
- package/compat/ImageSettings/EditableOptionsTable/ImageIcon/ImageIcon.styl +3 -0
- package/compat/ImageSettings/EditableOptionsTable/ImageIcon/ImageIcon.tsx +15 -0
- package/compat/ImageSettings/OptionsTable/OptionsTable.styl +47 -0
- package/compat/ImageSettings/OptionsTable/OptionsTable.tsx +122 -0
- package/compat/ImageSettings/PricePlan/PricePlan.styl +63 -0
- package/compat/ImageSettings/PricePlan/PricePlan.tsx +32 -0
- package/compat/ImageSettings/index.ts +42 -0
- package/compat/ImagesSet/ImagesSet.styl +28 -0
- package/compat/ImagesSet/ImagesSet.tsx +76 -0
- package/compat/InfoBlockWrapper/InfoBlockWrapper.styl +41 -0
- package/compat/InfoBlockWrapper/InfoBlockWrapper.tsx +46 -0
- package/compat/Loader/Loader.styl +39 -0
- package/compat/Loader/Loader.tsx +32 -0
- package/compat/MagnifyGlass/MagnifyGlass.styl +33 -0
- package/compat/MagnifyGlass/MagnifyGlass.tsx +213 -0
- package/compat/MdAccordionGroup/MdAccordionGroup.tsx +53 -0
- package/compat/MdCheckbox/MdCheckbox.tsx +69 -0
- package/compat/MdField/MdField.tsx +100 -0
- package/compat/MdSelect/MdSelect.tsx +103 -0
- package/compat/MdSwitch/MdSwitch.tsx +29 -0
- package/compat/MdTabs/MdTabs.tsx +47 -0
- package/compat/MdTooltip/MdTooltip.tsx +31 -0
- package/compat/OfferDetailedSection/OfferDetailedSection.styl +31 -0
- package/compat/OfferDetailedSection/OfferDetailedSection.tsx +100 -0
- package/compat/OfferDetailedSection/partials/PanelConfig.styl +132 -0
- package/compat/OfferDetailedSection/partials/PanelConfig.tsx +121 -0
- package/compat/OfferPanel/AboAccordion/AboAccordion.styl +25 -0
- package/compat/OfferPanel/AboAccordion/AboAccordion.tsx +128 -0
- package/compat/OfferPanel/AboAccordion/AboColorOptions/AboColorOptions.styl +12 -0
- package/compat/OfferPanel/AboAccordion/AboColorOptions/AboColorOptions.tsx +35 -0
- package/compat/OfferPanel/AboAccordion/AboFaq/AboFaq.styl +21 -0
- package/compat/OfferPanel/AboAccordion/AboFaq/AboFaq.tsx +25 -0
- package/compat/OfferPanel/AboAccordion/AboIncludedServices/AboIncludedServices.styl +14 -0
- package/compat/OfferPanel/AboAccordion/AboIncludedServices/AboIncludedServices.tsx +39 -0
- package/compat/OfferPanel/MuiOfferPeriod/MuiOfferPeriod.tsx +42 -0
- package/compat/OfferPanel/OfferCheckboxGroup/CheckboxContainer.tsx +140 -0
- package/compat/OfferPanel/OfferCheckboxGroup/OfferCheckboxGroup.styl +144 -0
- package/compat/OfferPanel/OfferCheckboxGroup/OfferCheckboxGroup.tsx +23 -0
- package/compat/OfferPanel/OfferPanel.styl +194 -0
- package/compat/OfferPanel/OfferPanel.tsx +81 -0
- package/compat/OfferPanel/OfferPeriod/OfferPeriod.styl +25 -0
- package/compat/OfferPanel/OfferPeriod/OfferPeriod.tsx +45 -0
- package/compat/OfferPanel/RangeGroup/RangeGroup.tsx +39 -0
- package/compat/OfferRequestButtonWrapper/OfferRequestButtonWrapper.styl +120 -0
- package/compat/OfferRequestButtonWrapper/OfferRequestButtonWrapper.styled.tsx +33 -0
- package/compat/OfferRequestButtonWrapper/OfferRequestButtonWrapper.tsx +122 -0
- package/compat/PriceRating/PriceRating.styl +47 -0
- package/compat/PriceRating/PriceRating.tsx +64 -0
- package/compat/PriceRatingDetailed/PriceRatingDetailed.styl +120 -0
- package/compat/PriceRatingDetailed/PriceRatingDetailed.tsx +191 -0
- package/compat/PricingToolBlock/PricingTool.styl +7 -0
- package/compat/PricingToolBlock/PricingTool.tsx +29 -0
- package/compat/Radio/Radio.styl +115 -0
- package/compat/Radio/Radio.tsx +141 -0
- package/compat/Radio/RadioGroup.styl +5 -0
- package/compat/Radio/RadioGroup.tsx +65 -0
- package/compat/Range/Range.tsx +79 -0
- package/compat/RateSearchValue/RateSearchValue.styl +22 -0
- package/compat/RateSearchValue/RateSearchValue.tsx +55 -0
- package/compat/RateSearchWidget/RateSearchWidget.styl +107 -0
- package/compat/RateSearchWidget/RateSearchWidget.tsx +163 -0
- package/compat/ServiceBlockItem/ServiceBlockItem.styl +48 -0
- package/compat/ServiceBlockItem/ServiceBlockItem.tsx +25 -0
- package/compat/SkeletonItem/SkeletonItem.styl +81 -0
- package/compat/SkeletonItem/SkeletonItem.tsx +80 -0
- package/compat/StarButton/StarButton.styl +39 -0
- package/compat/StarButton/StarButton.tsx +31 -0
- package/compat/TabPanel/TabPanel.tsx +29 -0
- package/compat/TimePicker/TimePicker.styl +23 -0
- package/compat/TimePicker/TimePicker.tsx +156 -0
- package/compat/Tooltip/Tooltip.styl +117 -0
- package/compat/Tooltip/Tooltip.tsx +63 -0
- package/compat/Usp/Usp.styl +78 -0
- package/compat/Usp/Usp.tsx +30 -0
- package/compat/Usp/uspTranslate.ts +12 -0
- package/compat/VehicleDetailedSidebar/VehicleDetailedSidebar.styl +37 -0
- package/compat/VehicleDetailedSidebar/VehicleDetailedSidebar.tsx +178 -0
- package/compat/VehicleDetailedSidebar/partials/Price.styl +27 -0
- package/compat/VehicleDetailedSidebar/partials/Price.tsx +41 -0
- package/compat/VehicleDetailedSidebar/partials/PriceContent.styl +124 -0
- package/compat/VehicleDetailedSidebar/partials/PriceContent.tsx +128 -0
- package/compat/VehicleDetailedSidebar/partials/Properties.styl +58 -0
- package/compat/VehicleDetailedSidebar/partials/Properties.tsx +155 -0
- package/compat/VehicleDetailedSidebar/partials/Title.styl +35 -0
- package/compat/VehicleDetailedSidebar/partials/Title.tsx +33 -0
- package/compat/VehicleDetailedSlider/VehicleDetailedSlider.styl +147 -0
- package/compat/VehicleDetailedSlider/VehicleDetailedSlider.tsx +382 -0
- package/compat/VehicleDetailedSlider/partials/MobileStast.tsx +61 -0
- package/compat/VehicleDetailedSlider/partials/MobileStats.styl +71 -0
- package/compat/VehicleDetailedSlider/partials/PriceData.styl +51 -0
- package/compat/VehicleDetailedSlider/partials/PriceData.tsx +67 -0
- package/compat/VehicleDetailedSlider/partials/Stats.styl +80 -0
- package/compat/VehicleDetailedSlider/partials/Stats.tsx +62 -0
- package/compat/VehicleDetailedSlider/partials/Title.styl +45 -0
- package/compat/VehicleDetailedSlider/partials/Title.tsx +36 -0
- package/compat/VehicleFormattedPrice/VehicleFormattedPrice.styl +149 -0
- package/compat/VehicleFormattedPrice/VehicleFormattedPrice.tsx +163 -0
- package/compat/VehicleSlider/VehicleSlider.styl +63 -0
- package/compat/VehicleSlider/VehicleSlider.tsx +125 -0
- package/compat/VehicleSlider/VehicleSliderForSRL.tsx +175 -0
- package/compat/VehicleSmallCard/SeoText/SeoText.styl +8 -0
- package/compat/VehicleSmallCard/SeoText/SeoText.tsx +16 -0
- package/compat/VehicleSmallCard/VehicleData/VechiclePriceItem/VechiclePriceItem.styl +204 -0
- package/compat/VehicleSmallCard/VehicleData/VechiclePriceItem/VechiclePriceItem.tsx +199 -0
- package/compat/VehicleSmallCard/VehicleData/VehicleInfo/VehicleInfo.styl +273 -0
- package/compat/VehicleSmallCard/VehicleData/VehicleInfo/VehicleInfo.tsx +179 -0
- package/compat/VehicleSmallCard/VehicleData/VehiclePrice/VehiclePrice.styl +165 -0
- package/compat/VehicleSmallCard/VehicleData/VehiclePrice/VehiclePrice.tsx +299 -0
- package/compat/VehicleSmallCard/VehicleData/VehicleProperty/VehicleProperty.styl +33 -0
- package/compat/VehicleSmallCard/VehicleData/VehicleProperty/VehicleProperty.tsx +35 -0
- package/compat/VehicleSmallCard/VehicleData/VehicleTitle/VehicleTitle.styl +136 -0
- package/compat/VehicleSmallCard/VehicleData/VehicleTitle/VehicleTitle.tsx +91 -0
- package/compat/VehicleSmallCard/VehicleSmallCard.styl +310 -0
- package/compat/VehicleSmallCard/VehicleSmallCard.tsx +448 -0
- package/compat/index.ts +77 -0
- package/compat/legacy-theme/mixins.styl +93 -0
- package/compat/legacy-theme/priceReviewColors.styl +12 -0
- package/compat/legacy-theme/slider.global.styl +5 -0
- package/compat/legacy-theme/theme.styl +136 -0
- package/compat/withLabel/withLabel.styl +33 -0
- package/compat/withLabel/withLabel.tsx +44 -0
- package/compat/withStats/withStats.styl +174 -0
- package/compat/withStats/withStats.tsx +238 -0
- package/constants/RateSearchWidget.ts +15 -0
- package/constants/Search.ts +290 -0
- package/constants/SearchWidget.ts +108 -0
- package/constants/app.ts +223 -0
- package/constants/common.ts +127 -0
- package/constants/core.ts +131 -0
- package/constants/highlights.ts +165 -0
- package/constants/price.ts +9 -0
- package/constants/selectors.ts +38 -0
- package/constants.ts +91 -0
- package/data/DataTransformers.ts +88 -0
- package/data/fieldMapping.ts +342 -0
- package/data/toAutobahnCar.ts +442 -0
- package/iconsvg/IconSVG.tsx +30 -0
- package/iconsvg/IconSVGConfig.tsx +768 -0
- package/iconsvg/SVG/AboPartner.tsx +16 -0
- package/iconsvg/SVG/ArrowQuotes.tsx +22 -0
- package/iconsvg/SVG/CloseIcon.tsx +17 -0
- package/iconsvg/SVG/CloseIconSelect.tsx +18 -0
- package/iconsvg/SVG/ClosedLockIcon.tsx +18 -0
- package/iconsvg/SVG/DealerCheckIcon.tsx +18 -0
- package/iconsvg/SVG/DealerPopoverMail.tsx +21 -0
- package/iconsvg/SVG/DealerPopoverPhone.tsx +21 -0
- package/iconsvg/SVG/GrayPhoneIcon.tsx +22 -0
- package/iconsvg/SVG/InternetIcon.tsx +18 -0
- package/iconsvg/SVG/WhiteEnvelopeIcon.tsx +21 -0
- package/iconsvg/SVG/bodyType/Cabrio.tsx +23 -0
- package/iconsvg/SVG/bodyType/Coupe.tsx +22 -0
- package/iconsvg/SVG/bodyType/Minibus.tsx +22 -0
- package/iconsvg/SVG/bodyType/Other.tsx +25 -0
- package/iconsvg/SVG/bodyType/Sedan.tsx +22 -0
- package/iconsvg/SVG/bodyType/SelectorCategoryCombi.tsx +68 -0
- package/iconsvg/SVG/bodyType/SelectorCategoryCompact.tsx +20 -0
- package/iconsvg/SVG/bodyType/SelectorCategoryConvertible.tsx +68 -0
- package/iconsvg/SVG/bodyType/SelectorCategoryCoupe.tsx +60 -0
- package/iconsvg/SVG/bodyType/SelectorCategoryMinibus.tsx +64 -0
- package/iconsvg/SVG/bodyType/SelectorCategoryOther.tsx +60 -0
- package/iconsvg/SVG/bodyType/SelectorCategorySedan.tsx +69 -0
- package/iconsvg/SVG/bodyType/SelectorCategorySuv.tsx +77 -0
- package/iconsvg/SVG/bodyType/SelectorCategoryTransporter.tsx +68 -0
- package/iconsvg/SVG/bodyType/SelectorCategoryVan.tsx +72 -0
- package/iconsvg/SVG/bodyType/Small.tsx +23 -0
- package/iconsvg/SVG/bodyType/Suv.tsx +23 -0
- package/iconsvg/SVG/bodyType/Van.tsx +23 -0
- package/iconsvg/SVG/bodyType/Wagon.tsx +23 -0
- package/iconsvg/SVG/common/AddIcon.tsx +16 -0
- package/iconsvg/SVG/common/AddPlus.tsx +16 -0
- package/iconsvg/SVG/common/AddressDashboard.tsx +29 -0
- package/iconsvg/SVG/common/AddressIcon.tsx +20 -0
- package/iconsvg/SVG/common/ArrowDetailedAccordionBlue.tsx +26 -0
- package/iconsvg/SVG/common/ArrowDownBlue.tsx +21 -0
- package/iconsvg/SVG/common/ArrowSelect.tsx +23 -0
- package/iconsvg/SVG/common/ArrowStepDown.tsx +18 -0
- package/iconsvg/SVG/common/Autocheck.tsx +19 -0
- package/iconsvg/SVG/common/AutodeLogo.tsx +36 -0
- package/iconsvg/SVG/common/Avatar.tsx +17 -0
- package/iconsvg/SVG/common/BellGray.tsx +19 -0
- package/iconsvg/SVG/common/BigInfoTransparent.tsx +13 -0
- package/iconsvg/SVG/common/Browse.tsx +20 -0
- package/iconsvg/SVG/common/Calendar.tsx +24 -0
- package/iconsvg/SVG/common/CallbackDashboard.tsx +30 -0
- package/iconsvg/SVG/common/Camera.tsx +17 -0
- package/iconsvg/SVG/common/Car.tsx +16 -0
- package/iconsvg/SVG/common/CarBody.tsx +19 -0
- package/iconsvg/SVG/common/CarFront.tsx +43 -0
- package/iconsvg/SVG/common/CarInspectionCheck.tsx +21 -0
- package/iconsvg/SVG/common/CarInspectionScheme0.tsx +32 -0
- package/iconsvg/SVG/common/CarInspectionScheme1.tsx +53 -0
- package/iconsvg/SVG/common/CarInspectionScheme2.tsx +52 -0
- package/iconsvg/SVG/common/CarInspectionScheme3.tsx +32 -0
- package/iconsvg/SVG/common/CarInspectionScheme4.tsx +32 -0
- package/iconsvg/SVG/common/CarInspectionScheme5.tsx +32 -0
- package/iconsvg/SVG/common/CarInspectionScheme6.tsx +32 -0
- package/iconsvg/SVG/common/CarInspectionSchemeGeneral copy.tsx +24 -0
- package/iconsvg/SVG/common/CarInspectionSchemeGeneral.tsx +24 -0
- package/iconsvg/SVG/common/CheckBlue.tsx +18 -0
- package/iconsvg/SVG/common/CheckGreen.tsx +22 -0
- package/iconsvg/SVG/common/CheckMark.tsx +16 -0
- package/iconsvg/SVG/common/CheckWhite.tsx +19 -0
- package/iconsvg/SVG/common/Chevron.tsx +17 -0
- package/iconsvg/SVG/common/CircledCheckmark.tsx +25 -0
- package/iconsvg/SVG/common/Clock.tsx +18 -0
- package/iconsvg/SVG/common/Close.tsx +19 -0
- package/iconsvg/SVG/common/CloseGrey.tsx +22 -0
- package/iconsvg/SVG/common/ContactEmail.tsx +21 -0
- package/iconsvg/SVG/common/ContactPhone.tsx +28 -0
- package/iconsvg/SVG/common/CopyIcon copy.tsx +22 -0
- package/iconsvg/SVG/common/CopyIcon.tsx +22 -0
- package/iconsvg/SVG/common/CopyIconForDealer.tsx +21 -0
- package/iconsvg/SVG/common/DashboardIcon.tsx +20 -0
- package/iconsvg/SVG/common/DashboardQuestionMark.tsx +20 -0
- package/iconsvg/SVG/common/DealersIcon.tsx +20 -0
- package/iconsvg/SVG/common/DeleteCircle.tsx +31 -0
- package/iconsvg/SVG/common/DeleteV1Icon.tsx +18 -0
- package/iconsvg/SVG/common/DeliveryDashboard.tsx +25 -0
- package/iconsvg/SVG/common/DeliveryMail.tsx +24 -0
- package/iconsvg/SVG/common/Discount100De.tsx +18 -0
- package/iconsvg/SVG/common/Discount100En.tsx +19 -0
- package/iconsvg/SVG/common/Discount66De.tsx +28 -0
- package/iconsvg/SVG/common/Discount66En.tsx +20 -0
- package/iconsvg/SVG/common/DoneIcon.tsx +18 -0
- package/iconsvg/SVG/common/EditCircle.tsx +32 -0
- package/iconsvg/SVG/common/EditPriceIcon.tsx +20 -0
- package/iconsvg/SVG/common/EuroCurrency.tsx +18 -0
- package/iconsvg/SVG/common/Export.tsx +20 -0
- package/iconsvg/SVG/common/Eye.tsx +17 -0
- package/iconsvg/SVG/common/EyeCatch.tsx +19 -0
- package/iconsvg/SVG/common/FavoritesIcon.tsx +20 -0
- package/iconsvg/SVG/common/FilterRange.tsx +16 -0
- package/iconsvg/SVG/common/FilterToolBlack.tsx +23 -0
- package/iconsvg/SVG/common/FlagDe.tsx +21 -0
- package/iconsvg/SVG/common/FlagEn.tsx +43 -0
- package/iconsvg/SVG/common/GrayEnvelopeIcon.tsx +19 -0
- package/iconsvg/SVG/common/HamburgerMenuIcon.tsx +18 -0
- package/iconsvg/SVG/common/HandingOverDashboard.tsx +32 -0
- package/iconsvg/SVG/common/ImageSettingsIcon.tsx +20 -0
- package/iconsvg/SVG/common/Info.tsx +16 -0
- package/iconsvg/SVG/common/InfoIcon.tsx +17 -0
- package/iconsvg/SVG/common/InfoTransparent.tsx +18 -0
- package/iconsvg/SVG/common/LogoutIcon.tsx +20 -0
- package/iconsvg/SVG/common/MagnifyingGlass.tsx +31 -0
- package/iconsvg/SVG/common/MenuArrow.tsx +16 -0
- package/iconsvg/SVG/common/MenuGrey.tsx +22 -0
- package/iconsvg/SVG/common/MobileDeLogo.tsx +108 -0
- package/iconsvg/SVG/common/MyOrderIcon.tsx +20 -0
- package/iconsvg/SVG/common/MyVehiclesIcon.tsx +20 -0
- package/iconsvg/SVG/common/NewFlagDe.tsx +25 -0
- package/iconsvg/SVG/common/NewFlagEn.tsx +34 -0
- package/iconsvg/SVG/common/OrderReceivedDashboard.tsx +27 -0
- package/iconsvg/SVG/common/Package.tsx +30 -0
- package/iconsvg/SVG/common/Phone.tsx +18 -0
- package/iconsvg/SVG/common/PhoneGrey.tsx +22 -0
- package/iconsvg/SVG/common/PickupDashboard.tsx +30 -0
- package/iconsvg/SVG/common/Picture.tsx +24 -0
- package/iconsvg/SVG/common/Pictures.tsx +32 -0
- package/iconsvg/SVG/common/Plus.tsx +16 -0
- package/iconsvg/SVG/common/PlusNew.tsx +16 -0
- package/iconsvg/SVG/common/PreparationDashboard.tsx +29 -0
- package/iconsvg/SVG/common/ProfileDashboard.tsx +24 -0
- package/iconsvg/SVG/common/ProfileIcon.tsx +17 -0
- package/iconsvg/SVG/common/Question.tsx +19 -0
- package/iconsvg/SVG/common/QuestionBold.tsx +25 -0
- package/iconsvg/SVG/common/RegistrationDashboard.tsx +31 -0
- package/iconsvg/SVG/common/SavedSearchsIcon.tsx +20 -0
- package/iconsvg/SVG/common/Search.tsx +19 -0
- package/iconsvg/SVG/common/SearchGrey.tsx +22 -0
- package/iconsvg/SVG/common/SettingPenIcon.tsx +20 -0
- package/iconsvg/SVG/common/Share.tsx +16 -0
- package/iconsvg/SVG/common/ShoppingCart.tsx +18 -0
- package/iconsvg/SVG/common/SliderArrow.tsx +21 -0
- package/iconsvg/SVG/common/SliderEye.tsx +17 -0
- package/iconsvg/SVG/common/SortUpDownArrows.tsx +18 -0
- package/iconsvg/SVG/common/Speedometer.tsx +23 -0
- package/iconsvg/SVG/common/Star.tsx +20 -0
- package/iconsvg/SVG/common/StarNew.tsx +16 -0
- package/iconsvg/SVG/common/StarOutline.tsx +20 -0
- package/iconsvg/SVG/common/StarRoundedCorners.tsx +18 -0
- package/iconsvg/SVG/common/Stats.tsx +17 -0
- package/iconsvg/SVG/common/Step1.tsx +21 -0
- package/iconsvg/SVG/common/Step2.tsx +20 -0
- package/iconsvg/SVG/common/Step3.tsx +21 -0
- package/iconsvg/SVG/common/SupportCallbackIcon.tsx +20 -0
- package/iconsvg/SVG/common/Telephone.tsx +22 -0
- package/iconsvg/SVG/common/Time.tsx +17 -0
- package/iconsvg/SVG/common/Timetable.tsx +18 -0
- package/iconsvg/SVG/common/Trash.tsx +22 -0
- package/iconsvg/SVG/common/TrashRed.tsx +23 -0
- package/iconsvg/SVG/common/Upload.tsx +17 -0
- package/iconsvg/SVG/common/UserGrey.tsx +22 -0
- package/iconsvg/SVG/common/UserProfileIcon.tsx +20 -0
- package/iconsvg/SVG/common/ValidateFailure.tsx +21 -0
- package/iconsvg/SVG/common/ValidateSuccess.tsx +21 -0
- package/iconsvg/SVG/common/WarningTriangle.tsx +20 -0
- package/iconsvg/SVG/common/WhiteArrowUp.tsx +21 -0
- package/iconsvg/SVG/common/WhiteKey.tsx +21 -0
- package/iconsvg/SVG/common/WhitePeople.tsx +23 -0
- package/iconsvg/SVG/common/WhiteTick.tsx +19 -0
- package/iconsvg/SVG/flags/AT.tsx +19 -0
- package/iconsvg/SVG/flags/BE.tsx +20 -0
- package/iconsvg/SVG/flags/BG.tsx +20 -0
- package/iconsvg/SVG/flags/CH.tsx +22 -0
- package/iconsvg/SVG/flags/CZ.tsx +18 -0
- package/iconsvg/SVG/flags/DE.tsx +18 -0
- package/iconsvg/SVG/flags/DK.tsx +18 -0
- package/iconsvg/SVG/flags/ES.tsx +2585 -0
- package/iconsvg/SVG/flags/FI.tsx +18 -0
- package/iconsvg/SVG/flags/FR.tsx +20 -0
- package/iconsvg/SVG/flags/GB.tsx +26 -0
- package/iconsvg/SVG/flags/HR.tsx +135 -0
- package/iconsvg/SVG/flags/HU.tsx +20 -0
- package/iconsvg/SVG/flags/IT.tsx +20 -0
- package/iconsvg/SVG/flags/LI.tsx +106 -0
- package/iconsvg/SVG/flags/LU.tsx +18 -0
- package/iconsvg/SVG/flags/NL.tsx +18 -0
- package/iconsvg/SVG/flags/NO.tsx +20 -0
- package/iconsvg/SVG/flags/PL.tsx +19 -0
- package/iconsvg/SVG/flags/RO.tsx +20 -0
- package/iconsvg/SVG/flags/RU.tsx +20 -0
- package/iconsvg/SVG/flags/SE.tsx +20 -0
- package/iconsvg/SVG/flags/SI.tsx +54 -0
- package/iconsvg/SVG/flags/SK.tsx +34 -0
- package/iconsvg/SVG/flags/UA.tsx +19 -0
- package/iconsvg/SVG/infoBlocks/14DaysReturnPolicy.tsx +18 -0
- package/iconsvg/SVG/infoBlocks/AlertInfo.tsx +19 -0
- package/iconsvg/SVG/infoBlocks/Autocheck.tsx +19 -0
- package/iconsvg/SVG/infoBlocks/CheckTheStory.tsx +22 -0
- package/iconsvg/SVG/infoBlocks/CustomerServiceWhite.tsx +16 -0
- package/iconsvg/SVG/infoBlocks/Guarantee.tsx +16 -0
- package/iconsvg/SVG/infoBlocks/OrderWhite.tsx +13 -0
- package/iconsvg/SVG/infoBlocks/PriceGuarantee.tsx +19 -0
- package/iconsvg/SVG/infoBlocks/PriceGuaranteeWhite.tsx +17 -0
- package/iconsvg/SVG/infoBlocks/TransportAndDelivery.tsx +21 -0
- package/iconsvg/SVG/infoBlocks/Warranty.tsx +23 -0
- package/iconsvg/SVG/popower/Mail.tsx +18 -0
- package/iconsvg/SVG/popower/Phone.tsx +19 -0
- package/iconsvg/SVG/popower/Schedule.tsx +18 -0
- package/iconsvg/SVG/searchWidgets/drive/AAllWheelDrive.tsx +26 -0
- package/iconsvg/SVG/searchWidgets/drive/AllWheelDrive.tsx +26 -0
- package/iconsvg/SVG/searchWidgets/drive/FrontWheelDrive.tsx +25 -0
- package/iconsvg/SVG/searchWidgets/drive/OtherWheelDrive.tsx +26 -0
- package/iconsvg/SVG/searchWidgets/drive/RearWheelDrive.tsx +25 -0
- package/iconsvg/SVG/searchWidgets/fuel/FuelDiesel.tsx +18 -0
- package/iconsvg/SVG/searchWidgets/fuel/FuelElectrical.tsx +19 -0
- package/iconsvg/SVG/searchWidgets/fuel/FuelElectricalDiesel.tsx +34 -0
- package/iconsvg/SVG/searchWidgets/fuel/FuelElectricalPetrol.tsx +20 -0
- package/iconsvg/SVG/searchWidgets/fuel/FuelEthanol.tsx +53 -0
- package/iconsvg/SVG/searchWidgets/fuel/FuelHydrogen.tsx +24 -0
- package/iconsvg/SVG/searchWidgets/fuel/FuelLpg.tsx +24 -0
- package/iconsvg/SVG/searchWidgets/fuel/FuelNaturalGas.tsx +23 -0
- package/iconsvg/SVG/searchWidgets/fuel/FuelOther.tsx +28 -0
- package/iconsvg/SVG/searchWidgets/fuel/FuelPetrol.tsx +18 -0
- package/iconsvg/SVG/settings/Account.tsx +17 -0
- package/iconsvg/SVG/settings/DataUsage.tsx +17 -0
- package/iconsvg/SVG/settings/MarketResearch.tsx +17 -0
- package/iconsvg/SVG/settings/Newsletter.tsx +17 -0
- package/iconsvg/SVG/settings/RemoveEye.tsx +17 -0
- package/iconsvg/SVG/settings/RemoveEyeOff.tsx +17 -0
- package/iconsvg/SVG/settings/Security.tsx +17 -0
- package/iconsvg/SVG/settings/Warning.tsx +17 -0
- package/iconsvg/SVG/slider/360.tsx +23 -0
- package/iconsvg/SVG/slider/360New.tsx +20 -0
- package/iconsvg/SVG/slider/Checked.tsx +19 -0
- package/iconsvg/SVG/slider/DiscountRibbon.tsx +51 -0
- package/iconsvg/SVG/slider/DiscountRibbonMobile.tsx +47 -0
- package/iconsvg/SVG/slider/DiscountRibbonNew.tsx +29 -0
- package/iconsvg/SVG/slider/Easy.tsx +19 -0
- package/iconsvg/SVG/slider/Fullscreen.tsx +16 -0
- package/iconsvg/SVG/slider/FullscreenWindow.tsx +23 -0
- package/iconsvg/SVG/slider/Safe.tsx +19 -0
- package/iconsvg/SVG/slider/ToBuy.tsx +19 -0
- package/iconsvg/SVG/slider/YoutubeButton.tsx +26 -0
- package/iconsvg/SVG/slider/ZoomIn.tsx +21 -0
- package/iconsvg/SVG/slider/ZoomOut.tsx +21 -0
- package/iconsvg/SVG/social/AndroidLogo.tsx +18 -0
- package/iconsvg/SVG/social/Apple.tsx +19 -0
- package/iconsvg/SVG/social/FacebookF.tsx +19 -0
- package/iconsvg/SVG/social/GooglePlusG.tsx +19 -0
- package/iconsvg/SVG/social/Instagram.tsx +17 -0
- package/iconsvg/SVG/social/Pinterest.tsx +19 -0
- package/iconsvg/SVG/social/SharingInterface.tsx +21 -0
- package/iconsvg/SVG/social/Twitter.tsx +19 -0
- package/iconsvg/SVG/social/Youtube.tsx +19 -0
- package/iconsvg/SVG/vehicle/AboIcon.tsx +11 -0
- package/iconsvg/SVG/vehicle/Abs.tsx +24 -0
- package/iconsvg/SVG/vehicle/AirCond.tsx +34 -0
- package/iconsvg/SVG/vehicle/Airbag.tsx +21 -0
- package/iconsvg/SVG/vehicle/AuxiliaryHeating.tsx +23 -0
- package/iconsvg/SVG/vehicle/Bluetooth.tsx +22 -0
- package/iconsvg/SVG/vehicle/BuyIcon.tsx +15 -0
- package/iconsvg/SVG/vehicle/CarAvailability.tsx +22 -0
- package/iconsvg/SVG/vehicle/CarInspectionCheck.tsx +21 -0
- package/iconsvg/SVG/vehicle/CarInspectionCross.tsx +21 -0
- package/iconsvg/SVG/vehicle/CheckoutChecked.tsx +15 -0
- package/iconsvg/SVG/vehicle/Co2.tsx +24 -0
- package/iconsvg/SVG/vehicle/CruiseControl.tsx +25 -0
- package/iconsvg/SVG/vehicle/Date.tsx +21 -0
- package/iconsvg/SVG/vehicle/Delivery.tsx +12 -0
- package/iconsvg/SVG/vehicle/Diesel.tsx +28 -0
- package/iconsvg/SVG/vehicle/Display.tsx +25 -0
- package/iconsvg/SVG/vehicle/Done.tsx +11 -0
- package/iconsvg/SVG/vehicle/Door.tsx +19 -0
- package/iconsvg/SVG/vehicle/DoubleDone.tsx +18 -0
- package/iconsvg/SVG/vehicle/EditIcon.tsx +11 -0
- package/iconsvg/SVG/vehicle/EmergencyBrakeAssistant.tsx +27 -0
- package/iconsvg/SVG/vehicle/Eps.tsx +24 -0
- package/iconsvg/SVG/vehicle/Esp.tsx +24 -0
- package/iconsvg/SVG/vehicle/FinancingIcon.tsx +20 -0
- package/iconsvg/SVG/vehicle/FuelConsumption.tsx +20 -0
- package/iconsvg/SVG/vehicle/Fueling.tsx +22 -0
- package/iconsvg/SVG/vehicle/FullDrive.tsx +24 -0
- package/iconsvg/SVG/vehicle/GasElectric.tsx +28 -0
- package/iconsvg/SVG/vehicle/HandsFreePhoneSystem.tsx +24 -0
- package/iconsvg/SVG/vehicle/Kw.tsx +23 -0
- package/iconsvg/SVG/vehicle/LastCrawledAt.tsx +22 -0
- package/iconsvg/SVG/vehicle/LeasingIcon.tsx +14 -0
- package/iconsvg/SVG/vehicle/Led.tsx +24 -0
- package/iconsvg/SVG/vehicle/LightSensor.tsx +22 -0
- package/iconsvg/SVG/vehicle/LinkAlternative.tsx +15 -0
- package/iconsvg/SVG/vehicle/Location.tsx +17 -0
- package/iconsvg/SVG/vehicle/MinusIcon.tsx +11 -0
- package/iconsvg/SVG/vehicle/Mirror.tsx +19 -0
- package/iconsvg/SVG/vehicle/Navigation.tsx +27 -0
- package/iconsvg/SVG/vehicle/NewCar.tsx +21 -0
- package/iconsvg/SVG/vehicle/NoImage.tsx +17 -0
- package/iconsvg/SVG/vehicle/Owner.tsx +18 -0
- package/iconsvg/SVG/vehicle/PanoramicRoof.tsx +23 -0
- package/iconsvg/SVG/vehicle/ParkingAssistants.tsx +24 -0
- package/iconsvg/SVG/vehicle/PickYourself.tsx +18 -0
- package/iconsvg/SVG/vehicle/PlusIcon.tsx +11 -0
- package/iconsvg/SVG/vehicle/Power.tsx +21 -0
- package/iconsvg/SVG/vehicle/Ps.tsx +19 -0
- package/iconsvg/SVG/vehicle/Question.tsx +24 -0
- package/iconsvg/SVG/vehicle/Seats.tsx +21 -0
- package/iconsvg/SVG/vehicle/SeatsHeating.tsx +26 -0
- package/iconsvg/SVG/vehicle/SelectorGearboxAutomatic.tsx +24 -0
- package/iconsvg/SVG/vehicle/SelectorGearboxManualShift.tsx +19 -0
- package/iconsvg/SVG/vehicle/SelectorGearboxOther.tsx +24 -0
- package/iconsvg/SVG/vehicle/SelectorGearboxSemiAutomatic.tsx +30 -0
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeAlcantara.tsx +225 -0
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeFabric.tsx +29 -0
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeFullLeather.tsx +29 -0
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeOther.tsx +26 -0
- package/iconsvg/SVG/vehicle/SelectorInteriorTypePartLeather.tsx +142 -0
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeSyntheticLeather.tsx +27 -0
- package/iconsvg/SVG/vehicle/SelectorInteriorTypeVelours.tsx +39 -0
- package/iconsvg/SVG/vehicle/Shield.tsx +39 -0
- package/iconsvg/SVG/vehicle/Speedometer.tsx +17 -0
- package/iconsvg/SVG/vehicle/StartStopSystem.tsx +30 -0
- package/iconsvg/SVG/vehicle/Stop.tsx +25 -0
- package/iconsvg/SVG/vehicle/TickMark.tsx +21 -0
- package/iconsvg/SVG/vehicle/TrafficSignRecognition.tsx +29 -0
- package/iconsvg/SVG/vehicle/TrailerCoupling.tsx +24 -0
- package/iconsvg/SVG/vehicle/Transmission.tsx +27 -0
- package/iconsvg/SVG/vehicle/Wheel.tsx +43 -0
- package/iconsvg/SVG/vehicle/Wipers.tsx +22 -0
- package/iconsvg/SVG/vehicle/Wrench.tsx +17 -0
- package/iconsvg/index.ts +7 -0
- package/index.ts +18 -0
- package/locales/de/autobahn.json +671 -0
- package/locales/en/autobahn.json +671 -0
- package/locales/legacy/SearchDetailedPage.ts +205 -0
- package/locales/legacy/cbd.ts +719 -0
- package/locales/legacy/common.ts +109 -0
- package/locales/legacy/data.ts +1118 -0
- package/locales/legacy/priceRating.ts +10 -0
- package/locales/legacy/sortingOptions.ts +21 -0
- package/media/images/question.svg +1 -0
- package/media/images/raiting-stars-min.svg +7 -0
- package/media/images/refresh-button.svg +49 -0
- package/media/images/searchWidget/selector_emissionSticker_green.png +0 -0
- package/media/images/searchWidget/selector_emissionSticker_red.png +0 -0
- package/media/images/searchWidget/selector_emissionSticker_yellow.png +0 -0
- package/media/images/slider-arrow-new.svg +1 -0
- package/media/images/user-icon.svg +16 -0
- package/media/svg/common/eye.svg +1 -0
- package/media/svg/common/star.svg +1 -0
- package/media/svg/infoBlocks/whyAutodeIconSet-F.svg +9 -0
- package/media/svg/infoBlocks/whyAutodeIconSet-G.svg +8 -0
- package/media/svg/infoBlocks/whyAutodeIconSet-Q.svg +6 -0
- package/media/svg/infoBlocks/whyAutodeIconSet-R.svg +9 -0
- package/media/svg/usp/icon1.svg +16 -0
- package/media/svg/usp/icon2.svg +13 -0
- package/media/svg/usp/icon3.svg +10 -0
- package/media/svg/usp/icon4.svg +14 -0
- package/package.json +30 -0
- package/schemes/AggregationScheme.ts +73 -0
- package/searchFilters/filterOptions.ts +119 -0
- package/searchFilters/filterProps.ts +35 -0
- package/searchFilters/index.ts +15 -0
- package/theme/autobahn.css +25 -0
- package/theme/colors_and_type.css +113 -0
- package/theme/md3.css +2034 -0
- package/types/types.ts +374 -0
- package/types.ts +8 -0
- package/ui/Accordion.tsx +134 -0
- package/ui/Button.tsx +62 -0
- package/ui/CardCarousel.tsx +133 -0
- package/ui/Chip.tsx +29 -0
- package/ui/DatePicker.tsx +145 -0
- package/ui/Dropdown.tsx +205 -0
- package/ui/FileUpload.tsx +154 -0
- package/ui/FormCheckbox.tsx +79 -0
- package/ui/FormDropdown.tsx +327 -0
- package/ui/FormField.tsx +88 -0
- package/ui/FormRadio.tsx +93 -0
- package/ui/FormRadioGroup.tsx +106 -0
- package/ui/Icon.tsx +391 -0
- package/ui/IconButton.tsx +44 -0
- package/ui/Modal.tsx +187 -0
- package/ui/Pagination.tsx +140 -0
- package/ui/Price.tsx +25 -0
- package/ui/PriceEvalBar.tsx +48 -0
- package/ui/SaveChip.tsx +34 -0
- package/ui/Segmented.tsx +48 -0
- package/ui/Skeleton.tsx +75 -0
- package/ui/Spec.tsx +24 -0
- package/ui/Stars.tsx +29 -0
- package/ui/StatChip.tsx +21 -0
- package/ui/Stepper.tsx +106 -0
- package/ui/Switch.tsx +65 -0
- package/ui/Table.tsx +156 -0
- package/ui/Textarea.tsx +58 -0
- package/ui/index.ts +88 -0
- package/utils/CommonUtils.ts +649 -0
- package/utils/DateUtils.ts +101 -0
- package/utils/index.ts +74 -0
- package/utils/power.ts +11 -0
- package/utils/query.ts +21 -0
- package/vdp/FinanceCalculator.tsx +465 -0
- package/vdp/VdpModules.tsx +1490 -0
- package/vdp/VdpViewer.tsx +139 -0
- package/vdp/index.ts +75 -0
- package/vdp/types.ts +197 -0
- package/vehiclesProps/cbdSelectors.ts +117 -0
- package/vehiclesProps/decoratedLightProps.tsx +572 -0
- package/vehiclesProps/decoratedProps.tsx +1746 -0
- package/vehiclesProps/equipment.ts +129 -0
- package/vehiclesProps/vehicleDetails.ts +428 -0
- package/widgets/SearchBox.tsx +256 -0
- package/widgets/index.ts +5 -0
package/ui/Modal.tsx
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// Autobahn (auto.de redesign) — md3 dialog (modal).
|
|
2
|
+
//
|
|
3
|
+
// A real MD3 dialog used by the new Autobahn pages in place of the legacy fe-ui-core
|
|
4
|
+
// modals (which the page shows via appStore.showModal('SOME_ID', props) and a global
|
|
5
|
+
// modal host renders into document.body — OUTSIDE the page's `.md3` subtree, so the
|
|
6
|
+
// scoped md3 theme is lost there).
|
|
7
|
+
//
|
|
8
|
+
// To keep the md3 tokens, this component does NOT render inline: it ReactDOM.createPortal's
|
|
9
|
+
// into a freshly-appended `<div className="md3">` on document.body, so `--md-*` tokens and
|
|
10
|
+
// every `.md3 .xxx` rule resolve correctly even though the DOM node sits at body level.
|
|
11
|
+
//
|
|
12
|
+
// Behaviour parity with a typical dialog:
|
|
13
|
+
// - controlled via `open`; `onClose` fires on scrim click (when dismissOnScrim),
|
|
14
|
+
// the close IconButton, and Esc.
|
|
15
|
+
// - scrim ~50% black; body scroll-locked while open; basic focus trap (Tab/Shift+Tab
|
|
16
|
+
// cycle within the surface, focus moves into the dialog on open and is restored to the
|
|
17
|
+
// previously-focused element on close).
|
|
18
|
+
// - a11y: role=dialog, aria-modal, aria-labelledby wired to the title when present.
|
|
19
|
+
//
|
|
20
|
+
// Pure/presentational — no store/API access beyond document/body (all SSR-guarded). The
|
|
21
|
+
// portal root carries `className="md3"` so the surface renders correctly even at body level.
|
|
22
|
+
|
|
23
|
+
import * as React from 'react';
|
|
24
|
+
import * as ReactDOM from 'react-dom';
|
|
25
|
+
|
|
26
|
+
import IconButton from './IconButton';
|
|
27
|
+
|
|
28
|
+
export type ModalSize = 'sm' | 'md' | 'lg';
|
|
29
|
+
|
|
30
|
+
export interface ModalProps {
|
|
31
|
+
/** whether the dialog is mounted/visible. */
|
|
32
|
+
open: boolean;
|
|
33
|
+
/** fired on scrim click (if dismissOnScrim), the close button, or Esc. */
|
|
34
|
+
onClose: () => void;
|
|
35
|
+
/** dialog heading; when set, wires aria-labelledby and renders the title row label. */
|
|
36
|
+
title?: React.ReactNode;
|
|
37
|
+
/** dialog body content (scrolls when taller than the viewport). */
|
|
38
|
+
children?: React.ReactNode;
|
|
39
|
+
/** optional actions row pinned to the bottom of the surface. */
|
|
40
|
+
footer?: React.ReactNode;
|
|
41
|
+
/** surface max-width preset (default 'md'). */
|
|
42
|
+
size?: ModalSize;
|
|
43
|
+
/** close when the scrim (backdrop) is clicked (default true). */
|
|
44
|
+
dismissOnScrim?: boolean;
|
|
45
|
+
/** extra class(es) appended on the surface (layout hooks). */
|
|
46
|
+
className?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// focusable descendants used by the basic focus trap.
|
|
50
|
+
const FOCUSABLE =
|
|
51
|
+
'a[href],area[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
|
|
52
|
+
|
|
53
|
+
const Modal: React.FunctionComponent<ModalProps> = ({
|
|
54
|
+
open,
|
|
55
|
+
onClose,
|
|
56
|
+
title,
|
|
57
|
+
children,
|
|
58
|
+
footer,
|
|
59
|
+
size = 'md',
|
|
60
|
+
dismissOnScrim = true,
|
|
61
|
+
className,
|
|
62
|
+
}) => {
|
|
63
|
+
const surfaceRef = React.useRef<HTMLDivElement | null>(null);
|
|
64
|
+
// the element focused before the dialog opened, so focus can be restored on close.
|
|
65
|
+
const prevFocusRef = React.useRef<HTMLElement | null>(null);
|
|
66
|
+
// stable id for aria-labelledby (avoids Math.random/Date.now, unavailable in this env).
|
|
67
|
+
const titleId = React.useMemo(
|
|
68
|
+
() => (title ? `mmodal-title-${Math.round((surfaceRef.current ? 1 : 0))}-${size}` : undefined),
|
|
69
|
+
[title, size],
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// The portal root: a div.md3 appended to body so the scoped theme applies at body level.
|
|
73
|
+
// Created lazily and only in the browser (SSR-guarded), reused for the component's life.
|
|
74
|
+
const portalRoot = React.useMemo<HTMLDivElement | null>(() => {
|
|
75
|
+
if (typeof document === 'undefined') return null;
|
|
76
|
+
const el = document.createElement('div');
|
|
77
|
+
el.className = 'md3';
|
|
78
|
+
return el;
|
|
79
|
+
}, []);
|
|
80
|
+
|
|
81
|
+
// mount/unmount the portal root on body while open; restore body scroll + focus on close.
|
|
82
|
+
React.useEffect(() => {
|
|
83
|
+
if (!open || !portalRoot || typeof document === 'undefined') return undefined;
|
|
84
|
+
|
|
85
|
+
prevFocusRef.current = (document.activeElement as HTMLElement) || null;
|
|
86
|
+
document.body.appendChild(portalRoot);
|
|
87
|
+
|
|
88
|
+
// body scroll lock (preserve and restore the prior inline overflow).
|
|
89
|
+
const prevOverflow = document.body.style.overflow;
|
|
90
|
+
document.body.style.overflow = 'hidden';
|
|
91
|
+
|
|
92
|
+
// move focus into the dialog (first focusable, else the surface itself).
|
|
93
|
+
const surface = surfaceRef.current;
|
|
94
|
+
if (surface) {
|
|
95
|
+
const first = surface.querySelector<HTMLElement>(FOCUSABLE);
|
|
96
|
+
(first || surface).focus();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return () => {
|
|
100
|
+
document.body.style.overflow = prevOverflow;
|
|
101
|
+
if (portalRoot.parentNode) portalRoot.parentNode.removeChild(portalRoot);
|
|
102
|
+
// restore focus to whatever was focused before opening.
|
|
103
|
+
if (prevFocusRef.current && prevFocusRef.current.focus) prevFocusRef.current.focus();
|
|
104
|
+
};
|
|
105
|
+
}, [open, portalRoot]);
|
|
106
|
+
|
|
107
|
+
// Esc to close + basic Tab focus trap, bound at the document level while open.
|
|
108
|
+
React.useEffect(() => {
|
|
109
|
+
if (!open || typeof document === 'undefined') return undefined;
|
|
110
|
+
const onKeyDown = (e: KeyboardEvent) => {
|
|
111
|
+
if (e.key === 'Escape') {
|
|
112
|
+
e.preventDefault();
|
|
113
|
+
onClose();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (e.key !== 'Tab') return;
|
|
117
|
+
const surface = surfaceRef.current;
|
|
118
|
+
if (!surface) return;
|
|
119
|
+
const nodes = Array.prototype.slice.call(
|
|
120
|
+
surface.querySelectorAll<HTMLElement>(FOCUSABLE),
|
|
121
|
+
) as HTMLElement[];
|
|
122
|
+
if (!nodes.length) {
|
|
123
|
+
// nothing focusable inside — keep focus on the surface.
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
surface.focus();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const first = nodes[0];
|
|
129
|
+
const last = nodes[nodes.length - 1];
|
|
130
|
+
const active = document.activeElement as HTMLElement | null;
|
|
131
|
+
// wrap at the edges; also pull focus back in if it has escaped the surface.
|
|
132
|
+
if (e.shiftKey) {
|
|
133
|
+
if (active === first || !surface.contains(active)) {
|
|
134
|
+
e.preventDefault();
|
|
135
|
+
last.focus();
|
|
136
|
+
}
|
|
137
|
+
} else if (active === last || !surface.contains(active)) {
|
|
138
|
+
e.preventDefault();
|
|
139
|
+
first.focus();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
document.addEventListener('keydown', onKeyDown, true);
|
|
143
|
+
return () => document.removeEventListener('keydown', onKeyDown, true);
|
|
144
|
+
}, [open, onClose]);
|
|
145
|
+
|
|
146
|
+
if (!open || !portalRoot) return null;
|
|
147
|
+
|
|
148
|
+
const surfaceCls = ['mmodal', `mmodal--${size}`, className].filter(Boolean).join(' ');
|
|
149
|
+
|
|
150
|
+
return ReactDOM.createPortal(
|
|
151
|
+
<div
|
|
152
|
+
className="mmodal-scrim"
|
|
153
|
+
onMouseDown={(e) => {
|
|
154
|
+
// only a click that starts AND lands on the scrim itself dismisses (not a drag
|
|
155
|
+
// that ends on the backdrop after starting inside the surface).
|
|
156
|
+
if (dismissOnScrim && e.target === e.currentTarget) onClose();
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
<div
|
|
160
|
+
ref={surfaceRef}
|
|
161
|
+
className={surfaceCls}
|
|
162
|
+
role="dialog"
|
|
163
|
+
aria-modal="true"
|
|
164
|
+
aria-labelledby={title ? titleId : undefined}
|
|
165
|
+
tabIndex={-1}
|
|
166
|
+
onMouseDown={(e) => e.stopPropagation()}
|
|
167
|
+
>
|
|
168
|
+
{/* head row always renders so the close button is always present. */}
|
|
169
|
+
<div className="mmodal-head">
|
|
170
|
+
{title ? (
|
|
171
|
+
<h2 id={titleId} className="mmodal-title md-headline-sm">
|
|
172
|
+
{title}
|
|
173
|
+
</h2>
|
|
174
|
+
) : (
|
|
175
|
+
<span className="mmodal-title" aria-hidden="true" />
|
|
176
|
+
)}
|
|
177
|
+
<IconButton name="x" label="Schließen" onClick={onClose} />
|
|
178
|
+
</div>
|
|
179
|
+
<div className="mmodal-body">{children}</div>
|
|
180
|
+
{footer ? <div className="mmodal-foot">{footer}</div> : null}
|
|
181
|
+
</div>
|
|
182
|
+
</div>,
|
|
183
|
+
portalRoot,
|
|
184
|
+
);
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export default Modal;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Autobahn (auto.de redesign) — md3 pager.
|
|
2
|
+
//
|
|
3
|
+
// Drop-in visual replacement for the legacy components/ui/Pagination/Pagination. Same prop
|
|
4
|
+
// surface (t, className?, totalPages, step?, currentPage?, changePage?) and the SAME click
|
|
5
|
+
// behaviour: the target page is clamped into [1, totalPages] before changePage() fires, so the
|
|
6
|
+
// existing Mitarbeiter (DealerEmployeesPage) / MyVehicles (MyVehiclesPage) callers work unchanged.
|
|
7
|
+
//
|
|
8
|
+
// Visual upgrade over the legacy 3-button strip: a real md3 pager with a prev/next pill plus
|
|
9
|
+
// numbered page buttons (current = filled primary) and ellipsis when the range is long.
|
|
10
|
+
//
|
|
11
|
+
// Pure/presentational — no store/API/window. Renders correctly only inside a `<div className="md3">`
|
|
12
|
+
// subtree (scoped theme); all classes use the `mpag-` prefix.
|
|
13
|
+
|
|
14
|
+
import * as React from 'react';
|
|
15
|
+
|
|
16
|
+
import Icon from './Icon';
|
|
17
|
+
|
|
18
|
+
export interface PaginationProps {
|
|
19
|
+
/** i18n translate — supplies the prev/next labels via common:goBack / common:goForward (legacy keys). */
|
|
20
|
+
t: (key: string, options?: object) => string;
|
|
21
|
+
/** total number of pages. */
|
|
22
|
+
totalPages: number;
|
|
23
|
+
/** 1-based current page. */
|
|
24
|
+
currentPage?: number;
|
|
25
|
+
/** fired with the chosen (clamped) 1-based page. */
|
|
26
|
+
changePage?: (page: number) => void;
|
|
27
|
+
/** kept for legacy prop-surface parity (unused by the md3 pager). */
|
|
28
|
+
step?: number;
|
|
29
|
+
/** extra class on the wrapper. */
|
|
30
|
+
className?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// How many numbered buttons to show before collapsing the middle into ellipsis.
|
|
34
|
+
// Window = first, last, current, and one neighbour each side (+ up to two ellipsis slots).
|
|
35
|
+
const SIBLINGS = 1;
|
|
36
|
+
const ELLIPSIS = 'ellipsis';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Build the list of page tokens to render: numbers and 'ellipsis' gaps.
|
|
40
|
+
* Always includes page 1 and totalPages; collapses long runs around the current page.
|
|
41
|
+
*/
|
|
42
|
+
function buildRange(currentPage: number, totalPages: number): Array<number | typeof ELLIPSIS> {
|
|
43
|
+
// Small enough to show every page (first + last + 2*siblings + 2 ellipsis-or-page slots).
|
|
44
|
+
if (totalPages <= SIBLINGS * 2 + 5) {
|
|
45
|
+
const all: Array<number | typeof ELLIPSIS> = [];
|
|
46
|
+
for (let p = 1; p <= totalPages; p += 1) all.push(p);
|
|
47
|
+
return all;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const left = Math.max(currentPage - SIBLINGS, 1);
|
|
51
|
+
const right = Math.min(currentPage + SIBLINGS, totalPages);
|
|
52
|
+
const showLeftEllipsis = left > 2;
|
|
53
|
+
const showRightEllipsis = right < totalPages - 1;
|
|
54
|
+
|
|
55
|
+
const range: Array<number | typeof ELLIPSIS> = [1];
|
|
56
|
+
// If there is no left gap, fill pages 2..left so the run stays contiguous.
|
|
57
|
+
if (showLeftEllipsis) range.push(ELLIPSIS);
|
|
58
|
+
else for (let p = 2; p < left; p += 1) range.push(p);
|
|
59
|
+
|
|
60
|
+
for (let p = left; p <= right; p += 1) if (p !== 1 && p !== totalPages) range.push(p);
|
|
61
|
+
|
|
62
|
+
if (showRightEllipsis) range.push(ELLIPSIS);
|
|
63
|
+
else for (let p = right + 1; p < totalPages; p += 1) range.push(p);
|
|
64
|
+
|
|
65
|
+
range.push(totalPages);
|
|
66
|
+
return range;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const Pagination: React.FunctionComponent<PaginationProps> = ({
|
|
70
|
+
t,
|
|
71
|
+
totalPages,
|
|
72
|
+
currentPage = 1,
|
|
73
|
+
changePage,
|
|
74
|
+
className,
|
|
75
|
+
}) => {
|
|
76
|
+
if (!totalPages || totalPages < 1) return null;
|
|
77
|
+
|
|
78
|
+
// Clamp into [1, totalPages] exactly like the legacy onButtonClick, then notify.
|
|
79
|
+
const go = (value: number) => {
|
|
80
|
+
if (!changePage) return;
|
|
81
|
+
let computed = value < 1 ? 1 : value;
|
|
82
|
+
computed = computed > totalPages ? totalPages : computed;
|
|
83
|
+
changePage(computed);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const backDisabled = currentPage <= 1;
|
|
87
|
+
const forwardDisabled = currentPage >= totalPages;
|
|
88
|
+
const wrapCls = ['mpag', className].filter(Boolean).join(' ');
|
|
89
|
+
|
|
90
|
+
const tokens = buildRange(currentPage, totalPages);
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<nav className={wrapCls} role="navigation" aria-label="Pagination">
|
|
94
|
+
<button
|
|
95
|
+
type="button"
|
|
96
|
+
className="mpag-edge mpag-edge--prev"
|
|
97
|
+
disabled={backDisabled}
|
|
98
|
+
aria-label={t('common:goBack')}
|
|
99
|
+
onClick={() => go(currentPage - 1)}
|
|
100
|
+
>
|
|
101
|
+
<Icon name="chevron-left" size={18} />
|
|
102
|
+
<span className="mpag-edge-label">{t('common:goBack')}</span>
|
|
103
|
+
</button>
|
|
104
|
+
|
|
105
|
+
<ul className="mpag-list">
|
|
106
|
+
{tokens.map((tok, i) =>
|
|
107
|
+
tok === ELLIPSIS ? (
|
|
108
|
+
<li key={`e${i}`} className="mpag-gap" aria-hidden="true">
|
|
109
|
+
…
|
|
110
|
+
</li>
|
|
111
|
+
) : (
|
|
112
|
+
<li key={tok}>
|
|
113
|
+
<button
|
|
114
|
+
type="button"
|
|
115
|
+
className={'mpag-page' + (tok === currentPage ? ' is-current' : '')}
|
|
116
|
+
aria-current={tok === currentPage ? 'page' : undefined}
|
|
117
|
+
onClick={() => go(tok)}
|
|
118
|
+
>
|
|
119
|
+
<span className="num">{tok}</span>
|
|
120
|
+
</button>
|
|
121
|
+
</li>
|
|
122
|
+
),
|
|
123
|
+
)}
|
|
124
|
+
</ul>
|
|
125
|
+
|
|
126
|
+
<button
|
|
127
|
+
type="button"
|
|
128
|
+
className="mpag-edge mpag-edge--next"
|
|
129
|
+
disabled={forwardDisabled}
|
|
130
|
+
aria-label={t('common:goForward')}
|
|
131
|
+
onClick={() => go(currentPage + 1)}
|
|
132
|
+
>
|
|
133
|
+
<span className="mpag-edge-label">{t('common:goForward')}</span>
|
|
134
|
+
<Icon name="chevron-right" size={18} />
|
|
135
|
+
</button>
|
|
136
|
+
</nav>
|
|
137
|
+
);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export default Pagination;
|
package/ui/Price.tsx
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export interface PriceProps {
|
|
4
|
+
/** price in EUR; formatted with the de-DE locale. */
|
|
5
|
+
value: number;
|
|
6
|
+
size?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Price in strong neutral text (modern) — no green spam. */
|
|
10
|
+
const Price: React.FunctionComponent<PriceProps> = ({ value, size = 26 }) => (
|
|
11
|
+
<span
|
|
12
|
+
className="num"
|
|
13
|
+
style={{
|
|
14
|
+
fontWeight: 700,
|
|
15
|
+
fontSize: size,
|
|
16
|
+
color: 'var(--md-on-surface)',
|
|
17
|
+
letterSpacing: '-.5px',
|
|
18
|
+
whiteSpace: 'nowrap',
|
|
19
|
+
}}
|
|
20
|
+
>
|
|
21
|
+
{value.toLocaleString('de-DE')} €
|
|
22
|
+
</span>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
export default Price;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { TIER_COLORS, TIER_LABELS, RatingTier } from '../constants';
|
|
4
|
+
|
|
5
|
+
export interface PriceEvalBarProps {
|
|
6
|
+
/** price tier 0 (Top) … 4 (Hoch). */
|
|
7
|
+
tier?: RatingTier;
|
|
8
|
+
/** thinner bar (6px instead of 8px). */
|
|
9
|
+
compact?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Preisbewertung mini bar — the trust signal: green→red gradient with a marker
|
|
14
|
+
* at the car's tier. Colors/labels come from the shared autobahn constants.
|
|
15
|
+
*/
|
|
16
|
+
const PriceEvalBar: React.FunctionComponent<PriceEvalBarProps> = ({ tier = 1, compact }) => (
|
|
17
|
+
<div style={{ width: '100%' }}>
|
|
18
|
+
<div
|
|
19
|
+
style={{
|
|
20
|
+
position: 'relative',
|
|
21
|
+
display: 'flex',
|
|
22
|
+
height: compact ? 6 : 8,
|
|
23
|
+
borderRadius: 'var(--md-r-full)',
|
|
24
|
+
overflow: 'hidden',
|
|
25
|
+
}}
|
|
26
|
+
aria-label={TIER_LABELS[tier]}
|
|
27
|
+
>
|
|
28
|
+
{TIER_COLORS.map((c, i) => (
|
|
29
|
+
<div key={i} style={{ flex: 1, background: c, opacity: i === tier ? 1 : 0.32 }} />
|
|
30
|
+
))}
|
|
31
|
+
<span
|
|
32
|
+
style={{
|
|
33
|
+
position: 'absolute',
|
|
34
|
+
top: '50%',
|
|
35
|
+
left: `calc(${(tier + 0.5) * 20}% - 6px)`,
|
|
36
|
+
transform: 'translateY(-50%)',
|
|
37
|
+
width: 12,
|
|
38
|
+
height: 12,
|
|
39
|
+
borderRadius: '50%',
|
|
40
|
+
background: '#fff',
|
|
41
|
+
boxShadow: '0 0 0 3px ' + TIER_COLORS[tier],
|
|
42
|
+
}}
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
export default PriceEvalBar;
|
package/ui/SaveChip.tsx
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TranslationFunction } from '../types';
|
|
3
|
+
|
|
4
|
+
import Icon from './Icon';
|
|
5
|
+
|
|
6
|
+
export interface SaveChipProps {
|
|
7
|
+
/** amount saved in EUR; formatted with the de-DE locale. */
|
|
8
|
+
amount: number;
|
|
9
|
+
t: TranslationFunction;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Savings chip (deal accent — used sparingly). */
|
|
13
|
+
const SaveChip: React.FunctionComponent<SaveChipProps> = ({ amount, t }) => (
|
|
14
|
+
<span
|
|
15
|
+
style={{
|
|
16
|
+
display: 'inline-flex',
|
|
17
|
+
alignItems: 'center',
|
|
18
|
+
gap: 5,
|
|
19
|
+
height: 26,
|
|
20
|
+
padding: '0 11px',
|
|
21
|
+
borderRadius: 'var(--md-r-full)',
|
|
22
|
+
background: 'var(--md-good)',
|
|
23
|
+
color: '#fff',
|
|
24
|
+
fontSize: 12.5,
|
|
25
|
+
fontWeight: 700,
|
|
26
|
+
whiteSpace: 'nowrap',
|
|
27
|
+
}}
|
|
28
|
+
>
|
|
29
|
+
<Icon name="trending-down" size={14} stroke={2.4} />
|
|
30
|
+
{t('autobahn:card.price.savedAmount', { amount: amount.toLocaleString('de-DE') })}
|
|
31
|
+
</span>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export default SaveChip;
|
package/ui/Segmented.tsx
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import Icon from './Icon';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* [value, label, optional kebab-case lucide icon name, optional explicit aria-label].
|
|
7
|
+
*
|
|
8
|
+
* `label` doubles as the button's visible text AND (when non-empty) its accessible name.
|
|
9
|
+
* Icon-only options (empty `label`, e.g. the SRP list/grid view toggle) render no visible
|
|
10
|
+
* text, so `Segmented` derives an accessible name from `key` (Title-cased) when neither
|
|
11
|
+
* `label` nor an explicit `ariaLabel` is supplied — every rendered `<button>` always ends up
|
|
12
|
+
* with SOME discernible name (WCAG 4.1.2 / axe "button-name"). Pass `ariaLabel` explicitly for
|
|
13
|
+
* a real (ideally translated) name instead of relying on the key-derived fallback.
|
|
14
|
+
*/
|
|
15
|
+
export type SegmentedOption = readonly [key: string, label: string, icon?: string, ariaLabel?: string];
|
|
16
|
+
|
|
17
|
+
export interface SegmentedProps {
|
|
18
|
+
options: ReadonlyArray<SegmentedOption>;
|
|
19
|
+
value: string;
|
|
20
|
+
onChange: (value: string) => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Title-cases a raw option key ('list' -> 'List') as a last-resort accessible name. */
|
|
24
|
+
const titleCase = (s: string): string => (s ? s.charAt(0).toUpperCase() + s.slice(1) : s);
|
|
25
|
+
|
|
26
|
+
const Segmented: React.FunctionComponent<SegmentedProps> = ({ options, value, onChange }) => (
|
|
27
|
+
<div className="segmented">
|
|
28
|
+
{options.map(([k, label, icon, ariaLabel]) => {
|
|
29
|
+
// only set aria-label when there's no visible text label already providing the name —
|
|
30
|
+
// avoids a redundant/conflicting name on labelled buttons (WCAG 2.5.3 Label in Name).
|
|
31
|
+
const accessibleName = ariaLabel || (label ? undefined : titleCase(k));
|
|
32
|
+
return (
|
|
33
|
+
<button
|
|
34
|
+
key={k}
|
|
35
|
+
type="button"
|
|
36
|
+
className={value === k ? 'on' : ''}
|
|
37
|
+
aria-label={accessibleName}
|
|
38
|
+
onClick={() => onChange(k)}
|
|
39
|
+
>
|
|
40
|
+
{icon && <Icon name={icon} size={16} />}
|
|
41
|
+
{label}
|
|
42
|
+
</button>
|
|
43
|
+
);
|
|
44
|
+
})}
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
export default Segmented;
|
package/ui/Skeleton.tsx
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Autobahn (auto.de redesign) — md3 loading skeleton.
|
|
2
|
+
//
|
|
3
|
+
// md3.css ships no skeleton class, so this is the ONE addition covering every
|
|
4
|
+
// legacy `Skeleton`/`SkeletonItem` (MUI) call site: a div with an animated
|
|
5
|
+
// gradient shimmer built from --md surface tokens. Prop surface mirrors the
|
|
6
|
+
// subset fe-main actually used (variant / width / height / className / style;
|
|
7
|
+
// `animation` is accepted and ignored — the shimmer always runs).
|
|
8
|
+
// Renders correctly only inside a `<div className="md3">` subtree.
|
|
9
|
+
|
|
10
|
+
import React from 'react';
|
|
11
|
+
|
|
12
|
+
export interface SkeletonProps {
|
|
13
|
+
variant?: 'text' | 'rectangular' | 'circular';
|
|
14
|
+
width?: number | string;
|
|
15
|
+
height?: number | string;
|
|
16
|
+
className?: string;
|
|
17
|
+
style?: React.CSSProperties;
|
|
18
|
+
/** legacy MUI prop, accepted and ignored. */
|
|
19
|
+
animation?: 'pulse' | 'wave' | false;
|
|
20
|
+
children?: React.ReactNode;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const SKELETON_CSS = `
|
|
24
|
+
.md3 .mskeleton {
|
|
25
|
+
display: block;
|
|
26
|
+
background: linear-gradient(90deg, var(--md-sc) 25%, var(--md-sc-high, var(--md-sc-lowest)) 37%, var(--md-sc) 63%);
|
|
27
|
+
background-size: 400% 100%;
|
|
28
|
+
animation: md3-skeleton-shimmer 1.4s ease infinite;
|
|
29
|
+
border-radius: var(--md-r-sm);
|
|
30
|
+
}
|
|
31
|
+
.md3 .mskeleton--text { border-radius: var(--md-r-xs, 4px); transform: scale(1, 0.7); }
|
|
32
|
+
.md3 .mskeleton--circular { border-radius: 50%; }
|
|
33
|
+
@keyframes md3-skeleton-shimmer {
|
|
34
|
+
0% { background-position: 100% 50%; }
|
|
35
|
+
100% { background-position: 0 50%; }
|
|
36
|
+
}`;
|
|
37
|
+
|
|
38
|
+
const SKELETON_STYLE_ID = 'md3-skeleton-styles';
|
|
39
|
+
|
|
40
|
+
// one <style id> in document.head no matter how many skeletons mount — the same
|
|
41
|
+
// pattern fe-main's VehicleSmallCardMd3 uses. SSR-safe (guarded document access).
|
|
42
|
+
function ensureStylesInjected(): void {
|
|
43
|
+
if (typeof document === 'undefined' || document.getElementById(SKELETON_STYLE_ID)) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const style = document.createElement('style');
|
|
47
|
+
style.id = SKELETON_STYLE_ID;
|
|
48
|
+
style.innerHTML = SKELETON_CSS;
|
|
49
|
+
document.head.appendChild(style);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const Skeleton: React.FunctionComponent<SkeletonProps> = ({
|
|
53
|
+
variant = 'rectangular', width, height, className, style, children,
|
|
54
|
+
}) => {
|
|
55
|
+
React.useEffect(() => { ensureStylesInjected(); }, []);
|
|
56
|
+
const dims: React.CSSProperties = {};
|
|
57
|
+
if (width != null) dims.width = width;
|
|
58
|
+
if (height != null) dims.height = height;
|
|
59
|
+
if (variant === 'text' && height == null) dims.height = '1.2em';
|
|
60
|
+
return (
|
|
61
|
+
<span
|
|
62
|
+
className={
|
|
63
|
+
'mskeleton' +
|
|
64
|
+
(variant !== 'rectangular' ? ` mskeleton--${variant}` : '') +
|
|
65
|
+
(className ? ` ${className}` : '')
|
|
66
|
+
}
|
|
67
|
+
style={{ ...dims, ...style }}
|
|
68
|
+
aria-hidden='true'
|
|
69
|
+
>
|
|
70
|
+
{children}
|
|
71
|
+
</span>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export default Skeleton;
|
package/ui/Spec.tsx
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import Icon from './Icon';
|
|
4
|
+
|
|
5
|
+
export interface SpecProps {
|
|
6
|
+
/** kebab-case lucide icon name. */
|
|
7
|
+
icon: string;
|
|
8
|
+
/** caption shown beneath the bold value. */
|
|
9
|
+
label?: React.ReactNode;
|
|
10
|
+
/** the bold value. */
|
|
11
|
+
children?: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const Spec: React.FunctionComponent<SpecProps> = ({ icon, label, children }) => (
|
|
15
|
+
<div className="specitem">
|
|
16
|
+
<Icon name={icon} size={20} stroke={1.75} />
|
|
17
|
+
<div>
|
|
18
|
+
<b>{children}</b>
|
|
19
|
+
<span>{label}</span>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export default Spec;
|
package/ui/Stars.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import Icon from './Icon';
|
|
4
|
+
|
|
5
|
+
export interface StarsProps {
|
|
6
|
+
/** rating value 0–5; each star fills when value − index >= 0.5. */
|
|
7
|
+
value: number;
|
|
8
|
+
size?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** 5-star row (rounded to nearest .5). */
|
|
12
|
+
const Stars: React.FunctionComponent<StarsProps> = ({ value, size = 16 }) => (
|
|
13
|
+
<span style={{ display: 'inline-flex', gap: 1 }}>
|
|
14
|
+
{[0, 1, 2, 3, 4].map((i) => {
|
|
15
|
+
const fill = value - i;
|
|
16
|
+
return (
|
|
17
|
+
<Icon
|
|
18
|
+
key={i}
|
|
19
|
+
name={fill >= 0.5 ? 'star' : 'star'}
|
|
20
|
+
size={size}
|
|
21
|
+
color={fill >= 0.5 ? '#F2A900' : '#D8D6DC'}
|
|
22
|
+
style={{ fill: fill >= 0.5 ? '#F2A900' : '#D8D6DC' }}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
})}
|
|
26
|
+
</span>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export default Stars;
|
package/ui/StatChip.tsx
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import Icon from './Icon';
|
|
4
|
+
|
|
5
|
+
export type StatChipTone = 'good' | 'warn';
|
|
6
|
+
|
|
7
|
+
export interface StatChipProps {
|
|
8
|
+
tone?: StatChipTone;
|
|
9
|
+
/** kebab-case lucide icon name rendered before the content. */
|
|
10
|
+
icon?: string;
|
|
11
|
+
children?: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const StatChip: React.FunctionComponent<StatChipProps> = ({ tone = 'good', icon, children }) => (
|
|
15
|
+
<span className={`statchip statchip--${tone}`}>
|
|
16
|
+
{icon && <Icon name={icon} size={14} />}
|
|
17
|
+
{children}
|
|
18
|
+
</span>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export default StatChip;
|