@smicolon/fasla-ui 0.6.0 → 0.8.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/README.md +24 -5
- package/dist/cli/index.js +2983 -648
- package/dist/index.cjs +50 -12
- package/dist/index.js +50 -12
- package/dist/motion/index.cjs +12 -0
- package/dist/motion/index.d.cts +7 -0
- package/dist/motion/index.d.ts +7 -0
- package/dist/motion/index.js +12 -0
- package/dist/registry/index.cjs +4 -4
- package/dist/registry/index.js +4 -4
- package/dist/tokens/index.cjs +34 -8
- package/dist/tokens/index.d.cts +23 -1
- package/dist/tokens/index.d.ts +23 -1
- package/dist/tokens/index.js +34 -8
- package/package.json +6 -1
- package/registry/blocks/about-approach-stack-cards/AboutApproachStackCards.tsx +305 -0
- package/registry/blocks/about-approach-stack-cards/index.ts +9 -0
- package/registry/blocks/about-bento/AboutBento.tsx +442 -0
- package/registry/blocks/about-bento/index.ts +9 -0
- package/registry/blocks/about-collage-hero/AboutCollageHero.tsx +285 -0
- package/registry/blocks/about-collage-hero/index.ts +8 -0
- package/registry/blocks/about-color-bento/AboutColorBento.tsx +235 -0
- package/registry/blocks/about-color-bento/index.ts +6 -0
- package/registry/blocks/about-culture-masonry/AboutCultureMasonry.tsx +305 -0
- package/registry/blocks/about-culture-masonry/index.ts +9 -0
- package/registry/blocks/about-headline-photos/AboutHeadlinePhotos.tsx +270 -0
- package/registry/blocks/about-headline-photos/index.ts +8 -0
- package/registry/blocks/about-impact-stats-band/AboutImpactStatsBand.test.tsx +45 -0
- package/registry/blocks/about-impact-stats-band/AboutImpactStatsBand.tsx +348 -0
- package/registry/blocks/about-impact-stats-band/index.ts +9 -0
- package/registry/blocks/about-letter-card/AboutLetterCard.tsx +403 -0
- package/registry/blocks/about-letter-card/index.ts +9 -0
- package/registry/blocks/about-mission-statement-hero/AboutMissionStatementHero.tsx +282 -0
- package/registry/blocks/about-mission-statement-hero/index.ts +8 -0
- package/registry/blocks/about-numbered-rows/AboutNumberedRows.tsx +289 -0
- package/registry/blocks/about-numbered-rows/index.ts +7 -0
- package/registry/blocks/about-split-panel/AboutSplitPanel.tsx +247 -0
- package/registry/blocks/about-split-panel/index.ts +8 -0
- package/registry/blocks/about-spotlight/AboutSpotlight.tsx +260 -0
- package/registry/blocks/about-spotlight/index.ts +7 -0
- package/registry/blocks/about-statement-band/AboutStatementBand.tsx +236 -0
- package/registry/blocks/about-statement-band/index.ts +7 -0
- package/registry/blocks/about-story-photos/AboutStoryPhotos.test.tsx +12 -0
- package/registry/blocks/about-story-photos/AboutStoryPhotos.tsx +252 -0
- package/registry/blocks/about-story-photos/index.ts +8 -0
- package/registry/blocks/about-story-snapshots/AboutStorySnapshots.tsx +239 -0
- package/registry/blocks/about-story-snapshots/index.ts +8 -0
- package/registry/blocks/about-type-stack/AboutTypeStack.tsx +205 -0
- package/registry/blocks/about-type-stack/index.ts +6 -0
- package/registry/blocks/about-values-connector-list/AboutValuesConnectorList.tsx +316 -0
- package/registry/blocks/about-values-connector-list/index.ts +7 -0
- package/registry/blocks/about-values-focus/AboutValuesFocus.tsx +303 -0
- package/registry/blocks/about-values-focus/index.ts +8 -0
- package/registry/blocks/about-values-spotlight/AboutValuesSpotlight.tsx +265 -0
- package/registry/blocks/about-values-spotlight/index.ts +8 -0
- package/registry/blocks/auth-centered-card-sign-in/AuthCenteredCardSignIn.tsx +373 -0
- package/registry/blocks/auth-centered-card-sign-in/index.ts +9 -0
- package/registry/blocks/auth-check-your-email/AuthCheckYourEmail.tsx +366 -0
- package/registry/blocks/auth-check-your-email/index.ts +7 -0
- package/registry/blocks/auth-forgot-password/AuthForgotPassword.tsx +265 -0
- package/registry/blocks/auth-forgot-password/index.ts +8 -0
- package/registry/blocks/auth-locked-session-re-authenticate/AuthLockedSessionReAuthenticate.tsx +305 -0
- package/registry/blocks/auth-locked-session-re-authenticate/index.ts +8 -0
- package/registry/blocks/auth-magic-link-request/AuthMagicLinkRequest.tsx +336 -0
- package/registry/blocks/auth-magic-link-request/index.ts +8 -0
- package/registry/blocks/auth-minimal-centered-sign-in/AuthMinimalCenteredSignIn.tsx +261 -0
- package/registry/blocks/auth-minimal-centered-sign-in/index.ts +8 -0
- package/registry/blocks/auth-multi-step-sign-up-wizard/AuthMultiStepSignUpWizard.tsx +460 -0
- package/registry/blocks/auth-multi-step-sign-up-wizard/index.ts +8 -0
- package/registry/blocks/auth-otp-verification/AuthOtpVerification.tsx +348 -0
- package/registry/blocks/auth-otp-verification/index.ts +7 -0
- package/registry/blocks/auth-passkey-sign-in/AuthPasskeySignIn.tsx +294 -0
- package/registry/blocks/auth-passkey-sign-in/index.ts +8 -0
- package/registry/blocks/auth-password-changed/AuthPasswordChanged.tsx +239 -0
- package/registry/blocks/auth-password-changed/index.ts +8 -0
- package/registry/blocks/auth-phone-number-sign-in/AuthPhoneNumberSignIn.tsx +402 -0
- package/registry/blocks/auth-phone-number-sign-in/index.ts +10 -0
- package/registry/blocks/auth-photo-background-sign-in/AuthPhotoBackgroundSignIn.tsx +398 -0
- package/registry/blocks/auth-photo-background-sign-in/index.ts +10 -0
- package/registry/blocks/auth-profile-setup-onboarding/AuthProfileSetupOnboarding.tsx +420 -0
- package/registry/blocks/auth-profile-setup-onboarding/index.ts +7 -0
- package/registry/blocks/auth-qr-device-login/AuthQrDeviceLogin.tsx +303 -0
- package/registry/blocks/auth-qr-device-login/index.ts +7 -0
- package/registry/blocks/auth-reset-password/AuthResetPassword.tsx +313 -0
- package/registry/blocks/auth-reset-password/index.ts +7 -0
- package/registry/blocks/auth-sign-in-error-state/AuthSignInErrorState.tsx +419 -0
- package/registry/blocks/auth-sign-in-error-state/index.ts +9 -0
- package/registry/blocks/auth-sign-up-benefits-column/AuthSignUpBenefitsColumn.tsx +481 -0
- package/registry/blocks/auth-sign-up-benefits-column/index.ts +10 -0
- package/registry/blocks/auth-sign-up-password-strength/AuthSignUpPasswordStrength.tsx +511 -0
- package/registry/blocks/auth-sign-up-password-strength/index.ts +8 -0
- package/registry/blocks/auth-social-first-sign-in/AuthSocialFirstSignIn.tsx +337 -0
- package/registry/blocks/auth-social-first-sign-in/index.ts +9 -0
- package/registry/blocks/auth-split-photo-sign-in/AuthSplitPhotoSignIn.tsx +472 -0
- package/registry/blocks/auth-split-photo-sign-in/index.ts +11 -0
- package/registry/blocks/auth-split-testimonial-sign-up/AuthSplitTestimonialSignUp.tsx +548 -0
- package/registry/blocks/auth-split-testimonial-sign-up/index.ts +11 -0
- package/registry/blocks/auth-tabbed-sign-in-sign-up/AuthTabbedSignInSignUp.tsx +566 -0
- package/registry/blocks/auth-tabbed-sign-in-sign-up/index.ts +11 -0
- package/registry/blocks/auth-team-invite-accept/AuthTeamInviteAccept.tsx +372 -0
- package/registry/blocks/auth-team-invite-accept/index.ts +9 -0
- package/registry/blocks/auth-two-factor-authenticator/AuthTwoFactorAuthenticator.tsx +333 -0
- package/registry/blocks/auth-two-factor-authenticator/index.ts +7 -0
- package/registry/blocks/auth-two-factor-method-chooser/AuthTwoFactorMethodChooser.tsx +290 -0
- package/registry/blocks/auth-two-factor-method-chooser/index.ts +8 -0
- package/registry/blocks/auth-waitlist-early-access/AuthWaitlistEarlyAccess.tsx +430 -0
- package/registry/blocks/auth-waitlist-early-access/index.ts +11 -0
- package/registry/blocks/blog-cards-alongside.test.tsx +176 -0
- package/registry/blocks/blog-cards-author-spotlight/BlogCardsAuthorSpotlight.tsx +342 -0
- package/registry/blocks/blog-cards-author-spotlight/index.ts +6 -0
- package/registry/blocks/blog-cards-bento-editorial-grid/BlogCardsBentoEditorialGrid.tsx +345 -0
- package/registry/blocks/blog-cards-bento-editorial-grid/index.ts +7 -0
- package/registry/blocks/blog-cards-browse.test.tsx +367 -0
- package/registry/blocks/blog-cards-classic-3-up-grid/BlogCardsClassic3UpGrid.tsx +287 -0
- package/registry/blocks/blog-cards-classic-3-up-grid/index.ts +7 -0
- package/registry/blocks/blog-cards-compact-4-up-thumb-grid/BlogCardsCompact4UpThumbGrid.tsx +265 -0
- package/registry/blocks/blog-cards-compact-4-up-thumb-grid/index.ts +7 -0
- package/registry/blocks/blog-cards-dark-editorial-feature/BlogCardsDarkEditorialFeature.tsx +287 -0
- package/registry/blocks/blog-cards-dark-editorial-feature/index.ts +6 -0
- package/registry/blocks/blog-cards-featured-two-up/BlogCardsFeaturedTwoUp.tsx +295 -0
- package/registry/blocks/blog-cards-featured-two-up/index.ts +7 -0
- package/registry/blocks/blog-cards-features.test.tsx +183 -0
- package/registry/blocks/blog-cards-filter-sidebar-results/BlogCardsFilterSidebarResults.tsx +582 -0
- package/registry/blocks/blog-cards-filter-sidebar-results/index.ts +6 -0
- package/registry/blocks/blog-cards-grids.test.tsx +110 -0
- package/registry/blocks/blog-cards-hairline-text-index/BlogCardsHairlineTextIndex.tsx +193 -0
- package/registry/blocks/blog-cards-hairline-text-index/index.ts +7 -0
- package/registry/blocks/blog-cards-journal-bento/BlogCardsJournalBento.tsx +409 -0
- package/registry/blocks/blog-cards-journal-bento/index.ts +8 -0
- package/registry/blocks/blog-cards-latest-popular-split/BlogCardsLatestPopularSplit.tsx +258 -0
- package/registry/blocks/blog-cards-latest-popular-split/index.ts +7 -0
- package/registry/blocks/blog-cards-lead-ranked-picks/BlogCardsLeadRankedPicks.tsx +276 -0
- package/registry/blocks/blog-cards-lead-ranked-picks/index.ts +6 -0
- package/registry/blocks/blog-cards-left-thumb-row-cards/BlogCardsLeftThumbRowCards.tsx +288 -0
- package/registry/blocks/blog-cards-left-thumb-row-cards/index.ts +7 -0
- package/registry/blocks/blog-cards-lists.test.tsx +93 -0
- package/registry/blocks/blog-cards-magazine-cover-story/BlogCardsMagazineCoverStory.tsx +326 -0
- package/registry/blocks/blog-cards-magazine-cover-story/index.ts +6 -0
- package/registry/blocks/blog-cards-newsletter-latest/BlogCardsNewsletterLatest.tsx +291 -0
- package/registry/blocks/blog-cards-newsletter-latest/index.ts +6 -0
- package/registry/blocks/blog-cards-numbered-reading-list/BlogCardsNumberedReadingList.tsx +275 -0
- package/registry/blocks/blog-cards-numbered-reading-list/index.ts +7 -0
- package/registry/blocks/blog-cards-overlay-photo-trio/BlogCardsOverlayPhotoTrio.tsx +279 -0
- package/registry/blocks/blog-cards-overlay-photo-trio/index.ts +7 -0
- package/registry/blocks/blog-cards-post-carousel-with-controls/BlogCardsPostCarouselWithControls.tsx +257 -0
- package/registry/blocks/blog-cards-post-carousel-with-controls/index.ts +6 -0
- package/registry/blocks/blog-cards-pull-quote-feature/BlogCardsPullQuoteFeature.tsx +245 -0
- package/registry/blocks/blog-cards-pull-quote-feature/index.ts +6 -0
- package/registry/blocks/blog-cards-related-posts-strip/BlogCardsRelatedPostsStrip.tsx +247 -0
- package/registry/blocks/blog-cards-related-posts-strip/index.ts +6 -0
- package/registry/blocks/blog-cards-search-chips-results/BlogCardsSearchChipsResults.tsx +473 -0
- package/registry/blocks/blog-cards-search-chips-results/index.ts +6 -0
- package/registry/blocks/blog-cards-split-feature/BlogCardsSplitFeature.tsx +214 -0
- package/registry/blocks/blog-cards-split-feature/index.ts +6 -0
- package/registry/blocks/careers/careers.test.tsx +414 -0
- package/registry/blocks/careers/careers.tsx +391 -0
- package/registry/blocks/careers/index.ts +27 -0
- package/registry/blocks/careers-about-card-role-list/CareersAboutCardRoleList.tsx +235 -0
- package/registry/blocks/careers-about-card-role-list/index.ts +8 -0
- package/registry/blocks/careers-featured-role-spotlight/CareersFeaturedRoleSpotlight.tsx +271 -0
- package/registry/blocks/careers-featured-role-spotlight/index.ts +8 -0
- package/registry/blocks/careers-no-open-roles-empty-state/CareersNoOpenRolesEmptyState.tsx +330 -0
- package/registry/blocks/careers-no-open-roles-empty-state/index.ts +8 -0
- package/registry/blocks/careers-open-roles-hairline-list/CareersOpenRolesHairlineList.tsx +320 -0
- package/registry/blocks/careers-open-roles-hairline-list/index.ts +6 -0
- package/registry/blocks/careers-open-vacancies-table/CareersOpenVacanciesTable.tsx +493 -0
- package/registry/blocks/careers-open-vacancies-table/index.ts +6 -0
- package/registry/blocks/careers-perks-benefits/CareersPerksBenefits.tsx +181 -0
- package/registry/blocks/careers-perks-benefits/index.ts +8 -0
- package/registry/blocks/careers-role-cards-grid/CareersRoleCardsGrid.tsx +405 -0
- package/registry/blocks/careers-role-cards-grid/index.ts +6 -0
- package/registry/blocks/careers-role-detail-page/CareersRoleDetailPage.tsx +541 -0
- package/registry/blocks/careers-role-detail-page/index.ts +10 -0
- package/registry/blocks/careers-role-detail-panel/CareersRoleDetailPanel.tsx +255 -0
- package/registry/blocks/careers-role-detail-panel/index.ts +6 -0
- package/registry/blocks/careers-roles-by-department/CareersRolesByDepartment.tsx +242 -0
- package/registry/blocks/careers-roles-by-department/index.ts +7 -0
- package/registry/blocks/careers-roles-list-accordion-expanded/CareersRolesListAccordionExpanded.tsx +558 -0
- package/registry/blocks/careers-roles-list-accordion-expanded/index.ts +9 -0
- package/registry/blocks/contact-us/contact-us.test.tsx +239 -0
- package/registry/blocks/contact-us/contact-us.tsx +989 -0
- package/registry/blocks/contact-us/index.ts +34 -0
- package/registry/blocks/contact-us-bento-grid/ContactUsBentoGrid.tsx +304 -0
- package/registry/blocks/contact-us-bento-grid/index.ts +5 -0
- package/registry/blocks/contact-us-bento-grid.test.tsx +102 -0
- package/registry/blocks/contact-us-book-a-call/ContactUsBookACall.tsx +403 -0
- package/registry/blocks/contact-us-book-a-call/index.ts +7 -0
- package/registry/blocks/contact-us-book-a-call.test.tsx +134 -0
- package/registry/blocks/contact-us-classic-centered/ContactUsClassicCentered.tsx +199 -0
- package/registry/blocks/contact-us-classic-centered/index.ts +6 -0
- package/registry/blocks/contact-us-dark-statement/ContactUsDarkStatement.tsx +218 -0
- package/registry/blocks/contact-us-dark-statement/index.ts +6 -0
- package/registry/blocks/contact-us-editorial-and-address-card/ContactUsEditorialAndAddressCard.tsx +212 -0
- package/registry/blocks/contact-us-editorial-and-address-card/index.ts +6 -0
- package/registry/blocks/contact-us-editorial-statement/ContactUsEditorialStatement.tsx +205 -0
- package/registry/blocks/contact-us-editorial-statement/index.ts +6 -0
- package/registry/blocks/contact-us-form-contact-methods/ContactUsFormContactMethods.tsx +272 -0
- package/registry/blocks/contact-us-form-contact-methods/index.ts +6 -0
- package/registry/blocks/contact-us-form-with-faq/ContactUsFormWithFaq.tsx +383 -0
- package/registry/blocks/contact-us-form-with-faq/index.ts +7 -0
- package/registry/blocks/contact-us-form-with-faq.test.tsx +161 -0
- package/registry/blocks/contact-us-forms.test.tsx +333 -0
- package/registry/blocks/contact-us-global-offices-table/ContactUsGlobalOfficesTable.tsx +301 -0
- package/registry/blocks/contact-us-global-offices-table/index.ts +5 -0
- package/registry/blocks/contact-us-global-offices-table.test.tsx +100 -0
- package/registry/blocks/contact-us-grand-headline-form/ContactUsGrandHeadlineForm.tsx +180 -0
- package/registry/blocks/contact-us-grand-headline-form/index.ts +6 -0
- package/registry/blocks/contact-us-hours-and-availability/ContactUsHoursAndAvailability.tsx +412 -0
- package/registry/blocks/contact-us-hours-and-availability/index.ts +5 -0
- package/registry/blocks/contact-us-hours-and-availability.test.tsx +123 -0
- package/registry/blocks/contact-us-hq-feature/ContactUsHqFeature.tsx +281 -0
- package/registry/blocks/contact-us-hq-feature/index.ts +5 -0
- package/registry/blocks/contact-us-hq-feature.test.tsx +102 -0
- package/registry/blocks/contact-us-map-split/ContactUsMapSplit.tsx +211 -0
- package/registry/blocks/contact-us-map-split/index.ts +5 -0
- package/registry/blocks/contact-us-map-split.test.tsx +70 -0
- package/registry/blocks/contact-us-named-owners/ContactUsNamedOwners.tsx +324 -0
- package/registry/blocks/contact-us-named-owners/index.ts +6 -0
- package/registry/blocks/contact-us-named-owners.test.tsx +116 -0
- package/registry/blocks/contact-us-newsletter-combo/ContactUsNewsletterCombo.tsx +363 -0
- package/registry/blocks/contact-us-newsletter-combo/index.ts +6 -0
- package/registry/blocks/contact-us-newsletter-combo.test.tsx +165 -0
- package/registry/blocks/contact-us-office-cards/ContactUsOfficeCards.tsx +235 -0
- package/registry/blocks/contact-us-office-cards/index.ts +5 -0
- package/registry/blocks/contact-us-office-cards.test.tsx +71 -0
- package/registry/blocks/contact-us-oversized-wordmark/ContactUsOversizedWordmark.tsx +222 -0
- package/registry/blocks/contact-us-oversized-wordmark/index.ts +6 -0
- package/registry/blocks/contact-us-photo-and-dark-panel/ContactUsPhotoAndDarkPanel.tsx +185 -0
- package/registry/blocks/contact-us-photo-and-dark-panel/index.ts +6 -0
- package/registry/blocks/contact-us-photo-forms.test.tsx +311 -0
- package/registry/blocks/contact-us-pitch-and-inquiry/ContactUsPitchAndInquiry.tsx +202 -0
- package/registry/blocks/contact-us-pitch-and-inquiry/index.ts +6 -0
- package/registry/blocks/contact-us-rtl.test.tsx +105 -0
- package/registry/blocks/contact-us-ruled-split-form/ContactUsRuledSplitForm.tsx +214 -0
- package/registry/blocks/contact-us-ruled-split-form/index.ts +6 -0
- package/registry/blocks/contact-us-social-rail/ContactUsSocialRail.tsx +270 -0
- package/registry/blocks/contact-us-social-rail/index.ts +7 -0
- package/registry/blocks/contact-us-social-rail.test.tsx +121 -0
- package/registry/blocks/contact-us-split-photo-dark/ContactUsSplitPhotoDark.tsx +185 -0
- package/registry/blocks/contact-us-split-photo-dark/index.ts +6 -0
- package/registry/blocks/contact-us-support-channels/ContactUsSupportChannels.tsx +267 -0
- package/registry/blocks/contact-us-support-channels/index.ts +5 -0
- package/registry/blocks/contact-us-support-channels.test.tsx +81 -0
- package/registry/blocks/data-table/DataTable.test.tsx +1 -34
- package/registry/blocks/data-table/DataTable.tsx +0 -139
- package/registry/blocks/data-table/index.ts +1 -8
- package/registry/blocks/error-state-access-denied-403/ErrorStateAccessDenied403.tsx +324 -0
- package/registry/blocks/error-state-access-denied-403/index.ts +10 -0
- package/registry/blocks/error-state-broken-trail-breadcrumb/ErrorStateBrokenTrailBreadcrumb.tsx +179 -0
- package/registry/blocks/error-state-broken-trail-breadcrumb/index.ts +8 -0
- package/registry/blocks/error-state-centered-minimal/ErrorStateCenteredMinimal.tsx +119 -0
- package/registry/blocks/error-state-centered-minimal/index.ts +7 -0
- package/registry/blocks/error-state-colour-field-scatter/ErrorStateColourFieldScatter.tsx +144 -0
- package/registry/blocks/error-state-colour-field-scatter/index.ts +7 -0
- package/registry/blocks/error-state-countdown-redirect/ErrorStateCountdownRedirect.tsx +272 -0
- package/registry/blocks/error-state-countdown-redirect/index.ts +7 -0
- package/registry/blocks/error-state-dark-spotlight/ErrorStateDarkSpotlight.tsx +156 -0
- package/registry/blocks/error-state-dark-spotlight/index.ts +7 -0
- package/registry/blocks/error-state-display-numeral-split/ErrorStateDisplayNumeralSplit.tsx +156 -0
- package/registry/blocks/error-state-display-numeral-split/index.ts +8 -0
- package/registry/blocks/error-state-editorial-photo-split/ErrorStateEditorialPhotoSplit.tsx +156 -0
- package/registry/blocks/error-state-editorial-photo-split/index.ts +8 -0
- package/registry/blocks/error-state-empty-search-results/ErrorStateEmptySearchResults.tsx +243 -0
- package/registry/blocks/error-state-empty-search-results/index.ts +6 -0
- package/registry/blocks/error-state-error-card-panel/ErrorStateErrorCardPanel.tsx +213 -0
- package/registry/blocks/error-state-error-card-panel/index.ts +7 -0
- package/registry/blocks/error-state-full-bleed-photo/ErrorStateFullBleedPhoto.tsx +130 -0
- package/registry/blocks/error-state-full-bleed-photo/index.ts +8 -0
- package/registry/blocks/error-state-ghost-watermark/ErrorStateGhostWatermark.tsx +115 -0
- package/registry/blocks/error-state-ghost-watermark/index.ts +7 -0
- package/registry/blocks/error-state-helpful-links-list/ErrorStateHelpfulLinksList.tsx +185 -0
- package/registry/blocks/error-state-helpful-links-list/index.ts +8 -0
- package/registry/blocks/error-state-illustrated-empty-state/ErrorStateIllustratedEmptyState.tsx +201 -0
- package/registry/blocks/error-state-illustrated-empty-state/index.ts +7 -0
- package/registry/blocks/error-state-layered-badge-centered/ErrorStateLayeredBadgeCentered.tsx +138 -0
- package/registry/blocks/error-state-layered-badge-centered/index.ts +7 -0
- package/registry/blocks/error-state-light-editorial/ErrorStateLightEditorial.tsx +126 -0
- package/registry/blocks/error-state-light-editorial/index.ts +7 -0
- package/registry/blocks/error-state-maintenance-mode/ErrorStateMaintenanceMode.tsx +255 -0
- package/registry/blocks/error-state-maintenance-mode/index.ts +6 -0
- package/registry/blocks/error-state-marquee-404-band/ErrorStateMarquee404Band.tsx +316 -0
- package/registry/blocks/error-state-marquee-404-band/index.ts +7 -0
- package/registry/blocks/error-state-offline-state/ErrorStateOfflineState.tsx +188 -0
- package/registry/blocks/error-state-offline-state/index.ts +7 -0
- package/registry/blocks/error-state-photo-collage-scatter/ErrorStatePhotoCollageScatter.tsx +224 -0
- package/registry/blocks/error-state-photo-collage-scatter/index.ts +8 -0
- package/registry/blocks/error-state-popular-pages-grid/ErrorStatePopularPagesGrid.tsx +195 -0
- package/registry/blocks/error-state-popular-pages-grid/index.ts +9 -0
- package/registry/blocks/error-state-recovery-bento/ErrorStateRecoveryBento.tsx +274 -0
- package/registry/blocks/error-state-recovery-bento/index.ts +7 -0
- package/registry/blocks/error-state-search-recovery/ErrorStateSearchRecovery.tsx +173 -0
- package/registry/blocks/error-state-search-recovery/index.ts +7 -0
- package/registry/blocks/error-state-server-error-500/ErrorStateServerError500.tsx +277 -0
- package/registry/blocks/error-state-server-error-500/index.ts +9 -0
- package/registry/blocks/error-state-sitemap-columns/ErrorStateSitemapColumns.tsx +192 -0
- package/registry/blocks/error-state-sitemap-columns/index.ts +9 -0
- package/registry/blocks/error-state-split-colour-panel/ErrorStateSplitColourPanel.tsx +156 -0
- package/registry/blocks/error-state-split-colour-panel/index.ts +7 -0
- package/registry/blocks/error-state-support-escalation-band/ErrorStateSupportEscalationBand.tsx +186 -0
- package/registry/blocks/error-state-support-escalation-band/index.ts +8 -0
- package/registry/blocks/error-state-terminal-console/ErrorStateTerminalConsole.tsx +208 -0
- package/registry/blocks/error-state-terminal-console/index.ts +8 -0
- package/registry/blocks/faq-accent-active-card/FaqAccentActiveCard.tsx +186 -0
- package/registry/blocks/faq-accent-active-card/index.ts +1 -0
- package/registry/blocks/faq-category-chip-grid/FaqCategoryChipGrid.tsx +425 -0
- package/registry/blocks/faq-category-chip-grid/index.ts +8 -0
- package/registry/blocks/faq-category-columns/FaqCategoryColumns.tsx +248 -0
- package/registry/blocks/faq-category-columns/index.ts +8 -0
- package/registry/blocks/faq-chat-thread/FaqChatThread.tsx +273 -0
- package/registry/blocks/faq-chat-thread/index.ts +7 -0
- package/registry/blocks/faq-classic-centered/FaqClassicCentered.tsx +190 -0
- package/registry/blocks/faq-classic-centered/index.ts +7 -0
- package/registry/blocks/faq-contact-cta-card/FaqContactCtaCard.tsx +229 -0
- package/registry/blocks/faq-contact-cta-card/index.ts +9 -0
- package/registry/blocks/faq-dark-panel/FaqDarkPanel.tsx +186 -0
- package/registry/blocks/faq-dark-panel/index.ts +1 -0
- package/registry/blocks/faq-featured-question/FaqFeaturedQuestion.tsx +221 -0
- package/registry/blocks/faq-featured-question/index.ts +1 -0
- package/registry/blocks/faq-grouped-sections/FaqGroupedSections.tsx +266 -0
- package/registry/blocks/faq-grouped-sections/index.ts +8 -0
- package/registry/blocks/faq-help-hero-popular/FaqHelpHeroPopular.tsx +212 -0
- package/registry/blocks/faq-help-hero-popular/index.ts +7 -0
- package/registry/blocks/faq-masonry-cards/FaqMasonryCards.tsx +268 -0
- package/registry/blocks/faq-masonry-cards/index.ts +7 -0
- package/registry/blocks/faq-media-split/FaqMediaSplit.tsx +197 -0
- package/registry/blocks/faq-media-split/index.ts +8 -0
- package/registry/blocks/faq-mono-index/FaqMonoIndex.tsx +247 -0
- package/registry/blocks/faq-mono-index/index.ts +1 -0
- package/registry/blocks/faq-newsletter-close/FaqNewsletterClose.tsx +314 -0
- package/registry/blocks/faq-newsletter-close/index.ts +8 -0
- package/registry/blocks/faq-numbered-editorial/FaqNumberedEditorial.tsx +190 -0
- package/registry/blocks/faq-numbered-editorial/index.ts +1 -0
- package/registry/blocks/faq-search-categories/FaqSearchCategories.tsx +312 -0
- package/registry/blocks/faq-search-categories/index.ts +8 -0
- package/registry/blocks/faq-sidebar-nav/FaqSidebarNav.tsx +390 -0
- package/registry/blocks/faq-sidebar-nav/index.ts +8 -0
- package/registry/blocks/faq-soft-filled-rows/FaqSoftFilledRows.tsx +209 -0
- package/registry/blocks/faq-soft-filled-rows/index.ts +1 -0
- package/registry/blocks/faq-split-sticky/FaqSplitSticky.tsx +205 -0
- package/registry/blocks/faq-split-sticky/index.ts +7 -0
- package/registry/blocks/faq-support-channels/FaqSupportChannels.tsx +266 -0
- package/registry/blocks/faq-support-channels/index.ts +8 -0
- package/registry/blocks/faq-support-stats/FaqSupportStats.tsx +242 -0
- package/registry/blocks/faq-support-stats/index.ts +8 -0
- package/registry/blocks/faq-table-compact/FaqTableCompact.tsx +220 -0
- package/registry/blocks/faq-table-compact/index.ts +1 -0
- package/registry/blocks/faq-tabs-by-topic/FaqTabsByTopic.tsx +347 -0
- package/registry/blocks/faq-tabs-by-topic/index.ts +8 -0
- package/registry/blocks/faq-topic-tiles/FaqTopicTiles.tsx +254 -0
- package/registry/blocks/faq-topic-tiles/index.ts +7 -0
- package/registry/blocks/faq-two-column-grid/FaqTwoColumnGrid.tsx +256 -0
- package/registry/blocks/faq-two-column-grid/index.ts +7 -0
- package/registry/blocks/faq-uppercase-dense/FaqUppercaseDense.tsx +213 -0
- package/registry/blocks/faq-uppercase-dense/index.ts +1 -0
- package/registry/blocks/features/features.tsx +164 -0
- package/registry/blocks/features/index.ts +12 -0
- package/registry/blocks/features-accordion-photo/FeaturesAccordionPhoto.tsx +149 -0
- package/registry/blocks/features-accordion-photo/index.ts +7 -0
- package/registry/blocks/features-colour-block-cards/FeaturesColourBlockCards.tsx +118 -0
- package/registry/blocks/features-colour-block-cards/index.ts +8 -0
- package/registry/blocks/features-compact-icon-index/FeaturesCompactIconIndex.tsx +136 -0
- package/registry/blocks/features-compact-icon-index/index.ts +7 -0
- package/registry/blocks/features-compare-panels-chat-answer/FeaturesComparePanelsChatAnswer.tsx +346 -0
- package/registry/blocks/features-compare-panels-chat-answer/index.ts +8 -0
- package/registry/blocks/features-editorial-photo-split/FeaturesEditorialPhotoSplit.tsx +118 -0
- package/registry/blocks/features-editorial-photo-split/index.ts +7 -0
- package/registry/blocks/features-expanding-step-cards/FeaturesExpandingStepCards.tsx +300 -0
- package/registry/blocks/features-expanding-step-cards/index.ts +7 -0
- package/registry/blocks/features-feature-checklist-columns/FeaturesFeatureChecklistColumns.tsx +158 -0
- package/registry/blocks/features-feature-checklist-columns/index.ts +7 -0
- package/registry/blocks/features-feature-list-thumbnails/FeaturesFeatureListThumbnails.tsx +137 -0
- package/registry/blocks/features-feature-list-thumbnails/index.ts +7 -0
- package/registry/blocks/features-full-bleed-photo-banner/FeaturesFullBleedPhotoBanner.tsx +116 -0
- package/registry/blocks/features-full-bleed-photo-banner/index.ts +7 -0
- package/registry/blocks/features-icon-card-grid/FeaturesIconCardGrid.tsx +120 -0
- package/registry/blocks/features-icon-card-grid/index.ts +7 -0
- package/registry/blocks/features-icon-titled-preview-rail/FeaturesIconTitledPreviewRail.tsx +321 -0
- package/registry/blocks/features-icon-titled-preview-rail/index.ts +7 -0
- package/registry/blocks/features-icons-numbers.test.tsx +107 -0
- package/registry/blocks/features-interactive.test.tsx +175 -0
- package/registry/blocks/features-media-rail/FeaturesMediaRail.tsx +119 -0
- package/registry/blocks/features-media-rail/index.ts +7 -0
- package/registry/blocks/features-notched-photo-columns/FeaturesNotchedPhotoColumns.tsx +209 -0
- package/registry/blocks/features-notched-photo-columns/index.ts +7 -0
- package/registry/blocks/features-numbered-feature-rows/FeaturesNumberedFeatureRows.tsx +107 -0
- package/registry/blocks/features-numbered-feature-rows/index.ts +7 -0
- package/registry/blocks/features-numbered-steps-floating-cards/FeaturesNumberedStepsFloatingCards.tsx +324 -0
- package/registry/blocks/features-numbered-steps-floating-cards/index.ts +8 -0
- package/registry/blocks/features-perforated-photo-strip/FeaturesPerforatedPhotoStrip.tsx +218 -0
- package/registry/blocks/features-perforated-photo-strip/index.ts +7 -0
- package/registry/blocks/features-photo-bento/FeaturesPhotoBento.tsx +160 -0
- package/registry/blocks/features-photo-bento/index.ts +8 -0
- package/registry/blocks/features-photo-carousel/FeaturesPhotoCarousel.tsx +249 -0
- package/registry/blocks/features-photo-carousel/index.ts +7 -0
- package/registry/blocks/features-photo-collage/FeaturesPhotoCollage.tsx +143 -0
- package/registry/blocks/features-photo-collage/index.ts +7 -0
- package/registry/blocks/features-photo-feature-chips/FeaturesPhotoFeatureChips.tsx +125 -0
- package/registry/blocks/features-photo-feature-chips/index.ts +7 -0
- package/registry/blocks/features-photo-led.test.tsx +177 -0
- package/registry/blocks/features-photo-tabs-panel/FeaturesPhotoTabsPanel.tsx +197 -0
- package/registry/blocks/features-photo-tabs-panel/index.ts +7 -0
- package/registry/blocks/features-portrait-photo-cards-link-row/FeaturesPortraitPhotoCardsLinkRow.tsx +202 -0
- package/registry/blocks/features-portrait-photo-cards-link-row/index.ts +7 -0
- package/registry/blocks/features-product-in-use.test.tsx +188 -0
- package/registry/blocks/features-showcase-card-pair/FeaturesShowcaseCardPair.tsx +161 -0
- package/registry/blocks/features-showcase-card-pair/index.ts +7 -0
- package/registry/blocks/features-solid-colour-cards/FeaturesSolidColourCards.tsx +264 -0
- package/registry/blocks/features-solid-colour-cards/index.ts +7 -0
- package/registry/blocks/features-split-photo-icon-list/FeaturesSplitPhotoIconList.tsx +117 -0
- package/registry/blocks/features-split-photo-icon-list/index.ts +7 -0
- package/registry/blocks/features-stat-feature-band/FeaturesStatFeatureBand.tsx +114 -0
- package/registry/blocks/features-stat-feature-band/index.ts +7 -0
- package/registry/blocks/features-tinted-product-bento/FeaturesTintedProductBento.tsx +252 -0
- package/registry/blocks/features-tinted-product-bento/index.ts +7 -0
- package/registry/blocks/footer/footer.test.tsx +253 -0
- package/registry/blocks/footer/footer.tsx +554 -0
- package/registry/blocks/footer/index.ts +31 -0
- package/registry/blocks/footer-accordion-sitemap/FooterAccordionSitemap.tsx +260 -0
- package/registry/blocks/footer-accordion-sitemap/index.ts +7 -0
- package/registry/blocks/footer-bars.test.tsx +121 -0
- package/registry/blocks/footer-bento-tile/FooterBentoTile.tsx +331 -0
- package/registry/blocks/footer-bento-tile/index.ts +6 -0
- package/registry/blocks/footer-big-question-cta/FooterBigQuestionCta.tsx +250 -0
- package/registry/blocks/footer-big-question-cta/index.ts +6 -0
- package/registry/blocks/footer-big-type-link-stack/FooterBigTypeLinkStack.tsx +275 -0
- package/registry/blocks/footer-big-type-link-stack/index.ts +6 -0
- package/registry/blocks/footer-brand-panel-split/FooterBrandPanelSplit.tsx +163 -0
- package/registry/blocks/footer-brand-panel-split/index.ts +6 -0
- package/registry/blocks/footer-brand.test.tsx +608 -0
- package/registry/blocks/footer-careers-culture/FooterCareersCulture.tsx +297 -0
- package/registry/blocks/footer-careers-culture/index.ts +7 -0
- package/registry/blocks/footer-centered-brand-minimal/FooterCenteredBrandMinimal.tsx +121 -0
- package/registry/blocks/footer-centered-brand-minimal/index.ts +6 -0
- package/registry/blocks/footer-commerce.test.tsx +208 -0
- package/registry/blocks/footer-community-events/FooterCommunityEvents.tsx +263 -0
- package/registry/blocks/footer-community-events/index.ts +8 -0
- package/registry/blocks/footer-community.test.tsx +309 -0
- package/registry/blocks/footer-contact-first/FooterContactFirst.tsx +242 -0
- package/registry/blocks/footer-contact-first/index.ts +7 -0
- package/registry/blocks/footer-contact.test.tsx +285 -0
- package/registry/blocks/footer-controls.test.tsx +78 -0
- package/registry/blocks/footer-cta-band-columns/FooterCtaBandColumns.tsx +225 -0
- package/registry/blocks/footer-cta-band-columns/index.ts +6 -0
- package/registry/blocks/footer-cta.test.tsx +445 -0
- package/registry/blocks/footer-dashboard-slim-bar/FooterDashboardSlimBar.tsx +148 -0
- package/registry/blocks/footer-dashboard-slim-bar/index.ts +6 -0
- package/registry/blocks/footer-docs-page/FooterDocsPage.tsx +261 -0
- package/registry/blocks/footer-docs-page/index.ts +9 -0
- package/registry/blocks/footer-ecommerce-mega/FooterEcommerceMega.tsx +289 -0
- package/registry/blocks/footer-ecommerce-mega/index.ts +6 -0
- package/registry/blocks/footer-floating-demo-card/FooterFloatingDemoCard.tsx +261 -0
- package/registry/blocks/footer-floating-demo-card/index.ts +6 -0
- package/registry/blocks/footer-four-column-directory/FooterFourColumnDirectory.tsx +104 -0
- package/registry/blocks/footer-four-column-directory/index.ts +6 -0
- package/registry/blocks/footer-giant-wordmark/FooterGiantWordmark.tsx +252 -0
- package/registry/blocks/footer-giant-wordmark/index.ts +6 -0
- package/registry/blocks/footer-image-backed-brand/FooterImageBackedBrand.tsx +251 -0
- package/registry/blocks/footer-image-backed-brand/index.ts +6 -0
- package/registry/blocks/footer-index-numbered-columns/FooterIndexNumberedColumns.tsx +236 -0
- package/registry/blocks/footer-index-numbered-columns/index.ts +7 -0
- package/registry/blocks/footer-inline-preferences/FooterInlinePreferences.tsx +164 -0
- package/registry/blocks/footer-inline-preferences/index.ts +7 -0
- package/registry/blocks/footer-legal-first-slim/FooterLegalFirstSlim.tsx +174 -0
- package/registry/blocks/footer-legal-first-slim/index.ts +6 -0
- package/registry/blocks/footer-legal.test.tsx +180 -0
- package/registry/blocks/footer-local-business/FooterLocalBusiness.tsx +258 -0
- package/registry/blocks/footer-local-business/index.ts +7 -0
- package/registry/blocks/footer-marquee-strip/FooterMarqueeStrip.tsx +244 -0
- package/registry/blocks/footer-marquee-strip/index.ts +6 -0
- package/registry/blocks/footer-multi-region/FooterMultiRegion.tsx +310 -0
- package/registry/blocks/footer-multi-region/index.ts +7 -0
- package/registry/blocks/footer-newsletter-split/FooterNewsletterSplit.tsx +255 -0
- package/registry/blocks/footer-newsletter-split/index.ts +6 -0
- package/registry/blocks/footer-product-family-switcher/FooterProductFamilySwitcher.tsx +241 -0
- package/registry/blocks/footer-product-family-switcher/index.ts +7 -0
- package/registry/blocks/footer-service-promise-band/FooterServicePromiseBand.tsx +237 -0
- package/registry/blocks/footer-service-promise-band/index.ts +7 -0
- package/registry/blocks/footer-single-line-bar/FooterSingleLineBar.tsx +107 -0
- package/registry/blocks/footer-single-line-bar/index.ts +6 -0
- package/registry/blocks/footer-sitemap.test.tsx +390 -0
- package/registry/blocks/footer-split-hairline-micro/FooterSplitHairlineMicro.tsx +100 -0
- package/registry/blocks/footer-split-hairline-micro/index.ts +6 -0
- package/registry/blocks/footer-support-contact/FooterSupportContact.tsx +204 -0
- package/registry/blocks/footer-support-contact/index.ts +7 -0
- package/registry/blocks/footer-trust-compliance/FooterTrustCompliance.tsx +234 -0
- package/registry/blocks/footer-trust-compliance/index.ts +7 -0
- package/registry/blocks/footer-two-row-compact/FooterTwoRowCompact.tsx +124 -0
- package/registry/blocks/footer-two-row-compact/index.ts +6 -0
- package/registry/blocks/footer-two-tier-doormat/FooterTwoTierDoormat.tsx +232 -0
- package/registry/blocks/footer-two-tier-doormat/index.ts +8 -0
- package/registry/blocks/footer-utility.test.tsx +406 -0
- package/registry/blocks/footer-wide-sitemap-mega/FooterWideSitemapMega.tsx +227 -0
- package/registry/blocks/footer-wide-sitemap-mega/index.ts +6 -0
- package/registry/blocks/gallery-album-cards/GalleryAlbumCards.tsx +243 -0
- package/registry/blocks/gallery-album-cards/index.ts +8 -0
- package/registry/blocks/gallery-before-after-compare/GalleryBeforeAfterCompare.tsx +269 -0
- package/registry/blocks/gallery-before-after-compare/index.ts +7 -0
- package/registry/blocks/gallery-contact-sheet-wall/GalleryContactSheetWall.tsx +299 -0
- package/registry/blocks/gallery-contact-sheet-wall/index.ts +9 -0
- package/registry/blocks/gallery-culture-photo-grid/GalleryCulturePhotoGrid.tsx +203 -0
- package/registry/blocks/gallery-culture-photo-grid/index.ts +8 -0
- package/registry/blocks/gallery-dark-cinema-wall/GalleryDarkCinemaWall.tsx +180 -0
- package/registry/blocks/gallery-dark-cinema-wall/index.ts +7 -0
- package/registry/blocks/gallery-editorial-split/GalleryEditorialSplit.tsx +188 -0
- package/registry/blocks/gallery-editorial-split/index.ts +8 -0
- package/registry/blocks/gallery-featured-thumb-rail/GalleryFeaturedThumbRail.tsx +397 -0
- package/registry/blocks/gallery-featured-thumb-rail/index.ts +8 -0
- package/registry/blocks/gallery-filmstrip-carousel/GalleryFilmstripCarousel.tsx +384 -0
- package/registry/blocks/gallery-filmstrip-carousel/index.ts +8 -0
- package/registry/blocks/gallery-filter-tabs-grid/GalleryFilterTabsGrid.tsx +403 -0
- package/registry/blocks/gallery-filter-tabs-grid/index.ts +9 -0
- package/registry/blocks/gallery-full-bleed-slider/GalleryFullBleedSlider.tsx +309 -0
- package/registry/blocks/gallery-full-bleed-slider/index.ts +8 -0
- package/registry/blocks/gallery-horizontal-scroll-rail/GalleryHorizontalScrollRail.tsx +300 -0
- package/registry/blocks/gallery-horizontal-scroll-rail/index.ts +8 -0
- package/registry/blocks/gallery-hover-caption-cards/GalleryHoverCaptionCards.tsx +244 -0
- package/registry/blocks/gallery-hover-caption-cards/index.ts +8 -0
- package/registry/blocks/gallery-hover-index-list/GalleryHoverIndexList.tsx +253 -0
- package/registry/blocks/gallery-hover-index-list/index.ts +9 -0
- package/registry/blocks/gallery-lightbox-viewer/GalleryLightboxViewer.tsx +329 -0
- package/registry/blocks/gallery-lightbox-viewer/index.ts +7 -0
- package/registry/blocks/gallery-masonry-gallery/GalleryMasonryGallery.tsx +251 -0
- package/registry/blocks/gallery-masonry-gallery/index.ts +7 -0
- package/registry/blocks/gallery-mosaic-statement-tile/GalleryMosaicStatementTile.tsx +159 -0
- package/registry/blocks/gallery-mosaic-statement-tile/index.ts +8 -0
- package/registry/blocks/gallery-photo-bento/GalleryPhotoBento.tsx +166 -0
- package/registry/blocks/gallery-photo-bento/index.ts +8 -0
- package/registry/blocks/gallery-photo-spotlight/GalleryPhotoSpotlight.tsx +305 -0
- package/registry/blocks/gallery-photo-spotlight/index.ts +9 -0
- package/registry/blocks/gallery-scattered-collage/GalleryScatteredCollage.tsx +286 -0
- package/registry/blocks/gallery-scattered-collage/index.ts +9 -0
- package/registry/blocks/gallery-social-feed-strip/GallerySocialFeedStrip.tsx +288 -0
- package/registry/blocks/gallery-social-feed-strip/index.ts +8 -0
- package/registry/blocks/gallery-timeline-gallery/GalleryTimelineGallery.tsx +243 -0
- package/registry/blocks/gallery-timeline-gallery/index.ts +8 -0
- package/registry/blocks/gallery-video-gallery/GalleryVideoGallery.tsx +362 -0
- package/registry/blocks/gallery-video-gallery/index.ts +8 -0
- package/registry/blocks/hero-annotated-object/HeroAnnotatedObject.tsx +310 -0
- package/registry/blocks/hero-annotated-object/index.ts +10 -0
- package/registry/blocks/hero-arc-gallery/HeroArcGallery.tsx +244 -0
- package/registry/blocks/hero-arc-gallery/index.ts +9 -0
- package/registry/blocks/hero-bento-split/HeroBentoSplit.tsx +266 -0
- package/registry/blocks/hero-bento-split/index.ts +9 -0
- package/registry/blocks/hero-brand-color-block/HeroBrandColorBlock.tsx +259 -0
- package/registry/blocks/hero-brand-color-block/index.ts +8 -0
- package/registry/blocks/hero-colour-stage/HeroColourStage.tsx +292 -0
- package/registry/blocks/hero-colour-stage/index.ts +8 -0
- package/registry/blocks/hero-component-pattern/HeroComponentPattern.tsx +248 -0
- package/registry/blocks/hero-component-pattern/index.ts +9 -0
- package/registry/blocks/hero-curved-media-rail/HeroCurvedMediaRail.tsx +272 -0
- package/registry/blocks/hero-curved-media-rail/index.ts +8 -0
- package/registry/blocks/hero-duo-card/HeroDuoCard.tsx +210 -0
- package/registry/blocks/hero-duo-card/index.ts +8 -0
- package/registry/blocks/hero-editorial-arch/HeroEditorialArch.tsx +226 -0
- package/registry/blocks/hero-editorial-arch/index.ts +10 -0
- package/registry/blocks/hero-editorial-triptych/HeroEditorialTriptych.tsx +252 -0
- package/registry/blocks/hero-editorial-triptych/index.ts +9 -0
- package/registry/blocks/hero-floating-integrations/HeroFloatingIntegrations.tsx +454 -0
- package/registry/blocks/hero-floating-integrations/index.ts +11 -0
- package/registry/blocks/hero-framed-full-bleed/HeroFramedFullBleed.tsx +226 -0
- package/registry/blocks/hero-framed-full-bleed/index.ts +9 -0
- package/registry/blocks/hero-framed-studio-card/HeroFramedStudioCard.tsx +264 -0
- package/registry/blocks/hero-framed-studio-card/index.ts +8 -0
- package/registry/blocks/hero-illustration-split/HeroIllustrationSplit.tsx +200 -0
- package/registry/blocks/hero-illustration-split/index.ts +8 -0
- package/registry/blocks/hero-inline-image-headline/HeroInlineImageHeadline.tsx +305 -0
- package/registry/blocks/hero-inline-image-headline/index.ts +8 -0
- package/registry/blocks/hero-masked-type-reveal/HeroMaskedTypeReveal.tsx +323 -0
- package/registry/blocks/hero-masked-type-reveal/index.ts +9 -0
- package/registry/blocks/hero-motion.test.tsx +185 -0
- package/registry/blocks/hero-orbit-track/HeroOrbitTrack.tsx +238 -0
- package/registry/blocks/hero-orbit-track/index.ts +8 -0
- package/registry/blocks/hero-photo-constellation/HeroPhotoConstellation.tsx +228 -0
- package/registry/blocks/hero-photo-constellation/index.ts +8 -0
- package/registry/blocks/hero-scramble-decode/HeroScrambleDecode.tsx +381 -0
- package/registry/blocks/hero-scramble-decode/index.ts +7 -0
- package/registry/blocks/hero-shape-grid/HeroShapeGrid.tsx +279 -0
- package/registry/blocks/hero-shape-grid/index.ts +8 -0
- package/registry/blocks/hero-split-band-headline/HeroSplitBandHeadline.tsx +242 -0
- package/registry/blocks/hero-split-band-headline/index.ts +8 -0
- package/registry/blocks/hero-split-flap-counters/HeroSplitFlapCounters.tsx +323 -0
- package/registry/blocks/hero-split-flap-counters/index.ts +8 -0
- package/registry/blocks/hero-studio-mosaic/HeroStudioMosaic.tsx +332 -0
- package/registry/blocks/hero-studio-mosaic/index.ts +9 -0
- package/registry/blocks/hero-textured-dark/HeroTexturedDark.tsx +378 -0
- package/registry/blocks/hero-textured-dark/index.ts +10 -0
- package/registry/blocks/hero-twin-panels/HeroTwinPanels.tsx +231 -0
- package/registry/blocks/hero-twin-panels/index.ts +9 -0
- package/registry/blocks/hero-velocity-marquee/HeroVelocityMarquee.tsx +392 -0
- package/registry/blocks/hero-velocity-marquee/index.ts +8 -0
- package/registry/blocks/hero-video-in-type/HeroVideoInType.tsx +374 -0
- package/registry/blocks/hero-video-in-type/index.ts +9 -0
- package/registry/blocks/hero-video-spotlight/HeroVideoSpotlight.tsx +292 -0
- package/registry/blocks/hero-video-spotlight/index.ts +9 -0
- package/registry/blocks/hero-wave-band/HeroWaveBand.tsx +309 -0
- package/registry/blocks/hero-wave-band/index.ts +8 -0
- package/registry/blocks/how-it-works/how-it-works.tsx +330 -0
- package/registry/blocks/how-it-works/index.ts +28 -0
- package/registry/blocks/how-it-works-accordion-steps/HowItWorksAccordionSteps.tsx +213 -0
- package/registry/blocks/how-it-works-accordion-steps/index.ts +7 -0
- package/registry/blocks/how-it-works-center-spine-timeline/HowItWorksCenterSpineTimeline.tsx +200 -0
- package/registry/blocks/how-it-works-center-spine-timeline/index.ts +7 -0
- package/registry/blocks/how-it-works-column-panels/HowItWorksColumnPanels.tsx +299 -0
- package/registry/blocks/how-it-works-column-panels/index.ts +6 -0
- package/registry/blocks/how-it-works-contained-timeline/HowItWorksContainedTimeline.tsx +223 -0
- package/registry/blocks/how-it-works-contained-timeline/index.ts +8 -0
- package/registry/blocks/how-it-works-diagonal-photo-collage/HowItWorksDiagonalPhotoCollage.tsx +170 -0
- package/registry/blocks/how-it-works-diagonal-photo-collage/index.ts +7 -0
- package/registry/blocks/how-it-works-fanned-dissolve-cards/HowItWorksFannedDissolveCards.tsx +258 -0
- package/registry/blocks/how-it-works-fanned-dissolve-cards/index.ts +8 -0
- package/registry/blocks/how-it-works-full-bleed-step-panel/HowItWorksFullBleedStepPanel.tsx +319 -0
- package/registry/blocks/how-it-works-full-bleed-step-panel/index.ts +7 -0
- package/registry/blocks/how-it-works-grids.test.tsx +292 -0
- package/registry/blocks/how-it-works-interactive.test.tsx +262 -0
- package/registry/blocks/how-it-works-numbered-editorial-rows/HowItWorksNumberedEditorialRows.tsx +177 -0
- package/registry/blocks/how-it-works-numbered-editorial-rows/index.ts +7 -0
- package/registry/blocks/how-it-works-numbered-instruction-panels/HowItWorksNumberedInstructionPanels.tsx +226 -0
- package/registry/blocks/how-it-works-numbered-instruction-panels/index.ts +6 -0
- package/registry/blocks/how-it-works-numbered-photo-steps/HowItWorksNumberedPhotoSteps.tsx +150 -0
- package/registry/blocks/how-it-works-numbered-photo-steps/index.ts +7 -0
- package/registry/blocks/how-it-works-orbital-process/HowItWorksOrbitalProcess.tsx +317 -0
- package/registry/blocks/how-it-works-orbital-process/index.ts +7 -0
- package/registry/blocks/how-it-works-overlay-numeral-cards/HowItWorksOverlayNumeralCards.tsx +145 -0
- package/registry/blocks/how-it-works-overlay-numeral-cards/index.ts +7 -0
- package/registry/blocks/how-it-works-phase-line/HowItWorksPhaseLine.tsx +147 -0
- package/registry/blocks/how-it-works-phase-line/index.ts +8 -0
- package/registry/blocks/how-it-works-photo-bento-steps/HowItWorksPhotoBentoSteps.tsx +178 -0
- package/registry/blocks/how-it-works-photo-bento-steps/index.ts +7 -0
- package/registry/blocks/how-it-works-photo-rail-progress/HowItWorksPhotoRailProgress.tsx +231 -0
- package/registry/blocks/how-it-works-photo-rail-progress/index.ts +7 -0
- package/registry/blocks/how-it-works-pill-timeline/HowItWorksPillTimeline.tsx +181 -0
- package/registry/blocks/how-it-works-pill-timeline/index.ts +8 -0
- package/registry/blocks/how-it-works-rounded-cards-device-crop/HowItWorksRoundedCardsDeviceCrop.tsx +286 -0
- package/registry/blocks/how-it-works-rounded-cards-device-crop/index.ts +6 -0
- package/registry/blocks/how-it-works-six-card-grid/HowItWorksSixCardGrid.tsx +385 -0
- package/registry/blocks/how-it-works-six-card-grid/index.ts +6 -0
- package/registry/blocks/how-it-works-split-feature-band/HowItWorksSplitFeatureBand.tsx +316 -0
- package/registry/blocks/how-it-works-split-feature-band/index.ts +6 -0
- package/registry/blocks/how-it-works-split-photo-step-list/HowItWorksSplitPhotoStepList.tsx +179 -0
- package/registry/blocks/how-it-works-split-photo-step-list/index.ts +7 -0
- package/registry/blocks/how-it-works-stacked-media-text/HowItWorksStackedMediaText.tsx +310 -0
- package/registry/blocks/how-it-works-stacked-media-text/index.ts +8 -0
- package/registry/blocks/how-it-works-step-tabs-photo-panel/HowItWorksStepTabsPhotoPanel.tsx +245 -0
- package/registry/blocks/how-it-works-step-tabs-photo-panel/index.ts +7 -0
- package/registry/blocks/how-it-works-tall-visual-rail/HowItWorksTallVisualRail.tsx +349 -0
- package/registry/blocks/how-it-works-tall-visual-rail/index.ts +7 -0
- package/registry/blocks/how-it-works-timelines.test.tsx +265 -0
- package/registry/blocks/how-it-works-vertical-timeline-card/HowItWorksVerticalTimelineCard.tsx +169 -0
- package/registry/blocks/how-it-works-vertical-timeline-card/index.ts +8 -0
- package/registry/blocks/how-it-works-visual-steps.test.tsx +368 -0
- package/registry/blocks/logo-cloud-bento-logo-wall/LogoCloudBentoLogoWall.tsx +159 -0
- package/registry/blocks/logo-cloud-bento-logo-wall/index.ts +7 -0
- package/registry/blocks/logo-cloud-bordered-cell-grid/LogoCloudBorderedCellGrid.tsx +132 -0
- package/registry/blocks/logo-cloud-bordered-cell-grid/index.ts +7 -0
- package/registry/blocks/logo-cloud-centered-caption-row/LogoCloudCenteredCaptionRow.tsx +141 -0
- package/registry/blocks/logo-cloud-centered-caption-row/index.ts +7 -0
- package/registry/blocks/logo-cloud-contained-card/LogoCloudContainedCard.tsx +106 -0
- package/registry/blocks/logo-cloud-contained-card/index.ts +7 -0
- package/registry/blocks/logo-cloud-dark-logo-wall/LogoCloudDarkLogoWall.tsx +123 -0
- package/registry/blocks/logo-cloud-dark-logo-wall/index.ts +7 -0
- package/registry/blocks/logo-cloud-divider-rule-row/LogoCloudDividerRuleRow.tsx +156 -0
- package/registry/blocks/logo-cloud-divider-rule-row/index.ts +7 -0
- package/registry/blocks/logo-cloud-editorial-eyebrow-split/LogoCloudEditorialEyebrowSplit.tsx +121 -0
- package/registry/blocks/logo-cloud-editorial-eyebrow-split/index.ts +7 -0
- package/registry/blocks/logo-cloud-enterprise-wall/LogoCloudEnterpriseWall.tsx +114 -0
- package/registry/blocks/logo-cloud-enterprise-wall/index.ts +7 -0
- package/registry/blocks/logo-cloud-flanked-heading/LogoCloudFlankedHeading.tsx +162 -0
- package/registry/blocks/logo-cloud-flanked-heading/index.ts +8 -0
- package/registry/blocks/logo-cloud-grid-closing-cta/LogoCloudGridClosingCta.tsx +173 -0
- package/registry/blocks/logo-cloud-grid-closing-cta/index.ts +8 -0
- package/registry/blocks/logo-cloud-heading-grid/LogoCloudHeadingGrid.tsx +124 -0
- package/registry/blocks/logo-cloud-heading-grid/index.ts +7 -0
- package/registry/blocks/logo-cloud-heading-left-grid-right/LogoCloudHeadingLeftGridRight.tsx +172 -0
- package/registry/blocks/logo-cloud-heading-left-grid-right/index.ts +8 -0
- package/registry/blocks/logo-cloud-logo-metric-tiles/LogoCloudLogoMetricTiles.tsx +159 -0
- package/registry/blocks/logo-cloud-logo-metric-tiles/index.ts +8 -0
- package/registry/blocks/logo-cloud-logo-quote-cards/LogoCloudLogoQuoteCards.tsx +162 -0
- package/registry/blocks/logo-cloud-logo-quote-cards/index.ts +8 -0
- package/registry/blocks/logo-cloud-logo-testimonial-strip/LogoCloudLogoTestimonialStrip.tsx +159 -0
- package/registry/blocks/logo-cloud-logo-testimonial-strip/index.ts +8 -0
- package/registry/blocks/logo-cloud-named-integration-cards/LogoCloudNamedIntegrationCards.tsx +186 -0
- package/registry/blocks/logo-cloud-named-integration-cards/index.ts +9 -0
- package/registry/blocks/logo-cloud-pyramid-row-stack/LogoCloudPyramidRowStack.tsx +156 -0
- package/registry/blocks/logo-cloud-pyramid-row-stack/index.ts +7 -0
- package/registry/blocks/logo-cloud-quote-panel-grid/LogoCloudQuotePanelGrid.tsx +177 -0
- package/registry/blocks/logo-cloud-quote-panel-grid/index.ts +8 -0
- package/registry/blocks/logo-cloud-scatter-field/LogoCloudScatterField.tsx +190 -0
- package/registry/blocks/logo-cloud-scatter-field/index.ts +8 -0
- package/registry/blocks/logo-cloud-side-label-rail/LogoCloudSideLabelRail.tsx +139 -0
- package/registry/blocks/logo-cloud-side-label-rail/index.ts +7 -0
- package/registry/blocks/logo-cloud-stat-rail-above-grid/LogoCloudStatRailAboveGrid.tsx +173 -0
- package/registry/blocks/logo-cloud-stat-rail-above-grid/index.ts +8 -0
- package/registry/blocks/logo-cloud-tabbed-industry-filter/LogoCloudTabbedIndustryFilter.tsx +200 -0
- package/registry/blocks/logo-cloud-tabbed-industry-filter/index.ts +8 -0
- package/registry/blocks/navbar/index.ts +22 -11
- package/registry/blocks/navbar/navbar.test.tsx +42 -0
- package/registry/blocks/navbar/navbar.tsx +455 -0
- package/registry/blocks/navbar-active-action-with-border/NavbarActiveActionWithBorder.tsx +120 -0
- package/registry/blocks/navbar-active-action-with-border/index.ts +6 -0
- package/registry/blocks/navbar-active-action-with-round/NavbarActiveActionWithRound.tsx +120 -0
- package/registry/blocks/navbar-active-action-with-round/index.ts +6 -0
- package/registry/blocks/navbar-centered-floating/NavbarCenteredFloating.tsx +121 -0
- package/registry/blocks/navbar-centered-floating/index.ts +6 -0
- package/registry/blocks/navbar-default/NavbarDefault.tsx +102 -0
- package/registry/blocks/navbar-default/index.ts +6 -0
- package/registry/blocks/navbar-e-commerce/NavbarECommerce.tsx +212 -0
- package/registry/blocks/navbar-e-commerce/index.ts +6 -0
- package/registry/blocks/navbar-extended-at-top/NavbarExtendedAtTop.tsx +155 -0
- package/registry/blocks/navbar-extended-at-top/index.ts +7 -0
- package/registry/blocks/navbar-multiple-action/NavbarMultipleAction.tsx +133 -0
- package/registry/blocks/navbar-multiple-action/index.ts +6 -0
- package/registry/blocks/navbar-multiple-icon/NavbarMultipleIcon.tsx +132 -0
- package/registry/blocks/navbar-multiple-icon/index.ts +6 -0
- package/registry/blocks/navbar-rounded/NavbarRounded.tsx +140 -0
- package/registry/blocks/navbar-rounded/index.ts +6 -0
- package/registry/blocks/navbar-rounded-small/NavbarRoundedSmall.tsx +143 -0
- package/registry/blocks/navbar-rounded-small/index.ts +6 -0
- package/registry/blocks/navbar-small/NavbarSmall.tsx +142 -0
- package/registry/blocks/navbar-small/index.ts +6 -0
- package/registry/blocks/navbar-with-centered-logo/NavbarWithCenteredLogo.tsx +118 -0
- package/registry/blocks/navbar-with-centered-logo/index.ts +6 -0
- package/registry/blocks/navbar-with-cta-button/NavbarWithCtaButton.tsx +131 -0
- package/registry/blocks/navbar-with-cta-button/index.ts +6 -0
- package/registry/blocks/navbar-with-dropdown/NavbarWithDropdown.tsx +118 -0
- package/registry/blocks/navbar-with-dropdown/index.ts +6 -0
- package/registry/blocks/navbar-with-icon-indicator-avatar/NavbarWithIconIndicatorAvatar.tsx +85 -0
- package/registry/blocks/navbar-with-icon-indicator-avatar/index.ts +6 -0
- package/registry/blocks/navbar-with-search-input/NavbarWithSearchInput.tsx +90 -0
- package/registry/blocks/navbar-with-search-input/index.ts +6 -0
- package/registry/blocks/navbar-with-submenu/NavbarWithSubmenu.tsx +156 -0
- package/registry/blocks/navbar-with-submenu/index.ts +6 -0
- package/registry/blocks/page-header/PageHeader.tsx +5 -9
- package/registry/blocks/pricing/index.ts +20 -0
- package/registry/blocks/pricing/pricing.test.tsx +82 -0
- package/registry/blocks/pricing/pricing.tsx +343 -0
- package/registry/blocks/pricing-comparison-matrix/PricingComparisonMatrix.tsx +336 -0
- package/registry/blocks/pricing-comparison-matrix/index.ts +10 -0
- package/registry/blocks/pricing-plan-picker-summary/PricingPlanPickerSummary.tsx +399 -0
- package/registry/blocks/pricing-plan-picker-summary/index.ts +8 -0
- package/registry/blocks/pricing-plan-spotlight/PricingPlanSpotlight.tsx +281 -0
- package/registry/blocks/pricing-plan-spotlight/index.ts +7 -0
- package/registry/blocks/pricing-tiers/PricingTiers.tsx +264 -0
- package/registry/blocks/pricing-tiers/index.ts +8 -0
- package/registry/blocks/pricing-two-plan-compare/PricingTwoPlanCompare.tsx +187 -0
- package/registry/blocks/pricing-two-plan-compare/index.ts +7 -0
- package/registry/blocks/social-proof/index.ts +36 -0
- package/registry/blocks/social-proof/social-proof.test.tsx +504 -0
- package/registry/blocks/social-proof/social-proof.tsx +759 -0
- package/registry/blocks/social-proof-app-review-row/SocialProofAppReviewRow.tsx +168 -0
- package/registry/blocks/social-proof-app-review-row/index.ts +7 -0
- package/registry/blocks/social-proof-arch-portrait-quote/SocialProofArchPortraitQuote.tsx +114 -0
- package/registry/blocks/social-proof-arch-portrait-quote/index.ts +6 -0
- package/registry/blocks/social-proof-avatar-selector-row/SocialProofAvatarSelectorRow.tsx +276 -0
- package/registry/blocks/social-proof-avatar-selector-row/index.ts +7 -0
- package/registry/blocks/social-proof-benefit-title-cards/SocialProofBenefitTitleCards.tsx +182 -0
- package/registry/blocks/social-proof-benefit-title-cards/index.ts +8 -0
- package/registry/blocks/social-proof-bracket-framed-quote/SocialProofBracketFramedQuote.tsx +120 -0
- package/registry/blocks/social-proof-bracket-framed-quote/index.ts +6 -0
- package/registry/blocks/social-proof-case-study-row/SocialProofCaseStudyRow.tsx +210 -0
- package/registry/blocks/social-proof-case-study-row/index.ts +7 -0
- package/registry/blocks/social-proof-centered-logo-spotlight/SocialProofCenteredLogoSpotlight.tsx +103 -0
- package/registry/blocks/social-proof-centered-logo-spotlight/index.ts +6 -0
- package/registry/blocks/social-proof-classic-trio-grid/SocialProofClassicTrioGrid.tsx +138 -0
- package/registry/blocks/social-proof-classic-trio-grid/index.ts +7 -0
- package/registry/blocks/social-proof-dark-editorial-split/SocialProofDarkEditorialSplit.tsx +111 -0
- package/registry/blocks/social-proof-dark-editorial-split/index.ts +6 -0
- package/registry/blocks/social-proof-giant-quote-duo/SocialProofGiantQuoteDuo.tsx +156 -0
- package/registry/blocks/social-proof-giant-quote-duo/index.ts +8 -0
- package/registry/blocks/social-proof-highlighted-phrase-spotlight/SocialProofHighlightedPhraseSpotlight.tsx +130 -0
- package/registry/blocks/social-proof-highlighted-phrase-spotlight/index.ts +7 -0
- package/registry/blocks/social-proof-overlay-photo-quote/SocialProofOverlayPhotoQuote.tsx +111 -0
- package/registry/blocks/social-proof-overlay-photo-quote/index.ts +7 -0
- package/registry/blocks/social-proof-persona-pillars/SocialProofPersonaPillars.tsx +253 -0
- package/registry/blocks/social-proof-persona-pillars/index.ts +7 -0
- package/registry/blocks/social-proof-progress-carousel/SocialProofProgressCarousel.tsx +249 -0
- package/registry/blocks/social-proof-progress-carousel/index.ts +8 -0
- package/registry/blocks/social-proof-proof-bento/SocialProofProofBento.tsx +218 -0
- package/registry/blocks/social-proof-proof-bento/index.ts +6 -0
- package/registry/blocks/social-proof-spotlight-carousel/SocialProofSpotlightCarousel.tsx +212 -0
- package/registry/blocks/social-proof-spotlight-carousel/index.ts +7 -0
- package/registry/blocks/social-proof-staggered-columns/SocialProofStaggeredColumns.tsx +227 -0
- package/registry/blocks/social-proof-staggered-columns/index.ts +7 -0
- package/registry/blocks/social-proof-stat-story-cards/SocialProofStatStoryCards.tsx +218 -0
- package/registry/blocks/social-proof-stat-story-cards/index.ts +7 -0
- package/registry/blocks/social-proof-tinted-panel-portrait/SocialProofTintedPanelPortrait.tsx +130 -0
- package/registry/blocks/social-proof-tinted-panel-portrait/index.ts +7 -0
- package/registry/blocks/social-proof-tweet-wall/SocialProofTweetWall.tsx +179 -0
- package/registry/blocks/social-proof-tweet-wall/index.ts +7 -0
- package/registry/blocks/social-proof-vertical-column-wall/SocialProofVerticalColumnWall.tsx +220 -0
- package/registry/blocks/social-proof-vertical-column-wall/index.ts +7 -0
- package/registry/blocks/social-proof-video-story-cards/SocialProofVideoStoryCards.tsx +177 -0
- package/registry/blocks/social-proof-video-story-cards/index.ts +7 -0
- package/registry/blocks/social-proof-workplace-portrait-stories/SocialProofWorkplacePortraitStories.tsx +320 -0
- package/registry/blocks/social-proof-workplace-portrait-stories/index.ts +7 -0
- package/registry/blocks/team/index.ts +21 -0
- package/registry/blocks/team/team-classes.test.ts +35 -0
- package/registry/blocks/team/team.tsx +315 -0
- package/registry/blocks/team-annotated-portrait-lineup/TeamAnnotatedPortraitLineup.tsx +310 -0
- package/registry/blocks/team-annotated-portrait-lineup/index.ts +8 -0
- package/registry/blocks/team-annotated-portrait-lineup/team-annotated-portrait-lineup.test.tsx +71 -0
- package/registry/blocks/team-compact-directory-rows/TeamCompactDirectoryRows.tsx +190 -0
- package/registry/blocks/team-compact-directory-rows/compact-directory-rows.test.tsx +40 -0
- package/registry/blocks/team-compact-directory-rows/index.ts +7 -0
- package/registry/blocks/team-department-tabs-directory/TeamDepartmentTabsDirectory.tsx +414 -0
- package/registry/blocks/team-department-tabs-directory/department-tabs-directory.test.tsx +87 -0
- package/registry/blocks/team-department-tabs-directory/index.ts +10 -0
- package/registry/blocks/team-founder-spotlight/TeamFounderSpotlight.tsx +176 -0
- package/registry/blocks/team-founder-spotlight/index.ts +8 -0
- package/registry/blocks/team-founder-spotlight/team-founder-spotlight.test.tsx +70 -0
- package/registry/blocks/team-grid-backdrop-roster/TeamGridBackdropRoster.tsx +234 -0
- package/registry/blocks/team-grid-backdrop-roster/grid-backdrop-roster.test.tsx +72 -0
- package/registry/blocks/team-grid-backdrop-roster/index.ts +8 -0
- package/registry/blocks/team-hairline-grid/TeamHairlineGrid.tsx +190 -0
- package/registry/blocks/team-hairline-grid/hairline-grid.test.tsx +49 -0
- package/registry/blocks/team-hairline-grid/index.ts +1 -0
- package/registry/blocks/team-leadership-grid/TeamLeadershipGrid.tsx +183 -0
- package/registry/blocks/team-leadership-grid/index.ts +7 -0
- package/registry/blocks/team-leadership-grid/team-leadership-grid.test.tsx +38 -0
- package/registry/blocks/team-member-carousel/TeamMemberCarousel.tsx +178 -0
- package/registry/blocks/team-member-carousel/index.ts +7 -0
- package/registry/blocks/team-member-carousel/team-member-carousel.test.tsx +58 -0
- package/registry/blocks/team-member-table/TeamMemberTable.tsx +184 -0
- package/registry/blocks/team-member-table/index.ts +7 -0
- package/registry/blocks/team-member-table/member-table.test.tsx +43 -0
- package/registry/blocks/team-meta-profile-cards/TeamMetaProfileCards.tsx +155 -0
- package/registry/blocks/team-meta-profile-cards/index.ts +7 -0
- package/registry/blocks/team-meta-profile-cards/team-meta-profile-cards.test.tsx +29 -0
- package/registry/blocks/team-overlay-portrait-cards/TeamOverlayPortraitCards.tsx +145 -0
- package/registry/blocks/team-overlay-portrait-cards/index.ts +7 -0
- package/registry/blocks/team-overlay-portrait-cards/team-overlay-portrait-cards.test.tsx +49 -0
- package/registry/blocks/team-portrait-wall/TeamPortraitWall.tsx +131 -0
- package/registry/blocks/team-portrait-wall/index.ts +1 -0
- package/registry/blocks/team-portrait-wall/portrait-wall.test.tsx +45 -0
- package/registry/blocks/team-split-intro-member-rail/TeamSplitIntroMemberRail.tsx +203 -0
- package/registry/blocks/team-split-intro-member-rail/index.ts +7 -0
- package/registry/blocks/team-split-intro-member-rail/split-intro-member-rail.test.tsx +52 -0
- package/registry/blocks/team-we-re-hiring-cta/TeamWeReHiringCta.tsx +192 -0
- package/registry/blocks/team-we-re-hiring-cta/index.ts +7 -0
- package/registry/blocks/team-we-re-hiring-cta/we-re-hiring-cta.test.tsx +44 -0
- package/registry/blocks/video-call/index.ts +53 -0
- package/registry/blocks/video-call/video-call-around.test.tsx +427 -0
- package/registry/blocks/video-call/video-call-before.test.tsx +438 -0
- package/registry/blocks/video-call/video-call-hero.test.tsx +236 -0
- package/registry/blocks/video-call/video-call-stages.test.tsx +477 -0
- package/registry/blocks/video-call/video-call.test.tsx +794 -0
- package/registry/blocks/video-call/video-call.tsx +1282 -0
- package/registry/blocks/video-call-ai-meeting-recap/VideoCallAiMeetingRecap.tsx +466 -0
- package/registry/blocks/video-call-ai-meeting-recap/index.ts +9 -0
- package/registry/blocks/video-call-call-controls-dock/VideoCallCallControlsDock.tsx +211 -0
- package/registry/blocks/video-call-call-controls-dock/index.ts +6 -0
- package/registry/blocks/video-call-call-ended-summary/VideoCallCallEndedSummary.tsx +464 -0
- package/registry/blocks/video-call-call-ended-summary/index.ts +10 -0
- package/registry/blocks/video-call-call-with-side-panel/VideoCallCallWithSidePanel.tsx +357 -0
- package/registry/blocks/video-call-call-with-side-panel/index.ts +6 -0
- package/registry/blocks/video-call-captions-reactions/VideoCallCaptionsReactions.tsx +467 -0
- package/registry/blocks/video-call-captions-reactions/index.ts +10 -0
- package/registry/blocks/video-call-grid-gallery-call/VideoCallGridGalleryCall.tsx +312 -0
- package/registry/blocks/video-call-grid-gallery-call/index.ts +6 -0
- package/registry/blocks/video-call-hero-call-mockup/VideoCallHeroCallMockup.tsx +349 -0
- package/registry/blocks/video-call-hero-call-mockup/index.ts +7 -0
- package/registry/blocks/video-call-incoming-call/VideoCallIncomingCall.tsx +336 -0
- package/registry/blocks/video-call-incoming-call/index.ts +7 -0
- package/registry/blocks/video-call-join-link-dial-in/VideoCallJoinLinkDialIn.tsx +409 -0
- package/registry/blocks/video-call-join-link-dial-in/index.ts +9 -0
- package/registry/blocks/video-call-pre-join-lobby/VideoCallPreJoinLobby.tsx +345 -0
- package/registry/blocks/video-call-pre-join-lobby/index.ts +7 -0
- package/registry/blocks/video-call-screen-share-stage/VideoCallScreenShareStage.tsx +379 -0
- package/registry/blocks/video-call-screen-share-stage/index.ts +7 -0
- package/registry/blocks/video-call-speaker-filmstrip/VideoCallSpeakerFilmstrip.tsx +303 -0
- package/registry/blocks/video-call-speaker-filmstrip/index.ts +6 -0
- package/registry/blocks/video-call-upcoming-meetings/VideoCallUpcomingMeetings.tsx +349 -0
- package/registry/blocks/video-call-upcoming-meetings/index.ts +7 -0
- package/registry/blocks/video-call-waiting-room-knock/VideoCallWaitingRoomKnock.tsx +412 -0
- package/registry/blocks/video-call-waiting-room-knock/index.ts +7 -0
- package/registry/text-props-undefined.test.tsx +3 -26
- package/registry/ui/accordion/accordion.test.tsx +320 -0
- package/registry/ui/accordion/accordion.tsx +353 -0
- package/registry/ui/accordion/index.ts +15 -0
- package/registry/ui/alert/alert.test.tsx +325 -0
- package/registry/ui/alert/alert.tsx +384 -0
- package/registry/ui/alert/index.ts +10 -0
- package/registry/ui/alert-dialog/alert-dialog.test.tsx +396 -0
- package/registry/ui/alert-dialog/alert-dialog.tsx +423 -0
- package/registry/ui/alert-dialog/index.ts +21 -0
- package/registry/ui/avatar/avatar.test.tsx +2 -2
- package/registry/ui/avatar/avatar.tsx +3 -7
- package/registry/ui/breadcrumb/breadcrumb.test.tsx +305 -0
- package/registry/ui/breadcrumb/breadcrumb.tsx +205 -0
- package/registry/ui/breadcrumb/index.ts +11 -0
- package/registry/ui/button/button.test.tsx +353 -40
- package/registry/ui/button/button.tsx +304 -30
- package/registry/ui/calendar/calendar.test.tsx +192 -0
- package/registry/ui/calendar/calendar.tsx +405 -0
- package/registry/ui/calendar/index.ts +1 -0
- package/registry/ui/carousel/carousel.test.tsx +720 -0
- package/registry/ui/carousel/carousel.tsx +554 -0
- package/registry/ui/carousel/index.ts +11 -0
- package/registry/ui/checkbox/checkbox.test.tsx +318 -2
- package/registry/ui/checkbox/checkbox.tsx +253 -67
- package/registry/ui/checkbox/index.ts +1 -1
- package/registry/ui/content-carousel/content-carousel.test.tsx +303 -0
- package/registry/ui/content-carousel/content-carousel.tsx +180 -0
- package/registry/ui/content-carousel/index.ts +8 -0
- package/registry/ui/date-picker/date-picker.test.tsx +216 -0
- package/registry/ui/date-picker/date-picker.tsx +461 -0
- package/registry/ui/date-picker/index.ts +8 -0
- package/registry/ui/dialog/dialog.test.tsx +438 -0
- package/registry/ui/dialog/dialog.tsx +533 -0
- package/registry/ui/dialog/index.ts +20 -0
- package/registry/ui/dropdown-menu/dropdown-menu.test.tsx +502 -0
- package/registry/ui/dropdown-menu/dropdown-menu.tsx +627 -0
- package/registry/ui/dropdown-menu/index.ts +32 -0
- package/registry/ui/fasla-logo/fasla-logo.tsx +101 -0
- package/registry/ui/fasla-logo/index.ts +1 -0
- package/registry/ui/input/index.ts +10 -1
- package/registry/ui/input/input.test.tsx +251 -44
- package/registry/ui/input/input.tsx +311 -40
- package/registry/ui/input-number/index.ts +1 -0
- package/registry/ui/input-number/input-number.test.tsx +302 -0
- package/registry/ui/input-number/input-number.tsx +398 -0
- package/registry/ui/input-otp/index.ts +7 -0
- package/registry/ui/input-otp/input-otp.test.tsx +299 -0
- package/registry/ui/input-otp/input-otp.tsx +279 -0
- package/registry/ui/pagination/index.ts +12 -0
- package/registry/ui/pagination/pagination.test.tsx +330 -0
- package/registry/ui/pagination/pagination.tsx +336 -0
- package/registry/ui/progress/index.ts +8 -0
- package/registry/ui/progress/progress.test.tsx +168 -0
- package/registry/ui/progress/progress.tsx +165 -0
- package/registry/ui/select/index.ts +12 -1
- package/registry/ui/select/select.test.tsx +505 -0
- package/registry/ui/select/select.tsx +658 -56
- package/registry/ui/sheet/index.ts +19 -0
- package/registry/ui/sheet/sheet.test.tsx +411 -0
- package/registry/ui/sheet/sheet.tsx +496 -0
- package/registry/{blocks → ui}/sidebar/index.ts +10 -5
- package/registry/ui/sidebar/sidebar.test.tsx +224 -0
- package/registry/ui/sidebar/sidebar.tsx +754 -0
- package/registry/ui/slider/index.ts +8 -0
- package/registry/ui/slider/slider.test.tsx +231 -0
- package/registry/ui/slider/slider.tsx +319 -0
- package/registry/ui/social-icons/index.ts +1 -0
- package/registry/ui/social-icons/social-icons.tsx +284 -0
- package/registry/ui/steps/index.ts +16 -0
- package/registry/ui/steps/steps.test.tsx +435 -0
- package/registry/ui/steps/steps.tsx +571 -0
- package/registry/ui/switch/switch.tsx +3 -2
- package/registry/ui/tabs/index.ts +4 -0
- package/registry/ui/tabs/tabs.test.tsx +576 -0
- package/registry/ui/tabs/tabs.tsx +324 -112
- package/registry/ui/textarea/index.ts +1 -1
- package/registry/ui/textarea/textarea.test.tsx +294 -0
- package/registry/ui/textarea/textarea.tsx +329 -56
- package/registry/ui/tooltip/index.ts +14 -0
- package/registry/ui/tooltip/tooltip.test.tsx +301 -0
- package/registry/ui/tooltip/tooltip.tsx +409 -0
- package/registry.json +9702 -139
- package/tailwind-preset.ts +2 -2
- package/registry/blocks/navbar/Navbar.test.tsx +0 -12
- package/registry/blocks/navbar/Navbar.tsx +0 -175
- package/registry/blocks/sidebar/Sidebar.test.tsx +0 -39
- package/registry/blocks/sidebar/Sidebar.tsx +0 -212
|
@@ -0,0 +1,759 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { ChevronLeft, Star } from "lucide-react"
|
|
5
|
+
import { cn } from "../../../src/lib/utils"
|
|
6
|
+
import { Avatar } from "../../ui/avatar/avatar"
|
|
7
|
+
import { Button } from "../../ui/button/button"
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* Figma: `Social Proof` (46368:3361). The parts every `social-proof-*` block
|
|
11
|
+
* is built from: the section and its 1216px column, the header, a quote, the
|
|
12
|
+
* author line under it, the five stars, the hairline between a quote and its
|
|
13
|
+
* author, and the previous / next arrows.
|
|
14
|
+
*
|
|
15
|
+
* Mobile first, and sized by the block's own width, not the window's, as the
|
|
16
|
+
* Pricing and Gallery blocks are: the section is a query container, so a block
|
|
17
|
+
* lays out for the room it is given. The base classes are Figma's Mobile
|
|
18
|
+
* (360); `[@container(min-width:40rem)]:` is its Tablet and
|
|
19
|
+
* `[@container(min-width:64rem)]:` its Desktop. The section's own padding
|
|
20
|
+
* still follows the window, since an element can't query itself. The page's
|
|
21
|
+
* `dir` sets the direction; nothing here takes one.
|
|
22
|
+
*
|
|
23
|
+
* No block ships with photos. Every person and photo slot has an id, and a
|
|
24
|
+
* block takes `photos`, a map from those ids to image URLs: without it the
|
|
25
|
+
* avatars show initials and the photo slots their `muted` ground.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export type SocialProofLocale = "en" | "ar"
|
|
29
|
+
|
|
30
|
+
/** Photo URLs by id: a person's id (`"sami-naji"`) or a block's photo slot. */
|
|
31
|
+
export type SocialProofPhotos = Partial<Record<string, string>>
|
|
32
|
+
|
|
33
|
+
/** Someone quoted: the id their photo is keyed by, their name and their role. */
|
|
34
|
+
export interface SocialProofPerson {
|
|
35
|
+
/** The key in `photos` for this person's avatar. */
|
|
36
|
+
id: string
|
|
37
|
+
/** Up to 19 characters in English, 19 in Arabic. */
|
|
38
|
+
name: string
|
|
39
|
+
/** Role and company. Up to 48 characters in English, 50 in Arabic. */
|
|
40
|
+
role: React.ReactNode
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* A figure, a handle or a time inside a sentence: `2,300+`, `28%`, `2.1×`,
|
|
45
|
+
* `@Fasla`, `2:14`, `1.2K`, `01 / 04`. Each is a neutral run that an Arabic
|
|
46
|
+
* sentence would reorder (`+2,300`, `Fasla@`), so it is set in its own
|
|
47
|
+
* left-to-right isolate, as Figma's LRI…PDI marks set it.
|
|
48
|
+
*/
|
|
49
|
+
const FIGURE = /(@[A-Za-z0-9_.]+|\d+ \/ \d+|[−–-]?\$?\d[\d,.:]*[×%+Kh]?)/
|
|
50
|
+
|
|
51
|
+
/** Text with every figure and handle in its own left-to-right isolate. Anything but a string passes through. */
|
|
52
|
+
export function Isolated({ children }: { children: React.ReactNode }) {
|
|
53
|
+
if (typeof children !== "string") return <>{children}</>
|
|
54
|
+
const parts = children.split(FIGURE)
|
|
55
|
+
if (parts.length === 1) return <>{children}</>
|
|
56
|
+
return (
|
|
57
|
+
<>
|
|
58
|
+
{parts.map((part, index) =>
|
|
59
|
+
index % 2 === 1 ? (
|
|
60
|
+
<bdi key={index} dir="ltr">
|
|
61
|
+
{part}
|
|
62
|
+
</bdi>
|
|
63
|
+
) : (
|
|
64
|
+
<React.Fragment key={index}>{part}</React.Fragment>
|
|
65
|
+
)
|
|
66
|
+
)}
|
|
67
|
+
</>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface SocialProofSectionProps extends React.HTMLAttributes<HTMLElement> {
|
|
72
|
+
/** The id of the heading that names the section. */
|
|
73
|
+
labelledBy?: string
|
|
74
|
+
/** Classes for the column inside the padding. */
|
|
75
|
+
contentClassName?: string
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Figma's section: `background`, padding 96 × 112 on Desktop, 64 × 24 on
|
|
80
|
+
* Tablet and 32 × 16 on phones, and a 1216px column. Each block sets the gap
|
|
81
|
+
* between its header and what follows on `contentClassName`.
|
|
82
|
+
*/
|
|
83
|
+
export function SocialProofSection({ labelledBy, className, contentClassName, children, ...props }: SocialProofSectionProps) {
|
|
84
|
+
return (
|
|
85
|
+
<section
|
|
86
|
+
aria-labelledby={labelledBy}
|
|
87
|
+
className={cn("[container-type:inline-size] bg-background px-4 py-8 md:px-6 md:py-16 lg:px-28 lg:py-24", className)}
|
|
88
|
+
{...props}
|
|
89
|
+
>
|
|
90
|
+
<div className={cn("mx-auto flex w-full max-w-[1216px] flex-col items-center", contentClassName)}>{children}</div>
|
|
91
|
+
</section>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Figma's two header sizes: 4XL (3XL on phones), or 3XL (2XL on phones). */
|
|
96
|
+
export type SocialProofHeadingSize = "4xl" | "3xl"
|
|
97
|
+
|
|
98
|
+
const HEADING: Record<SocialProofHeadingSize, string> = {
|
|
99
|
+
"4xl": "text-3xl [@container(min-width:40rem)]:text-4xl",
|
|
100
|
+
"3xl": "text-2xl [@container(min-width:40rem)]:text-3xl",
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface SocialProofHeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
|
|
104
|
+
/** The id the section's `aria-labelledby` points at. */
|
|
105
|
+
headingId: string
|
|
106
|
+
/** The section's heading, an `h2`. Up to 46 characters in English, 40 in Arabic. */
|
|
107
|
+
heading: React.ReactNode
|
|
108
|
+
/** The line under the heading. Hidden when empty. Up to 128 characters in English, 125 in Arabic. */
|
|
109
|
+
description?: React.ReactNode
|
|
110
|
+
headingSize?: SocialProofHeadingSize
|
|
111
|
+
/** LG under a 4XL heading, Base under a 3XL one. */
|
|
112
|
+
descriptionSize?: "lg" | "base"
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The centred header: the heading, Semi Bold in `foreground`, and the
|
|
117
|
+
* description in `muted-foreground` under it.
|
|
118
|
+
*/
|
|
119
|
+
export function SocialProofHeader({
|
|
120
|
+
headingId,
|
|
121
|
+
heading,
|
|
122
|
+
description,
|
|
123
|
+
headingSize = "4xl",
|
|
124
|
+
descriptionSize = "lg",
|
|
125
|
+
className,
|
|
126
|
+
children,
|
|
127
|
+
...props
|
|
128
|
+
}: SocialProofHeaderProps) {
|
|
129
|
+
return (
|
|
130
|
+
<header className={cn("flex w-full flex-col items-center gap-4 text-center", className)} {...props}>
|
|
131
|
+
<h2 id={headingId} className={cn("font-semibold text-foreground", HEADING[headingSize])}>
|
|
132
|
+
<Isolated>{heading}</Isolated>
|
|
133
|
+
</h2>
|
|
134
|
+
{description ? (
|
|
135
|
+
<p className={cn("text-muted-foreground", descriptionSize === "lg" ? "text-lg" : "text-base")}>
|
|
136
|
+
<Isolated>{description}</Isolated>
|
|
137
|
+
</p>
|
|
138
|
+
) : null}
|
|
139
|
+
{children}
|
|
140
|
+
</header>
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface SocialProofPhotoProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
145
|
+
/** The image URL, from the block's `photos`. Without it the slot shows its `muted` ground. */
|
|
146
|
+
src?: string
|
|
147
|
+
/** Describes the photo. "" for a portrait beside the person's name, which already says who it is. */
|
|
148
|
+
alt?: string
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* A photo slot: the image cropped to fill the slot, or the slot's `muted`
|
|
153
|
+
* ground when no photo is passed, as the About blocks show an empty slot.
|
|
154
|
+
* Photographs never mirror in RTL; only the slot moves.
|
|
155
|
+
*/
|
|
156
|
+
export function SocialProofPhoto({ src, alt = "", className, ...props }: SocialProofPhotoProps) {
|
|
157
|
+
return (
|
|
158
|
+
<div className={cn("overflow-hidden bg-muted", className)} {...props}>
|
|
159
|
+
{src ? <img src={src} alt={alt} decoding="async" loading="lazy" className="size-full object-cover" /> : null}
|
|
160
|
+
</div>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** The default accessible name of the five stars, per language. */
|
|
165
|
+
const STARS_LABEL: Record<SocialProofLocale, string> = { en: "Rated 5 out of 5", ar: "التقييم 5 من 5" }
|
|
166
|
+
|
|
167
|
+
export interface SocialProofStarsProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
168
|
+
/** Figma's Rating colours: `warning` is Amber, `primary` is Primary. */
|
|
169
|
+
tone?: "warning" | "primary"
|
|
170
|
+
locale?: SocialProofLocale
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* STAND-IN for the Rating atom (Figma `363:7242`), which is not in the code
|
|
175
|
+
* library yet: five full 16px stars, touching, as Figma's `sm` Rating draws
|
|
176
|
+
* them. Replace it with the Rating atom once it exists. That atom needs a
|
|
177
|
+
* `value` prop: Figma's `Filled=True` draws 4½ stars, and every Social Proof
|
|
178
|
+
* instance overrides the half star to show five.
|
|
179
|
+
*/
|
|
180
|
+
export function SocialProofStars({ tone = "warning", locale = "en", className, ...props }: SocialProofStarsProps) {
|
|
181
|
+
return (
|
|
182
|
+
<span role="img" aria-label={STARS_LABEL[locale]} className={cn("inline-flex shrink-0", tone === "warning" ? "text-warning" : "text-primary", className)} {...props}>
|
|
183
|
+
{Array.from({ length: 5 }, (_, index) => (
|
|
184
|
+
<Star key={index} size={16} strokeWidth={0} fill="currentColor" aria-hidden />
|
|
185
|
+
))}
|
|
186
|
+
</span>
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* STAND-IN for the Separator atom (Figma `14860:69243`), which is not in the
|
|
192
|
+
* code library yet: a 1px `border` line across its container, as Pricing's
|
|
193
|
+
* `PricingRule` is. Replace it with the Separator atom once it exists.
|
|
194
|
+
*/
|
|
195
|
+
export function SocialProofRule({ className }: { className?: string }) {
|
|
196
|
+
return <div role="presentation" className={cn("w-full border-t border-border", className)} />
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export interface SocialProofQuoteProps extends React.HTMLAttributes<HTMLQuoteElement> {
|
|
200
|
+
quote: React.ReactNode
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** The customer's words as a `blockquote`, its paragraph styled by the block. */
|
|
204
|
+
export function SocialProofQuote({ quote, className, ...props }: SocialProofQuoteProps) {
|
|
205
|
+
return (
|
|
206
|
+
<blockquote className={cn("m-0", className)} {...props}>
|
|
207
|
+
<p>
|
|
208
|
+
<Isolated>{quote}</Isolated>
|
|
209
|
+
</p>
|
|
210
|
+
</blockquote>
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export interface SocialProofAuthorProps extends React.HTMLAttributes<HTMLElement> {
|
|
215
|
+
person: SocialProofPerson
|
|
216
|
+
photos?: SocialProofPhotos
|
|
217
|
+
/** Figma's Avatar size: 32, or 24 in Giant Quote Duo. */
|
|
218
|
+
avatarSize?: "32" | "24"
|
|
219
|
+
/** Classes for the avatar, for the walls that draw the 32 Avatar at 28 or 36. */
|
|
220
|
+
avatarClassName?: string
|
|
221
|
+
/** SM Medium names, or SM Semi Bold in Tweet Wall. */
|
|
222
|
+
nameClassName?: string
|
|
223
|
+
/** The role's size: SM in the trio cards, XS everywhere else. */
|
|
224
|
+
roleSize?: "sm" | "xs"
|
|
225
|
+
/** The role's colour class, `text-muted-foreground` unless the card is dark. */
|
|
226
|
+
roleClassName?: string
|
|
227
|
+
/** The gap: 12px beside a 32 Avatar, 10px in the walls and the duo. */
|
|
228
|
+
gap?: "3" | "2.5"
|
|
229
|
+
/** Anything after the name and role, such as Tweet Wall's X mark. */
|
|
230
|
+
trailing?: React.ReactNode
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* The author line: the Avatar, then the name in `foreground` over the role.
|
|
235
|
+
* It is the `figcaption` of the `figure` that holds the quote, the name a
|
|
236
|
+
* `<cite>`, so it must sit inside that figure.
|
|
237
|
+
* The avatar is decorative beside the name: it shows the photo or, without
|
|
238
|
+
* one, the person's initials, and assistive tech skips it.
|
|
239
|
+
*/
|
|
240
|
+
export function SocialProofAuthor({
|
|
241
|
+
person,
|
|
242
|
+
photos,
|
|
243
|
+
avatarSize = "32",
|
|
244
|
+
avatarClassName,
|
|
245
|
+
nameClassName = "font-medium",
|
|
246
|
+
roleSize = "xs",
|
|
247
|
+
roleClassName = "text-muted-foreground",
|
|
248
|
+
gap = "3",
|
|
249
|
+
trailing,
|
|
250
|
+
className,
|
|
251
|
+
...props
|
|
252
|
+
}: SocialProofAuthorProps) {
|
|
253
|
+
return (
|
|
254
|
+
<figcaption className={cn("flex w-full items-center", gap === "3" ? "gap-3" : "gap-2.5", className)} {...props}>
|
|
255
|
+
<Avatar aria-hidden size={avatarSize} radius="rounded" src={photos?.[person.id]} name={person.name} className={cn("shrink-0", avatarClassName)} />
|
|
256
|
+
<div className={cn("flex min-w-0 flex-1 flex-col", roleSize === "sm" && "gap-0.5")}>
|
|
257
|
+
<cite className={cn("text-sm not-italic", nameClassName)}>{person.name}</cite>
|
|
258
|
+
<span className={cn(roleSize === "sm" ? "text-sm" : "text-xs", roleClassName)}>
|
|
259
|
+
<Isolated>{person.role}</Isolated>
|
|
260
|
+
</span>
|
|
261
|
+
</div>
|
|
262
|
+
{trailing}
|
|
263
|
+
</figcaption>
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** The arrows' accessible names, per language. */
|
|
268
|
+
const STEP_LABELS: Record<SocialProofLocale, { previous: string; next: string }> = {
|
|
269
|
+
en: { previous: "Previous", next: "Next" },
|
|
270
|
+
ar: { previous: "السابق", next: "التالي" },
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export interface SocialProofStepperProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
274
|
+
/** The item or set shown, from 0. */
|
|
275
|
+
index: number
|
|
276
|
+
/** How many items or sets there are. */
|
|
277
|
+
count: number
|
|
278
|
+
onIndexChange: (index: number) => void
|
|
279
|
+
locale?: SocialProofLocale
|
|
280
|
+
/** Overrides the arrows' accessible names. */
|
|
281
|
+
labels?: { previous: string; next: string }
|
|
282
|
+
/** Figma's Icon Button: Ghost xs (26px) in App Review Row, Outline xs in the carousels. */
|
|
283
|
+
variant?: "ghost" | "outline"
|
|
284
|
+
/** Names the region the arrows step through. */
|
|
285
|
+
controls?: string
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* The previous and next arrows, Figma's Icon Button. Paging stops at both
|
|
290
|
+
* ends rather than wrapping, so previous is disabled on the first item and
|
|
291
|
+
* next on the last. The arrows follow the reading direction: previous sits at
|
|
292
|
+
* the start and points back, so in Arabic it is the right-hand arrow, pointing
|
|
293
|
+
* right.
|
|
294
|
+
*/
|
|
295
|
+
export function SocialProofStepper({
|
|
296
|
+
index,
|
|
297
|
+
count,
|
|
298
|
+
onIndexChange,
|
|
299
|
+
locale = "en",
|
|
300
|
+
labels,
|
|
301
|
+
variant = "ghost",
|
|
302
|
+
controls,
|
|
303
|
+
className,
|
|
304
|
+
...props
|
|
305
|
+
}: SocialProofStepperProps) {
|
|
306
|
+
const names = labels ?? STEP_LABELS[locale]
|
|
307
|
+
return (
|
|
308
|
+
<div className={cn("flex items-center gap-2", className)} {...props}>
|
|
309
|
+
<Button
|
|
310
|
+
type="button"
|
|
311
|
+
variant={variant}
|
|
312
|
+
size="icon-xs"
|
|
313
|
+
aria-label={names.previous}
|
|
314
|
+
aria-controls={controls}
|
|
315
|
+
disabled={index <= 0}
|
|
316
|
+
onClick={() => onIndexChange(index - 1)}
|
|
317
|
+
>
|
|
318
|
+
<ChevronLeft aria-hidden className="rtl:rotate-180" />
|
|
319
|
+
</Button>
|
|
320
|
+
<Button
|
|
321
|
+
type="button"
|
|
322
|
+
variant={variant}
|
|
323
|
+
size="icon-xs"
|
|
324
|
+
aria-label={names.next}
|
|
325
|
+
aria-controls={controls}
|
|
326
|
+
disabled={index >= count - 1}
|
|
327
|
+
onClick={() => onIndexChange(index + 1)}
|
|
328
|
+
>
|
|
329
|
+
<ChevronLeft aria-hidden className="rotate-180 rtl:rotate-0" />
|
|
330
|
+
</Button>
|
|
331
|
+
</div>
|
|
332
|
+
)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Whether the page reads right to left, from the closest `dir`. Swipes use it:
|
|
337
|
+
* on an Arabic page, swiping toward the right goes to the next item.
|
|
338
|
+
*/
|
|
339
|
+
function isRtl(el: Element | null) {
|
|
340
|
+
return el?.closest("[dir]")?.getAttribute("dir") === "rtl"
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Swipe to step, for the blocks whose motion note offers it on Mobile: a
|
|
345
|
+
* horizontal drag of 40px or more steps once, toward the next item when it
|
|
346
|
+
* moves against the reading direction. Touch and pen only, and only while the
|
|
347
|
+
* swiped element is phone-sized (under 640px, Figma's Tablet), as the notes
|
|
348
|
+
* offer it on Mobile alone; a vertical drag scrolls the page as usual. Spread
|
|
349
|
+
* the result on the element to swipe.
|
|
350
|
+
*/
|
|
351
|
+
export function useSwipeStep(step: (delta: 1 | -1) => void) {
|
|
352
|
+
const start = React.useRef<{ x: number; y: number } | null>(null)
|
|
353
|
+
return {
|
|
354
|
+
onPointerDown: (event: React.PointerEvent<HTMLElement>) => {
|
|
355
|
+
if (event.pointerType === "mouse" || event.currentTarget.getBoundingClientRect().width >= 640) return
|
|
356
|
+
start.current = { x: event.clientX, y: event.clientY }
|
|
357
|
+
},
|
|
358
|
+
onPointerUp: (event: React.PointerEvent<HTMLElement>) => {
|
|
359
|
+
const from = start.current
|
|
360
|
+
start.current = null
|
|
361
|
+
if (!from) return
|
|
362
|
+
const dx = event.clientX - from.x
|
|
363
|
+
const dy = event.clientY - from.y
|
|
364
|
+
if (Math.abs(dx) < 40 || Math.abs(dx) < Math.abs(dy)) return
|
|
365
|
+
const forward = isRtl(event.currentTarget) ? dx > 0 : dx < 0
|
|
366
|
+
step(forward ? 1 : -1)
|
|
367
|
+
},
|
|
368
|
+
onPointerCancel: () => {
|
|
369
|
+
start.current = null
|
|
370
|
+
},
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* The arrow keys, for a block the reader steps through: the key pointing along
|
|
376
|
+
* the reading direction goes to the next item, so on an Arabic page the left
|
|
377
|
+
* arrow is next. Home and End jump to the first and last item. Spread the
|
|
378
|
+
* result on the focusable region or the row of choices.
|
|
379
|
+
*/
|
|
380
|
+
export function stepKeys(index: number, count: number, go: (index: number) => void) {
|
|
381
|
+
return (event: React.KeyboardEvent<HTMLElement>) => {
|
|
382
|
+
const rtl = isRtl(event.currentTarget)
|
|
383
|
+
const next = rtl ? "ArrowLeft" : "ArrowRight"
|
|
384
|
+
const previous = rtl ? "ArrowRight" : "ArrowLeft"
|
|
385
|
+
let target: number | null = null
|
|
386
|
+
if (event.key === next) target = Math.min(index + 1, count - 1)
|
|
387
|
+
else if (event.key === previous) target = Math.max(index - 1, 0)
|
|
388
|
+
else if (event.key === "Home") target = 0
|
|
389
|
+
else if (event.key === "End") target = count - 1
|
|
390
|
+
if (target === null) return
|
|
391
|
+
event.preventDefault()
|
|
392
|
+
if (target !== index) go(target)
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/*
|
|
397
|
+
* Motion, from the house presets in src/motion/presets.ts, copied as values
|
|
398
|
+
* so the block installs without them, as the Hero and Sheet blocks do:
|
|
399
|
+
* `fast` 120ms, `base` 180ms, the `standard` curve, and items entering 60ms
|
|
400
|
+
* apart (the stagger preset). Reduced motion keeps opacity only, in 120ms,
|
|
401
|
+
* with no stagger. It runs on the Web Animations API, like the other blocks.
|
|
402
|
+
*/
|
|
403
|
+
// useLayoutEffect warns during server rendering in React 18.
|
|
404
|
+
const useIsomorphicLayoutEffect = typeof window === "undefined" ? React.useEffect : React.useLayoutEffect
|
|
405
|
+
|
|
406
|
+
const FAST_MS = 120
|
|
407
|
+
const BASE_MS = 180
|
|
408
|
+
const STAGGER_MS = 60
|
|
409
|
+
const STANDARD = "cubic-bezier(0.2, 0, 0, 1)"
|
|
410
|
+
|
|
411
|
+
function prefersReducedMotion() {
|
|
412
|
+
return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Plays an entrance on each element: a fade (fadeIn) or, with `slide`, a 10px
|
|
417
|
+
* rise with the fade (slideUp), 180ms each, 60ms apart with `stagger`. An
|
|
418
|
+
* element marked `data-step-item="slide"` or `"fade"` picks its own. With
|
|
419
|
+
* reduced motion every element fades in together in 120ms.
|
|
420
|
+
*/
|
|
421
|
+
export function playEntrance(
|
|
422
|
+
nodes: HTMLElement[],
|
|
423
|
+
{ slide = false, stagger = true, fromX }: { slide?: boolean; stagger?: boolean; fromX?: number } = {}
|
|
424
|
+
) {
|
|
425
|
+
const reduced = prefersReducedMotion()
|
|
426
|
+
return nodes
|
|
427
|
+
.filter((node) => typeof node.animate === "function")
|
|
428
|
+
.map((node, index) =>
|
|
429
|
+
node.animate(
|
|
430
|
+
reduced
|
|
431
|
+
? [{ opacity: 0 }, { opacity: 1 }]
|
|
432
|
+
: fromX !== undefined
|
|
433
|
+
? [{ opacity: 0, transform: `translateX(${fromX}px)` }, { opacity: 1, transform: "none" }]
|
|
434
|
+
: !(node.dataset.stepItem === "slide" || (slide && node.dataset.stepItem !== "fade"))
|
|
435
|
+
? [{ opacity: 0 }, { opacity: 1 }]
|
|
436
|
+
: [{ opacity: 0, transform: "translateY(10px)" }, { opacity: 1, transform: "none" }],
|
|
437
|
+
{
|
|
438
|
+
duration: reduced ? FAST_MS : BASE_MS,
|
|
439
|
+
delay: reduced || !stagger ? 0 : index * STAGGER_MS,
|
|
440
|
+
easing: STANDARD,
|
|
441
|
+
fill: "backwards",
|
|
442
|
+
}
|
|
443
|
+
)
|
|
444
|
+
)
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Fades the elements out together, 180ms (120ms with reduced motion), and
|
|
449
|
+
* resolves when they are gone. With `toX` they also move that many pixels
|
|
450
|
+
* sideways, in 120ms: the horizontal swap's exit.
|
|
451
|
+
*/
|
|
452
|
+
export function playExit(nodes: HTMLElement[], { toX }: { toX?: number } = {}) {
|
|
453
|
+
const reduced = prefersReducedMotion()
|
|
454
|
+
const animations = nodes
|
|
455
|
+
.filter((node) => typeof node.animate === "function")
|
|
456
|
+
.map((node) =>
|
|
457
|
+
node.animate(
|
|
458
|
+
!reduced && toX !== undefined
|
|
459
|
+
? [{ opacity: 1, transform: "none" }, { opacity: 0, transform: `translateX(${toX}px)` }]
|
|
460
|
+
: [{ opacity: 1 }, { opacity: 0 }],
|
|
461
|
+
{ duration: reduced || toX !== undefined ? FAST_MS : BASE_MS, easing: STANDARD, fill: "forwards" }
|
|
462
|
+
)
|
|
463
|
+
)
|
|
464
|
+
return Promise.all(animations.map((animation) => animation.finished.catch(() => undefined)))
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/** How far a horizontal swap moves, in px: the `slideX` preset's 24. */
|
|
468
|
+
const SLIDE_X = 24
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* State for content the reader steps through or picks from: a set of
|
|
472
|
+
* reviews, a quote, a story, a portrait. `go` fades the shown items
|
|
473
|
+
* (`[data-step-item]` inside `ref`) out unless `exit` is off, swaps the index,
|
|
474
|
+
* then plays their entrance on the new ones, 60ms apart with `stagger`. It is
|
|
475
|
+
* manual only: nothing advances on a timer, and it stops at both ends.
|
|
476
|
+
*/
|
|
477
|
+
export function useStepper<T extends HTMLElement>({
|
|
478
|
+
count,
|
|
479
|
+
index: controlled,
|
|
480
|
+
onIndexChange,
|
|
481
|
+
defaultIndex = 0,
|
|
482
|
+
slide = true,
|
|
483
|
+
stagger = false,
|
|
484
|
+
exit = true,
|
|
485
|
+
axis = "y",
|
|
486
|
+
}: {
|
|
487
|
+
count: number
|
|
488
|
+
index?: number
|
|
489
|
+
onIndexChange?: (index: number) => void
|
|
490
|
+
defaultIndex?: number
|
|
491
|
+
slide?: boolean
|
|
492
|
+
stagger?: boolean
|
|
493
|
+
exit?: boolean
|
|
494
|
+
/**
|
|
495
|
+
* `"x"` swaps sideways (the `slideX` preset): every item leaves toward the
|
|
496
|
+
* start of the swap and the new ones arrive from the other side, mirrored on
|
|
497
|
+
* a right-to-left page. Going forward is toward the reading direction's end.
|
|
498
|
+
*/
|
|
499
|
+
axis?: "x" | "y"
|
|
500
|
+
}) {
|
|
501
|
+
const ref = React.useRef<T>(null)
|
|
502
|
+
const step = React.useRef(1)
|
|
503
|
+
const [own, setOwn] = React.useState(defaultIndex)
|
|
504
|
+
const index = Math.min(Math.max(controlled ?? own, 0), Math.max(count - 1, 0))
|
|
505
|
+
const changed = React.useRef(false)
|
|
506
|
+
const items = () => Array.from(ref.current?.querySelectorAll<HTMLElement>("[data-step-item]") ?? [])
|
|
507
|
+
useIsomorphicLayoutEffect(() => {
|
|
508
|
+
if (!changed.current) return
|
|
509
|
+
changed.current = false
|
|
510
|
+
playEntrance(items(), { slide, stagger, fromX: axis === "x" ? step.current * SLIDE_X : undefined })
|
|
511
|
+
}, [index, slide, stagger, axis])
|
|
512
|
+
const go = React.useCallback(
|
|
513
|
+
(next: number) => {
|
|
514
|
+
if (next < 0 || next >= count || next === index) return
|
|
515
|
+
const swap = () => {
|
|
516
|
+
changed.current = true
|
|
517
|
+
setOwn(next)
|
|
518
|
+
onIndexChange?.(next)
|
|
519
|
+
}
|
|
520
|
+
// +1 when the new item comes in from the end side: right in LTR, left in RTL.
|
|
521
|
+
step.current = (next > index ? 1 : -1) * (isRtl(ref.current) ? -1 : 1)
|
|
522
|
+
if (exit) playExit(items(), { toX: axis === "x" ? -step.current * SLIDE_X : undefined }).then(swap)
|
|
523
|
+
else swap()
|
|
524
|
+
},
|
|
525
|
+
[count, index, onIndexChange, exit, axis]
|
|
526
|
+
)
|
|
527
|
+
return { ref, index, go }
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* How many columns a stacked layout has room for, by the element's own width:
|
|
532
|
+
* one on phones, two from 640px (Figma's Tablet), three from 1024px (its
|
|
533
|
+
* Desktop), as the container queries split them. It starts at one, so the
|
|
534
|
+
* first render is the phone layout until the element has been measured.
|
|
535
|
+
*/
|
|
536
|
+
export function useColumnCount<T extends HTMLElement>(max: 2 | 3 = 3) {
|
|
537
|
+
const ref = React.useRef<T>(null)
|
|
538
|
+
const [count, setCount] = React.useState(1)
|
|
539
|
+
React.useEffect(() => {
|
|
540
|
+
const el = ref.current
|
|
541
|
+
if (!el) return
|
|
542
|
+
const measure = (width: number) => setCount(width >= 1024 && max === 3 ? 3 : width >= 640 ? 2 : 1)
|
|
543
|
+
measure(el.getBoundingClientRect().width)
|
|
544
|
+
if (typeof ResizeObserver === "undefined") return
|
|
545
|
+
const observer = new ResizeObserver((entries) => measure(entries[0]?.contentRect.width ?? el.getBoundingClientRect().width))
|
|
546
|
+
observer.observe(el)
|
|
547
|
+
return () => observer.disconnect()
|
|
548
|
+
}, [max])
|
|
549
|
+
return [ref, count] as const
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Splits items into columns the way Figma's walls do: three columns take the
|
|
554
|
+
* items in runs (1–2, 3–4, 5–6), two columns take them in turn (1, 3, 5 and
|
|
555
|
+
* 2, 4, 6), and one column takes them all.
|
|
556
|
+
*/
|
|
557
|
+
export function toColumns<T>(items: T[], count: number): T[][] {
|
|
558
|
+
if (count <= 1) return [items]
|
|
559
|
+
if (count === 2) return [items.filter((_, i) => i % 2 === 0), items.filter((_, i) => i % 2 === 1)]
|
|
560
|
+
const size = Math.ceil(items.length / count)
|
|
561
|
+
return Array.from({ length: count }, (_, i) => items.slice(i * size, (i + 1) * size))
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Plays the entrance once, the first time the element enters the viewport:
|
|
566
|
+
* its `[data-reveal]` children fade in one after another (fadeIn with the
|
|
567
|
+
* stagger preset), then stay. Vertical Column Wall's reveal is the only
|
|
568
|
+
* entrance in Social Proof. Besides it, only the two column Types move on
|
|
569
|
+
* their own (`useDrift`); everything else moves when the reader acts.
|
|
570
|
+
*/
|
|
571
|
+
export function useRevealOnce<T extends HTMLElement>() {
|
|
572
|
+
const ref = React.useRef<T>(null)
|
|
573
|
+
useIsomorphicLayoutEffect(() => {
|
|
574
|
+
const node = ref.current
|
|
575
|
+
if (!node || typeof IntersectionObserver === "undefined") return
|
|
576
|
+
let animations: Animation[] = []
|
|
577
|
+
const observer = new IntersectionObserver(
|
|
578
|
+
(entries) => {
|
|
579
|
+
if (!entries.some((entry) => entry.isIntersecting)) return
|
|
580
|
+
observer.disconnect()
|
|
581
|
+
animations = playEntrance(Array.from(node.querySelectorAll<HTMLElement>("[data-reveal]")))
|
|
582
|
+
},
|
|
583
|
+
{ threshold: 0.2 }
|
|
584
|
+
)
|
|
585
|
+
observer.observe(node)
|
|
586
|
+
return () => {
|
|
587
|
+
observer.disconnect()
|
|
588
|
+
animations.forEach((animation) => animation.cancel())
|
|
589
|
+
}
|
|
590
|
+
}, [])
|
|
591
|
+
return ref
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/** The play and stop buttons' accessible names, per language. */
|
|
595
|
+
const VIDEO_LABELS: Record<SocialProofLocale, { play: string; stop: string }> = {
|
|
596
|
+
en: { play: "Play", stop: "Close video" },
|
|
597
|
+
ar: { play: "تشغيل", stop: "إغلاق الفيديو" },
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* The play state of a story's video, for Video Story Cards and Proof Bento.
|
|
602
|
+
* The video starts only when the reader presses play: no hover preview, no
|
|
603
|
+
* autoplay, no pulse. Starting swaps the poster for the video with a fade
|
|
604
|
+
* (fadeIn, 180ms; 120ms with reduced motion), and the video's own controls
|
|
605
|
+
* take over. Figma shows the poster only, so the playing state and the way
|
|
606
|
+
* out of it, `stop`, are the block's. Focus follows: to the video on play,
|
|
607
|
+
* back to the play button on stop. Without a `src` there is nothing to play.
|
|
608
|
+
*/
|
|
609
|
+
export function useVideoPlayback(src: string | undefined, locale: SocialProofLocale = "en") {
|
|
610
|
+
const videoRef = React.useRef<HTMLVideoElement>(null)
|
|
611
|
+
const playRef = React.useRef<HTMLButtonElement>(null)
|
|
612
|
+
const [started, setStarted] = React.useState(false)
|
|
613
|
+
const refocus = React.useRef(false)
|
|
614
|
+
const play = () => {
|
|
615
|
+
if (!src) return
|
|
616
|
+
setStarted(true)
|
|
617
|
+
}
|
|
618
|
+
const stop = React.useCallback(() => {
|
|
619
|
+
videoRef.current?.pause()
|
|
620
|
+
refocus.current = true
|
|
621
|
+
setStarted(false)
|
|
622
|
+
}, [])
|
|
623
|
+
useIsomorphicLayoutEffect(() => {
|
|
624
|
+
const video = videoRef.current
|
|
625
|
+
if (started && video) {
|
|
626
|
+
playEntrance([video], { slide: false, stagger: false })
|
|
627
|
+
video.currentTime = 0
|
|
628
|
+
const playing = video.play?.()
|
|
629
|
+
playing?.catch?.(() => {})
|
|
630
|
+
video.focus()
|
|
631
|
+
} else if (refocus.current) {
|
|
632
|
+
refocus.current = false
|
|
633
|
+
playRef.current?.focus()
|
|
634
|
+
}
|
|
635
|
+
}, [started])
|
|
636
|
+
return { videoRef, playRef, started, play, stop, labels: VIDEO_LABELS[locale], available: Boolean(src) }
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/*
|
|
640
|
+
* Drift: the two column Types move on their own while they are in view, as
|
|
641
|
+
* the home page's wall of love does. It is the only motion in Social Proof
|
|
642
|
+
* that no one asked for, so it is held back wherever it could cost someone:
|
|
643
|
+
* it runs only while the block is in the viewport, pauses while the pointer
|
|
644
|
+
* is over it or focus is inside it, and does not run at all with reduced
|
|
645
|
+
* motion (a still frame). There is no pause button: hover and focus are the
|
|
646
|
+
* pause, and the block has nothing in it to read that moves faster than a
|
|
647
|
+
* slow loop.
|
|
648
|
+
*/
|
|
649
|
+
|
|
650
|
+
/*
|
|
651
|
+
* Reading speeds, in px per second. A column's loop lasts its distance (one
|
|
652
|
+
* copy's height plus the gap) divided by its speed, so every variant reads at
|
|
653
|
+
* the same pace whatever its card heights. Tune the drift here.
|
|
654
|
+
*/
|
|
655
|
+
|
|
656
|
+
/** Vertical Column Wall: the outer columns, and the middle one a little slower so the parallax stays. */
|
|
657
|
+
export const WALL_DRIFT_SPEED = { outer: 42, middle: 38 }
|
|
658
|
+
|
|
659
|
+
/** Staggered Columns: every column, up or down. */
|
|
660
|
+
export const STAGGERED_DRIFT_SPEED = 40
|
|
661
|
+
|
|
662
|
+
/** How long a loop of `distance` px takes at `speed` px per second, in ms. */
|
|
663
|
+
export function driftDuration(distance: number, speed: number) {
|
|
664
|
+
return (distance / speed) * 1000
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Runs the animations `make` builds for `root`, only while it is in view and
|
|
669
|
+
* not hovered or holding focus. `make` is called again when the root's width
|
|
670
|
+
* changes, or the size of anything `watch` selects, since the distances depend
|
|
671
|
+
* on the cards' heights (which change as fonts and photos load). The
|
|
672
|
+
* animations are cancelled on unmount and when reduced motion is turned on.
|
|
673
|
+
*/
|
|
674
|
+
export function useDrift<T extends HTMLElement>(make: (root: T) => Animation[], deps: React.DependencyList, watch = "[data-drift] > :first-child") {
|
|
675
|
+
const ref = React.useRef<T>(null)
|
|
676
|
+
React.useEffect(() => {
|
|
677
|
+
const root = ref.current
|
|
678
|
+
if (!root || typeof IntersectionObserver === "undefined" || prefersReducedMotion()) return
|
|
679
|
+
let animations: Animation[] = []
|
|
680
|
+
let visible = false
|
|
681
|
+
let hovered = false
|
|
682
|
+
let focused = false
|
|
683
|
+
const sync = () => animations.forEach((animation) => (visible && !hovered && !focused ? animation.play() : animation.pause()))
|
|
684
|
+
const start = () => {
|
|
685
|
+
animations.forEach((animation) => animation.cancel())
|
|
686
|
+
animations = []
|
|
687
|
+
// A resize after reduced motion was turned on must not bring the drift back.
|
|
688
|
+
if (prefersReducedMotion()) return
|
|
689
|
+
animations = make(root)
|
|
690
|
+
animations.forEach((animation) => animation.pause())
|
|
691
|
+
sync()
|
|
692
|
+
}
|
|
693
|
+
start()
|
|
694
|
+
const intersection = new IntersectionObserver((entries) => {
|
|
695
|
+
visible = entries.some((entry) => entry.isIntersecting)
|
|
696
|
+
sync()
|
|
697
|
+
})
|
|
698
|
+
intersection.observe(root)
|
|
699
|
+
let frame = 0
|
|
700
|
+
const watched = () => Array.from(root.querySelectorAll<HTMLElement>(watch))
|
|
701
|
+
const measure = () =>
|
|
702
|
+
[root, ...watched()]
|
|
703
|
+
.map((el) => {
|
|
704
|
+
const box = el.getBoundingClientRect()
|
|
705
|
+
return `${Math.round(box.height)}x${Math.round(box.width)}`
|
|
706
|
+
})
|
|
707
|
+
.join()
|
|
708
|
+
let size = measure()
|
|
709
|
+
const resize =
|
|
710
|
+
typeof ResizeObserver === "undefined"
|
|
711
|
+
? null
|
|
712
|
+
: new ResizeObserver(() => {
|
|
713
|
+
const next = measure()
|
|
714
|
+
if (next === size) return
|
|
715
|
+
size = next
|
|
716
|
+
cancelAnimationFrame(frame)
|
|
717
|
+
frame = requestAnimationFrame(start)
|
|
718
|
+
})
|
|
719
|
+
resize?.observe(root)
|
|
720
|
+
watched().forEach((el) => resize?.observe(el))
|
|
721
|
+
const enter = () => ((hovered = true), sync())
|
|
722
|
+
const leave = () => ((hovered = false), sync())
|
|
723
|
+
const focusIn = () => ((focused = true), sync())
|
|
724
|
+
const focusOut = (event: FocusEvent) => {
|
|
725
|
+
focused = root.contains(event.relatedTarget as Node | null)
|
|
726
|
+
sync()
|
|
727
|
+
}
|
|
728
|
+
root.addEventListener("pointerenter", enter)
|
|
729
|
+
root.addEventListener("pointerleave", leave)
|
|
730
|
+
root.addEventListener("focusin", focusIn)
|
|
731
|
+
root.addEventListener("focusout", focusOut)
|
|
732
|
+
const reduce = typeof window.matchMedia === "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null
|
|
733
|
+
const stopForReduced = () => {
|
|
734
|
+
if (reduce?.matches) animations.forEach((animation) => animation.cancel())
|
|
735
|
+
}
|
|
736
|
+
reduce?.addEventListener?.("change", stopForReduced)
|
|
737
|
+
return () => {
|
|
738
|
+
cancelAnimationFrame(frame)
|
|
739
|
+
intersection.disconnect()
|
|
740
|
+
resize?.disconnect()
|
|
741
|
+
root.removeEventListener("pointerenter", enter)
|
|
742
|
+
root.removeEventListener("pointerleave", leave)
|
|
743
|
+
root.removeEventListener("focusin", focusIn)
|
|
744
|
+
root.removeEventListener("focusout", focusOut)
|
|
745
|
+
reduce?.removeEventListener?.("change", stopForReduced)
|
|
746
|
+
animations.forEach((animation) => animation.cancel())
|
|
747
|
+
}
|
|
748
|
+
// `make` is rebuilt every render; `deps` says when it would build something different.
|
|
749
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
750
|
+
}, deps)
|
|
751
|
+
return ref
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/** True once mounted without reduced motion: when a drifting block adds its looped repeat. */
|
|
755
|
+
export function useCanDrift() {
|
|
756
|
+
const [can, setCan] = React.useState(false)
|
|
757
|
+
React.useEffect(() => setCan(!prefersReducedMotion()), [])
|
|
758
|
+
return can
|
|
759
|
+
}
|