From a551b565e83527c7f0a4e428bf4c36d1b75dd059 Mon Sep 17 00:00:00 2001 From: David Jerleke Date: Sat, 27 Jan 2024 13:18:06 +0100 Subject: [PATCH] Implement #723. --- packages/embla-carousel-docs/package.json | 18 +- .../src/components/Header/HeaderLogo.tsx | 17 +- .../components/Mdx/Components/Blockquote.tsx | 14 + .../src/components/Mdx/Components/Hr.tsx | 18 + .../src/components/Mdx/Components/Link.tsx | 15 +- .../Mdx/Components/PrismSyntaxHighlight.tsx | 7 +- .../src/components/Mdx/Mdx.tsx | 6 +- .../src/components/Mdx/Styles/blockquote.ts | 16 - .../src/components/Mdx/Styles/code.ts | 21 +- .../src/components/Mdx/Styles/heading.ts | 26 +- .../src/components/Mdx/Styles/hr.ts | 20 - .../src/components/Mdx/Styles/index.ts | 12 +- .../src/components/Mdx/Styles/link.ts | 9 - .../components/Sandbox/SandboxSelection.tsx | 30 +- .../src/components/SiteLogo/SiteLogo.tsx | 2 +- .../SiteNavigationMenuCompact.tsx | 17 +- .../src/components/Tabs/TabsButton.tsx | 12 +- .../src/components/Tabs/TabsList.tsx | 79 +- .../src/consts/prismHighlight.ts | 1 + .../src/consts/scrollBars.ts | 5 +- .../src/content/pages/api/events.mdx | 517 ++++++++---- .../src/content/pages/api/methods.mdx | 282 +++++-- .../src/content/pages/api/options.mdx | 327 +++++--- .../src/content/pages/api/plugins.mdx | 790 ++++++++++++------ .../src/content/pages/get-started/cdn.mdx | 14 +- .../src/content/pages/get-started/module.mdx | 24 +- .../src/content/pages/get-started/react.mdx | 24 +- .../src/content/pages/get-started/solid.mdx | 30 +- .../src/content/pages/get-started/svelte.mdx | 26 +- .../src/content/pages/get-started/vue.mdx | 14 +- yarn.lock | 36 +- 31 files changed, 1590 insertions(+), 839 deletions(-) create mode 100644 packages/embla-carousel-docs/src/components/Mdx/Components/Blockquote.tsx create mode 100644 packages/embla-carousel-docs/src/components/Mdx/Components/Hr.tsx delete mode 100644 packages/embla-carousel-docs/src/components/Mdx/Styles/blockquote.ts delete mode 100644 packages/embla-carousel-docs/src/components/Mdx/Styles/hr.ts delete mode 100644 packages/embla-carousel-docs/src/components/Mdx/Styles/link.ts diff --git a/packages/embla-carousel-docs/package.json b/packages/embla-carousel-docs/package.json index adeaeb20e..558088bdd 100644 --- a/packages/embla-carousel-docs/package.json +++ b/packages/embla-carousel-docs/package.json @@ -43,19 +43,19 @@ "embla-carousel-class-names": "8.0.0-rc21", "embla-carousel-react": "8.0.0-rc21", "focus-trap-react": "^8.10.0", - "gatsby": "^5.10.0", - "gatsby-plugin-layout": "^4.4.0", - "gatsby-plugin-manifest": "^5.4.0", - "gatsby-plugin-mdx": "^5.4.0", + "gatsby": "^5.13.3", + "gatsby-plugin-layout": "^4.13.1", + "gatsby-plugin-manifest": "^5.13.1", + "gatsby-plugin-mdx": "^5.13.1", "gatsby-plugin-react-svg": "^3.3.0", - "gatsby-plugin-sitemap": "^6.10.0", - "gatsby-plugin-styled-components": "^6.4.0", - "gatsby-remark-autolink-headers": "^6.4.0", - "gatsby-source-filesystem": "^5.4.0", + "gatsby-plugin-sitemap": "^6.13.1", + "gatsby-plugin-styled-components": "^6.13.1", + "gatsby-remark-autolink-headers": "^6.13.1", + "gatsby-source-filesystem": "^5.13.1", "inter-ui": "^3.19.3", "lodash": "^4.17.21", "prism-react-renderer": "^1.3.5", - "prismjs": "^1.26.0", + "prismjs": "^1.29.0", "react": "^18.1.0", "react-dom": "^18.1.0", "react-intersection-observer": "^8.33.1", diff --git a/packages/embla-carousel-docs/src/components/Header/HeaderLogo.tsx b/packages/embla-carousel-docs/src/components/Header/HeaderLogo.tsx index 8a49e4b02..7439b4b9e 100644 --- a/packages/embla-carousel-docs/src/components/Header/HeaderLogo.tsx +++ b/packages/embla-carousel-docs/src/components/Header/HeaderLogo.tsx @@ -6,8 +6,14 @@ import { MEDIA } from 'consts/breakpoints' import { COLORS } from 'consts/themes' import { SPACINGS } from 'consts/spacings' import { FONT_SIZES, FONT_WEIGHTS } from 'consts/fontSizes' +import { BORDER_SIZES } from 'consts/border' import { LinkBare } from 'components/Link/LinkBare' -import { SiteLogo } from 'components/SiteLogo/SiteLogo' +import { + LogoDarkIcon, + LogoImage, + LogoLightIcon, + SiteLogo +} from 'components/SiteLogo/SiteLogo' const HeaderLogoWrapper = styled(LinkBare)` color: ${COLORS.TEXT_HIGH_CONTRAST}; @@ -24,16 +30,19 @@ const HeaderLogoWrapper = styled(LinkBare)` ` const HeaderLogoImage = styled(SiteLogo)` - ${createSquareSizeStyles('2.8rem')}; + ${createSquareSizeStyles('4rem')}; + border: ${BORDER_SIZES.DETAIL} solid ${COLORS.DETAIL_LOW_CONTRAST}; + border-radius: 50%; margin-right: ${SPACINGS.CUSTOM(({ ONE }) => ONE + 0.2)}; display: flex; ${MEDIA.MIN_XXS} { - ${createSquareSizeStyles('3rem')}; + ${createSquareSizeStyles('4.4rem')}; } - > img { + > ${LogoImage}, > ${LogoLightIcon}, > ${LogoDarkIcon} { ${createSquareSizeStyles('100%')}; + padding: ${SPACINGS.ONE}; } ` diff --git a/packages/embla-carousel-docs/src/components/Mdx/Components/Blockquote.tsx b/packages/embla-carousel-docs/src/components/Mdx/Components/Blockquote.tsx new file mode 100644 index 000000000..764bcf193 --- /dev/null +++ b/packages/embla-carousel-docs/src/components/Mdx/Components/Blockquote.tsx @@ -0,0 +1,14 @@ +import styled from 'styled-components' +import { COLORS } from 'consts/themes' +import { SPACINGS } from 'consts/spacings' +import { BORDER_SIZES } from 'consts/border' + +export const Blockquote = styled.blockquote` + padding-left: ${SPACINGS.FOUR}; + border-left: ${BORDER_SIZES.ACCENT_VERTICAL} solid + ${COLORS.DETAIL_LOW_CONTRAST}; + + > *:last-child { + margin-bottom: 0; + } +` diff --git a/packages/embla-carousel-docs/src/components/Mdx/Components/Hr.tsx b/packages/embla-carousel-docs/src/components/Mdx/Components/Hr.tsx new file mode 100644 index 000000000..034891e14 --- /dev/null +++ b/packages/embla-carousel-docs/src/components/Mdx/Components/Hr.tsx @@ -0,0 +1,18 @@ +import styled from 'styled-components' +import { COLORS } from 'consts/themes' +import { BORDER_SIZES } from 'consts/border' +import { SPACINGS } from 'consts/spacings' +import { HEADING_TOP_SPACING } from '../Styles/heading' + +const DECORATION_WIDTH = SPACINGS.CUSTOM(({ EIGHT }) => EIGHT + 0.2) + +export const Hr = styled.hr` + border-top: 0; + border-right: 0; + border-left: 0; + border-bottom: ${BORDER_SIZES.DETAIL} solid ${COLORS.DETAIL_MEDIUM_CONTRAST}; + margin-top: ${HEADING_TOP_SPACING}; + margin-bottom: ${HEADING_TOP_SPACING}; + width: ${DECORATION_WIDTH}; + background-color: ${COLORS.DETAIL_MEDIUM_CONTRAST}; +` diff --git a/packages/embla-carousel-docs/src/components/Mdx/Components/Link.tsx b/packages/embla-carousel-docs/src/components/Mdx/Components/Link.tsx index 8159f470f..9ecb8308a 100644 --- a/packages/embla-carousel-docs/src/components/Mdx/Components/Link.tsx +++ b/packages/embla-carousel-docs/src/components/Mdx/Components/Link.tsx @@ -1,12 +1,25 @@ import React, { AnchorHTMLAttributes } from 'react' +import styled, { css } from 'styled-components' +import { CODE_HIGHLIGHT_CLASS_NAME } from './Code' +import { BRAND_GRADIENT_TEXT_STYLES } from 'consts/gradients' import { LinkContent } from 'components/Link/LinkContent' import { LinkBare } from 'components/Link/LinkBare' +const linkStyles = css` + .${CODE_HIGHLIGHT_CLASS_NAME} > span { + ${BRAND_GRADIENT_TEXT_STYLES}; + } +` + +const LinkContentStyled = styled(LinkContent)` + ${linkStyles}; +` + type PropType = AnchorHTMLAttributes export const Link = (props: PropType) => { const { className, href = '' } = props const classList = className?.split(' ') || [] - const Link = classList.indexOf('anchor') > -1 ? LinkBare : LinkContent + const Link = classList.indexOf('anchor') > -1 ? LinkBare : LinkContentStyled return } diff --git a/packages/embla-carousel-docs/src/components/Mdx/Components/PrismSyntaxHighlight.tsx b/packages/embla-carousel-docs/src/components/Mdx/Components/PrismSyntaxHighlight.tsx index 0bb78222a..c55ca1229 100644 --- a/packages/embla-carousel-docs/src/components/Mdx/Components/PrismSyntaxHighlight.tsx +++ b/packages/embla-carousel-docs/src/components/Mdx/Components/PrismSyntaxHighlight.tsx @@ -18,10 +18,11 @@ type PropType = { export const PrismSyntaxHighlight = (props: PropType) => { const { children, className } = props - const { language, highlightedLines } = useMemo(() => { - const { language, highlight } = parseCodeBlockProps(className) + const { asLanguage, language, highlightedLines } = useMemo(() => { + const { asLanguage, language, highlight } = parseCodeBlockProps(className) return { language, + asLanguage, highlightedLines: parseHighlightedLines(highlight) } }, [className]) @@ -32,7 +33,7 @@ export const PrismSyntaxHighlight = (props: PropType) => { {({ className, tokens, getLineProps, getTokenProps }) => ( diff --git a/packages/embla-carousel-docs/src/components/Mdx/Mdx.tsx b/packages/embla-carousel-docs/src/components/Mdx/Mdx.tsx index 61b738beb..ec87f37bc 100644 --- a/packages/embla-carousel-docs/src/components/Mdx/Mdx.tsx +++ b/packages/embla-carousel-docs/src/components/Mdx/Mdx.tsx @@ -4,7 +4,9 @@ import { MdxStyles } from './Styles' import { Link } from 'components/Mdx/Components/Link' import { Pre } from 'components/Mdx/Components/Pre' import { Code } from 'components/Mdx/Components/Code' +import { Hr } from './Components/Hr' import { H1 } from 'components/Mdx/Components/H1' +import { Blockquote } from './Components/Blockquote' import { RepositoryLink } from 'components/Mdx/Components/RepositoryLink' import { PageChildLinks } from 'components/Mdx/Components/PageChildLinks' import { Admonition } from 'components/Mdx/Components/Admonition' @@ -32,7 +34,9 @@ export const Mdx = (props: PropType) => { BrandPrimaryText, BrandSecondaryText, BrandAlternativeText, - Admonition + Admonition, + hr: Hr, + blockquote: Blockquote }} > {children} diff --git a/packages/embla-carousel-docs/src/components/Mdx/Styles/blockquote.ts b/packages/embla-carousel-docs/src/components/Mdx/Styles/blockquote.ts deleted file mode 100644 index d53d1b61e..000000000 --- a/packages/embla-carousel-docs/src/components/Mdx/Styles/blockquote.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { css } from 'styled-components' -import { COLORS } from 'consts/themes' -import { SPACINGS } from 'consts/spacings' -import { BORDER_SIZES } from 'consts/border' - -export const blockquoteStyles = css` - blockquote { - padding-left: ${SPACINGS.FOUR}; - border-left: ${BORDER_SIZES.ACCENT_VERTICAL} solid - ${COLORS.DETAIL_LOW_CONTRAST}; - - > *:last-child { - margin-bottom: 0; - } - } -` diff --git a/packages/embla-carousel-docs/src/components/Mdx/Styles/code.ts b/packages/embla-carousel-docs/src/components/Mdx/Styles/code.ts index 8a2f48da6..669b7c5ae 100644 --- a/packages/embla-carousel-docs/src/components/Mdx/Styles/code.ts +++ b/packages/embla-carousel-docs/src/components/Mdx/Styles/code.ts @@ -9,7 +9,7 @@ import { FONT_SIZES, FONT_WEIGHTS } from 'consts/fontSizes' import { CODE_HIGHLIGHT_CLASS_NAME } from '../Components/Code' import { PRISM_FRAME_RADIUS } from '../Components/PrismSyntaxFrame' import { AdmonitionWrapper } from '../Components/Admonition' -import { createScrollBarStyles } from 'consts/scrollBars' +import { SCROLLBAR_SIZE, createScrollBarStyles } from 'consts/scrollBars' import { PRISM_HIGHLIGHT_CLASS_NAME, PRISM_HIGHLIGHT_LINE_CLASS_NAME @@ -137,10 +137,17 @@ export const codeStyles = css` } .${PRISM_HIGHLIGHT_CLASS_NAME} pre[class*='language-'] { - padding: ${PAGE_FRAME_SPACING} 0; background-color: transparent; border: 0; margin-bottom: 0; + padding-left: 0; + padding-right: 0; + padding-top: ${PAGE_FRAME_SPACING}; + padding-bottom: calc(${PAGE_FRAME_SPACING} - ${SCROLLBAR_SIZE}); + + @media (hover: none), (hover: on-demand) { + padding-bottom: ${PAGE_FRAME_SPACING}; + } } .${PRISM_HIGHLIGHT_CLASS_NAME} pre code { @@ -156,8 +163,12 @@ export const codeStyles = css` pre { ${createScrollBarStyles('x')}; color: ${COLORS.TEXT_BODY}; - overflow: auto; white-space: pre; + overflow-x: scroll; + + @media (hover: none), (hover: on-demand) { + overflow-x: auto; + } } .token-line { @@ -178,7 +189,7 @@ export const codeStyles = css` .token.function, .token.class-name, .token.maybe-class-name:not(.imports), - .token.literal-property.property, + .token.literal-property.property:not(.parameter), .token.unit, .token.symbol { color: ${COLORS.BRAND_ALTERNATIVE}; @@ -203,7 +214,7 @@ export const codeStyles = css` .token.attr-value, .token.keyword, - .token.property, + .token.property:not(.parameter), .token.control, .token.directive, .token.selector, diff --git a/packages/embla-carousel-docs/src/components/Mdx/Styles/heading.ts b/packages/embla-carousel-docs/src/components/Mdx/Styles/heading.ts index 7a7ba15bc..6529d6051 100644 --- a/packages/embla-carousel-docs/src/components/Mdx/Styles/heading.ts +++ b/packages/embla-carousel-docs/src/components/Mdx/Styles/heading.ts @@ -76,7 +76,7 @@ export const headingStyles = css` } } - > .anchor > div { + > .anchor > span { position: absolute; top: 0; left: 0; @@ -102,18 +102,18 @@ export const headingStyles = css` } } - h1:hover .anchor > div > svg, - h2:hover .anchor > div > svg, - h3:hover .anchor > div > svg, - h4:hover .anchor > div > svg, - h5:hover .anchor > div > svg, - h6:hover .anchor > div > svg, - h1 .anchor:focus > div > svg, - h2 .anchor:focus > div > svg, - h3 .anchor:focus > div > svg, - h4 .anchor:focus > div > svg, - h5 .anchor:focus > div > svg, - h6 .anchor:focus > div > svg { + h1:hover .anchor > span > svg, + h2:hover .anchor > span > svg, + h3:hover .anchor > span > svg, + h4:hover .anchor > span > svg, + h5:hover .anchor > span > svg, + h6:hover .anchor > span > svg, + h1 .anchor:focus > span > svg, + h2 .anchor:focus > span > svg, + h3 .anchor:focus > span > svg, + h4 .anchor:focus > span > svg, + h5 .anchor:focus > span > svg, + h6 .anchor:focus > span > svg { visibility: visible; } ` diff --git a/packages/embla-carousel-docs/src/components/Mdx/Styles/hr.ts b/packages/embla-carousel-docs/src/components/Mdx/Styles/hr.ts deleted file mode 100644 index 03fc7e3e5..000000000 --- a/packages/embla-carousel-docs/src/components/Mdx/Styles/hr.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { css } from 'styled-components' -import { COLORS } from 'consts/themes' -import { BORDER_SIZES } from 'consts/border' -import { HEADING_TOP_SPACING } from './heading' -import { SPACINGS } from 'consts/spacings' - -const DECORATION_WIDTH = SPACINGS.CUSTOM(({ EIGHT }) => EIGHT + 0.2) - -export const hrStyles = css` - hr { - border-top: 0; - border-right: 0; - border-left: 0; - border-bottom: ${BORDER_SIZES.DETAIL} solid ${COLORS.DETAIL_MEDIUM_CONTRAST}; - margin-top: ${HEADING_TOP_SPACING}; - margin-bottom: ${HEADING_TOP_SPACING}; - width: ${DECORATION_WIDTH}; - background-color: ${COLORS.DETAIL_MEDIUM_CONTRAST}; - } -` diff --git a/packages/embla-carousel-docs/src/components/Mdx/Styles/index.ts b/packages/embla-carousel-docs/src/components/Mdx/Styles/index.ts index ed3d230b9..b058304e3 100644 --- a/packages/embla-carousel-docs/src/components/Mdx/Styles/index.ts +++ b/packages/embla-carousel-docs/src/components/Mdx/Styles/index.ts @@ -6,17 +6,11 @@ import { TabsWrapper } from 'components/Tabs/Tabs' import { TabsPanelWrapper } from 'components/Tabs/TabsPanel' import { AdmonitionWrapper, AdmonitionContent } from '../Components/Admonition' import { headingStyles } from './heading' -import { blockquoteStyles } from './blockquote' import { listStyles } from './list' import { codeStyles } from './code' -import { linkStyles } from './link' -import { hrStyles } from './hr' export const MdxStyles = styled.div` - ${blockquoteStyles}; ${codeStyles}; - ${hrStyles}; - ${linkStyles}; color: ${COLORS.TEXT_BODY}; @@ -32,20 +26,18 @@ export const MdxStyles = styled.div` h4, h5, h6, - hgroup, ul, ol, dl, - blockquote, p, + hgroup, address, table, fieldset, figure, pre, - ul, - ol, dd, + blockquote, blockquote code, kbd, samp, diff --git a/packages/embla-carousel-docs/src/components/Mdx/Styles/link.ts b/packages/embla-carousel-docs/src/components/Mdx/Styles/link.ts deleted file mode 100644 index 44fa2c6da..000000000 --- a/packages/embla-carousel-docs/src/components/Mdx/Styles/link.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { css } from 'styled-components' -import { BRAND_GRADIENT_TEXT_STYLES } from 'consts/gradients' -import { CODE_HIGHLIGHT_CLASS_NAME } from '../Components/Code' - -export const linkStyles = css` - a .${CODE_HIGHLIGHT_CLASS_NAME} > span { - ${BRAND_GRADIENT_TEXT_STYLES}; - } -` diff --git a/packages/embla-carousel-docs/src/components/Sandbox/SandboxSelection.tsx b/packages/embla-carousel-docs/src/components/Sandbox/SandboxSelection.tsx index 89cefef35..c75328c82 100644 --- a/packages/embla-carousel-docs/src/components/Sandbox/SandboxSelection.tsx +++ b/packages/embla-carousel-docs/src/components/Sandbox/SandboxSelection.tsx @@ -30,7 +30,7 @@ const SandboxSelectionWrapper = styled.div` margin-top: -${SPACINGS.THREE}; ` -const SandboxSelectionButtons = styled(ButtonBare)` +const SandboxSelectionOpenModalButton = styled(ButtonBare)` color: ${COLORS.TEXT_LOW_CONTRAST}; font-size: ${FONT_SIZES.COMPLEMENTARY}; margin-bottom: ${SPACINGS.ONE}; @@ -44,7 +44,7 @@ const SandboxSelectionButtons = styled(ButtonBare)` } ` -const SelectionModal = styled.div` +const SandboxSelectionModal = styled.div` z-index: ${LAYERS.SEARCH + LAYERS.STEP}; padding: ${PAGE_FRAME_SPACING} 0; background-color: ${COLORS.BACKGROUND_SITE}; @@ -68,7 +68,7 @@ const SelectionModal = styled.div` } ` -const SelectionModalOverlay = styled.div` +const SandboxSelectionModalOverlay = styled.div` z-index: ${LAYERS.SEARCH}; position: fixed; top: 0; @@ -82,7 +82,7 @@ const SelectionModalOverlay = styled.div` } ` -const SelectionModalCloseButton = styled(ButtonBare)` +const SandboxSelectionModalCloseButton = styled(ButtonBare)` ${createSquareSizeStyles(BUTTON_SIZE)}; z-index: ${LAYERS.STEP}; display: flex; @@ -93,7 +93,7 @@ const SelectionModalCloseButton = styled(ButtonBare)` right: 0; ` -const SelectionModalScrollArea = styled.div` +const SandboxSelectionScrollArea = styled.div` padding: 0 ${PAGE_FRAME_SPACING}; overflow: auto; position: relative; @@ -119,7 +119,7 @@ export const SandboxSelection = (props: PropType) => { return ( - { Edit Code - + {selectionOpen && (
- setSelectionOpen(false)} /> + setSelectionOpen(false)} + /> - - setSelectionOpen(false)} > - + - + - - + +
diff --git a/packages/embla-carousel-docs/src/components/SiteLogo/SiteLogo.tsx b/packages/embla-carousel-docs/src/components/SiteLogo/SiteLogo.tsx index 3dbfa9ed5..f27ea5a92 100644 --- a/packages/embla-carousel-docs/src/components/SiteLogo/SiteLogo.tsx +++ b/packages/embla-carousel-docs/src/components/SiteLogo/SiteLogo.tsx @@ -33,7 +33,7 @@ const imageStyles = css` z-index: ${LAYERS.STEP}; ` -const LogoImage = styled.img` +export const LogoImage = styled.img` ${imageStyles}; ` diff --git a/packages/embla-carousel-docs/src/components/SiteNavigation/SiteNavigationMenuCompact.tsx b/packages/embla-carousel-docs/src/components/SiteNavigation/SiteNavigationMenuCompact.tsx index d29f6ad4c..011ee74de 100644 --- a/packages/embla-carousel-docs/src/components/SiteNavigation/SiteNavigationMenuCompact.tsx +++ b/packages/embla-carousel-docs/src/components/SiteNavigation/SiteNavigationMenuCompact.tsx @@ -12,7 +12,7 @@ import { TableOfContents } from 'components/TableOfContents/TableOfContents' import { FooterLinks } from 'components/Footer/FooterLinks' import { TabsItem } from 'components/Tabs/TabsItem' import { Tabs } from 'components/Tabs/Tabs' -import { TabsList } from 'components/Tabs/TabsList' +import { TabsListScrollArea, TabsListWrapper } from 'components/Tabs/TabsList' import { TabsButtonWrapper } from 'components/Tabs/TabsButton' import { TabsPanelWrapper } from 'components/Tabs/TabsPanel' import { SiteNavigationSubMenus } from './SiteNavigationSubMenus' @@ -53,7 +53,7 @@ const MenuTabs = styled(Tabs)<{ }>` height: 100%; - ${TabsList} { + ${TabsListWrapper} { height: ${HEADER_HEIGHT}; z-index: ${LAYERS.STEP * 2}; position: absolute; @@ -67,6 +67,19 @@ const MenuTabs = styled(Tabs)<{ border-top: ${BORDER_SIZES.DETAIL} solid ${COLORS.DETAIL_LOW_CONTRAST}; border-bottom: 0; justify-content: center; + + &:before { + display: none; + } + } + + ${TabsListScrollArea} { + overflow: visible; + + &:before, + &:after { + display: none; + } } ${TabsPanelWrapper} { diff --git a/packages/embla-carousel-docs/src/components/Tabs/TabsButton.tsx b/packages/embla-carousel-docs/src/components/Tabs/TabsButton.tsx index 10245808c..fb490bcc5 100644 --- a/packages/embla-carousel-docs/src/components/Tabs/TabsButton.tsx +++ b/packages/embla-carousel-docs/src/components/Tabs/TabsButton.tsx @@ -2,11 +2,12 @@ import React, { useCallback } from 'react' import styled, { css } from 'styled-components' import { BRAND_GRADIENT_BACKGROUND_STYLES } from 'consts/gradients' import { SPACINGS } from 'consts/spacings' -import { TabsItemWithIndexType } from 'consts/tabs' +import { TabsItemType } from 'consts/tabs' import { ButtonBare, ButtonBareText } from 'components/Button/ButtonBare' import { COLORS } from 'consts/themes' import { BORDER_SIZES } from 'consts/border' import { PropType as ButtonPropType } from 'components/Button/ButtonBare' +import { LAYERS } from 'consts/layers' import { ActiveText as TabsButtonActiveText, InactiveText as TabsButtonInactiveText @@ -26,8 +27,9 @@ export const TabsButtonWrapper = styled(ButtonBare)<{ $selected: boolean }>` ${({ $selected }) => $selected && css` - &:before { + &:after { ${BRAND_GRADIENT_BACKGROUND_STYLES}; + z-index: ${LAYERS.STEP}; content: ''; position: absolute; left: 0; @@ -40,11 +42,11 @@ export const TabsButtonWrapper = styled(ButtonBare)<{ $selected: boolean }>` ` type PropType = ButtonPropType & { - tab: TabsItemWithIndexType - activeTab: TabsItemWithIndexType + tab: TabsItemType + activeTab: TabsItemType groupId: string setActiveTab: ( - tab: TabsItemWithIndexType, + tab: TabsItemType, element: EventTarget & HTMLButtonElement ) => void } diff --git a/packages/embla-carousel-docs/src/components/Tabs/TabsList.tsx b/packages/embla-carousel-docs/src/components/Tabs/TabsList.tsx index 7e6ee748f..e3012b113 100644 --- a/packages/embla-carousel-docs/src/components/Tabs/TabsList.tsx +++ b/packages/embla-carousel-docs/src/components/Tabs/TabsList.tsx @@ -1,11 +1,82 @@ +import React, { PropsWithRef, ReactNode } from 'react' import styled from 'styled-components' import { BORDER_SIZES } from 'consts/border' import { SPACINGS } from 'consts/spacings' import { COLORS } from 'consts/themes' +import { LAYERS } from 'consts/layers' +import { PAGE_FRAME_SPACING } from 'components/Page/PageFrame' +import { + SCROLLBAR_SIZE, + createScrollBarShadowStyles, + createScrollBarStyles +} from 'consts/scrollBars' -export const TabsList = styled.div` - margin-bottom: ${SPACINGS.FOUR}; - border-bottom: ${BORDER_SIZES.DETAIL} solid ${COLORS.DETAIL_LOW_CONTRAST}; +export const TabsListWrapper = styled.div` display: flex; - overflow-x: auto; + position: relative; + margin-bottom: calc(${SPACINGS.FOUR} - ${SCROLLBAR_SIZE}); + overflow: hidden; + + &:after { + position: absolute; + content: ''; + height: ${BORDER_SIZES.DETAIL}; + background-color: ${COLORS.DETAIL_LOW_CONTRAST}; + width: 100%; + display: block; + bottom: calc(${SCROLLBAR_SIZE} - ${BORDER_SIZES.DETAIL}); + z-index: ${LAYERS.STEP}; + + @media (hover: none), (hover: on-demand) { + bottom: ${SCROLLBAR_SIZE}; + } + } ` + +export const TabsListScrollArea = styled.div` + ${createScrollBarStyles('x')}; + + display: flex; + width: 100%; + overflow-x: scroll; + + @media (hover: none), (hover: on-demand) { + overflow-x: auto; + padding-bottom: ${SCROLLBAR_SIZE}; + } + + &:before, + &:after { + z-index: ${LAYERS.STEP}; + width: ${PAGE_FRAME_SPACING}; + display: block; + position: absolute; + content: ''; + top: 0; + bottom: 0; + } + &:before { + ${createScrollBarShadowStyles('left')}; + left: -4rem; + } + &:after { + ${createScrollBarShadowStyles('right')}; + right: -4rem; + } +` + +type PropType = { children?: ReactNode | undefined } & PropsWithRef< + React.DetailedHTMLProps, HTMLDivElement> +> + +export const TabsList = (props: PropType) => { + const { children, ...restProps } = props + + return ( + + + {children} + + + ) +} diff --git a/packages/embla-carousel-docs/src/consts/prismHighlight.ts b/packages/embla-carousel-docs/src/consts/prismHighlight.ts index 9c15914ac..86ec3f842 100644 --- a/packages/embla-carousel-docs/src/consts/prismHighlight.ts +++ b/packages/embla-carousel-docs/src/consts/prismHighlight.ts @@ -6,5 +6,6 @@ export const PRISM_HIGHLIGHT_PROP_SEPARATOR = '___' export type PrismCodeBlockPropsType = { language: PrismLanguage + asLanguage?: PrismLanguage highlight?: string } diff --git a/packages/embla-carousel-docs/src/consts/scrollBars.ts b/packages/embla-carousel-docs/src/consts/scrollBars.ts index 4a85c38ba..467218f9c 100644 --- a/packages/embla-carousel-docs/src/consts/scrollBars.ts +++ b/packages/embla-carousel-docs/src/consts/scrollBars.ts @@ -6,6 +6,9 @@ import { } from 'styled-components' import { BORDER_RADIUSES } from './border' import { COLORS } from './themes' +import { SPACINGS } from './spacings' + +export const SCROLLBAR_SIZE = SPACINGS.ONE type ScrollBarAxisType = 'x' | 'y' @@ -23,7 +26,7 @@ export const createScrollBarStyles = ( background-color: transparent; } ::-webkit-scrollbar { - ${sizeProperty}: 0.6rem; + ${sizeProperty}: ${SCROLLBAR_SIZE}; } &:hover { diff --git a/packages/embla-carousel-docs/src/content/pages/api/events.mdx b/packages/embla-carousel-docs/src/content/pages/api/events.mdx index e95e1a216..3a707f6ad 100644 --- a/packages/embla-carousel-docs/src/content/pages/api/events.mdx +++ b/packages/embla-carousel-docs/src/content/pages/api/events.mdx @@ -21,68 +21,114 @@ You need an **initialized carousel** in order to **make use of events**. Events ### Adding event listeners -After initializing a carousel, we're going to **subscribe** to the [select](/api/events/#select) **event** in the following example: +After initializing a carousel, we're going to **subscribe** to the [slidesInView](/api/events/#slidesinview) **event** in the following example: - + - ```js highlight={9} - import EmblaCarousel from 'embla-carousel' +```js highlight={10} +import EmblaCarousel from 'embla-carousel' - const emblaApi = EmblaCarousel(emblaNode, { loop: true }) +const emblaNode = document.querySelector('.embla') +const emblaApi = EmblaCarousel(emblaNode) - const onSelect = (emblaApi, eventName) => { - console.log(`Embla just triggered ${eventName}!`) - } +function logSlidesInView(emblaApi) { + console.log(emblaApi.slidesInView()) +} + +emblaApi.on('slidesInView', logSlidesInView) +``` + + + + +```jsx highlight={12} +import { useCallback, useEffect } from 'react' +import useEmblaCarousel from 'embla-carousel-react' + +export function EmblaCarousel() { + const [emblaRef, emblaApi] = useEmblaCarousel() + + const logSlidesInView = useCallback((emblaApi) => { + console.log(emblaApi.slidesInView()) + }, []) + + useEffect(() => { + if (emblaApi) emblaApi.on('slidesInView', logSlidesInView) + }, [emblaApi, logSlidesInView]) + + // ... +} +``` - emblaApi.on('select', onSelect) - ``` + + - - +```html highlight={12} + +``` - // ... - } - ``` + + - - +```jsx highlight={13} +import { createEffect } from 'solid-js' +import createEmblaCarousel from 'embla-carousel-solid' - ```html highlight={12} - - ``` + + - +```html highlight={12} + + +
...
+``` + +
### Removing event listeners @@ -90,77 +136,116 @@ After initializing a carousel, we're going to **subscribe** to the [select](/api In order to remove an event listener, you'll have to call the [off](/api/methods/#off) method and make sure to pass the **same callback reference** you passed to the [on](/api/methods/#off) method: - + - ```js highlight={9-11} - import EmblaCarousel from 'embla-carousel' +```js highlight={8} +import EmblaCarousel from 'embla-carousel' - const emblaApi = EmblaCarousel(emblaNode, { loop: true }) +const emblaNode = document.querySelector('.embla') +const emblaApi = EmblaCarousel(emblaNode) - const onSelect = (emblaApi, eventName) => { - console.log(`Embla just triggered ${eventName}!`) - } +function logSlidesInViewOnce(emblaApi) { + console.log(emblaApi.slidesInView()) + emblaApi.off('slidesInView', logSlidesInViewOnce) +} + +emblaApi.on('slidesInView', logSlidesInViewOnce) +``` + + + - const removeOnSelectListener = () => { - emblaApi.off('select', onSelect) - } +```jsx highlight={9} +import { useCallback, useEffect } from 'react' +import useEmblaCarousel from 'embla-carousel-react' - emblaApi.on('select', onSelect) - ``` +export function EmblaCarousel() { + const [emblaRef, emblaApi] = useEmblaCarousel() - - + const logSlidesInViewOnce = useCallback((emblaApi) => { + console.log(emblaApi.slidesInView()) + emblaApi.off('slidesInView', logSlidesInViewOnce) + }, []) - ```jsx highlight={11-13} - import { useCallback, useEffect } from 'react' - import useEmblaCarousel from 'embla-carousel-react' + useEffect(() => { + if (emblaApi) emblaApi.on('slidesInView', logSlidesInViewOnce) + }, [emblaApi, logSlidesInViewOnce]) - export const EmblaCarousel = () => { - const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true }) + // ... +} +``` - const onSelect = useCallback((emblaApi, eventName) => { - console.log(`Embla just triggered ${eventName}!`) - }, []) + + - const removeOnSelectListener = useCallback(() => { - if (emblaApi) emblaApi.off('select', onSelect) - }, [emblaApi, onSelect]) +```html highlight={9} + +``` - const [emblaNode, emblaApi] = emblaCarouselVue({ loop: true }) + + - const onSelect = (emblaApi, eventName) => { - console.log(`Embla just triggered ${eventName}!`) - } +```jsx highlight={9} +import { createEffect } from 'solid-js' +import createEmblaCarousel from 'embla-carousel-solid' - const removeOnSelectListener = () => { - if (emblaApi.value) emblaApi.value.off('select', onSelect) - } +export function EmblaCarousel() { + const [emblaRef, emblaApi] = createEmblaCarousel() - watchEffect(() => { - if (emblaApi.value) emblaApi.value.on('select', onSelect) - }) + function logSlidesInViewOnce(emblaApi) { + console.log(emblaApi.slidesInView()) + emblaApi.off('slidesInView', logSlidesInViewOnce) + } - // ... - - ``` + createEffect(() => { + const api = emblaApi() + if (api) api.on('slidesInView', logSlidesInViewOnce) + }) - + // ... +} +``` + + + + +```html highlight={8} + + +
...
+``` + +
### TypeScript @@ -168,93 +253,165 @@ In order to remove an event listener, you'll have to call the [off](/api/methods The `EmblaEventType` is obtained directly from the **core package** `embla-carousel` and used like so: - - - ```ts highlight={3,8} - import EmblaCarousel, { - EmblaCarouselType, - EmblaEventType - } from 'embla-carousel' - - function onSlidesInView( - emblaApi: EmblaCarouselType, - eventName: EmblaEventType - ): void { + + +```ts asLanguage=tsx highlight={3,11} +import EmblaCarousel, { + EmblaCarouselType, + EmblaEventType +} from 'embla-carousel' + +const emblaNode = document.querySelector('.embla') +const emblaApi = EmblaCarousel(emblaNode) + +function logEmblaEvent( + emblaApi: EmblaCarouselType, + eventName: EmblaEventType +): void { + console.log(`Embla just triggered ${eventName}!`) +} + +emblaApi.on('slidesInView', logEmblaEvent) +``` + + + + +```tsx highlight={2,9} +import React, { useCallback } from 'react' +import { EmblaCarouselType, EmblaEventType } from 'embla-carousel' +import useEmblaCarousel from 'embla-carousel-react' + +export function EmblaCarousel() { + const [emblaRef, emblaApi] = useEmblaCarousel() + + const logEmblaEvent = useCallback( + (emblaApi: EmblaCarouselType, eventName: EmblaEventType) => { console.log(`Embla just triggered ${eventName}!`) - } - - const emblaApi = EmblaCarousel(emblaNode, { loop: true }) - emblaApi.on('slidesInView', onSlidesInView) - ``` - - - - - ```tsx highlight={2,9} - import React, { useCallback } from 'react' - import { EmblaCarouselType, EmblaEventType } from 'embla-carousel' - import useEmblaCarousel from 'embla-carousel-react' - - export function EmblaCarousel() { - const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true }) - - const onSlidesInView = useCallback( - (emblaApi: EmblaCarouselType, eventName: EmblaEventType) => { - console.log(`Embla just triggered ${eventName}!`) - }, - [] - ) - - useEffect(() => { - if (!emblaApi) return - - emblaApi.on('slidesInView', onSlidesInView) - }, [onSlidesInView]) - - // ... - } - ``` - - - If you're using `pnpm`, you need to install `embla-carousel` as a **devDependency** when importing types from it like demonstrated above. -
- This is because even though `embla-carousel-react` has `embla-carousel` as a dependency, `pnpm` makes nested dependencies inaccessible by design. -
- -
- - - ```html highlight={3,10} - - ``` - - - If you're using `pnpm`, you need to install `embla-carousel` as a **devDependency** when importing types from it like demonstrated above. -
- This is because even though `embla-carousel-vue` has `embla-carousel` as a dependency, `pnpm` makes nested dependencies inaccessible by design. -
- -
+ }, + [] + ) + + useEffect(() => { + if (emblaApi) emblaApi.on('slidesInView', logEmblaEvent) + }, [logEmblaEvent]) + + // ... +} +``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-react` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
+ + +```html highlight={3,10} + +``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-vue` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
+ + +```jsx highlight={2,10} +import { createEffect } from 'solid-js' +import { EmblaCarouselType, EmblaEventType } from 'embla-carousel' +import createEmblaCarousel from 'embla-carousel-solid' + +export function EmblaCarousel() { + const [emblaRef, emblaApi] = createEmblaCarousel() + + function logEmblaEvent( + emblaApi: EmblaCarouselType, + eventName: EmblaEventType + ): void { + console.log(`Embla just triggered ${eventName}!`) + } + + createEffect(() => { + const api = emblaApi() + if (api) api.on('slidesInView', logEmblaEvent) + }) + + // ... +} +``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-solid` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
+ + +```html highlight={2,9} + + +
...
+``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-svelte` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
## Reference diff --git a/packages/embla-carousel-docs/src/content/pages/api/methods.mdx b/packages/embla-carousel-docs/src/content/pages/api/methods.mdx index f11b56c39..10b4460cd 100644 --- a/packages/embla-carousel-docs/src/content/pages/api/methods.mdx +++ b/packages/embla-carousel-docs/src/content/pages/api/methods.mdx @@ -24,53 +24,91 @@ You need an **initialized carousel** in order to **make use of methods**. They c In the following example, the [slideNodes](/api/methods/#slidenodes) method is called and logged to the console as soon as the carousel has been initialized: - + - ```js highlight={5} - import EmblaCarousel from 'embla-carousel' +```js highlight={6} +import EmblaCarousel from 'embla-carousel' - const emblaApi = EmblaCarousel(emblaNode, { loop: true }) +const emblaNode = document.querySelector('.embla') +const emblaApi = EmblaCarousel(emblaNode) - console.log(emblaApi.slideNodes()) - ``` +console.log(emblaApi.slideNodes()) +``` + + + + +```jsx highlight={8} +import { useEffect } from 'react' +import useEmblaCarousel from 'embla-carousel-react' + +export function EmblaCarousel() { + const [emblaRef, emblaApi] = useEmblaCarousel() + + useEffect(() => { + if (emblaApi) console.log(emblaApi.slideNodes()) + }, [emblaApi]) + + // ... +} +``` + + + + +```html highlight={8} + +``` - useEffect(() => { - if (emblaApi) console.log(emblaApi.slideNodes()) - }, [emblaApi]) + + - // ... - } - ``` +```jsx highlight={9} +import { createEffect } from 'solid-js' +import createEmblaCarousel from 'embla-carousel-solid' - - +export function EmblaCarousel() { + const [emblaRef, emblaApi] = createEmblaCarousel() - ```html highlight={8} - - ``` +```html highlight={8} + + +
...
+``` + +
### TypeScript @@ -78,81 +116,147 @@ In the following example, the [slideNodes](/api/methods/#slidenodes) method is c The `EmblaCarouselType` is obtained directly from the **core package** `embla-carousel` and used like so: - + + +```ts asLanguage=tsx highlight={1,6} +import EmblaCarousel, { EmblaCarouselType } from 'embla-carousel' + +const emblaNode = document.querySelector('.embla') +const emblaApi = EmblaCarousel(emblaNode) + +function logSlidesInView(emblaApi: EmblaCarouselType): void { + console.log(emblaApi.slidesInView()) +} - ```ts highlight={1,3} - import EmblaCarousel, { EmblaCarouselType } from 'embla-carousel' +emblaApi.on('slidesInView', logSlidesInView) +``` - function onSlidesInView(emblaApi: EmblaCarouselType): void { - console.log(emblaApi.slidesInView()) - } + + - const emblaApi = EmblaCarousel(emblaNode, { loop: true }) - emblaApi.on('slidesInView', onSlidesInView) - ``` +```tsx highlight={2,8} +import React, { useCallback } from 'react' +import { EmblaCarouselType } from 'embla-carousel' +import useEmblaCarousel from 'embla-carousel-react' - - +export function EmblaCarousel() { + const [emblaRef, emblaApi] = useEmblaCarousel() - ```tsx highlight={2,8} - import React, { useCallback } from 'react' - import { EmblaCarouselType } from 'embla-carousel' - import useEmblaCarousel from 'embla-carousel-react' + const logSlidesInView = useCallback((emblaApi: EmblaCarouselType) => { + console.log(emblaApi.slidesInView()) + }, []) - export function EmblaCarousel() { - const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true }) + useEffect(() => { + if (emblaApi) emblaApi.on('slidesInView', logSlidesInView) + }, [emblaApi, logSlidesInView]) - const onSlidesInView = useCallback((emblaApi: EmblaCarouselType) => { - console.log(emblaApi.slidesInView()) - }, []) + // ... +} +``` - useEffect(() => { - if (!emblaApi) return + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-react` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
+ + +```html highlight={3,8} + +``` - - + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-vue` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
+ - ```html highlight={3,8} - - ``` + // ... +} +``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-solid` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
- - If you're using `pnpm`, you need to install `embla-carousel` as a **devDependency** when importing types from it like demonstrated above. -
- This is because even though `embla-carousel-vue` has `embla-carousel` as a dependency, `pnpm` makes nested dependencies inaccessible by design. -
+
+ + +```html highlight={2,5,7} + + +
...
+``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-svelte` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
-
+
## Reference diff --git a/packages/embla-carousel-docs/src/content/pages/api/options.mdx b/packages/embla-carousel-docs/src/content/pages/api/options.mdx index b910b4fd5..12c99a600 100644 --- a/packages/embla-carousel-docs/src/content/pages/api/options.mdx +++ b/packages/embla-carousel-docs/src/content/pages/api/options.mdx @@ -24,39 +24,68 @@ You can customize Embla with the [constructor options](/api/options/#constructor The constructor options is the default way of providing options to Embla Carousel. In the following example, the carousel [loop](/api/options/#loop) option is set to `true`: - + - ```js highlight={3} - import EmblaCarousel from 'embla-carousel' +```js highlight={4} +import EmblaCarousel from 'embla-carousel' - const emblaApi = EmblaCarousel(emblaNode, { loop: true }) - ``` +const emblaNode = document.querySelector('.embla') +const emblaApi = EmblaCarousel(emblaNode, { loop: true }) +``` - - + + - ```jsx highlight={4} - import useEmblaCarousel from 'embla-carousel-react' +```jsx highlight={4} +import useEmblaCarousel from 'embla-carousel-react' - export function EmblaCarousel() { - const [emblaRef] = useEmblaCarousel({ loop: true }) - // ... - } - ``` +export function EmblaCarousel() { + const [emblaRef] = useEmblaCarousel({ loop: true }) - - + // ... +} +``` - ```html highlight={4} - - ``` +```html highlight={4} + +``` + + + + +```jsx highlight={4} +import createEmblaCarousel from 'embla-carousel-solid' + +export function EmblaCarousel() { + const [emblaRef] = createEmblaCarousel(() => ({ loop: true })) + + // ... +} +``` + + + + +```html highlight={4,7} + + +
...
+``` + +
@@ -70,45 +99,78 @@ The constructor options is the default way of providing options to Embla Carouse Setting **global options** will be applied to **all carousels** which will override the Embla default options with your own. In the following example [loop](/api/options/#loop) is set to `true`: - + + +```js highlight={3} +import EmblaCarousel from 'embla-carousel' + +EmblaCarousel.globalOptions = { loop: true } + +const emblaNode = document.querySelector('.embla') +const emblaApi = EmblaCarousel(emblaNode, { align: 'start' }) +``` + + + - ```js highlight={3} - import EmblaCarousel from 'embla-carousel' +```jsx highlight={3} +import useEmblaCarousel from 'embla-carousel-react' - EmblaCarousel.globalOptions = { loop: true } +useEmblaCarousel.globalOptions = { loop: true } - const emblaApi = EmblaCarousel(emblaNode, { align: 'center' }) - ``` +export function EmblaCarousel() { + const [emblaRef] = useEmblaCarousel({ align: 'start' }) - - + // ... +} +``` - ```jsx highlight={3} - import useEmblaCarousel from 'embla-carousel-react' + + - useEmblaCarousel.globalOptions = { loop: true } +```html highlight={4} + +``` - emblaCarouselVue.globalOptions = { loop: true } + + - const [emblaNode] = emblaCarouselVue({ align: 'center' }) - // ... - - ``` +```jsx highlight={3} +import createEmblaCarousel from 'embla-carousel-solid' - +createEmblaCarousel.globalOptions = { loop: true } + +export function EmblaCarousel() { + const [emblaRef] = createEmblaCarousel(() => ({ align: 'start' })) + + // ... +} +``` + + + + +```html highlight={4} + + +
...
+``` + +
@@ -122,60 +184,115 @@ Setting **global options** will be applied to **all carousels** which will overr The `EmblaOptionsType` is obtained directly from the **core package** `embla-carousel` and used like so: - - - ```ts highlight={1,3} - import EmblaCarousel, { EmblaOptionsType } from 'embla-carousel' - - const options: EmblaOptionsType = { loop: true } - const emblaApi = EmblaCarousel(emblaNode, options) - ``` - - - - - ```tsx highlight={2,6} - import React from 'react' - import { EmblaOptionsType } from 'embla-carousel' - import useEmblaCarousel from 'embla-carousel-react' - - type PropType = { - options?: EmblaOptionsType - } - - export function EmblaCarousel(props: PropType) { - const [emblaRef, emblaApi] = useEmblaCarousel(props.options) - // ... - } - ``` - - - If you're using `pnpm`, you need to install `embla-carousel` as a **devDependency** when importing types from it like demonstrated above. -
- This is because even though `embla-carousel-react` has `embla-carousel` as a dependency, `pnpm` makes nested dependencies inaccessible by design. -
- -
- - - ```html highlight={2,5} - - ``` - - - If you're using `pnpm`, you need to install `embla-carousel` as a **devDependency** when importing types from it like demonstrated above. -
- This is because even though `embla-carousel-vue` has `embla-carousel` as a dependency, `pnpm` makes nested dependencies inaccessible by design. -
- -
+ + +```ts asLanguage=tsx highlight={1,4} +import EmblaCarousel, { EmblaOptionsType } from 'embla-carousel' + +const emblaNode = document.querySelector('.embla') +const options: EmblaOptionsType = { loop: true } +const emblaApi = EmblaCarousel(emblaNode, options) +``` + + + + +```tsx highlight={2,6} +import React from 'react' +import { EmblaOptionsType } from 'embla-carousel' +import useEmblaCarousel from 'embla-carousel-react' + +type PropType = { + options?: EmblaOptionsType +} + +export function EmblaCarousel(props: PropType) { + const [emblaRef, emblaApi] = useEmblaCarousel(props.options) + + // ... +} +``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-react` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
+ + +```html highlight={2,5} + +``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-vue` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
+ + +```tsx highlight={1,5} +import { EmblaOptionsType } from 'embla-carousel' +import createEmblaCarousel from 'embla-carousel-solid' + +type PropType = { + options?: EmblaOptionsType +} + +export function EmblaCarousel(props) { + const [emblaRef] = createEmblaCarousel(() => props.options) + + // ... +} +``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-solid` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
+ + +```html highlight={2,5} + + +
...
+``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-svelte` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
## Reference diff --git a/packages/embla-carousel-docs/src/content/pages/api/plugins.mdx b/packages/embla-carousel-docs/src/content/pages/api/plugins.mdx index bf6bf95e7..9c0a619d5 100644 --- a/packages/embla-carousel-docs/src/content/pages/api/plugins.mdx +++ b/packages/embla-carousel-docs/src/content/pages/api/plugins.mdx @@ -21,27 +21,27 @@ It's possible to **extend** Embla carousel with additional features using **plug All **official plugins** are separate **NPM packages**. They're all **prefixed** with `embla-carousel` followed by its **unique** plugin **name**. For example, the `Autoplay` plugin is installed like so: - + - ```html - - ``` +```html + +``` - - + + - ```shell - npm install embla-carousel-autoplay --save - ``` +```shell +npm install embla-carousel-autoplay --save +``` - - + + - ```shell - yarn add embla-carousel-autoplay - ``` +```shell +yarn add embla-carousel-autoplay +``` - + ## Usage @@ -53,42 +53,76 @@ The Embla Carousel **constructor** accepts an **array of plugins**. Each plugin The constructor plugin array is the default way of providing plugins to Embla Carousel. In the following example, the [Autoplay](/plugins/autoplay/) plugin is added to the carousel: - + - ```js highlight={2,4} - import EmblaCarousel from 'embla-carousel' - import Autoplay from 'embla-carousel-autoplay' +```js highlight={2,5} +import EmblaCarousel from 'embla-carousel' +import Autoplay from 'embla-carousel-autoplay' - const embla = EmblaCarousel(emblaNode, { loop: true }, [Autoplay()]) - ``` +const emblaNode = document.querySelector('.embla') +const embla = EmblaCarousel(emblaNode, { loop: true }, [Autoplay()]) +``` - - + + - ```jsx highlight={2,5} - import useEmblaCarousel from 'embla-carousel-react' - import Autoplay from 'embla-carousel-autoplay' +```jsx highlight={2,5} +import useEmblaCarousel from 'embla-carousel-react' +import Autoplay from 'embla-carousel-autoplay' - export function EmblaCarousel() { - const [emblaRef] = useEmblaCarousel({ loop: true }, [Autoplay()]) - // ... - } - ``` +export function EmblaCarousel() { + const [emblaRef] = useEmblaCarousel({ loop: true }, [Autoplay()]) - - + // ... +} +``` - ```html highlight={3,5} - - ``` +```html highlight={3,5} + +``` + + + + +```jsx highlight={2,7} +import createEmblaCarousel from 'embla-carousel-solid' +import Autoplay from 'embla-carousel-autoplay' + +export function EmblaCarousel() { + const [emblaRef] = createEmblaCarousel( + () => ({ loop: true }), + () => [AutoPlay()] + ) + + // ... +} +``` + + + + +```html highlight={3,5,8} + + +
...
+``` + +
@@ -102,48 +136,82 @@ The constructor plugin array is the default way of providing plugins to Embla Ca Plugins have their own specific **options** which is the first argument of the plugin constructor. This allows for configuring the plugin to your liking: - - - ```js highlight={5} - import EmblaCarousel from 'embla-carousel' - import Autoplay from 'embla-carousel-autoplay' - - const embla = EmblaCarousel(emblaNode, { loop: true }, [ - Autoplay({ delay: 4000 }) - ]) - ``` - - - - - ```jsx highlight={6} - import useEmblaCarousel from 'embla-carousel-react' - import Autoplay from 'embla-carousel-autoplay' - - export function EmblaCarousel() { - const [emblaRef] = useEmblaCarousel({ loop: true }, [ - Autoplay({ delay: 4000 }) - ]) - // ... - } - ``` - - - - - ```html highlight={6} - - ``` - - + + +```js highlight={6} +import EmblaCarousel from 'embla-carousel' +import Autoplay from 'embla-carousel-autoplay' + +const emblaNode = document.querySelector('.embla') +const embla = EmblaCarousel(emblaNode, { loop: true }, [ + Autoplay({ delay: 4000 }) +]) +``` + + + + +```jsx highlight={6} +import useEmblaCarousel from 'embla-carousel-react' +import Autoplay from 'embla-carousel-autoplay' + +export function EmblaCarousel() { + const [emblaRef] = useEmblaCarousel({ loop: true }, [ + Autoplay({ delay: 4000 }) + ]) + + // ... +} +``` + + + + +```html highlight={6} + +``` + + + + +```jsx highlight={7} +import createEmblaCarousel from 'embla-carousel-solid' +import Autoplay from 'embla-carousel-autoplay' + +export function EmblaCarousel() { + const [emblaRef] = createEmblaCarousel( + () => ({ loop: true }), + () => [AutoPlay({ delay: 4000 })] + ) + + // ... +} +``` + + + + +```html highlight={5} + + +
...
+``` + +
### Global options @@ -151,48 +219,86 @@ Plugins have their own specific **options** which is the first argument of the p All [official plugins](/plugins/) allows you to set **global options** that will be applied to all instances. This allows for overriding the default plugin options with your own: - + + +```js highlight={4} +import EmblaCarousel from 'embla-carousel' +import Autoplay from 'embla-carousel-autoplay' + +Autoplay.globalOptions = { delay: 4000 } + +const emblaNode = document.querySelector('.embla') +const embla = EmblaCarousel(emblaNode, { loop: true }, [Autoplay()]) +``` + + + + +```jsx highlight={4} +import useEmblaCarousel from 'embla-carousel-react' +import Autoplay from 'embla-carousel-autoplay' + +Autoplay.globalOptions = { delay: 4000 } + +export function EmblaCarousel() { + const [emblaRef] = useEmblaCarousel({ loop: true }, [Autoplay()]) - ```js highlight={4} - import EmblaCarousel from 'embla-carousel' - import Autoplay from 'embla-carousel-autoplay' + // ... +} +``` - Autoplay.globalOptions = { delay: 4000 } + + - const embla = EmblaCarousel(emblaNode, { loop: true }, [Autoplay()]) - ``` +```html highlight={5} + +``` - export function EmblaCarousel() { - const [emblaRef] = useEmblaCarousel({ loop: true }, [Autoplay()]) - // ... - } - ``` + + - - +```jsx highlight={4} +import createEmblaCarousel from 'embla-carousel-solid' +import Autoplay from 'embla-carousel-autoplay' - ```html highlight={5} - - ``` + // ... +} +``` - + + + +```html highlight={5} + + +
...
+``` + +
@@ -206,58 +312,107 @@ All [official plugins](/plugins/) allows you to set **global options** that will Additionally, some plugins expose their own **API methods**. You can access plugin methods by calling the [plugin](/api/methods/#plugins) method like demonstrated below: - + - ```js highlight={6} - import EmblaCarousel from 'embla-carousel' - import Autoplay from 'embla-carousel-autoplay' +```js highlight={7} +import EmblaCarousel from 'embla-carousel' +import Autoplay from 'embla-carousel-autoplay' - const emblaApi = EmblaCarousel(emblaNode, { loop: true }, [Autoplay()]) +const emblaNode = document.querySelector('.embla') +const emblaApi = EmblaCarousel(emblaNode, { loop: true }, [Autoplay()]) - emblaApi.plugins().autoplay.stop() - ``` +emblaApi.plugins().autoplay.stop() +``` + + + + +```jsx highlight={9} +import { useEffect } from 'react' +import useEmblaCarousel from 'embla-carousel-react' +import Autoplay from 'embla-carousel-autoplay' + +export function EmblaCarousel() { + const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true }, [Autoplay()]) + + useEffect(() => { + if (emblaApi) emblaApi.plugins().autoplay.stop() + }, [emblaApi]) + + // ... +} +``` + + + - - +```html highlight={9} + +``` - // ... - } - ``` + - - + - ```html highlight={11} - - ``` + // ... +} +``` - + + + +```html highlight={10} + + +
+ ... +
+``` + +
### Adding event listeners @@ -265,74 +420,126 @@ Additionally, some plugins expose their own **API methods**. You can access plug Some plugins fire their own **events**. Plugin events are structured as follows `:eventname`. [Adding](/api/events/#adding-event-listeners) and [removing](/api/events/#removing-event-listeners) plugin event listeners is done the same way as native Embla events. Here's an example where an event is added to the autoplay plugin: - + - ```js highlight={10} - import EmblaCarousel from 'embla-carousel' - import Autoplay from 'embla-carousel-autoplay' +```js highlight={11} +import EmblaCarousel from 'embla-carousel' +import Autoplay from 'embla-carousel-autoplay' - const emblaApi = EmblaCarousel(emblaNode, { loop: true }, [Autoplay()]) +const emblaNode = document.querySelector('.embla') +const emblaApi = EmblaCarousel(emblaNode, { loop: true }, [Autoplay()]) - function logPluginEvent(emblaApi, eventName) { - console.log('Autoplay plugin stopped playing!') - } +function logPluginEvent(emblaApi, eventName) { + console.log(`Autoplay just triggered ${eventName}!`) +} - emblaApi.on('autoplay:stop', logPluginEvent) - ``` +emblaApi.on('autoplay:stop', logPluginEvent) +``` + + + + +```jsx highlight={13} +import { useEffect, useCallback } from 'react' +import useEmblaCarousel from 'embla-carousel-react' +import Autoplay from 'embla-carousel-autoplay' + +export function EmblaCarousel() { + const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true }, [Autoplay()]) + + const logPluginEvent = useCallback((emblaApi, eventName) => { + console.log(`Autoplay just triggered ${eventName}!`) + }, []) + + useEffect(() => { + if (emblaApi) emblaApi.on('autoplay:stop', logPluginEvent) + }, [emblaApi, logPluginEvent]) + + // ... +} +``` + + + - - +```html highlight={13} + +``` - emblaApi.on('autoplay:stop', logAutoplayStopEvent) // add - }, [emblaApi, logAutoplayStopEvent]) + + - // ... - } - ``` +```jsx highlight={17} +import { createEffect } from 'solid-js' +import createEmblaCarousel from 'embla-carousel-solid' +import Autoplay from 'embla-carousel-autoplay' - - +export function EmblaCarousel() { + const [emblaRef, emblaApi] = createEmblaCarousel( + () => ({ loop: true }), + () => [AutoPlay()] + ) - ```html highlight={16} - - ``` +```html highlight={14} + + +
+ ... +
+``` + +
### TypeScript @@ -340,65 +547,122 @@ Some plugins fire their own **events**. Plugin events are structured as follows The `EmblaPluginType` is obtained directly from the **core package** `embla-carousel` and used like so: - - - ```ts highlight={3,8} - import EmblaCarousel, { - EmblaOptionsType, - EmblaPluginType - } from 'embla-carousel' - import Autoplay from 'embla-carousel-autoplay' - - const options: EmblaOptionsType = { loop: true } - const plugins: EmblaPluginType[] = [Autoplay()] - const emblaApi = EmblaCarousel(emblaNode, options, plugins) - ``` - - - - - ```tsx highlight={2,7} - import React from 'react' - import { EmblaOptionsType, EmblaPluginType } from 'embla-carousel' - import useEmblaCarousel from 'embla-carousel-react' - import Autoplay from 'embla-carousel-autoplay' - - const options: EmblaOptionsType = { loop: true } - const plugins: EmblaPluginType[] = [Autoplay()] - - export function EmblaCarousel() { - const [emblaRef, emblaApi] = useEmblaCarousel(options, plugins) - // ... - } - ``` - - - If you're using `pnpm`, you need to install `embla-carousel` as a **devDependency** when importing types from it like demonstrated above. -
- This is because even though `embla-carousel-react` has `embla-carousel` as a dependency, `pnpm` makes nested dependencies inaccessible by design. -
- -
- - - ```html highlight={2,7} - - ``` - - - If you're using `pnpm`, you need to install `embla-carousel` as a **devDependency** when importing types from it like demonstrated above. -
- This is because even though `embla-carousel-vue` has `embla-carousel` as a dependency, `pnpm` makes nested dependencies inaccessible by design. -
- -
+ + +```ts asLanguage=tsx highlight={1,5} +import EmblaCarousel, { EmblaPluginType } from 'embla-carousel' +import Autoplay from 'embla-carousel-autoplay' + +const emblaNode = document.querySelector('.embla') +const plugins: EmblaPluginType[] = [Autoplay()] +const emblaApi = EmblaCarousel(emblaNode, { loop: true }, plugins) +``` + + + + +```tsx highlight={2,7} +import React from 'react' +import { EmblaPluginType } from 'embla-carousel' +import useEmblaCarousel from 'embla-carousel-react' +import Autoplay from 'embla-carousel-autoplay' + +type PropType = { + plugins?: EmblaPluginType[] +} + +export function EmblaCarousel(props) { + const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true }, props.plugins) + + // ... +} +``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-react` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
+ + +```html highlight={2,6} + +``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-vue` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
+ + +```tsx highlight={1,6} +import { EmblaPluginType } from 'embla-carousel' +import createEmblaCarousel from 'embla-carousel-solid' +import Autoplay from 'embla-carousel-autoplay' + +type PropType = { + plugins?: EmblaPluginType[] +} + +export function EmblaCarousel(props) { + const [emblaRef, emblaApi] = createEmblaCarousel( + () => ({ loop: true }), + props.plugins + ) + + // ... +} +``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-solid` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
+ + +```html highlight={2,7} + + +
...
+``` + + + If you're using `pnpm`, you need to install `embla-carousel` as a + **devDependency** when importing types from it like demonstrated above. +
+ This is because even though `embla-carousel-svelte` has `embla-carousel` as a + dependency, `pnpm` makes nested dependencies inaccessible by design. +
+ +
diff --git a/packages/embla-carousel-docs/src/content/pages/get-started/cdn.mdx b/packages/embla-carousel-docs/src/content/pages/get-started/cdn.mdx index ac520abf2..fc6f77213 100644 --- a/packages/embla-carousel-docs/src/content/pages/get-started/cdn.mdx +++ b/packages/embla-carousel-docs/src/content/pages/get-started/cdn.mdx @@ -52,9 +52,9 @@ Grab the element with the classname `embla` and pass it as the first argument to ```html highlight={6} @@ -73,10 +73,10 @@ Plugins included from a CDN will be **prefixed** with **EmblaCarousel**. Here's ```html highlight={4-5} ``` diff --git a/packages/embla-carousel-docs/src/content/pages/get-started/module.mdx b/packages/embla-carousel-docs/src/content/pages/get-started/module.mdx index 46689dbe6..ff3ed2c7a 100644 --- a/packages/embla-carousel-docs/src/content/pages/get-started/module.mdx +++ b/packages/embla-carousel-docs/src/content/pages/get-started/module.mdx @@ -16,16 +16,16 @@ Start by installing the **npm package** and save it to your dependencies: - ```shell - npm install embla-carousel --save - ``` +```shell +npm install embla-carousel --save +``` - ```shell - yarn add embla-carousel - ``` +```shell +yarn add embla-carousel +``` @@ -84,16 +84,16 @@ Start by installing the plugin you want to use. In this example, we're going to - ```shell - npm install embla-carousel-autoplay --save - ``` +```shell +npm install embla-carousel-autoplay --save +``` - ```shell - yarn add embla-carousel-autoplay - ``` +```shell +yarn add embla-carousel-autoplay +``` diff --git a/packages/embla-carousel-docs/src/content/pages/get-started/react.mdx b/packages/embla-carousel-docs/src/content/pages/get-started/react.mdx index 0c2040072..deadd088f 100644 --- a/packages/embla-carousel-docs/src/content/pages/get-started/react.mdx +++ b/packages/embla-carousel-docs/src/content/pages/get-started/react.mdx @@ -16,16 +16,16 @@ Start by installing the Embla Carousel **npm package** and add it to your depend - ```shell - npm install embla-carousel-react --save - ``` +```shell +npm install embla-carousel-react --save +``` - ```shell - yarn add embla-carousel-react - ``` +```shell +yarn add embla-carousel-react +``` @@ -108,16 +108,16 @@ Start by installing the plugin you want to use. In this example, we're going to - ```shell - npm install embla-carousel-autoplay --save - ``` +```shell +npm install embla-carousel-autoplay --save +``` - ```shell - yarn add embla-carousel-autoplay - ``` +```shell +yarn add embla-carousel-autoplay +``` diff --git a/packages/embla-carousel-docs/src/content/pages/get-started/solid.mdx b/packages/embla-carousel-docs/src/content/pages/get-started/solid.mdx index 4aef8126a..c46dd1261 100644 --- a/packages/embla-carousel-docs/src/content/pages/get-started/solid.mdx +++ b/packages/embla-carousel-docs/src/content/pages/get-started/solid.mdx @@ -16,16 +16,16 @@ Start by installing the Embla Carousel **npm package** and add it to your depend - ```shell - npm install embla-carousel-solid --save - ``` +```shell +npm install embla-carousel-solid --save +``` - ```shell - yarn add embla-carousel-solid - ``` +```shell +yarn add embla-carousel-solid +``` @@ -39,7 +39,7 @@ Embla Carousel provides the handy `createEmblaCarousel` method for seamless inte ```jsx import createEmblaCarousel from 'embla-carousel-solid' -export const EmblaCarousel = () => { +export function EmblaCarousel() { const [emblaRef] = createEmblaCarousel() return ( @@ -79,7 +79,7 @@ The `createEmblaCarousel` method takes the Embla Carousel [options](/api/options import { createEffect } from 'solid-js' import createEmblaCarousel from 'embla-carousel-solid' -export const EmblaCarousel = () => { +export function EmblaCarousel() { const [emblaRef, emblaApi] = createEmblaCarousel(() => ({ loop: true })) createEffect(() => { @@ -108,16 +108,16 @@ Start by installing the plugin you want to use. In this example, we're going to - ```shell - npm install embla-carousel-autoplay --save - ``` +```shell +npm install embla-carousel-autoplay --save +``` - ```shell - yarn add embla-carousel-autoplay - ``` +```shell +yarn add embla-carousel-autoplay +``` @@ -128,7 +128,7 @@ The `createEmblaCarousel` method accepts [plugins](/plugins/) as the second argu import createEmblaCarousel from 'embla-carousel-solid' import Autoplay from 'embla-carousel-autoplay' -export const EmblaCarousel = () => { +export function EmblaCarousel() { const [emblaRef] = createEmblaCarousel( () => ({ loop: true }), () => [AutoPlay()] diff --git a/packages/embla-carousel-docs/src/content/pages/get-started/svelte.mdx b/packages/embla-carousel-docs/src/content/pages/get-started/svelte.mdx index fa79aa844..6a300d484 100644 --- a/packages/embla-carousel-docs/src/content/pages/get-started/svelte.mdx +++ b/packages/embla-carousel-docs/src/content/pages/get-started/svelte.mdx @@ -16,16 +16,16 @@ Start by installing the Embla Carousel **npm package** and add it to your depend - ```shell - npm install embla-carousel-svelte --save - ``` +```shell +npm install embla-carousel-svelte --save +``` - ```shell - yarn add embla-carousel-svelte - ``` +```shell +yarn add embla-carousel-svelte +``` @@ -80,7 +80,7 @@ The `emblaCarouselSvelte` action takes the Embla Carousel [options](/api/options let emblaApi let options = { loop: false } - const onInit = (event) => { + function onInit(event) { emblaApi = event.detail console.log(emblaApi.slideNodes()) // Access API } @@ -106,16 +106,16 @@ Start by installing the plugin you want to use. In this example, we're going to - ```shell - npm install embla-carousel-autoplay --save - ``` +```shell +npm install embla-carousel-autoplay --save +``` - ```shell - yarn add embla-carousel-autoplay - ``` +```shell +yarn add embla-carousel-autoplay +``` diff --git a/packages/embla-carousel-docs/src/content/pages/get-started/vue.mdx b/packages/embla-carousel-docs/src/content/pages/get-started/vue.mdx index df160b5b4..b34981637 100644 --- a/packages/embla-carousel-docs/src/content/pages/get-started/vue.mdx +++ b/packages/embla-carousel-docs/src/content/pages/get-started/vue.mdx @@ -40,11 +40,11 @@ Embla Carousel provides the handy `emblaCarouselVue` function for seamless integ