@cronos-labs/ui 0.2.1 → 0.5.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.
@@ -0,0 +1,32 @@
1
+ import type { ElementType, MouseEvent, ReactNode } from 'react';
2
+ export type ButtonVariant = 'light' | 'dark';
3
+ export interface ButtonProps {
4
+ label: string;
5
+ variant?: ButtonVariant;
6
+ /** Decorative mark shown before the label. Pair with `iconSrc`. */
7
+ icon?: 'google-play' | 'app-store';
8
+ /** Resolved icon URL, so each site can ship its own artwork. */
9
+ iconSrc?: string;
10
+ /** Smaller line above the label, e.g. "Download on the". */
11
+ subLabel?: ReactNode;
12
+ href?: string;
13
+ rel?: string;
14
+ target?: string;
15
+ onClick?: (event: MouseEvent<HTMLElement>) => void;
16
+ /**
17
+ * Render as a different element or component.
18
+ *
19
+ * The reason this exists: an in-app destination needs a router link, not an
20
+ * `<a>`, or the navigation becomes a full page reload. Without it, callers
21
+ * re-implemented this button's surface by hand to get a `Link`.
22
+ *
23
+ * ```tsx
24
+ * <Button as={Link} to="/create" label="Create token" />
25
+ * ```
26
+ */
27
+ as?: ElementType;
28
+ /** Destination when rendering as a router link. Forwarded verbatim. */
29
+ to?: string;
30
+ 'aria-label'?: string;
31
+ }
32
+ export declare function Button({ icon, iconSrc, href, label, rel, subLabel, target, variant, as, to, onClick, 'aria-label': ariaLabel, }: ButtonProps): React.JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { IconWrap, Label, StoreSubLabel, Surface } from './styles.js';
3
+ export function Button({ icon, iconSrc, href, label, rel, subLabel, target, variant = 'light', as, to, onClick, 'aria-label': ariaLabel, }) {
4
+ return (_jsxs(Surface, { "$variant": variant, ...(as ? { as } : {}), ...(to !== undefined ? { to } : {}), href: href, rel: rel, target: target, onClick: onClick, "aria-label": ariaLabel, children: [icon && iconSrc ? (_jsx(IconWrap, { "$variant": variant, children: _jsx("img", { src: iconSrc, alt: "", "aria-hidden": "true" }) })) : null, _jsxs(Label, { children: [subLabel ? _jsx(StoreSubLabel, { "$variant": variant, children: subLabel }) : null, _jsx("strong", { children: label })] })] }));
5
+ }
@@ -0,0 +1,18 @@
1
+ export declare const Surface: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "style"> & {
2
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
3
+ }, {
4
+ $variant: "light" | "dark";
5
+ }>> & string;
6
+ export declare const IconWrap: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
7
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
8
+ }, {
9
+ $variant: "light" | "dark";
10
+ }>> & string;
11
+ export declare const Label: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
12
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
13
+ }> & string;
14
+ export declare const StoreSubLabel: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
15
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
16
+ }, {
17
+ $variant: "light" | "dark";
18
+ }>> & string;
@@ -0,0 +1,83 @@
1
+ import styled from 'styled-components';
2
+ export const Surface = styled.a `
3
+ display: inline-flex;
4
+ align-items: center;
5
+ justify-content: flex-start;
6
+ gap: ${({ $variant }) => ($variant === 'dark' ? '10px' : '8px')};
7
+ min-height: 56px;
8
+ min-width: 0;
9
+ padding: 16px 20px;
10
+ border: 1px solid
11
+ ${({ $variant, theme }) => $variant === 'dark' ? theme.colors.overlayBorderStrong : 'rgb(255 255 255 / 0.4)'};
12
+ border-radius: ${({ theme }) => theme.borderRadius.panel};
13
+ background: ${({ $variant, theme }) => ($variant === 'dark' ? '#111111' : theme.colors.light)};
14
+ color: ${({ $variant, theme }) => ($variant === 'dark' ? theme.colors.light : theme.colors.ink)};
15
+ box-shadow: ${({ theme }) => theme.shadow.button};
16
+ transition:
17
+ transform ${({ theme }) => theme.motion.duration.fast}
18
+ ${({ theme }) => theme.motion.easing.standard},
19
+ box-shadow ${({ theme }) => theme.motion.duration.fast}
20
+ ${({ theme }) => theme.motion.easing.standard},
21
+ background-color ${({ theme }) => theme.motion.duration.fast}
22
+ ${({ theme }) => theme.motion.easing.standard};
23
+
24
+ &:hover {
25
+ transform: translateY(-2px);
26
+ background: ${({ $variant, theme }) => $variant === 'dark' ? theme.colors.dark : 'rgb(255 255 255 / 0.92)'};
27
+ box-shadow: ${({ theme }) => theme.shadow.md};
28
+ }
29
+
30
+ &:focus-visible {
31
+ outline: none;
32
+ box-shadow:
33
+ 0 0 0 3px ${({ theme }) => theme.colors.focusRing},
34
+ ${({ theme }) => theme.shadow.button};
35
+ }
36
+
37
+ ${({ theme }) => theme.mediaQueries.md} {
38
+ min-height: 60px;
39
+ min-width: 153px;
40
+ padding: 18px 24px;
41
+ }
42
+ `;
43
+ export const IconWrap = styled.span `
44
+ display: inline-flex;
45
+ align-items: center;
46
+ justify-content: center;
47
+ min-width: 28px;
48
+ height: 24px;
49
+ font-size: 1.2rem;
50
+ line-height: 1;
51
+
52
+ img {
53
+ display: block;
54
+ width: auto;
55
+ height: 100%;
56
+ }
57
+ `;
58
+ export const Label = styled.span `
59
+ display: grid;
60
+ justify-items: start;
61
+ text-align: left;
62
+ gap: 6px;
63
+ line-height: 1;
64
+ min-width: 0;
65
+ font-family: ${({ theme }) => theme.typography.fontFamily.ui};
66
+
67
+ ${({ theme }) => theme.mediaQueries.xs} {
68
+ min-width: max-content;
69
+ }
70
+
71
+ strong {
72
+ font-size: 0.875rem;
73
+ font-weight: ${({ theme }) => theme.fontWeight.semibold};
74
+ letter-spacing: -0.03em;
75
+ }
76
+ `;
77
+ export const StoreSubLabel = styled.span `
78
+ color: ${({ $variant, theme }) => $variant === 'dark' ? theme.colors.overlayTextMuted : 'rgb(0 0 0 / 0.4)'};
79
+ font-size: 0.625rem;
80
+ font-weight: ${({ theme }) => theme.fontWeight.semibold};
81
+ letter-spacing: -0.03em;
82
+ text-transform: uppercase;
83
+ `;
@@ -22,7 +22,8 @@ export interface FooterContent {
22
22
  disclaimer: string[];
23
23
  }
