@cronos-labs/ui 0.5.0 → 0.6.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/dist/FooterWaitlist/helper.d.ts +9 -2
- package/dist/FooterWaitlist/helper.js +21 -6
- package/dist/FooterWaitlist/index.d.ts +10 -1
- package/dist/FooterWaitlist/index.js +8 -9
- package/dist/FooterWaitlist/types.d.ts +21 -0
- package/dist/FooterWaitlist/types.js +1 -0
- package/dist/Header/index.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
import type { NavigationContent } from '../navigationContent.js';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
2
|
+
import type { FooterWaitlistContent } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Falls back to the bundled Cronos copy for a locale.
|
|
5
|
+
*
|
|
6
|
+
* The dictionary shipped with this package is a convenience for the Cronos
|
|
7
|
+
* properties, not a definition of what the component says — a differently
|
|
8
|
+
* branded site passes its own `content` instead and never reads this.
|
|
9
|
+
*/
|
|
10
|
+
export declare const resolveFooterWaitlistContent: (navContent: NavigationContent) => FooterWaitlistContent;
|
|
@@ -1,7 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Falls back to the bundled Cronos copy for a locale.
|
|
3
|
+
*
|
|
4
|
+
* The dictionary shipped with this package is a convenience for the Cronos
|
|
5
|
+
* properties, not a definition of what the component says — a differently
|
|
6
|
+
* branded site passes its own `content` instead and never reads this.
|
|
7
|
+
*/
|
|
8
|
+
export const resolveFooterWaitlistContent = (navContent) => ({
|
|
9
|
+
ctaTitle: navContent.footer.ctaTitle,
|
|
10
|
+
emailPlaceholder: navContent.footer.emailPlaceholder,
|
|
11
|
+
submitLabel: navContent.footer.submitLabel,
|
|
12
|
+
consentLabel: navContent.footer.consentLabel,
|
|
13
|
+
consentNote: navContent.footer.consentNote,
|
|
14
|
+
socialHeading: navContent.footer.socialHeading,
|
|
15
|
+
messages: {
|
|
16
|
+
successMessage: navContent.footer.waitlistForm.successMessage,
|
|
17
|
+
emptyEmailMessage: navContent.footer.waitlistForm.emptyEmailMessage,
|
|
18
|
+
invalidEmailMessage: navContent.footer.waitlistForm.invalidEmailMessage,
|
|
19
|
+
errorMessage: navContent.footer.waitlistForm.errorMessage,
|
|
20
|
+
submittingLabel: navContent.footer.waitlistForm.submittingLabel,
|
|
21
|
+
},
|
|
7
22
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import type { WaitlistRequest, WaitlistSource } from '../waitlist/types.js';
|
|
3
|
+
import type { FooterWaitlistContent } from './types.js';
|
|
3
4
|
import { type FooterWaitlistVariant } from './styles.js';
|
|
4
5
|
export interface FooterWaitlistProps {
|
|
5
6
|
/** Identifies which form on the site was submitted. */
|
|
@@ -14,6 +15,14 @@ export interface FooterWaitlistProps {
|
|
|
14
15
|
onWaitlistError?: ((message: string) => void) | undefined;
|
|
15
16
|
/** Fires when submit is pressed, before validation. For analytics. */
|
|
16
17
|
onSubmitClick?: (() => void) | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Every string this renders, already localized.
|
|
20
|
+
*
|
|
21
|
+
* Omit it and the component falls back to the Cronos copy bundled with this
|
|
22
|
+
* package for the active locale. Any site that is not Cronos should pass its
|
|
23
|
+
* own — the bundled dictionary is a convenience, not the component's voice.
|
|
24
|
+
*/
|
|
25
|
+
content?: FooterWaitlistContent | undefined;
|
|
17
26
|
}
|
|
18
27
|
/**
|
|
19
28
|
* Email capture card with the site's social row beneath it.
|
|
@@ -21,4 +30,4 @@ export interface FooterWaitlistProps {
|
|
|
21
30
|
* Wordmark and social links come from `<BrandProvider>`, so two sites render
|
|
22
31
|
* this identically while showing entirely different artwork and destinations.
|
|
23
32
|
*/
|
|
24
|
-
export declare function FooterWaitlist({ source, submit, attributionKey, variant, legalMeta, onWaitlistSuccess, onWaitlistError, onSubmitClick, }: FooterWaitlistProps): React.JSX.Element;
|
|
33
|
+
export declare function FooterWaitlist({ source, submit, attributionKey, variant, legalMeta, onWaitlistSuccess, onWaitlistError, onSubmitClick, content, }: FooterWaitlistProps): React.JSX.Element;
|
|
@@ -5,7 +5,7 @@ import { navigationContent } from '../navigationContent.js';
|
|
|
5
5
|
import { useCurrentLocale } from '../locale/hooks.js';
|
|
6
6
|
import { resetAutocompleteFillMarkersAfterInput } from '../waitlist/autocompleteFillMarkers.js';
|
|
7
7
|
import { useWaitlistForm } from '../waitlist/useWaitlistForm.js';
|
|
8
|
-
import {
|
|
8
|
+
import { resolveFooterWaitlistContent } from './helper.js';
|
|
9
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
10
|
// Below this the address is unreadable; the field scrolls instead of shrinking further.
|
|
11
11
|
const minWaitlistInputScale = 0.5;
|
|
@@ -15,18 +15,17 @@ const minWaitlistInputScale = 0.5;
|
|
|
15
15
|
* Wordmark and social links come from `<BrandProvider>`, so two sites render
|
|
16
16
|
* this identically while showing entirely different artwork and destinations.
|
|
17
17
|
*/
|
|
18
|
-
export function FooterWaitlist({ source, submit, attributionKey, variant = 'footer', legalMeta, onWaitlistSuccess, onWaitlistError, onSubmitClick, }) {
|
|
18
|
+
export function FooterWaitlist({ source, submit, attributionKey, variant = 'footer', legalMeta, onWaitlistSuccess, onWaitlistError, onSubmitClick, content, }) {
|
|
19
19
|
const locale = useCurrentLocale();
|
|
20
20
|
const brand = useBrand();
|
|
21
|
-
const
|
|
22
|
-
const waitlistContent = resolveWaitlistFormContent(navContent);
|
|
21
|
+
const copy = content ?? resolveFooterWaitlistContent(navigationContent[locale]);
|
|
23
22
|
const inputRef = useRef(null);
|
|
24
23
|
const inputMeasureRef = useRef(null);
|
|
25
24
|
const [waitlistInputScale, setWaitlistInputScale] = useState(1);
|
|
26
25
|
const waitlistMessages = {
|
|
27
|
-
...
|
|
28
|
-
emailPlaceholder:
|
|
29
|
-
submitLabel:
|
|
26
|
+
...copy.messages,
|
|
27
|
+
emailPlaceholder: copy.emailPlaceholder,
|
|
28
|
+
submitLabel: copy.submitLabel,
|
|
30
29
|
};
|
|
31
30
|
const waitlistOptions = {
|
|
32
31
|
source,
|
|
@@ -80,7 +79,7 @@ export function FooterWaitlist({ source, submit, attributionKey, variant = 'foot
|
|
|
80
79
|
window.removeEventListener('resize', updateWaitlistInputScale);
|
|
81
80
|
};
|
|
82
81
|
}, [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:
|
|
82
|
+
return (_jsx(WaitlistSectionShell, { "$variant": variant, children: _jsx(WaitlistContainer, { "$variant": variant, children: _jsx(WaitlistCard, { children: _jsxs(WaitlistCardContent, { "$variant": variant, children: [_jsx(WaitlistCardTitle, { "$variant": variant, children: copy.ctaTitle }), _jsxs(WaitlistForm, { "$variant": variant, noValidate: true, onSubmit: (event) => {
|
|
84
83
|
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:
|
|
84
|
+
}, 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: copy.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: copy.consentLabel })] }), brand.socialLinks.length > 0 ? (_jsx(WaitlistSocialBlock, { "$variant": variant, "aria-label": copy.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", loading: "lazy" }) }, socialLink.key))) }) })) : null, legalMeta] })] }) }) }) }));
|
|
86
85
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { WaitlistFormMessages } from '../waitlist/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Every string `FooterWaitlist` renders.
|
|
4
|
+
*
|
|
5
|
+
* Supplied per site so the component carries no brand's wording. Localize
|
|
6
|
+
* before passing it in — this package does not translate.
|
|
7
|
+
*/
|
|
8
|
+
export interface FooterWaitlistContent {
|
|
9
|
+
/** Heading above the form. */
|
|
10
|
+
ctaTitle: string;
|
|
11
|
+
emailPlaceholder: string;
|
|
12
|
+
submitLabel: string;
|
|
13
|
+
/** Label beside the marketing-consent checkbox. */
|
|
14
|
+
consentLabel: string;
|
|
15
|
+
/** Fine print under the form, e.g. a privacy-notice acknowledgement. */
|
|
16
|
+
consentNote: string;
|
|
17
|
+
/** Accessible name for the social-links group. */
|
|
18
|
+
socialHeading: string;
|
|
19
|
+
/** Validation and submission feedback. */
|
|
20
|
+
messages: WaitlistFormMessages;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/Header/index.js
CHANGED
|
@@ -94,7 +94,7 @@ export function Header({ brandWordmarkSrc, content, forceDocumentNavigation = fa
|
|
|
94
94
|
setIsMobileMenuOpen(false);
|
|
95
95
|
waitlistCta?.onClick?.(event, ctaLocation);
|
|
96
96
|
};
|
|
97
|
-
return (_jsxs(HeaderFrame, { "data-header-frame": "true", "$shouldAnimatePresentation": shouldAnimatePresentation, "$backgroundColor": presentation.backgroundColor, "$mobileBackgroundColor": mobilePresentation?.backgroundColor, "$contrast": presentation.contrast, children: [_jsxs(HeaderShell, { "$shouldAnimatePresentation": shouldAnimatePresentation, "$textColor": presentation.textColor, "$mobileTextColor": mobilePresentation?.textColor, children: [_jsx(HeaderBrandLink, { href: forceDocumentNavigation ? canonicalizeDocumentHref(homeHref) : homeHref, "aria-label":
|
|
97
|
+
return (_jsxs(HeaderFrame, { "data-header-frame": "true", "$shouldAnimatePresentation": shouldAnimatePresentation, "$backgroundColor": presentation.backgroundColor, "$mobileBackgroundColor": mobilePresentation?.backgroundColor, "$contrast": presentation.contrast, children: [_jsxs(HeaderShell, { "$shouldAnimatePresentation": shouldAnimatePresentation, "$textColor": presentation.textColor, "$mobileTextColor": mobilePresentation?.textColor, children: [_jsx(HeaderBrandLink, { href: forceDocumentNavigation ? canonicalizeDocumentHref(homeHref) : homeHref, "aria-label": brandName ? `${brandName} home` : 'Home', onClick: forceDocumentNavigation
|
|
98
98
|
? undefined
|
|
99
99
|
: (event) => handleInternalNavigation(event, homeHref), children: presentation.contrast ? (_jsx(BrandWordmarkMask, { "$url": wordmarkSrc, role: "img", "aria-label": brandName })) : (_jsx(Wordmark, { "$shouldAnimatePresentation": shouldAnimatePresentation, "$variant": presentation.variant, "$mobileVariant": mobilePresentation?.variant, src: wordmarkSrc, alt: brandName })) }), _jsx(Nav, { "$variant": presentation.variant, "$contrast": presentation.contrast, "aria-label": "Global navigation", children: enabledNavItems.map((item) => {
|
|
100
100
|
const label = item.label;
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export { isOneTrustEventTarget, openCookiePreferences } from './onetrust.js';
|
|
|
25
25
|
export { BrandProvider, useBrand, useOptionalBrand } from './brand/index.js';
|
|
26
26
|
export type { BrandAssets, BrandSocialLink } from './brand/index.js';
|
|
27
27
|
export { FooterWaitlist, type FooterWaitlistProps } from './FooterWaitlist/index.js';
|
|
28
|
+
export type { FooterWaitlistContent } from './FooterWaitlist/types.js';
|
|
29
|
+
export { resolveFooterWaitlistContent } from './FooterWaitlist/helper.js';
|
|
28
30
|
export { useWaitlistForm } from './waitlist/useWaitlistForm.js';
|
|
29
31
|
export type { UseWaitlistFormOptions, WaitlistStatusTone } from './waitlist/useWaitlistForm.js';
|
|
30
32
|
export type { WaitlistRequest, WaitlistResponse, WaitlistSource, WaitlistFormMessages, } from './waitlist/types.js';
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ export { fetchJson, HttpError } from './fetch.js';
|
|
|
21
21
|
export { isOneTrustEventTarget, openCookiePreferences } from './onetrust.js';
|
|
22
22
|
export { BrandProvider, useBrand, useOptionalBrand } from './brand/index.js';
|
|
23
23
|
export { FooterWaitlist } from './FooterWaitlist/index.js';
|
|
24
|
+
export { resolveFooterWaitlistContent } from './FooterWaitlist/helper.js';
|
|
24
25
|
export { useWaitlistForm } from './waitlist/useWaitlistForm.js';
|
|
25
26
|
export { resetAutocompleteFillMarkersAfterInput } from './waitlist/autocompleteFillMarkers.js';
|
|
26
27
|
export { clearWaitlistAttribution, getWaitlistBrowserContext } from './waitlist/attribution.js';
|