@flopay/ui 0.4.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/README.md +81 -0
- package/dist/annotations/index.cjs +223 -0
- package/dist/annotations/index.cjs.map +1 -0
- package/dist/annotations/index.d.cts +115 -0
- package/dist/annotations/index.d.ts +115 -0
- package/dist/annotations/index.mjs +190 -0
- package/dist/annotations/index.mjs.map +1 -0
- package/dist/marketing/index.cjs +95 -12
- package/dist/marketing/index.cjs.map +1 -1
- package/dist/marketing/index.d.cts +45 -1
- package/dist/marketing/index.d.ts +45 -1
- package/dist/marketing/index.mjs +90 -9
- package/dist/marketing/index.mjs.map +1 -1
- package/package.json +10 -4
- package/styles/annotations.css +124 -0
- package/styles/components.css +6 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/marketing/index.ts","../../src/marketing/footer.tsx","../../src/cn.ts","../../src/marketing/link.tsx","../../src/marketing/nav.tsx"],"sourcesContent":["export type { FooterBrand, FooterColumn, FooterLink, FooterProps } from './footer';\nexport { Footer } from './footer';\nexport type { MarketingLinkProps } from './link';\nexport { MarketingLink } from './link';\nexport type { NavLink, NavLogo, NavProps } from './nav';\nexport { Nav } from './nav';\n","import Image, { type ImageProps } from 'next/image';\nimport type { ReactNode } from 'react';\nimport { cn } from '../cn';\nimport { MarketingLink } from './link';\n\nexport interface FooterLink {\n href: string;\n label: ReactNode;\n external?: boolean;\n}\n\nexport interface FooterColumn {\n title: ReactNode;\n links: FooterLink[];\n}\n\nexport interface FooterBrand {\n /** A URL string or a statically-imported image (e.g. `@flopay/ui/logo.png`). */\n src: ImageProps['src'];\n alt?: string;\n label?: ReactNode;\n href?: string;\n size?: number;\n mark?: boolean;\n tagline?: ReactNode;\n}\n\nexport interface FooterProps {\n brand: FooterBrand;\n columns?: FooterColumn[];\n legal?: FooterLink[];\n copyright?: ReactNode;\n className?: string;\n}\n\n/** Shared site footer for marketing surfaces (landing, demo). */\nexport function Footer({ brand, columns = [], legal = [], copyright, className }: FooterProps) {\n const size = brand.size ?? 20;\n const image = <Image src={brand.src} alt={brand.alt ?? ''} width={size} height={size} />;\n\n return (\n <footer className={cn('footer', className)}>\n <div className=\"footer-inner\">\n <div className=\"footer-brand\">\n <MarketingLink href={brand.href ?? '/'} className=\"nav-logo\">\n {brand.mark ? (\n <span className=\"nav-logo-mark\" style={{ width: size, height: size }}>\n {image}\n </span>\n ) : (\n image\n )}\n {brand.label}\n </MarketingLink>\n {brand.tagline ? <p>{brand.tagline}</p> : null}\n </div>\n {columns.map((column, index) => (\n <div className=\"footer-column\" key={index}>\n <h4>{column.title}</h4>\n <ul>\n {column.links.map((link) => (\n <li key={link.href}>\n <MarketingLink href={link.href} external={link.external}>\n {link.label}\n </MarketingLink>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n <div className=\"footer-bottom\">\n {copyright ? <p>{copyright}</p> : <span />}\n {legal.length > 0 ? (\n <div className=\"footer-legal\">\n {legal.map((link) => (\n <MarketingLink key={link.href} href={link.href} external={link.external}>\n {link.label}\n </MarketingLink>\n ))}\n </div>\n ) : null}\n </div>\n </footer>\n );\n}\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Merge class names, resolving conflicting Tailwind utilities (last wins).\n * Mirrors the helper used across the FloPay frontends so consumers can extend\n * any primitive's classes safely.\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import Link from 'next/link';\nimport type { ReactNode } from 'react';\n\nexport interface MarketingLinkProps {\n href: string;\n /** Force new-tab rendering. Defaults to true for absolute http(s) URLs. */\n external?: boolean;\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Picks the right element for a marketing link:\n * - internal route (\"/...\", \"#...\") → next/link\n * - protocol link (mailto:/tel:) → plain anchor\n * - absolute URL (or `external`) → new-tab anchor\n */\nexport function MarketingLink({ href, external, className, children }: MarketingLinkProps) {\n const isAbsolute = /^https?:\\/\\//.test(href) || href.startsWith('//');\n const isProtocol = !isAbsolute && /^[a-z][a-z0-9+.-]*:/i.test(href);\n const openExternally = external ?? isAbsolute;\n\n if (openExternally) {\n return (\n <a href={href} className={className} target=\"_blank\" rel=\"noopener noreferrer\">\n {children}\n </a>\n );\n }\n if (isProtocol) {\n return (\n <a href={href} className={className}>\n {children}\n </a>\n );\n }\n return (\n <Link href={href} className={className}>\n {children}\n </Link>\n );\n}\n","import Image, { type ImageProps } from 'next/image';\nimport type { ReactNode } from 'react';\nimport { cn } from '../cn';\nimport { MarketingLink } from './link';\n\nexport interface NavLink {\n href: string;\n label: ReactNode;\n external?: boolean;\n /** Render as the prominent call-to-action button. */\n cta?: boolean;\n}\n\nexport interface NavLogo {\n /** A URL string or a statically-imported image (e.g. `@flopay/ui/logo.png`). */\n src: ImageProps['src'];\n alt?: string;\n label?: ReactNode;\n href?: string;\n /** Logo image edge size in px (default 28). */\n size?: number;\n /** Wrap the image in the rounded brand mark. */\n mark?: boolean;\n}\n\nexport interface NavProps {\n logo: NavLogo;\n links?: NavLink[];\n /** Extra item appended to the link list (e.g. an interactive control). */\n children?: ReactNode;\n className?: string;\n}\n\n/** Shared fixed top navigation for marketing surfaces (landing, demo). */\nexport function Nav({ logo, links = [], children, className }: NavProps) {\n const size = logo.size ?? 28;\n const image = <Image src={logo.src} alt={logo.alt ?? ''} width={size} height={size} priority />;\n\n return (\n <nav className={cn('nav', className)}>\n <div className=\"nav-inner\">\n <MarketingLink href={logo.href ?? '/'} className=\"nav-logo\">\n {logo.mark ? (\n <span className=\"nav-logo-mark\" style={{ width: size, height: size }}>\n {image}\n </span>\n ) : (\n image\n )}\n {logo.label}\n </MarketingLink>\n <ul className=\"nav-links\">\n {links.map((link) => (\n <li key={link.href}>\n <MarketingLink\n href={link.href}\n external={link.external}\n className={link.cta ? 'nav-cta' : undefined}\n >\n {link.label}\n </MarketingLink>\n </li>\n ))}\n {children ? <li>{children}</li> : null}\n </ul>\n </div>\n </nav>\n );\n}\n"],"mappings":"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","names":["Link","import_jsx_runtime","Image","import_image","import_jsx_runtime","Image"]}
|
|
1
|
+
{"version":3,"sources":["../../src/marketing/index.ts","../../src/marketing/footer.tsx","../../src/cn.ts","../../src/marketing/link.tsx","../../src/marketing/flopay-footer.tsx","../../src/marketing/nav.tsx"],"sourcesContent":["export type {\n FlopayFooterContent,\n FlopayFooterOptions,\n FlopayFooterProps,\n} from './flopay-footer';\nexport { FlopayFooter, flopayFooterContent } from './flopay-footer';\nexport type { FooterBrand, FooterColumn, FooterLink, FooterProps } from './footer';\nexport { Footer } from './footer';\nexport type { MarketingLinkProps } from './link';\nexport { MarketingLink } from './link';\nexport type { NavLink, NavLogo, NavProps } from './nav';\nexport { Nav } from './nav';\n","import Image, { type ImageProps } from 'next/image';\nimport type { ReactNode } from 'react';\nimport { cn } from '../cn';\nimport { MarketingLink } from './link';\n\nexport interface FooterLink {\n href: string;\n label: ReactNode;\n external?: boolean;\n}\n\nexport interface FooterColumn {\n title: ReactNode;\n links: FooterLink[];\n}\n\nexport interface FooterBrand {\n /** A URL string or a statically-imported image (e.g. `@flopay/ui/logo.png`). */\n src: ImageProps['src'];\n alt?: string;\n label?: ReactNode;\n href?: string;\n size?: number;\n mark?: boolean;\n tagline?: ReactNode;\n}\n\nexport interface FooterProps {\n brand: FooterBrand;\n columns?: FooterColumn[];\n legal?: FooterLink[];\n copyright?: ReactNode;\n className?: string;\n}\n\n/** Shared site footer for marketing surfaces (landing, demo). */\nexport function Footer({ brand, columns = [], legal = [], copyright, className }: FooterProps) {\n const size = brand.size ?? 20;\n const image = <Image src={brand.src} alt={brand.alt ?? ''} width={size} height={size} />;\n\n return (\n <footer className={cn('footer', className)}>\n <div className=\"footer-inner\">\n <div className=\"footer-brand\">\n <MarketingLink href={brand.href ?? '/'} className=\"nav-logo\">\n {brand.mark ? (\n <span className=\"nav-logo-mark\" style={{ width: size, height: size }}>\n {image}\n </span>\n ) : (\n image\n )}\n {brand.label}\n </MarketingLink>\n {brand.tagline ? <p>{brand.tagline}</p> : null}\n </div>\n {columns.map((column, index) => (\n <div className=\"footer-column\" key={index}>\n <h4>{column.title}</h4>\n <ul>\n {/* Keyed by index: placeholder links legitimately share an href. */}\n {column.links.map((link, linkIndex) => (\n <li key={linkIndex}>\n <MarketingLink href={link.href} external={link.external}>\n {link.label}\n </MarketingLink>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n <div className=\"footer-bottom\">\n {copyright ? <p>{copyright}</p> : <span />}\n {legal.length > 0 ? (\n <div className=\"footer-legal\">\n {legal.map((link) => (\n <MarketingLink key={link.href} href={link.href} external={link.external}>\n {link.label}\n </MarketingLink>\n ))}\n </div>\n ) : null}\n </div>\n </footer>\n );\n}\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Merge class names, resolving conflicting Tailwind utilities (last wins).\n * Mirrors the helper used across the FloPay frontends so consumers can extend\n * any primitive's classes safely.\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import Link from 'next/link';\nimport type { ReactNode } from 'react';\n\nexport interface MarketingLinkProps {\n href: string;\n /** Force new-tab rendering. Defaults to true for absolute http(s) URLs. */\n external?: boolean;\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Picks the right element for a marketing link:\n * - internal route (\"/...\", \"#...\") → next/link\n * - protocol link (mailto:/tel:) → plain anchor\n * - absolute URL (or `external`) → new-tab anchor\n */\nexport function MarketingLink({ href, external, className, children }: MarketingLinkProps) {\n const isAbsolute = /^https?:\\/\\//.test(href) || href.startsWith('//');\n const isProtocol = !isAbsolute && /^[a-z][a-z0-9+.-]*:/i.test(href);\n const openExternally = external ?? isAbsolute;\n\n if (openExternally) {\n return (\n <a href={href} className={className} target=\"_blank\" rel=\"noopener noreferrer\">\n {children}\n </a>\n );\n }\n if (isProtocol) {\n return (\n <a href={href} className={className}>\n {children}\n </a>\n );\n }\n return (\n <Link href={href} className={className}>\n {children}\n </Link>\n );\n}\n","import type { ImageProps } from 'next/image';\nimport type { FooterBrand, FooterColumn, FooterLink } from './footer';\nimport { Footer } from './footer';\n\nexport interface FlopayFooterOptions {\n /**\n * Origin for marketing-site routes, e.g. `https://flopay.com`. Leave unset on\n * the marketing site itself so its own routes stay relative.\n */\n baseUrl?: string;\n /** Where \"Demo Playground\" points. Defaults to the hosted playground. */\n demoUrl?: string;\n /** Where \"Contact\" points. Defaults to `<baseUrl>/contact`. */\n contactUrl?: string;\n}\n\nexport interface FlopayFooterContent {\n tagline: string;\n columns: FooterColumn[];\n legal: FooterLink[];\n copyright: string;\n}\n\nconst TAGLINE = 'Payment Orchestration That Keeps Revenue Flowing';\nconst COMPANY = 'FloPay LLC';\nconst DOCS_URL = 'https://docs.flopay.com/docs';\nconst API_URL = 'https://api.flopay.com/docs';\nconst DEMO_URL = 'https://demo.flopay.com';\n\n/**\n * The FloPay footer sitemap — one source of truth so every portal shows the\n * same columns, labels and order.\n *\n * Products without a page yet point at the marketing home page (`#` when the\n * caller *is* the marketing site, where that would be a self-link).\n */\nexport function flopayFooterContent({\n baseUrl = '',\n demoUrl = DEMO_URL,\n contactUrl,\n}: FlopayFooterOptions = {}): FlopayFooterContent {\n const route = (path: string) => `${baseUrl}${path}`;\n const pending = baseUrl || '#';\n\n return {\n tagline: TAGLINE,\n columns: [\n {\n title: 'Product',\n links: [\n { href: route('/vault'), label: 'Card Vault' },\n { href: route('/chargeback-prevention'), label: 'Chargeback Prevention' },\n { href: pending, label: 'Agent-Assisted Commerce' },\n { href: pending, label: 'The Agent Vault' },\n { href: pending, label: 'Agentic Discovery Network' },\n { href: pending, label: 'Smart Agentic Orchestration' },\n ],\n },\n {\n title: 'Development',\n links: [\n { href: DOCS_URL, label: 'Documentation' },\n { href: pending, label: 'MCP Server' },\n { href: API_URL, label: 'API Reference' },\n { href: demoUrl, label: 'Demo Playground' },\n ],\n },\n {\n title: 'Company',\n links: [\n { href: route('/mission'), label: 'Mission' },\n { href: route('/values'), label: 'Values' },\n { href: route('/pricing'), label: 'Pricing' },\n { href: route('/blog'), label: 'Blog' },\n { href: contactUrl ?? route('/contact'), label: 'Contact' },\n ],\n },\n ],\n legal: [\n { href: route('/legal/privacy'), label: 'Privacy' },\n { href: route('/legal/terms'), label: 'Terms' },\n { href: route('/legal/cookies'), label: 'Cookies' },\n ],\n copyright: `© ${new Date().getFullYear()} ${COMPANY}. All rights reserved.`,\n };\n}\n\nexport interface FlopayFooterProps extends FlopayFooterOptions {\n /** The shared logo: `import logo from '@flopay/ui/logo.png'`. */\n logo: ImageProps['src'];\n /** Override parts of the default brand block (label, tagline, size, …). */\n brand?: Partial<Omit<FooterBrand, 'src'>>;\n className?: string;\n}\n\n/**\n * The FloPay footer, content included — drop it into any portal and the\n * sitemap, tagline and copyright come from this package.\n *\n * ```tsx\n * import logo from '@flopay/ui/logo.png';\n * <FlopayFooter logo={logo} /> // on flopay.com\n * <FlopayFooter logo={logo} baseUrl=\"https://flopay.com\" /> // anywhere else\n * ```\n */\nexport function FlopayFooter({ logo, brand, className, ...options }: FlopayFooterProps) {\n const { tagline, columns, legal, copyright } = flopayFooterContent(options);\n\n return (\n <Footer\n className={className}\n brand={{\n src: logo,\n alt: 'FloPay',\n label: 'FloPay',\n href: options.baseUrl || '/',\n size: 20,\n mark: true,\n tagline,\n ...brand,\n }}\n columns={columns}\n legal={legal}\n copyright={copyright}\n />\n );\n}\n","import Image, { type ImageProps } from 'next/image';\nimport type { ReactNode } from 'react';\nimport { cn } from '../cn';\nimport { MarketingLink } from './link';\n\nexport interface NavLink {\n href: string;\n label: ReactNode;\n external?: boolean;\n /** Render as the prominent call-to-action button. */\n cta?: boolean;\n}\n\nexport interface NavLogo {\n /** A URL string or a statically-imported image (e.g. `@flopay/ui/logo.png`). */\n src: ImageProps['src'];\n alt?: string;\n label?: ReactNode;\n href?: string;\n /** Logo image edge size in px (default 28). */\n size?: number;\n /** Wrap the image in the rounded brand mark. */\n mark?: boolean;\n}\n\nexport interface NavProps {\n logo: NavLogo;\n links?: NavLink[];\n /** Extra item appended to the link list (e.g. an interactive control). */\n children?: ReactNode;\n className?: string;\n}\n\n/** Shared fixed top navigation for marketing surfaces (landing, demo). */\nexport function Nav({ logo, links = [], children, className }: NavProps) {\n const size = logo.size ?? 28;\n const image = <Image src={logo.src} alt={logo.alt ?? ''} width={size} height={size} priority />;\n\n return (\n <nav className={cn('nav', className)}>\n <div className=\"nav-inner\">\n <MarketingLink href={logo.href ?? '/'} className=\"nav-logo\">\n {logo.mark ? (\n <span className=\"nav-logo-mark\" style={{ width: size, height: size }}>\n {image}\n </span>\n ) : (\n image\n )}\n {logo.label}\n </MarketingLink>\n <ul className=\"nav-links\">\n {/* Keyed by index: placeholder links legitimately share an href.\n `nav-link-item` is what the narrow-viewport rule hides, so the\n call to action survives on mobile while the rest collapse. */}\n {links.map((link, index) => (\n <li key={index} className={link.cta ? undefined : 'nav-link-item'}>\n <MarketingLink\n href={link.href}\n external={link.external}\n className={link.cta ? 'nav-cta' : undefined}\n >\n {link.label}\n </MarketingLink>\n </li>\n ))}\n {children ? <li>{children}</li> : null}\n </ul>\n </div>\n </nav>\n );\n}\n"],"mappings":"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","names":["Link","import_jsx_runtime","Image","import_jsx_runtime","import_image","import_jsx_runtime","Image"]}
|
|
@@ -31,6 +31,50 @@ interface FooterProps {
|
|
|
31
31
|
/** Shared site footer for marketing surfaces (landing, demo). */
|
|
32
32
|
declare function Footer({ brand, columns, legal, copyright, className }: FooterProps): react.JSX.Element;
|
|
33
33
|
|
|
34
|
+
interface FlopayFooterOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Origin for marketing-site routes, e.g. `https://flopay.com`. Leave unset on
|
|
37
|
+
* the marketing site itself so its own routes stay relative.
|
|
38
|
+
*/
|
|
39
|
+
baseUrl?: string;
|
|
40
|
+
/** Where "Demo Playground" points. Defaults to the hosted playground. */
|
|
41
|
+
demoUrl?: string;
|
|
42
|
+
/** Where "Contact" points. Defaults to `<baseUrl>/contact`. */
|
|
43
|
+
contactUrl?: string;
|
|
44
|
+
}
|
|
45
|
+
interface FlopayFooterContent {
|
|
46
|
+
tagline: string;
|
|
47
|
+
columns: FooterColumn[];
|
|
48
|
+
legal: FooterLink[];
|
|
49
|
+
copyright: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The FloPay footer sitemap — one source of truth so every portal shows the
|
|
53
|
+
* same columns, labels and order.
|
|
54
|
+
*
|
|
55
|
+
* Products without a page yet point at the marketing home page (`#` when the
|
|
56
|
+
* caller *is* the marketing site, where that would be a self-link).
|
|
57
|
+
*/
|
|
58
|
+
declare function flopayFooterContent({ baseUrl, demoUrl, contactUrl, }?: FlopayFooterOptions): FlopayFooterContent;
|
|
59
|
+
interface FlopayFooterProps extends FlopayFooterOptions {
|
|
60
|
+
/** The shared logo: `import logo from '@flopay/ui/logo.png'`. */
|
|
61
|
+
logo: ImageProps['src'];
|
|
62
|
+
/** Override parts of the default brand block (label, tagline, size, …). */
|
|
63
|
+
brand?: Partial<Omit<FooterBrand, 'src'>>;
|
|
64
|
+
className?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The FloPay footer, content included — drop it into any portal and the
|
|
68
|
+
* sitemap, tagline and copyright come from this package.
|
|
69
|
+
*
|
|
70
|
+
* ```tsx
|
|
71
|
+
* import logo from '@flopay/ui/logo.png';
|
|
72
|
+
* <FlopayFooter logo={logo} /> // on flopay.com
|
|
73
|
+
* <FlopayFooter logo={logo} baseUrl="https://flopay.com" /> // anywhere else
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
declare function FlopayFooter({ logo, brand, className, ...options }: FlopayFooterProps): react.JSX.Element;
|
|
77
|
+
|
|
34
78
|
interface MarketingLinkProps {
|
|
35
79
|
href: string;
|
|
36
80
|
/** Force new-tab rendering. Defaults to true for absolute http(s) URLs. */
|
|
@@ -74,4 +118,4 @@ interface NavProps {
|
|
|
74
118
|
/** Shared fixed top navigation for marketing surfaces (landing, demo). */
|
|
75
119
|
declare function Nav({ logo, links, children, className }: NavProps): react.JSX.Element;
|
|
76
120
|
|
|
77
|
-
export { Footer, type FooterBrand, type FooterColumn, type FooterLink, type FooterProps, MarketingLink, type MarketingLinkProps, Nav, type NavLink, type NavLogo, type NavProps };
|
|
121
|
+
export { FlopayFooter, type FlopayFooterContent, type FlopayFooterOptions, type FlopayFooterProps, Footer, type FooterBrand, type FooterColumn, type FooterLink, type FooterProps, MarketingLink, type MarketingLinkProps, Nav, type NavLink, type NavLogo, type NavProps, flopayFooterContent };
|
|
@@ -31,6 +31,50 @@ interface FooterProps {
|
|
|
31
31
|
/** Shared site footer for marketing surfaces (landing, demo). */
|
|
32
32
|
declare function Footer({ brand, columns, legal, copyright, className }: FooterProps): react.JSX.Element;
|
|
33
33
|
|
|
34
|
+
interface FlopayFooterOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Origin for marketing-site routes, e.g. `https://flopay.com`. Leave unset on
|
|
37
|
+
* the marketing site itself so its own routes stay relative.
|
|
38
|
+
*/
|
|
39
|
+
baseUrl?: string;
|
|
40
|
+
/** Where "Demo Playground" points. Defaults to the hosted playground. */
|
|
41
|
+
demoUrl?: string;
|
|
42
|
+
/** Where "Contact" points. Defaults to `<baseUrl>/contact`. */
|
|
43
|
+
contactUrl?: string;
|
|
44
|
+
}
|
|
45
|
+
interface FlopayFooterContent {
|
|
46
|
+
tagline: string;
|
|
47
|
+
columns: FooterColumn[];
|
|
48
|
+
legal: FooterLink[];
|
|
49
|
+
copyright: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The FloPay footer sitemap — one source of truth so every portal shows the
|
|
53
|
+
* same columns, labels and order.
|
|
54
|
+
*
|
|
55
|
+
* Products without a page yet point at the marketing home page (`#` when the
|
|
56
|
+
* caller *is* the marketing site, where that would be a self-link).
|
|
57
|
+
*/
|
|
58
|
+
declare function flopayFooterContent({ baseUrl, demoUrl, contactUrl, }?: FlopayFooterOptions): FlopayFooterContent;
|
|
59
|
+
interface FlopayFooterProps extends FlopayFooterOptions {
|
|
60
|
+
/** The shared logo: `import logo from '@flopay/ui/logo.png'`. */
|
|
61
|
+
logo: ImageProps['src'];
|
|
62
|
+
/** Override parts of the default brand block (label, tagline, size, …). */
|
|
63
|
+
brand?: Partial<Omit<FooterBrand, 'src'>>;
|
|
64
|
+
className?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The FloPay footer, content included — drop it into any portal and the
|
|
68
|
+
* sitemap, tagline and copyright come from this package.
|
|
69
|
+
*
|
|
70
|
+
* ```tsx
|
|
71
|
+
* import logo from '@flopay/ui/logo.png';
|
|
72
|
+
* <FlopayFooter logo={logo} /> // on flopay.com
|
|
73
|
+
* <FlopayFooter logo={logo} baseUrl="https://flopay.com" /> // anywhere else
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
declare function FlopayFooter({ logo, brand, className, ...options }: FlopayFooterProps): react.JSX.Element;
|
|
77
|
+
|
|
34
78
|
interface MarketingLinkProps {
|
|
35
79
|
href: string;
|
|
36
80
|
/** Force new-tab rendering. Defaults to true for absolute http(s) URLs. */
|
|
@@ -74,4 +118,4 @@ interface NavProps {
|
|
|
74
118
|
/** Shared fixed top navigation for marketing surfaces (landing, demo). */
|
|
75
119
|
declare function Nav({ logo, links, children, className }: NavProps): react.JSX.Element;
|
|
76
120
|
|
|
77
|
-
export { Footer, type FooterBrand, type FooterColumn, type FooterLink, type FooterProps, MarketingLink, type MarketingLinkProps, Nav, type NavLink, type NavLogo, type NavProps };
|
|
121
|
+
export { FlopayFooter, type FlopayFooterContent, type FlopayFooterOptions, type FlopayFooterProps, Footer, type FooterBrand, type FooterColumn, type FooterLink, type FooterProps, MarketingLink, type MarketingLinkProps, Nav, type NavLink, type NavLogo, type NavProps, flopayFooterContent };
|
package/dist/marketing/index.mjs
CHANGED
|
@@ -37,7 +37,7 @@ function Footer({ brand, columns = [], legal = [], copyright, className }) {
|
|
|
37
37
|
] }),
|
|
38
38
|
columns.map((column, index) => /* @__PURE__ */ jsxs("div", { className: "footer-column", children: [
|
|
39
39
|
/* @__PURE__ */ jsx2("h4", { children: column.title }),
|
|
40
|
-
/* @__PURE__ */ jsx2("ul", { children: column.links.map((link) => /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsx2(MarketingLink, { href: link.href, external: link.external, children: link.label }) },
|
|
40
|
+
/* @__PURE__ */ jsx2("ul", { children: column.links.map((link, linkIndex) => /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsx2(MarketingLink, { href: link.href, external: link.external, children: link.label }) }, linkIndex)) })
|
|
41
41
|
] }, index))
|
|
42
42
|
] }),
|
|
43
43
|
/* @__PURE__ */ jsxs("div", { className: "footer-bottom", children: [
|
|
@@ -47,19 +47,98 @@ function Footer({ brand, columns = [], legal = [], copyright, className }) {
|
|
|
47
47
|
] });
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
// src/marketing/flopay-footer.tsx
|
|
51
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
52
|
+
var TAGLINE = "Payment Orchestration That Keeps Revenue Flowing";
|
|
53
|
+
var COMPANY = "FloPay LLC";
|
|
54
|
+
var DOCS_URL = "https://docs.flopay.com/docs";
|
|
55
|
+
var API_URL = "https://api.flopay.com/docs";
|
|
56
|
+
var DEMO_URL = "https://demo.flopay.com";
|
|
57
|
+
function flopayFooterContent({
|
|
58
|
+
baseUrl = "",
|
|
59
|
+
demoUrl = DEMO_URL,
|
|
60
|
+
contactUrl
|
|
61
|
+
} = {}) {
|
|
62
|
+
const route = (path) => `${baseUrl}${path}`;
|
|
63
|
+
const pending = baseUrl || "#";
|
|
64
|
+
return {
|
|
65
|
+
tagline: TAGLINE,
|
|
66
|
+
columns: [
|
|
67
|
+
{
|
|
68
|
+
title: "Product",
|
|
69
|
+
links: [
|
|
70
|
+
{ href: route("/vault"), label: "Card Vault" },
|
|
71
|
+
{ href: route("/chargeback-prevention"), label: "Chargeback Prevention" },
|
|
72
|
+
{ href: pending, label: "Agent-Assisted Commerce" },
|
|
73
|
+
{ href: pending, label: "The Agent Vault" },
|
|
74
|
+
{ href: pending, label: "Agentic Discovery Network" },
|
|
75
|
+
{ href: pending, label: "Smart Agentic Orchestration" }
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
title: "Development",
|
|
80
|
+
links: [
|
|
81
|
+
{ href: DOCS_URL, label: "Documentation" },
|
|
82
|
+
{ href: pending, label: "MCP Server" },
|
|
83
|
+
{ href: API_URL, label: "API Reference" },
|
|
84
|
+
{ href: demoUrl, label: "Demo Playground" }
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
title: "Company",
|
|
89
|
+
links: [
|
|
90
|
+
{ href: route("/mission"), label: "Mission" },
|
|
91
|
+
{ href: route("/values"), label: "Values" },
|
|
92
|
+
{ href: route("/pricing"), label: "Pricing" },
|
|
93
|
+
{ href: route("/blog"), label: "Blog" },
|
|
94
|
+
{ href: contactUrl ?? route("/contact"), label: "Contact" }
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
legal: [
|
|
99
|
+
{ href: route("/legal/privacy"), label: "Privacy" },
|
|
100
|
+
{ href: route("/legal/terms"), label: "Terms" },
|
|
101
|
+
{ href: route("/legal/cookies"), label: "Cookies" }
|
|
102
|
+
],
|
|
103
|
+
copyright: `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${COMPANY}. All rights reserved.`
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function FlopayFooter({ logo, brand, className, ...options }) {
|
|
107
|
+
const { tagline, columns, legal, copyright } = flopayFooterContent(options);
|
|
108
|
+
return /* @__PURE__ */ jsx3(
|
|
109
|
+
Footer,
|
|
110
|
+
{
|
|
111
|
+
className,
|
|
112
|
+
brand: {
|
|
113
|
+
src: logo,
|
|
114
|
+
alt: "FloPay",
|
|
115
|
+
label: "FloPay",
|
|
116
|
+
href: options.baseUrl || "/",
|
|
117
|
+
size: 20,
|
|
118
|
+
mark: true,
|
|
119
|
+
tagline,
|
|
120
|
+
...brand
|
|
121
|
+
},
|
|
122
|
+
columns,
|
|
123
|
+
legal,
|
|
124
|
+
copyright
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
50
129
|
// src/marketing/nav.tsx
|
|
51
130
|
import Image2 from "next/image";
|
|
52
|
-
import { jsx as
|
|
131
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
53
132
|
function Nav({ logo, links = [], children, className }) {
|
|
54
133
|
const size = logo.size ?? 28;
|
|
55
|
-
const image = /* @__PURE__ */
|
|
56
|
-
return /* @__PURE__ */
|
|
134
|
+
const image = /* @__PURE__ */ jsx4(Image2, { src: logo.src, alt: logo.alt ?? "", width: size, height: size, priority: true });
|
|
135
|
+
return /* @__PURE__ */ jsx4("nav", { className: cn("nav", className), children: /* @__PURE__ */ jsxs2("div", { className: "nav-inner", children: [
|
|
57
136
|
/* @__PURE__ */ jsxs2(MarketingLink, { href: logo.href ?? "/", className: "nav-logo", children: [
|
|
58
|
-
logo.mark ? /* @__PURE__ */
|
|
137
|
+
logo.mark ? /* @__PURE__ */ jsx4("span", { className: "nav-logo-mark", style: { width: size, height: size }, children: image }) : image,
|
|
59
138
|
logo.label
|
|
60
139
|
] }),
|
|
61
140
|
/* @__PURE__ */ jsxs2("ul", { className: "nav-links", children: [
|
|
62
|
-
links.map((link) => /* @__PURE__ */
|
|
141
|
+
links.map((link, index) => /* @__PURE__ */ jsx4("li", { className: link.cta ? void 0 : "nav-link-item", children: /* @__PURE__ */ jsx4(
|
|
63
142
|
MarketingLink,
|
|
64
143
|
{
|
|
65
144
|
href: link.href,
|
|
@@ -67,14 +146,16 @@ function Nav({ logo, links = [], children, className }) {
|
|
|
67
146
|
className: link.cta ? "nav-cta" : void 0,
|
|
68
147
|
children: link.label
|
|
69
148
|
}
|
|
70
|
-
) },
|
|
71
|
-
children ? /* @__PURE__ */
|
|
149
|
+
) }, index)),
|
|
150
|
+
children ? /* @__PURE__ */ jsx4("li", { children }) : null
|
|
72
151
|
] })
|
|
73
152
|
] }) });
|
|
74
153
|
}
|
|
75
154
|
export {
|
|
155
|
+
FlopayFooter,
|
|
76
156
|
Footer,
|
|
77
157
|
MarketingLink,
|
|
78
|
-
Nav
|
|
158
|
+
Nav,
|
|
159
|
+
flopayFooterContent
|
|
79
160
|
};
|
|
80
161
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/marketing/footer.tsx","../../src/marketing/link.tsx","../../src/marketing/nav.tsx"],"sourcesContent":["import Image, { type ImageProps } from 'next/image';\nimport type { ReactNode } from 'react';\nimport { cn } from '../cn';\nimport { MarketingLink } from './link';\n\nexport interface FooterLink {\n href: string;\n label: ReactNode;\n external?: boolean;\n}\n\nexport interface FooterColumn {\n title: ReactNode;\n links: FooterLink[];\n}\n\nexport interface FooterBrand {\n /** A URL string or a statically-imported image (e.g. `@flopay/ui/logo.png`). */\n src: ImageProps['src'];\n alt?: string;\n label?: ReactNode;\n href?: string;\n size?: number;\n mark?: boolean;\n tagline?: ReactNode;\n}\n\nexport interface FooterProps {\n brand: FooterBrand;\n columns?: FooterColumn[];\n legal?: FooterLink[];\n copyright?: ReactNode;\n className?: string;\n}\n\n/** Shared site footer for marketing surfaces (landing, demo). */\nexport function Footer({ brand, columns = [], legal = [], copyright, className }: FooterProps) {\n const size = brand.size ?? 20;\n const image = <Image src={brand.src} alt={brand.alt ?? ''} width={size} height={size} />;\n\n return (\n <footer className={cn('footer', className)}>\n <div className=\"footer-inner\">\n <div className=\"footer-brand\">\n <MarketingLink href={brand.href ?? '/'} className=\"nav-logo\">\n {brand.mark ? (\n <span className=\"nav-logo-mark\" style={{ width: size, height: size }}>\n {image}\n </span>\n ) : (\n image\n )}\n {brand.label}\n </MarketingLink>\n {brand.tagline ? <p>{brand.tagline}</p> : null}\n </div>\n {columns.map((column, index) => (\n <div className=\"footer-column\" key={index}>\n <h4>{column.title}</h4>\n <ul>\n {column.links.map((link) => (\n <li key={link.href}>\n <MarketingLink href={link.href} external={link.external}>\n {link.label}\n </MarketingLink>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n <div className=\"footer-bottom\">\n {copyright ? <p>{copyright}</p> : <span />}\n {legal.length > 0 ? (\n <div className=\"footer-legal\">\n {legal.map((link) => (\n <MarketingLink key={link.href} href={link.href} external={link.external}>\n {link.label}\n </MarketingLink>\n ))}\n </div>\n ) : null}\n </div>\n </footer>\n );\n}\n","import Link from 'next/link';\nimport type { ReactNode } from 'react';\n\nexport interface MarketingLinkProps {\n href: string;\n /** Force new-tab rendering. Defaults to true for absolute http(s) URLs. */\n external?: boolean;\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Picks the right element for a marketing link:\n * - internal route (\"/...\", \"#...\") → next/link\n * - protocol link (mailto:/tel:) → plain anchor\n * - absolute URL (or `external`) → new-tab anchor\n */\nexport function MarketingLink({ href, external, className, children }: MarketingLinkProps) {\n const isAbsolute = /^https?:\\/\\//.test(href) || href.startsWith('//');\n const isProtocol = !isAbsolute && /^[a-z][a-z0-9+.-]*:/i.test(href);\n const openExternally = external ?? isAbsolute;\n\n if (openExternally) {\n return (\n <a href={href} className={className} target=\"_blank\" rel=\"noopener noreferrer\">\n {children}\n </a>\n );\n }\n if (isProtocol) {\n return (\n <a href={href} className={className}>\n {children}\n </a>\n );\n }\n return (\n <Link href={href} className={className}>\n {children}\n </Link>\n );\n}\n","import Image, { type ImageProps } from 'next/image';\nimport type { ReactNode } from 'react';\nimport { cn } from '../cn';\nimport { MarketingLink } from './link';\n\nexport interface NavLink {\n href: string;\n label: ReactNode;\n external?: boolean;\n /** Render as the prominent call-to-action button. */\n cta?: boolean;\n}\n\nexport interface NavLogo {\n /** A URL string or a statically-imported image (e.g. `@flopay/ui/logo.png`). */\n src: ImageProps['src'];\n alt?: string;\n label?: ReactNode;\n href?: string;\n /** Logo image edge size in px (default 28). */\n size?: number;\n /** Wrap the image in the rounded brand mark. */\n mark?: boolean;\n}\n\nexport interface NavProps {\n logo: NavLogo;\n links?: NavLink[];\n /** Extra item appended to the link list (e.g. an interactive control). */\n children?: ReactNode;\n className?: string;\n}\n\n/** Shared fixed top navigation for marketing surfaces (landing, demo). */\nexport function Nav({ logo, links = [], children, className }: NavProps) {\n const size = logo.size ?? 28;\n const image = <Image src={logo.src} alt={logo.alt ?? ''} width={size} height={size} priority />;\n\n return (\n <nav className={cn('nav', className)}>\n <div className=\"nav-inner\">\n <MarketingLink href={logo.href ?? '/'} className=\"nav-logo\">\n {logo.mark ? (\n <span className=\"nav-logo-mark\" style={{ width: size, height: size }}>\n {image}\n </span>\n ) : (\n image\n )}\n {logo.label}\n </MarketingLink>\n <ul className=\"nav-links\">\n {links.map((link) => (\n <li key={link.href}>\n <MarketingLink\n href={link.href}\n external={link.external}\n className={link.cta ? 'nav-cta' : undefined}\n >\n {link.label}\n </MarketingLink>\n </li>\n ))}\n {children ? <li>{children}</li> : null}\n </ul>\n </div>\n </nav>\n );\n}\n"],"mappings":"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","names":["jsx","Image","jsx","jsxs","Image"]}
|
|
1
|
+
{"version":3,"sources":["../../src/marketing/footer.tsx","../../src/marketing/link.tsx","../../src/marketing/flopay-footer.tsx","../../src/marketing/nav.tsx"],"sourcesContent":["import Image, { type ImageProps } from 'next/image';\nimport type { ReactNode } from 'react';\nimport { cn } from '../cn';\nimport { MarketingLink } from './link';\n\nexport interface FooterLink {\n href: string;\n label: ReactNode;\n external?: boolean;\n}\n\nexport interface FooterColumn {\n title: ReactNode;\n links: FooterLink[];\n}\n\nexport interface FooterBrand {\n /** A URL string or a statically-imported image (e.g. `@flopay/ui/logo.png`). */\n src: ImageProps['src'];\n alt?: string;\n label?: ReactNode;\n href?: string;\n size?: number;\n mark?: boolean;\n tagline?: ReactNode;\n}\n\nexport interface FooterProps {\n brand: FooterBrand;\n columns?: FooterColumn[];\n legal?: FooterLink[];\n copyright?: ReactNode;\n className?: string;\n}\n\n/** Shared site footer for marketing surfaces (landing, demo). */\nexport function Footer({ brand, columns = [], legal = [], copyright, className }: FooterProps) {\n const size = brand.size ?? 20;\n const image = <Image src={brand.src} alt={brand.alt ?? ''} width={size} height={size} />;\n\n return (\n <footer className={cn('footer', className)}>\n <div className=\"footer-inner\">\n <div className=\"footer-brand\">\n <MarketingLink href={brand.href ?? '/'} className=\"nav-logo\">\n {brand.mark ? (\n <span className=\"nav-logo-mark\" style={{ width: size, height: size }}>\n {image}\n </span>\n ) : (\n image\n )}\n {brand.label}\n </MarketingLink>\n {brand.tagline ? <p>{brand.tagline}</p> : null}\n </div>\n {columns.map((column, index) => (\n <div className=\"footer-column\" key={index}>\n <h4>{column.title}</h4>\n <ul>\n {/* Keyed by index: placeholder links legitimately share an href. */}\n {column.links.map((link, linkIndex) => (\n <li key={linkIndex}>\n <MarketingLink href={link.href} external={link.external}>\n {link.label}\n </MarketingLink>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n <div className=\"footer-bottom\">\n {copyright ? <p>{copyright}</p> : <span />}\n {legal.length > 0 ? (\n <div className=\"footer-legal\">\n {legal.map((link) => (\n <MarketingLink key={link.href} href={link.href} external={link.external}>\n {link.label}\n </MarketingLink>\n ))}\n </div>\n ) : null}\n </div>\n </footer>\n );\n}\n","import Link from 'next/link';\nimport type { ReactNode } from 'react';\n\nexport interface MarketingLinkProps {\n href: string;\n /** Force new-tab rendering. Defaults to true for absolute http(s) URLs. */\n external?: boolean;\n className?: string;\n children: ReactNode;\n}\n\n/**\n * Picks the right element for a marketing link:\n * - internal route (\"/...\", \"#...\") → next/link\n * - protocol link (mailto:/tel:) → plain anchor\n * - absolute URL (or `external`) → new-tab anchor\n */\nexport function MarketingLink({ href, external, className, children }: MarketingLinkProps) {\n const isAbsolute = /^https?:\\/\\//.test(href) || href.startsWith('//');\n const isProtocol = !isAbsolute && /^[a-z][a-z0-9+.-]*:/i.test(href);\n const openExternally = external ?? isAbsolute;\n\n if (openExternally) {\n return (\n <a href={href} className={className} target=\"_blank\" rel=\"noopener noreferrer\">\n {children}\n </a>\n );\n }\n if (isProtocol) {\n return (\n <a href={href} className={className}>\n {children}\n </a>\n );\n }\n return (\n <Link href={href} className={className}>\n {children}\n </Link>\n );\n}\n","import type { ImageProps } from 'next/image';\nimport type { FooterBrand, FooterColumn, FooterLink } from './footer';\nimport { Footer } from './footer';\n\nexport interface FlopayFooterOptions {\n /**\n * Origin for marketing-site routes, e.g. `https://flopay.com`. Leave unset on\n * the marketing site itself so its own routes stay relative.\n */\n baseUrl?: string;\n /** Where \"Demo Playground\" points. Defaults to the hosted playground. */\n demoUrl?: string;\n /** Where \"Contact\" points. Defaults to `<baseUrl>/contact`. */\n contactUrl?: string;\n}\n\nexport interface FlopayFooterContent {\n tagline: string;\n columns: FooterColumn[];\n legal: FooterLink[];\n copyright: string;\n}\n\nconst TAGLINE = 'Payment Orchestration That Keeps Revenue Flowing';\nconst COMPANY = 'FloPay LLC';\nconst DOCS_URL = 'https://docs.flopay.com/docs';\nconst API_URL = 'https://api.flopay.com/docs';\nconst DEMO_URL = 'https://demo.flopay.com';\n\n/**\n * The FloPay footer sitemap — one source of truth so every portal shows the\n * same columns, labels and order.\n *\n * Products without a page yet point at the marketing home page (`#` when the\n * caller *is* the marketing site, where that would be a self-link).\n */\nexport function flopayFooterContent({\n baseUrl = '',\n demoUrl = DEMO_URL,\n contactUrl,\n}: FlopayFooterOptions = {}): FlopayFooterContent {\n const route = (path: string) => `${baseUrl}${path}`;\n const pending = baseUrl || '#';\n\n return {\n tagline: TAGLINE,\n columns: [\n {\n title: 'Product',\n links: [\n { href: route('/vault'), label: 'Card Vault' },\n { href: route('/chargeback-prevention'), label: 'Chargeback Prevention' },\n { href: pending, label: 'Agent-Assisted Commerce' },\n { href: pending, label: 'The Agent Vault' },\n { href: pending, label: 'Agentic Discovery Network' },\n { href: pending, label: 'Smart Agentic Orchestration' },\n ],\n },\n {\n title: 'Development',\n links: [\n { href: DOCS_URL, label: 'Documentation' },\n { href: pending, label: 'MCP Server' },\n { href: API_URL, label: 'API Reference' },\n { href: demoUrl, label: 'Demo Playground' },\n ],\n },\n {\n title: 'Company',\n links: [\n { href: route('/mission'), label: 'Mission' },\n { href: route('/values'), label: 'Values' },\n { href: route('/pricing'), label: 'Pricing' },\n { href: route('/blog'), label: 'Blog' },\n { href: contactUrl ?? route('/contact'), label: 'Contact' },\n ],\n },\n ],\n legal: [\n { href: route('/legal/privacy'), label: 'Privacy' },\n { href: route('/legal/terms'), label: 'Terms' },\n { href: route('/legal/cookies'), label: 'Cookies' },\n ],\n copyright: `© ${new Date().getFullYear()} ${COMPANY}. All rights reserved.`,\n };\n}\n\nexport interface FlopayFooterProps extends FlopayFooterOptions {\n /** The shared logo: `import logo from '@flopay/ui/logo.png'`. */\n logo: ImageProps['src'];\n /** Override parts of the default brand block (label, tagline, size, …). */\n brand?: Partial<Omit<FooterBrand, 'src'>>;\n className?: string;\n}\n\n/**\n * The FloPay footer, content included — drop it into any portal and the\n * sitemap, tagline and copyright come from this package.\n *\n * ```tsx\n * import logo from '@flopay/ui/logo.png';\n * <FlopayFooter logo={logo} /> // on flopay.com\n * <FlopayFooter logo={logo} baseUrl=\"https://flopay.com\" /> // anywhere else\n * ```\n */\nexport function FlopayFooter({ logo, brand, className, ...options }: FlopayFooterProps) {\n const { tagline, columns, legal, copyright } = flopayFooterContent(options);\n\n return (\n <Footer\n className={className}\n brand={{\n src: logo,\n alt: 'FloPay',\n label: 'FloPay',\n href: options.baseUrl || '/',\n size: 20,\n mark: true,\n tagline,\n ...brand,\n }}\n columns={columns}\n legal={legal}\n copyright={copyright}\n />\n );\n}\n","import Image, { type ImageProps } from 'next/image';\nimport type { ReactNode } from 'react';\nimport { cn } from '../cn';\nimport { MarketingLink } from './link';\n\nexport interface NavLink {\n href: string;\n label: ReactNode;\n external?: boolean;\n /** Render as the prominent call-to-action button. */\n cta?: boolean;\n}\n\nexport interface NavLogo {\n /** A URL string or a statically-imported image (e.g. `@flopay/ui/logo.png`). */\n src: ImageProps['src'];\n alt?: string;\n label?: ReactNode;\n href?: string;\n /** Logo image edge size in px (default 28). */\n size?: number;\n /** Wrap the image in the rounded brand mark. */\n mark?: boolean;\n}\n\nexport interface NavProps {\n logo: NavLogo;\n links?: NavLink[];\n /** Extra item appended to the link list (e.g. an interactive control). */\n children?: ReactNode;\n className?: string;\n}\n\n/** Shared fixed top navigation for marketing surfaces (landing, demo). */\nexport function Nav({ logo, links = [], children, className }: NavProps) {\n const size = logo.size ?? 28;\n const image = <Image src={logo.src} alt={logo.alt ?? ''} width={size} height={size} priority />;\n\n return (\n <nav className={cn('nav', className)}>\n <div className=\"nav-inner\">\n <MarketingLink href={logo.href ?? '/'} className=\"nav-logo\">\n {logo.mark ? (\n <span className=\"nav-logo-mark\" style={{ width: size, height: size }}>\n {image}\n </span>\n ) : (\n image\n )}\n {logo.label}\n </MarketingLink>\n <ul className=\"nav-links\">\n {/* Keyed by index: placeholder links legitimately share an href.\n `nav-link-item` is what the narrow-viewport rule hides, so the\n call to action survives on mobile while the rest collapse. */}\n {links.map((link, index) => (\n <li key={index} className={link.cta ? undefined : 'nav-link-item'}>\n <MarketingLink\n href={link.href}\n external={link.external}\n className={link.cta ? 'nav-cta' : undefined}\n >\n {link.label}\n </MarketingLink>\n </li>\n ))}\n {children ? <li>{children}</li> : null}\n </ul>\n </div>\n </nav>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","Image","jsx","jsxs","Image"]}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flopay/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"packageManager": "pnpm@
|
|
5
|
+
"packageManager": "pnpm@11.17.0",
|
|
6
6
|
"description": "FloPay shared design system — design tokens, a Tailwind v4 preset, and React primitives shared across landing, demo, docs, and dashboard.",
|
|
7
7
|
"license": "UNLICENSED",
|
|
8
8
|
"publishConfig": {
|
|
@@ -27,12 +27,18 @@
|
|
|
27
27
|
"import": "./dist/marketing/index.mjs",
|
|
28
28
|
"require": "./dist/marketing/index.cjs"
|
|
29
29
|
},
|
|
30
|
+
"./annotations": {
|
|
31
|
+
"types": "./dist/annotations/index.d.ts",
|
|
32
|
+
"import": "./dist/annotations/index.mjs",
|
|
33
|
+
"require": "./dist/annotations/index.cjs"
|
|
34
|
+
},
|
|
30
35
|
"./styles": "./styles/index.css",
|
|
31
36
|
"./styles/index.css": "./styles/index.css",
|
|
32
37
|
"./styles/tokens.css": "./styles/tokens.css",
|
|
33
38
|
"./styles/reset.css": "./styles/reset.css",
|
|
34
39
|
"./styles/components.css": "./styles/components.css",
|
|
35
40
|
"./styles/preset.css": "./styles/preset.css",
|
|
41
|
+
"./styles/annotations.css": "./styles/annotations.css",
|
|
36
42
|
"./logo.png": "./assets/logo.png",
|
|
37
43
|
"./package.json": "./package.json"
|
|
38
44
|
},
|
|
@@ -68,10 +74,10 @@
|
|
|
68
74
|
"tailwind-merge": "^3.6.0"
|
|
69
75
|
},
|
|
70
76
|
"devDependencies": {
|
|
71
|
-
"@biomejs/biome": "^2.
|
|
77
|
+
"@biomejs/biome": "^2.5.3",
|
|
72
78
|
"@types/react": "^19.2.15",
|
|
73
79
|
"@types/react-dom": "^19.2.3",
|
|
74
|
-
"next": "^16.2.
|
|
80
|
+
"next": "^16.2.10",
|
|
75
81
|
"react": "^19.2.6",
|
|
76
82
|
"react-dom": "^19.2.6",
|
|
77
83
|
"tsup": "^8.3.0",
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/* @flopay/ui — hand-drawn annotation layer.
|
|
2
|
+
*
|
|
3
|
+
* Marker-style notes and arrows drawn over a UI, for guided demos and product
|
|
4
|
+
* tours. Opt-in, since the arrow geometry is a few KB that most pages don't
|
|
5
|
+
* need:
|
|
6
|
+
*
|
|
7
|
+
* @import "@flopay/ui/styles/annotations.css";
|
|
8
|
+
*
|
|
9
|
+
* Backs the components exported from `@flopay/ui/annotations`, and depends on
|
|
10
|
+
* tokens.css custom properties. */
|
|
11
|
+
|
|
12
|
+
:root {
|
|
13
|
+
/* Brand blue by default, in a handwriting face, so notes read as marker over
|
|
14
|
+
the UI rather than as part of it. Override either per app. */
|
|
15
|
+
--annotation-ink: var(--brand);
|
|
16
|
+
--annotation-font: 'Bradley Hand', 'Segoe Print', 'Chalkboard SE', 'Comic Sans MS', cursive;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.annotation-stage {
|
|
20
|
+
width: 100%;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* The positioning context for `pos`. Notes overhang it into the outer stage. */
|
|
24
|
+
.annotation-stage-inner {
|
|
25
|
+
position: relative;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* ── Narrow: the notes as a plain list under the content ── */
|
|
29
|
+
.annotation-layer {
|
|
30
|
+
display: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.annotation-list {
|
|
34
|
+
max-width: 420px;
|
|
35
|
+
margin: 18px auto 0;
|
|
36
|
+
padding-top: 14px;
|
|
37
|
+
border-top: 1px dashed var(--border-hover);
|
|
38
|
+
list-style: none;
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-direction: column;
|
|
41
|
+
gap: 7px;
|
|
42
|
+
font-family: var(--annotation-font);
|
|
43
|
+
font-size: 16px;
|
|
44
|
+
line-height: 1.45;
|
|
45
|
+
color: var(--annotation-ink);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.annotation-list li::before {
|
|
49
|
+
content: '→ ';
|
|
50
|
+
opacity: 0.7;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* ── Wide: notes float around the content ──
|
|
54
|
+
Notes overhang the stage into the surrounding margins, so what matters is
|
|
55
|
+
the room *around* the content — which belongs to an ancestor the package
|
|
56
|
+
doesn't own. A container query on the stage would measure the content box
|
|
57
|
+
instead and never match. Hence a viewport query.
|
|
58
|
+
1120px is where a ~720px content box has room for 200px notes either side.
|
|
59
|
+
An app in a constrained layout (a sidebar, a split view) should re-declare
|
|
60
|
+
this one block at its own breakpoint; a custom property can't be used in a
|
|
61
|
+
media condition. */
|
|
62
|
+
@media (min-width: 1120px) {
|
|
63
|
+
.annotation-layer {
|
|
64
|
+
display: block;
|
|
65
|
+
position: absolute;
|
|
66
|
+
inset: 0;
|
|
67
|
+
pointer-events: none;
|
|
68
|
+
/* Above the content so an arrow tip can cross onto its target rather than
|
|
69
|
+
stopping at the edge. */
|
|
70
|
+
z-index: 2;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.annotation-list {
|
|
74
|
+
display: none;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.annotation {
|
|
78
|
+
position: absolute;
|
|
79
|
+
width: 200px;
|
|
80
|
+
display: flex;
|
|
81
|
+
flex-direction: column;
|
|
82
|
+
gap: 1px;
|
|
83
|
+
transform: rotate(var(--annotation-tilt, 0deg));
|
|
84
|
+
font-family: var(--annotation-font);
|
|
85
|
+
font-size: 18px;
|
|
86
|
+
line-height: 1.3;
|
|
87
|
+
color: var(--annotation-ink);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Arrow above the text for upward variants, below it otherwise. */
|
|
91
|
+
.annotation[data-flip] {
|
|
92
|
+
flex-direction: column-reverse;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Text rags toward whatever the arrow points at. */
|
|
96
|
+
.annotation[data-side='right'] { text-align: right; }
|
|
97
|
+
.annotation[data-side='left'] { text-align: left; }
|
|
98
|
+
.annotation[data-side='center'] { text-align: center; }
|
|
99
|
+
|
|
100
|
+
/* `position: relative` on both halves is what lets `posText` / `posArrow`
|
|
101
|
+
nudge one without the other. Offsets shift them off the spot `pos` put
|
|
102
|
+
them, leaving the flex layout — and therefore each other — undisturbed. */
|
|
103
|
+
.annotation-text {
|
|
104
|
+
position: relative;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* `--annotation-arrow-rotate` re-aims the curve and the flips mirror it, so
|
|
108
|
+
one drawing covers several approach directions without a new curve. Those
|
|
109
|
+
are visual only — the layout box stays put, which is why a re-aimed arrow
|
|
110
|
+
overhangs it. Scale sits to the right of rotate so it applies first: you
|
|
111
|
+
pick the mirrored shape, then aim it. */
|
|
112
|
+
.annotation-arrow {
|
|
113
|
+
position: relative;
|
|
114
|
+
width: calc(160px * var(--annotation-arrow-scale, 1));
|
|
115
|
+
height: auto;
|
|
116
|
+
opacity: 0.9;
|
|
117
|
+
transform: rotate(var(--annotation-arrow-rotate, 0deg))
|
|
118
|
+
scale(var(--annotation-arrow-flip-x, 1), var(--annotation-arrow-flip-y, 1));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.annotation[data-side='right'] .annotation-arrow { align-self: flex-end; }
|
|
122
|
+
.annotation[data-side='left'] .annotation-arrow { align-self: flex-start; }
|
|
123
|
+
.annotation[data-side='center'] .annotation-arrow { align-self: center; }
|
|
124
|
+
}
|
package/styles/components.css
CHANGED
|
@@ -368,6 +368,12 @@
|
|
|
368
368
|
.nav-inner {
|
|
369
369
|
padding: 0 16px;
|
|
370
370
|
}
|
|
371
|
+
/* Collapse the nav to logo + call to action; `Nav` tags every non-CTA
|
|
372
|
+
item with `nav-link-item`. Apps that don't import this file (they keep
|
|
373
|
+
their own component CSS) can re-declare just this rule to opt in. */
|
|
374
|
+
.nav-links .nav-link-item {
|
|
375
|
+
display: none;
|
|
376
|
+
}
|
|
371
377
|
.section {
|
|
372
378
|
padding: 80px 16px;
|
|
373
379
|
}
|