24
24
  interface FooterProps {
25
- brandWordmarkSrc: string;
25
+ /** Overrides the wordmark from `<BrandProvider>`. Optional when one is present. */
26
+ brandWordmarkSrc?: string;
26
27
  columns: FooterLinkGroup[];
27
28
  content: FooterContent;
28
29
  forceDocumentNavigation?: boolean;
@@ -4,6 +4,7 @@ import { LocaleSelector } from '../LocaleSelector/index.js';
4
4
  import { buildLocalizedPath } from '../locale/routes.js';
5
5
  import { useCurrentLocale } from '../locale/hooks.js';
6
6
  import { desktopViewportQuery } from '../tokens.js';
7
+ import { useOptionalBrand } from '../brand/index.js';
7
8
  import { FooterColumn, FooterColumnHeading, FooterContainer, FooterCopyright, FooterColumnsGrid, FooterDesktopLocaleSlot, FooterDisclaimer, FooterDisclaimerStack, FooterGrid, FooterLegalButton, FooterLegalDivider, FooterLegalLink as FooterLegalLinkStyled, FooterLegalMeta, FooterLegalNav, FooterLegalText, FooterLocaleSlot, FooterLink as FooterLinkStyled, FooterLinkList, FooterMobileCopyright, FooterMobileDivider, FooterMobileLegalDividerTrack, FooterMobileLegalMeta, FooterMobileLegalNav, FooterShell, FooterWaitlistSlot, FooterWordmark, FooterWordmarkImage, } from './styles.js';
8
9
  const buildFooterHref = (target, locale, localize = true) => {
9
10
  if (target.startsWith('/') && localize) {
@@ -18,6 +19,11 @@ const getExternalLinkProps = (external) => {
18
19
  return { target: '_blank', rel: 'noreferrer' };
19
20
  };
20
21
  export function Footer({ brandWordmarkSrc, columns, content, forceDocumentNavigation = false, legalLinks, onOpenCookiePreferences, waitlistSlot, }) {
22
+ const brand = useOptionalBrand();
23
+ const wordmarkSrc = brandWordmarkSrc ?? brand?.wordmarkSrc;
24
+ if (wordmarkSrc === undefined) {
25
+ throw new Error('<Footer> needs a brandWordmarkSrc prop or a <BrandProvider>.');
26
+ }
21
27
  const locale = useCurrentLocale();
22
28
  const [isDesktopFooterLayout, setIsDesktopFooterLayout] = useState(true);
23
29
  useEffect(() => {
@@ -44,5 +50,5 @@ export function Footer({ brandWordmarkSrc, columns, content, forceDocumentNaviga
44
50
  return (_jsx(FooterLegalLinkStyled, { href: buildFooterHref(link.target, locale), ...getExternalLinkProps(link.external), children: link.label }));
45
51
  };
46
52
  const legalMeta = isDesktopFooterLayout ? (_jsxs(FooterLegalMeta, { children: [_jsx(FooterCopyright, { children: content.copyrightText }), _jsx(FooterLegalNav, { "aria-label": content.legalNavLabel, children: legalLinks.map((link, index) => (_jsxs("span", { children: [index > 0 ? _jsx(FooterLegalDivider, { "aria-hidden": "true" }) : null, renderLegalLink(link)] }, link.target))) })] })) : undefined;
47
- return (_jsx(FooterShell, { children: _jsxs(FooterContainer, { children: [_jsxs(FooterGrid, { children: [_jsx(FooterWaitlistSlot, { children: waitlistSlot?.(legalMeta) }), _jsx(FooterMobileDivider, { "aria-hidden": "true" }), _jsxs(FooterColumnsGrid, { children: [columns.map((group) => (_jsxs(FooterColumn, { children: [_jsx(FooterColumnHeading, { children: group.group }), _jsx(FooterLinkList, { children: group.links.map((link) => renderFooterLink(link)) })] }, group.group))), _jsxs(FooterDisclaimerStack, { children: [isDesktopFooterLayout ? (_jsx(FooterDesktopLocaleSlot, { children: _jsx(LocaleSelector, { ariaLabel: content.localeSelectorAriaLabel, forceDocumentNavigation: forceDocumentNavigation }) })) : null, _jsx(FooterDisclaimer, { children: content.disclaimer.map((paragraph) => (_jsx("p", { children: paragraph }, paragraph))) })] })] }), !isDesktopFooterLayout ? (_jsxs(FooterMobileLegalMeta, { children: [_jsx(FooterLocaleSlot, { children: _jsx(LocaleSelector, { ariaLabel: content.localeSelectorAriaLabel, forceDocumentNavigation: forceDocumentNavigation }) }), _jsx(FooterMobileCopyright, { children: content.copyrightText }), _jsx(FooterMobileLegalNav, { "aria-label": content.legalNavLabel, children: legalLinks.map((link, index) => (_jsxs(Fragment, { children: [index > 0 ? (_jsx(FooterMobileLegalDividerTrack, { children: _jsx(FooterLegalDivider, { "aria-hidden": "true" }) })) : null, renderLegalLink(link)] }, link.target))) })] })) : null] }), _jsx(FooterWordmark, { "aria-hidden": "true", children: _jsx(FooterWordmarkImage, { src: brandWordmarkSrc, alt: "" }) })] }) }));
53
+ return (_jsx(FooterShell, { children: _jsxs(FooterContainer, { children: [_jsxs(FooterGrid, { children: [_jsx(FooterWaitlistSlot, { children: waitlistSlot?.(legalMeta) }), _jsx(FooterMobileDivider, { "aria-hidden": "true" }), _jsxs(FooterColumnsGrid, { children: [columns.map((group) => (_jsxs(FooterColumn, { children: [_jsx(FooterColumnHeading, { children: group.group }), _jsx(FooterLinkList, { children: group.links.map((link) => renderFooterLink(link)) })] }, group.group))), _jsxs(FooterDisclaimerStack, { children: [isDesktopFooterLayout ? (_jsx(FooterDesktopLocaleSlot, { children: _jsx(LocaleSelector, { ariaLabel: content.localeSelectorAriaLabel, forceDocumentNavigation: forceDocumentNavigation }) })) : null, _jsx(FooterDisclaimer, { children: content.disclaimer.map((paragraph) => (_jsx("p", { children: paragraph }, paragraph))) })] })] }), !isDesktopFooterLayout ? (_jsxs(FooterMobileLegalMeta, { children: [_jsx(FooterLocaleSlot, { children: _jsx(LocaleSelector, { ariaLabel: content.localeSelectorAriaLabel, forceDocumentNavigation: forceDocumentNavigation }) }), _jsx(FooterMobileCopyright, { children: content.copyrightText }), _jsx(FooterMobileLegalNav, { "aria-label": content.legalNavLabel, children: legalLinks.map((link, index) => (_jsxs(Fragment, { children: [index > 0 ? (_jsx(FooterMobileLegalDividerTrack, { children: _jsx(FooterLegalDivider, { "aria-hidden": "true" }) })) : null, renderLegalLink(link)] }, link.target))) })] })) : null] }), _jsx(FooterWordmark, { "aria-hidden": "true", children: _jsx(FooterWordmarkImage, { src: wordmarkSrc, alt: "" }) })] }) }));
48
54
  }
@@ -0,0 +1,3 @@
1
+ import type { NavigationContent } from '../navigationContent.js';
2
+ import type { WaitlistFormMessages } from '../waitlist/types.js';
3
+ export declare const resolveWaitlistFormContent: (navContent: NavigationContent) => WaitlistFormMessages;
@@ -0,0 +1,7 @@
1
+ export const resolveWaitlistFormContent = (navContent) => ({
2
+ successMessage: navContent.footer.waitlistForm.successMessage,
3
+ emptyEmailMessage: navContent.footer.waitlistForm.emptyEmailMessage,
4
+ invalidEmailMessage: navContent.footer.waitlistForm.invalidEmailMessage,
5
+ errorMessage: navContent.footer.waitlistForm.errorMessage,
6
+ submittingLabel: navContent.footer.waitlistForm.submittingLabel,
7
+ });
@@ -0,0 +1,24 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { WaitlistRequest, WaitlistSource } from '../waitlist/types.js';
3
+ import { type FooterWaitlistVariant } from './styles.js';
4
+ export interface FooterWaitlistProps {
5
+ /** Identifies which form on the site was submitted. */
6
+ source: WaitlistSource;
7
+ /** Performs the submission. Resolve for success, throw for failure. */
8
+ submit: (request: WaitlistRequest) => Promise<unknown>;
9
+ /** Namespaces stored attribution. One stable value per site. */
10
+ attributionKey: string;
11
+ variant?: FooterWaitlistVariant;
12
+ legalMeta?: ReactNode | undefined;
13
+ onWaitlistSuccess?: ((message: string) => void) | undefined;
14
+ onWaitlistError?: ((message: string) => void) | undefined;
15
+ /** Fires when submit is pressed, before validation. For analytics. */
16
+ onSubmitClick?: (() => void) | undefined;
17
+ }
18
+ /**
19
+ * Email capture card with the site's social row beneath it.
20
+ *
21
+ * Wordmark and social links come from `<BrandProvider>`, so two sites render
22
+ * this identically while showing entirely different artwork and destinations.
23
+ */
24
+ export declare function FooterWaitlist({ source, submit, attributionKey, variant, legalMeta, onWaitlistSuccess, onWaitlistError, onSubmitClick, }: FooterWaitlistProps): React.JSX.Element;
@@ -0,0 +1,86 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
3
+ import { useBrand } from '../brand/index.js';
4
+ import { navigationContent } from '../navigationContent.js';
5
+ import { useCurrentLocale } from '../locale/hooks.js';
6
+ import { resetAutocompleteFillMarkersAfterInput } from '../waitlist/autocompleteFillMarkers.js';
7
+ import { useWaitlistForm } from '../waitlist/useWaitlistForm.js';
8
+ import { resolveWaitlistFormContent } from './helper.js';
9
+ import { WaitlistCard, WaitlistCardContent, WaitlistCardTitle, WaitlistCheckbox, WaitlistCheckboxLabel, WaitlistCheckboxRow, WaitlistContainer, WaitlistDisclaimer, WaitlistFieldGroup, WaitlistForm, WaitlistInput, WaitlistInputMeasure, WaitlistLowerContent, WaitlistSectionShell, WaitlistSocialBlock, WaitlistSocialIcon, WaitlistSocialLink, WaitlistSocialLinks, WaitlistStatusText, WaitlistSubmitButton, } from './styles.js';
10
+ // Below this the address is unreadable; the field scrolls instead of shrinking further.
11
+ const minWaitlistInputScale = 0.5;
12
+ /**
13
+ * Email capture card with the site's social row beneath it.
14
+ *
15
+ * Wordmark and social links come from `<BrandProvider>`, so two sites render
16
+ * this identically while showing entirely different artwork and destinations.
17
+ */
18
+ export function FooterWaitlist({ source, submit, attributionKey, variant = 'footer', legalMeta, onWaitlistSuccess, onWaitlistError, onSubmitClick, }) {
19
+ const locale = useCurrentLocale();
20
+ const brand = useBrand();
21
+ const navContent = navigationContent[locale];
22
+ const waitlistContent = resolveWaitlistFormContent(navContent);
23
+ const inputRef = useRef(null);
24
+ const inputMeasureRef = useRef(null);
25
+ const [waitlistInputScale, setWaitlistInputScale] = useState(1);
26
+ const waitlistMessages = {
27
+ ...waitlistContent,
28
+ emailPlaceholder: navContent.footer.emailPlaceholder,
29
+ submitLabel: navContent.footer.submitLabel,
30
+ };
31
+ const waitlistOptions = {
32
+ source,
33
+ submit,
34
+ attributionKey,
35
+ messages: waitlistMessages,
36
+ initialConsentMarketing: false,
37
+ };
38
+ if (onWaitlistSuccess) {
39
+ waitlistOptions.onSuccess = onWaitlistSuccess;
40
+ }
41
+ if (onWaitlistError) {
42
+ waitlistOptions.onError = onWaitlistError;
43
+ }
44
+ const { email, setEmail, consentMarketing, setConsentMarketing, emailError, isSubmitting, statusMessage, statusTone, onSubmit, } = useWaitlistForm(waitlistOptions);
45
+ const describedBy = statusMessage ? `${variant}-waitlist-status` : undefined;
46
+ const setWaitlistInputRef = useCallback((input) => {
47
+ inputRef.current = input;
48
+ if (input) {
49
+ resetAutocompleteFillMarkersAfterInput(input);
50
+ }
51
+ }, []);
52
+ const updateWaitlistInputScale = useCallback(() => {
53
+ const input = inputRef.current;
54
+ const inputMeasure = inputMeasureRef.current;
55
+ if (!email || !input || !inputMeasure) {
56
+ setWaitlistInputScale(1);
57
+ return;
58
+ }
59
+ const inputStyles = window.getComputedStyle(input);
60
+ const inputHorizontalPadding = Number.parseFloat(inputStyles.paddingLeft) + Number.parseFloat(inputStyles.paddingRight);
61
+ const availableInputWidth = input.clientWidth - inputHorizontalPadding;
62
+ const measuredTextWidth = inputMeasure.getBoundingClientRect().width;
63
+ if (availableInputWidth <= 0 || measuredTextWidth <= 0) {
64
+ setWaitlistInputScale(1);
65
+ return;
66
+ }
67
+ const nextScale = Math.min(1, Math.max(minWaitlistInputScale, availableInputWidth / measuredTextWidth));
68
+ setWaitlistInputScale((currentScale) => Math.abs(currentScale - nextScale) < 0.01 ? currentScale : nextScale);
69
+ }, [email]);
70
+ const handleWaitlistEmailChange = useCallback((event) => {
71
+ setEmail(event.currentTarget.value);
72
+ resetAutocompleteFillMarkersAfterInput(event.currentTarget);
73
+ }, [setEmail]);
74
+ useLayoutEffect(() => {
75
+ updateWaitlistInputScale();
76
+ }, [updateWaitlistInputScale]);
77
+ useEffect(() => {
78
+ window.addEventListener('resize', updateWaitlistInputScale);
79
+ return () => {
80
+ window.removeEventListener('resize', updateWaitlistInputScale);
81
+ };
82
+ }, [updateWaitlistInputScale]);
83
+ return (_jsx(WaitlistSectionShell, { "$variant": variant, children: _jsx(WaitlistContainer, { "$variant": variant, children: _jsx(WaitlistCard, { children: _jsxs(WaitlistCardContent, { "$variant": variant, children: [_jsx(WaitlistCardTitle, { "$variant": variant, children: navContent.footer.ctaTitle }), _jsxs(WaitlistForm, { "$variant": variant, noValidate: true, onSubmit: (event) => {
84
+ void onSubmit(event);
85
+ }, children: [_jsxs(WaitlistFieldGroup, { "$variant": variant, children: [_jsx(WaitlistInputMeasure, { ref: inputMeasureRef, "$variant": variant, "aria-hidden": "true", children: email }), _jsx(WaitlistInput, { ref: setWaitlistInputRef, "$variant": variant, "$fontScale": waitlistInputScale, "aria-describedby": describedBy, "aria-invalid": emailError ? true : undefined, "aria-label": waitlistMessages.emailPlaceholder, autoComplete: "email", placeholder: waitlistMessages.emailPlaceholder, type: "email", value: email, onChange: handleWaitlistEmailChange, onFocus: (event) => resetAutocompleteFillMarkersAfterInput(event.currentTarget) }), _jsx(WaitlistSubmitButton, { "$variant": variant, type: "submit", disabled: isSubmitting, onClick: onSubmitClick, children: isSubmitting ? waitlistMessages.submittingLabel : waitlistMessages.submitLabel })] }), statusMessage ? (_jsx(WaitlistStatusText, { "$tone": statusTone, id: `${variant}-waitlist-status`, "aria-live": "polite", role: "status", children: statusMessage })) : null, _jsx(WaitlistDisclaimer, { children: navContent.footer.consentNote })] }), _jsxs(WaitlistLowerContent, { "$variant": variant, children: [_jsxs(WaitlistCheckboxRow, { htmlFor: `${variant}-waitlist-marketing`, children: [_jsx(WaitlistCheckbox, { id: `${variant}-waitlist-marketing`, checked: consentMarketing, type: "checkbox", onChange: (event) => setConsentMarketing(event.target.checked) }), _jsx(WaitlistCheckboxLabel, { children: navContent.footer.consentLabel })] }), brand.socialLinks.length > 0 ? (_jsx(WaitlistSocialBlock, { "$variant": variant, "aria-label": navContent.footer.socialHeading, children: _jsx(WaitlistSocialLinks, { children: brand.socialLinks.map((socialLink) => (_jsx(WaitlistSocialLink, { href: socialLink.href, target: "_blank", rel: "noreferrer", "aria-label": socialLink.label, children: _jsx(WaitlistSocialIcon, { src: socialLink.iconSrc, alt: "", "aria-hidden": "true" }) }, socialLink.key))) }) })) : null, legalMeta] })] }) }) }) }));
86
+ }
@@ -0,0 +1,71 @@
1
+ export type FooterWaitlistVariant = 'standalone' | 'footer';
2
+ type StatusTone = 'default' | 'success' | 'error';
3
+ interface VariantProps {
4
+ $variant: FooterWaitlistVariant;
5
+ }
6
+ interface WaitlistInputProps extends VariantProps {
7
+ $fontScale: number;
8
+ }
9
+ export declare const WaitlistSectionShell: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, "style"> & {
10
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
11
+ }, VariantProps>> & string;
12
+ export declare const WaitlistContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
13
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
14
+ }, VariantProps>> & string;
15
+ export declare const WaitlistCard: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, "style"> & {
16
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
17
+ }> & string;
18
+ export declare const WaitlistCardContent: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
19
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
20
+ }, VariantProps>> & string;
21
+ export declare const WaitlistCardTitle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>, "style"> & {
22
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
23
+ }, VariantProps>> & string;
24
+ export declare const WaitlistForm: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>, "style"> & {
25
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
26
+ }, VariantProps>> & string;
27
+ export declare const WaitlistLowerContent: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
28
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
29
+ }, VariantProps>> & string;
30
+ export declare const WaitlistFieldGroup: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
31
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
32
+ }, VariantProps>> & string;
33
+ export declare const WaitlistInputMeasure: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
34
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
35
+ }, VariantProps>> & string;
36
+ export declare const WaitlistInput: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "style"> & {
37
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
38
+ }, WaitlistInputProps>> & string;
39
+ export declare const WaitlistSubmitButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "style"> & {
40
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
41
+ }, VariantProps>> & string;
42
+ export declare const WaitlistDisclaimer: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, "style"> & {
43
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
44
+ }> & string;
45
+ export declare const WaitlistCheckboxRow: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "style"> & {
46
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
47
+ }> & string;
48
+ export declare const WaitlistCheckbox: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "style"> & {
49
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
50
+ }> & string;
51
+ export declare const WaitlistCheckboxLabel: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "style"> & {
52
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
53
+ }> & string;
54
+ export declare const WaitlistStatusText: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>, "style"> & {
55
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
56
+ }, {
57
+ $tone: StatusTone;
58
+ }>> & string;
59
+ export declare const WaitlistSocialBlock: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Merged<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
60
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
61
+ }, VariantProps>> & string;
62
+ export declare const WaitlistSocialLinks: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
63
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
64
+ }> & string;
65
+ export declare const WaitlistSocialLink: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "style"> & {
66
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
67
+ }> & string;
68
+ export declare const WaitlistSocialIcon: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<import("react").DetailedHTMLProps<import("react").ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, "style"> & {
69
+ style?: import("react").CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
70
+ }> & string;
71
+ export {};