@flopay/ui 0.1.0 → 0.2.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 CHANGED
@@ -103,7 +103,8 @@ After that, releases are automatic:
103
103
  1. Bump `version` in `package.json` on `main`.
104
104
  2. `CI` runs (`.github/workflows/ci.yml`).
105
105
  3. On CI success, `Publish Package` (`.github/workflows/publish.yml`) sees the
106
- new version has no `v<version>` tag, `npm publish`es via OIDC (with
107
- provenance), then pushes the tag.
106
+ new version has no `v<version>` tag, `npm publish`es via OIDC, then pushes
107
+ the tag. (No npm provenance: this repo is private, and provenance attestation
108
+ requires a public source repo.)
108
109
 
109
110
  CSS files ship raw (no build step); only the JS/types are bundled by tsup.
@@ -0,0 +1,11 @@
1
+ // src/cn.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ export {
9
+ cn
10
+ };
11
+ //# sourceMappingURL=chunk-XF3CK37X.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cn.ts"],"sourcesContent":["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"],"mappings":";AAAA,SAA0B,YAAY;AACtC,SAAS,eAAe;AAOjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;","names":[]}
package/dist/index.mjs CHANGED
@@ -1,9 +1,6 @@
1
- // src/cn.ts
2
- import { clsx } from "clsx";
3
- import { twMerge } from "tailwind-merge";
4
- function cn(...inputs) {
5
- return twMerge(clsx(inputs));
6
- }
1
+ import {
2
+ cn
3
+ } from "./chunk-XF3CK37X.mjs";
7
4
 
8
5
  // src/components/badge.tsx
