bonprix-design-system 0.68.0 → 0.69.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/dist/components/BottomSheet/BottomSheet.js.map +1 -1
- package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -1
- package/dist/components/Buttons/BadgeIconButton/BadgeIconButton.js.map +1 -1
- package/dist/components/ButtonsSection/ButtonsSection.js.map +1 -1
- package/dist/components/Carousel/Carousel.js +32 -30
- package/dist/components/Carousel/Carousel.js.map +1 -1
- package/dist/components/Carousel/CarouselArrow.js.map +1 -1
- package/dist/components/CarouselV2/CarouselArrow.js.map +1 -1
- package/dist/components/CarouselV2/CarouselV2.js.map +1 -1
- package/dist/components/CarouselV2/PositionIndicator/PositionIndicator.js.map +1 -1
- package/dist/components/CarouselV2/useCreateCarousel.js +30 -30
- package/dist/components/CarouselV2/useCreateCarousel.js.map +1 -1
- package/dist/components/Dialog/Dialog.js.map +1 -1
- package/dist/components/Image/Image.js.map +1 -1
- package/dist/components/InputFields/BaseInputField/BaseInputField.js.map +1 -1
- package/dist/components/Link/Link.js.map +1 -1
- package/dist/components/LinkGroup/LinkGroup.js.map +1 -1
- package/dist/components/Notification/Notification.js.map +1 -1
- package/dist/components/Overlay/Overlay.js.map +1 -1
- package/dist/components/RemovedItemPlaceholder/RemovedItemPlaceholder.js.map +1 -1
- package/dist/components/ShowMoreList/ShowMoreList.js.map +1 -1
- package/dist/components/SideNavigation/SideNavigation.js.map +1 -1
- package/dist/components/SideSheet/SideSheet.js.map +1 -1
- package/dist/components/TabGroup/TabGroup.js.map +1 -1
- package/dist/components/TabGroup/TabGroupItem/TabGroupItem.js.map +1 -1
- package/dist/components/Textarea/Textarea.js.map +1 -1
- package/dist/styles/web-components/collapsible.css +2 -2
- package/dist/styles/web-components.css +7 -4
- package/dist/web-components/accordion/accordion-item/index.js.map +1 -1
- package/dist/web-components/collapsible/collapsible.css +1 -1
- package/dist/web-components/collapsible/index.js +3 -18
- package/dist/web-components/collapsible/index.js.map +1 -1
- package/dist/web-components/feature-hint/index.js +14 -13
- package/dist/web-components/feature-hint/index.js.map +1 -1
- package/dist/web-components.d.ts +0 -2
- package/package.json +13 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheet.js","names":[],"sources":["../../../src/components/BottomSheet/BottomSheet.tsx"],"sourcesContent":["\"use client\";\n\nimport { type IconType } from \"@bonprix-ds/react-icon\";\nimport IconButton from \"@bonprix-ds/react-icon-button\";\nimport Typography from \"@bonprix-ds/react-typography\";\nimport { TitleLevel, usePrefersReducedMotion, ZIndexContext } from \"@bonprix-ds/utils\";\nimport React, { ComponentProps, ElementType, FC, ReactNode, Ref, useId } from \"react\";\nimport { Sheet } from \"react-modal-sheet\";\nimport { tv } from \"tailwind-variants\";\n\nimport { Button } from \"@components/Buttons\";\nimport { useInnerOpen } from \"@hooks\";\nimport { backdrop } from \"@utils/tailwindVariants\";\n\nimport BottomSheetContext from \"./BottomSheetContext\";\nimport useConsumeBottomSheet from \"./useConsumeBottomSheet\";\nimport useCreateBottomSheet from \"./useCreateBottomSheet\";\n\nconst generateClasses = tv({\n slots: {\n root: \"preflight block\",\n container: \"shadow-none rounded-none bg-clr-bg-modal max-h-[calc(100%-4rem)]\",\n header: \"px-4 py-3\",\n titleAndIcons: \"flex gap-2 items-center touch-pan-down\",\n contentWrapper: \"flex flex-col w-full\",\n content: [\n \"typography-body1 text-clr-primary\",\n // scroller must be a flexbox to fix scrollbar\n // scroller needs some padding to not cut off the focus-ring\n \"*:flex *:-mx-0.5 *:px-0.5\",\n // scroller must set min-h-0 in order to make scrolling work inside our flex context\n \"*:min-h-0\",\n ],\n dragHandleContainer: \"h-6 flex justify-center items-center shrink-0\",\n dragHandle: \"h-1 w-8 rounded-full bg-clr-on-bg-low\",\n backdrop: backdrop(),\n scrollArea: \"scroll-area relative\",\n },\n variants: {\n disableHorizontalPadding: {\n false: { scrollArea: \"px-4\" },\n true: \"\",\n },\n },\n});\n\ninterface SheetProps {\n /** All of the subcomponents should be placed inside this property. */\n children: ReactNode;\n /** Toggles the visibility of the sheet. Should be used in conjunction with the `onClose` property. */\n isOpen: boolean;\n /** Callback function, that is triggered when the sheet is attempted to be closed.\n *\n * It will be called in following cases:\n * - Click on backdrop\n * - Swipe down to close\n * - Click on \"close\" icon button in the upper-right corner\n * - Click on any button (PrimaryButton or SecondaryButton)\n *\n * Should be used in conjunction with `isOpen`. */\n onClose: () => void;\n /** Callback to execute when clicking back icon. */\n onBack?: () => void;\n /** The z-index of the sheet.. */\n zIndex?: number;\n}\n\ninterface SheetTitleProps {\n /** The text content. */\n children: string;\n /** An optional subline that is displayed right below the title. */\n subline?: string;\n /** The heading level for the title. */\n level?: TitleLevel;\n}\n\ninterface SheetButtonSectionProps {\n /** Primary and secondary buttons should be placed inside this section. */\n children: ReactNode;\n}\n\ninterface SheetContentProps {\n /** The content of the content section. */\n children: ReactNode;\n /** If `true`, the horizontal padding around the content will be removed. */\n disableHorizontalPadding?: boolean;\n}\n\ninterface SheetButtonBaseProps {\n /** The label of the button. */\n children: string;\n /** If used, an icon will be additionally shown. The value is a name of one icon from our icon set. */\n icon?: IconType;\n /** The position of the icon relative to the content. */\n iconPosition?: \"start\" | \"end\";\n}\n\nexport type SheetButtonProps<C extends ElementType> = SheetButtonBaseProps & {\n /** The semantic component to render the Button. Preferrably `\"button\"`. Defaults to `\"button\"`. Native props will be passed to this component. */\n component?: C;\n} & Omit<ComponentProps<C>, keyof SheetButtonBaseProps | \"component\">;\n\ntype SheetPrimaryButtonProps<C extends ElementType> = SheetButtonProps<C> & {\n /** If `true`, a loading spinner will be shown instead of the content. */\n loading?: boolean;\n};\n\ninterface SheetSubcomponents {\n Title: typeof Title;\n Content: typeof Content;\n ButtonSection: typeof ButtonSection;\n PrimaryButton: typeof PrimaryButton;\n SecondaryButton: typeof SecondaryButton;\n}\n\nexport interface Props extends SheetProps {\n /** A reference to the root element of the sheet. */\n ref?: Ref<HTMLDivElement>;\n}\n\nconst BottomSheet: FC<Props> & SheetSubcomponents = ({ children, isOpen, onClose, onBack, zIndex = 2, ref }) => {\n // TODO: add aria-modal = true once we implemented the dialog pattern fully and i.e. manage the focus\n const prefersReducedMotion = usePrefersReducedMotion();\n const { root, container, dragHandleContainer, dragHandle, content, contentWrapper, backdrop } = generateClasses();\n const { isShown, scrollRef, scrollPosition } = useCreateBottomSheet({ isOpen });\n\n // When \"middle\" or \"bottom\", dragging is disabled to allow for regular scrolling.\n // When at \"top\", we need to enable drag to close. When `undefined`, the element is not scrollable and can be dragged, too.\n const disableDrag = scrollPosition === \"middle\" || scrollPosition === \"bottom\";\n\n const { innerOpen } = useInnerOpen(isShown);\n\n const titleId = useId();\n\n return (\n <Sheet\n isOpen={innerOpen}\n onClose={onClose}\n className={root()}\n detent=\"content\"\n data-bpds=\"bottom-sheet\"\n prefersReducedMotion={prefersReducedMotion}\n // @ts-expect-error setting custom properties is not recognized by React.CSSProperties\n // This is consumed by the inner ScrollArea to fix drag to close.\n style={{ \"--touch-action\": disableDrag ? \"initial\" : \"pan-down\" }}\n role=\"dialog\"\n avoidKeyboard={false}\n aria-labelledby={titleId}\n >\n <Sheet.Container className={container()} ref={ref} style={{ zIndex }}>\n <Sheet.Header unstyled className={dragHandleContainer()}>\n <Sheet.DragIndicator unstyled className={dragHandle()} />\n </Sheet.Header>\n <ZIndexContext.Provider value={10000}>\n <BottomSheetContext.Provider value={{ scrollRef, scrollPosition, onClose, onBack, titleId }}>\n <Sheet.Content\n className={content()}\n // disable default scrolling\n disableScroll\n // Dragging is still managed by `Sheet.Content` so we control it here\n disableDrag={disableDrag}\n // Apply keyboard height as padding bottom to keep content above the keyboard\n style={{ paddingBottom: \"max(var(--keyboard-inset-height, 0rem), var(--app-safe-area-inset-bottom, 1rem))\" }}\n >\n <div className={contentWrapper()}>{children}</div>\n </Sheet.Content>\n </BottomSheetContext.Provider>\n </ZIndexContext.Provider>\n </Sheet.Container>\n {/* TODO: Deactivate the animation, when the user prefers reduced motion: https://github.com/Temzasse/react-modal-sheet/issues/227 */}\n <Sheet.Backdrop aria-label=\"Bottom Sheet schließen\" onTap={onClose} className={backdrop()} style={{ zIndex: zIndex - 1 }} />\n </Sheet>\n );\n};\n\nexport default BottomSheet;\n\nconst Title = ({ children, subline, level = \"h3\" }: SheetTitleProps) => {\n const { onBack, onClose, titleId } = useConsumeBottomSheet();\n const { header, titleAndIcons } = generateClasses();\n return (\n <div className={header()}>\n <div className={titleAndIcons()}>\n {onBack && <IconButton onClick={onBack} icon=\"arrow-left\" label=\"Zurück\" variant=\"tertiary\" size=\"small\" />}\n <Typography variant=\"bonprix-h6\" component={level} className=\"grow line-clamp-2\" id={titleId}>\n {children}\n </Typography>\n <IconButton onClick={onClose} icon=\"closer\" label=\"Schließen\" variant=\"tertiary\" size=\"small\" />\n </div>\n {subline && <Typography>{subline}</Typography>}\n </div>\n );\n};\n\nconst Content = ({ children, disableHorizontalPadding = false }: SheetContentProps) => {\n const { scrollRef: setScrollRef } = useConsumeBottomSheet();\n const { scrollArea } = generateClasses({ disableHorizontalPadding });\n\n return (\n <div ref={setScrollRef} className={scrollArea()} data-bpds-disable-horizontal-padding={disableHorizontalPadding}>\n {children}\n </div>\n );\n};\n\nconst ButtonSection = ({ children }: SheetButtonSectionProps) => {\n return <div className=\"button-section w-full flex flex-col gap-3 px-4 pt-4 shrink-0 touch-pan-down\">{children}</div>;\n};\n\nconst PrimaryButton = <C extends ElementType>({\n children,\n icon,\n iconPosition,\n loading,\n component = \"button\" as C,\n ...props\n}: SheetPrimaryButtonProps<C>) => {\n const Component: ElementType = component;\n const { onClick, type = \"button\", ...otherProps } = props;\n const { onClose } = useConsumeBottomSheet();\n const handleClick = (event: React.MouseEvent) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n onClick?.(event);\n onClose();\n };\n return (\n <Button\n component={Component}\n {...otherProps}\n variant=\"primary\"\n onClick={handleClick}\n type={type}\n icon={icon}\n iconPosition={iconPosition}\n size=\"large\"\n loading={loading}\n >\n {children}\n </Button>\n );\n};\n\nconst SecondaryButton = <C extends ElementType>({\n children,\n icon,\n iconPosition,\n component = \"button\" as C,\n ...props\n}: SheetButtonProps<C>) => {\n const Component: ElementType = component;\n const { onClose } = useConsumeBottomSheet();\n return (\n <Button\n component={Component}\n {...props}\n variant=\"secondary\"\n type=\"button\"\n onClick={onClose}\n icon={icon}\n iconPosition={iconPosition}\n size=\"large\"\n >\n {children}\n </Button>\n );\n};\n\nBottomSheet.displayName = \"BottomSheet\";\n\nBottomSheet.Title = Title;\nBottomSheet.Content = Content;\nBottomSheet.ButtonSection = ButtonSection;\nBottomSheet.PrimaryButton = PrimaryButton;\nBottomSheet.SecondaryButton = SecondaryButton;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BottomSheet.js","names":[],"sources":["../../../src/components/BottomSheet/BottomSheet.tsx"],"sourcesContent":["\"use client\";\n\nimport { type IconType } from \"@bonprix-ds/react-icon\";\nimport IconButton from \"@bonprix-ds/react-icon-button\";\nimport Typography from \"@bonprix-ds/react-typography\";\nimport { TitleLevel, usePrefersReducedMotion, ZIndexContext } from \"@bonprix-ds/utils\";\nimport React, { ComponentProps, ElementType, FC, ReactNode, Ref, useId } from \"react\";\nimport { Sheet } from \"react-modal-sheet\";\nimport { tv } from \"tailwind-variants\";\n\nimport { Button } from \"@components/Buttons\";\nimport { useInnerOpen } from \"@hooks\";\nimport { backdrop } from \"@utils/tailwindVariants\";\n\nimport BottomSheetContext from \"./BottomSheetContext\";\nimport useConsumeBottomSheet from \"./useConsumeBottomSheet\";\nimport useCreateBottomSheet from \"./useCreateBottomSheet\";\n\nconst generateClasses = tv({\n slots: {\n root: \"preflight block\",\n container: \"shadow-none rounded-none bg-clr-bg-modal max-h-[calc(100%-4rem)]\",\n header: \"px-4 py-3\",\n titleAndIcons: \"flex gap-2 items-center touch-pan-down\",\n contentWrapper: \"flex flex-col w-full\",\n content: [\n \"typography-body1 text-clr-primary\",\n // scroller must be a flexbox to fix scrollbar\n // scroller needs some padding to not cut off the focus-ring\n \"*:flex *:-mx-0.5 *:px-0.5\",\n // scroller must set min-h-0 in order to make scrolling work inside our flex context\n \"*:min-h-0\",\n ],\n dragHandleContainer: \"h-6 flex justify-center items-center shrink-0\",\n dragHandle: \"h-1 w-8 rounded-full bg-clr-on-bg-low\",\n backdrop: backdrop(),\n scrollArea: \"scroll-area relative\",\n },\n variants: {\n disableHorizontalPadding: {\n false: { scrollArea: \"px-4\" },\n true: \"\",\n },\n },\n});\n\ninterface SheetProps {\n /** All of the subcomponents should be placed inside this property. */\n children: ReactNode;\n /** Toggles the visibility of the sheet. Should be used in conjunction with the `onClose` property. */\n isOpen: boolean;\n /** Callback function, that is triggered when the sheet is attempted to be closed.\n *\n * It will be called in following cases:\n * - Click on backdrop\n * - Swipe down to close\n * - Click on \"close\" icon button in the upper-right corner\n * - Click on any button (PrimaryButton or SecondaryButton)\n *\n * Should be used in conjunction with `isOpen`. */\n onClose: () => void;\n /** Callback to execute when clicking back icon. */\n onBack?: () => void;\n /** The z-index of the sheet.. */\n zIndex?: number;\n}\n\ninterface SheetTitleProps {\n /** The text content. */\n children: string;\n /** An optional subline that is displayed right below the title. */\n subline?: string;\n /** The heading level for the title. */\n level?: TitleLevel;\n}\n\ninterface SheetButtonSectionProps {\n /** Primary and secondary buttons should be placed inside this section. */\n children: ReactNode;\n}\n\ninterface SheetContentProps {\n /** The content of the content section. */\n children: ReactNode;\n /** If `true`, the horizontal padding around the content will be removed. */\n disableHorizontalPadding?: boolean;\n}\n\ninterface SheetButtonBaseProps {\n /** The label of the button. */\n children: string;\n /** If used, an icon will be additionally shown. The value is a name of one icon from our icon set. */\n icon?: IconType;\n /** The position of the icon relative to the content. */\n iconPosition?: \"start\" | \"end\";\n}\n\nexport type SheetButtonProps<C extends ElementType> = SheetButtonBaseProps & {\n /** The semantic component to render the Button. Preferrably `\"button\"`. Defaults to `\"button\"`. Native props will be passed to this component. */\n component?: C;\n} & Omit<ComponentProps<C>, keyof SheetButtonBaseProps | \"component\">;\n\ntype SheetPrimaryButtonProps<C extends ElementType> = SheetButtonProps<C> & {\n /** If `true`, a loading spinner will be shown instead of the content. */\n loading?: boolean;\n};\n\ninterface SheetSubcomponents {\n Title: typeof Title;\n Content: typeof Content;\n ButtonSection: typeof ButtonSection;\n PrimaryButton: typeof PrimaryButton;\n SecondaryButton: typeof SecondaryButton;\n}\n\nexport interface Props extends SheetProps {\n /** A reference to the root element of the sheet. */\n ref?: Ref<HTMLDivElement>;\n}\n\nconst BottomSheet: FC<Props> & SheetSubcomponents = ({ children, isOpen, onClose, onBack, zIndex = 2, ref }) => {\n // TODO: add aria-modal = true once we implemented the dialog pattern fully and i.e. manage the focus\n const prefersReducedMotion = usePrefersReducedMotion();\n const { root, container, dragHandleContainer, dragHandle, content, contentWrapper, backdrop } = generateClasses();\n const { isShown, scrollRef, scrollPosition } = useCreateBottomSheet({ isOpen });\n\n // When \"middle\" or \"bottom\", dragging is disabled to allow for regular scrolling.\n // When at \"top\", we need to enable drag to close. When `undefined`, the element is not scrollable and can be dragged, too.\n const disableDrag = scrollPosition === \"middle\" || scrollPosition === \"bottom\";\n\n const { innerOpen } = useInnerOpen(isShown);\n\n const titleId = useId();\n\n return (\n <Sheet\n isOpen={innerOpen}\n onClose={onClose}\n className={root()}\n detent=\"content\"\n data-bpds=\"bottom-sheet\"\n prefersReducedMotion={prefersReducedMotion}\n // @ts-expect-error setting custom properties is not recognized by React.CSSProperties\n // This is consumed by the inner ScrollArea to fix drag to close.\n style={{ \"--touch-action\": disableDrag ? \"initial\" : \"pan-down\" }}\n role=\"dialog\"\n avoidKeyboard={false}\n aria-labelledby={titleId}\n >\n <Sheet.Container className={container()} ref={ref} style={{ zIndex }}>\n <Sheet.Header unstyled className={dragHandleContainer()}>\n <Sheet.DragIndicator unstyled className={dragHandle()} />\n </Sheet.Header>\n <ZIndexContext.Provider value={10000}>\n <BottomSheetContext.Provider value={{ scrollRef, scrollPosition, onClose, onBack, titleId }}>\n <Sheet.Content\n className={content()}\n // disable default scrolling\n disableScroll\n // Dragging is still managed by `Sheet.Content` so we control it here\n disableDrag={disableDrag}\n // Apply keyboard height as padding bottom to keep content above the keyboard\n style={{ paddingBottom: \"max(var(--keyboard-inset-height, 0rem), var(--app-safe-area-inset-bottom, 1rem))\" }}\n >\n <div className={contentWrapper()}>{children}</div>\n </Sheet.Content>\n </BottomSheetContext.Provider>\n </ZIndexContext.Provider>\n </Sheet.Container>\n {/* TODO: Deactivate the animation, when the user prefers reduced motion: https://github.com/Temzasse/react-modal-sheet/issues/227 */}\n <Sheet.Backdrop aria-label=\"Bottom Sheet schließen\" onTap={onClose} className={backdrop()} style={{ zIndex: zIndex - 1 }} />\n </Sheet>\n );\n};\n\nexport default BottomSheet;\n\nconst Title = ({ children, subline, level = \"h3\" }: SheetTitleProps) => {\n const { onBack, onClose, titleId } = useConsumeBottomSheet();\n const { header, titleAndIcons } = generateClasses();\n return (\n <div className={header()}>\n <div className={titleAndIcons()}>\n {onBack && <IconButton onClick={onBack} icon=\"arrow-left\" label=\"Zurück\" variant=\"tertiary\" size=\"small\" />}\n <Typography variant=\"bonprix-h6\" component={level} className=\"grow line-clamp-2\" id={titleId}>\n {children}\n </Typography>\n <IconButton onClick={onClose} icon=\"closer\" label=\"Schließen\" variant=\"tertiary\" size=\"small\" />\n </div>\n {subline && <Typography>{subline}</Typography>}\n </div>\n );\n};\n\nconst Content = ({ children, disableHorizontalPadding = false }: SheetContentProps) => {\n const { scrollRef: setScrollRef } = useConsumeBottomSheet();\n const { scrollArea } = generateClasses({ disableHorizontalPadding });\n\n return (\n <div ref={setScrollRef} className={scrollArea()} data-bpds-disable-horizontal-padding={disableHorizontalPadding}>\n {children}\n </div>\n );\n};\n\nconst ButtonSection = ({ children }: SheetButtonSectionProps) => {\n return <div className=\"button-section w-full flex flex-col gap-3 px-4 pt-4 shrink-0 touch-pan-down\">{children}</div>;\n};\n\nconst PrimaryButton = <C extends ElementType>({\n children,\n icon,\n iconPosition,\n loading,\n component = \"button\" as C,\n ...props\n}: SheetPrimaryButtonProps<C>) => {\n const Component: ElementType = component;\n const { onClick, type = \"button\", ...otherProps } = props;\n const { onClose } = useConsumeBottomSheet();\n const handleClick = (event: React.MouseEvent) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n onClick?.(event);\n onClose();\n };\n return (\n <Button\n component={Component}\n {...otherProps}\n variant=\"primary\"\n onClick={handleClick}\n type={type}\n icon={icon}\n iconPosition={iconPosition}\n size=\"large\"\n loading={loading}\n >\n {children}\n </Button>\n );\n};\n\nconst SecondaryButton = <C extends ElementType>({\n children,\n icon,\n iconPosition,\n component = \"button\" as C,\n ...props\n}: SheetButtonProps<C>) => {\n const Component: ElementType = component;\n const { onClose } = useConsumeBottomSheet();\n return (\n <Button\n component={Component}\n {...props}\n variant=\"secondary\"\n type=\"button\"\n onClick={onClose}\n icon={icon}\n iconPosition={iconPosition}\n size=\"large\"\n >\n {children}\n </Button>\n );\n};\n\nBottomSheet.displayName = \"BottomSheet\";\n\nBottomSheet.Title = Title;\nBottomSheet.Content = Content;\nBottomSheet.ButtonSection = ButtonSection;\nBottomSheet.PrimaryButton = PrimaryButton;\nBottomSheet.SecondaryButton = SecondaryButton;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Breadcrumb.js","names":[],"sources":["../../../src/components/Breadcrumb/Breadcrumb.tsx"],"sourcesContent":["\"use client\";\n\nimport Icon from \"@bonprix-ds/react-icon\";\nimport Typography from \"@bonprix-ds/react-typography\";\nimport React, { ComponentProps, ElementType } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nconst generateClasses = tv({\n base: \"preflight flex flex-col gap-1 text-clr-on-bg-high\",\n slots: {\n link: \"flex items-center gap-1 group focus:outline-none\",\n icon: \"w-7 h-7 fill-clr-on-bg-high\",\n previousPageContainer: \"border border-transparent group-focus:border-clr-primary rounded-sm\",\n previousPage: [\n \"typography-body1 pt-0.5 mx-0.5 border-b-2 border-transparent\",\n \"group-hover:border-clr-primary group-focus:group-hover:border-transparent\",\n ],\n header: \"flex gap-x-2 items-baseline flex-wrap\",\n iconWrapper: \"min-w-7 min-h-7\",\n },\n});\n\ninterface BaseProps {\n /** Title of the current page. */\n currentPageTitle: string;\n /** Title of the previous page. */\n previousPageTitle: string;\n /** URL of the previous page */\n previousPageUrl: string;\n /** Will completely hide the title of the current page and the amount of items, if set to `true`. */\n hideHeader?: boolean;\n /** Text that should contain the amount of items for the channel or category page. */\n numberOfItemsText?: string;\n}\n\nexport type Props<C extends ElementType> = BaseProps & {\n /** The semantic component to render the Breadcrumb's previous page. Preferrably `\"a\"` or something like `Link` from NextJS. Defaults to `\"a\"`. Native props will be passed to this component. */\n previousPageComponent?: C;\n} & Omit<ComponentProps<C>, keyof BaseProps | \"previousPageComponent\" | \"href\">;\n\nconst Breadcrumb = <C extends ElementType>({\n currentPageTitle,\n previousPageTitle,\n previousPageUrl,\n hideHeader = false,\n numberOfItemsText = \"\",\n previousPageComponent = \"a\" as C,\n ...previousLinkProps\n}: Props<C>) => {\n const PreviousPageComponent: ElementType = previousPageComponent;\n const { base, icon, previousPage, previousPageContainer, link, header, iconWrapper } = generateClasses();\n return (\n <div className={base()} data-bpds=\"breadcrumb\" data-bpds-hide-header={hideHeader}>\n <PreviousPageComponent href={previousPageUrl} className={link()} {...previousLinkProps}>\n <span className={iconWrapper()}>\n {/* Preserve size before icon loads to avoid flicker, until the way SVG is loaded changes */}\n <Icon variant=\"back\" className={icon()} />\n </span>\n\n <span className={previousPageContainer()}>\n <span className={previousPage()}>{previousPageTitle}</span>\n </span>\n </PreviousPageComponent>\n {hideHeader ? null : (\n <div className={header()}>\n <Typography variant=\"bonprix-h3\">{currentPageTitle}</Typography>\n <Typography color=\"on-bg-low\">{numberOfItemsText}</Typography>\n </div>\n )}\n </div>\n );\n};\n\nexport default Breadcrumb;\n"],"mappings":";;;;;;;AAOA,IAAM,IAAkB,EAAG;CACzB,MAAM;CACN,OAAO;EACL,MAAM;EACN,MAAM;EACN,uBAAuB;EACvB,cAAc,CACZ,gEACA,2EACF;EACA,QAAQ;EACR,aAAa;CACf;AACF,CAAC,GAoBK,KAAqC,EACzC,qBACA,sBACA,oBACA,gBAAa,IACb,uBAAoB,IACpB,2BAAwB,KACxB,GAAG,QACW;CACd,IAAM,IAAqC,GACrC,EAAE,SAAM,SAAM,iBAAc,0BAAuB,SAAM,WAAQ,mBAAgB,EAAgB;CACvG,OACE,kBAAC,OAAD;EAAK,WAAW,EAAK;EAAG,aAAU;EAAa,yBAAuB;
|
|
1
|
+
{"version":3,"file":"Breadcrumb.js","names":[],"sources":["../../../src/components/Breadcrumb/Breadcrumb.tsx"],"sourcesContent":["\"use client\";\n\nimport Icon from \"@bonprix-ds/react-icon\";\nimport Typography from \"@bonprix-ds/react-typography\";\nimport React, { ComponentProps, ElementType } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nconst generateClasses = tv({\n base: \"preflight flex flex-col gap-1 text-clr-on-bg-high\",\n slots: {\n link: \"flex items-center gap-1 group focus:outline-none\",\n icon: \"w-7 h-7 fill-clr-on-bg-high\",\n previousPageContainer: \"border border-transparent group-focus:border-clr-primary rounded-sm\",\n previousPage: [\n \"typography-body1 pt-0.5 mx-0.5 border-b-2 border-transparent\",\n \"group-hover:border-clr-primary group-focus:group-hover:border-transparent\",\n ],\n header: \"flex gap-x-2 items-baseline flex-wrap\",\n iconWrapper: \"min-w-7 min-h-7\",\n },\n});\n\ninterface BaseProps {\n /** Title of the current page. */\n currentPageTitle: string;\n /** Title of the previous page. */\n previousPageTitle: string;\n /** URL of the previous page */\n previousPageUrl: string;\n /** Will completely hide the title of the current page and the amount of items, if set to `true`. */\n hideHeader?: boolean;\n /** Text that should contain the amount of items for the channel or category page. */\n numberOfItemsText?: string;\n}\n\nexport type Props<C extends ElementType> = BaseProps & {\n /** The semantic component to render the Breadcrumb's previous page. Preferrably `\"a\"` or something like `Link` from NextJS. Defaults to `\"a\"`. Native props will be passed to this component. */\n previousPageComponent?: C;\n} & Omit<ComponentProps<C>, keyof BaseProps | \"previousPageComponent\" | \"href\">;\n\nconst Breadcrumb = <C extends ElementType>({\n currentPageTitle,\n previousPageTitle,\n previousPageUrl,\n hideHeader = false,\n numberOfItemsText = \"\",\n previousPageComponent = \"a\" as C,\n ...previousLinkProps\n}: Props<C>) => {\n const PreviousPageComponent: ElementType = previousPageComponent;\n const { base, icon, previousPage, previousPageContainer, link, header, iconWrapper } = generateClasses();\n return (\n <div className={base()} data-bpds=\"breadcrumb\" data-bpds-hide-header={hideHeader}>\n <PreviousPageComponent href={previousPageUrl} className={link()} {...previousLinkProps}>\n <span className={iconWrapper()}>\n {/* Preserve size before icon loads to avoid flicker, until the way SVG is loaded changes */}\n <Icon variant=\"back\" className={icon()} />\n </span>\n\n <span className={previousPageContainer()}>\n <span className={previousPage()}>{previousPageTitle}</span>\n </span>\n </PreviousPageComponent>\n {hideHeader ? null : (\n <div className={header()}>\n <Typography variant=\"bonprix-h3\">{currentPageTitle}</Typography>\n <Typography color=\"on-bg-low\">{numberOfItemsText}</Typography>\n </div>\n )}\n </div>\n );\n};\n\nexport default Breadcrumb;\n"],"mappings":";;;;;;;AAOA,IAAM,IAAkB,EAAG;CACzB,MAAM;CACN,OAAO;EACL,MAAM;EACN,MAAM;EACN,uBAAuB;EACvB,cAAc,CACZ,gEACA,2EACF;EACA,QAAQ;EACR,aAAa;CACf;AACF,CAAC,GAoBK,KAAqC,EACzC,qBACA,sBACA,oBACA,gBAAa,IACb,uBAAoB,IACpB,2BAAwB,KACxB,GAAG,QACW;CACd,IAAM,IAAqC,GACrC,EAAE,SAAM,SAAM,iBAAc,0BAAuB,SAAM,WAAQ,mBAAgB,EAAgB;CACvG,OACE,kBAAC,OAAD;EAAK,WAAW,EAAK;EAAG,aAAU;EAAa,yBAAuB;EAAtE,UAAA,CACE,kBAAC,GAAD;GAAuB,MAAM;GAAiB,WAAW,EAAK;GAAG,GAAI;GAArE,UAAA,CACE,kBAAC,QAAD;IAAM,WAAW,EAAY;IAE3B,UAAA,kBAAC,GAAD;KAAM,SAAQ;KAAO,WAAW,EAAK;IAAI,CAAA;GACrC,CAAA,GAEN,kBAAC,QAAD;IAAM,WAAW,EAAsB;IACrC,UAAA,kBAAC,QAAD;KAAM,WAAW,EAAa;KAAI,UAAA;IAAwB,CAAA;GACtD,CAAA,CACe;EACtB,CAAA,GAAA,IAAa,OACZ,kBAAC,OAAD;GAAK,WAAW,EAAO;GAAvB,UAAA,CACE,kBAAC,GAAD;IAAY,SAAQ;IAAc,UAAA;GAA6B,CAAA,GAC/D,kBAAC,GAAD;IAAY,OAAM;IAAa,UAAA;GAA8B,CAAA,CAC1D;EAEJ,CAAA,CAAA;;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BadgeIconButton.js","names":[],"sources":["../../../../src/components/Buttons/BadgeIconButton/BadgeIconButton.tsx"],"sourcesContent":["\"use client\";\n\nimport { IconType } from \"@bonprix-ds/react-icon\";\nimport IconButton from \"@bonprix-ds/react-icon-button\";\nimport React, { ComponentProps, ElementType } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\ninterface BaseProps {\n /** If used, an icon will be additionally shown. The value is a name of one icon from our icon set. */\n icon: IconType;\n /** An accessible label of the icon button. */\n label: string;\n /** A number that is shown in the badge. It is quantitatively related to the context of the button. If the amount is zero, no badge will be shown. If the amount is more then 99, then the displayed value will be capped to \"99+\" */\n amount?: number;\n}\n\nexport type Props<C extends ElementType> = BaseProps & {\n /** The semantic component to render the BadgeIconButton. Preferrably `\"button\"`, `\"a\"` or something like `Link` from NextJS. Defaults to `\"button\"`. Native props will be passed to this component. */\n component?: C;\n} & Omit<ComponentProps<C>, keyof BaseProps | \"component\">;\n\nconst generateClasses = tv({\n base: \"preflight relative inline-block w-fit\",\n slots: {\n counter:\n \"typography-body2 text-clr-on-primary-high absolute flex px-[0.3125rem] bg-clr-primary min-w-4 h-4 rounded-full start-6 top-1 pointer-events-none\",\n },\n});\n\nconst BadgeIconButton = <C extends ElementType = \"button\">({ amount = 0, label, component = \"button\" as C, ...props }: Props<C>) => {\n const Component: ElementType = component;\n const badgeVisible = amount > 0;\n const SRlabel = badgeVisible ? label.replace(/(\\s)*\\.?(\\s)*$/, `. ${amount} artikel`) : label;\n const badgeCounter = amount > 99 ? \"99+\" : amount;\n const { base, counter } = generateClasses();\n return (\n <span className={base()} data-bpds=\"badge-icon-button\" data-bpds-amount={amount}>\n <IconButton {...props} component={Component} label={SRlabel} variant=\"tertiary\" hasPadding />\n {badgeVisible && <span className={counter()}>{badgeCounter}</span>}\n </span>\n );\n};\nexport default BadgeIconButton;\n"],"mappings":";;;;;;AAqBA,IAAM,IAAkB,EAAG;CACzB,MAAM;CACN,OAAO,EACL,SACE,mJACJ;AACF,CAAC,GAEK,KAAqD,EAAE,YAAS,GAAG,UAAO,eAAY,UAAe,GAAG,QAAsB;CAClI,IAAM,IAAyB,GACzB,IAAe,IAAS,GACxB,IAAU,IAAe,EAAM,QAAQ,kBAAkB,KAAK,EAAO,SAAS,IAAI,GAClF,IAAe,IAAS,KAAK,QAAQ,GACrC,EAAE,SAAM,eAAY,EAAgB;CAC1C,OACE,kBAAC,QAAD;EAAM,WAAW,EAAK;EAAG,aAAU;EAAoB,oBAAkB;
|
|
1
|
+
{"version":3,"file":"BadgeIconButton.js","names":[],"sources":["../../../../src/components/Buttons/BadgeIconButton/BadgeIconButton.tsx"],"sourcesContent":["\"use client\";\n\nimport { IconType } from \"@bonprix-ds/react-icon\";\nimport IconButton from \"@bonprix-ds/react-icon-button\";\nimport React, { ComponentProps, ElementType } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\ninterface BaseProps {\n /** If used, an icon will be additionally shown. The value is a name of one icon from our icon set. */\n icon: IconType;\n /** An accessible label of the icon button. */\n label: string;\n /** A number that is shown in the badge. It is quantitatively related to the context of the button. If the amount is zero, no badge will be shown. If the amount is more then 99, then the displayed value will be capped to \"99+\" */\n amount?: number;\n}\n\nexport type Props<C extends ElementType> = BaseProps & {\n /** The semantic component to render the BadgeIconButton. Preferrably `\"button\"`, `\"a\"` or something like `Link` from NextJS. Defaults to `\"button\"`. Native props will be passed to this component. */\n component?: C;\n} & Omit<ComponentProps<C>, keyof BaseProps | \"component\">;\n\nconst generateClasses = tv({\n base: \"preflight relative inline-block w-fit\",\n slots: {\n counter:\n \"typography-body2 text-clr-on-primary-high absolute flex px-[0.3125rem] bg-clr-primary min-w-4 h-4 rounded-full start-6 top-1 pointer-events-none\",\n },\n});\n\nconst BadgeIconButton = <C extends ElementType = \"button\">({ amount = 0, label, component = \"button\" as C, ...props }: Props<C>) => {\n const Component: ElementType = component;\n const badgeVisible = amount > 0;\n const SRlabel = badgeVisible ? label.replace(/(\\s)*\\.?(\\s)*$/, `. ${amount} artikel`) : label;\n const badgeCounter = amount > 99 ? \"99+\" : amount;\n const { base, counter } = generateClasses();\n return (\n <span className={base()} data-bpds=\"badge-icon-button\" data-bpds-amount={amount}>\n <IconButton {...props} component={Component} label={SRlabel} variant=\"tertiary\" hasPadding />\n {badgeVisible && <span className={counter()}>{badgeCounter}</span>}\n </span>\n );\n};\nexport default BadgeIconButton;\n"],"mappings":";;;;;;AAqBA,IAAM,IAAkB,EAAG;CACzB,MAAM;CACN,OAAO,EACL,SACE,mJACJ;AACF,CAAC,GAEK,KAAqD,EAAE,YAAS,GAAG,UAAO,eAAY,UAAe,GAAG,QAAsB;CAClI,IAAM,IAAyB,GACzB,IAAe,IAAS,GACxB,IAAU,IAAe,EAAM,QAAQ,kBAAkB,KAAK,EAAO,SAAS,IAAI,GAClF,IAAe,IAAS,KAAK,QAAQ,GACrC,EAAE,SAAM,eAAY,EAAgB;CAC1C,OACE,kBAAC,QAAD;EAAM,WAAW,EAAK;EAAG,aAAU;EAAoB,oBAAkB;EAAzE,UAAA,CACE,kBAAC,GAAD;GAAY,GAAI;GAAO,WAAW;GAAW,OAAO;GAAS,SAAQ;GAAW,YAAA;EAAY,CAAA,GAC3F,KAAgB,kBAAC,QAAD;GAAM,WAAW,EAAQ;GAAI,UAAA;EAAmB,CAAA,CAC7D;;AAEV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ButtonsSection.js","names":[],"sources":["../../../src/components/ButtonsSection/ButtonsSection.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { FC, ReactNode } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { useSubcomponent } from \"@hooks\";\n\nimport PrimaryButton, { Props as SubcomponentProps } from \"./PrimaryButton\";\nimport SecondaryButton from \"./SecondaryButton\";\n\nconst generateClasses = tv({\n slots: { root: \"flex justify-center flex-wrap gap-3\" },\n});\n\nexport interface Props {\n owner: string;\n primary: ReactNode;\n secondary?: ReactNode;\n fullWidthButtons?: boolean;\n classes?: string;\n}\n\nconst ButtonsSection: FC<Props> = ({ owner, primary, secondary, fullWidthButtons = false, classes = \"\" }) => {\n const { getSingleChildFromSubcomponent, printBadConstructionMessage } = useSubcomponent([primary, secondary]);\n const injectedProps = { contentWidth: !fullWidthButtons } as SubcomponentProps<\"button\">;\n const { root } = generateClasses();\n\n if (!primary) {\n printBadConstructionMessage(`${owner}'s ButtonSection`);\n return null;\n }\n\n return (\n <div className={root({ class: classes })}>\n {getSingleChildFromSubcomponent(SecondaryButton, secondary ?? null, injectedProps)}\n {getSingleChildFromSubcomponent(PrimaryButton, primary, injectedProps)}\n </div>\n );\n};\n\nexport default ButtonsSection;\n"],"mappings":";;;;;;;;AAUA,IAAM,IAAkB,EAAG,EACzB,OAAO,EAAE,MAAM,sCAAsC,EACvD,CAAC,GAUK,KAA6B,EAAE,UAAO,YAAS,cAAW,sBAAmB,IAAO,aAAU,SAAS;CAC3G,IAAM,EAAE,mCAAgC,mCAAgC,EAAgB,CAAC,GAAS,CAAS,CAAC,GACtG,IAAgB,EAAE,cAAc,CAAC,EAAiB,GAClD,EAAE,YAAS,EAAgB;CAOjC,OALK,IAMH,kBAAC,OAAD;EAAK,WAAW,EAAK,EAAE,OAAO,EAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"ButtonsSection.js","names":[],"sources":["../../../src/components/ButtonsSection/ButtonsSection.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { FC, ReactNode } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { useSubcomponent } from \"@hooks\";\n\nimport PrimaryButton, { Props as SubcomponentProps } from \"./PrimaryButton\";\nimport SecondaryButton from \"./SecondaryButton\";\n\nconst generateClasses = tv({\n slots: { root: \"flex justify-center flex-wrap gap-3\" },\n});\n\nexport interface Props {\n owner: string;\n primary: ReactNode;\n secondary?: ReactNode;\n fullWidthButtons?: boolean;\n classes?: string;\n}\n\nconst ButtonsSection: FC<Props> = ({ owner, primary, secondary, fullWidthButtons = false, classes = \"\" }) => {\n const { getSingleChildFromSubcomponent, printBadConstructionMessage } = useSubcomponent([primary, secondary]);\n const injectedProps = { contentWidth: !fullWidthButtons } as SubcomponentProps<\"button\">;\n const { root } = generateClasses();\n\n if (!primary) {\n printBadConstructionMessage(`${owner}'s ButtonSection`);\n return null;\n }\n\n return (\n <div className={root({ class: classes })}>\n {getSingleChildFromSubcomponent(SecondaryButton, secondary ?? null, injectedProps)}\n {getSingleChildFromSubcomponent(PrimaryButton, primary, injectedProps)}\n </div>\n );\n};\n\nexport default ButtonsSection;\n"],"mappings":";;;;;;;;AAUA,IAAM,IAAkB,EAAG,EACzB,OAAO,EAAE,MAAM,sCAAsC,EACvD,CAAC,GAUK,KAA6B,EAAE,UAAO,YAAS,cAAW,sBAAmB,IAAO,aAAU,SAAS;CAC3G,IAAM,EAAE,mCAAgC,mCAAgC,EAAgB,CAAC,GAAS,CAAS,CAAC,GACtG,IAAgB,EAAE,cAAc,CAAC,EAAiB,GAClD,EAAE,YAAS,EAAgB;CAOjC,OALK,IAMH,kBAAC,OAAD;EAAK,WAAW,EAAK,EAAE,OAAO,EAAQ,CAAC;EAAvC,UAAA,CACG,EAA+B,GAAiB,KAAa,MAAM,CAAa,GAChF,EAA+B,GAAe,GAAS,CAAa,CAClE;OARL,EAA4B,GAAG,EAAM,iBAAiB,GAC/C;AASX"}
|
|
@@ -27,36 +27,38 @@ var c = n({
|
|
|
27
27
|
} }
|
|
28
28
|
}), l = ({ children: n, label: l, perPage: u = 1, perMove: d = 1, rewind: f = !1, buttonsContrast: p = !1, invertButtons: m = !1, focus: h, gap: g = 20, showArrows: _ = "always", pagination: v = !0, onMove: y, padding: b, disableHorizontalPadding: x = !1, start: S = 0, disableDrag: C = !1, paginationRef: w }) => {
|
|
29
29
|
let { getChildrenFromSubcomponent: T, printBadConstructionMessage: E } = e(n), { root: D, buttons: O, paginationClass: k, page: A } = c({ showArrows: _ });
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
slideLabel: "%s von %s"
|
|
57
|
-
},
|
|
58
|
-
drag: !C
|
|
30
|
+
if (!n) return E("Carousel"), null;
|
|
31
|
+
let j = {
|
|
32
|
+
perPage: u,
|
|
33
|
+
perMove: d,
|
|
34
|
+
type: f ? "loop" : "slide",
|
|
35
|
+
focus: h,
|
|
36
|
+
gap: g,
|
|
37
|
+
arrows: _ !== "never",
|
|
38
|
+
pagination: v,
|
|
39
|
+
padding: b,
|
|
40
|
+
start: S,
|
|
41
|
+
lazyLoad: "nearby",
|
|
42
|
+
classes: { page: A() },
|
|
43
|
+
i18n: {
|
|
44
|
+
prev: "vorherige Ansicht",
|
|
45
|
+
next: "nächste Ansicht",
|
|
46
|
+
first: "erste Ansicht",
|
|
47
|
+
last: "letzte Ansicht",
|
|
48
|
+
slideX: "gehe zu Ansicht %s",
|
|
49
|
+
pageX: "gehe zu Seite %s",
|
|
50
|
+
play: "starte Wiedergabe",
|
|
51
|
+
pause: "pausiere Wiedergabe",
|
|
52
|
+
carousel: "carousel",
|
|
53
|
+
select: "wähle eine Ansicht aus",
|
|
54
|
+
slide: "slide",
|
|
55
|
+
slideLabel: "%s von %s"
|
|
59
56
|
},
|
|
57
|
+
drag: !C
|
|
58
|
+
};
|
|
59
|
+
return /* @__PURE__ */ i(a, {
|
|
60
|
+
"aria-label": l,
|
|
61
|
+
options: j,
|
|
60
62
|
hasTrack: !1,
|
|
61
63
|
onMove: (e, t, n) => y?.(t, n),
|
|
62
64
|
"data-bpds": "carousel",
|
|
@@ -92,7 +94,7 @@ var c = n({
|
|
|
92
94
|
ref: w
|
|
93
95
|
})
|
|
94
96
|
]
|
|
95
|
-
})
|
|
97
|
+
});
|
|
96
98
|
};
|
|
97
99
|
l.displayName = "Carousel", l.Slide = o, o.displayName = "Carousel.Slide";
|
|
98
100
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Carousel.js","names":[],"sources":["../../../src/components/Carousel/Carousel.tsx"],"sourcesContent":["\"use client\";\n\n/* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment */\nimport React, { ComponentPropsWithoutRef, FC, Ref } from \"react\";\nimport { tv } from \"tailwind-variants\";\n// @ts-expect-error: Splide does not export its types correctly and hasn't been maintained for a few years now, so we are not expecting that to change. This component will be replaced soon, so we'll not take effort to fix or patch this.\nimport { Options, Splide, SplideSlide, SplideTrack } from \"@splidejs/react-splide\";\n\nimport { useSubcomponent } from \"@hooks\";\n\nimport CarouselArrow from \"./CarouselArrow\";\n\nconst generateClasses = tv({\n slots: {\n root: \"\",\n buttons: \"\",\n paginationClass: \"splide__pagination flex gap-1 absolute start-0 end-0 bottom-2 px-4 py-0 z-1\",\n page: [\n \"splide__pagination__page block p-0 relative bg-clr-on-bg-low w-3 h-0.25 m-0 opacity-100 border-none rounded-none transform-none transition-all\",\n \"[&.is-active]:bg-clr-black [&.is-active]:h-1\",\n \"after:content-[''] after:absolute after:start-0 after:-mt-1 after:h-2 after:w-3 after:cursor-pointer [&.is-active]:after:content-[]\",\n ],\n },\n variants: {\n showArrows: {\n always: \"\",\n hover: {\n root: \"group/crsl\",\n buttons: \"hidden group-hover/crsl:flex\",\n },\n never: \"\",\n },\n },\n});\n\ninterface Subcomponents {\n Slide: typeof SplideSlide;\n}\n\nexport interface Props {\n /** The content of the carousel. Here, Carousel.Slide subcomponents should be placed. */\n children: React.ReactNode;\n /** Sets accessible label with help of `aria-label` */\n label: string;\n /** Amount of slides to show per page. */\n perPage?: number;\n /** Amount of slides to move on each transition. */\n perMove?: number;\n /** If set to `true`, the carousel will loop back to the first slide after reaching the last one. */\n rewind?: boolean;\n /** If set to `true`, the primary variant of icon buttons will be used to achieve a high contrast. */\n buttonsContrast?: boolean;\n /** If set to `true`, the color of the arrow buttons will be inverted. */\n invertButtons?: boolean;\n /** If set to `true`, the horizontal padding for the arrow buttons will be removed. */\n disableHorizontalPadding?: boolean;\n /** Determines which slide should be active if there are multiple slides in a page */\n focus?: number | \"center\";\n /** The gap between the slides in pixels. */\n gap?: number;\n /** Manages the behavior of the arrow icon buttons. */\n showArrows?: \"always\" | \"hover\" | \"never\";\n /** Toggles the visibility of page indicators. */\n pagination?: boolean;\n /** Callback function that is called when the slide changes. */\n onMove?: (destIndex: number, prevIndex: number) => void;\n /** Sets padding left/right or top/bottom of the carousel. The CSS format is acceptable */\n padding?: Options[\"padding\"];\n /** The index of the initial slide to be displayed */\n start?: number;\n /* If `true`, disables dragging/swiping between slides. Can be used to control touch events and implement further gestures like pinch/zoom. */\n disableDrag?: boolean;\n /* Ref to the pagination element. Can be used to control pagination from outside of the Carousel component. */\n paginationRef?: Ref<HTMLUListElement>;\n}\n\ntype SplideProps = ComponentPropsWithoutRef<typeof Splide>;\ntype SplideOptions = SplideProps[\"options\"];\n\nconst Carousel: FC<Props> & Subcomponents = ({\n children,\n label,\n perPage = 1,\n perMove = 1,\n rewind = false,\n buttonsContrast = false,\n invertButtons = false,\n focus,\n gap = 20,\n showArrows = \"always\",\n pagination = true,\n onMove,\n padding,\n disableHorizontalPadding = false,\n start = 0,\n disableDrag = false,\n paginationRef,\n}) => {\n const { getChildrenFromSubcomponent, printBadConstructionMessage } = useSubcomponent(children);\n const { root, buttons, paginationClass, page } = generateClasses({ showArrows });\n\n if (!children) {\n printBadConstructionMessage(\"Carousel\");\n return null;\n }\n\n const options: SplideOptions = {\n perPage,\n perMove,\n type: rewind ? \"loop\" : \"slide\",\n focus,\n gap,\n arrows: showArrows !== \"never\",\n pagination,\n padding,\n start,\n lazyLoad: \"nearby\",\n classes: { page: page() },\n i18n: {\n prev: \"vorherige Ansicht\",\n next: \"nächste Ansicht\",\n first: \"erste Ansicht\",\n last: \"letzte Ansicht\",\n slideX: \"gehe zu Ansicht %s\",\n pageX: \"gehe zu Seite %s\",\n play: \"starte Wiedergabe\",\n pause: \"pausiere Wiedergabe\",\n carousel: \"carousel\",\n select: \"wähle eine Ansicht aus\",\n slide: \"slide\",\n slideLabel: \"%s von %s\",\n },\n drag: !disableDrag,\n };\n\n return (\n <Splide\n aria-label={label}\n options={options}\n hasTrack={false}\n onMove={(_slide: unknown, destIndex: number, prevIndex: number) => onMove?.(destIndex, prevIndex)}\n data-bpds=\"carousel\"\n data-bpds-per-page={perPage}\n data-bpds-per-move={perMove}\n data-bpds-rewind={rewind}\n data-bpds-buttons-contrast={buttonsContrast}\n data-bpds-invert-buttons={invertButtons}\n data-bpds-disable-horizontal-padding={disableHorizontalPadding}\n data-bpds-gap={gap}\n data-bpds-padding={padding}\n data-bpds-pagination={pagination}\n data-bpds-show-arrows={showArrows}\n className={root()}\n >\n <div className={`splide__arrows ${buttons()}`}>\n <CarouselArrow\n invertButtons={invertButtons}\n position=\"left\"\n buttonsContrast={buttonsContrast}\n disableHorizontalPadding={disableHorizontalPadding}\n />\n <CarouselArrow\n invertButtons={invertButtons}\n position=\"right\"\n buttonsContrast={buttonsContrast}\n disableHorizontalPadding={disableHorizontalPadding}\n />\n </div>\n <SplideTrack>{getChildrenFromSubcomponent(SplideSlide)}</SplideTrack>\n <ul className={paginationClass()} ref={paginationRef}></ul>\n </Splide>\n );\n};\n\nCarousel.displayName = \"Carousel\";\n\nCarousel.Slide = SplideSlide;\n// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\nSplideSlide.displayName = \"Carousel.Slide\";\n\nexport default Carousel;\n"],"mappings":";;;;;;;;AAYA,IAAM,IAAkB,EAAG;CACzB,OAAO;EACL,MAAM;EACN,SAAS;EACT,iBAAiB;EACjB,MAAM;GACJ;GACA;GACA;EACF;CACF;CACA,UAAU,EACR,YAAY;EACV,QAAQ;EACR,OAAO;GACL,MAAM;GACN,SAAS;EACX;EACA,OAAO;CACT,EACF;AACF,CAAC,GA8CK,KAAuC,EAC3C,aACA,UACA,aAAU,GACV,aAAU,GACV,YAAS,IACT,qBAAkB,IAClB,mBAAgB,IAChB,UACA,SAAM,IACN,gBAAa,UACb,gBAAa,IACb,WACA,YACA,8BAA2B,IAC3B,WAAQ,GACR,iBAAc,IACd,uBACI;CACJ,IAAM,EAAE,gCAA6B,mCAAgC,EAAgB,CAAQ,GACvF,EAAE,SAAM,YAAS,oBAAiB,YAAS,EAAgB,EAAE,cAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"Carousel.js","names":[],"sources":["../../../src/components/Carousel/Carousel.tsx"],"sourcesContent":["\"use client\";\n\n/* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment */\nimport React, { ComponentPropsWithoutRef, FC, Ref } from \"react\";\nimport { tv } from \"tailwind-variants\";\n// @ts-expect-error: Splide does not export its types correctly and hasn't been maintained for a few years now, so we are not expecting that to change. This component will be replaced soon, so we'll not take effort to fix or patch this.\nimport { Options, Splide, SplideSlide, SplideTrack } from \"@splidejs/react-splide\";\n\nimport { useSubcomponent } from \"@hooks\";\n\nimport CarouselArrow from \"./CarouselArrow\";\n\nconst generateClasses = tv({\n slots: {\n root: \"\",\n buttons: \"\",\n paginationClass: \"splide__pagination flex gap-1 absolute start-0 end-0 bottom-2 px-4 py-0 z-1\",\n page: [\n \"splide__pagination__page block p-0 relative bg-clr-on-bg-low w-3 h-0.25 m-0 opacity-100 border-none rounded-none transform-none transition-all\",\n \"[&.is-active]:bg-clr-black [&.is-active]:h-1\",\n \"after:content-[''] after:absolute after:start-0 after:-mt-1 after:h-2 after:w-3 after:cursor-pointer [&.is-active]:after:content-[]\",\n ],\n },\n variants: {\n showArrows: {\n always: \"\",\n hover: {\n root: \"group/crsl\",\n buttons: \"hidden group-hover/crsl:flex\",\n },\n never: \"\",\n },\n },\n});\n\ninterface Subcomponents {\n Slide: typeof SplideSlide;\n}\n\nexport interface Props {\n /** The content of the carousel. Here, Carousel.Slide subcomponents should be placed. */\n children: React.ReactNode;\n /** Sets accessible label with help of `aria-label` */\n label: string;\n /** Amount of slides to show per page. */\n perPage?: number;\n /** Amount of slides to move on each transition. */\n perMove?: number;\n /** If set to `true`, the carousel will loop back to the first slide after reaching the last one. */\n rewind?: boolean;\n /** If set to `true`, the primary variant of icon buttons will be used to achieve a high contrast. */\n buttonsContrast?: boolean;\n /** If set to `true`, the color of the arrow buttons will be inverted. */\n invertButtons?: boolean;\n /** If set to `true`, the horizontal padding for the arrow buttons will be removed. */\n disableHorizontalPadding?: boolean;\n /** Determines which slide should be active if there are multiple slides in a page */\n focus?: number | \"center\";\n /** The gap between the slides in pixels. */\n gap?: number;\n /** Manages the behavior of the arrow icon buttons. */\n showArrows?: \"always\" | \"hover\" | \"never\";\n /** Toggles the visibility of page indicators. */\n pagination?: boolean;\n /** Callback function that is called when the slide changes. */\n onMove?: (destIndex: number, prevIndex: number) => void;\n /** Sets padding left/right or top/bottom of the carousel. The CSS format is acceptable */\n padding?: Options[\"padding\"];\n /** The index of the initial slide to be displayed */\n start?: number;\n /* If `true`, disables dragging/swiping between slides. Can be used to control touch events and implement further gestures like pinch/zoom. */\n disableDrag?: boolean;\n /* Ref to the pagination element. Can be used to control pagination from outside of the Carousel component. */\n paginationRef?: Ref<HTMLUListElement>;\n}\n\ntype SplideProps = ComponentPropsWithoutRef<typeof Splide>;\ntype SplideOptions = SplideProps[\"options\"];\n\nconst Carousel: FC<Props> & Subcomponents = ({\n children,\n label,\n perPage = 1,\n perMove = 1,\n rewind = false,\n buttonsContrast = false,\n invertButtons = false,\n focus,\n gap = 20,\n showArrows = \"always\",\n pagination = true,\n onMove,\n padding,\n disableHorizontalPadding = false,\n start = 0,\n disableDrag = false,\n paginationRef,\n}) => {\n const { getChildrenFromSubcomponent, printBadConstructionMessage } = useSubcomponent(children);\n const { root, buttons, paginationClass, page } = generateClasses({ showArrows });\n\n if (!children) {\n printBadConstructionMessage(\"Carousel\");\n return null;\n }\n\n const options: SplideOptions = {\n perPage,\n perMove,\n type: rewind ? \"loop\" : \"slide\",\n focus,\n gap,\n arrows: showArrows !== \"never\",\n pagination,\n padding,\n start,\n lazyLoad: \"nearby\",\n classes: { page: page() },\n i18n: {\n prev: \"vorherige Ansicht\",\n next: \"nächste Ansicht\",\n first: \"erste Ansicht\",\n last: \"letzte Ansicht\",\n slideX: \"gehe zu Ansicht %s\",\n pageX: \"gehe zu Seite %s\",\n play: \"starte Wiedergabe\",\n pause: \"pausiere Wiedergabe\",\n carousel: \"carousel\",\n select: \"wähle eine Ansicht aus\",\n slide: \"slide\",\n slideLabel: \"%s von %s\",\n },\n drag: !disableDrag,\n };\n\n return (\n <Splide\n aria-label={label}\n options={options}\n hasTrack={false}\n onMove={(_slide: unknown, destIndex: number, prevIndex: number) => onMove?.(destIndex, prevIndex)}\n data-bpds=\"carousel\"\n data-bpds-per-page={perPage}\n data-bpds-per-move={perMove}\n data-bpds-rewind={rewind}\n data-bpds-buttons-contrast={buttonsContrast}\n data-bpds-invert-buttons={invertButtons}\n data-bpds-disable-horizontal-padding={disableHorizontalPadding}\n data-bpds-gap={gap}\n data-bpds-padding={padding}\n data-bpds-pagination={pagination}\n data-bpds-show-arrows={showArrows}\n className={root()}\n >\n <div className={`splide__arrows ${buttons()}`}>\n <CarouselArrow\n invertButtons={invertButtons}\n position=\"left\"\n buttonsContrast={buttonsContrast}\n disableHorizontalPadding={disableHorizontalPadding}\n />\n <CarouselArrow\n invertButtons={invertButtons}\n position=\"right\"\n buttonsContrast={buttonsContrast}\n disableHorizontalPadding={disableHorizontalPadding}\n />\n </div>\n <SplideTrack>{getChildrenFromSubcomponent(SplideSlide)}</SplideTrack>\n <ul className={paginationClass()} ref={paginationRef}></ul>\n </Splide>\n );\n};\n\nCarousel.displayName = \"Carousel\";\n\nCarousel.Slide = SplideSlide;\n// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\nSplideSlide.displayName = \"Carousel.Slide\";\n\nexport default Carousel;\n"],"mappings":";;;;;;;;AAYA,IAAM,IAAkB,EAAG;CACzB,OAAO;EACL,MAAM;EACN,SAAS;EACT,iBAAiB;EACjB,MAAM;GACJ;GACA;GACA;EACF;CACF;CACA,UAAU,EACR,YAAY;EACV,QAAQ;EACR,OAAO;GACL,MAAM;GACN,SAAS;EACX;EACA,OAAO;CACT,EACF;AACF,CAAC,GA8CK,KAAuC,EAC3C,aACA,UACA,aAAU,GACV,aAAU,GACV,YAAS,IACT,qBAAkB,IAClB,mBAAgB,IAChB,UACA,SAAM,IACN,gBAAa,UACb,gBAAa,IACb,WACA,YACA,8BAA2B,IAC3B,WAAQ,GACR,iBAAc,IACd,uBACI;CACJ,IAAM,EAAE,gCAA6B,mCAAgC,EAAgB,CAAQ,GACvF,EAAE,SAAM,YAAS,oBAAiB,YAAS,EAAgB,EAAE,cAAW,CAAC;CAE/E,IAAI,CAAC,GAEH,OADA,EAA4B,UAAU,GAC/B;CAGT,IAAM,IAAyB;EAC7B;EACA;EACA,MAAM,IAAS,SAAS;EACxB;EACA;EACA,QAAQ,MAAe;EACvB;EACA;EACA;EACA,UAAU;EACV,SAAS,EAAE,MAAM,EAAK,EAAE;EACxB,MAAM;GACJ,MAAM;GACN,MAAM;GACN,OAAO;GACP,MAAM;GACN,QAAQ;GACR,OAAO;GACP,MAAM;GACN,OAAO;GACP,UAAU;GACV,QAAQ;GACR,OAAO;GACP,YAAY;EACd;EACA,MAAM,CAAC;CACT;CAEA,OACE,kBAAC,GAAD;EACE,cAAY;EACH;EACT,UAAU;EACV,SAAS,GAAiB,GAAmB,MAAsB,IAAS,GAAW,CAAS;EAChG,aAAU;EACV,sBAAoB;EACpB,sBAAoB;EACpB,oBAAkB;EAClB,8BAA4B;EAC5B,4BAA0B;EAC1B,wCAAsC;EACtC,iBAAe;EACf,qBAAmB;EACnB,wBAAsB;EACtB,yBAAuB;EACvB,WAAW,EAAK;EAhBlB,UAAA;GAkBE,kBAAC,OAAD;IAAK,WAAW,kBAAkB,EAAQ;IAA1C,UAAA,CACE,kBAAC,GAAD;KACiB;KACf,UAAS;KACQ;KACS;IAC3B,CAAA,GACD,kBAAC,GAAD;KACiB;KACf,UAAS;KACQ;KACS;IAC3B,CAAA,CACE;;GACL,kBAAC,GAAD,EAAA,UAAc,EAA4B,CAAW,EAAe,CAAA;GACpE,kBAAC,MAAD;IAAI,WAAW,EAAgB;IAAG,KAAK;GAAmB,CAAA;EACpD;;AAEZ;AAEA,EAAS,cAAc,YAEvB,EAAS,QAAQ,GAEjB,EAAY,cAAc"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselArrow.js","names":[],"sources":["../../../src/components/Carousel/CarouselArrow.tsx"],"sourcesContent":["\"use client\";\n\nimport { BaseButton } from \"@bonprix-ds/internal-components\";\nimport React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nconst generateClasses = tv({\n slots: {\n wrapper: \"z-[1] absolute top-1/2 transform -translate-y-1/2\",\n button: \"disabled:hidden\",\n },\n variants: {\n position: {\n left: {\n wrapper: \"start-3\",\n button: \"splide__arrow--prev\",\n },\n right: {\n wrapper: \"end-3\",\n button: \"splide__arrow--next\",\n },\n },\n disableHorizontalPadding: {\n true: \"\",\n false: \"\",\n },\n },\n compoundVariants: [\n {\n disableHorizontalPadding: true,\n position: \"left\",\n class: {\n wrapper: \"start-0\",\n },\n },\n {\n disableHorizontalPadding: true,\n position: \"right\",\n class: {\n wrapper: \"end-0\",\n },\n },\n ],\n});\n\ninterface Props {\n position: \"left\" | \"right\";\n buttonsContrast: boolean;\n invertButtons: boolean;\n disableHorizontalPadding: boolean;\n}\n\nconst CarouselArrow: React.FC<Props> = ({ position, buttonsContrast, invertButtons, disableHorizontalPadding }) => {\n const isLeftArrow = position === \"left\" ? true : false;\n const icon = isLeftArrow ? \"arrow-left\" : \"arrow-right\";\n const label = isLeftArrow ? \"Previous Page\" : \"Next Page\";\n const variant = buttonsContrast ? \"primary\" : \"tertiary\";\n const { wrapper, button } = generateClasses({ position, disableHorizontalPadding });\n\n return (\n <span className={wrapper()}>\n <BaseButton type=\"button\" className={button()} variant={variant} icon={icon} componentName=\"icon-button\" inverted={invertButtons}>\n {label}\n </BaseButton>\n </span>\n );\n};\n\nexport default CarouselArrow;\n"],"mappings":";;;;;;AAMA,IAAM,IAAkB,EAAG;CACzB,OAAO;EACL,SAAS;EACT,QAAQ;CACV;CACA,UAAU;EACR,UAAU;GACR,MAAM;IACJ,SAAS;IACT,QAAQ;GACV;GACA,OAAO;IACL,SAAS;IACT,QAAQ;GACV;EACF;EACA,0BAA0B;GACxB,MAAM;GACN,OAAO;EACT;CACF;CACA,kBAAkB,CAChB;EACE,0BAA0B;EAC1B,UAAU;EACV,OAAO,EACL,SAAS,UACX;CACF,GACA;EACE,0BAA0B;EAC1B,UAAU;EACV,OAAO,EACL,SAAS,QACX;CACF,CACF;AACF,CAAC,GASK,KAAkC,EAAE,aAAU,oBAAiB,kBAAe,kCAA+B;CACjH,IAAM,IAAc,MAAa,QAC3B,IAAO,IAAc,eAAe,eACpC,IAAQ,IAAc,kBAAkB,aACxC,IAAU,IAAkB,YAAY,YACxC,EAAE,YAAS,cAAW,EAAgB;EAAE;EAAU;CAAyB,CAAC;CAElF,OACE,kBAAC,QAAD;EAAM,WAAW,EAAQ;
|
|
1
|
+
{"version":3,"file":"CarouselArrow.js","names":[],"sources":["../../../src/components/Carousel/CarouselArrow.tsx"],"sourcesContent":["\"use client\";\n\nimport { BaseButton } from \"@bonprix-ds/internal-components\";\nimport React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nconst generateClasses = tv({\n slots: {\n wrapper: \"z-[1] absolute top-1/2 transform -translate-y-1/2\",\n button: \"disabled:hidden\",\n },\n variants: {\n position: {\n left: {\n wrapper: \"start-3\",\n button: \"splide__arrow--prev\",\n },\n right: {\n wrapper: \"end-3\",\n button: \"splide__arrow--next\",\n },\n },\n disableHorizontalPadding: {\n true: \"\",\n false: \"\",\n },\n },\n compoundVariants: [\n {\n disableHorizontalPadding: true,\n position: \"left\",\n class: {\n wrapper: \"start-0\",\n },\n },\n {\n disableHorizontalPadding: true,\n position: \"right\",\n class: {\n wrapper: \"end-0\",\n },\n },\n ],\n});\n\ninterface Props {\n position: \"left\" | \"right\";\n buttonsContrast: boolean;\n invertButtons: boolean;\n disableHorizontalPadding: boolean;\n}\n\nconst CarouselArrow: React.FC<Props> = ({ position, buttonsContrast, invertButtons, disableHorizontalPadding }) => {\n const isLeftArrow = position === \"left\" ? true : false;\n const icon = isLeftArrow ? \"arrow-left\" : \"arrow-right\";\n const label = isLeftArrow ? \"Previous Page\" : \"Next Page\";\n const variant = buttonsContrast ? \"primary\" : \"tertiary\";\n const { wrapper, button } = generateClasses({ position, disableHorizontalPadding });\n\n return (\n <span className={wrapper()}>\n <BaseButton type=\"button\" className={button()} variant={variant} icon={icon} componentName=\"icon-button\" inverted={invertButtons}>\n {label}\n </BaseButton>\n </span>\n );\n};\n\nexport default CarouselArrow;\n"],"mappings":";;;;;;AAMA,IAAM,IAAkB,EAAG;CACzB,OAAO;EACL,SAAS;EACT,QAAQ;CACV;CACA,UAAU;EACR,UAAU;GACR,MAAM;IACJ,SAAS;IACT,QAAQ;GACV;GACA,OAAO;IACL,SAAS;IACT,QAAQ;GACV;EACF;EACA,0BAA0B;GACxB,MAAM;GACN,OAAO;EACT;CACF;CACA,kBAAkB,CAChB;EACE,0BAA0B;EAC1B,UAAU;EACV,OAAO,EACL,SAAS,UACX;CACF,GACA;EACE,0BAA0B;EAC1B,UAAU;EACV,OAAO,EACL,SAAS,QACX;CACF,CACF;AACF,CAAC,GASK,KAAkC,EAAE,aAAU,oBAAiB,kBAAe,kCAA+B;CACjH,IAAM,IAAc,MAAa,QAC3B,IAAO,IAAc,eAAe,eACpC,IAAQ,IAAc,kBAAkB,aACxC,IAAU,IAAkB,YAAY,YACxC,EAAE,YAAS,cAAW,EAAgB;EAAE;EAAU;CAAyB,CAAC;CAElF,OACE,kBAAC,QAAD;EAAM,WAAW,EAAQ;EACvB,UAAA,kBAAC,GAAD;GAAY,MAAK;GAAS,WAAW,EAAO;GAAY;GAAe;GAAM,eAAc;GAAc,UAAU;GAChH,UAAA;EACS,CAAA;CACR,CAAA;AAEV"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselArrow.js","names":[],"sources":["../../../src/components/CarouselV2/CarouselArrow.tsx"],"sourcesContent":["\"use client\";\n\nimport { BaseButton } from \"@bonprix-ds/internal-components\";\nimport React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport ThemeForcer from \"../ThemeForcer\";\n\nconst generateClasses = tv({\n slots: {\n wrapper: \"z-[1] absolute top-1/2 transform -translate-y-1/2\",\n button: \"disabled:hidden\",\n },\n variants: {\n position: {\n left: {\n wrapper: \"start-3\",\n },\n right: {\n wrapper: \"end-3\",\n },\n },\n disableHorizontalPadding: {\n true: \"\",\n false: \"\",\n },\n show: {\n always: { button: \"\" },\n hover: { button: \"hidden group-hover:block\" },\n never: { button: \"hidden\" },\n },\n },\n compoundVariants: [\n {\n disableHorizontalPadding: true,\n position: \"left\",\n class: {\n wrapper: \"start-0\",\n },\n },\n {\n disableHorizontalPadding: true,\n position: \"right\",\n class: {\n wrapper: \"end-0\",\n },\n },\n ],\n});\n\ninterface Props {\n position: \"left\" | \"right\";\n buttonsContrast: boolean;\n invertButtons: boolean;\n disableHorizontalPadding: boolean;\n onClick: () => void;\n disabled: boolean;\n show?: \"always\" | \"hover\" | \"never\";\n}\n\nconst CarouselArrow: React.FC<Props> = ({\n position,\n buttonsContrast,\n invertButtons,\n disableHorizontalPadding,\n onClick,\n disabled,\n show = \"always\",\n}) => {\n const isLeftArrow = position === \"left\" ? true : false;\n const icon = isLeftArrow ? \"arrow-left\" : \"arrow-right\";\n const label = isLeftArrow ? \"zurück\" : \"weiter\";\n const variant = buttonsContrast ? \"primary\" : \"tertiary\";\n const themeMode = invertButtons ? \"dark\" : \"light\";\n const { wrapper, button } = generateClasses({ position, disableHorizontalPadding, show });\n\n return (\n <ThemeForcer theme={themeMode}>\n <span className={wrapper()}>\n <BaseButton\n type=\"button\"\n className={button()}\n variant={variant}\n icon={icon}\n componentName=\"icon-button\"\n onClick={onClick}\n disabled={disabled}\n >\n {label}\n </BaseButton>\n </span>\n </ThemeForcer>\n );\n};\n\nexport default CarouselArrow;\n"],"mappings":";;;;;;;AAQA,IAAM,IAAkB,EAAG;CACzB,OAAO;EACL,SAAS;EACT,QAAQ;CACV;CACA,UAAU;EACR,UAAU;GACR,MAAM,EACJ,SAAS,UACX;GACA,OAAO,EACL,SAAS,QACX;EACF;EACA,0BAA0B;GACxB,MAAM;GACN,OAAO;EACT;EACA,MAAM;GACJ,QAAQ,EAAE,QAAQ,GAAG;GACrB,OAAO,EAAE,QAAQ,2BAA2B;GAC5C,OAAO,EAAE,QAAQ,SAAS;EAC5B;CACF;CACA,kBAAkB,CAChB;EACE,0BAA0B;EAC1B,UAAU;EACV,OAAO,EACL,SAAS,UACX;CACF,GACA;EACE,0BAA0B;EAC1B,UAAU;EACV,OAAO,EACL,SAAS,QACX;CACF,CACF;AACF,CAAC,GAYK,KAAkC,EACtC,aACA,oBACA,kBACA,6BACA,YACA,aACA,UAAO,eACH;CACJ,IAAM,IAAc,MAAa,QAC3B,IAAO,IAAc,eAAe,eACpC,IAAQ,IAAc,WAAW,UACjC,IAAU,IAAkB,YAAY,YACxC,IAAY,IAAgB,SAAS,SACrC,EAAE,YAAS,cAAW,EAAgB;EAAE;EAAU;EAA0B;CAAK,CAAC;CAExF,OACE,kBAAC,GAAD;EAAa,OAAO;
|
|
1
|
+
{"version":3,"file":"CarouselArrow.js","names":[],"sources":["../../../src/components/CarouselV2/CarouselArrow.tsx"],"sourcesContent":["\"use client\";\n\nimport { BaseButton } from \"@bonprix-ds/internal-components\";\nimport React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport ThemeForcer from \"../ThemeForcer\";\n\nconst generateClasses = tv({\n slots: {\n wrapper: \"z-[1] absolute top-1/2 transform -translate-y-1/2\",\n button: \"disabled:hidden\",\n },\n variants: {\n position: {\n left: {\n wrapper: \"start-3\",\n },\n right: {\n wrapper: \"end-3\",\n },\n },\n disableHorizontalPadding: {\n true: \"\",\n false: \"\",\n },\n show: {\n always: { button: \"\" },\n hover: { button: \"hidden group-hover:block\" },\n never: { button: \"hidden\" },\n },\n },\n compoundVariants: [\n {\n disableHorizontalPadding: true,\n position: \"left\",\n class: {\n wrapper: \"start-0\",\n },\n },\n {\n disableHorizontalPadding: true,\n position: \"right\",\n class: {\n wrapper: \"end-0\",\n },\n },\n ],\n});\n\ninterface Props {\n position: \"left\" | \"right\";\n buttonsContrast: boolean;\n invertButtons: boolean;\n disableHorizontalPadding: boolean;\n onClick: () => void;\n disabled: boolean;\n show?: \"always\" | \"hover\" | \"never\";\n}\n\nconst CarouselArrow: React.FC<Props> = ({\n position,\n buttonsContrast,\n invertButtons,\n disableHorizontalPadding,\n onClick,\n disabled,\n show = \"always\",\n}) => {\n const isLeftArrow = position === \"left\" ? true : false;\n const icon = isLeftArrow ? \"arrow-left\" : \"arrow-right\";\n const label = isLeftArrow ? \"zurück\" : \"weiter\";\n const variant = buttonsContrast ? \"primary\" : \"tertiary\";\n const themeMode = invertButtons ? \"dark\" : \"light\";\n const { wrapper, button } = generateClasses({ position, disableHorizontalPadding, show });\n\n return (\n <ThemeForcer theme={themeMode}>\n <span className={wrapper()}>\n <BaseButton\n type=\"button\"\n className={button()}\n variant={variant}\n icon={icon}\n componentName=\"icon-button\"\n onClick={onClick}\n disabled={disabled}\n >\n {label}\n </BaseButton>\n </span>\n </ThemeForcer>\n );\n};\n\nexport default CarouselArrow;\n"],"mappings":";;;;;;;AAQA,IAAM,IAAkB,EAAG;CACzB,OAAO;EACL,SAAS;EACT,QAAQ;CACV;CACA,UAAU;EACR,UAAU;GACR,MAAM,EACJ,SAAS,UACX;GACA,OAAO,EACL,SAAS,QACX;EACF;EACA,0BAA0B;GACxB,MAAM;GACN,OAAO;EACT;EACA,MAAM;GACJ,QAAQ,EAAE,QAAQ,GAAG;GACrB,OAAO,EAAE,QAAQ,2BAA2B;GAC5C,OAAO,EAAE,QAAQ,SAAS;EAC5B;CACF;CACA,kBAAkB,CAChB;EACE,0BAA0B;EAC1B,UAAU;EACV,OAAO,EACL,SAAS,UACX;CACF,GACA;EACE,0BAA0B;EAC1B,UAAU;EACV,OAAO,EACL,SAAS,QACX;CACF,CACF;AACF,CAAC,GAYK,KAAkC,EACtC,aACA,oBACA,kBACA,6BACA,YACA,aACA,UAAO,eACH;CACJ,IAAM,IAAc,MAAa,QAC3B,IAAO,IAAc,eAAe,eACpC,IAAQ,IAAc,WAAW,UACjC,IAAU,IAAkB,YAAY,YACxC,IAAY,IAAgB,SAAS,SACrC,EAAE,YAAS,cAAW,EAAgB;EAAE;EAAU;EAA0B;CAAK,CAAC;CAExF,OACE,kBAAC,GAAD;EAAa,OAAO;EAClB,UAAA,kBAAC,QAAD;GAAM,WAAW,EAAQ;GACvB,UAAA,kBAAC,GAAD;IACE,MAAK;IACL,WAAW,EAAO;IACT;IACH;IACN,eAAc;IACL;IACC;IAET,UAAA;GACS,CAAA;EACR,CAAA;CACK,CAAA;AAEjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CarouselV2.js","names":[],"sources":["../../../src/components/CarouselV2/CarouselV2.tsx"],"sourcesContent":["\"use client\";\n\nimport { Breakpoint } from \"@bonprix-ds/utils\";\nimport React, { FC, ReactNode, Ref, useId, useImperativeHandle, useRef, useState } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport CarouselArrow from \"./CarouselArrow\";\nimport CarouselContext from \"./carouselContext\";\nimport PositionIndicator from \"./PositionIndicator/PositionIndicator\";\nimport Slide from \"./Slide/Slide\";\nimport Slides from \"./Slides/Slides\";\nimport useCreateCarousel from \"./useCreateCarousel\";\nimport { getActiveSlide, getFirstSlideIndexOnPage } from \"./utils\";\n\nconst generateClasses = tv({\n base: \"relative min-h-8 touch-manipulation group\", // group is for arrows on hover\n slots: {\n header: \"sr-only\",\n status: \"sr-only\",\n },\n});\n\nexport type ResponsiveNumber = Partial<Record<Breakpoint, number>>;\n\ntype AccessibilityLabel =\n | {\n /** Sets an invisible header for the carousel to create a landmark. Do not use both `title` and `aria-labelledby`. */\n title: string;\n /** Defines the level of the used header element. Only applicable if using `title` instead of `aria-labelledby`. */\n titleLevel?: \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\";\n \"aria-labelledby\"?: never;\n }\n | {\n /** Use if a title already exists on the page. Do not use both `title`and `aria-labelledby`. */\n \"aria-labelledby\": string;\n title?: never;\n titleLevel?: never;\n };\n\nexport interface CarouselV2Ref {\n moveToPage: (pageNumber: number) => void;\n}\n\nexport type CarouselV2Props = AccessibilityLabel & {\n /** The content of the carousel. Here, all of the subcomponents should be placed. */\n children: ReactNode;\n /** Amount of slides that will be visible at the same time, thus building a page. */\n perPage?: number | ResponsiveNumber;\n /** Amount of slides to move per arrow icon button click. */\n perMove?: number | ResponsiveNumber;\n /** If true, the carousel will rewind to the beginning when reaching the end or going to end when going before the first slide. There must be more than two pages for this to work! Doesn't run smoothly with `padding` right now. */\n rewind?: boolean;\n /** If set to `true`, the primary variant of icon buttons will be used to achieve a high contrast. */\n buttonsContrast?: boolean;\n /** The padding at the right side of the page in pixels. Can be used to implement the so-called \"scroll hint\" */\n padding?: number;\n /** Callback function that is called when the slide changes. */\n onMove?: (destIndex: number, prevIndex: number) => void;\n /** Manages the behavior of the arrow icon buttons. */\n showArrows?: \"always\" | \"hover\" | \"never\";\n /** The gap between slides in pixels. */\n gap?: number;\n /** If set to `true`, the color of the arrow buttons will be inverted. */\n invertButtons?: boolean;\n /** If set to `true`, the horizontal padding for the arrow buttons will be removed. */\n disableHorizontalPadding?: boolean;\n /** If set to `true`, scrolling via mouse drag will be enabled just like you would expect from a mobile touch pointer. */\n simulateTouch?: boolean;\n /** The index of the initial slide to be displayed. For programmatic scrolling after initial mount, use `ref`'s `moveToPage`. */\n start?: number;\n /** A reference to the Carousel instance. You can call `moveToPage(pageNumber: number)` on this one, e.g. `carouselRef.current.moveToPage(2)`. To set an initial slide, use `start` prop instead. */\n ref?: Ref<CarouselV2Ref>;\n};\ninterface SubComponents {\n Slides: typeof Slides;\n Slide: typeof Slide;\n PositionIndicator: typeof PositionIndicator;\n}\n\nconst CarouselV2: FC<CarouselV2Props> & SubComponents = ({\n children,\n title,\n titleLevel: TitleComponent = \"h3\",\n perPage = 1,\n perMove = perPage,\n rewind = false,\n buttonsContrast = false,\n padding = 0,\n onMove,\n showArrows = \"always\",\n gap = 0,\n invertButtons = false,\n disableHorizontalPadding = false,\n simulateTouch = false,\n start,\n ref,\n ...props\n}) => {\n const options = useCreateCarousel({ rewind, perPage, perMove, padding, gap, children, simulateTouch, start });\n const headerId = useId();\n const focusManagerRef = useRef<HTMLDivElement>(null);\n const {\n listRef,\n pages,\n activePage,\n activeSlide,\n canScrollPrev,\n canScrollNext,\n onClickLeft,\n onClickRight,\n slideWidth,\n getIntersectionObserver,\n setIntersectionObserver,\n buttonTriggeredScroll,\n scrollDirection,\n finishButtonTriggeredScroll,\n slidesCount,\n currentPerPage,\n } = options;\n const { base, header, status: statusClass } = generateClasses({ showArrows });\n const [status, setStatus] = useState<string>(\"\");\n const [previousActiveSlide, setPreviousActiveSlide] = useState<number>(0);\n\n // executed on scroll end in Slides component\n const handleScrollEnd = () => {\n // When calling handleScrollEnd, `activeSlide` might be stale due to a race condition with our handleScroll callback and its throttling.\n // Therefore, we get the currentActiveSlide from the browser scroll position fresh here. Otherwise, `moveToPage` would result in wrong `onMove` callbacks.\n const currentActiveSlide = listRef.current\n ? getActiveSlide({ scrollPosition: listRef.current.scrollLeft, slidesContainer: listRef.current })\n : activeSlide;\n\n if (currentActiveSlide !== previousActiveSlide) {\n onMove?.(currentActiveSlide, previousActiveSlide);\n setPreviousActiveSlide(currentActiveSlide);\n }\n\n const activeSlideNumbers = [];\n const slides = listRef.current?.querySelectorAll(\"li[aria-roledescription='slide']\") ?? [];\n for (let i = 0; i < slides.length; i++) {\n const slide = slides[i];\n if (!slide.hasAttribute(\"inert\")) {\n activeSlideNumbers.push(i);\n }\n }\n\n if (buttonTriggeredScroll) {\n if ((scrollDirection === \"left\" && !canScrollPrev) || (scrollDirection === \"right\" && !canScrollNext))\n focusManagerRef.current?.focus();\n\n finishButtonTriggeredScroll();\n }\n\n // TODO: Set this on initial load, too. It only gets set after scrolling right now.\n // This is the only place where we use 1-indexes because it is actually read to users and more intuitive than 0-based indexes.\n let newStatus = \"\";\n if (activeSlideNumbers.length === 1) {\n newStatus = `Slide ${activeSlideNumbers[0] + 1} aus ${slidesCount}`;\n } else if (activeSlideNumbers.length > 1) {\n newStatus = `Slides ${activeSlideNumbers[0] + 1} bis ${activeSlideNumbers[activeSlideNumbers.length - 1] + 1} aus ${slidesCount}`;\n }\n setStatus(newStatus);\n };\n\n useImperativeHandle(ref, () => ({\n moveToPage(pageNumber: number) {\n if (!listRef.current || pageNumber < 0 || pageNumber >= pages || pages === 1) return;\n\n const firstSlideIndexOnPage = getFirstSlideIndexOnPage({ pageNumber, perPage: currentPerPage });\n const firstSlideOfPage = listRef.current.querySelector(`[data-index='${firstSlideIndexOnPage}']`);\n\n firstSlideOfPage?.scrollIntoView({ behavior: \"instant\", inline: \"start\" });\n },\n }));\n\n return (\n <section\n className={base()}\n data-bpds=\"carousel-v2\"\n aria-roledescription=\"carousel\"\n aria-labelledby={props[\"aria-labelledby\"] ?? headerId}\n data-bpds-per-page={perPage}\n data-bpds-per-move={perMove}\n data-bpds-rewind={rewind}\n data-bpds-buttons-contrast={buttonsContrast}\n data-bpds-show-arrows={showArrows}\n data-bpds-invert-buttons={invertButtons}\n data-bpds-disable-horizontal-padding={disableHorizontalPadding}\n data-bpds-gap={gap}\n data-bpds-padding={padding}\n >\n {!props[\"aria-labelledby\"] && (\n <TitleComponent id={headerId} className={header()}>\n {title}\n </TitleComponent>\n )}\n <div className={statusClass()} role=\"status\">\n {status}\n </div>\n <div tabIndex={-1} ref={focusManagerRef}></div>\n <CarouselArrow\n invertButtons={invertButtons}\n position=\"left\"\n buttonsContrast={buttonsContrast}\n disableHorizontalPadding={disableHorizontalPadding}\n onClick={onClickLeft}\n disabled={!canScrollPrev}\n show={showArrows}\n />\n <CarouselContext.Provider\n value={{\n perPage,\n activeSlide,\n activePage,\n pages,\n listRef,\n handleScrollEnd,\n gap,\n slideWidth,\n getIntersectionObserver,\n setIntersectionObserver,\n simulateTouch,\n }}\n >\n {children}\n </CarouselContext.Provider>\n <CarouselArrow\n invertButtons={invertButtons}\n position=\"right\"\n buttonsContrast={buttonsContrast}\n disableHorizontalPadding={disableHorizontalPadding}\n onClick={onClickRight}\n disabled={!canScrollNext}\n show={showArrows}\n />\n </section>\n );\n};\n\nCarouselV2.displayName = \"CarouselV2\";\n\nCarouselV2.Slides = Slides;\nCarouselV2.Slides.displayName = \"CarouselV2.Slides\";\n\nCarouselV2.Slide = Slide;\nCarouselV2.Slide.displayName = \"CarouselV2.Slide\";\n\nCarouselV2.PositionIndicator = PositionIndicator;\nCarouselV2.PositionIndicator.displayName = \"CarouselV2.PositionIndicator\";\n\nexport default CarouselV2;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CarouselV2.js","names":[],"sources":["../../../src/components/CarouselV2/CarouselV2.tsx"],"sourcesContent":["\"use client\";\n\nimport { Breakpoint } from \"@bonprix-ds/utils\";\nimport React, { FC, ReactNode, Ref, useId, useImperativeHandle, useRef, useState } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport CarouselArrow from \"./CarouselArrow\";\nimport CarouselContext from \"./carouselContext\";\nimport PositionIndicator from \"./PositionIndicator/PositionIndicator\";\nimport Slide from \"./Slide/Slide\";\nimport Slides from \"./Slides/Slides\";\nimport useCreateCarousel from \"./useCreateCarousel\";\nimport { getActiveSlide, getFirstSlideIndexOnPage } from \"./utils\";\n\nconst generateClasses = tv({\n base: \"relative min-h-8 touch-manipulation group\", // group is for arrows on hover\n slots: {\n header: \"sr-only\",\n status: \"sr-only\",\n },\n});\n\nexport type ResponsiveNumber = Partial<Record<Breakpoint, number>>;\n\ntype AccessibilityLabel =\n | {\n /** Sets an invisible header for the carousel to create a landmark. Do not use both `title` and `aria-labelledby`. */\n title: string;\n /** Defines the level of the used header element. Only applicable if using `title` instead of `aria-labelledby`. */\n titleLevel?: \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\";\n \"aria-labelledby\"?: never;\n }\n | {\n /** Use if a title already exists on the page. Do not use both `title`and `aria-labelledby`. */\n \"aria-labelledby\": string;\n title?: never;\n titleLevel?: never;\n };\n\nexport interface CarouselV2Ref {\n moveToPage: (pageNumber: number) => void;\n}\n\nexport type CarouselV2Props = AccessibilityLabel & {\n /** The content of the carousel. Here, all of the subcomponents should be placed. */\n children: ReactNode;\n /** Amount of slides that will be visible at the same time, thus building a page. */\n perPage?: number | ResponsiveNumber;\n /** Amount of slides to move per arrow icon button click. */\n perMove?: number | ResponsiveNumber;\n /** If true, the carousel will rewind to the beginning when reaching the end or going to end when going before the first slide. There must be more than two pages for this to work! Doesn't run smoothly with `padding` right now. */\n rewind?: boolean;\n /** If set to `true`, the primary variant of icon buttons will be used to achieve a high contrast. */\n buttonsContrast?: boolean;\n /** The padding at the right side of the page in pixels. Can be used to implement the so-called \"scroll hint\" */\n padding?: number;\n /** Callback function that is called when the slide changes. */\n onMove?: (destIndex: number, prevIndex: number) => void;\n /** Manages the behavior of the arrow icon buttons. */\n showArrows?: \"always\" | \"hover\" | \"never\";\n /** The gap between slides in pixels. */\n gap?: number;\n /** If set to `true`, the color of the arrow buttons will be inverted. */\n invertButtons?: boolean;\n /** If set to `true`, the horizontal padding for the arrow buttons will be removed. */\n disableHorizontalPadding?: boolean;\n /** If set to `true`, scrolling via mouse drag will be enabled just like you would expect from a mobile touch pointer. */\n simulateTouch?: boolean;\n /** The index of the initial slide to be displayed. For programmatic scrolling after initial mount, use `ref`'s `moveToPage`. */\n start?: number;\n /** A reference to the Carousel instance. You can call `moveToPage(pageNumber: number)` on this one, e.g. `carouselRef.current.moveToPage(2)`. To set an initial slide, use `start` prop instead. */\n ref?: Ref<CarouselV2Ref>;\n};\ninterface SubComponents {\n Slides: typeof Slides;\n Slide: typeof Slide;\n PositionIndicator: typeof PositionIndicator;\n}\n\nconst CarouselV2: FC<CarouselV2Props> & SubComponents = ({\n children,\n title,\n titleLevel: TitleComponent = \"h3\",\n perPage = 1,\n perMove = perPage,\n rewind = false,\n buttonsContrast = false,\n padding = 0,\n onMove,\n showArrows = \"always\",\n gap = 0,\n invertButtons = false,\n disableHorizontalPadding = false,\n simulateTouch = false,\n start,\n ref,\n ...props\n}) => {\n const options = useCreateCarousel({ rewind, perPage, perMove, padding, gap, children, simulateTouch, start });\n const headerId = useId();\n const focusManagerRef = useRef<HTMLDivElement>(null);\n const {\n listRef,\n pages,\n activePage,\n activeSlide,\n canScrollPrev,\n canScrollNext,\n onClickLeft,\n onClickRight,\n slideWidth,\n getIntersectionObserver,\n setIntersectionObserver,\n buttonTriggeredScroll,\n scrollDirection,\n finishButtonTriggeredScroll,\n slidesCount,\n currentPerPage,\n } = options;\n const { base, header, status: statusClass } = generateClasses({ showArrows });\n const [status, setStatus] = useState<string>(\"\");\n const [previousActiveSlide, setPreviousActiveSlide] = useState<number>(0);\n\n // executed on scroll end in Slides component\n const handleScrollEnd = () => {\n // When calling handleScrollEnd, `activeSlide` might be stale due to a race condition with our handleScroll callback and its throttling.\n // Therefore, we get the currentActiveSlide from the browser scroll position fresh here. Otherwise, `moveToPage` would result in wrong `onMove` callbacks.\n const currentActiveSlide = listRef.current\n ? getActiveSlide({ scrollPosition: listRef.current.scrollLeft, slidesContainer: listRef.current })\n : activeSlide;\n\n if (currentActiveSlide !== previousActiveSlide) {\n onMove?.(currentActiveSlide, previousActiveSlide);\n setPreviousActiveSlide(currentActiveSlide);\n }\n\n const activeSlideNumbers = [];\n const slides = listRef.current?.querySelectorAll(\"li[aria-roledescription='slide']\") ?? [];\n for (let i = 0; i < slides.length; i++) {\n const slide = slides[i];\n if (!slide.hasAttribute(\"inert\")) {\n activeSlideNumbers.push(i);\n }\n }\n\n if (buttonTriggeredScroll) {\n if ((scrollDirection === \"left\" && !canScrollPrev) || (scrollDirection === \"right\" && !canScrollNext))\n focusManagerRef.current?.focus();\n\n finishButtonTriggeredScroll();\n }\n\n // TODO: Set this on initial load, too. It only gets set after scrolling right now.\n // This is the only place where we use 1-indexes because it is actually read to users and more intuitive than 0-based indexes.\n let newStatus = \"\";\n if (activeSlideNumbers.length === 1) {\n newStatus = `Slide ${activeSlideNumbers[0] + 1} aus ${slidesCount}`;\n } else if (activeSlideNumbers.length > 1) {\n newStatus = `Slides ${activeSlideNumbers[0] + 1} bis ${activeSlideNumbers[activeSlideNumbers.length - 1] + 1} aus ${slidesCount}`;\n }\n setStatus(newStatus);\n };\n\n useImperativeHandle(ref, () => ({\n moveToPage(pageNumber: number) {\n if (!listRef.current || pageNumber < 0 || pageNumber >= pages || pages === 1) return;\n\n const firstSlideIndexOnPage = getFirstSlideIndexOnPage({ pageNumber, perPage: currentPerPage });\n const firstSlideOfPage = listRef.current.querySelector(`[data-index='${firstSlideIndexOnPage}']`);\n\n firstSlideOfPage?.scrollIntoView({ behavior: \"instant\", inline: \"start\" });\n },\n }));\n\n return (\n <section\n className={base()}\n data-bpds=\"carousel-v2\"\n aria-roledescription=\"carousel\"\n aria-labelledby={props[\"aria-labelledby\"] ?? headerId}\n data-bpds-per-page={perPage}\n data-bpds-per-move={perMove}\n data-bpds-rewind={rewind}\n data-bpds-buttons-contrast={buttonsContrast}\n data-bpds-show-arrows={showArrows}\n data-bpds-invert-buttons={invertButtons}\n data-bpds-disable-horizontal-padding={disableHorizontalPadding}\n data-bpds-gap={gap}\n data-bpds-padding={padding}\n >\n {!props[\"aria-labelledby\"] && (\n <TitleComponent id={headerId} className={header()}>\n {title}\n </TitleComponent>\n )}\n <div className={statusClass()} role=\"status\">\n {status}\n </div>\n <div tabIndex={-1} ref={focusManagerRef}></div>\n <CarouselArrow\n invertButtons={invertButtons}\n position=\"left\"\n buttonsContrast={buttonsContrast}\n disableHorizontalPadding={disableHorizontalPadding}\n onClick={onClickLeft}\n disabled={!canScrollPrev}\n show={showArrows}\n />\n <CarouselContext.Provider\n value={{\n perPage,\n activeSlide,\n activePage,\n pages,\n listRef,\n handleScrollEnd,\n gap,\n slideWidth,\n getIntersectionObserver,\n setIntersectionObserver,\n simulateTouch,\n }}\n >\n {children}\n </CarouselContext.Provider>\n <CarouselArrow\n invertButtons={invertButtons}\n position=\"right\"\n buttonsContrast={buttonsContrast}\n disableHorizontalPadding={disableHorizontalPadding}\n onClick={onClickRight}\n disabled={!canScrollNext}\n show={showArrows}\n />\n </section>\n );\n};\n\nCarouselV2.displayName = \"CarouselV2\";\n\nCarouselV2.Slides = Slides;\nCarouselV2.Slides.displayName = \"CarouselV2.Slides\";\n\nCarouselV2.Slide = Slide;\nCarouselV2.Slide.displayName = \"CarouselV2.Slide\";\n\nCarouselV2.PositionIndicator = PositionIndicator;\nCarouselV2.PositionIndicator.displayName = \"CarouselV2.PositionIndicator\";\n\nexport default CarouselV2;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PositionIndicator.js","names":[],"sources":["../../../../src/components/CarouselV2/PositionIndicator/PositionIndicator.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { FC, Ref } from \"react\";\n\nimport useConsumeCarousel from \"../useConsumeCarousel\";\n\ninterface PositionIndicatorProps {\n /** Ref to the element */\n ref?: Ref<HTMLDivElement>;\n}\n\nconst PositionIndicator: FC<PositionIndicatorProps> = ({ ref }) => {\n const { activePage, pages } = useConsumeCarousel();\n const getPageClasses = (pageNumber: number): string => {\n return activePage === pageNumber ? \"bg-clr-primary w-3 h-1\" : \"bg-clr-on-bg-low w-3 h-0.25\";\n };\n const indicators = [];\n for (let i = 0; i < pages; i++) {\n indicators.push(<div className={getPageClasses(i)} key={i}></div>);\n }\n return (\n <div className=\"flex items-center gap-1 absolute bottom-4 start-1/2 -translate-x-1/2 min-h-1\" ref={ref}>\n {indicators}\n </div>\n );\n};\n\nexport default PositionIndicator;\n"],"mappings":";;;;;AAWA,IAAM,KAAiD,EAAE,aAAU;CACjE,IAAM,EAAE,eAAY,aAAU,EAAmB,GAC3C,KAAkB,MACf,MAAe,IAAa,2BAA2B,+BAE1D,IAAa,CAAC;CACpB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KACzB,EAAW,KAAK,kBAAC,OAAD,EAAK,WAAW,EAAe,CAAC,EAAgB,GAAR,CAAQ,CAAC;CAEnE,OACE,kBAAC,OAAD;EAAK,WAAU;EAAoF;
|
|
1
|
+
{"version":3,"file":"PositionIndicator.js","names":[],"sources":["../../../../src/components/CarouselV2/PositionIndicator/PositionIndicator.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { FC, Ref } from \"react\";\n\nimport useConsumeCarousel from \"../useConsumeCarousel\";\n\ninterface PositionIndicatorProps {\n /** Ref to the element */\n ref?: Ref<HTMLDivElement>;\n}\n\nconst PositionIndicator: FC<PositionIndicatorProps> = ({ ref }) => {\n const { activePage, pages } = useConsumeCarousel();\n const getPageClasses = (pageNumber: number): string => {\n return activePage === pageNumber ? \"bg-clr-primary w-3 h-1\" : \"bg-clr-on-bg-low w-3 h-0.25\";\n };\n const indicators = [];\n for (let i = 0; i < pages; i++) {\n indicators.push(<div className={getPageClasses(i)} key={i}></div>);\n }\n return (\n <div className=\"flex items-center gap-1 absolute bottom-4 start-1/2 -translate-x-1/2 min-h-1\" ref={ref}>\n {indicators}\n </div>\n );\n};\n\nexport default PositionIndicator;\n"],"mappings":";;;;;AAWA,IAAM,KAAiD,EAAE,aAAU;CACjE,IAAM,EAAE,eAAY,aAAU,EAAmB,GAC3C,KAAkB,MACf,MAAe,IAAa,2BAA2B,+BAE1D,IAAa,CAAC;CACpB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAO,KACzB,EAAW,KAAK,kBAAC,OAAD,EAAK,WAAW,EAAe,CAAC,EAAgB,GAAR,CAAQ,CAAC;CAEnE,OACE,kBAAC,OAAD;EAAK,WAAU;EAAoF;EAChG,UAAA;CACE,CAAA;AAET"}
|
|
@@ -4,47 +4,47 @@ import { getActivePage as n, getActiveSlide as r, getBreakpoint as i, getCanScro
|
|
|
4
4
|
import { useCallback as f, useEffect as p, useMemo as m, useRef as h, useState as g } from "react";
|
|
5
5
|
import _ from "lodash.throttle";
|
|
6
6
|
//#region src/components/CarouselV2/useCreateCarousel.ts
|
|
7
|
-
var v = ({ perPage: v = 1, perMove:
|
|
8
|
-
let C = h(null),
|
|
7
|
+
var v = ({ perPage: v = 1, perMove: y = v, rewind: b = !1, padding: x = 0, gap: S = 0, children: ne, simulateTouch: re = !1, start: ie }) => {
|
|
8
|
+
let C = h(null), w = typeof document < "u" ? document.documentElement.clientWidth : 0, [T, E] = g(w), [D, ae] = g(0), [O, oe] = g(0), [k, se] = g(0), [A, j] = g(!1), [M, N] = g(!0), [P, F] = g(!1), [I, L] = g(null), [R, z] = g(0), B = () => {
|
|
9
9
|
F(!1), L(null);
|
|
10
10
|
}, V = h(null), H = f(() => V.current, []), U = f((e) => {
|
|
11
11
|
V.current = e;
|
|
12
|
-
}, []), W = i({ viewportWidth:
|
|
12
|
+
}, []), W = i({ viewportWidth: T }), G = s({
|
|
13
13
|
perPage: v,
|
|
14
14
|
breakpoint: W
|
|
15
15
|
}), K = ee({
|
|
16
|
-
perMove:
|
|
16
|
+
perMove: y,
|
|
17
17
|
breakpoint: W
|
|
18
|
-
}) / G,
|
|
18
|
+
}) / G, ce = u({
|
|
19
19
|
perPage: G,
|
|
20
|
-
padding:
|
|
21
|
-
gap:
|
|
20
|
+
padding: x,
|
|
21
|
+
gap: S
|
|
22
22
|
}), q = m(() => c({
|
|
23
23
|
slidesCount: R,
|
|
24
24
|
currentPerPage: G
|
|
25
|
-
}), [R, G]), J = m(() => q < 3, [q]), [Y,
|
|
25
|
+
}), [R, G]), J = m(() => q < 3, [q]), [Y, le] = g(0), ue = n({
|
|
26
26
|
activeSlide: Y,
|
|
27
27
|
currentPerPage: G,
|
|
28
28
|
slidesCount: R,
|
|
29
29
|
pages: q,
|
|
30
|
-
rewind:
|
|
30
|
+
rewind: b
|
|
31
31
|
}), X = l({
|
|
32
32
|
scrollPosition: k,
|
|
33
|
-
scrollPortWidth:
|
|
34
|
-
scrollContainerWidth:
|
|
35
|
-
rewind:
|
|
33
|
+
scrollPortWidth: O,
|
|
34
|
+
scrollContainerWidth: D,
|
|
35
|
+
rewind: b,
|
|
36
36
|
distanceMultiplier: K
|
|
37
37
|
}), Z = te({
|
|
38
38
|
scrollPosition: k,
|
|
39
|
-
scrollPortWidth:
|
|
40
|
-
scrollContainerWidth:
|
|
41
|
-
rewind:
|
|
39
|
+
scrollPortWidth: O,
|
|
40
|
+
scrollContainerWidth: D,
|
|
41
|
+
rewind: b,
|
|
42
42
|
distanceMultiplier: K
|
|
43
43
|
});
|
|
44
44
|
p(() => {
|
|
45
45
|
let e = C.current;
|
|
46
46
|
e && Array.from(e.children).forEach((e, t) => e.dataset.index ??= t.toString());
|
|
47
|
-
}, [
|
|
47
|
+
}, [ne]);
|
|
48
48
|
let Q = f((e) => {
|
|
49
49
|
let t = e.scrollWidth, n = e.scrollLeft, r = e.offsetWidth, i = Array.from(e.children);
|
|
50
50
|
J || !r || !t || (d(n, 0) && requestAnimationFrame(() => {
|
|
@@ -54,7 +54,7 @@ var v = ({ perPage: v = 1, perMove: ne = v, rewind: y = !1, padding: b = 0, gap:
|
|
|
54
54
|
}));
|
|
55
55
|
}, [G, J]), $ = h(void 0);
|
|
56
56
|
return p(() => {
|
|
57
|
-
if (!
|
|
57
|
+
if (!b) return;
|
|
58
58
|
let e = C.current;
|
|
59
59
|
if (!e) return;
|
|
60
60
|
let t = () => {
|
|
@@ -63,12 +63,12 @@ var v = ({ perPage: v = 1, perMove: ne = v, rewind: y = !1, padding: b = 0, gap:
|
|
|
63
63
|
return e.addEventListener("scroll", t), () => {
|
|
64
64
|
$.current && clearTimeout($.current), e.removeEventListener("scroll", t);
|
|
65
65
|
};
|
|
66
|
-
}, [
|
|
66
|
+
}, [b, Q]), p(() => {
|
|
67
67
|
let e = C.current;
|
|
68
68
|
if (!e) return;
|
|
69
69
|
let t = new ResizeObserver(([{ target: t }]) => {
|
|
70
70
|
let n = t.getBoundingClientRect().width, r = t.scrollWidth;
|
|
71
|
-
|
|
71
|
+
oe(n), ae(r), b && Q(e);
|
|
72
72
|
});
|
|
73
73
|
return t.observe(e), () => {
|
|
74
74
|
t.disconnect();
|
|
@@ -76,7 +76,7 @@ var v = ({ perPage: v = 1, perMove: ne = v, rewind: y = !1, padding: b = 0, gap:
|
|
|
76
76
|
}, [
|
|
77
77
|
G,
|
|
78
78
|
Q,
|
|
79
|
-
|
|
79
|
+
b,
|
|
80
80
|
R
|
|
81
81
|
]), p(() => {
|
|
82
82
|
if (!C.current) return;
|
|
@@ -84,14 +84,14 @@ var v = ({ perPage: v = 1, perMove: ne = v, rewind: y = !1, padding: b = 0, gap:
|
|
|
84
84
|
z(e);
|
|
85
85
|
let t = () => {
|
|
86
86
|
let e = document.documentElement.clientWidth;
|
|
87
|
-
|
|
87
|
+
E(e);
|
|
88
88
|
}, n = (e) => {
|
|
89
89
|
if (!e.target) return;
|
|
90
90
|
let t = e.target, n = t.scrollLeft, i = r({
|
|
91
91
|
scrollPosition: n,
|
|
92
92
|
slidesContainer: t
|
|
93
93
|
});
|
|
94
|
-
|
|
94
|
+
se(n), le(i);
|
|
95
95
|
}, i = _(t, 200, { trailing: !0 }), a = _(n, 200, { trailing: !0 });
|
|
96
96
|
window.addEventListener("resize", i);
|
|
97
97
|
let o = C.current;
|
|
@@ -109,25 +109,25 @@ var v = ({ perPage: v = 1, perMove: ne = v, rewind: y = !1, padding: b = 0, gap:
|
|
|
109
109
|
if (C.current) {
|
|
110
110
|
let e = o({
|
|
111
111
|
scrollPosition: k,
|
|
112
|
-
rewind:
|
|
112
|
+
rewind: b,
|
|
113
113
|
forceDisableRewind: J
|
|
114
114
|
}), t = a({
|
|
115
115
|
scrollPosition: k,
|
|
116
|
-
scrollPortWidth:
|
|
117
|
-
scrollContainerWidth:
|
|
118
|
-
rewind:
|
|
116
|
+
scrollPortWidth: O,
|
|
117
|
+
scrollContainerWidth: D,
|
|
118
|
+
rewind: b,
|
|
119
119
|
forceDisableRewind: J
|
|
120
120
|
});
|
|
121
121
|
j(e), N(t);
|
|
122
122
|
}
|
|
123
123
|
}, [
|
|
124
|
-
|
|
124
|
+
b,
|
|
125
125
|
k,
|
|
126
|
+
O,
|
|
126
127
|
D,
|
|
127
|
-
E,
|
|
128
128
|
J
|
|
129
129
|
]), {
|
|
130
|
-
activePage:
|
|
130
|
+
activePage: ue,
|
|
131
131
|
activeSlide: Y,
|
|
132
132
|
pages: q,
|
|
133
133
|
listRef: C,
|
|
@@ -145,7 +145,7 @@ var v = ({ perPage: v = 1, perMove: ne = v, rewind: y = !1, padding: b = 0, gap:
|
|
|
145
145
|
behavior: "smooth"
|
|
146
146
|
}), F(!0), L("right"));
|
|
147
147
|
}, [M, Z]),
|
|
148
|
-
slideWidth:
|
|
148
|
+
slideWidth: ce,
|
|
149
149
|
getIntersectionObserver: H,
|
|
150
150
|
setIntersectionObserver: U,
|
|
151
151
|
buttonTriggeredScroll: P,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCreateCarousel.js","names":[],"sources":["../../../src/components/CarouselV2/useCreateCarousel.ts"],"sourcesContent":["import throttle from \"lodash.throttle\";\nimport { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport type { ResponsiveNumber } from \"./CarouselV2\";\nimport useSimulateTouch from \"./useSimulateTouch\";\nimport useStart from \"./useStart\";\nimport {\n getActivePage,\n getActiveSlide,\n getBreakpoint,\n getCanScrollNext,\n getCanScrollPrev,\n getCurrentPerMove,\n getCurrentPerPage,\n getPages,\n getScrollDistanceNext,\n getScrollDistancePrev,\n getSlideWidthStyle,\n roughlyEqual,\n} from \"./utils\";\n\ninterface UseCarouselProps {\n perPage?: number | ResponsiveNumber;\n perMove?: number | ResponsiveNumber;\n rewind?: boolean;\n gap?: number;\n padding?: number;\n children?: ReactNode;\n simulateTouch?: boolean;\n start?: number;\n}\n\nconst useCreateCarousel = ({\n perPage = 1,\n perMove = perPage,\n rewind = false,\n padding = 0,\n gap = 0,\n children,\n simulateTouch = false,\n start,\n}: UseCarouselProps) => {\n ////// STATE //////\n const listRef = useRef<HTMLUListElement>(null);\n\n const initialViewportWidth = typeof document !== \"undefined\" ? document.documentElement.clientWidth : 0;\n const [viewportWidth, setViewportWidth] = useState(initialViewportWidth);\n\n /** The overall width of the scroll container (also the overflowed part).\n * It's dynamic, because the slides are growing and shrinking according to the viewport width! */\n const [scrollContainerWidth, setScrollContainerWidth] = useState(0);\n // The width that is available for the slides. https://developer.mozilla.org/en-US/docs/Glossary/Scroll_container.\n const [scrollPortWidth, setScrollPortWidth] = useState(0);\n /** Position within the scroll container, measured from the left corner. Equals to \"scrollLeft\". */\n const [scrollPosition, setScrollPosition] = useState(0);\n const [canScrollPrev, setCanScrollPrev] = useState(false);\n const [canScrollNext, setCanScrollNext] = useState(true);\n /** If `true`, the carousel is scrolled with help of one of the arrow icon buttons. */\n const [buttonTriggeredScroll, setButtonTriggeredScroll] = useState(false);\n /** If not null, it indicates the direction of the button-triggered scroll. */\n const [scrollDirection, setScrollDirection] = useState<\"left\" | \"right\" | null>(null);\n\n const [slidesCount, setSlidesCount] = useState(0);\n\n const finishButtonTriggeredScroll = () => {\n setButtonTriggeredScroll(false);\n setScrollDirection(null);\n };\n\n const observerRef = useRef<IntersectionObserver | null>(null);\n const getIntersectionObserver = useCallback(() => observerRef.current, []);\n const setIntersectionObserver = useCallback((observer: IntersectionObserver | null) => {\n observerRef.current = observer;\n }, []);\n\n ////// DERIVED STATE //////\n\n const breakpoint = getBreakpoint({ viewportWidth });\n const currentPerPage = getCurrentPerPage({ perPage, breakpoint });\n const currentPerMove = getCurrentPerMove({ perMove, breakpoint });\n const distanceMultiplier = currentPerMove / currentPerPage;\n const slideWidth = getSlideWidthStyle({ perPage: currentPerPage, padding, gap });\n\n /** Overall amount of pages in the carousel. a page can hold one or multiple slides. */\n const pages = useMemo(() => getPages({ slidesCount, currentPerPage }), [slidesCount, currentPerPage]);\n\n // Disable rewind if there are less than 3 pages to avoid infinite prepending/appending loop\n const forceDisableRewind = useMemo(() => pages < 3, [pages]);\n\n /** Currently active slide */\n const [activeSlide, setActiveSlide] = useState(0);\n\n /** Currently active page, derived from activeSlide */\n const activePage = getActivePage({\n activeSlide,\n currentPerPage,\n slidesCount,\n pages,\n rewind,\n });\n\n /** Scroll distance is the amount in px the scroll port will be moved either to left or right. */\n const scrollDistancePrev = getScrollDistancePrev({ scrollPosition, scrollPortWidth, scrollContainerWidth, rewind, distanceMultiplier });\n const scrollDistanceNext = getScrollDistanceNext({\n scrollPosition,\n scrollPortWidth,\n scrollContainerWidth,\n rewind,\n distanceMultiplier,\n });\n\n ////// EFFECTS //////\n\n useEffect(() => {\n const slidesRef = listRef.current;\n if (!slidesRef) return;\n\n const items = Array.from(slidesRef.children) as HTMLLIElement[];\n\n // Add index to each slide item to figure out the current slide and page later on.\n // This effect runs when re-rendering children, so also when context changes due to resizing.\n // We need to ensure the item ids stay the same even in that case, so we only apply indexes if we don't have them already.\n items.forEach((item, i) => (item.dataset.index ??= i.toString()));\n }, [children]);\n\n // inspired by `updateSort` from here: https://codepen.io/scottjehl/pen/jOEzYWw\n const rearrangeSlides = useCallback(\n (el: HTMLUListElement) => {\n const scrollWidth = el.scrollWidth;\n const scrollLeft = el.scrollLeft;\n const width = el.offsetWidth;\n const items = Array.from(el.children);\n\n if (forceDisableRewind) return;\n\n // When teleported, width and scrollWidth might be 0 temporarily,\n // so we don't rearrange in that case to not mess up item order.\n if (!width || !scrollWidth) return;\n\n if (roughlyEqual(scrollLeft, 0)) {\n requestAnimationFrame(() => {\n const itemsToPrepend = items.slice(-currentPerPage).reverse();\n itemsToPrepend.forEach((item) => el.prepend(item));\n el.scrollLeft = scrollLeft + width;\n });\n }\n // roughly right edge\n if (roughlyEqual(scrollWidth - scrollLeft, width)) {\n requestAnimationFrame(() => {\n const itemsToAppend = items.slice(0, currentPerPage);\n itemsToAppend.forEach((item) => el.append(item));\n el.scrollLeft = scrollLeft - width;\n });\n }\n },\n [currentPerPage, forceDisableRewind],\n );\n\n const rearrangeSlidesTimeout = useRef<NodeJS.Timeout | undefined>(undefined);\n useEffect(() => {\n if (!rewind) return;\n\n const slidesRef = listRef.current;\n if (!slidesRef) return;\n\n const callRearrangeSlides = () => {\n if (rearrangeSlidesTimeout) clearTimeout(rearrangeSlidesTimeout.current);\n rearrangeSlidesTimeout.current = setTimeout(() => rearrangeSlides(slidesRef), 50);\n };\n\n slidesRef.addEventListener(\"scroll\", callRearrangeSlides);\n\n return () => {\n if (rearrangeSlidesTimeout.current) clearTimeout(rearrangeSlidesTimeout.current);\n slidesRef.removeEventListener(\"scroll\", callRearrangeSlides);\n };\n }, [rewind, rearrangeSlides]);\n\n useEffect(() => {\n const slidesRef = listRef.current;\n if (!slidesRef) return;\n\n const resizeObserver = new ResizeObserver(([{ target }]) => {\n // When teleporting, `scrollPortWidth`, `scrollContainerWidth` and `pages` are temporarily 0,\n // so we need to check once dimensions have stabilized.\n const newScrollPortWidth = target.getBoundingClientRect().width;\n const newScrollContainerWidth = target.scrollWidth;\n\n setScrollPortWidth(newScrollPortWidth);\n setScrollContainerWidth(newScrollContainerWidth);\n\n // This gets called on initial mount, but also after teleporting which is what we need in order\n // to fix a bug where you can't rewind from first to last page when clicking the prev button.\n if (rewind) rearrangeSlides(slidesRef);\n });\n\n resizeObserver.observe(slidesRef);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [currentPerPage, rearrangeSlides, rewind, slidesCount]);\n\n useEffect(() => {\n if (!listRef.current) return;\n\n const _slidesCount = listRef.current.querySelectorAll(\"li[aria-roledescription='slide']\").length;\n setSlidesCount(_slidesCount);\n\n const handleResize = () => {\n const newViewportWidth = document.documentElement.clientWidth;\n setViewportWidth(newViewportWidth);\n };\n\n const handleScroll = (event: Event) => {\n if (!event.target) return;\n\n const slidesContainer = event.target as HTMLUListElement;\n\n const newScrollPosition = slidesContainer.scrollLeft;\n const newActiveSlide = getActiveSlide({ scrollPosition: newScrollPosition, slidesContainer });\n\n setScrollPosition(newScrollPosition);\n setActiveSlide(newActiveSlide);\n };\n\n const throttledHandleResize = throttle(handleResize, 200, { trailing: true });\n const throttledHandleScroll = throttle(handleScroll, 200, { trailing: true });\n\n window.addEventListener(\"resize\", throttledHandleResize);\n const slidesRef = listRef.current;\n slidesRef.addEventListener(\"scroll\", throttledHandleScroll);\n\n return () => {\n window.removeEventListener(\"resize\", throttledHandleResize);\n slidesRef.removeEventListener(\"scroll\", throttledHandleScroll);\n };\n }, []);\n\n useSimulateTouch({ simulateTouch, listRef });\n useStart({ start, slidesCount, listRef });\n\n /////////////////////\n\n useEffect(() => {\n if (listRef.current) {\n const _canScrollLeft = getCanScrollPrev({ scrollPosition, rewind, forceDisableRewind });\n const _canScrollNext = getCanScrollNext({ scrollPosition, scrollPortWidth, scrollContainerWidth, rewind, forceDisableRewind });\n setCanScrollPrev(_canScrollLeft);\n setCanScrollNext(_canScrollNext);\n }\n }, [rewind, scrollPosition, scrollPortWidth, scrollContainerWidth, forceDisableRewind]);\n\n ////// CALLBACKS //////\n\n const onClickLeft = useCallback(() => {\n if (!listRef.current || !canScrollPrev) return;\n listRef.current.scrollBy({ left: -scrollDistancePrev, behavior: \"smooth\" });\n setButtonTriggeredScroll(true);\n setScrollDirection(\"left\");\n }, [canScrollPrev, scrollDistancePrev]);\n\n const onClickRight = useCallback(() => {\n if (!listRef.current || !canScrollNext) return;\n listRef.current.scrollBy({ left: scrollDistanceNext, behavior: \"smooth\" });\n setButtonTriggeredScroll(true);\n setScrollDirection(\"right\");\n }, [canScrollNext, scrollDistanceNext]);\n\n return {\n activePage,\n activeSlide,\n pages,\n listRef,\n canScrollPrev,\n canScrollNext,\n onClickLeft,\n onClickRight,\n slideWidth,\n getIntersectionObserver,\n setIntersectionObserver,\n buttonTriggeredScroll,\n finishButtonTriggeredScroll,\n scrollDirection,\n slidesCount,\n currentPerPage,\n };\n};\n\nexport default useCreateCarousel;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useCreateCarousel.js","names":[],"sources":["../../../src/components/CarouselV2/useCreateCarousel.ts"],"sourcesContent":["import throttle from \"lodash.throttle\";\nimport { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\nimport type { ResponsiveNumber } from \"./CarouselV2\";\nimport useSimulateTouch from \"./useSimulateTouch\";\nimport useStart from \"./useStart\";\nimport {\n getActivePage,\n getActiveSlide,\n getBreakpoint,\n getCanScrollNext,\n getCanScrollPrev,\n getCurrentPerMove,\n getCurrentPerPage,\n getPages,\n getScrollDistanceNext,\n getScrollDistancePrev,\n getSlideWidthStyle,\n roughlyEqual,\n} from \"./utils\";\n\ninterface UseCarouselProps {\n perPage?: number | ResponsiveNumber;\n perMove?: number | ResponsiveNumber;\n rewind?: boolean;\n gap?: number;\n padding?: number;\n children?: ReactNode;\n simulateTouch?: boolean;\n start?: number;\n}\n\nconst useCreateCarousel = ({\n perPage = 1,\n perMove = perPage,\n rewind = false,\n padding = 0,\n gap = 0,\n children,\n simulateTouch = false,\n start,\n}: UseCarouselProps) => {\n ////// STATE //////\n const listRef = useRef<HTMLUListElement>(null);\n\n const initialViewportWidth = typeof document !== \"undefined\" ? document.documentElement.clientWidth : 0;\n const [viewportWidth, setViewportWidth] = useState(initialViewportWidth);\n\n /** The overall width of the scroll container (also the overflowed part).\n * It's dynamic, because the slides are growing and shrinking according to the viewport width! */\n const [scrollContainerWidth, setScrollContainerWidth] = useState(0);\n // The width that is available for the slides. https://developer.mozilla.org/en-US/docs/Glossary/Scroll_container.\n const [scrollPortWidth, setScrollPortWidth] = useState(0);\n /** Position within the scroll container, measured from the left corner. Equals to \"scrollLeft\". */\n const [scrollPosition, setScrollPosition] = useState(0);\n const [canScrollPrev, setCanScrollPrev] = useState(false);\n const [canScrollNext, setCanScrollNext] = useState(true);\n /** If `true`, the carousel is scrolled with help of one of the arrow icon buttons. */\n const [buttonTriggeredScroll, setButtonTriggeredScroll] = useState(false);\n /** If not null, it indicates the direction of the button-triggered scroll. */\n const [scrollDirection, setScrollDirection] = useState<\"left\" | \"right\" | null>(null);\n\n const [slidesCount, setSlidesCount] = useState(0);\n\n const finishButtonTriggeredScroll = () => {\n setButtonTriggeredScroll(false);\n setScrollDirection(null);\n };\n\n const observerRef = useRef<IntersectionObserver | null>(null);\n const getIntersectionObserver = useCallback(() => observerRef.current, []);\n const setIntersectionObserver = useCallback((observer: IntersectionObserver | null) => {\n observerRef.current = observer;\n }, []);\n\n ////// DERIVED STATE //////\n\n const breakpoint = getBreakpoint({ viewportWidth });\n const currentPerPage = getCurrentPerPage({ perPage, breakpoint });\n const currentPerMove = getCurrentPerMove({ perMove, breakpoint });\n const distanceMultiplier = currentPerMove / currentPerPage;\n const slideWidth = getSlideWidthStyle({ perPage: currentPerPage, padding, gap });\n\n /** Overall amount of pages in the carousel. a page can hold one or multiple slides. */\n const pages = useMemo(() => getPages({ slidesCount, currentPerPage }), [slidesCount, currentPerPage]);\n\n // Disable rewind if there are less than 3 pages to avoid infinite prepending/appending loop\n const forceDisableRewind = useMemo(() => pages < 3, [pages]);\n\n /** Currently active slide */\n const [activeSlide, setActiveSlide] = useState(0);\n\n /** Currently active page, derived from activeSlide */\n const activePage = getActivePage({\n activeSlide,\n currentPerPage,\n slidesCount,\n pages,\n rewind,\n });\n\n /** Scroll distance is the amount in px the scroll port will be moved either to left or right. */\n const scrollDistancePrev = getScrollDistancePrev({ scrollPosition, scrollPortWidth, scrollContainerWidth, rewind, distanceMultiplier });\n const scrollDistanceNext = getScrollDistanceNext({\n scrollPosition,\n scrollPortWidth,\n scrollContainerWidth,\n rewind,\n distanceMultiplier,\n });\n\n ////// EFFECTS //////\n\n useEffect(() => {\n const slidesRef = listRef.current;\n if (!slidesRef) return;\n\n const items = Array.from(slidesRef.children) as HTMLLIElement[];\n\n // Add index to each slide item to figure out the current slide and page later on.\n // This effect runs when re-rendering children, so also when context changes due to resizing.\n // We need to ensure the item ids stay the same even in that case, so we only apply indexes if we don't have them already.\n items.forEach((item, i) => (item.dataset.index ??= i.toString()));\n }, [children]);\n\n // inspired by `updateSort` from here: https://codepen.io/scottjehl/pen/jOEzYWw\n const rearrangeSlides = useCallback(\n (el: HTMLUListElement) => {\n const scrollWidth = el.scrollWidth;\n const scrollLeft = el.scrollLeft;\n const width = el.offsetWidth;\n const items = Array.from(el.children);\n\n if (forceDisableRewind) return;\n\n // When teleported, width and scrollWidth might be 0 temporarily,\n // so we don't rearrange in that case to not mess up item order.\n if (!width || !scrollWidth) return;\n\n if (roughlyEqual(scrollLeft, 0)) {\n requestAnimationFrame(() => {\n const itemsToPrepend = items.slice(-currentPerPage).reverse();\n itemsToPrepend.forEach((item) => el.prepend(item));\n el.scrollLeft = scrollLeft + width;\n });\n }\n // roughly right edge\n if (roughlyEqual(scrollWidth - scrollLeft, width)) {\n requestAnimationFrame(() => {\n const itemsToAppend = items.slice(0, currentPerPage);\n itemsToAppend.forEach((item) => el.append(item));\n el.scrollLeft = scrollLeft - width;\n });\n }\n },\n [currentPerPage, forceDisableRewind],\n );\n\n const rearrangeSlidesTimeout = useRef<NodeJS.Timeout | undefined>(undefined);\n useEffect(() => {\n if (!rewind) return;\n\n const slidesRef = listRef.current;\n if (!slidesRef) return;\n\n const callRearrangeSlides = () => {\n if (rearrangeSlidesTimeout) clearTimeout(rearrangeSlidesTimeout.current);\n rearrangeSlidesTimeout.current = setTimeout(() => rearrangeSlides(slidesRef), 50);\n };\n\n slidesRef.addEventListener(\"scroll\", callRearrangeSlides);\n\n return () => {\n if (rearrangeSlidesTimeout.current) clearTimeout(rearrangeSlidesTimeout.current);\n slidesRef.removeEventListener(\"scroll\", callRearrangeSlides);\n };\n }, [rewind, rearrangeSlides]);\n\n useEffect(() => {\n const slidesRef = listRef.current;\n if (!slidesRef) return;\n\n const resizeObserver = new ResizeObserver(([{ target }]) => {\n // When teleporting, `scrollPortWidth`, `scrollContainerWidth` and `pages` are temporarily 0,\n // so we need to check once dimensions have stabilized.\n const newScrollPortWidth = target.getBoundingClientRect().width;\n const newScrollContainerWidth = target.scrollWidth;\n\n setScrollPortWidth(newScrollPortWidth);\n setScrollContainerWidth(newScrollContainerWidth);\n\n // This gets called on initial mount, but also after teleporting which is what we need in order\n // to fix a bug where you can't rewind from first to last page when clicking the prev button.\n if (rewind) rearrangeSlides(slidesRef);\n });\n\n resizeObserver.observe(slidesRef);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [currentPerPage, rearrangeSlides, rewind, slidesCount]);\n\n useEffect(() => {\n if (!listRef.current) return;\n\n const _slidesCount = listRef.current.querySelectorAll(\"li[aria-roledescription='slide']\").length;\n setSlidesCount(_slidesCount);\n\n const handleResize = () => {\n const newViewportWidth = document.documentElement.clientWidth;\n setViewportWidth(newViewportWidth);\n };\n\n const handleScroll = (event: Event) => {\n if (!event.target) return;\n\n const slidesContainer = event.target as HTMLUListElement;\n\n const newScrollPosition = slidesContainer.scrollLeft;\n const newActiveSlide = getActiveSlide({ scrollPosition: newScrollPosition, slidesContainer });\n\n setScrollPosition(newScrollPosition);\n setActiveSlide(newActiveSlide);\n };\n\n const throttledHandleResize = throttle(handleResize, 200, { trailing: true });\n const throttledHandleScroll = throttle(handleScroll, 200, { trailing: true });\n\n window.addEventListener(\"resize\", throttledHandleResize);\n const slidesRef = listRef.current;\n slidesRef.addEventListener(\"scroll\", throttledHandleScroll);\n\n return () => {\n window.removeEventListener(\"resize\", throttledHandleResize);\n slidesRef.removeEventListener(\"scroll\", throttledHandleScroll);\n };\n }, []);\n\n useSimulateTouch({ simulateTouch, listRef });\n useStart({ start, slidesCount, listRef });\n\n /////////////////////\n\n useEffect(() => {\n if (listRef.current) {\n const _canScrollLeft = getCanScrollPrev({ scrollPosition, rewind, forceDisableRewind });\n const _canScrollNext = getCanScrollNext({ scrollPosition, scrollPortWidth, scrollContainerWidth, rewind, forceDisableRewind });\n setCanScrollPrev(_canScrollLeft);\n setCanScrollNext(_canScrollNext);\n }\n }, [rewind, scrollPosition, scrollPortWidth, scrollContainerWidth, forceDisableRewind]);\n\n ////// CALLBACKS //////\n\n const onClickLeft = useCallback(() => {\n if (!listRef.current || !canScrollPrev) return;\n listRef.current.scrollBy({ left: -scrollDistancePrev, behavior: \"smooth\" });\n setButtonTriggeredScroll(true);\n setScrollDirection(\"left\");\n }, [canScrollPrev, scrollDistancePrev]);\n\n const onClickRight = useCallback(() => {\n if (!listRef.current || !canScrollNext) return;\n listRef.current.scrollBy({ left: scrollDistanceNext, behavior: \"smooth\" });\n setButtonTriggeredScroll(true);\n setScrollDirection(\"right\");\n }, [canScrollNext, scrollDistanceNext]);\n\n return {\n activePage,\n activeSlide,\n pages,\n listRef,\n canScrollPrev,\n canScrollNext,\n onClickLeft,\n onClickRight,\n slideWidth,\n getIntersectionObserver,\n setIntersectionObserver,\n buttonTriggeredScroll,\n finishButtonTriggeredScroll,\n scrollDirection,\n slidesCount,\n currentPerPage,\n };\n};\n\nexport default useCreateCarousel;\n"],"mappings":";;;;;;AAgCA,IAAM,KAAqB,EACzB,aAAU,GACV,aAAU,GACV,YAAS,IACT,aAAU,GACV,SAAM,GACN,cACA,oBAAgB,IAChB,gBACsB;CAEtB,IAAM,IAAU,EAAyB,IAAI,GAEvC,IAAuB,OAAO,WAAa,MAAc,SAAS,gBAAgB,cAAc,GAChG,CAAC,GAAe,KAAoB,EAAS,CAAoB,GAIjE,CAAC,GAAsB,MAA2B,EAAS,CAAC,GAE5D,CAAC,GAAiB,MAAsB,EAAS,CAAC,GAElD,CAAC,GAAgB,MAAqB,EAAS,CAAC,GAChD,CAAC,GAAe,KAAoB,EAAS,EAAK,GAClD,CAAC,GAAe,KAAoB,EAAS,EAAI,GAEjD,CAAC,GAAuB,KAA4B,EAAS,EAAK,GAElE,CAAC,GAAiB,KAAsB,EAAkC,IAAI,GAE9E,CAAC,GAAa,KAAkB,EAAS,CAAC,GAE1C,UAAoC;EAExC,AADA,EAAyB,EAAK,GAC9B,EAAmB,IAAI;CACzB,GAEM,IAAc,EAAoC,IAAI,GACtD,IAA0B,QAAkB,EAAY,SAAS,CAAC,CAAC,GACnE,IAA0B,GAAa,MAA0C;EACrF,EAAY,UAAU;CACxB,GAAG,CAAC,CAAC,GAIC,IAAa,EAAc,EAAE,iBAAc,CAAC,GAC5C,IAAiB,EAAkB;EAAE;EAAS;CAAW,CAAC,GAE1D,IADiB,GAAkB;EAAE;EAAS;CAAW,CACpC,IAAiB,GACtC,KAAa,EAAmB;EAAE,SAAS;EAAgB;EAAS;CAAI,CAAC,GAGzE,IAAQ,QAAc,EAAS;EAAE;EAAa;CAAe,CAAC,GAAG,CAAC,GAAa,CAAc,CAAC,GAG9F,IAAqB,QAAc,IAAQ,GAAG,CAAC,CAAK,CAAC,GAGrD,CAAC,GAAa,MAAkB,EAAS,CAAC,GAG1C,KAAa,EAAc;EAC/B;EACA;EACA;EACA;EACA;CACF,CAAC,GAGK,IAAqB,EAAsB;EAAE;EAAgB;EAAiB;EAAsB;EAAQ;CAAmB,CAAC,GAChI,IAAqB,GAAsB;EAC/C;EACA;EACA;EACA;EACA;CACF,CAAC;CAID,QAAgB;EACd,IAAM,IAAY,EAAQ;EACrB,KAOL,MALoB,KAAK,EAAU,QAKnC,CAAA,CAAM,SAAS,GAAM,MAAO,EAAK,QAAQ,UAAU,EAAE,SAAS,CAAE;CAClE,GAAG,CAAC,EAAQ,CAAC;CAGb,IAAM,IAAkB,GACrB,MAAyB;EACxB,IAAM,IAAc,EAAG,aACjB,IAAa,EAAG,YAChB,IAAQ,EAAG,aACX,IAAQ,MAAM,KAAK,EAAG,QAAQ;EAEhC,KAIA,CAAC,KAAS,CAAC,MAEX,EAAa,GAAY,CAAC,KAC5B,4BAA4B;GAG1B,AADA,EAD6B,MAAM,CAAC,CAAc,CAAC,CAAC,QACpD,CAAA,CAAe,SAAS,MAAS,EAAG,QAAQ,CAAI,CAAC,GACjD,EAAG,aAAa,IAAa;EAC/B,CAAC,GAGC,EAAa,IAAc,GAAY,CAAK,KAC9C,4BAA4B;GAG1B,AADA,EAD4B,MAAM,GAAG,CACrC,CAAA,CAAc,SAAS,MAAS,EAAG,OAAO,CAAI,CAAC,GAC/C,EAAG,aAAa,IAAa;EAC/B,CAAC;CAEL,GACA,CAAC,GAAgB,CAAkB,CACrC,GAEM,IAAyB,EAAmC,KAAA,CAAS;CA+G3E,OA9GA,QAAgB;EACd,IAAI,CAAC,GAAQ;EAEb,IAAM,IAAY,EAAQ;EAC1B,IAAI,CAAC,GAAW;EAEhB,IAAM,UAA4B;GAEhC,AADI,KAAwB,aAAa,EAAuB,OAAO,GACvE,EAAuB,UAAU,iBAAiB,EAAgB,CAAS,GAAG,EAAE;EAClF;EAIA,OAFA,EAAU,iBAAiB,UAAU,CAAmB,SAE3C;GAEX,AADI,EAAuB,WAAS,aAAa,EAAuB,OAAO,GAC/E,EAAU,oBAAoB,UAAU,CAAmB;EAC7D;CACF,GAAG,CAAC,GAAQ,CAAe,CAAC,GAE5B,QAAgB;EACd,IAAM,IAAY,EAAQ;EAC1B,IAAI,CAAC,GAAW;EAEhB,IAAM,IAAiB,IAAI,gBAAgB,CAAC,EAAE,iBAAc;GAG1D,IAAM,IAAqB,EAAO,sBAAsB,CAAC,CAAC,OACpD,IAA0B,EAAO;GAOvC,AALA,GAAmB,CAAkB,GACrC,GAAwB,CAAuB,GAI3C,KAAQ,EAAgB,CAAS;EACvC,CAAC;EAID,OAFA,EAAe,QAAQ,CAAS,SAEnB;GACX,EAAe,WAAW;EAC5B;CACF,GAAG;EAAC;EAAgB;EAAiB;EAAQ;CAAW,CAAC,GAEzD,QAAgB;EACd,IAAI,CAAC,EAAQ,SAAS;EAEtB,IAAM,IAAe,EAAQ,QAAQ,iBAAiB,kCAAkC,CAAC,CAAC;EAC1F,EAAe,CAAY;EAE3B,IAAM,UAAqB;GACzB,IAAM,IAAmB,SAAS,gBAAgB;GAClD,EAAiB,CAAgB;EACnC,GAEM,KAAgB,MAAiB;GACrC,IAAI,CAAC,EAAM,QAAQ;GAEnB,IAAM,IAAkB,EAAM,QAExB,IAAoB,EAAgB,YACpC,IAAiB,EAAe;IAAE,gBAAgB;IAAmB;GAAgB,CAAC;GAG5F,AADA,GAAkB,CAAiB,GACnC,GAAe,CAAc;EAC/B,GAEM,IAAwB,EAAS,GAAc,KAAK,EAAE,UAAU,GAAK,CAAC,GACtE,IAAwB,EAAS,GAAc,KAAK,EAAE,UAAU,GAAK,CAAC;EAE5E,OAAO,iBAAiB,UAAU,CAAqB;EACvD,IAAM,IAAY,EAAQ;EAG1B,OAFA,EAAU,iBAAiB,UAAU,CAAqB,SAE7C;GAEX,AADA,OAAO,oBAAoB,UAAU,CAAqB,GAC1D,EAAU,oBAAoB,UAAU,CAAqB;EAC/D;CACF,GAAG,CAAC,CAAC,GAEL,EAAiB;EAAE;EAAe;CAAQ,CAAC,GAC3C,EAAS;EAAE;EAAO;EAAa;CAAQ,CAAC,GAIxC,QAAgB;EACd,IAAI,EAAQ,SAAS;GACnB,IAAM,IAAiB,EAAiB;IAAE;IAAgB;IAAQ;GAAmB,CAAC,GAChF,IAAiB,EAAiB;IAAE;IAAgB;IAAiB;IAAsB;IAAQ;GAAmB,CAAC;GAE7H,AADA,EAAiB,CAAc,GAC/B,EAAiB,CAAc;EACjC;CACF,GAAG;EAAC;EAAQ;EAAgB;EAAiB;EAAsB;CAAkB,CAAC,GAkB/E;EACL;EACA;EACA;EACA;EACA;EACA;EACA,aArBkB,QAAkB;GAChC,CAAC,EAAQ,WAAW,CAAC,MACzB,EAAQ,QAAQ,SAAS;IAAE,MAAM,CAAC;IAAoB,UAAU;GAAS,CAAC,GAC1E,EAAyB,EAAI,GAC7B,EAAmB,MAAM;EAC3B,GAAG,CAAC,GAAe,CAAkB,CAgBnC;EACA,cAfmB,QAAkB;GACjC,CAAC,EAAQ,WAAW,CAAC,MACzB,EAAQ,QAAQ,SAAS;IAAE,MAAM;IAAoB,UAAU;GAAS,CAAC,GACzE,EAAyB,EAAI,GAC7B,EAAmB,OAAO;EAC5B,GAAG,CAAC,GAAe,CAAkB,CAUnC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF"}
|