@deriv-com/dds-marketing 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.llm/components/awards.md +209 -0
- package/.llm/components/background.md +420 -0
- package/.llm/components/bottomsheet.md +5 -0
- package/.llm/components/comparisoncards.md +257 -0
- package/.llm/components/comparisontable.md +231 -0
- package/.llm/components/ctabanner.md +22 -0
- package/.llm/components/ctabannerslider.md +36 -2
- package/.llm/components/datatable.md +273 -0
- package/.llm/components/downloadbanner.md +283 -0
- package/.llm/components/featurecards.md +41 -3
- package/.llm/components/featurecardscarousel.md +311 -0
- package/.llm/components/featuresplit.md +5 -0
- package/.llm/components/featurestack.md +227 -0
- package/.llm/components/illustrationcard.md +236 -0
- package/.llm/components/illustrationscene.md +229 -0
- package/.llm/components/imagebanner.md +278 -0
- package/.llm/components/landinghero.md +24 -0
- package/.llm/components/navbar.md +1 -1
- package/.llm/components/navbaritem.md +4 -0
- package/.llm/components/pageheader.md +22 -0
- package/.llm/components/paginationdots.md +6 -1
- package/.llm/components/producthero.md +35 -11
- package/.llm/components/resourcebanner.md +247 -0
- package/.llm/components/scenescroll.md +222 -0
- package/.llm/components/select.md +17 -0
- package/.llm/components/stats.md +219 -0
- package/.llm/components/steps.md +286 -0
- package/.llm/components/stickycards.md +251 -0
- package/.llm/components/tableheadercell.md +19 -0
- package/.llm/components/teamgrid.md +243 -0
- package/.llm/components/testimonialrow.md +5 -0
- package/.llm/components/testimonialslider.md +14 -1
- package/.llm/components/textarea.md +13 -0
- package/.llm/components/textinput.md +13 -0
- package/.llm/components/textscroll.md +187 -0
- package/.llm/components/tiers.md +227 -0
- package/.llm/digest/awards.md +45 -0
- package/.llm/digest/background.md +53 -0
- package/.llm/digest/bottomsheet.md +2 -0
- package/.llm/digest/comparisoncards.md +51 -0
- package/.llm/digest/comparisontable.md +53 -0
- package/.llm/digest/ctabanner.md +4 -0
- package/.llm/digest/ctabannerslider.md +7 -0
- package/.llm/digest/datatable.md +65 -0
- package/.llm/digest/downloadbanner.md +65 -0
- package/.llm/digest/featurecards.md +1 -1
- package/.llm/digest/featurecardscarousel.md +54 -0
- package/.llm/digest/featuresplit.md +1 -0
- package/.llm/digest/featurestack.md +48 -0
- package/.llm/digest/illustrationcard.md +46 -0
- package/.llm/digest/illustrationscene.md +50 -0
- package/.llm/digest/imagebanner.md +64 -0
- package/.llm/digest/landinghero.md +7 -0
- package/.llm/digest/navbaritem.md +1 -0
- package/.llm/digest/pageheader.md +4 -0
- package/.llm/digest/paginationdots.md +3 -1
- package/.llm/digest/producthero.md +4 -2
- package/.llm/digest/resourcebanner.md +53 -0
- package/.llm/digest/scenescroll.md +49 -0
- package/.llm/digest/select.md +5 -0
- package/.llm/digest/stats.md +46 -0
- package/.llm/digest/steps.md +55 -0
- package/.llm/digest/stickycards.md +52 -0
- package/.llm/digest/tableheadercell.md +4 -0
- package/.llm/digest/teamgrid.md +53 -0
- package/.llm/digest/testimonialrow.md +2 -0
- package/.llm/digest/testimonialslider.md +4 -0
- package/.llm/digest/textarea.md +4 -0
- package/.llm/digest/textinput.md +4 -0
- package/.llm/digest/textscroll.md +43 -0
- package/.llm/digest/tiers.md +50 -0
- package/.llm/index.md +25 -2
- package/.llm/tokens.md +37 -1
- package/AGENTS.md +20 -1
- package/dist/components/awards-data.d.ts +24 -0
- package/dist/components/awards-data.js +11 -0
- package/dist/components/block-image-data.d.ts +24 -0
- package/dist/components/block-image-data.js +9 -0
- package/dist/components/blocks/awards/Awards.css +134 -0
- package/dist/components/blocks/awards/Awards.d.ts +24 -0
- package/dist/components/blocks/awards/Awards.js +114 -0
- package/dist/components/blocks/awards/Awards.types.d.ts +31 -0
- package/dist/components/blocks/awards/Awards.types.js +16 -0
- package/dist/components/blocks/awards/awards-impl.css +222 -0
- package/dist/components/blocks/cards-of.d.ts +16 -0
- package/dist/components/blocks/cards-of.js +23 -0
- package/dist/components/blocks/comparison-cards/ComparisonCards.css +195 -0
- package/dist/components/blocks/comparison-cards/ComparisonCards.d.ts +24 -0
- package/dist/components/blocks/comparison-cards/ComparisonCards.js +75 -0
- package/dist/components/blocks/comparison-cards/ComparisonCards.types.d.ts +49 -0
- package/dist/components/blocks/comparison-cards/ComparisonCards.types.js +26 -0
- package/dist/components/blocks/comparison-cards/comparison-cards-impl.css +262 -0
- package/dist/components/blocks/comparison-table/ComparisonTable.css +111 -0
- package/dist/components/blocks/comparison-table/ComparisonTable.d.ts +25 -0
- package/dist/components/blocks/comparison-table/ComparisonTable.js +100 -0
- package/dist/components/blocks/comparison-table/ComparisonTable.types.d.ts +36 -0
- package/dist/components/blocks/comparison-table/ComparisonTable.types.js +15 -0
- package/dist/components/blocks/comparison-table/comparison-table-impl.css +143 -0
- package/dist/components/blocks/cta-banner/CtaBanner.css +1 -0
- package/dist/components/blocks/cta-banner/CtaBanner.d.ts +1 -1
- package/dist/components/blocks/cta-banner/CtaBanner.js +3 -2
- package/dist/components/blocks/cta-banner/CtaBanner.types.d.ts +6 -0
- package/dist/components/blocks/cta-banner/CtaBanner.types.js +1 -1
- package/dist/components/blocks/cta-banner/cta-banner-impl.css +8 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.css +1 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.d.ts +1 -1
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.js +10 -5
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.d.ts +12 -0
- package/dist/components/blocks/cta-banner-slider/CtaBannerSlider.types.js +1 -1
- package/dist/components/blocks/cta-banner-slider/cta-banner-slider-impl.css +8 -0
- package/dist/components/blocks/data-table/DataTable.css +170 -0
- package/dist/components/blocks/data-table/DataTable.d.ts +29 -0
- package/dist/components/blocks/data-table/DataTable.js +84 -0
- package/dist/components/blocks/data-table/DataTable.types.d.ts +69 -0
- package/dist/components/blocks/data-table/DataTable.types.js +19 -0
- package/dist/components/blocks/data-table/data-table-impl.css +155 -0
- package/dist/components/blocks/download-banner/DownloadBanner.css +228 -0
- package/dist/components/blocks/download-banner/DownloadBanner.d.ts +28 -0
- package/dist/components/blocks/download-banner/DownloadBanner.js +75 -0
- package/dist/components/blocks/download-banner/DownloadBanner.types.d.ts +56 -0
- package/dist/components/blocks/download-banner/DownloadBanner.types.js +23 -0
- package/dist/components/blocks/download-banner/download-banner-impl.css +216 -0
- package/dist/components/blocks/faq-accordion/FaqAccordion.css +1 -0
- package/dist/components/blocks/faq-accordion/faq-accordion-impl.css +3 -7
- package/dist/components/blocks/feature-bullets/FeatureBullets.css +1 -0
- package/dist/components/blocks/feature-bullets/feature-bullets-impl.css +14 -1
- package/dist/components/blocks/feature-cards/FeatureCards.css +1 -0
- package/dist/components/blocks/feature-cards/FeatureCards.d.ts +2 -1
- package/dist/components/blocks/feature-cards/FeatureCards.js +4 -21
- package/dist/components/blocks/feature-cards/feature-cards-impl.css +10 -9
- package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.css +115 -0
- package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.d.ts +30 -0
- package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.js +160 -0
- package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.types.d.ts +52 -0
- package/dist/components/blocks/feature-cards-carousel/FeatureCardsCarousel.types.js +17 -0
- package/dist/components/blocks/feature-cards-carousel/feature-cards-carousel-impl.css +207 -0
- package/dist/components/blocks/feature-scroll/FeatureScroll.css +1 -0
- package/dist/components/blocks/feature-split/FeatureSplit.css +1 -0
- package/dist/components/blocks/feature-split/feature-split-impl.css +14 -1
- package/dist/components/blocks/feature-stack/FeatureStack.css +86 -0
- package/dist/components/blocks/feature-stack/FeatureStack.d.ts +19 -0
- package/dist/components/blocks/feature-stack/FeatureStack.js +27 -0
- package/dist/components/blocks/feature-stack/FeatureStack.types.d.ts +34 -0
- package/dist/components/blocks/feature-stack/FeatureStack.types.js +14 -0
- package/dist/components/blocks/feature-stack/feature-stack-impl.css +87 -0
- package/dist/components/blocks/image-banner/ImageBanner.css +133 -0
- package/dist/components/blocks/image-banner/ImageBanner.d.ts +32 -0
- package/dist/components/blocks/image-banner/ImageBanner.js +41 -0
- package/dist/components/blocks/image-banner/ImageBanner.types.d.ts +54 -0
- package/dist/components/blocks/image-banner/ImageBanner.types.js +14 -0
- package/dist/components/blocks/image-banner/image-banner-impl.css +281 -0
- package/dist/components/blocks/landing-hero/LandingHero.css +1 -0
- package/dist/components/blocks/landing-hero/LandingHero.d.ts +1 -1
- package/dist/components/blocks/landing-hero/LandingHero.js +4 -3
- package/dist/components/blocks/landing-hero/LandingHero.types.d.ts +7 -3
- package/dist/components/blocks/logo-columns/LogoColumns.css +1 -0
- package/dist/components/blocks/logo-rows/LogoRows.css +1 -0
- package/dist/components/blocks/page-header/PageHeader.css +1 -0
- package/dist/components/blocks/page-header/PageHeader.d.ts +1 -1
- package/dist/components/blocks/page-header/PageHeader.js +3 -2
- package/dist/components/blocks/page-header/PageHeader.types.d.ts +6 -0
- package/dist/components/blocks/page-header/PageHeader.types.js +1 -1
- package/dist/components/blocks/page-header/page-header-impl.css +10 -0
- package/dist/components/blocks/product-hero/ProductHero.css +8 -3
- package/dist/components/blocks/product-hero/ProductHero.d.ts +1 -1
- package/dist/components/blocks/product-hero/ProductHero.js +5 -2
- package/dist/components/blocks/product-hero/ProductHero.types.d.ts +5 -1
- package/dist/components/blocks/product-hero/ProductHero.types.js +1 -0
- package/dist/components/blocks/product-hero/product-hero-impl.css +43 -12
- package/dist/components/blocks/resource-banner/ResourceBanner.css +106 -0
- package/dist/components/blocks/resource-banner/ResourceBanner.d.ts +32 -0
- package/dist/components/blocks/resource-banner/ResourceBanner.js +51 -0
- package/dist/components/blocks/resource-banner/ResourceBanner.types.d.ts +44 -0
- package/dist/components/blocks/resource-banner/ResourceBanner.types.js +14 -0
- package/dist/components/blocks/resource-banner/resource-banner-impl.css +69 -0
- package/dist/components/blocks/scene-scroll/SceneScroll.css +93 -0
- package/dist/components/blocks/scene-scroll/SceneScroll.d.ts +36 -0
- package/dist/components/blocks/scene-scroll/SceneScroll.js +54 -0
- package/dist/components/blocks/scene-scroll/SceneScroll.types.d.ts +32 -0
- package/dist/components/blocks/scene-scroll/SceneScroll.types.js +15 -0
- package/dist/components/blocks/scene-scroll/scene-scroll-impl.css +275 -0
- package/dist/components/blocks/stats/Stats.css +139 -0
- package/dist/components/blocks/stats/Stats.d.ts +24 -0
- package/dist/components/blocks/stats/Stats.js +120 -0
- package/dist/components/blocks/stats/Stats.types.d.ts +36 -0
- package/dist/components/blocks/stats/Stats.types.js +19 -0
- package/dist/components/blocks/stats/stats-count.d.ts +34 -0
- package/dist/components/blocks/stats/stats-count.js +61 -0
- package/dist/components/blocks/stats/stats-impl.css +284 -0
- package/dist/components/blocks/stats/use-wheel.d.ts +37 -0
- package/dist/components/blocks/stats/use-wheel.js +126 -0
- package/dist/components/blocks/steps/Steps.css +202 -0
- package/dist/components/blocks/steps/Steps.d.ts +32 -0
- package/dist/components/blocks/steps/Steps.js +65 -0
- package/dist/components/blocks/steps/Steps.types.d.ts +48 -0
- package/dist/components/blocks/steps/Steps.types.js +21 -0
- package/dist/components/blocks/steps/steps-impl.css +216 -0
- package/dist/components/blocks/steps/use-turn.d.ts +33 -0
- package/dist/components/blocks/steps/use-turn.js +75 -0
- package/dist/components/blocks/sticky-cards/StickyCards.css +154 -0
- package/dist/components/blocks/sticky-cards/StickyCards.d.ts +35 -0
- package/dist/components/blocks/sticky-cards/StickyCards.js +153 -0
- package/dist/components/blocks/sticky-cards/StickyCards.types.d.ts +43 -0
- package/dist/components/blocks/sticky-cards/StickyCards.types.js +18 -0
- package/dist/components/blocks/sticky-cards/sticky-cards-impl.css +393 -0
- package/dist/components/blocks/team-grid/TeamGrid.css +159 -0
- package/dist/components/blocks/team-grid/TeamGrid.d.ts +28 -0
- package/dist/components/blocks/team-grid/TeamGrid.js +74 -0
- package/dist/components/blocks/team-grid/TeamGrid.types.d.ts +51 -0
- package/dist/components/blocks/team-grid/TeamGrid.types.js +20 -0
- package/dist/components/blocks/team-grid/team-grid-impl.css +129 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.css +1 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.d.ts +1 -1
- package/dist/components/blocks/testimonial-row/TestimonialRow.js +4 -3
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.d.ts +3 -0
- package/dist/components/blocks/testimonial-row/TestimonialRow.types.js +1 -1
- package/dist/components/blocks/testimonial-row/testimonial-row-impl.css +8 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.css +1 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.d.ts +1 -1
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.js +2 -2
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.d.ts +8 -0
- package/dist/components/blocks/testimonial-slider/TestimonialSlider.types.js +1 -1
- package/dist/components/blocks/text-scroll/TextScroll.css +53 -0
- package/dist/components/blocks/text-scroll/TextScroll.d.ts +5 -0
- package/dist/components/blocks/text-scroll/TextScroll.js +71 -0
- package/dist/components/blocks/text-scroll/TextScroll.types.d.ts +22 -0
- package/dist/components/blocks/text-scroll/TextScroll.types.js +10 -0
- package/dist/components/blocks/text-scroll/text-scroll-impl.css +115 -0
- package/dist/components/blocks/tiers/Tiers.css +233 -0
- package/dist/components/blocks/tiers/Tiers.d.ts +32 -0
- package/dist/components/blocks/tiers/Tiers.js +68 -0
- package/dist/components/blocks/tiers/Tiers.types.d.ts +45 -0
- package/dist/components/blocks/tiers/Tiers.types.js +25 -0
- package/dist/components/blocks/tiers/tiers-impl.css +185 -0
- package/dist/components/blocks/use-rotation.d.ts +12 -2
- package/dist/components/blocks/use-rotation.js +6 -28
- package/dist/components/comparison-cards-data.d.ts +59 -0
- package/dist/components/comparison-cards-data.js +12 -0
- package/dist/components/comparison-table-data.d.ts +39 -0
- package/dist/components/comparison-table-data.js +11 -0
- package/dist/components/core/accordion-item/AccordionItem.css +1 -5
- package/dist/components/core/background/Background.css +92 -0
- package/dist/components/core/background/Background.d.ts +27 -0
- package/dist/components/core/background/Background.js +45 -0
- package/dist/components/core/background/Background.types.d.ts +39 -0
- package/dist/components/core/background/Background.types.js +11 -0
- package/dist/components/core/background/background-impl.css +760 -0
- package/dist/components/core/background/halftone.d.ts +134 -0
- package/dist/components/core/background/halftone.js +722 -0
- package/dist/components/core/background/patterns.d.ts +66 -0
- package/dist/components/core/background/patterns.js +244 -0
- package/dist/components/core/background/shader.d.ts +44 -0
- package/dist/components/core/background/shader.js +307 -0
- package/dist/components/core/background/use-halftone.d.ts +15 -0
- package/dist/components/core/background/use-halftone.js +27 -0
- package/dist/components/core/background/use-offscreen.d.ts +10 -0
- package/dist/components/core/background/use-offscreen.js +30 -0
- package/dist/components/core/background/use-shader.d.ts +11 -0
- package/dist/components/core/background/use-shader.js +25 -0
- package/dist/components/core/background/use-spotlight.d.ts +14 -0
- package/dist/components/core/background/use-spotlight.js +73 -0
- package/dist/components/core/bottom-sheet/BottomSheet.js +2 -2
- package/dist/components/core/bottom-sheet/BottomSheet.types.d.ts +3 -1
- package/dist/components/core/breadcrumb/Breadcrumb.d.ts +1 -0
- package/dist/components/core/breadcrumb/Breadcrumb.js +1 -0
- package/dist/components/core/breadcrumb/breadcrumb-impl.css +11 -0
- package/dist/components/core/button/button-impl.css +14 -1
- package/dist/components/core/illustration-card/IllustrationCard.css +40 -0
- package/dist/components/core/illustration-card/IllustrationCard.d.ts +22 -0
- package/dist/components/core/illustration-card/IllustrationCard.js +82 -0
- package/dist/components/core/illustration-card/IllustrationCard.types.d.ts +23 -0
- package/dist/components/core/illustration-card/IllustrationCard.types.js +8 -0
- package/dist/components/core/illustration-card/illustration-card-impl.css +47 -0
- package/dist/components/core/illustration-scene/IllustrationScene.css +41 -0
- package/dist/components/core/illustration-scene/IllustrationScene.d.ts +14 -0
- package/dist/components/core/illustration-scene/IllustrationScene.js +16 -0
- package/dist/components/core/illustration-scene/IllustrationScene.types.d.ts +32 -0
- package/dist/components/core/illustration-scene/IllustrationScene.types.js +8 -0
- package/dist/components/core/illustration-scene/illustration-scene-impl.css +46 -0
- package/dist/components/core/link/Link.js +7 -3
- package/dist/components/core/link/link-impl.css +29 -2
- package/dist/components/core/navbar/Navbar.css +2 -2
- package/dist/components/core/navbar/Navbar.types.d.ts +1 -1
- package/dist/components/core/navbar-item/NavbarItem.d.ts +2 -1
- package/dist/components/core/navbar-item/NavbarItem.js +3 -10
- package/dist/components/core/navbar-item/NavbarItem.types.d.ts +4 -1
- package/dist/components/core/navbar-item/NavbarItem.types.js +1 -1
- package/dist/components/core/navbar-item/navbar-item-impl.css +10 -0
- package/dist/components/core/navbar-menu/navbar-menu-impl.css +9 -0
- package/dist/components/core/navbar-switcher/navbar-switcher-impl.css +19 -0
- package/dist/components/core/pagination/Pagination.js +1 -1
- package/dist/components/core/pagination/pagination-impl.css +9 -0
- package/dist/components/core/pagination-dots/PaginationDots.d.ts +1 -1
- package/dist/components/core/pagination-dots/PaginationDots.js +3 -3
- package/dist/components/core/pagination-dots/PaginationDots.types.d.ts +3 -1
- package/dist/components/core/segmented-control/SegmentedControl.css +4 -3
- package/dist/components/core/segmented-control/SegmentedControl.js +17 -3
- package/dist/components/core/segmented-control-item/SegmentedControlItem.css +2 -1
- package/dist/components/core/select/Select.js +3 -3
- package/dist/components/core/select/Select.types.d.ts +11 -1
- package/dist/components/core/select/Select.types.js +1 -1
- package/dist/components/core/tab-list/TabList.js +9 -1
- package/dist/components/core/table-header-cell/TableHeaderCell.d.ts +1 -1
- package/dist/components/core/table-header-cell/TableHeaderCell.js +5 -2
- package/dist/components/core/table-header-cell/TableHeaderCell.types.d.ts +7 -1
- package/dist/components/core/table-header-cell/TableHeaderCell.types.js +1 -1
- package/dist/components/core/text-area/TextArea.d.ts +1 -1
- package/dist/components/core/text-area/TextArea.js +2 -2
- package/dist/components/core/text-area/TextArea.types.d.ts +9 -1
- package/dist/components/core/text-area/TextArea.types.js +1 -1
- package/dist/components/core/text-input/TextInput.d.ts +1 -1
- package/dist/components/core/text-input/TextInput.js +2 -2
- package/dist/components/core/text-input/TextInput.types.d.ts +9 -1
- package/dist/components/core/text-input/TextInput.types.js +1 -1
- package/dist/components/data-table-data.d.ts +33 -0
- package/dist/components/data-table-data.js +12 -0
- package/dist/components/download-banner-data.d.ts +52 -0
- package/dist/components/download-banner-data.js +11 -0
- package/dist/components/index.d.ts +51 -0
- package/dist/components/index.js +38 -0
- package/dist/components/resource-banner-data.d.ts +34 -0
- package/dist/components/resource-banner-data.js +13 -0
- package/dist/components/scene-scroll-data.d.ts +24 -0
- package/dist/components/scene-scroll-data.js +9 -0
- package/dist/components/stats-data.d.ts +28 -0
- package/dist/components/stats-data.js +11 -0
- package/dist/components/steps-data.d.ts +38 -0
- package/dist/components/steps-data.js +13 -0
- package/dist/components/sticky-cards-data.d.ts +43 -0
- package/dist/components/sticky-cards-data.js +12 -0
- package/dist/components/team-grid-data.d.ts +38 -0
- package/dist/components/team-grid-data.js +11 -0
- package/dist/components/tiers-data.d.ts +47 -0
- package/dist/components/tiers-data.js +13 -0
- package/dist/marketing.css +101 -28
- package/package.json +1 -1
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
/**
|
|
3
|
+
* What every pattern's shader is given. Positions are in the band's own terms: `uv` runs 0 to 1 left
|
|
4
|
+
* to right and top to bottom, `px` is the same point in CSS pixels, and the pointer is in `uv`.
|
|
5
|
+
*/
|
|
6
|
+
const PRELUDE = `
|
|
7
|
+
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
8
|
+
precision highp float;
|
|
9
|
+
#else
|
|
10
|
+
precision mediump float;
|
|
11
|
+
#endif
|
|
12
|
+
uniform vec2 u_size; // the band, in CSS pixels
|
|
13
|
+
uniform float u_scale; // device pixels to the CSS pixel, as drawn
|
|
14
|
+
uniform float u_time; // seconds of motion so far
|
|
15
|
+
uniform vec2 u_pointer; // where the light is, eased after the pointer, in uv
|
|
16
|
+
uniform float u_hover; // 0 to 1, how present the pointer is, eased
|
|
17
|
+
uniform float u_strength; // how strongly the pattern is painted on this ground
|
|
18
|
+
uniform float u_grain; // how much grain is laid over it
|
|
19
|
+
uniform float u_pitch; // a length the pattern repeats at, in CSS pixels, where it has one
|
|
20
|
+
uniform float u_hairline; // a hairline's width, in CSS pixels
|
|
21
|
+
uniform float u_shade; // how far a pattern's deepest ink is held back, where it has one
|
|
22
|
+
uniform vec3 u_ink0; // the ground
|
|
23
|
+
uniform vec3 u_ink1;
|
|
24
|
+
uniform vec3 u_ink2;
|
|
25
|
+
uniform vec3 u_ink3;
|
|
26
|
+
uniform vec3 u_ink4;
|
|
27
|
+
uniform vec3 u_ink5;
|
|
28
|
+
|
|
29
|
+
float hash(vec2 p) {
|
|
30
|
+
p = fract(p * vec2(123.34, 456.21));
|
|
31
|
+
p += dot(p, p + 45.32);
|
|
32
|
+
return fract(p.x * p.y);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Value noise with a quintic fade, smooth to the second derivative so no crease shows in a fold.
|
|
36
|
+
float noise(vec2 p) {
|
|
37
|
+
vec2 i = floor(p);
|
|
38
|
+
vec2 f = fract(p);
|
|
39
|
+
vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
|
|
40
|
+
float a = hash(i);
|
|
41
|
+
float b = hash(i + vec2(1.0, 0.0));
|
|
42
|
+
float c = hash(i + vec2(0.0, 1.0));
|
|
43
|
+
float d = hash(i + vec2(1.0, 1.0));
|
|
44
|
+
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Four octaves, each turned against the last, so the layers never line up into a grid. A fifth
|
|
48
|
+
// added detail too fine to see under the grain, at a fifth more of the cost.
|
|
49
|
+
float fbm(vec2 p) {
|
|
50
|
+
float sum = 0.0;
|
|
51
|
+
float amp = 0.5;
|
|
52
|
+
mat2 turn = mat2(0.8, 0.6, -0.6, 0.8);
|
|
53
|
+
for (int k = 0; k < 4; k++) {
|
|
54
|
+
sum += amp * noise(p);
|
|
55
|
+
p = turn * p * 2.03 + 17.1;
|
|
56
|
+
amp *= 0.5;
|
|
57
|
+
}
|
|
58
|
+
return sum;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// A grain that changes every frame, and the dither that keeps a long gradient from banding.
|
|
62
|
+
vec3 grain(vec3 colour, vec2 frag) {
|
|
63
|
+
float n = hash(frag + fract(u_time * 7.13) * 91.7) - 0.5;
|
|
64
|
+
return colour + n * u_grain;
|
|
65
|
+
}
|
|
66
|
+
`;
|
|
67
|
+
const VERTEX = `
|
|
68
|
+
attribute vec2 a_position;
|
|
69
|
+
void main() { gl_Position = vec4(a_position, 0.0, 1.0); }
|
|
70
|
+
`;
|
|
71
|
+
/** A computed colour as linear-ish RGB from 0 to 1. Accepts rgb(), rgba() and color(srgb …). */
|
|
72
|
+
function channels(value) {
|
|
73
|
+
const numbers = value.match(/-?[\d.]+/g)?.map(Number) ?? [];
|
|
74
|
+
if (value.startsWith('color('))
|
|
75
|
+
return [numbers[0] ?? 0, numbers[1] ?? 0, numbers[2] ?? 0];
|
|
76
|
+
return [(numbers[0] ?? 0) / 255, (numbers[1] ?? 0) / 255, (numbers[2] ?? 0) / 255];
|
|
77
|
+
}
|
|
78
|
+
/** A custom property's colour, as the browser resolves it on this element. */
|
|
79
|
+
function ink(element, property) {
|
|
80
|
+
const before = element.style.color;
|
|
81
|
+
element.style.color = `var(${property})`;
|
|
82
|
+
const resolved = getComputedStyle(element).color;
|
|
83
|
+
element.style.color = before;
|
|
84
|
+
return channels(resolved);
|
|
85
|
+
}
|
|
86
|
+
function numberOf(element, property, fallback) {
|
|
87
|
+
const parsed = Number.parseFloat(getComputedStyle(element).getPropertyValue(property));
|
|
88
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
89
|
+
}
|
|
90
|
+
function milliseconds(value, fallback) {
|
|
91
|
+
const amount = Number.parseFloat(value);
|
|
92
|
+
if (!Number.isFinite(amount))
|
|
93
|
+
return fallback;
|
|
94
|
+
return /ms$/i.test(value.trim()) ? amount : amount * 1000;
|
|
95
|
+
}
|
|
96
|
+
function compile(gl, type, source) {
|
|
97
|
+
const shader = gl.createShader(type);
|
|
98
|
+
if (shader === null)
|
|
99
|
+
return null;
|
|
100
|
+
gl.shaderSource(shader, source);
|
|
101
|
+
gl.compileShader(shader);
|
|
102
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
103
|
+
// A pattern that does not compile falls back to the stylesheet; say why, once, for whoever is
|
|
104
|
+
// writing the shader.
|
|
105
|
+
console.warn('Background shader:', gl.getShaderInfoLog(shader));
|
|
106
|
+
gl.deleteShader(shader);
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
return shader;
|
|
110
|
+
}
|
|
111
|
+
export function shader(root, canvas, options) {
|
|
112
|
+
const nothing = { destroy: () => { } };
|
|
113
|
+
const gl = canvas.getContext('webgl', { alpha: false, antialias: false, premultipliedAlpha: false, powerPreference: 'low-power' });
|
|
114
|
+
if (gl === null)
|
|
115
|
+
return nothing;
|
|
116
|
+
const vertex = compile(gl, gl.VERTEX_SHADER, VERTEX);
|
|
117
|
+
const fragment = compile(gl, gl.FRAGMENT_SHADER, PRELUDE + options.fragment);
|
|
118
|
+
if (vertex === null || fragment === null)
|
|
119
|
+
return nothing;
|
|
120
|
+
const program = gl.createProgram();
|
|
121
|
+
if (program === null)
|
|
122
|
+
return nothing;
|
|
123
|
+
gl.attachShader(program, vertex);
|
|
124
|
+
gl.attachShader(program, fragment);
|
|
125
|
+
gl.linkProgram(program);
|
|
126
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
|
|
127
|
+
return nothing;
|
|
128
|
+
gl.useProgram(program);
|
|
129
|
+
// One triangle larger than the screen: every pixel of the band, one draw.
|
|
130
|
+
const buffer = gl.createBuffer();
|
|
131
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
132
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
|
|
133
|
+
const position = gl.getAttribLocation(program, 'a_position');
|
|
134
|
+
gl.enableVertexAttribArray(position);
|
|
135
|
+
gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
|
|
136
|
+
const at = (name) => gl.getUniformLocation(program, name);
|
|
137
|
+
const u = {
|
|
138
|
+
size: at('u_size'),
|
|
139
|
+
scale: at('u_scale'),
|
|
140
|
+
time: at('u_time'),
|
|
141
|
+
pointer: at('u_pointer'),
|
|
142
|
+
hover: at('u_hover'),
|
|
143
|
+
strength: at('u_strength'),
|
|
144
|
+
grain: at('u_grain'),
|
|
145
|
+
pitch: at('u_pitch'),
|
|
146
|
+
hairline: at('u_hairline'),
|
|
147
|
+
shade: at('u_shade'),
|
|
148
|
+
inks: [0, 1, 2, 3, 4, 5].map((k) => at(`u_ink${k}`)),
|
|
149
|
+
};
|
|
150
|
+
const still = typeof window.matchMedia === 'function' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
151
|
+
const moving = options.animated && !still;
|
|
152
|
+
const answering = options.interactive && !still;
|
|
153
|
+
/** Everything read from the stylesheet: the inks, the strengths, the measures, the timing. */
|
|
154
|
+
let follow = 500;
|
|
155
|
+
const read = () => {
|
|
156
|
+
options.inks.forEach((property, k) => {
|
|
157
|
+
const location = u.inks[k];
|
|
158
|
+
if (location !== undefined)
|
|
159
|
+
gl.uniform3fv(location, ink(root, property));
|
|
160
|
+
});
|
|
161
|
+
gl.uniform1f(u.strength, numberOf(root, '--dds-background-gl-strength', 1));
|
|
162
|
+
gl.uniform1f(u.grain, numberOf(root, '--dds-background-gl-grain', 0.04));
|
|
163
|
+
gl.uniform1f(u.pitch, numberOf(root, '--dds-background-gl-pitch', 96));
|
|
164
|
+
gl.uniform1f(u.hairline, numberOf(root, '--dds-background-gl-hairline', 1));
|
|
165
|
+
// Read off the mesh's own element, which is where the stylesheet keeps it per tone.
|
|
166
|
+
const mesh = root.querySelector('.dds-background__mesh') ?? root;
|
|
167
|
+
gl.uniform1f(u.shade, numberOf(mesh, '--dds-background-mesh-shade', 1));
|
|
168
|
+
gl.uniform1f(u.shade, numberOf(root, '--dds-background-mesh-shade', 1));
|
|
169
|
+
follow = milliseconds(getComputedStyle(root).getPropertyValue('--motion-duration-trail'), 500);
|
|
170
|
+
};
|
|
171
|
+
let width = 0;
|
|
172
|
+
let height = 0;
|
|
173
|
+
const resize = () => {
|
|
174
|
+
const box = root.getBoundingClientRect();
|
|
175
|
+
width = Math.max(1, box.width);
|
|
176
|
+
height = Math.max(1, box.height);
|
|
177
|
+
const density = Math.min(window.devicePixelRatio || 1, options.density);
|
|
178
|
+
canvas.width = Math.round(width * density);
|
|
179
|
+
canvas.height = Math.round(height * density);
|
|
180
|
+
gl.viewport(0, 0, canvas.width, canvas.height);
|
|
181
|
+
gl.uniform2f(u.size, width, height);
|
|
182
|
+
gl.uniform1f(u.scale, density);
|
|
183
|
+
};
|
|
184
|
+
// Where the light is and where it is going. It rests a little above the middle of the band's foot.
|
|
185
|
+
const rest = { x: 0.5, y: 0.85 };
|
|
186
|
+
const light = { ...rest, hover: 0 };
|
|
187
|
+
const target = { ...rest, hover: 0 };
|
|
188
|
+
let time = 0;
|
|
189
|
+
let last = 0;
|
|
190
|
+
let frame = 0;
|
|
191
|
+
let visible = true;
|
|
192
|
+
let drawn = false;
|
|
193
|
+
let lost = false;
|
|
194
|
+
let skip = false;
|
|
195
|
+
const draw = (now) => {
|
|
196
|
+
frame = 0;
|
|
197
|
+
if (lost)
|
|
198
|
+
return;
|
|
199
|
+
const step = last === 0 ? 0 : Math.min(0.1, (now - last) / 1000);
|
|
200
|
+
last = now;
|
|
201
|
+
// At rest it moves only if asked to; under the pointer it moves either way — a band asked to
|
|
202
|
+
// hold still flows while somebody is over it, and stops where it is when they leave.
|
|
203
|
+
const flowing = moving || (answering && target.hover > 0);
|
|
204
|
+
if (flowing)
|
|
205
|
+
time = (time + step) % 3600;
|
|
206
|
+
// Ease the light after its target: most of the gap closed within the trail duration.
|
|
207
|
+
const ease = step === 0 ? 1 : 1 - Math.exp((-step * 1000 * 3) / follow);
|
|
208
|
+
light.x += (target.x - light.x) * ease;
|
|
209
|
+
light.y += (target.y - light.y) * ease;
|
|
210
|
+
light.hover += (target.hover - light.hover) * ease;
|
|
211
|
+
const settling = Math.abs(target.x - light.x) + Math.abs(target.y - light.y) + Math.abs(target.hover - light.hover) > 0.001;
|
|
212
|
+
gl.uniform1f(u.time, time);
|
|
213
|
+
gl.uniform2f(u.pointer, light.x, light.y);
|
|
214
|
+
gl.uniform1f(u.hover, light.hover);
|
|
215
|
+
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
216
|
+
if (!drawn) {
|
|
217
|
+
drawn = true;
|
|
218
|
+
root.dataset['shaded'] = 'true';
|
|
219
|
+
}
|
|
220
|
+
// Keep going while there is something to show: the pattern moving, or the light still arriving.
|
|
221
|
+
if (visible && (flowing || settling))
|
|
222
|
+
schedule(settling);
|
|
223
|
+
};
|
|
224
|
+
// At rest, every other frame; while the light is arriving, every frame.
|
|
225
|
+
const schedule = (urgent) => {
|
|
226
|
+
if (frame !== 0)
|
|
227
|
+
return;
|
|
228
|
+
frame = requestAnimationFrame((now) => {
|
|
229
|
+
skip = !skip;
|
|
230
|
+
if (!urgent && skip) {
|
|
231
|
+
frame = 0;
|
|
232
|
+
schedule(false);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
draw(now);
|
|
236
|
+
});
|
|
237
|
+
};
|
|
238
|
+
read();
|
|
239
|
+
resize();
|
|
240
|
+
schedule(true);
|
|
241
|
+
const sizes = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(() => {
|
|
242
|
+
resize();
|
|
243
|
+
schedule(true);
|
|
244
|
+
});
|
|
245
|
+
sizes?.observe(root);
|
|
246
|
+
const sight = typeof IntersectionObserver === 'undefined'
|
|
247
|
+
? null
|
|
248
|
+
: new IntersectionObserver(([entry]) => {
|
|
249
|
+
visible = entry?.isIntersecting ?? true;
|
|
250
|
+
last = 0;
|
|
251
|
+
if (visible)
|
|
252
|
+
schedule(true);
|
|
253
|
+
});
|
|
254
|
+
sight?.observe(root);
|
|
255
|
+
// A tone or a theme that changes under the band changes its inks.
|
|
256
|
+
const restyle = new MutationObserver(() => {
|
|
257
|
+
read();
|
|
258
|
+
schedule(true);
|
|
259
|
+
});
|
|
260
|
+
restyle.observe(root, { attributes: true, attributeFilter: ['data-tone'] });
|
|
261
|
+
const themed = root.closest('[data-theme]');
|
|
262
|
+
if (themed !== null)
|
|
263
|
+
restyle.observe(themed, { attributes: true, attributeFilter: ['data-theme'] });
|
|
264
|
+
const host = options.host ?? root;
|
|
265
|
+
const move = (event) => {
|
|
266
|
+
if (event.pointerType === 'touch')
|
|
267
|
+
return;
|
|
268
|
+
const box = root.getBoundingClientRect();
|
|
269
|
+
target.x = (event.clientX - box.left) / box.width;
|
|
270
|
+
target.y = (event.clientY - box.top) / box.height;
|
|
271
|
+
target.hover = 1;
|
|
272
|
+
schedule(true);
|
|
273
|
+
};
|
|
274
|
+
const leave = () => {
|
|
275
|
+
target.x = rest.x;
|
|
276
|
+
target.y = rest.y;
|
|
277
|
+
target.hover = 0;
|
|
278
|
+
schedule(true);
|
|
279
|
+
};
|
|
280
|
+
if (answering) {
|
|
281
|
+
host.addEventListener('pointermove', move, { passive: true });
|
|
282
|
+
host.addEventListener('pointerleave', leave, { passive: true });
|
|
283
|
+
}
|
|
284
|
+
const onLost = (event) => {
|
|
285
|
+
event.preventDefault();
|
|
286
|
+
lost = true;
|
|
287
|
+
delete root.dataset['shaded'];
|
|
288
|
+
};
|
|
289
|
+
canvas.addEventListener('webglcontextlost', onLost);
|
|
290
|
+
return {
|
|
291
|
+
destroy: () => {
|
|
292
|
+
if (frame !== 0)
|
|
293
|
+
cancelAnimationFrame(frame);
|
|
294
|
+
sizes?.disconnect();
|
|
295
|
+
sight?.disconnect();
|
|
296
|
+
restyle.disconnect();
|
|
297
|
+
host.removeEventListener('pointermove', move);
|
|
298
|
+
host.removeEventListener('pointerleave', leave);
|
|
299
|
+
canvas.removeEventListener('webglcontextlost', onLost);
|
|
300
|
+
delete root.dataset['shaded'];
|
|
301
|
+
gl.deleteProgram(program);
|
|
302
|
+
gl.deleteShader(vertex);
|
|
303
|
+
gl.deleteShader(fragment);
|
|
304
|
+
gl.deleteBuffer(buffer);
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* A halftone mounted on a band: the band to observe and listen on, and the canvas to draw in.
|
|
4
|
+
*
|
|
5
|
+
* Shared by Background and by the blocks that can stand on the same pattern, so there is one
|
|
6
|
+
* painter and one set of rules about when it draws. Returns the two refs to place; `enabled` false
|
|
7
|
+
* mounts nothing, which is a block without the option asked for.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useHalftone<Band extends HTMLElement>(enabled: boolean, interactive: boolean,
|
|
10
|
+
/** Whether the glow drifts on its own while nothing is happening. */
|
|
11
|
+
animated: boolean,
|
|
12
|
+
/** Anything whose change should re-read the tokens — a tone that changes the ink. */
|
|
13
|
+
key?: string,
|
|
14
|
+
/** Listen for the pointer on the band's parent rather than the band: a Background used as a layer. */
|
|
15
|
+
onParent?: boolean): [RefObject<Band | null>, RefObject<HTMLCanvasElement | null>];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import { halftone } from './halftone.js';
|
|
4
|
+
/**
|
|
5
|
+
* A halftone mounted on a band: the band to observe and listen on, and the canvas to draw in.
|
|
6
|
+
*
|
|
7
|
+
* Shared by Background and by the blocks that can stand on the same pattern, so there is one
|
|
8
|
+
* painter and one set of rules about when it draws. Returns the two refs to place; `enabled` false
|
|
9
|
+
* mounts nothing, which is a block without the option asked for.
|
|
10
|
+
*/
|
|
11
|
+
export function useHalftone(enabled, interactive,
|
|
12
|
+
/** Whether the glow drifts on its own while nothing is happening. */
|
|
13
|
+
animated,
|
|
14
|
+
/** Anything whose change should re-read the tokens — a tone that changes the ink. */
|
|
15
|
+
key,
|
|
16
|
+
/** Listen for the pointer on the band's parent rather than the band: a Background used as a layer. */
|
|
17
|
+
onParent = false) {
|
|
18
|
+
const band = useRef(null);
|
|
19
|
+
const canvas = useRef(null);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!enabled || band.current === null || canvas.current === null)
|
|
22
|
+
return undefined;
|
|
23
|
+
const host = onParent ? (band.current.parentElement ?? undefined) : undefined;
|
|
24
|
+
return halftone(band.current, canvas.current, { interactive, animated, host }).destroy;
|
|
25
|
+
}, [enabled, interactive, animated, key, onParent]);
|
|
26
|
+
return [band, canvas];
|
|
27
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Whether a band is off screen, written onto it as `data-offscreen` so the stylesheet can pause
|
|
4
|
+
* the motion it runs at rest. A pattern the stylesheet animates repaints the band each frame, and
|
|
5
|
+
* nobody sees a band move that is not on screen; the halftone pauses itself the same way.
|
|
6
|
+
*
|
|
7
|
+
* `enabled` false observes nothing — a pattern that does not move at rest, or the halftone, whose
|
|
8
|
+
* painter has its own observer.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useOffscreen(band: RefObject<HTMLElement | null>, enabled: boolean): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Whether a band is off screen, written onto it as `data-offscreen` so the stylesheet can pause
|
|
5
|
+
* the motion it runs at rest. A pattern the stylesheet animates repaints the band each frame, and
|
|
6
|
+
* nobody sees a band move that is not on screen; the halftone pauses itself the same way.
|
|
7
|
+
*
|
|
8
|
+
* `enabled` false observes nothing — a pattern that does not move at rest, or the halftone, whose
|
|
9
|
+
* painter has its own observer.
|
|
10
|
+
*/
|
|
11
|
+
export function useOffscreen(band, enabled) {
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const root = band.current;
|
|
14
|
+
if (!enabled || root === null || typeof IntersectionObserver === 'undefined')
|
|
15
|
+
return undefined;
|
|
16
|
+
const sight = new IntersectionObserver(([entry]) => {
|
|
17
|
+
if (entry === undefined)
|
|
18
|
+
return;
|
|
19
|
+
if (entry.isIntersecting)
|
|
20
|
+
delete root.dataset['offscreen'];
|
|
21
|
+
else
|
|
22
|
+
root.dataset['offscreen'] = 'true';
|
|
23
|
+
});
|
|
24
|
+
sight.observe(root);
|
|
25
|
+
return () => {
|
|
26
|
+
sight.disconnect();
|
|
27
|
+
delete root.dataset['offscreen'];
|
|
28
|
+
};
|
|
29
|
+
}, [band, enabled]);
|
|
30
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import { type ShadedPattern } from './patterns.js';
|
|
3
|
+
/**
|
|
4
|
+
* A shaded pattern mounted on a band: the band to observe and listen on, and the canvas to draw in.
|
|
5
|
+
* `pattern` undefined mounts nothing — the halftone, which has its own painter.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useShader<Band extends HTMLElement>(band: RefObject<Band | null>, pattern: ShadedPattern | undefined, interactive: boolean, animated: boolean,
|
|
8
|
+
/** Anything whose change should re-read the inks — a tone. */
|
|
9
|
+
key?: string,
|
|
10
|
+
/** Listen for the pointer on the band's parent rather than the band: a Background used as a layer. */
|
|
11
|
+
onParent?: boolean): RefObject<HTMLCanvasElement | null>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import { SHADERS } from './patterns.js';
|
|
4
|
+
import { shader } from './shader.js';
|
|
5
|
+
/** The inks every shaded pattern reads, ground first; the stylesheet sets them per pattern and tone. */
|
|
6
|
+
const INKS = [0, 1, 2, 3, 4, 5].map((k) => `--dds-background-gl-ink${k}`);
|
|
7
|
+
/**
|
|
8
|
+
* A shaded pattern mounted on a band: the band to observe and listen on, and the canvas to draw in.
|
|
9
|
+
* `pattern` undefined mounts nothing — the halftone, which has its own painter.
|
|
10
|
+
*/
|
|
11
|
+
export function useShader(band, pattern, interactive, animated,
|
|
12
|
+
/** Anything whose change should re-read the inks — a tone. */
|
|
13
|
+
key,
|
|
14
|
+
/** Listen for the pointer on the band's parent rather than the band: a Background used as a layer. */
|
|
15
|
+
onParent = false) {
|
|
16
|
+
const canvas = useRef(null);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (pattern === undefined || band.current === null || canvas.current === null)
|
|
19
|
+
return undefined;
|
|
20
|
+
const host = onParent ? (band.current.parentElement ?? undefined) : undefined;
|
|
21
|
+
const { fragment, density } = SHADERS[pattern];
|
|
22
|
+
return shader(band.current, canvas.current, { fragment, density, inks: INKS, interactive, animated, host }).destroy;
|
|
23
|
+
}, [band, pattern, interactive, animated, key, onParent]);
|
|
24
|
+
return canvas;
|
|
25
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The pointer's light on a pattern the stylesheet paints: where the pointer is, written onto the
|
|
4
|
+
* band as two custom properties the stylesheet centres its light on — a brighter copy of the grid
|
|
5
|
+
* or the rings, the aurora's trailing pool — the same place as a lean from the middle, which the
|
|
6
|
+
* mesh's pools follow, and whether it is over the band.
|
|
7
|
+
*
|
|
8
|
+
* Events only record the pointer; the position is written once a frame, so a fast mouse costs one
|
|
9
|
+
* style write a frame rather than one per event. Nothing runs while the pointer is elsewhere. A
|
|
10
|
+
* touch has no hover to follow, so it lights nothing, and `enabled` false listens for nothing.
|
|
11
|
+
*/
|
|
12
|
+
export declare function useSpotlight(band: RefObject<HTMLElement | null>, enabled: boolean,
|
|
13
|
+
/** Listen on the band's parent: a Background used as a layer under a block's content. */
|
|
14
|
+
onParent?: boolean): void;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* The pointer's light on a pattern the stylesheet paints: where the pointer is, written onto the
|
|
5
|
+
* band as two custom properties the stylesheet centres its light on — a brighter copy of the grid
|
|
6
|
+
* or the rings, the aurora's trailing pool — the same place as a lean from the middle, which the
|
|
7
|
+
* mesh's pools follow, and whether it is over the band.
|
|
8
|
+
*
|
|
9
|
+
* Events only record the pointer; the position is written once a frame, so a fast mouse costs one
|
|
10
|
+
* style write a frame rather than one per event. Nothing runs while the pointer is elsewhere. A
|
|
11
|
+
* touch has no hover to follow, so it lights nothing, and `enabled` false listens for nothing.
|
|
12
|
+
*/
|
|
13
|
+
export function useSpotlight(band, enabled,
|
|
14
|
+
/** Listen on the band's parent: a Background used as a layer under a block's content. */
|
|
15
|
+
onParent = false) {
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const root = band.current;
|
|
18
|
+
if (!enabled || root === null)
|
|
19
|
+
return undefined;
|
|
20
|
+
// A layer takes no pointer events and the content covers it, so the pointer is listened for on
|
|
21
|
+
// the band around it. The layer fills that band, so positions measured against it agree.
|
|
22
|
+
const host = onParent ? (root.parentElement ?? root) : root;
|
|
23
|
+
let frame = 0;
|
|
24
|
+
let clientX = 0;
|
|
25
|
+
let clientY = 0;
|
|
26
|
+
const write = () => {
|
|
27
|
+
frame = 0;
|
|
28
|
+
const box = root.getBoundingClientRect();
|
|
29
|
+
root.style.setProperty('--dds-background-spot-x', `${clientX - box.left}px`);
|
|
30
|
+
root.style.setProperty('--dds-background-spot-y', `${clientY - box.top}px`);
|
|
31
|
+
// And as a lean, -1 to 1 each way from the band's middle, for the mesh's pools to follow by
|
|
32
|
+
// their depth: CSS cannot divide one length by another to get there itself.
|
|
33
|
+
root.style.setProperty('--dds-background-lean-x', String(((clientX - box.left) / box.width) * 2 - 1));
|
|
34
|
+
root.style.setProperty('--dds-background-lean-y', String(((clientY - box.top) / box.height) * 2 - 1));
|
|
35
|
+
};
|
|
36
|
+
const move = (event) => {
|
|
37
|
+
if (event.pointerType === 'touch')
|
|
38
|
+
return;
|
|
39
|
+
clientX = event.clientX;
|
|
40
|
+
clientY = event.clientY;
|
|
41
|
+
if (root.dataset['spotlit'] !== 'true') {
|
|
42
|
+
// Arriving: place the light under the pointer before lighting it, and let the browser
|
|
43
|
+
// take that position in — reading the aurora pool's computed transform does — so what
|
|
44
|
+
// fades in is already where the pointer is, rather than easing over from where it last
|
|
45
|
+
// was. Unlit, the pool does not trail, so the move is instant.
|
|
46
|
+
if (frame !== 0)
|
|
47
|
+
cancelAnimationFrame(frame);
|
|
48
|
+
frame = 0;
|
|
49
|
+
write();
|
|
50
|
+
void getComputedStyle(root, '::after').transform;
|
|
51
|
+
root.dataset['spotlit'] = 'true';
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (frame === 0)
|
|
55
|
+
frame = requestAnimationFrame(write);
|
|
56
|
+
};
|
|
57
|
+
const leave = () => {
|
|
58
|
+
delete root.dataset['spotlit'];
|
|
59
|
+
// The mesh's pools ease back to where they rest.
|
|
60
|
+
root.style.removeProperty('--dds-background-lean-x');
|
|
61
|
+
root.style.removeProperty('--dds-background-lean-y');
|
|
62
|
+
};
|
|
63
|
+
host.addEventListener('pointermove', move, { passive: true });
|
|
64
|
+
host.addEventListener('pointerleave', leave, { passive: true });
|
|
65
|
+
return () => {
|
|
66
|
+
host.removeEventListener('pointermove', move);
|
|
67
|
+
host.removeEventListener('pointerleave', leave);
|
|
68
|
+
if (frame !== 0)
|
|
69
|
+
cancelAnimationFrame(frame);
|
|
70
|
+
delete root.dataset['spotlit'];
|
|
71
|
+
};
|
|
72
|
+
}, [band, enabled, onParent]);
|
|
73
|
+
}
|
|
@@ -63,7 +63,7 @@ const FOCUSABLE = [
|
|
|
63
63
|
* disagree eventually, and the consumer is the one that has to win.
|
|
64
64
|
*/
|
|
65
65
|
export function BottomSheet(props) {
|
|
66
|
-
const { open = bottomSheetDefaults.open, height = bottomSheetDefaults.height, title, showTitle = bottomSheetDefaults.showTitle, description, back, action, showClose = bottomSheetDefaults.showClose, showHandle = bottomSheetDefaults.showHandle, onOpenChange, children, id, ...rest } = props;
|
|
66
|
+
const { open = bottomSheetDefaults.open, height = bottomSheetDefaults.height, title, closeLabel, showTitle = bottomSheetDefaults.showTitle, description, back, action, showClose = bottomSheetDefaults.showClose, showHandle = bottomSheetDefaults.showHandle, onOpenChange, children, id, ...rest } = props;
|
|
67
67
|
const fallbackId = useId();
|
|
68
68
|
const rootId = id ?? fallbackId;
|
|
69
69
|
const titleId = `${rootId}-title`;
|
|
@@ -335,7 +335,7 @@ export function BottomSheet(props) {
|
|
|
335
335
|
/* The compact step. A sheet's exit sits on the row that names it, beside a title at the
|
|
336
336
|
smallest heading step — at the default size the button stood taller than the words it
|
|
337
337
|
sat next to and read as the loudest thing in the header. */
|
|
338
|
-
size: "sm", label: `Close ${title}`,
|
|
338
|
+
size: "sm", label: closeLabel ?? `Close ${title}`,
|
|
339
339
|
/* The bare glyph, not wrapped in an Icon. Which step belongs in a button of this size is
|
|
340
340
|
ButtonIcon's own rule and it applies it by cloning — an Icon around it puts `dds-icon`
|
|
341
341
|
on the svg at Icon's own default instead, which is a step and a half larger and beats
|
|
@@ -26,10 +26,12 @@ export interface BottomSheetOwnProps {
|
|
|
26
26
|
|
|
27
27
|
The second argument is which of the four ways out the reader took, for a page that treats an abandoned task differently from a finished one. It is only ever called with false today — a sheet is opened by whatever opens it, never by itself — and the boolean is first anyway, so the shape does not have to change if that ever stops being true. */
|
|
28
28
|
onOpenChange: (open: boolean, reason: 'close-button' | 'scrim' | 'escape' | 'drag') => void;
|
|
29
|
+
/** The accessible name of the close button. Without it the button is named "Close" and the title; pass it to translate that with the page. */
|
|
30
|
+
closeLabel?: string;
|
|
29
31
|
/** Allowed: any content */
|
|
30
32
|
children: ReactNode;
|
|
31
33
|
}
|
|
32
|
-
export type BottomSheetProps = BottomSheetOwnProps & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'open' | 'height' | 'title' | 'showTitle' | 'description' | 'showClose' | 'back' | 'action' | 'showHandle' | 'onOpenChange'> & ({
|
|
34
|
+
export type BottomSheetProps = BottomSheetOwnProps & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'open' | 'height' | 'title' | 'showTitle' | 'description' | 'showClose' | 'back' | 'action' | 'showHandle' | 'onOpenChange' | 'closeLabel'> & ({
|
|
33
35
|
showHandle?: boolean;
|
|
34
36
|
showClose?: false;
|
|
35
37
|
} | {
|
|
@@ -3,6 +3,7 @@ import { Children, Fragment } from 'react';
|
|
|
3
3
|
import { ChevronRightRegularIcon } from '@deriv-com/quill-icons-web';
|
|
4
4
|
import { Icon } from '../icon/Icon.js';
|
|
5
5
|
import './Breadcrumb.css';
|
|
6
|
+
import './breadcrumb-impl.css';
|
|
6
7
|
import { breadcrumbDefaults, breadcrumbParts } from './Breadcrumb.types.js';
|
|
7
8
|
/**
|
|
8
9
|
* A `<nav>` holding an ordered list of the levels above the current page.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* What the contract cannot hold: a reading direction.
|
|
3
|
+
*
|
|
4
|
+
* The separator points from one level to the next. A right-to-left trail runs leftward, so the
|
|
5
|
+
* chevron is mirrored to point the way the trail reads — drawn as it ships, it pointed back at the
|
|
6
|
+
* level before it. The contract binds parts in states, and the direction a line is set in is
|
|
7
|
+
* neither.
|
|
8
|
+
*/
|
|
9
|
+
:where([data-dds-context="marketing"]) .dds-breadcrumb .dds-breadcrumb__separator .dds-icon:dir(rtl) {
|
|
10
|
+
scale: -1 1;
|
|
11
|
+
}
|
|
@@ -34,13 +34,26 @@
|
|
|
34
34
|
translate: var(--space-gap-xs);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* A right-to-left line reads leftward, so the arrow points left and the nudge goes left: the mark
|
|
39
|
+
* still moves on in the direction of reading, by the same gap.
|
|
40
|
+
*/
|
|
41
|
+
:where([data-dds-context="marketing"]) .dds-button .dds-button__icon:dir(rtl) {
|
|
42
|
+
scale: -1 1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
:where([data-dds-context="marketing"]) .dds-button:hover .dds-button__icon:dir(rtl) {
|
|
46
|
+
translate: calc(-1 * var(--space-gap-xs));
|
|
47
|
+
}
|
|
48
|
+
|
|
37
49
|
/**
|
|
38
50
|
* A reader who asked for less motion gets none, rather than the same distance travelled
|
|
39
51
|
* instantly. The generated sheet already drops the transition under this query, which on its
|
|
40
52
|
* own would leave the four-pixel jump — the movement, minus the part that made it legible.
|
|
41
53
|
*/
|
|
42
54
|
@media (prefers-reduced-motion: reduce) {
|
|
43
|
-
:where([data-dds-context="marketing"]) .dds-button:hover .dds-button__icon
|
|
55
|
+
:where([data-dds-context="marketing"]) .dds-button:hover .dds-button__icon,
|
|
56
|
+
:where([data-dds-context="marketing"]) .dds-button:hover .dds-button__icon:dir(rtl) {
|
|
44
57
|
translate: 0;
|
|
45
58
|
}
|
|
46
59
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* GENERATED from illustrationcard.contract.json. Do not edit. */
|
|
2
|
+
|
|
3
|
+
:where([data-dds-context="marketing"]) .dds-illustrationcard {
|
|
4
|
+
border-style: solid;
|
|
5
|
+
box-sizing: border-box;
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
inline-size: 100%;
|
|
9
|
+
overflow: hidden;
|
|
10
|
+
text-align: start;
|
|
11
|
+
background-color: var(--color-bg-surface-glass);
|
|
12
|
+
border-color: var(--color-border-subtle);
|
|
13
|
+
border-radius: var(--radius-surface);
|
|
14
|
+
border-width: var(--border-width-hairline);
|
|
15
|
+
color: var(--color-fg-default);
|
|
16
|
+
padding-block: var(--space-inset-card);
|
|
17
|
+
padding-inline: var(--space-inset-card);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
:where([data-dds-context="marketing"]) .dds-illustrationcard .dds-illustrationcard__content {
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
flex-shrink: 0;
|
|
24
|
+
min-block-size: 0;
|
|
25
|
+
user-select: none;
|
|
26
|
+
gap: var(--space-gap-sm);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
:where([data-dds-context="marketing"]) .dds-illustrationcard[data-ratio="landscape"] {
|
|
30
|
+
aspect-ratio: var(--aspect-landscape);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
:where([data-dds-context="marketing"]) .dds-illustrationcard[data-ratio="square"] {
|
|
34
|
+
aspect-ratio: var(--aspect-square);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
:where([data-dds-context="marketing"]) .dds-illustrationcard[data-ratio="upright"] {
|
|
38
|
+
aspect-ratio: var(--aspect-upright);
|
|
39
|
+
}
|
|
40
|
+
|