9
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cn.ts","../src/components/badge.tsx","../src/components/button.tsx","../src/components/card.tsx","../src/components/container.tsx","../src/components/section.tsx"],"sourcesContent":["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 type { HTMLAttributes } from 'react';\nimport { cn } from '../cn';\n\nexport interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n /** Render a leading status dot. */\n dot?: boolean;\n}\n\n/** Pill badge, optionally with a leading status dot. */\nexport function Badge({ dot = false, className, children, ...props }: BadgeProps) {\n return (\n <span className={cn('badge', className)} {...props}>\n {dot ? <span className=\"badge-dot\" /> : null}\n {children}\n </span>\n );\n}\n","import type { ButtonHTMLAttributes } from 'react';\nimport { cn } from '../cn';\n\nexport type ButtonVariant = 'primary' | 'secondary' | 'outline';\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n}\n\nconst variantClass: Record<ButtonVariant, string> = {\n primary: 'btn-primary',\n secondary: 'btn-secondary',\n outline: 'btn-outline',\n};\n\nexport function Button({ variant = 'primary', className, type = 'button', ...props }: ButtonProps) {\n return <button type={type} className={cn(variantClass[variant], className)} {...props} />;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../cn';\n\nexport type CardProps = HTMLAttributes<HTMLDivElement>;\n\n/** Bordered surface card with hover elevation. */\nexport function Card({ className, ...props }: CardProps) {\n return <div className={cn('card', className)} {...props} />;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../cn';\n\nexport type ContainerProps = HTMLAttributes<HTMLDivElement>;\n\n/** Centered, max-width content wrapper (var(--max-w)) with horizontal padding. */\nexport function Container({ className, ...props }: ContainerProps) {\n return <div className={cn('container', className)} {...props} />;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../cn';\n\nexport type SectionProps = HTMLAttributes<HTMLElement>;\n\n/** Vertical page section with max-width and standard padding. */\nexport function Section({ className, ...props }: SectionProps) {\n return <section className={cn('section', className)} {...props} />;\n}\n\nexport interface SectionHeaderProps {\n /** Small eyebrow label above the title (brand colored). */\n label?: ReactNode;\n title: ReactNode;\n description?: ReactNode;\n className?: string;\n}\n\n/** Centered section heading: optional label, title, optional description. */\nexport function SectionHeader({ label, title, description, className }: SectionHeaderProps) {\n return (\n <div className={cn('section-center', className)}>\n {label ? <div className=\"section-label\">{label}</div> : null}\n <h2 className=\"section-title\">{title}</h2>\n {description ? <p className=\"section-desc\">{description}</p> : null}\n </div>\n );\n}\n"],"mappings":";AAAA,SAA0B,YAAY;AACtC,SAAS,eAAe;AAOjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;ACCI,SACS,KADT;AAFG,SAAS,MAAM,EAAE,MAAM,OAAO,WAAW,UAAU,GAAG,MAAM,GAAe;AAChF,SACE,qBAAC,UAAK,WAAW,GAAG,SAAS,SAAS,GAAI,GAAG,OAC1C;AAAA,UAAM,oBAAC,UAAK,WAAU,aAAY,IAAK;AAAA,IACvC;AAAA,KACH;AAEJ;;;ACAS,gBAAAA,YAAA;AAPT,IAAM,eAA8C;AAAA,EAClD,SAAS;AAAA,EACT,WAAW;AAAA,EACX,SAAS;AACX;AAEO,SAAS,OAAO,EAAE,UAAU,WAAW,WAAW,OAAO,UAAU,GAAG,MAAM,GAAgB;AACjG,SAAO,gBAAAA,KAAC,YAAO,MAAY,WAAW,GAAG,aAAa,OAAO,GAAG,SAAS,GAAI,GAAG,OAAO;AACzF;;;ACVS,gBAAAC,YAAA;AADF,SAAS,KAAK,EAAE,WAAW,GAAG,MAAM,GAAc;AACvD,SAAO,gBAAAA,KAAC,SAAI,WAAW,GAAG,QAAQ,SAAS,GAAI,GAAG,OAAO;AAC3D;;;ACDS,gBAAAC,YAAA;AADF,SAAS,UAAU,EAAE,WAAW,GAAG,MAAM,GAAmB;AACjE,SAAO,gBAAAA,KAAC,SAAI,WAAW,GAAG,aAAa,SAAS,GAAI,GAAG,OAAO;AAChE;;;ACDS,gBAAAC,MAcL,QAAAC,aAdK;AADF,SAAS,QAAQ,EAAE,WAAW,GAAG,MAAM,GAAiB;AAC7D,SAAO,gBAAAD,KAAC,aAAQ,WAAW,GAAG,WAAW,SAAS,GAAI,GAAG,OAAO;AAClE;AAWO,SAAS,cAAc,EAAE,OAAO,OAAO,aAAa,UAAU,GAAuB;AAC1F,SACE,gBAAAC,MAAC,SAAI,WAAW,GAAG,kBAAkB,SAAS,GAC3C;AAAA,YAAQ,gBAAAD,KAAC,SAAI,WAAU,iBAAiB,iBAAM,IAAS;AAAA,IACxD,gBAAAA,KAAC,QAAG,WAAU,iBAAiB,iBAAM;AAAA,IACpC,cAAc,gBAAAA,KAAC,OAAE,WAAU,gBAAgB,uBAAY,IAAO;AAAA,KACjE;AAEJ;","names":["jsx","jsx","jsx","jsx","jsxs"]}
1
+ {"version":3,"sources":["../src/components/badge.tsx","../src/components/button.tsx","../src/components/card.tsx","../src/components/container.tsx","../src/components/section.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\nimport { cn } from '../cn';\n\nexport interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {\n /** Render a leading status dot. */\n dot?: boolean;\n}\n\n/** Pill badge, optionally with a leading status dot. */\nexport function Badge({ dot = false, className, children, ...props }: BadgeProps) {\n return (\n <span className={cn('badge', className)} {...props}>\n {dot ? <span className=\"badge-dot\" /> : null}\n {children}\n </span>\n );\n}\n","import type { ButtonHTMLAttributes } from 'react';\nimport { cn } from '../cn';\n\nexport type ButtonVariant = 'primary' | 'secondary' | 'outline';\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: ButtonVariant;\n}\n\nconst variantClass: Record<ButtonVariant, string> = {\n primary: 'btn-primary',\n secondary: 'btn-secondary',\n outline: 'btn-outline',\n};\n\nexport function Button({ variant = 'primary', className, type = 'button', ...props }: ButtonProps) {\n return <button type={type} className={cn(variantClass[variant], className)} {...props} />;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../cn';\n\nexport type CardProps = HTMLAttributes<HTMLDivElement>;\n\n/** Bordered surface card with hover elevation. */\nexport function Card({ className, ...props }: CardProps) {\n return <div className={cn('card', className)} {...props} />;\n}\n","import type { HTMLAttributes } from 'react';\nimport { cn } from '../cn';\n\nexport type ContainerProps = HTMLAttributes<HTMLDivElement>;\n\n/** Centered, max-width content wrapper (var(--max-w)) with horizontal padding. */\nexport function Container({ className, ...props }: ContainerProps) {\n return <div className={cn('container', className)} {...props} />;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../cn';\n\nexport type SectionProps = HTMLAttributes<HTMLElement>;\n\n/** Vertical page section with max-width and standard padding. */\nexport function Section({ className, ...props }: SectionProps) {\n return <section className={cn('section', className)} {...props} />;\n}\n\nexport interface SectionHeaderProps {\n /** Small eyebrow label above the title (brand colored). */\n label?: ReactNode;\n title: ReactNode;\n description?: ReactNode;\n className?: string;\n}\n\n/** Centered section heading: optional label, title, optional description. */\nexport function SectionHeader({ label, title, description, className }: SectionHeaderProps) {\n return (\n <div className={cn('section-center', className)}>\n {label ? <div className=\"section-label\">{label}</div> : null}\n <h2 className=\"section-title\">{title}</h2>\n {description ? <p className=\"section-desc\">{description}</p> : null}\n </div>\n );\n}\n"],"mappings":";;;;;AAWI,SACS,KADT;AAFG,SAAS,MAAM,EAAE,MAAM,OAAO,WAAW,UAAU,GAAG,MAAM,GAAe;AAChF,SACE,qBAAC,UAAK,WAAW,GAAG,SAAS,SAAS,GAAI,GAAG,OAC1C;AAAA,UAAM,oBAAC,UAAK,WAAU,aAAY,IAAK;AAAA,IACvC;AAAA,KACH;AAEJ;;;ACAS,gBAAAA,YAAA;AAPT,IAAM,eAA8C;AAAA,EAClD,SAAS;AAAA,EACT,WAAW;AAAA,EACX,SAAS;AACX;AAEO,SAAS,OAAO,EAAE,UAAU,WAAW,WAAW,OAAO,UAAU,GAAG,MAAM,GAAgB;AACjG,SAAO,gBAAAA,KAAC,YAAO,MAAY,WAAW,GAAG,aAAa,OAAO,GAAG,SAAS,GAAI,GAAG,OAAO;AACzF;;;ACVS,gBAAAC,YAAA;AADF,SAAS,KAAK,EAAE,WAAW,GAAG,MAAM,GAAc;AACvD,SAAO,gBAAAA,KAAC,SAAI,WAAW,GAAG,QAAQ,SAAS,GAAI,GAAG,OAAO;AAC3D;;;ACDS,gBAAAC,YAAA;AADF,SAAS,UAAU,EAAE,WAAW,GAAG,MAAM,GAAmB;AACjE,SAAO,gBAAAA,KAAC,SAAI,WAAW,GAAG,aAAa,SAAS,GAAI,GAAG,OAAO;AAChE;;;ACDS,gBAAAC,MAcL,QAAAC,aAdK;AADF,SAAS,QAAQ,EAAE,WAAW,GAAG,MAAM,GAAiB;AAC7D,SAAO,gBAAAD,KAAC,aAAQ,WAAW,GAAG,WAAW,SAAS,GAAI,GAAG,OAAO;AAClE;AAWO,SAAS,cAAc,EAAE,OAAO,OAAO,aAAa,UAAU,GAAuB;AAC1F,SACE,gBAAAC,MAAC,SAAI,WAAW,GAAG,kBAAkB,SAAS,GAC3C;AAAA,YAAQ,gBAAAD,KAAC,SAAI,WAAU,iBAAiB,iBAAM,IAAS;AAAA,IACxD,gBAAAA,KAAC,QAAG,WAAU,iBAAiB,iBAAM;AAAA,IACpC,cAAc,gBAAAA,KAAC,OAAE,WAAU,gBAAgB,uBAAY,IAAO;AAAA,KACjE;AAEJ;","names":["jsx","jsx","jsx","jsx","jsxs"]}
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/marketing/index.ts
31
+ var marketing_exports = {};
32
+ __export(marketing_exports, {
33
+ Footer: () => Footer,
34
+ MarketingLink: () => MarketingLink,
35
+ Nav: () => Nav
36
+ });
37
+ module.exports = __toCommonJS(marketing_exports);
38
+
39
+ // src/marketing/footer.tsx
40
+ var import_image = __toESM(require("next/image"), 1);
41
+
42
+ // src/cn.ts
43
+ var import_clsx = require("clsx");
44
+ var import_tailwind_merge = require("tailwind-merge");
45
+ function cn(...inputs) {
46
+ return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
47
+ }
48
+
49
+ // src/marketing/link.tsx
50
+ var import_link = __toESM(require("next/link"), 1);
51
+ var import_jsx_runtime = require("react/jsx-runtime");
52
+ function MarketingLink({ href, external, className, children }) {
53
+ const isAbsolute = /^https?:\/\//.test(href) || href.startsWith("//");
54
+ const isProtocol = !isAbsolute && /^[a-z][a-z0-9+.-]*:/i.test(href);
55
+ const openExternally = external ?? isAbsolute;
56
+ if (openExternally) {
57
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href, className, target: "_blank", rel: "noopener noreferrer", children });
58
+ }
59
+ if (isProtocol) {
60
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href, className, children });
61
+ }
62
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href, className, children });
63
+ }
64
+
65
+ // src/marketing/footer.tsx
66
+ var import_jsx_runtime2 = require("react/jsx-runtime");
67
+ function Footer({ brand, columns = [], legal = [], copyright, className }) {
68
+ const size = brand.size ?? 20;
69
+ const image = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_image.default, { src: brand.src, alt: brand.alt ?? "", width: size, height: size });
70
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("footer", { className: cn("footer", className), children: [
71
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "footer-inner", children: [
72
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "footer-brand", children: [
73
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(MarketingLink, { href: brand.href ?? "/", className: "nav-logo", children: [
74
+ brand.mark ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "nav-logo-mark", style: { width: size, height: size }, children: image }) : image,
75
+ brand.label
76
+ ] }),
77
+ brand.tagline ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: brand.tagline }) : null
78
+ ] }),
79
+ columns.map((column, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "footer-column", children: [
80
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { children: column.title }),
81
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { children: column.links.map((link) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MarketingLink, { href: link.href, external: link.external, children: link.label }) }, link.href)) })
82
+ ] }, index))
83
+ ] }),
84
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "footer-bottom", children: [
85
+ copyright ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: copyright }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {}),
86
+ legal.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "footer-legal", children: legal.map((link) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MarketingLink, { href: link.href, external: link.external, children: link.label }, link.href)) }) : null
87
+ ] })
88
+ ] });
89
+ }
90
+
91
+ // src/marketing/nav.tsx
92
+ var import_image2 = __toESM(require("next/image"), 1);
93
+ var import_jsx_runtime3 = require("react/jsx-runtime");
94
+ function Nav({ logo, links = [], children, className }) {
95
+ const size = logo.size ?? 28;
96
+ const image = /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_image2.default, { src: logo.src, alt: logo.alt ?? "", width: size, height: size, priority: true });
97
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("nav", { className: cn("nav", className), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "nav-inner", children: [
98
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(MarketingLink, { href: logo.href ?? "/", className: "nav-logo", children: [
99
+ logo.mark ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "nav-logo-mark", style: { width: size, height: size }, children: image }) : image,
100
+ logo.label
101
+ ] }),
102
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("ul", { className: "nav-links", children: [
103
+ links.map((link) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
104
+ MarketingLink,
105
+ {
106
+ href: link.href,
107
+ external: link.external,
108
+ className: link.cta ? "nav-cta" : void 0,
109
+ children: link.label
110
+ }
111
+ ) }, link.href)),
112
+ children ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { children }) : null
113
+ ] })
114
+ ] }) });
115
+ }
116
+ // Annotate the CommonJS export names for ESM import in node:
117
+ 0 && (module.exports = {
118
+ Footer,
119
+ MarketingLink,
120
+ Nav
121
+ });
122
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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 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 src: string;\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 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 src: string;\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"]}
@@ -0,0 +1,74 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ interface FooterLink {
5
+ href: string;
6
+ label: ReactNode;
7
+ external?: boolean;
8
+ }
9
+ interface FooterColumn {
10
+ title: ReactNode;
11
+ links: FooterLink[];
12
+ }
13
+ interface FooterBrand {
14
+ src: string;
15
+ alt?: string;
16
+ label?: ReactNode;
17
+ href?: string;
18
+ size?: number;
19
+ mark?: boolean;
20
+ tagline?: ReactNode;
21
+ }
22
+ interface FooterProps {
23
+ brand: FooterBrand;
24
+ columns?: FooterColumn[];
25
+ legal?: FooterLink[];
26
+ copyright?: ReactNode;
27
+ className?: string;
28
+ }
29
+ /** Shared site footer for marketing surfaces (landing, demo). */
30
+ declare function Footer({ brand, columns, legal, copyright, className }: FooterProps): react.JSX.Element;
31
+
32
+ interface MarketingLinkProps {
33
+ href: string;
34
+ /** Force new-tab rendering. Defaults to true for absolute http(s) URLs. */
35
+ external?: boolean;
36
+ className?: string;
37
+ children: ReactNode;
38
+ }
39
+ /**
40
+ * Picks the right element for a marketing link:
41
+ * - internal route ("/...", "#...") → next/link
42
+ * - protocol link (mailto:/tel:) → plain anchor
43
+ * - absolute URL (or `external`) → new-tab anchor
44
+ */
45
+ declare function MarketingLink({ href, external, className, children }: MarketingLinkProps): react.JSX.Element;
46
+
47
+ interface NavLink {
48
+ href: string;
49
+ label: ReactNode;
50
+ external?: boolean;
51
+ /** Render as the prominent call-to-action button. */
52
+ cta?: boolean;
53
+ }
54
+ interface NavLogo {
55
+ src: string;
56
+ alt?: string;
57
+ label?: ReactNode;
58
+ href?: string;
59
+ /** Logo image edge size in px (default 28). */
60
+ size?: number;
61
+ /** Wrap the image in the rounded brand mark. */
62
+ mark?: boolean;
63
+ }
64
+ interface NavProps {
65
+ logo: NavLogo;
66
+ links?: NavLink[];
67
+ /** Extra item appended to the link list (e.g. an interactive control). */
68
+ children?: ReactNode;
69
+ className?: string;
70
+ }
71
+ /** Shared fixed top navigation for marketing surfaces (landing, demo). */
72
+ declare function Nav({ logo, links, children, className }: NavProps): react.JSX.Element;
73
+
74
+ export { Footer, type FooterBrand, type FooterColumn, type FooterLink, type FooterProps, MarketingLink, type MarketingLinkProps, Nav, type NavLink, type NavLogo, type NavProps };
@@ -0,0 +1,74 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ interface FooterLink {
5
+ href: string;
6
+ label: ReactNode;
7
+ external?: boolean;
8
+ }
9
+ interface FooterColumn {
10
+ title: ReactNode;
11
+ links: FooterLink[];
12
+ }
13
+ interface FooterBrand {
14
+ src: string;
15
+ alt?: string;
16
+ label?: ReactNode;
17
+ href?: string;
18
+ size?: number;
19
+ mark?: boolean;
20
+ tagline?: ReactNode;
21
+ }
22
+ interface FooterProps {
23
+ brand: FooterBrand;
24
+ columns?: FooterColumn[];
25
+ legal?: FooterLink[];
26
+ copyright?: ReactNode;
27
+ className?: string;
28
+ }
29
+ /** Shared site footer for marketing surfaces (landing, demo). */
30
+ declare function Footer({ brand, columns, legal, copyright, className }: FooterProps): react.JSX.Element;
31
+
32
+ interface MarketingLinkProps {
33
+ href: string;
34
+ /** Force new-tab rendering. Defaults to true for absolute http(s) URLs. */
35
+ external?: boolean;
36
+ className?: string;
37
+ children: ReactNode;
38
+ }
39
+ /**
40
+ * Picks the right element for a marketing link:
41
+ * - internal route ("/...", "#...") → next/link
42
+ * - protocol link (mailto:/tel:) → plain anchor
43
+ * - absolute URL (or `external`) → new-tab anchor
44
+ */
45
+ declare function MarketingLink({ href, external, className, children }: MarketingLinkProps): react.JSX.Element;
46
+
47
+ interface NavLink {
48
+ href: string;
49
+ label: ReactNode;
50
+ external?: boolean;
51
+ /** Render as the prominent call-to-action button. */
52
+ cta?: boolean;
53
+ }
54
+ interface NavLogo {
55
+ src: string;
56
+ alt?: string;
57
+ label?: ReactNode;
58
+ href?: string;
59
+ /** Logo image edge size in px (default 28). */
60
+ size?: number;
61
+ /** Wrap the image in the rounded brand mark. */
62
+ mark?: boolean;
63
+ }
64
+ interface NavProps {
65
+ logo: NavLogo;
66
+ links?: NavLink[];
67
+ /** Extra item appended to the link list (e.g. an interactive control). */
68
+ children?: ReactNode;
69
+ className?: string;
70
+ }
71
+ /** Shared fixed top navigation for marketing surfaces (landing, demo). */
72
+ declare function Nav({ logo, links, children, className }: NavProps): react.JSX.Element;
73
+
74
+ export { Footer, type FooterBrand, type FooterColumn, type FooterLink, type FooterProps, MarketingLink, type MarketingLinkProps, Nav, type NavLink, type NavLogo, type NavProps };
@@ -0,0 +1,80 @@
1
+ import {
2
+ cn
3
+ } from "../chunk-XF3CK37X.mjs";
4
+
5
+ // src/marketing/footer.tsx
6
+ import Image from "next/image";
7
+
8
+ // src/marketing/link.tsx
9
+ import Link from "next/link";
10
+ import { jsx } from "react/jsx-runtime";
11
+ function MarketingLink({ href, external, className, children }) {
12
+ const isAbsolute = /^https?:\/\//.test(href) || href.startsWith("//");
13
+ const isProtocol = !isAbsolute && /^[a-z][a-z0-9+.-]*:/i.test(href);
14
+ const openExternally = external ?? isAbsolute;
15
+ if (openExternally) {
16
+ return /* @__PURE__ */ jsx("a", { href, className, target: "_blank", rel: "noopener noreferrer", children });
17
+ }
18
+ if (isProtocol) {
19
+ return /* @__PURE__ */ jsx("a", { href, className, children });
20
+ }
21
+ return /* @__PURE__ */ jsx(Link, { href, className, children });
22
+ }
23
+
24
+ // src/marketing/footer.tsx
25
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
26
+ function Footer({ brand, columns = [], legal = [], copyright, className }) {
27
+ const size = brand.size ?? 20;
28
+ const image = /* @__PURE__ */ jsx2(Image, { src: brand.src, alt: brand.alt ?? "", width: size, height: size });
29
+ return /* @__PURE__ */ jsxs("footer", { className: cn("footer", className), children: [
30
+ /* @__PURE__ */ jsxs("div", { className: "footer-inner", children: [
31
+ /* @__PURE__ */ jsxs("div", { className: "footer-brand", children: [
32
+ /* @__PURE__ */ jsxs(MarketingLink, { href: brand.href ?? "/", className: "nav-logo", children: [
33
+ brand.mark ? /* @__PURE__ */ jsx2("span", { className: "nav-logo-mark", style: { width: size, height: size }, children: image }) : image,
34
+ brand.label
35
+ ] }),
36
+ brand.tagline ? /* @__PURE__ */ jsx2("p", { children: brand.tagline }) : null
37
+ ] }),
38
+ columns.map((column, index) => /* @__PURE__ */ jsxs("div", { className: "footer-column", children: [
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 }) }, link.href)) })
41
+ ] }, index))
42
+ ] }),
43
+ /* @__PURE__ */ jsxs("div", { className: "footer-bottom", children: [
44
+ copyright ? /* @__PURE__ */ jsx2("p", { children: copyright }) : /* @__PURE__ */ jsx2("span", {}),
45
+ legal.length > 0 ? /* @__PURE__ */ jsx2("div", { className: "footer-legal", children: legal.map((link) => /* @__PURE__ */ jsx2(MarketingLink, { href: link.href, external: link.external, children: link.label }, link.href)) }) : null
46
+ ] })
47
+ ] });
48
+ }
49
+
50
+ // src/marketing/nav.tsx
51
+ import Image2 from "next/image";
52
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
53
+ function Nav({ logo, links = [], children, className }) {
54
+ const size = logo.size ?? 28;
55
+ const image = /* @__PURE__ */ jsx3(Image2, { src: logo.src, alt: logo.alt ?? "", width: size, height: size, priority: true });
56
+ return /* @__PURE__ */ jsx3("nav", { className: cn("nav", className), children: /* @__PURE__ */ jsxs2("div", { className: "nav-inner", children: [
57
+ /* @__PURE__ */ jsxs2(MarketingLink, { href: logo.href ?? "/", className: "nav-logo", children: [
58
+ logo.mark ? /* @__PURE__ */ jsx3("span", { className: "nav-logo-mark", style: { width: size, height: size }, children: image }) : image,
59
+ logo.label
60
+ ] }),
61
+ /* @__PURE__ */ jsxs2("ul", { className: "nav-links", children: [
62
+ links.map((link) => /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsx3(
63
+ MarketingLink,
64
+ {
65
+ href: link.href,
66
+ external: link.external,
67
+ className: link.cta ? "nav-cta" : void 0,
68
+ children: link.label
69
+ }
70
+ ) }, link.href)),
71
+ children ? /* @__PURE__ */ jsx3("li", { children }) : null
72
+ ] })
73
+ ] }) });
74
+ }
75
+ export {
76
+ Footer,
77
+ MarketingLink,
78
+ Nav
79
+ };
80
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/marketing/footer.tsx","../../src/marketing/link.tsx","../../src/marketing/nav.tsx"],"sourcesContent":["import Image 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 src: string;\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 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 src: string;\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flopay/ui",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@9.15.0",
6
6
  "description": "FloPay shared design system — design tokens, a Tailwind v4 preset, and React primitives shared across landing, demo, docs, and dashboard.",
