@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
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import React, { useState, useRef, useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import Icon from './Icon';
|
|
4
|
+
|
|
5
|
+
export interface CardCarouselProps {
|
|
6
|
+
/** ready-to-use image URLs (already resolved by the caller — no asset/window lookup here). */
|
|
7
|
+
images: string[];
|
|
8
|
+
/** px number or any CSS length (e.g. "100%") so cards can fill their media box. */
|
|
9
|
+
height?: number | string;
|
|
10
|
+
radius?: number | string;
|
|
11
|
+
/** fired with the new active index whenever the slide changes. */
|
|
12
|
+
onChange?: (index: number) => void;
|
|
13
|
+
/** object-fit for each image; 'contain' adds inset padding. */
|
|
14
|
+
fit?: 'cover' | 'contain';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Image carousel for cards — touch-swipeable, dots + hover arrows (desktop).
|
|
19
|
+
* Stops click bubbling so it can live inside a clickable card.
|
|
20
|
+
*/
|
|
21
|
+
const CardCarousel: React.FunctionComponent<CardCarouselProps> = ({
|
|
22
|
+
images,
|
|
23
|
+
height = 188,
|
|
24
|
+
radius,
|
|
25
|
+
onChange,
|
|
26
|
+
fit = 'cover',
|
|
27
|
+
}) => {
|
|
28
|
+
const [i, setI] = useState(0);
|
|
29
|
+
const n = images.length;
|
|
30
|
+
// MOBX-CQ-2: reset to the first slide whenever the caller hands us a
|
|
31
|
+
// DIFFERENT gallery (this instance reused for another car) — otherwise a
|
|
32
|
+
// stale index can point past the end of a shorter gallery or show the
|
|
33
|
+
// wrong photo. Keyed on CONTENT, not array identity: parents (e.g. the
|
|
34
|
+
// VDP) rebuild the array every render, and an identity-keyed reset undid
|
|
35
|
+
// every arrow click whose onChange triggered a parent re-render (the
|
|
36
|
+
// counter advanced while the track snapped back to slide 0).
|
|
37
|
+
const gallerySignature = images.join('|');
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
setI(0);
|
|
40
|
+
}, [gallerySignature]);
|
|
41
|
+
const jump = (nx: number, e?: React.SyntheticEvent) => {
|
|
42
|
+
e && e.stopPropagation();
|
|
43
|
+
setI(nx);
|
|
44
|
+
onChange && onChange(nx);
|
|
45
|
+
};
|
|
46
|
+
const go = (d: number, e?: React.SyntheticEvent) => jump((i + d + n) % n, e);
|
|
47
|
+
const trackRef = useRef<HTMLDivElement>(null);
|
|
48
|
+
const tx = useRef<number | null>(null);
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
className="cardcar"
|
|
52
|
+
style={{ position: 'relative', height, overflow: 'hidden', borderRadius: radius }}
|
|
53
|
+
onTouchStart={(e) => {
|
|
54
|
+
tx.current = e.touches[0].clientX;
|
|
55
|
+
}}
|
|
56
|
+
onTouchEnd={(e) => {
|
|
57
|
+
if (tx.current == null) return;
|
|
58
|
+
const dx = e.changedTouches[0].clientX - tx.current;
|
|
59
|
+
tx.current = null;
|
|
60
|
+
if (Math.abs(dx) > 40) go(dx > 0 ? -1 : 1);
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
<div
|
|
64
|
+
ref={trackRef}
|
|
65
|
+
style={{
|
|
66
|
+
display: 'flex',
|
|
67
|
+
height: '100%',
|
|
68
|
+
transform: `translateX(-${i * 100}%)`,
|
|
69
|
+
transition: 'transform var(--dur-3) var(--ease-emphasized)',
|
|
70
|
+
}}
|
|
71
|
+
>
|
|
72
|
+
{images.map((src, k) => (
|
|
73
|
+
<img
|
|
74
|
+
key={k}
|
|
75
|
+
src={src}
|
|
76
|
+
alt=""
|
|
77
|
+
loading="lazy"
|
|
78
|
+
decoding="async"
|
|
79
|
+
style={{
|
|
80
|
+
flex: '0 0 100%',
|
|
81
|
+
width: '100%',
|
|
82
|
+
height: '100%',
|
|
83
|
+
objectFit: fit,
|
|
84
|
+
padding: fit === 'contain' ? '5% 6%' : 0,
|
|
85
|
+
boxSizing: 'border-box',
|
|
86
|
+
background: '#fff',
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
))}
|
|
90
|
+
</div>
|
|
91
|
+
{/* arrows + dots only when there is actually something to switch to — with a single
|
|
92
|
+
image (e.g. SRP cards before their gallery is lazy-loaded) they are dead controls. */}
|
|
93
|
+
{n > 1 && (
|
|
94
|
+
<>
|
|
95
|
+
<button className="car-arrow car-arrow--l" aria-label="zurück" onClick={(e) => go(-1, e)}>
|
|
96
|
+
<Icon name="chevron-left" size={20} />
|
|
97
|
+
</button>
|
|
98
|
+
<button className="car-arrow car-arrow--r" aria-label="weiter" onClick={(e) => go(1, e)}>
|
|
99
|
+
<Icon name="chevron-right" size={20} />
|
|
100
|
+
</button>
|
|
101
|
+
<div
|
|
102
|
+
style={{
|
|
103
|
+
position: 'absolute',
|
|
104
|
+
bottom: 9,
|
|
105
|
+
left: 0,
|
|
106
|
+
right: 0,
|
|
107
|
+
display: 'flex',
|
|
108
|
+
justifyContent: 'center',
|
|
109
|
+
gap: 6,
|
|
110
|
+
pointerEvents: 'none',
|
|
111
|
+
}}
|
|
112
|
+
>
|
|
113
|
+
{images.slice(0, 6).map((_, k) => (
|
|
114
|
+
<span
|
|
115
|
+
key={k}
|
|
116
|
+
style={{
|
|
117
|
+
width: k === i ? 16 : 6,
|
|
118
|
+
height: 6,
|
|
119
|
+
borderRadius: 3,
|
|
120
|
+
background: k === i ? 'var(--md-on-surface)' : 'rgba(26,27,34,.3)',
|
|
121
|
+
boxShadow: '0 0 0 1px rgba(255,255,255,.5)',
|
|
122
|
+
transition: 'width var(--dur-2)',
|
|
123
|
+
}}
|
|
124
|
+
/>
|
|
125
|
+
))}
|
|
126
|
+
</div>
|
|
127
|
+
</>
|
|
128
|
+
)}
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export default CardCarousel;
|
package/ui/Chip.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import Icon from './Icon';
|
|
4
|
+
|
|
5
|
+
export interface ChipProps {
|
|
6
|
+
/** kebab-case lucide icon name rendered before the label. */
|
|
7
|
+
icon?: string;
|
|
8
|
+
/** toggled/applied state — also drives `aria-pressed` so assistive tech announces the chip
|
|
9
|
+
* as a pressed toggle button (undefined = not a toggle, so no `aria-pressed` is rendered). */
|
|
10
|
+
selected?: boolean;
|
|
11
|
+
/** renders the filter-chip variant (different selected color). */
|
|
12
|
+
filter?: boolean;
|
|
13
|
+
children?: React.ReactNode;
|
|
14
|
+
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
|
15
|
+
/** native `<button>` type; defaults to "button" (see Button.tsx for the same footgun). */
|
|
16
|
+
type?: 'button' | 'submit' | 'reset';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const Chip: React.FunctionComponent<ChipProps> = ({ icon, selected, filter, children, onClick, type = 'button' }) => {
|
|
20
|
+
const cn = ['chip', filter && 'chip--filter', selected && 'chip--selected'].filter(Boolean).join(' ');
|
|
21
|
+
return (
|
|
22
|
+
<button type={type} className={cn} aria-pressed={selected} onClick={onClick}>
|
|
23
|
+
{icon && <Icon name={icon} size={16} />}
|
|
24
|
+
{children}
|
|
25
|
+
</button>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default Chip;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// Autobahn (auto.de redesign) — md3 date field bound to a mobx-react-form field.
|
|
2
|
+
//
|
|
3
|
+
// Native, themeable replacement for the legacy fe-ui-core <MaterialDatePicker> (which mounts a MUI
|
|
4
|
+
// <MobileDatePicker> under its own <ThemeProvider> — that second theme bleeds into the scoped `.md3`
|
|
5
|
+
// subtree and reads as "not-md3"). Instead we render a single <input type="date"> styled exactly like
|
|
6
|
+
// `.mfield`, so the browser supplies a locale-correct calendar popup while WE own the visual chrome.
|
|
7
|
+
//
|
|
8
|
+
// DATA CONTRACT — must match the legacy MaterialDatePicker usage EXACTLY (5 pages: Einstellungen
|
|
9
|
+
// birthday, Checkout birthday + co-borrower birthday, VehicleEdit constructionDate), because the same
|
|
10
|
+
// mobx-react-form field + validation rules + submit hooks are reused unchanged:
|
|
11
|
+
// - value: Date | string | null (legacy passes `field.value || null`; we read field.value here).
|
|
12
|
+
// - onChange emits a **Date object** via `field.onChange(value, field.name)` — the exact call the
|
|
13
|
+
// legacy callers wired into MaterialDatePicker's `onChange(value: Date)`. Clearing emits `null`.
|
|
14
|
+
// - minDate / maxDate: Date objects (legacy: `_minDate` = 1900-01-01, `handleMaxDateForPicker()` =
|
|
15
|
+
// today−18y). We forward them to the native input as min/max=yyyy-mm-dd so out-of-range dates
|
|
16
|
+
// can't be picked, mirroring the legacy onAccept clamp.
|
|
17
|
+
// - error shown inline from field.error (legacy passed `field.hasError && field.error`).
|
|
18
|
+
//
|
|
19
|
+
// The native <input type="date"> is locale-free at the value level (always yyyy-mm-dd), so the
|
|
20
|
+
// `format`/`language` props are accepted for signature parity but don't change the wire value; the
|
|
21
|
+
// browser renders the visible date in the user's locale. observer-wrapped so it re-renders on
|
|
22
|
+
// field value/error changes. Renders correctly only inside a `<div className="md3">` subtree.
|
|
23
|
+
|
|
24
|
+
import * as React from 'react';
|
|
25
|
+
import { observer } from 'mobx-react';
|
|
26
|
+
|
|
27
|
+
export interface DatePickerProps {
|
|
28
|
+
/** mobx-react-form field (ContactDetailsForm.$('privateAddress.birthday') etc.). Typed any — the lib ships no TS types. */
|
|
29
|
+
field: any;
|
|
30
|
+
/** i18n translate — resolves the field's label/placeholder key. Optional (matches legacy, which passed t). */
|
|
31
|
+
t?: (key: string, options?: object) => string;
|
|
32
|
+
/** kept for legacy signature parity; the native input value is always locale-free yyyy-mm-dd. */
|
|
33
|
+
language?: 'de' | 'en';
|
|
34
|
+
/** earliest selectable date (legacy `_minDate`). */
|
|
35
|
+
minDate?: Date;
|
|
36
|
+
/** latest selectable date (legacy `handleMaxDateForPicker()`). */
|
|
37
|
+
maxDate?: Date;
|
|
38
|
+
/** kept for legacy signature parity (display format); does not change the emitted Date value. */
|
|
39
|
+
format?: string;
|
|
40
|
+
/** explicit visible label override (legacy ProfileTabAccount/Checkout pass a namespaced label). */
|
|
41
|
+
label?: string;
|
|
42
|
+
id?: string;
|
|
43
|
+
disabled?: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Date | string | null -> 'yyyy-mm-dd' (the native <input type="date"> value), or '' when empty/invalid. */
|
|
47
|
+
function toInputValue(value: Date | string | null | undefined): string {
|
|
48
|
+
if (!value) return '';
|
|
49
|
+
const d = value instanceof Date ? value : new Date(value);
|
|
50
|
+
const time = d.getTime();
|
|
51
|
+
if (Number.isNaN(time)) return '';
|
|
52
|
+
// Use local Y/M/D (not toISOString, which shifts by timezone and can land on the previous day).
|
|
53
|
+
const y = d.getFullYear();
|
|
54
|
+
const m = `${d.getMonth() + 1}`.padStart(2, '0');
|
|
55
|
+
const day = `${d.getDate()}`.padStart(2, '0');
|
|
56
|
+
return `${y}-${m}-${day}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** 'yyyy-mm-dd' -> a local-midnight Date (matching `new Date('01/01/1970')` semantics the legacy used), or null. */
|
|
60
|
+
function fromInputValue(value: string): Date | null {
|
|
61
|
+
if (!value) return null;
|
|
62
|
+
const parts = value.split('-');
|
|
63
|
+
if (parts.length !== 3) return null;
|
|
64
|
+
const y = Number(parts[0]);
|
|
65
|
+
const m = Number(parts[1]);
|
|
66
|
+
const day = Number(parts[2]);
|
|
67
|
+
if (!y || !m || !day) return null;
|
|
68
|
+
return new Date(y, m - 1, day);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const DatePicker: React.FunctionComponent<DatePickerProps> = observer(
|
|
72
|
+
({ field, t, minDate, maxDate, label, id, disabled }) => {
|
|
73
|
+
const translate = t || ((k: string) => k);
|
|
74
|
+
const hasError = !!field.hasError && !!field.error;
|
|
75
|
+
|
|
76
|
+
// Visible label: explicit `label` prop wins (namespaced callers), else FormField's pattern —
|
|
77
|
+
// prefer the field's placeholder key, else its label key. translate() returns the input
|
|
78
|
+
// unchanged when there's no translation, so this is safe for plain-string labels too.
|
|
79
|
+
const resolvedLabel =
|
|
80
|
+
label != null
|
|
81
|
+
? label
|
|
82
|
+
: field.placeholder
|
|
83
|
+
? translate(field.placeholder)
|
|
84
|
+
: field.label
|
|
85
|
+
? translate(field.label)
|
|
86
|
+
: '';
|
|
87
|
+
|
|
88
|
+
const value = toInputValue(field.value);
|
|
89
|
+
const min = minDate ? toInputValue(minDate) : undefined;
|
|
90
|
+
const max = maxDate ? toInputValue(maxDate) : undefined;
|
|
91
|
+
|
|
92
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
93
|
+
const next = fromInputValue(e.target.value);
|
|
94
|
+
// Emit a Date (or null) via the EXACT legacy call: field.onChange(value, field.name).
|
|
95
|
+
field.onChange(next as any, field.name);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const handleBlur = () => {
|
|
99
|
+
// Mirror the legacy onBlurBirthday: validate, surfacing errors if the field is invalid.
|
|
100
|
+
if (typeof field.validate === 'function') {
|
|
101
|
+
const result = field.validate();
|
|
102
|
+
if (result && typeof result.then === 'function') {
|
|
103
|
+
result.then((subField: any) => {
|
|
104
|
+
if (field.isValid === false && subField && typeof subField.showErrors === 'function') {
|
|
105
|
+
subField.showErrors(true);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<div className="mfield-group mdate">
|
|
114
|
+
{resolvedLabel ? (
|
|
115
|
+
<label className="md-label-sm mfield-label" htmlFor={id}>
|
|
116
|
+
{resolvedLabel}
|
|
117
|
+
</label>
|
|
118
|
+
) : null}
|
|
119
|
+
<div
|
|
120
|
+
className={
|
|
121
|
+
'mfield mdate-field' +
|
|
122
|
+
(hasError ? ' mfield--error' : '') +
|
|
123
|
+
(disabled ? ' mfield--disabled' : '')
|
|
124
|
+
}
|
|
125
|
+
>
|
|
126
|
+
<input
|
|
127
|
+
id={id}
|
|
128
|
+
type="date"
|
|
129
|
+
className="mdate-input"
|
|
130
|
+
value={value}
|
|
131
|
+
min={min}
|
|
132
|
+
max={max}
|
|
133
|
+
disabled={disabled}
|
|
134
|
+
onChange={handleChange}
|
|
135
|
+
onBlur={handleBlur}
|
|
136
|
+
style={{ width: '100%' }}
|
|
137
|
+
/>
|
|
138
|
+
</div>
|
|
139
|
+
{hasError ? <span className="mfield-error-text">{field.error}</span> : null}
|
|
140
|
+
</div>
|
|
141
|
+
);
|
|
142
|
+
},
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
export default DatePicker;
|
package/ui/Dropdown.tsx
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
// Autobahn (auto.de redesign) — md3 single-select dropdown.
|
|
2
|
+
//
|
|
3
|
+
// A real, themeable replacement for the native HTML `<select>`. The browser renders
|
|
4
|
+
// a native `<select>`'s option list with the OS popup, which CANNOT be styled (it
|
|
5
|
+
// ignores the scoped `.md3` theme and reads as "broken"/un-md3). This component
|
|
6
|
+
// reproduces the control as a button trigger (`.mselect-btn`, styled like `.mfield`)
|
|
7
|
+
// plus an absolutely-positioned `.mcard`-style popover menu we fully control.
|
|
8
|
+
//
|
|
9
|
+
// Behaviour parity with a real select:
|
|
10
|
+
// - controlled: `value` + `options` ({value,label,disabled?}) + `onChange(value)`.
|
|
11
|
+
// - keyboard: ↓/Enter/Space open; ↑/↓ move the active option; Enter selects;
|
|
12
|
+
// Esc / Tab close (Esc refocuses the trigger); Home/End jump.
|
|
13
|
+
// - click-away (document mousedown) closes; the active option scrolls into view.
|
|
14
|
+
// - a11y: trigger `aria-haspopup=listbox` + `aria-expanded`; menu `role=listbox`;
|
|
15
|
+
// options `role=option` + `aria-selected`; `aria-activedescendant` tracks focus.
|
|
16
|
+
//
|
|
17
|
+
// Pure/presentational — no store/API/window beyond the click-away listener (guarded
|
|
18
|
+
// for SSR). Renders correctly only inside a `<div className="md3">` subtree.
|
|
19
|
+
|
|
20
|
+
import React from 'react';
|
|
21
|
+
|
|
22
|
+
import Icon from './Icon';
|
|
23
|
+
|
|
24
|
+
export interface DropdownOption {
|
|
25
|
+
value: string;
|
|
26
|
+
label: string;
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface DropdownProps {
|
|
31
|
+
/** currently selected option value. */
|
|
32
|
+
value: string;
|
|
33
|
+
/** the selectable options, in display order. */
|
|
34
|
+
options: DropdownOption[];
|
|
35
|
+
/** fired with the chosen option's value. */
|
|
36
|
+
onChange: (value: string) => void;
|
|
37
|
+
/** shown (muted) when `value` matches no option. */
|
|
38
|
+
placeholder?: string;
|
|
39
|
+
/** leading lucide icon (kebab-case), e.g. 'arrow-up-down'. */
|
|
40
|
+
icon?: string;
|
|
41
|
+
disabled?: boolean;
|
|
42
|
+
/** full-width trigger (default true for form fields; pass false for inline controls). */
|
|
43
|
+
block?: boolean;
|
|
44
|
+
/** compact height (sort bar / inline). */
|
|
45
|
+
size?: 'sm' | 'md';
|
|
46
|
+
/** accessible label when there is no visible <label> wrapping the control. */
|
|
47
|
+
ariaLabel?: string;
|
|
48
|
+
/** extra class on the wrapper (e.g. 'srp-sort' for width rules). */
|
|
49
|
+
className?: string;
|
|
50
|
+
/** align the popover to the right edge of the trigger (default left). */
|
|
51
|
+
menuAlign?: 'left' | 'right';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const Dropdown: React.FunctionComponent<DropdownProps> = ({
|
|
55
|
+
value,
|
|
56
|
+
options,
|
|
57
|
+
onChange,
|
|
58
|
+
placeholder,
|
|
59
|
+
icon,
|
|
60
|
+
disabled = false,
|
|
61
|
+
block = true,
|
|
62
|
+
size = 'md',
|
|
63
|
+
ariaLabel,
|
|
64
|
+
className,
|
|
65
|
+
menuAlign = 'left',
|
|
66
|
+
}) => {
|
|
67
|
+
const [open, setOpen] = React.useState(false);
|
|
68
|
+
const [activeIndex, setActiveIndex] = React.useState(-1);
|
|
69
|
+
const rootRef = React.useRef<HTMLDivElement | null>(null);
|
|
70
|
+
const btnRef = React.useRef<HTMLButtonElement | null>(null);
|
|
71
|
+
const menuRef = React.useRef<HTMLUListElement | null>(null);
|
|
72
|
+
// stable id base for aria-activedescendant (avoids Math.random / Date.now, which are unavailable).
|
|
73
|
+
const idBase = React.useMemo(() => `mselect-${Math.round(value ? value.length : 0)}-`, [value]);
|
|
74
|
+
|
|
75
|
+
const selectedIndex = options.findIndex((o) => o.value === value);
|
|
76
|
+
const selected = selectedIndex !== -1 ? options[selectedIndex] : undefined;
|
|
77
|
+
|
|
78
|
+
// close + restore focus to the trigger.
|
|
79
|
+
const close = React.useCallback((focusTrigger: boolean) => {
|
|
80
|
+
setOpen(false);
|
|
81
|
+
setActiveIndex(-1);
|
|
82
|
+
if (focusTrigger && btnRef.current) btnRef.current.focus();
|
|
83
|
+
}, []);
|
|
84
|
+
|
|
85
|
+
const openMenu = React.useCallback(() => {
|
|
86
|
+
if (disabled) return;
|
|
87
|
+
setOpen(true);
|
|
88
|
+
// start the keyboard highlight on the current selection (or the first option).
|
|
89
|
+
setActiveIndex(selectedIndex !== -1 ? selectedIndex : 0);
|
|
90
|
+
}, [disabled, selectedIndex]);
|
|
91
|
+
|
|
92
|
+
// click-away (guarded for SSR).
|
|
93
|
+
React.useEffect(() => {
|
|
94
|
+
if (!open || typeof document === 'undefined') return undefined;
|
|
95
|
+
const onDocMouseDown = (e: MouseEvent) => {
|
|
96
|
+
if (rootRef.current && !rootRef.current.contains(e.target as Node)) close(false);
|
|
97
|
+
};
|
|
98
|
+
document.addEventListener('mousedown', onDocMouseDown);
|
|
99
|
+
return () => document.removeEventListener('mousedown', onDocMouseDown);
|
|
100
|
+
}, [open, close]);
|
|
101
|
+
|
|
102
|
+
// keep the active option scrolled into view while navigating by keyboard.
|
|
103
|
+
React.useEffect(() => {
|
|
104
|
+
if (!open || activeIndex < 0 || !menuRef.current) return;
|
|
105
|
+
const el = menuRef.current.children[activeIndex] as HTMLElement | undefined;
|
|
106
|
+
if (el && el.scrollIntoView) el.scrollIntoView({ block: 'nearest' });
|
|
107
|
+
}, [open, activeIndex]);
|
|
108
|
+
|
|
109
|
+
const commit = (idx: number) => {
|
|
110
|
+
const opt = options[idx];
|
|
111
|
+
if (!opt || opt.disabled) return;
|
|
112
|
+
onChange(opt.value);
|
|
113
|
+
close(true);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// move the active highlight, skipping disabled options.
|
|
117
|
+
const move = (dir: 1 | -1) => {
|
|
118
|
+
if (!options.length) return;
|
|
119
|
+
let i = activeIndex;
|
|
120
|
+
for (let step = 0; step < options.length; step += 1) {
|
|
121
|
+
i = (i + dir + options.length) % options.length;
|
|
122
|
+
if (!options[i].disabled) {
|
|
123
|
+
setActiveIndex(i);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const onTriggerKeyDown = (e: React.KeyboardEvent) => {
|
|
130
|
+
if (disabled) return;
|
|
131
|
+
if (!open) {
|
|
132
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' || e.key === ' ') {
|
|
133
|
+
e.preventDefault();
|
|
134
|
+
openMenu();
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
switch (e.key) {
|
|
139
|
+
case 'ArrowDown': e.preventDefault(); move(1); break;
|
|
140
|
+
case 'ArrowUp': e.preventDefault(); move(-1); break;
|
|
141
|
+
case 'Home': e.preventDefault(); setActiveIndex(options.findIndex((o) => !o.disabled)); break;
|
|
142
|
+
case 'End': e.preventDefault(); for (let i = options.length - 1; i >= 0; i -= 1) { if (!options[i].disabled) { setActiveIndex(i); break; } } break;
|
|
143
|
+
case 'Enter': case ' ': e.preventDefault(); if (activeIndex >= 0) commit(activeIndex); break;
|
|
144
|
+
case 'Escape': e.preventDefault(); close(true); break;
|
|
145
|
+
case 'Tab': close(false); break;
|
|
146
|
+
default: break;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const wrapCls = ['mselect'];
|
|
151
|
+
if (size === 'sm') wrapCls.push('mselect--sm');
|
|
152
|
+
if (block) wrapCls.push('mselect--block');
|
|
153
|
+
if (className) wrapCls.push(className);
|
|
154
|
+
|
|
155
|
+
const label = selected ? selected.label : placeholder || '';
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<div className={wrapCls.join(' ')} ref={rootRef}>
|
|
159
|
+
<button
|
|
160
|
+
ref={btnRef}
|
|
161
|
+
type="button"
|
|
162
|
+
className="mselect-btn"
|
|
163
|
+
aria-haspopup="listbox"
|
|
164
|
+
aria-expanded={open}
|
|
165
|
+
aria-label={ariaLabel}
|
|
166
|
+
disabled={disabled}
|
|
167
|
+
onClick={() => (open ? close(false) : openMenu())}
|
|
168
|
+
onKeyDown={onTriggerKeyDown}
|
|
169
|
+
>
|
|
170
|
+
{icon && <Icon name={icon} />}
|
|
171
|
+
<span className={'mselect-label' + (selected ? '' : ' mselect-label--ph')}>{label}</span>
|
|
172
|
+
<Icon name="chevron-down" cls="mselect-chev" />
|
|
173
|
+
</button>
|
|
174
|
+
{open && (
|
|
175
|
+
<ul
|
|
176
|
+
ref={menuRef}
|
|
177
|
+
className={'mselect-menu' + (menuAlign === 'right' ? ' mselect-menu--right' : '')}
|
|
178
|
+
role="listbox"
|
|
179
|
+
tabIndex={-1}
|
|
180
|
+
aria-activedescendant={activeIndex >= 0 ? `${idBase}${activeIndex}` : undefined}
|
|
181
|
+
>
|
|
182
|
+
{options.map((opt, i) => (
|
|
183
|
+
<li key={`${opt.value}_${i}`} role="presentation">
|
|
184
|
+
<button
|
|
185
|
+
id={`${idBase}${i}`}
|
|
186
|
+
type="button"
|
|
187
|
+
role="option"
|
|
188
|
+
aria-selected={opt.value === value}
|
|
189
|
+
disabled={opt.disabled}
|
|
190
|
+
className={'mselect-opt' + (i === activeIndex ? ' is-active' : '')}
|
|
191
|
+
onMouseEnter={() => setActiveIndex(i)}
|
|
192
|
+
onClick={() => commit(i)}
|
|
193
|
+
>
|
|
194
|
+
<span className="mselect-opt-label">{opt.label}</span>
|
|
195
|
+
{opt.value === value && <Icon name="check" size={16} cls="mselect-check" />}
|
|
196
|
+
</button>
|
|
197
|
+
</li>
|
|
198
|
+
))}
|
|
199
|
+
</ul>
|
|
200
|
+
)}
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export default Dropdown;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// Autobahn (auto.de redesign) — md3 file-upload dropzone SHELL.
|
|
2
|
+
//
|
|
3
|
+
// This is the md3 *chrome* around a preserved upload engine — it does NOT upload anything
|
|
4
|
+
// itself. The legacy pages keep their existing engine and slot it into this shell:
|
|
5
|
+
// - ImageUploadPage → Uppy `<DragDrop uppy>` + `<ProgressBar uppy>` (Uppy owns its own
|
|
6
|
+
// input + drag/drop); pass those as `children`. The shell is then
|
|
7
|
+
// pure presentation; Uppy still wires every file/upload event.
|
|
8
|
+
// - ImageUploader (EXPORT settings, react-dropzone v4) → legacy `onDrop(files: File[])`.
|
|
9
|
+
// Pass that same handler as `onFiles` and forward `multiple`/`accept`;
|
|
10
|
+
// render the loader / preview as `children`.
|
|
11
|
+
//
|
|
12
|
+
// Standalone (no engine slotted in) it is still usable: clicking the zone or dropping files on
|
|
13
|
+
// it fires `onFiles(File[])` via a hidden native <input type=file> — the SAME `File[]` shape
|
|
14
|
+
// react-dropzone's `onDrop` uses, so it is a drop-in for that signature. When you slot a child
|
|
15
|
+
// engine that owns its own input (Uppy), simply omit `onFiles` and the shell stays inert.
|
|
16
|
+
//
|
|
17
|
+
// Pure/presentational: no store, no API, no window access. The only state is the local
|
|
18
|
+
// drag-over highlight. Renders correctly only inside a `<div className="md3">` subtree (scoped
|
|
19
|
+
// theme). Not observer-wrapped — it binds to no mobx field (unlike FormField/Dropdown consumers).
|
|
20
|
+
|
|
21
|
+
import React from 'react';
|
|
22
|
+
|
|
23
|
+
import Icon from './Icon';
|
|
24
|
+
|
|
25
|
+
export interface FileUploadProps {
|
|
26
|
+
/**
|
|
27
|
+
* Fired with the selected/dropped files — matches react-dropzone v4's `onDrop(files: File[])`.
|
|
28
|
+
* Omit when the slotted engine (e.g. Uppy `<DragDrop>`) owns its own input/drop handling; the
|
|
29
|
+
* shell then becomes inert chrome (no hidden input, no drop handler) so it never double-fires.
|
|
30
|
+
*/
|
|
31
|
+
onFiles?: (files: File[]) => void;
|
|
32
|
+
/** forwarded to the hidden native input's `accept` (e.g. 'image/*'). Ignored when `onFiles` is unset. */
|
|
33
|
+
accept?: string;
|
|
34
|
+
/** allow selecting/dropping more than one file (default true). Mirrors react-dropzone `multiple`. */
|
|
35
|
+
multiple?: boolean;
|
|
36
|
+
/** secondary hint line under the headline (e.g. allowed types / size). */
|
|
37
|
+
hint?: React.ReactNode;
|
|
38
|
+
/** non-interactive + dimmed (mirrors react-dropzone/Uppy `disabled` while uploading). */
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
/** extra class(es) appended after the `mfu` classes (layout hooks). */
|
|
41
|
+
className?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Slot rendered BELOW the dropzone prompt: the file list / previews / progress bar, or the
|
|
44
|
+
* preserved engine element itself (Uppy `<DragDrop>` + `<ProgressBar>`).
|
|
45
|
+
*/
|
|
46
|
+
children?: React.ReactNode;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const FileUpload: React.FunctionComponent<FileUploadProps> = ({
|
|
50
|
+
onFiles,
|
|
51
|
+
accept,
|
|
52
|
+
multiple = true,
|
|
53
|
+
hint,
|
|
54
|
+
disabled = false,
|
|
55
|
+
className,
|
|
56
|
+
children,
|
|
57
|
+
}) => {
|
|
58
|
+
const [dragOver, setDragOver] = React.useState(false);
|
|
59
|
+
const inputRef = React.useRef<HTMLInputElement | null>(null);
|
|
60
|
+
|
|
61
|
+
// Only the shell drives input/drop when it is NOT just wrapping a self-contained engine.
|
|
62
|
+
const interactive = !disabled && typeof onFiles === 'function';
|
|
63
|
+
|
|
64
|
+
const emit = (list: FileList | null) => {
|
|
65
|
+
if (!interactive || !list || list.length === 0) return;
|
|
66
|
+
onFiles!(Array.prototype.slice.call(list) as File[]);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const openPicker = () => {
|
|
70
|
+
if (!interactive || !inputRef.current) return;
|
|
71
|
+
inputRef.current.click();
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const onInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
75
|
+
emit(e.target.files);
|
|
76
|
+
// reset so selecting the same file again still fires change.
|
|
77
|
+
e.target.value = '';
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const onDragOver = (e: React.DragEvent) => {
|
|
81
|
+
if (!interactive) return;
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
if (!dragOver) setDragOver(true);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const onDragLeave = (e: React.DragEvent) => {
|
|
87
|
+
if (!interactive) return;
|
|
88
|
+
// ignore leave events bubbling from children still inside the zone.
|
|
89
|
+
if (e.currentTarget.contains(e.relatedTarget as Node)) return;
|
|
90
|
+
setDragOver(false);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const onDrop = (e: React.DragEvent) => {
|
|
94
|
+
if (!interactive) return;
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
setDragOver(false);
|
|
97
|
+
emit(e.dataTransfer ? e.dataTransfer.files : null);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const onKeyDown = (e: React.KeyboardEvent) => {
|
|
101
|
+
if (!interactive) return;
|
|
102
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
openPicker();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const cn = ['mfu', dragOver && 'mfu--over', disabled && 'mfu--disabled', className]
|
|
109
|
+
.filter(Boolean)
|
|
110
|
+
.join(' ');
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<div className={cn}>
|
|
114
|
+
<div
|
|
115
|
+
className="mfu-zone"
|
|
116
|
+
role={interactive ? 'button' : undefined}
|
|
117
|
+
tabIndex={interactive ? 0 : undefined}
|
|
118
|
+
aria-disabled={disabled || undefined}
|
|
119
|
+
onClick={openPicker}
|
|
120
|
+
onKeyDown={onKeyDown}
|
|
121
|
+
onDragOver={onDragOver}
|
|
122
|
+
onDragEnter={onDragOver}
|
|
123
|
+
onDragLeave={onDragLeave}
|
|
124
|
+
onDrop={onDrop}
|
|
125
|
+
>
|
|
126
|
+
<span className="mfu-icon">
|
|
127
|
+
<Icon name="upload-cloud" size={28} />
|
|
128
|
+
</span>
|
|
129
|
+
<span className="mfu-prompt">
|
|
130
|
+
<span className="mfu-link">Dateien auswählen</span>
|
|
131
|
+
<span className="mfu-or"> oder hierher ziehen</span>
|
|
132
|
+
</span>
|
|
133
|
+
{hint ? <span className="mfu-hint md-body-sm">{hint}</span> : null}
|
|
134
|
+
{interactive ? (
|
|
135
|
+
<input
|
|
136
|
+
ref={inputRef}
|
|
137
|
+
type="file"
|
|
138
|
+
className="mfu-input"
|
|
139
|
+
accept={accept}
|
|
140
|
+
multiple={multiple}
|
|
141
|
+
disabled={disabled}
|
|
142
|
+
onChange={onInputChange}
|
|
143
|
+
// hide visually but keep accessible; click is proxied from the zone.
|
|
144
|
+
tabIndex={-1}
|
|
145
|
+
aria-hidden="true"
|
|
146
|
+
/>
|
|
147
|
+
) : null}
|
|
148
|
+
</div>
|
|
149
|
+
{children ? <div className="mfu-slot">{children}</div> : null}
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export default FileUpload;
|