@deriv-com/dds-marketing 0.2.0 → 1.0.1
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/.llm/components/accordion.md +9 -1
- package/.llm/components/accordionitem.md +9 -1
- package/.llm/components/aspectratio.md +9 -1
- package/.llm/components/badge.md +9 -1
- package/.llm/components/bottomsheet.md +9 -1
- package/.llm/components/breadcrumb.md +9 -1
- package/.llm/components/breadcrumbitem.md +9 -1
- package/.llm/components/button.md +55 -27
- package/.llm/components/buttonicon.md +16 -8
- package/.llm/components/card.md +16 -2
- package/.llm/components/cardbody.md +29 -3
- package/.llm/components/cardbutton.md +16 -2
- package/.llm/components/checkbox.md +9 -1
- package/.llm/components/ctabanner.md +186 -0
- package/.llm/components/ctabannerslider.md +204 -0
- package/.llm/components/divider.md +9 -1
- package/.llm/components/dropdownmenu.md +15 -7
- package/.llm/components/faqaccordion.md +217 -0
- package/.llm/components/featurebullets.md +254 -0
- package/.llm/components/featurecards.md +313 -0
- package/.llm/components/featurescroll.md +284 -0
- package/.llm/components/featuresplit.md +249 -0
- package/.llm/components/filterchip.md +9 -1
- package/.llm/components/footer.md +9 -1
- package/.llm/components/footergroup.md +9 -1
- package/.llm/components/grid.md +9 -1
- package/.llm/components/icon.md +21 -3
- package/.llm/components/landinghero.md +254 -0
- package/.llm/components/link.md +13 -5
- package/.llm/components/logocolumns.md +235 -0
- package/.llm/components/logorows.md +212 -0
- package/.llm/components/menuitem.md +9 -1
- package/.llm/components/navbar.md +80 -16
- package/.llm/components/navbaritem.md +10 -2
- package/.llm/components/navbarmenu.md +9 -1
- package/.llm/components/navbarmenugroup.md +9 -1
- package/.llm/components/navbarpanel.md +10 -2
- package/.llm/components/navbarswitcher.md +10 -2
- package/.llm/components/navbarswitcheroption.md +9 -1
- package/.llm/components/option.md +9 -1
- package/.llm/components/pageheader.md +231 -0
- package/.llm/components/pagination.md +27 -90
- package/.llm/components/paginationdots.md +215 -0
- package/.llm/components/producthero.md +248 -0
- package/.llm/components/removablechip.md +9 -1
- package/.llm/components/row.md +9 -1
- package/.llm/components/scroller.md +9 -1
- package/.llm/components/searchinput.md +9 -1
- package/.llm/components/segmentedcontrol.md +9 -1
- package/.llm/components/segmentedcontrolitem.md +9 -1
- package/.llm/components/select.md +9 -1
- package/.llm/components/selectchip.md +57 -16
- package/.llm/components/spinner.md +9 -1
- package/.llm/components/stack.md +9 -1
- package/.llm/components/statusdot.md +9 -1
- package/.llm/components/subdomainnavbar.md +9 -1
- package/.llm/components/tab.md +11 -3
- package/.llm/components/table.md +9 -1
- package/.llm/components/tablebody.md +9 -1
- package/.llm/components/tablecell.md +9 -1
- package/.llm/components/tablehead.md +9 -1
- package/.llm/components/tableheadercell.md +9 -1
- package/.llm/components/tablerow.md +9 -1
- package/.llm/components/tablist.md +9 -1
- package/.llm/components/testimonialrow.md +235 -0
- package/.llm/components/testimonialslider.md +254 -0
- package/.llm/components/textarea.md +9 -1
- package/.llm/components/textinput.md +9 -1
- package/.llm/components/tooltip.md +9 -1
- package/.llm/components/typography.md +9 -1
- package/.llm/digest/button.md +11 -6
- package/.llm/digest/buttonicon.md +2 -2
- package/.llm/digest/card.md +1 -0
- package/.llm/digest/cardbody.md +3 -1
- package/.llm/digest/cardbutton.md +1 -0
- package/.llm/digest/ctabanner.md +44 -0
- package/.llm/digest/ctabannerslider.md +45 -0
- package/.llm/digest/dropdownmenu.md +1 -1
- package/.llm/digest/faqaccordion.md +43 -0
- package/.llm/digest/featurebullets.md +52 -0
- package/.llm/digest/featurecards.md +49 -0
- package/.llm/digest/featurescroll.md +52 -0
- package/.llm/digest/featuresplit.md +54 -0
- package/.llm/digest/landinghero.md +53 -0
- package/.llm/digest/logocolumns.md +55 -0
- package/.llm/digest/logorows.md +48 -0
- package/.llm/digest/navbar.md +18 -3
- package/.llm/digest/pageheader.md +49 -0
- package/.llm/digest/pagination.md +6 -17
- package/.llm/digest/paginationdots.md +43 -0
- package/.llm/digest/producthero.md +53 -0
- package/.llm/digest/selectchip.md +6 -1
- package/.llm/digest/testimonialrow.md +51 -0
- package/.llm/digest/testimonialslider.md +51 -0
- package/.llm/index.md +24 -3
- package/.llm/rules.md +43 -9
- package/.llm/tokens.md +56 -12
- package/AGENTS.md +32 -8
- package/README.md +41 -21
- package/dist/components/banner-data.d.ts +38 -0
- package/dist/components/banner-data.js +15 -0
- package/dist/components/blocks/block-reveal.css +90 -0
- package/dist/components/blocks/cta-banner/CtaBanner.css +66 -0
- package/dist/components/blocks/cta-banner/CtaBanner.d.ts +22 -0
- package/dist/components/blocks/cta-banner/CtaBanner.js +31 -0
- package/dist/components/blocks/cta-banner/CtaBanner.types.d.ts +29 -0
- package/dist/components/blocks/cta-banner/CtaBanner.types.js +13 -0
- package/dist/components/blocks/cta-banner/cta-banner-impl.css +29 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.css +90 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.d.ts +39 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.js +60 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.d.ts +41 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.js +15 -0
- package/dist/components/blocks/cta-banner-slider/cta-banner-slider-impl.css +73 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.css +54 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.d.ts +20 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.js +28 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.types.d.ts +25 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.types.js +10 -0
- package/dist/components/blocks/faq-accordion/faq-accordion-impl.css +54 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.css +139 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.d.ts +31 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.js +55 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.types.d.ts +39 -0
- package/dist/components/blocks/feature-bullets/FeatureBullets.types.js +16 -0
- package/dist/components/blocks/feature-bullets/feature-bullets-impl.css +104 -0
- package/dist/components/blocks/feature-cards/FeatureCards.css +84 -0
- package/dist/components/blocks/feature-cards/FeatureCards.d.ts +24 -0
- package/dist/components/blocks/feature-cards/FeatureCards.js +66 -0
- package/dist/components/blocks/feature-cards/FeatureCards.types.d.ts +33 -0
- package/dist/components/blocks/feature-cards/FeatureCards.types.js +14 -0
- package/dist/components/blocks/feature-cards/feature-cards-impl.css +245 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.css +137 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.d.ts +39 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.js +167 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.types.d.ts +40 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.types.js +17 -0
- package/dist/components/blocks/feature-scroll/feature-scroll-impl.css +292 -0
- package/dist/components/blocks/feature-split/FeatureSplit.css +95 -0
- package/dist/components/blocks/feature-split/FeatureSplit.d.ts +30 -0
- package/dist/components/blocks/feature-split/FeatureSplit.js +38 -0
- package/dist/components/blocks/feature-split/FeatureSplit.types.d.ts +39 -0
- package/dist/components/blocks/feature-split/FeatureSplit.types.js +14 -0
- package/dist/components/blocks/feature-split/feature-split-impl.css +83 -0
- package/dist/components/blocks/landing-hero/LandingHero.css +85 -0
- package/dist/components/blocks/landing-hero/LandingHero.d.ts +41 -0
- package/dist/components/blocks/landing-hero/LandingHero.js +54 -0
- package/dist/components/blocks/landing-hero/LandingHero.types.d.ts +37 -0
- package/dist/components/blocks/landing-hero/LandingHero.types.js +15 -0
- package/dist/components/blocks/landing-hero/landing-hero-impl.css +355 -0
- package/dist/components/blocks/logo-columns/LogoColumns.css +161 -0
- package/dist/components/blocks/logo-columns/LogoColumns.d.ts +23 -0
- package/dist/components/blocks/logo-columns/LogoColumns.js +46 -0
- package/dist/components/blocks/logo-columns/LogoColumns.types.d.ts +46 -0
- package/dist/components/blocks/logo-columns/LogoColumns.types.js +18 -0
- package/dist/components/blocks/logo-columns/logo-columns-impl.css +188 -0
- package/dist/components/blocks/logo-rows/LogoRows.css +122 -0
- package/dist/components/blocks/logo-rows/LogoRows.d.ts +20 -0
- package/dist/components/blocks/logo-rows/LogoRows.js +43 -0
- package/dist/components/blocks/logo-rows/LogoRows.types.d.ts +36 -0
- package/dist/components/blocks/logo-rows/LogoRows.types.js +16 -0
- package/dist/components/blocks/logo-rows/logo-rows-impl.css +179 -0
- package/dist/components/blocks/page-header/PageHeader.css +79 -0
- package/dist/components/blocks/page-header/PageHeader.d.ts +34 -0
- package/dist/components/blocks/page-header/PageHeader.js +43 -0
- package/dist/components/blocks/page-header/PageHeader.types.d.ts +32 -0
- package/dist/components/blocks/page-header/PageHeader.types.js +14 -0
- package/dist/components/blocks/page-header/page-header-impl.css +176 -0
- package/dist/components/blocks/product-hero/ProductHero.css +86 -0
- package/dist/components/blocks/product-hero/ProductHero.d.ts +35 -0
- package/dist/components/blocks/product-hero/ProductHero.js +48 -0
- package/dist/components/blocks/product-hero/ProductHero.types.d.ts +37 -0
- package/dist/components/blocks/product-hero/ProductHero.types.js +15 -0
- package/dist/components/blocks/product-hero/product-hero-impl.css +354 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.css +245 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.d.ts +20 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.js +128 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.d.ts +54 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.js +26 -0
- package/dist/components/blocks/testimonial-row/testimonial-row-impl.css +195 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.css +181 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.d.ts +22 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.js +36 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.d.ts +49 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.js +21 -0
- package/dist/components/blocks/testimonial-slider/testimonial-slider-impl.css +202 -0
- package/dist/components/blocks/use-reveal.d.ts +46 -0
- package/dist/components/blocks/use-reveal.js +120 -0
- package/dist/components/blocks/use-rotation.d.ts +62 -0
- package/dist/components/blocks/use-rotation.js +176 -0
- package/dist/components/core/accordion-item/AccordionItem.css +6 -5
- package/dist/components/core/bottom-sheet/BottomSheet.css +1 -1
- package/dist/components/core/button/Button.css +63 -16
- package/dist/components/core/button/Button.d.ts +14 -12
- package/dist/components/core/button/Button.js +43 -14
- package/dist/components/core/button/Button.types.d.ts +9 -14
- package/dist/components/core/button/button-impl.css +25 -0
- package/dist/components/core/button-icon/ButtonIcon.css +31 -15
- package/dist/components/core/button-icon/ButtonIcon.d.ts +2 -2
- package/dist/components/core/button-icon/ButtonIcon.js +2 -2
- package/dist/components/core/button-icon/ButtonIcon.types.d.ts +4 -4
- package/dist/components/core/card/Card.css +13 -4
- package/dist/components/core/card/Card.types.d.ts +2 -1
- package/dist/components/core/card-body/CardBody.css +11 -6
- package/dist/components/core/card-body/CardBody.d.ts +1 -1
- package/dist/components/core/card-body/CardBody.js +2 -2
- package/dist/components/core/card-body/CardBody.types.d.ts +4 -1
- package/dist/components/core/card-body/CardBody.types.js +1 -0
- package/dist/components/core/card-button/CardButton.css +13 -4
- package/dist/components/core/card-button/CardButton.types.d.ts +2 -1
- package/dist/components/core/checkbox/Checkbox.css +8 -1
- package/dist/components/core/dropdown-menu/DropdownMenu.css +13 -12
- package/dist/components/core/dropdown-menu/DropdownMenu.d.ts +5 -3
- package/dist/components/core/dropdown-menu/DropdownMenu.js +5 -3
- package/dist/components/core/filter-chip/FilterChip.css +2 -1
- package/dist/components/core/footer/footer-impl.css +1 -1
- package/dist/components/core/footer-group/FooterGroup.css +8 -7
- package/dist/components/core/icon/Icon.css +1 -1
- package/dist/components/core/link/Link.css +1 -1
- package/dist/components/core/link/Link.js +5 -5
- package/dist/components/core/menu-item/MenuItem.css +1 -1
- package/dist/components/core/navbar/Navbar.css +7 -8
- package/dist/components/core/navbar/Navbar.d.ts +17 -1
- package/dist/components/core/navbar/Navbar.js +139 -12
- package/dist/components/core/navbar/Navbar.types.d.ts +23 -4
- package/dist/components/core/navbar/Navbar.types.js +1 -1
- package/dist/components/core/navbar/navbar-impl.css +10 -3
- package/dist/components/core/navbar/navbar-material.css +96 -0
- package/dist/components/core/navbar-item/NavbarItem.css +4 -4
- package/dist/components/core/navbar-menu/NavbarMenu.css +7 -5
- package/dist/components/core/navbar-menu/NavbarMenu.d.ts +1 -0
- package/dist/components/core/navbar-menu/NavbarMenu.js +1 -0
- package/dist/components/core/navbar-menu/navbar-menu-impl.css +7 -7
- package/dist/components/core/navbar-switcher/NavbarSwitcher.css +6 -5
- package/dist/components/core/navbar-switcher/NavbarSwitcher.d.ts +1 -0
- package/dist/components/core/navbar-switcher/NavbarSwitcher.js +2 -1
- package/dist/components/core/option/Option.css +1 -1
- package/dist/components/core/pagination/Pagination.css +1 -75
- package/dist/components/core/pagination/Pagination.d.ts +4 -4
- package/dist/components/core/pagination/Pagination.js +11 -51
- package/dist/components/core/pagination/Pagination.types.d.ts +5 -17
- package/dist/components/core/pagination/Pagination.types.js +1 -3
- package/dist/components/core/pagination-dots/PaginationDots.css +60 -0
- package/dist/components/core/pagination-dots/PaginationDots.d.ts +25 -0
- package/dist/components/core/pagination-dots/PaginationDots.js +104 -0
- package/dist/components/core/pagination-dots/PaginationDots.types.d.ts +38 -0
- package/dist/components/core/pagination-dots/PaginationDots.types.js +9 -0
- package/dist/components/core/removable-chip/RemovableChip.css +3 -3
- package/dist/components/core/search-input/SearchInput.css +1 -1
- package/dist/components/core/segmented-control/SegmentedControl.css +1 -1
- package/dist/components/core/segmented-control-item/SegmentedControlItem.css +1 -1
- package/dist/components/core/select/Select.css +2 -1
- package/dist/components/core/select-chip/SelectChip.css +14 -7
- package/dist/components/core/select-chip/SelectChip.d.ts +1 -1
- package/dist/components/core/select-chip/SelectChip.js +7 -4
- package/dist/components/core/select-chip/SelectChip.types.d.ts +7 -1
- package/dist/components/core/select-chip/SelectChip.types.js +1 -1
- package/dist/components/core/select-chip/select-chip-impl.css +14 -3
- package/dist/components/core/status-dot/StatusDot.css +1 -1
- package/dist/components/core/subdomain-navbar/SubdomainNavbar.css +3 -3
- package/dist/components/core/tab/Tab.css +1 -1
- package/dist/components/core/tab/Tab.types.d.ts +1 -1
- package/dist/components/core/tab-list/TabList.css +1 -1
- package/dist/components/core/table/table-impl.css +36 -14
- package/dist/components/core/table-header-cell/TableHeaderCell.css +5 -5
- package/dist/components/core/text-area/TextArea.css +1 -1
- package/dist/components/core/text-input/TextInput.css +1 -1
- package/dist/components/core/tooltip/Tooltip.css +1 -1
- package/dist/components/core/typography/Typography.css +5 -5
- package/dist/components/index.d.ts +35 -0
- package/dist/components/index.js +30 -0
- package/dist/components/logo-data.d.ts +24 -0
- package/dist/components/logo-data.js +11 -0
- package/dist/components/scroll-data.d.ts +64 -0
- package/dist/components/scroll-data.js +17 -0
- package/dist/components/testimonial-row-data.d.ts +51 -0
- package/dist/components/testimonial-row-data.js +11 -0
- package/dist/components/testimonial-slider-data.d.ts +26 -0
- package/dist/components/testimonial-slider-data.js +10 -0
- package/dist/marketing.css +385 -14
- package/package.json +1 -6
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { TestimonialSliderQuote } from '../../testimonial-slider-data.js';
|
|
2
|
+
export interface TestimonialSliderOwnProps {
|
|
3
|
+
/**
|
|
4
|
+
* `page` — The default, and the page's own white. The card is the recessed gray that sets it off
|
|
5
|
+
* `subtle` — The grey band, the reference design's ground for this section. The card turns white on it. Painted as the band's tint laid over the page's own ground, so it is the same grey whatever is behind the section
|
|
6
|
+
* `strong` — `color.bg.brand-strong`, the dark band, for a section a reader should arrive at. The heading and the quote turn white and the card takes color.bg.surface-card-strong — gray.900 in both themes, the colour a page card takes in dark mode, and TestimonialRow's card on the same band — so the band reads as a dark-mode section in either theme. The coral dots sit on it
|
|
7
|
+
*/
|
|
8
|
+
ground?: 'page' | 'subtle' | 'strong';
|
|
9
|
+
/** Always. Whose words these are, in a few — "What our partners say", "What our customers say". */
|
|
10
|
+
title: string;
|
|
11
|
+
/** Always. The quotes, in the order they rotate — two to five, each a few sentences, each with the name of who said it. An empty list draws nothing; one quote is drawn still, with no dots. */
|
|
12
|
+
quotes: TestimonialSliderQuote[];
|
|
13
|
+
/** A decorative picture, laid over the card's top start corner — a photograph, a product screen, any small piece of art, usually a PNG — as a path or a URL. It is drawn as it is, with rounded corners and no frame, so a transparent ground shows the card through it. Drawn square and cropped to fill its square, so a picture whose subject sits in its middle crops best. It runs up behind the card's top edge, so the edge cuts straight across it, set in from the side, stays put while the quotes rotate, and drifts down by motion.distance.drift as the section passes through the view. The one shown on a phone, where it moves to the top end corner above the quote and drifts half as far, so more of it shows. Decorative: it takes an empty alt and is hidden from assistive technology. */
|
|
14
|
+
imageStart?: string;
|
|
15
|
+
/** A decorative picture at the card's bottom end corner, the pair to imageStart: drawn the same way behind the card's bottom edge, and drifting up as the other drifts down, so the two read as depth. Drawn from the fold only: a phone has room for one, and it is the opening one. Decorative, as imageStart is. */
|
|
16
|
+
imageEnd?: string;
|
|
17
|
+
/** Whether it advances on its own, holding each slide for motion.duration.dwell. Off by default, so a slider nobody configured stays still. On, it holds while the pointer is over it or focus is inside it, never moves for a reader who asked for less motion, and stops for good once the reader presses anything in it — a slide, its action, a dot — or swipes it. A press stops it for good — the WAI carousel pattern's rule that a reader who has interacted is reading, not watching. That gives a reader a way to stop the rotation, which WCAG 2.2.2 asks for, but not a visible one: nothing says a press will stop it, so a page that needs 2.2.2 met plainly should still offer its own pause, or leave autoplay off. */
|
|
18
|
+
autoplay?: boolean;
|
|
19
|
+
/** The name the dots are announced by. Its own name rather than the section's, so a screen reader moving into the dots hears what they are. Translate it with the page. */
|
|
20
|
+
controlsLabel?: string;
|
|
21
|
+
/** The word each dot is announced by, before its number — 'Slide 2'. Translate it with the page, as controlsLabel is; a page that translates only the group's name still has every dot announced in English. */
|
|
22
|
+
slideLabel?: string;
|
|
23
|
+
}
|
|
24
|
+
export type TestimonialSliderProps = TestimonialSliderOwnProps;
|
|
25
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
26
|
+
export declare const testimonialSliderParts: {
|
|
27
|
+
readonly root: "dds-testimonialslider";
|
|
28
|
+
readonly inner: "dds-testimonialslider__inner";
|
|
29
|
+
readonly title: "dds-testimonialslider__title";
|
|
30
|
+
readonly carousel: "dds-testimonialslider__carousel";
|
|
31
|
+
readonly track: "dds-testimonialslider__track";
|
|
32
|
+
readonly item: "dds-testimonialslider__item";
|
|
33
|
+
readonly 'image-start': "dds-testimonialslider__image-start";
|
|
34
|
+
readonly 'image-end': "dds-testimonialslider__image-end";
|
|
35
|
+
readonly image: "dds-testimonialslider__image";
|
|
36
|
+
readonly quote: "dds-testimonialslider__quote";
|
|
37
|
+
readonly author: "dds-testimonialslider__author";
|
|
38
|
+
readonly avatar: "dds-testimonialslider__avatar";
|
|
39
|
+
readonly name: "dds-testimonialslider__name";
|
|
40
|
+
readonly detail: "dds-testimonialslider__detail";
|
|
41
|
+
readonly controls: "dds-testimonialslider__controls";
|
|
42
|
+
};
|
|
43
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
44
|
+
export declare const testimonialSliderDefaults: {
|
|
45
|
+
readonly ground: "page";
|
|
46
|
+
readonly autoplay: false;
|
|
47
|
+
readonly controlsLabel: "Testimonials";
|
|
48
|
+
readonly slideLabel: "Slide";
|
|
49
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// GENERATED from testimonial-slider.contract.json. Do not edit.
|
|
2
|
+
/** The class each part carries. Apply these — do not retype them. */
|
|
3
|
+
export const testimonialSliderParts = {
|
|
4
|
+
root: 'dds-testimonialslider',
|
|
5
|
+
inner: 'dds-testimonialslider__inner',
|
|
6
|
+
title: 'dds-testimonialslider__title',
|
|
7
|
+
carousel: 'dds-testimonialslider__carousel',
|
|
8
|
+
track: 'dds-testimonialslider__track',
|
|
9
|
+
item: 'dds-testimonialslider__item',
|
|
10
|
+
'image-start': 'dds-testimonialslider__image-start',
|
|
11
|
+
'image-end': 'dds-testimonialslider__image-end',
|
|
12
|
+
image: 'dds-testimonialslider__image',
|
|
13
|
+
quote: 'dds-testimonialslider__quote',
|
|
14
|
+
author: 'dds-testimonialslider__author',
|
|
15
|
+
avatar: 'dds-testimonialslider__avatar',
|
|
16
|
+
name: 'dds-testimonialslider__name',
|
|
17
|
+
detail: 'dds-testimonialslider__detail',
|
|
18
|
+
controls: 'dds-testimonialslider__controls',
|
|
19
|
+
};
|
|
20
|
+
/** Generated so defaults cannot drift from the contract. */
|
|
21
|
+
export const testimonialSliderDefaults = { ground: 'page', autoplay: false, controlsLabel: 'Testimonials', slideLabel: 'Slide' };
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Scoped to this package, like the generated sheet beside it.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* One cell for every quote, so a change of quote is a change in place.
|
|
7
|
+
*
|
|
8
|
+
* CtaBannerSlider's arrangement: the section takes the height of its longest quote whichever is
|
|
9
|
+
* showing, and nothing under it moves. The quote in view is drawn; the others wait in the same cell
|
|
10
|
+
* at opacity.hidden, and `visibility` takes them out of hit-testing as well as sight, beside the
|
|
11
|
+
* `inert` the component gives them. The fade borrows the track's timing through `inherit`, so the
|
|
12
|
+
* fade and the dots move on one beat.
|
|
13
|
+
*/
|
|
14
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__item {
|
|
15
|
+
grid-area: 1 / 1;
|
|
16
|
+
transition-property: opacity, visibility;
|
|
17
|
+
transition-duration: inherit;
|
|
18
|
+
transition-timing-function: inherit;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__item[aria-hidden='true'] {
|
|
22
|
+
opacity: var(--opacity-hidden);
|
|
23
|
+
visibility: hidden;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@media (prefers-reduced-motion: reduce) {
|
|
27
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__item {
|
|
28
|
+
transition-property: none;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* The track owns horizontal gestures and leaves vertical ones to the page — see CtaBannerSlider. */
|
|
33
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__track {
|
|
34
|
+
touch-action: pan-y;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* The card is ranged to the start on a phone and centred from the fold, as the reference design sets it.
|
|
39
|
+
*
|
|
40
|
+
* The heading, the quote and the person under it centre together. `margin-inline: auto` on the
|
|
41
|
+
* heading and the quote centres their measured boxes rather than their words inside a box left at
|
|
42
|
+
* the start edge.
|
|
43
|
+
*/
|
|
44
|
+
@container (min-width: 48rem) {
|
|
45
|
+
/* The heading centres with the card, the way every other block's heading does from the fold. */
|
|
46
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__title {
|
|
47
|
+
margin-inline: auto;
|
|
48
|
+
text-align: center;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__item {
|
|
52
|
+
align-items: center;
|
|
53
|
+
padding-inline: var(--space-inset-4xl);
|
|
54
|
+
text-align: center;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__quote {
|
|
58
|
+
margin-inline: auto;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* And the dots follow the quote: at the start edge on a phone, under the centre once it centres. */
|
|
62
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__controls {
|
|
63
|
+
justify-content: center;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/*
|
|
68
|
+
* How far the pictures drift, and so how far each is tucked behind its edge to keep its corners
|
|
69
|
+
* hidden while it does. Half of motion.distance.drift on a phone, where the one picture is set
|
|
70
|
+
* above the quote and every pixel tucked away is a pixel of it not shown; the whole of it from the
|
|
71
|
+
* fold, where the card is wide enough for the movement to read.
|
|
72
|
+
*/
|
|
73
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider {
|
|
74
|
+
--dds-testimonialslider-drift: calc(var(--motion-distance-drift) * 0.5);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@container (min-width: 48rem) {
|
|
78
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__track {
|
|
79
|
+
--dds-testimonialslider-drift: var(--motion-distance-drift);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/*
|
|
84
|
+
* The corner pictures, tucked behind the card's own edges.
|
|
85
|
+
*
|
|
86
|
+
* The opening one runs up behind the card's top edge and the closing one down behind its bottom
|
|
87
|
+
* edge, each set in from its side by the card's inset — so the pair runs from edge to edge of the
|
|
88
|
+
* card diagonally, as though passing behind it. Each is tucked by its own corner radius and the
|
|
89
|
+
* whole of its drift, so the corners on that side are behind the edge at every point of the
|
|
90
|
+
* scroll: the card's edge is a straight cut across the picture, and only the corners facing the
|
|
91
|
+
* quote show rounded. Their
|
|
92
|
+
* offsets are here rather than in bindings because a contract has no vocabulary for one: a
|
|
93
|
+
* position is a fact about this card's corners, which no other component shares.
|
|
94
|
+
*
|
|
95
|
+
* On a phone only the opening one is drawn, at full size, in the top end corner above the quote — the quote starts at the other edge, so the picture takes the side the words leave
|
|
96
|
+
* empty; from the fold both are, at full size, in opposite corners.
|
|
97
|
+
*/
|
|
98
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-start {
|
|
99
|
+
inline-size: var(--size-testimonial-art);
|
|
100
|
+
inset-block-start: calc(-1 * (var(--radius-container-item) + var(--dds-testimonialslider-drift)));
|
|
101
|
+
inset-inline-end: var(--space-inset-lg);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-end {
|
|
105
|
+
inset-block-end: calc(-1 * (var(--radius-container-item) + var(--dds-testimonialslider-drift)));
|
|
106
|
+
inset-inline-end: var(--space-inset-xl);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/*
|
|
110
|
+
* Room is made on the card for whichever is drawn, so a picture never sits over the words, and
|
|
111
|
+
* `:has()` asks the track whether one is there, so a card with none keeps its own padding.
|
|
112
|
+
*
|
|
113
|
+
* Above the quote on a phone: as much of the picture as ever comes out from behind the top edge —
|
|
114
|
+
* its size less its corner, the drift and the tuck cancelling — and two insets between it and
|
|
115
|
+
* the words.
|
|
116
|
+
*/
|
|
117
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__track:has(> .dds-testimonialslider__image-start) .dds-testimonialslider__item {
|
|
118
|
+
padding-block-start: calc(var(--size-testimonial-art) - var(--radius-container-item) + 2 * var(--space-inset-lg));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@container (min-width: 48rem) {
|
|
122
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-start {
|
|
123
|
+
inline-size: var(--size-testimonial-art);
|
|
124
|
+
inset-block-start: calc(-1 * (var(--radius-container-item) + var(--dds-testimonialslider-drift)));
|
|
125
|
+
inset-inline-end: auto;
|
|
126
|
+
inset-inline-start: var(--space-inset-xl);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-end {
|
|
130
|
+
display: block;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* At the sides from the fold: each picture, with an inset either side of it. Tall enough to hold
|
|
134
|
+
a picture and its insets, so neither runs off the top or the bottom of a short card. */
|
|
135
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__track:is(:has(> .dds-testimonialslider__image-start), :has(> .dds-testimonialslider__image-end)) .dds-testimonialslider__item {
|
|
136
|
+
justify-content: center;
|
|
137
|
+
min-block-size: calc(var(--size-testimonial-art) + 2 * var(--space-inset-3xl));
|
|
138
|
+
padding-block-start: var(--space-inset-3xl);
|
|
139
|
+
padding-inline: calc(var(--size-testimonial-art) + 2 * var(--space-inset-xl));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/*
|
|
144
|
+
* They drift against the scroll while the section passes through the view — half of
|
|
145
|
+
* motion.distance.drift on a phone, all of it from the fold: the opening one down and the closing one up, each from where it rests, so the two mirror
|
|
146
|
+
* each other at every point of the scroll and keep the same distance from their own edges.
|
|
147
|
+
*
|
|
148
|
+
* Scroll-driven, LandingHero's way: a view timeline measures the card against the viewport, so it
|
|
149
|
+
* moves as the reader scrolls and back again as they scroll back, and there is no timer and no
|
|
150
|
+
* script. A browser with no scroll timeline draws both still, which is the whole of the fallback.
|
|
151
|
+
*/
|
|
152
|
+
@keyframes dds-testimonialslider-drift-down {
|
|
153
|
+
from {
|
|
154
|
+
translate: none;
|
|
155
|
+
}
|
|
156
|
+
to {
|
|
157
|
+
translate: 0 var(--dds-testimonialslider-drift);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@keyframes dds-testimonialslider-drift-up {
|
|
162
|
+
from {
|
|
163
|
+
translate: none;
|
|
164
|
+
}
|
|
165
|
+
to {
|
|
166
|
+
translate: 0 calc(-1 * var(--dds-testimonialslider-drift));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
@supports (animation-timeline: view()) {
|
|
171
|
+
/* One timeline for the pair, the card's own pass through the view. Each picture measuring its own
|
|
172
|
+
would put the higher one further along at every point of the scroll, and the two would drift
|
|
173
|
+
by different distances.
|
|
174
|
+
|
|
175
|
+
It measures against the nearest scroll container, which is why the section and the track clip
|
|
176
|
+
with `overflow: clip` rather than `hidden`: `hidden` makes a box a scroll container even when
|
|
177
|
+
it never scrolls, and the timeline would then measure the card against a box that does not
|
|
178
|
+
move — the pictures would sit still at one point of the drift however far the page scrolled. */
|
|
179
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__track {
|
|
180
|
+
view-timeline: --dds-testimonialslider-card block;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-start {
|
|
184
|
+
animation: dds-testimonialslider-drift-down linear both;
|
|
185
|
+
animation-range: cover;
|
|
186
|
+
animation-timeline: --dds-testimonialslider-card;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-end {
|
|
190
|
+
animation: dds-testimonialslider-drift-up linear both;
|
|
191
|
+
animation-range: cover;
|
|
192
|
+
animation-timeline: --dds-testimonialslider-card;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* A reader who asked for less movement gets none of it: the pictures hold still in their corners. */
|
|
197
|
+
@media (prefers-reduced-motion: reduce) {
|
|
198
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-start,
|
|
199
|
+
:where([data-dds-context="marketing"]) .dds-testimonialslider .dds-testimonialslider__image-end {
|
|
200
|
+
animation: none;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a block has arrived on screen yet, so its stylesheet can bring it in.
|
|
3
|
+
*
|
|
4
|
+
* Every trigger CSS alone can offer is invisible somewhere, and both were tried here first. A
|
|
5
|
+
* timed animation fires when the element is created, so a block below the fold has finished
|
|
6
|
+
* arriving before a reader scrolls to it. A scroll-driven one — `animation-timeline: view()` —
|
|
7
|
+
* fires as the element enters the viewport, so a block that is *already* in view at the first
|
|
8
|
+
* frame is past the range before anything is painted, and an opening band never moves at all.
|
|
9
|
+
*
|
|
10
|
+
* What is wanted is "when it comes into view, counting already being there as coming into view",
|
|
11
|
+
* and that is the one thing a view timeline cannot say. An observer can, which is the whole reason
|
|
12
|
+
* this file exists.
|
|
13
|
+
*
|
|
14
|
+
* It answers `true` before it knows anything, and that is deliberate. A block hidden until
|
|
15
|
+
* JavaScript says otherwise is content behind a script — a reader with none, or one whose bundle
|
|
16
|
+
* failed, gets a blank band. So the resting answer is visible, and hiding is something this only
|
|
17
|
+
* does once it is running and has somewhere to put the block back.
|
|
18
|
+
*
|
|
19
|
+
* `useLayoutEffect` so the hiding lands before the browser paints. In an effect it would run after
|
|
20
|
+
* the first frame, and every block would show itself, hide, and come back — a flash on every
|
|
21
|
+
* section of the page.
|
|
22
|
+
*
|
|
23
|
+
* It fires once. A section that re-arrived every time a reader scrolled back up would be a page
|
|
24
|
+
* that will not settle, and the observer is disconnected rather than left listening.
|
|
25
|
+
*/
|
|
26
|
+
export declare function useReveal<T extends HTMLElement>(): [
|
|
27
|
+
ref: (held: T | null) => void,
|
|
28
|
+
revealed: boolean
|
|
29
|
+
];
|
|
30
|
+
/**
|
|
31
|
+
* One part's place in the order its block arrives in.
|
|
32
|
+
*
|
|
33
|
+
* Spread onto each part that moves: `<p {...arriving(1)} …>`. Two spellings of one number, because
|
|
34
|
+
* CSS needs both and can do neither job with the other's — an attribute is what a selector can
|
|
35
|
+
* match, and a custom property is what `calc()` can multiply into a delay.
|
|
36
|
+
*
|
|
37
|
+
* The number is the reading order rather than the DOM order, and they are not always the same: a
|
|
38
|
+
* hero's picture sits before its words in the markup, because a band paints its ground before it
|
|
39
|
+
* sets type on it, and a reader still meets the claim first.
|
|
40
|
+
*/
|
|
41
|
+
export declare function arriving(at: number): {
|
|
42
|
+
'data-reveal-at': number;
|
|
43
|
+
style: {
|
|
44
|
+
[key: string]: string | number;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useLayoutEffect, useRef, useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Whether a block has arrived on screen yet, so its stylesheet can bring it in.
|
|
5
|
+
*
|
|
6
|
+
* Every trigger CSS alone can offer is invisible somewhere, and both were tried here first. A
|
|
7
|
+
* timed animation fires when the element is created, so a block below the fold has finished
|
|
8
|
+
* arriving before a reader scrolls to it. A scroll-driven one — `animation-timeline: view()` —
|
|
9
|
+
* fires as the element enters the viewport, so a block that is *already* in view at the first
|
|
10
|
+
* frame is past the range before anything is painted, and an opening band never moves at all.
|
|
11
|
+
*
|
|
12
|
+
* What is wanted is "when it comes into view, counting already being there as coming into view",
|
|
13
|
+
* and that is the one thing a view timeline cannot say. An observer can, which is the whole reason
|
|
14
|
+
* this file exists.
|
|
15
|
+
*
|
|
16
|
+
* It answers `true` before it knows anything, and that is deliberate. A block hidden until
|
|
17
|
+
* JavaScript says otherwise is content behind a script — a reader with none, or one whose bundle
|
|
18
|
+
* failed, gets a blank band. So the resting answer is visible, and hiding is something this only
|
|
19
|
+
* does once it is running and has somewhere to put the block back.
|
|
20
|
+
*
|
|
21
|
+
* `useLayoutEffect` so the hiding lands before the browser paints. In an effect it would run after
|
|
22
|
+
* the first frame, and every block would show itself, hide, and come back — a flash on every
|
|
23
|
+
* section of the page.
|
|
24
|
+
*
|
|
25
|
+
* It fires once. A section that re-arrived every time a reader scrolled back up would be a page
|
|
26
|
+
* that will not settle, and the observer is disconnected rather than left listening.
|
|
27
|
+
*/
|
|
28
|
+
export function useReveal() {
|
|
29
|
+
const held = useRef(null);
|
|
30
|
+
const [revealed, setRevealed] = useState(true);
|
|
31
|
+
useLayoutEffect(() => {
|
|
32
|
+
const element = held.current;
|
|
33
|
+
if (element === null)
|
|
34
|
+
return;
|
|
35
|
+
// A reader who asked for less movement is not hidden and then shown; they are simply shown.
|
|
36
|
+
// The stylesheet drops the transition as well, so this is the half that matters: without it
|
|
37
|
+
// the block would still be hidden for a frame before appearing, which is the flicker that
|
|
38
|
+
// preference exists to remove.
|
|
39
|
+
//
|
|
40
|
+
// Asked defensively, like the observer below. A renderer with no `matchMedia` cannot be
|
|
41
|
+
// asked what the reader prefers, and the honest answer to a question that cannot be asked
|
|
42
|
+
// is the one that hides nothing.
|
|
43
|
+
const asked = typeof window.matchMedia === 'function';
|
|
44
|
+
if (asked && window.matchMedia('(prefers-reduced-motion: reduce)').matches)
|
|
45
|
+
return;
|
|
46
|
+
// Anything the browser cannot observe arrives already arrived, which is the same answer this
|
|
47
|
+
// hook starts on: seen rather than waiting.
|
|
48
|
+
if (typeof IntersectionObserver === 'undefined')
|
|
49
|
+
return;
|
|
50
|
+
/**
|
|
51
|
+
* A box that does not exist cannot come into view, so it is never hidden.
|
|
52
|
+
*
|
|
53
|
+
* `display: contents` is the case, and it cost a section its words: FeatureScroll's text column
|
|
54
|
+
* gives up its box on a phone so the picture can sit between the title and the line under it,
|
|
55
|
+
* an observer watching it was never going to report anything, and the copy stayed waiting for
|
|
56
|
+
* an arrival that could not happen. Permanently invisible content is the worst failure this
|
|
57
|
+
* hook has available to it, so it checks.
|
|
58
|
+
*
|
|
59
|
+
* A caller that wants motion for such a group watches something inside it that does have a box
|
|
60
|
+
* and marks the group — the ref and the attribute need not sit on the same element. This is the
|
|
61
|
+
* floor under that, not a substitute for it.
|
|
62
|
+
*/
|
|
63
|
+
if (element.getClientRects().length === 0)
|
|
64
|
+
return;
|
|
65
|
+
setRevealed(false);
|
|
66
|
+
/**
|
|
67
|
+
* The arrival is put off to the next frame, and that one frame is the whole of it.
|
|
68
|
+
*
|
|
69
|
+
* A transition needs a painted starting state. For a block already on screen the observer's
|
|
70
|
+
* first callback is delivered in the rendering steps of the frame the block was laid out in —
|
|
71
|
+
* so flipping there applies the landed state before the waiting one has ever been painted, and
|
|
72
|
+
* the browser has nothing to move between. It goes straight to the end, which looks exactly
|
|
73
|
+
* like no animation at all.
|
|
74
|
+
*
|
|
75
|
+
* That was the bug, and it hid itself well: a block below the fold worked, because the
|
|
76
|
+
* observer does not fire until a reader scrolls and by then the waiting state has been on
|
|
77
|
+
* screen for many frames. Everything a reader sees first — the heading, the first block, any
|
|
78
|
+
* band shown on its own — did not.
|
|
79
|
+
*/
|
|
80
|
+
let frame = 0;
|
|
81
|
+
const watching = new IntersectionObserver((entries) => {
|
|
82
|
+
if (!entries.some((entry) => entry.isIntersecting))
|
|
83
|
+
return;
|
|
84
|
+
watching.disconnect();
|
|
85
|
+
frame = window.requestAnimationFrame(() => {
|
|
86
|
+
frame = 0;
|
|
87
|
+
setRevealed(true);
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
// A tenth of the block, so a band a screen tall is not held back until a reader has scrolled
|
|
91
|
+
// most of it into view, and a short one is not brought in by a sliver at the edge.
|
|
92
|
+
{ threshold: 0.1 });
|
|
93
|
+
watching.observe(element);
|
|
94
|
+
return () => {
|
|
95
|
+
watching.disconnect();
|
|
96
|
+
if (frame !== 0)
|
|
97
|
+
window.cancelAnimationFrame(frame);
|
|
98
|
+
};
|
|
99
|
+
}, []);
|
|
100
|
+
return [
|
|
101
|
+
(element) => {
|
|
102
|
+
held.current = element;
|
|
103
|
+
},
|
|
104
|
+
revealed,
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* One part's place in the order its block arrives in.
|
|
109
|
+
*
|
|
110
|
+
* Spread onto each part that moves: `<p {...arriving(1)} …>`. Two spellings of one number, because
|
|
111
|
+
* CSS needs both and can do neither job with the other's — an attribute is what a selector can
|
|
112
|
+
* match, and a custom property is what `calc()` can multiply into a delay.
|
|
113
|
+
*
|
|
114
|
+
* The number is the reading order rather than the DOM order, and they are not always the same: a
|
|
115
|
+
* hero's picture sits before its words in the markup, because a band paints its ground before it
|
|
116
|
+
* sets type on it, and a reader still meets the claim first.
|
|
117
|
+
*/
|
|
118
|
+
export function arriving(at) {
|
|
119
|
+
return { 'data-reveal-at': at, style: { '--dds-reveal-at': at } };
|
|
120
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type FocusEvent, type MouseEvent, type PointerEvent } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* One block rotating between a few things in place — which one is in view, and every way a reader
|
|
4
|
+
* moves it, holds it or stops it.
|
|
5
|
+
*
|
|
6
|
+
* Shared because two blocks rotate, CtaBannerSlider and TestimonialSlider, and a carousel is the
|
|
7
|
+
* kind of thing that drifts: one stops on a press and the other does not, one swallows the click a swipe
|
|
8
|
+
* ends in and the other follows the link. The rules are stated once here and each block spreads
|
|
9
|
+
* what this hands back onto its own parts.
|
|
10
|
+
*
|
|
11
|
+
* The clock is not here. PaginationDots holds the timer and the reduced-motion stillness, and this
|
|
12
|
+
* tells it when to wait — so there is one clock per block, and it is the one a reader can see.
|
|
13
|
+
*
|
|
14
|
+
* What it hands back:
|
|
15
|
+
* - `root`, the ref for the block's own element, which the swipe threshold and the reading
|
|
16
|
+
* direction are read off;
|
|
17
|
+
* - `region`, spread on that element: the carousel's role description and the hold and stop
|
|
18
|
+
* handlers;
|
|
19
|
+
* - `track`, spread on the element holding the items: the swipe and what is announced;
|
|
20
|
+
* - `item(at)`, spread on each item: its group role, its "2 / 3" name and its inert state;
|
|
21
|
+
* - `dots`, spread on PaginationDots alongside the block's own label.
|
|
22
|
+
*
|
|
23
|
+
* Fewer than two items is a set with nothing to move to, drawn still rather than broken: every
|
|
24
|
+
* attribute that says "carousel" is left off and the dots are the block's to omit.
|
|
25
|
+
*/
|
|
26
|
+
export declare function useRotation(count: number, autoplay: boolean): {
|
|
27
|
+
current: number;
|
|
28
|
+
rotating: boolean;
|
|
29
|
+
root: import("react").RefObject<HTMLElement | null>;
|
|
30
|
+
region: {
|
|
31
|
+
'aria-roledescription': string | undefined;
|
|
32
|
+
onPointerEnter: (event: PointerEvent<HTMLElement>) => void;
|
|
33
|
+
onPointerLeave: (event: PointerEvent<HTMLElement>) => void;
|
|
34
|
+
onFocus: () => void;
|
|
35
|
+
onPointerDownCapture: (event: PointerEvent<HTMLElement>) => void;
|
|
36
|
+
onBlur: (event: FocusEvent<HTMLElement>) => void;
|
|
37
|
+
};
|
|
38
|
+
track: {
|
|
39
|
+
'aria-live': "polite" | "off";
|
|
40
|
+
onPointerDown: (event: PointerEvent<HTMLElement>) => void;
|
|
41
|
+
onPointerUp: (event: PointerEvent<HTMLElement>) => void;
|
|
42
|
+
onPointerCancel: () => void;
|
|
43
|
+
onPointerLeave: () => void;
|
|
44
|
+
onClickCapture: (event: MouseEvent<HTMLElement>) => void;
|
|
45
|
+
};
|
|
46
|
+
/** Whether an item is out of view: inert, hidden, and waiting rather than arrived. */
|
|
47
|
+
away: (at: number) => boolean;
|
|
48
|
+
item: (at: number) => {
|
|
49
|
+
role: string | undefined;
|
|
50
|
+
'aria-roledescription': string | undefined;
|
|
51
|
+
'aria-label': string | undefined;
|
|
52
|
+
'aria-hidden': true | undefined;
|
|
53
|
+
inert: true | undefined;
|
|
54
|
+
};
|
|
55
|
+
dots: {
|
|
56
|
+
page: number;
|
|
57
|
+
totalPages: number;
|
|
58
|
+
onPageChange: (page: number) => void;
|
|
59
|
+
autoplay: boolean;
|
|
60
|
+
paused: boolean;
|
|
61
|
+
};
|
|
62
|
+
};
|