@@ -22,6 +22,11 @@
22
22
  "import": "./dist/index.mjs",
23
23
  "require": "./dist/index.cjs"
24
24
  },
25
+ "./marketing": {
26
+ "types": "./dist/marketing/index.d.ts",
27
+ "import": "./dist/marketing/index.mjs",
28
+ "require": "./dist/marketing/index.cjs"
29
+ },
25
30
  "./styles": "./styles/index.css",
26
31
  "./styles/index.css": "./styles/index.css",
27
32
  "./styles/tokens.css": "./styles/tokens.css",
@@ -47,9 +52,15 @@
47
52
  "prepublishOnly": "node scripts/check-publish-registry.cjs"
48
53
  },
49
54
  "peerDependencies": {
55
+ "next": ">=15",
50
56
  "react": "^19",
51
57
  "react-dom": "^19"
52
58
  },
59
+ "peerDependenciesMeta": {
60
+ "next": {
61
+ "optional": true
62
+ }
63
+ },
53
64
  "dependencies": {
54
65
  "clsx": "^2.1.1",
55
66
  "tailwind-merge": "^3.6.0"
@@ -58,6 +69,7 @@
58
69
  "@biomejs/biome": "^2.4.15",
59
70
  "@types/react": "^19.2.15",
60
71
  "@types/react-dom": "^19.2.3",
72
+ "next": "^16.2.6",
61
73
  "react": "^19.2.6",
62
74
  "react-dom": "^19.2.6",
63
75
  "tsup": "^8.3.0",
package/styles/tokens.css CHANGED
@@ -35,6 +35,11 @@
35
35
  --brand-light: #4ba6ec;
36
36
  --brand-secondary: #38d299;
37
37
 
38
+ /* Brand as raw HSL channels — for consumers that need `H S% L%`
39
+ (e.g. Fumadocs `--fd-primary`). Mirror --brand / --brand-light. */
40
+ --brand-hsl: 207 81% 48%;
41
+ --brand-light-hsl: 206 81% 61%;
42
+
38
43
  /* Status */
39
44
  --success: #16a34a;
40
45
  --danger: #dc2626;