@medialane/ui 0.1.6 → 0.3.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.
Files changed (92) hide show
  1. package/dist/components/activity-feed-shell.cjs +90 -0
  2. package/dist/components/activity-feed-shell.cjs.map +1 -0
  3. package/dist/components/activity-feed-shell.d.cts +13 -0
  4. package/dist/components/activity-feed-shell.d.ts +13 -0
  5. package/dist/components/activity-feed-shell.js +56 -0
  6. package/dist/components/activity-feed-shell.js.map +1 -0
  7. package/dist/components/activity-row.cjs +95 -0
  8. package/dist/components/activity-row.cjs.map +1 -0
  9. package/dist/components/activity-row.d.cts +20 -0
  10. package/dist/components/activity-row.d.ts +20 -0
  11. package/dist/components/activity-row.js +61 -0
  12. package/dist/components/activity-row.js.map +1 -0
  13. package/dist/components/activity-ticker.cjs +92 -0
  14. package/dist/components/activity-ticker.cjs.map +1 -0
  15. package/dist/components/activity-ticker.d.cts +12 -0
  16. package/dist/components/activity-ticker.d.ts +12 -0
  17. package/dist/components/activity-ticker.js +58 -0
  18. package/dist/components/activity-ticker.js.map +1 -0
  19. package/dist/components/collection-card.cjs +124 -0
  20. package/dist/components/collection-card.cjs.map +1 -0
  21. package/dist/components/collection-card.d.cts +13 -0
  22. package/dist/components/collection-card.d.ts +13 -0
  23. package/dist/components/collection-card.js +89 -0
  24. package/dist/components/collection-card.js.map +1 -0
  25. package/dist/components/cta-card-grid.cjs +67 -0
  26. package/dist/components/cta-card-grid.cjs.map +1 -0
  27. package/dist/components/cta-card-grid.d.cts +23 -0
  28. package/dist/components/cta-card-grid.d.ts +23 -0
  29. package/dist/components/cta-card-grid.js +33 -0
  30. package/dist/components/cta-card-grid.js.map +1 -0
  31. package/dist/components/hero-slider.cjs +133 -0
  32. package/dist/components/hero-slider.cjs.map +1 -0
  33. package/dist/components/hero-slider.d.cts +12 -0
  34. package/dist/components/hero-slider.d.ts +12 -0
  35. package/dist/components/hero-slider.js +98 -0
  36. package/dist/components/hero-slider.js.map +1 -0
  37. package/dist/components/launchpad-grid.cjs +77 -0
  38. package/dist/components/launchpad-grid.cjs.map +1 -0
  39. package/dist/components/launchpad-grid.d.cts +20 -0
  40. package/dist/components/launchpad-grid.d.ts +20 -0
  41. package/dist/components/launchpad-grid.js +43 -0
  42. package/dist/components/launchpad-grid.js.map +1 -0
  43. package/dist/components/listing-card.cjs +146 -0
  44. package/dist/components/listing-card.cjs.map +1 -0
  45. package/dist/components/listing-card.d.cts +16 -0
  46. package/dist/components/listing-card.d.ts +16 -0
  47. package/dist/components/listing-card.js +111 -0
  48. package/dist/components/listing-card.js.map +1 -0
  49. package/dist/components/motion-primitives.cjs +126 -0
  50. package/dist/components/motion-primitives.cjs.map +1 -0
  51. package/dist/components/motion-primitives.d.cts +36 -0
  52. package/dist/components/motion-primitives.d.ts +36 -0
  53. package/dist/components/motion-primitives.js +96 -0
  54. package/dist/components/motion-primitives.js.map +1 -0
  55. package/dist/components/scroll-section.cjs +72 -0
  56. package/dist/components/scroll-section.cjs.map +1 -0
  57. package/dist/components/scroll-section.d.cts +18 -0
  58. package/dist/components/scroll-section.d.ts +18 -0
  59. package/dist/components/scroll-section.js +38 -0
  60. package/dist/components/scroll-section.js.map +1 -0
  61. package/dist/components/share-button.cjs +86 -0
  62. package/dist/components/share-button.cjs.map +1 -0
  63. package/dist/components/share-button.d.cts +12 -0
  64. package/dist/components/share-button.d.ts +12 -0
  65. package/dist/components/share-button.js +62 -0
  66. package/dist/components/share-button.js.map +1 -0
  67. package/dist/components/token-card.cjs +281 -0
  68. package/dist/components/token-card.cjs.map +1 -0
  69. package/dist/components/token-card.d.cts +31 -0
  70. package/dist/components/token-card.d.ts +31 -0
  71. package/dist/components/token-card.js +256 -0
  72. package/dist/components/token-card.js.map +1 -0
  73. package/dist/data/activity.cjs +48 -0
  74. package/dist/data/activity.cjs.map +1 -0
  75. package/dist/data/activity.d.cts +16 -0
  76. package/dist/data/activity.d.ts +16 -0
  77. package/dist/data/activity.js +23 -0
  78. package/dist/data/activity.js.map +1 -0
  79. package/dist/index.cjs +66 -2
  80. package/dist/index.cjs.map +1 -1
  81. package/dist/index.d.cts +18 -0
  82. package/dist/index.d.ts +18 -0
  83. package/dist/index.js +40 -1
  84. package/dist/index.js.map +1 -1
  85. package/dist/medialane.css +184 -0
  86. package/dist/utils/time.cjs +42 -0
  87. package/dist/utils/time.cjs.map +1 -0
  88. package/dist/utils/time.d.cts +7 -0
  89. package/dist/utils/time.d.ts +7 -0
  90. package/dist/utils/time.js +18 -0
  91. package/dist/utils/time.js.map +1 -0
  92. package/package.json +17 -10
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var listing_card_exports = {};
31
+ __export(listing_card_exports, {
32
+ ListingCard: () => ListingCard,
33
+ ListingCardSkeleton: () => ListingCardSkeleton
34
+ });
35
+ module.exports = __toCommonJS(listing_card_exports);
36
+ var import_jsx_runtime = require("react/jsx-runtime");
37
+ var import_react = require("react");
38
+ var import_link = __toESM(require("next/link"), 1);
39
+ var import_image = __toESM(require("next/image"), 1);
40
+ var import_lucide_react = require("lucide-react");
41
+ var import_motion_primitives = require("./motion-primitives.js");
42
+ var import_currency_icon = require("./currency-icon.js");
43
+ var import_cn = require("../utils/cn.js");
44
+ var import_ipfs = require("../utils/ipfs.js");
45
+ var import_format = require("../utils/format.js");
46
+ var import_time = require("../utils/time.js");
47
+ function ListingCard({ order, inCart = false, onBuy, onCart, overflowMenu, compact = false }) {
48
+ const [imgError, setImgError] = (0, import_react.useState)(false);
49
+ const isListing = order.offer.itemType === "ERC721" || order.offer.itemType === "ERC1155";
50
+ const name = order.token?.name ?? `Token #${order.nftTokenId}`;
51
+ const image = order.token?.image ? (0, import_ipfs.ipfsToHttp)(order.token.image) : null;
52
+ const assetHref = `/asset/${order.nftContract}/${order.nftTokenId}`;
53
+ const showActionBar = isListing && (onBuy || onCart || overflowMenu);
54
+ if (compact) {
55
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_motion_primitives.MotionCard, { className: "card-base", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_link.default, { href: assetHref, className: "block", children: [
56
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "relative aspect-square bg-muted overflow-hidden", children: image && !imgError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_image.default, { src: image, alt: name, fill: true, unoptimized: true, sizes: "(max-width: 640px) 33vw, 20vw", className: "object-cover group-hover:scale-105 transition-transform duration-500", onError: () => setImgError(true) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0 flex items-center justify-center bg-gradient-to-br from-brand-purple/15 to-brand-blue/15", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "text-xl font-mono text-muted-foreground", children: [
57
+ "#",
58
+ order.nftTokenId
59
+ ] }) }) }),
60
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "p-2.5 space-y-0.5", children: [
61
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs font-semibold truncate", children: name }),
62
+ order.price?.formatted && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-[11px] font-bold price-value", children: [
63
+ (0, import_format.formatDisplayPrice)(order.price.formatted),
64
+ " ",
65
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground font-normal", children: order.price.currency })
66
+ ] }),
67
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-[10px] text-muted-foreground", children: (0, import_time.timeAgo)(order.createdAt) })
68
+ ] })
69
+ ] }) });
70
+ }
71
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_motion_primitives.MotionCard, { className: "card-base", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_link.default, { href: assetHref, className: "block", children: [
72
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "relative aspect-square bg-muted overflow-hidden", children: image && !imgError ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_image.default, { src: image, alt: name, fill: true, unoptimized: true, sizes: "(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 25vw", className: "object-cover group-hover:scale-105 transition-transform duration-500", onError: () => setImgError(true) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute inset-0 flex items-center justify-center bg-gradient-to-br from-brand-purple/15 to-brand-blue/15", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "text-2xl font-mono text-muted-foreground", children: [
73
+ "#",
74
+ order.nftTokenId
75
+ ] }) }) }),
76
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "p-4 space-y-3", children: [
77
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
78
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "font-semibold text-base truncate leading-snug", children: name }),
79
+ order.token?.description ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-[11px] text-muted-foreground line-clamp-1 leading-snug mt-0.5", children: order.token.description }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-[11px] text-muted-foreground", children: [
80
+ "#",
81
+ order.nftTokenId
82
+ ] })
83
+ ] }),
84
+ order.price?.formatted && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1.5", children: [
85
+ order.price.currency && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_currency_icon.CurrencyIcon, { symbol: order.price.currency, size: 14 }),
86
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-lg font-bold price-value leading-none", children: [
87
+ (0, import_format.formatDisplayPrice)(order.price.formatted),
88
+ " ",
89
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground font-normal text-sm", children: order.price.currency })
90
+ ] })
91
+ ] }),
92
+ showActionBar && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1.5", children: [
93
+ onBuy && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-9", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
94
+ "button",
95
+ {
96
+ className: "w-full h-full rounded-[9px] bg-background flex items-center justify-center gap-1.5 text-xs font-semibold text-foreground hover:bg-muted/60 transition-all active:scale-[0.98]",
97
+ onClick: (e) => {
98
+ e.preventDefault();
99
+ onBuy(order);
100
+ },
101
+ children: [
102
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Zap, { className: "h-3.5 w-3.5 shrink-0" }),
103
+ " Buy"
104
+ ]
105
+ }
106
+ ) }),
107
+ onCart && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
108
+ "button",
109
+ {
110
+ className: (0, import_cn.cn)(
111
+ "h-9 w-9 shrink-0 rounded-[9px] border flex items-center justify-center transition-colors",
112
+ inCart ? "border-brand-orange/50 bg-brand-orange/10 text-brand-orange" : "border-border bg-background hover:bg-muted text-foreground"
113
+ ),
114
+ onClick: (e) => {
115
+ e.preventDefault();
116
+ if (!inCart) onCart(order);
117
+ },
118
+ disabled: inCart,
119
+ "aria-label": inCart ? "Added to cart" : "Add to cart",
120
+ children: inCart ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ShoppingCart, { className: "h-3.5 w-3.5" })
121
+ }
122
+ ),
123
+ overflowMenu
124
+ ] })
125
+ ] })
126
+ ] }) });
127
+ }
128
+ function ListingCardSkeleton() {
129
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "card-base", children: [
130
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "aspect-square w-full bg-muted animate-pulse" }),
131
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "p-3 space-y-2.5", children: [
132
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1", children: [
133
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-4 w-3/4 bg-muted animate-pulse rounded" }),
134
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-3 w-1/2 bg-muted animate-pulse rounded" })
135
+ ] }),
136
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-6 w-1/2 bg-muted animate-pulse rounded" }),
137
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-3 w-2/3 bg-muted animate-pulse rounded" })
138
+ ] })
139
+ ] });
140
+ }
141
+ // Annotate the CommonJS export names for ESM import in node:
142
+ 0 && (module.exports = {
143
+ ListingCard,
144
+ ListingCardSkeleton
145
+ });
146
+ //# sourceMappingURL=listing-card.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/listing-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { ShoppingCart, Check, Zap } from \"lucide-react\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport type { ApiOrder } from \"@medialane/sdk\";\n\nexport interface ListingCardProps {\n order: ApiOrder;\n inCart?: boolean;\n onBuy?: (order: ApiOrder) => void;\n onCart?: (order: ApiOrder) => void;\n /** App passes a fully constructed <DropdownMenu> here */\n overflowMenu?: React.ReactNode;\n compact?: boolean;\n}\n\nexport function ListingCard({ order, inCart = false, onBuy, onCart, overflowMenu, compact = false }: ListingCardProps) {\n const [imgError, setImgError] = useState(false);\n const isListing = order.offer.itemType === \"ERC721\" || order.offer.itemType === \"ERC1155\";\n const name = order.token?.name ?? `Token #${order.nftTokenId}`;\n const image = order.token?.image ? ipfsToHttp(order.token.image) : null;\n const assetHref = `/asset/${order.nftContract}/${order.nftTokenId}`;\n\n const showActionBar = isListing && (onBuy || onCart || overflowMenu);\n\n // ─── Compact variant ──────────────────────────────────────────────────────\n if (compact) {\n return (\n <MotionCard className=\"card-base\">\n <Link href={assetHref} className=\"block\">\n <div className=\"relative aspect-square bg-muted overflow-hidden\">\n {image && !imgError ? (\n <Image src={image} alt={name} fill unoptimized sizes=\"(max-width: 640px) 33vw, 20vw\" className=\"object-cover group-hover:scale-105 transition-transform duration-500\" onError={() => setImgError(true)} />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center bg-gradient-to-br from-brand-purple/15 to-brand-blue/15\">\n <span className=\"text-xl font-mono text-muted-foreground\">#{order.nftTokenId}</span>\n </div>\n )}\n </div>\n <div className=\"p-2.5 space-y-0.5\">\n <p className=\"text-xs font-semibold truncate\">{name}</p>\n {order.price?.formatted && (\n <p className=\"text-[11px] font-bold price-value\">\n {formatDisplayPrice(order.price.formatted)} <span className=\"text-muted-foreground font-normal\">{order.price.currency}</span>\n </p>\n )}\n <p className=\"text-[10px] text-muted-foreground\">{timeAgo(order.createdAt)}</p>\n </div>\n </Link>\n </MotionCard>\n );\n }\n\n // ─── Full variant ─────────────────────────────────────────────────────────\n return (\n <MotionCard className=\"card-base\">\n <Link href={assetHref} className=\"block\">\n <div className=\"relative aspect-square bg-muted overflow-hidden\">\n {image && !imgError ? (\n <Image src={image} alt={name} fill unoptimized sizes=\"(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 25vw\" className=\"object-cover group-hover:scale-105 transition-transform duration-500\" onError={() => setImgError(true)} />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center bg-gradient-to-br from-brand-purple/15 to-brand-blue/15\">\n <span className=\"text-2xl font-mono text-muted-foreground\">#{order.nftTokenId}</span>\n </div>\n )}\n </div>\n\n <div className=\"p-4 space-y-3\">\n <div>\n <p className=\"font-semibold text-base truncate leading-snug\">{name}</p>\n {order.token?.description ? (\n <p className=\"text-[11px] text-muted-foreground line-clamp-1 leading-snug mt-0.5\">{order.token.description}</p>\n ) : (\n <p className=\"text-[11px] text-muted-foreground\">#{order.nftTokenId}</p>\n )}\n </div>\n\n {order.price?.formatted && (\n <div className=\"flex items-center gap-1.5\">\n {order.price.currency && <CurrencyIcon symbol={order.price.currency} size={14} />}\n <p className=\"text-lg font-bold price-value leading-none\">\n {formatDisplayPrice(order.price.formatted)} <span className=\"text-muted-foreground font-normal text-sm\">{order.price.currency}</span>\n </p>\n </div>\n )}\n\n {showActionBar && (\n <div className=\"flex items-center gap-1.5\">\n {onBuy && (\n <div className=\"btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-9\">\n <button\n className=\"w-full h-full rounded-[9px] bg-background flex items-center justify-center gap-1.5 text-xs font-semibold text-foreground hover:bg-muted/60 transition-all active:scale-[0.98]\"\n onClick={(e) => { e.preventDefault(); onBuy(order); }}\n >\n <Zap className=\"h-3.5 w-3.5 shrink-0\" /> Buy\n </button>\n </div>\n )}\n {onCart && (\n <button\n className={cn(\n \"h-9 w-9 shrink-0 rounded-[9px] border flex items-center justify-center transition-colors\",\n inCart\n ? \"border-brand-orange/50 bg-brand-orange/10 text-brand-orange\"\n : \"border-border bg-background hover:bg-muted text-foreground\"\n )}\n onClick={(e) => { e.preventDefault(); if (!inCart) onCart(order); }}\n disabled={inCart}\n aria-label={inCart ? \"Added to cart\" : \"Add to cart\"}\n >\n {inCart ? <Check className=\"h-3.5 w-3.5\" /> : <ShoppingCart className=\"h-3.5 w-3.5\" />}\n </button>\n )}\n {overflowMenu}\n </div>\n )}\n </div>\n </Link>\n </MotionCard>\n );\n}\n\nexport function ListingCardSkeleton() {\n return (\n <div className=\"card-base\">\n <div className=\"aspect-square w-full bg-muted animate-pulse\" />\n <div className=\"p-3 space-y-2.5\">\n <div className=\"space-y-1\">\n <div className=\"h-4 w-3/4 bg-muted animate-pulse rounded\" />\n <div className=\"h-3 w-1/2 bg-muted animate-pulse rounded\" />\n </div>\n <div className=\"h-6 w-1/2 bg-muted animate-pulse rounded\" />\n <div className=\"h-3 w-2/3 bg-muted animate-pulse rounded\" />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["Link","Image"]}
@@ -0,0 +1,16 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ApiOrder } from '@medialane/sdk';
3
+
4
+ interface ListingCardProps {
5
+ order: ApiOrder;
6
+ inCart?: boolean;
7
+ onBuy?: (order: ApiOrder) => void;
8
+ onCart?: (order: ApiOrder) => void;
9
+ /** App passes a fully constructed <DropdownMenu> here */
10
+ overflowMenu?: React.ReactNode;
11
+ compact?: boolean;
12
+ }
13
+ declare function ListingCard({ order, inCart, onBuy, onCart, overflowMenu, compact }: ListingCardProps): react_jsx_runtime.JSX.Element;
14
+ declare function ListingCardSkeleton(): react_jsx_runtime.JSX.Element;
15
+
16
+ export { ListingCard, type ListingCardProps, ListingCardSkeleton };
@@ -0,0 +1,16 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ApiOrder } from '@medialane/sdk';
3
+
4
+ interface ListingCardProps {
5
+ order: ApiOrder;
6
+ inCart?: boolean;
7
+ onBuy?: (order: ApiOrder) => void;
8
+ onCart?: (order: ApiOrder) => void;
9
+ /** App passes a fully constructed <DropdownMenu> here */
10
+ overflowMenu?: React.ReactNode;
11
+ compact?: boolean;
12
+ }
13
+ declare function ListingCard({ order, inCart, onBuy, onCart, overflowMenu, compact }: ListingCardProps): react_jsx_runtime.JSX.Element;
14
+ declare function ListingCardSkeleton(): react_jsx_runtime.JSX.Element;
15
+
16
+ export { ListingCard, type ListingCardProps, ListingCardSkeleton };
@@ -0,0 +1,111 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import Link from "next/link";
5
+ import Image from "next/image";
6
+ import { ShoppingCart, Check, Zap } from "lucide-react";
7
+ import { MotionCard } from "./motion-primitives.js";
8
+ import { CurrencyIcon } from "./currency-icon.js";
9
+ import { cn } from "../utils/cn.js";
10
+ import { ipfsToHttp } from "../utils/ipfs.js";
11
+ import { formatDisplayPrice } from "../utils/format.js";
12
+ import { timeAgo } from "../utils/time.js";
13
+ function ListingCard({ order, inCart = false, onBuy, onCart, overflowMenu, compact = false }) {
14
+ const [imgError, setImgError] = useState(false);
15
+ const isListing = order.offer.itemType === "ERC721" || order.offer.itemType === "ERC1155";
16
+ const name = order.token?.name ?? `Token #${order.nftTokenId}`;
17
+ const image = order.token?.image ? ipfsToHttp(order.token.image) : null;
18
+ const assetHref = `/asset/${order.nftContract}/${order.nftTokenId}`;
19
+ const showActionBar = isListing && (onBuy || onCart || overflowMenu);
20
+ if (compact) {
21
+ return /* @__PURE__ */ jsx(MotionCard, { className: "card-base", children: /* @__PURE__ */ jsxs(Link, { href: assetHref, className: "block", children: [
22
+ /* @__PURE__ */ jsx("div", { className: "relative aspect-square bg-muted overflow-hidden", children: image && !imgError ? /* @__PURE__ */ jsx(Image, { src: image, alt: name, fill: true, unoptimized: true, sizes: "(max-width: 640px) 33vw, 20vw", className: "object-cover group-hover:scale-105 transition-transform duration-500", onError: () => setImgError(true) }) : /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-gradient-to-br from-brand-purple/15 to-brand-blue/15", children: /* @__PURE__ */ jsxs("span", { className: "text-xl font-mono text-muted-foreground", children: [
23
+ "#",
24
+ order.nftTokenId
25
+ ] }) }) }),
26
+ /* @__PURE__ */ jsxs("div", { className: "p-2.5 space-y-0.5", children: [
27
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold truncate", children: name }),
28
+ order.price?.formatted && /* @__PURE__ */ jsxs("p", { className: "text-[11px] font-bold price-value", children: [
29
+ formatDisplayPrice(order.price.formatted),
30
+ " ",
31
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground font-normal", children: order.price.currency })
32
+ ] }),
33
+ /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground", children: timeAgo(order.createdAt) })
34
+ ] })
35
+ ] }) });
36
+ }
37
+ return /* @__PURE__ */ jsx(MotionCard, { className: "card-base", children: /* @__PURE__ */ jsxs(Link, { href: assetHref, className: "block", children: [
38
+ /* @__PURE__ */ jsx("div", { className: "relative aspect-square bg-muted overflow-hidden", children: image && !imgError ? /* @__PURE__ */ jsx(Image, { src: image, alt: name, fill: true, unoptimized: true, sizes: "(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 25vw", className: "object-cover group-hover:scale-105 transition-transform duration-500", onError: () => setImgError(true) }) : /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-gradient-to-br from-brand-purple/15 to-brand-blue/15", children: /* @__PURE__ */ jsxs("span", { className: "text-2xl font-mono text-muted-foreground", children: [
39
+ "#",
40
+ order.nftTokenId
41
+ ] }) }) }),
42
+ /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-3", children: [
43
+ /* @__PURE__ */ jsxs("div", { children: [
44
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-base truncate leading-snug", children: name }),
45
+ order.token?.description ? /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground line-clamp-1 leading-snug mt-0.5", children: order.token.description }) : /* @__PURE__ */ jsxs("p", { className: "text-[11px] text-muted-foreground", children: [
46
+ "#",
47
+ order.nftTokenId
48
+ ] })
49
+ ] }),
50
+ order.price?.formatted && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
51
+ order.price.currency && /* @__PURE__ */ jsx(CurrencyIcon, { symbol: order.price.currency, size: 14 }),
52
+ /* @__PURE__ */ jsxs("p", { className: "text-lg font-bold price-value leading-none", children: [
53
+ formatDisplayPrice(order.price.formatted),
54
+ " ",
55
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground font-normal text-sm", children: order.price.currency })
56
+ ] })
57
+ ] }),
58
+ showActionBar && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
59
+ onBuy && /* @__PURE__ */ jsx("div", { className: "btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-9", children: /* @__PURE__ */ jsxs(
60
+ "button",
61
+ {
62
+ className: "w-full h-full rounded-[9px] bg-background flex items-center justify-center gap-1.5 text-xs font-semibold text-foreground hover:bg-muted/60 transition-all active:scale-[0.98]",
63
+ onClick: (e) => {
64
+ e.preventDefault();
65
+ onBuy(order);
66
+ },
67
+ children: [
68
+ /* @__PURE__ */ jsx(Zap, { className: "h-3.5 w-3.5 shrink-0" }),
69
+ " Buy"
70
+ ]
71
+ }
72
+ ) }),
73
+ onCart && /* @__PURE__ */ jsx(
74
+ "button",
75
+ {
76
+ className: cn(
77
+ "h-9 w-9 shrink-0 rounded-[9px] border flex items-center justify-center transition-colors",
78
+ inCart ? "border-brand-orange/50 bg-brand-orange/10 text-brand-orange" : "border-border bg-background hover:bg-muted text-foreground"
79
+ ),
80
+ onClick: (e) => {
81
+ e.preventDefault();
82
+ if (!inCart) onCart(order);
83
+ },
84
+ disabled: inCart,
85
+ "aria-label": inCart ? "Added to cart" : "Add to cart",
86
+ children: inCart ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(ShoppingCart, { className: "h-3.5 w-3.5" })
87
+ }
88
+ ),
89
+ overflowMenu
90
+ ] })
91
+ ] })
92
+ ] }) });
93
+ }
94
+ function ListingCardSkeleton() {
95
+ return /* @__PURE__ */ jsxs("div", { className: "card-base", children: [
96
+ /* @__PURE__ */ jsx("div", { className: "aspect-square w-full bg-muted animate-pulse" }),
97
+ /* @__PURE__ */ jsxs("div", { className: "p-3 space-y-2.5", children: [
98
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
99
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-3/4 bg-muted animate-pulse rounded" }),
100
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-1/2 bg-muted animate-pulse rounded" })
101
+ ] }),
102
+ /* @__PURE__ */ jsx("div", { className: "h-6 w-1/2 bg-muted animate-pulse rounded" }),
103
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-2/3 bg-muted animate-pulse rounded" })
104
+ ] })
105
+ ] });
106
+ }
107
+ export {
108
+ ListingCard,
109
+ ListingCardSkeleton
110
+ };
111
+ //# sourceMappingURL=listing-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/listing-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { ShoppingCart, Check, Zap } from \"lucide-react\";\nimport { MotionCard } from \"./motion-primitives.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { ipfsToHttp } from \"../utils/ipfs.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport type { ApiOrder } from \"@medialane/sdk\";\n\nexport interface ListingCardProps {\n order: ApiOrder;\n inCart?: boolean;\n onBuy?: (order: ApiOrder) => void;\n onCart?: (order: ApiOrder) => void;\n /** App passes a fully constructed <DropdownMenu> here */\n overflowMenu?: React.ReactNode;\n compact?: boolean;\n}\n\nexport function ListingCard({ order, inCart = false, onBuy, onCart, overflowMenu, compact = false }: ListingCardProps) {\n const [imgError, setImgError] = useState(false);\n const isListing = order.offer.itemType === \"ERC721\" || order.offer.itemType === \"ERC1155\";\n const name = order.token?.name ?? `Token #${order.nftTokenId}`;\n const image = order.token?.image ? ipfsToHttp(order.token.image) : null;\n const assetHref = `/asset/${order.nftContract}/${order.nftTokenId}`;\n\n const showActionBar = isListing && (onBuy || onCart || overflowMenu);\n\n // ─── Compact variant ──────────────────────────────────────────────────────\n if (compact) {\n return (\n <MotionCard className=\"card-base\">\n <Link href={assetHref} className=\"block\">\n <div className=\"relative aspect-square bg-muted overflow-hidden\">\n {image && !imgError ? (\n <Image src={image} alt={name} fill unoptimized sizes=\"(max-width: 640px) 33vw, 20vw\" className=\"object-cover group-hover:scale-105 transition-transform duration-500\" onError={() => setImgError(true)} />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center bg-gradient-to-br from-brand-purple/15 to-brand-blue/15\">\n <span className=\"text-xl font-mono text-muted-foreground\">#{order.nftTokenId}</span>\n </div>\n )}\n </div>\n <div className=\"p-2.5 space-y-0.5\">\n <p className=\"text-xs font-semibold truncate\">{name}</p>\n {order.price?.formatted && (\n <p className=\"text-[11px] font-bold price-value\">\n {formatDisplayPrice(order.price.formatted)} <span className=\"text-muted-foreground font-normal\">{order.price.currency}</span>\n </p>\n )}\n <p className=\"text-[10px] text-muted-foreground\">{timeAgo(order.createdAt)}</p>\n </div>\n </Link>\n </MotionCard>\n );\n }\n\n // ─── Full variant ─────────────────────────────────────────────────────────\n return (\n <MotionCard className=\"card-base\">\n <Link href={assetHref} className=\"block\">\n <div className=\"relative aspect-square bg-muted overflow-hidden\">\n {image && !imgError ? (\n <Image src={image} alt={name} fill unoptimized sizes=\"(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 25vw\" className=\"object-cover group-hover:scale-105 transition-transform duration-500\" onError={() => setImgError(true)} />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center bg-gradient-to-br from-brand-purple/15 to-brand-blue/15\">\n <span className=\"text-2xl font-mono text-muted-foreground\">#{order.nftTokenId}</span>\n </div>\n )}\n </div>\n\n <div className=\"p-4 space-y-3\">\n <div>\n <p className=\"font-semibold text-base truncate leading-snug\">{name}</p>\n {order.token?.description ? (\n <p className=\"text-[11px] text-muted-foreground line-clamp-1 leading-snug mt-0.5\">{order.token.description}</p>\n ) : (\n <p className=\"text-[11px] text-muted-foreground\">#{order.nftTokenId}</p>\n )}\n </div>\n\n {order.price?.formatted && (\n <div className=\"flex items-center gap-1.5\">\n {order.price.currency && <CurrencyIcon symbol={order.price.currency} size={14} />}\n <p className=\"text-lg font-bold price-value leading-none\">\n {formatDisplayPrice(order.price.formatted)} <span className=\"text-muted-foreground font-normal text-sm\">{order.price.currency}</span>\n </p>\n </div>\n )}\n\n {showActionBar && (\n <div className=\"flex items-center gap-1.5\">\n {onBuy && (\n <div className=\"btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-9\">\n <button\n className=\"w-full h-full rounded-[9px] bg-background flex items-center justify-center gap-1.5 text-xs font-semibold text-foreground hover:bg-muted/60 transition-all active:scale-[0.98]\"\n onClick={(e) => { e.preventDefault(); onBuy(order); }}\n >\n <Zap className=\"h-3.5 w-3.5 shrink-0\" /> Buy\n </button>\n </div>\n )}\n {onCart && (\n <button\n className={cn(\n \"h-9 w-9 shrink-0 rounded-[9px] border flex items-center justify-center transition-colors\",\n inCart\n ? \"border-brand-orange/50 bg-brand-orange/10 text-brand-orange\"\n : \"border-border bg-background hover:bg-muted text-foreground\"\n )}\n onClick={(e) => { e.preventDefault(); if (!inCart) onCart(order); }}\n disabled={inCart}\n aria-label={inCart ? \"Added to cart\" : \"Add to cart\"}\n >\n {inCart ? <Check className=\"h-3.5 w-3.5\" /> : <ShoppingCart className=\"h-3.5 w-3.5\" />}\n </button>\n )}\n {overflowMenu}\n </div>\n )}\n </div>\n </Link>\n </MotionCard>\n );\n}\n\nexport function ListingCardSkeleton() {\n return (\n <div className=\"card-base\">\n <div className=\"aspect-square w-full bg-muted animate-pulse\" />\n <div className=\"p-3 space-y-2.5\">\n <div className=\"space-y-1\">\n <div className=\"h-4 w-3/4 bg-muted animate-pulse rounded\" />\n <div className=\"h-3 w-1/2 bg-muted animate-pulse rounded\" />\n </div>\n <div className=\"h-6 w-1/2 bg-muted animate-pulse rounded\" />\n <div className=\"h-3 w-2/3 bg-muted animate-pulse rounded\" />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ "use client";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var motion_primitives_exports = {};
21
+ __export(motion_primitives_exports, {
22
+ EASE_OUT: () => EASE_OUT,
23
+ FadeIn: () => FadeIn,
24
+ KineticWords: () => KineticWords,
25
+ MotionCard: () => MotionCard,
26
+ SPRING: () => SPRING,
27
+ Stagger: () => Stagger,
28
+ StaggerItem: () => StaggerItem
29
+ });
30
+ module.exports = __toCommonJS(motion_primitives_exports);
31
+ var import_jsx_runtime = require("react/jsx-runtime");
32
+ var import_framer_motion = require("framer-motion");
33
+ const SPRING = { type: "spring", stiffness: 400, damping: 28 };
34
+ const EASE_OUT = [0.25, 0.46, 0.45, 0.94];
35
+ function MotionCard({ children, className, ...props }) {
36
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
37
+ import_framer_motion.motion.div,
38
+ {
39
+ className,
40
+ whileTap: { scale: 0.96 },
41
+ transition: SPRING,
42
+ ...props,
43
+ children
44
+ }
45
+ );
46
+ }
47
+ function FadeIn({ children, className, delay = 0, y = 20 }) {
48
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
49
+ import_framer_motion.motion.div,
50
+ {
51
+ className,
52
+ initial: { opacity: 0, y },
53
+ whileInView: { opacity: 1, y: 0 },
54
+ viewport: { once: true, margin: "-60px" },
55
+ transition: { duration: 0.5, delay, ease: EASE_OUT },
56
+ children
57
+ }
58
+ );
59
+ }
60
+ function Stagger({ children, className, staggerDelay = 0.07 }) {
61
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
62
+ import_framer_motion.motion.div,
63
+ {
64
+ className,
65
+ initial: "hidden",
66
+ whileInView: "show",
67
+ viewport: { once: true, margin: "-60px" },
68
+ variants: {
69
+ hidden: {},
70
+ show: { transition: { staggerChildren: staggerDelay } }
71
+ },
72
+ children
73
+ }
74
+ );
75
+ }
76
+ function StaggerItem({ children, className }) {
77
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
78
+ import_framer_motion.motion.div,
79
+ {
80
+ className,
81
+ variants: {
82
+ hidden: { opacity: 0, y: 20 },
83
+ show: { opacity: 1, y: 0, transition: { duration: 0.45, ease: EASE_OUT } }
84
+ },
85
+ children
86
+ }
87
+ );
88
+ }
89
+ function KineticWords({ text, className }) {
90
+ const words = text.split(" ");
91
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
92
+ import_framer_motion.motion.span,
93
+ {
94
+ className,
95
+ initial: "hidden",
96
+ animate: "show",
97
+ variants: {
98
+ hidden: {},
99
+ show: { transition: { staggerChildren: 0.08, delayChildren: 0.1 } }
100
+ },
101
+ children: words.map((word, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
102
+ import_framer_motion.motion.span,
103
+ {
104
+ className: "inline-block mr-[0.25em]",
105
+ variants: {
106
+ hidden: { opacity: 0, y: 24, rotateX: -20 },
107
+ show: { opacity: 1, y: 0, rotateX: 0, transition: { duration: 0.5, ease: EASE_OUT } }
108
+ },
109
+ children: word
110
+ },
111
+ i
112
+ ))
113
+ }
114
+ );
115
+ }
116
+ // Annotate the CommonJS export names for ESM import in node:
117
+ 0 && (module.exports = {
118
+ EASE_OUT,
119
+ FadeIn,
120
+ KineticWords,
121
+ MotionCard,
122
+ SPRING,
123
+ Stagger,
124
+ StaggerItem
125
+ });
126
+ //# sourceMappingURL=motion-primitives.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/motion-primitives.tsx"],"sourcesContent":["\"use client\";\n\nimport { motion, type HTMLMotionProps } from \"framer-motion\";\n\nexport const SPRING = { type: \"spring\", stiffness: 400, damping: 28 } as const;\nexport const EASE_OUT = [0.25, 0.46, 0.45, 0.94] as const;\n\n// ─── Press-able card wrapper ──────────────────────────────────────────────────\n\ninterface MotionCardProps extends HTMLMotionProps<\"div\"> {\n children: React.ReactNode;\n}\n\nexport function MotionCard({ children, className, ...props }: MotionCardProps) {\n return (\n <motion.div\n className={className}\n whileTap={{ scale: 0.96 }}\n transition={SPRING}\n {...props}\n >\n {children}\n </motion.div>\n );\n}\n\n// ─── Scroll-triggered fade-in ─────────────────────────────────────────────────\n\ninterface FadeInProps {\n children: React.ReactNode;\n className?: string;\n delay?: number;\n y?: number;\n}\n\nexport function FadeIn({ children, className, delay = 0, y = 20 }: FadeInProps) {\n return (\n <motion.div\n className={className}\n initial={{ opacity: 0, y }}\n whileInView={{ opacity: 1, y: 0 }}\n viewport={{ once: true, margin: \"-60px\" }}\n transition={{ duration: 0.5, delay, ease: EASE_OUT }}\n >\n {children}\n </motion.div>\n );\n}\n\n// ─── Stagger container ────────────────────────────────────────────────────────\n\ninterface StaggerProps {\n children: React.ReactNode;\n className?: string;\n staggerDelay?: number;\n}\n\nexport function Stagger({ children, className, staggerDelay = 0.07 }: StaggerProps) {\n return (\n <motion.div\n className={className}\n initial=\"hidden\"\n whileInView=\"show\"\n viewport={{ once: true, margin: \"-60px\" }}\n variants={{\n hidden: {},\n show: { transition: { staggerChildren: staggerDelay } },\n }}\n >\n {children}\n </motion.div>\n );\n}\n\nexport function StaggerItem({ children, className }: { children: React.ReactNode; className?: string }) {\n return (\n <motion.div\n className={className}\n variants={{\n hidden: { opacity: 0, y: 20 },\n show: { opacity: 1, y: 0, transition: { duration: 0.45, ease: EASE_OUT } },\n }}\n >\n {children}\n </motion.div>\n );\n}\n\n// ─── Kinetic headline words ───────────────────────────────────────────────────\n\nexport function KineticWords({ text, className }: { text: string; className?: string }) {\n const words = text.split(\" \");\n return (\n <motion.span\n className={className}\n initial=\"hidden\"\n animate=\"show\"\n variants={{\n hidden: {},\n show: { transition: { staggerChildren: 0.08, delayChildren: 0.1 } },\n }}\n >\n {words.map((word, i) => (\n <motion.span\n key={i}\n className=\"inline-block mr-[0.25em]\"\n variants={{\n hidden: { opacity: 0, y: 24, rotateX: -20 },\n show: { opacity: 1, y: 0, rotateX: 0, transition: { duration: 0.5, ease: EASE_OUT } },\n }}\n >\n {word}\n </motion.span>\n ))}\n </motion.span>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeI;AAbJ,2BAA6C;AAEtC,MAAM,SAAS,EAAE,MAAM,UAAU,WAAW,KAAK,SAAS,GAAG;AAC7D,MAAM,WAAW,CAAC,MAAM,MAAM,MAAM,IAAI;AAQxC,SAAS,WAAW,EAAE,UAAU,WAAW,GAAG,MAAM,GAAoB;AAC7E,SACE;AAAA,IAAC,4BAAO;AAAA,IAAP;AAAA,MACC;AAAA,MACA,UAAU,EAAE,OAAO,KAAK;AAAA,MACxB,YAAY;AAAA,MACX,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAWO,SAAS,OAAO,EAAE,UAAU,WAAW,QAAQ,GAAG,IAAI,GAAG,GAAgB;AAC9E,SACE;AAAA,IAAC,4BAAO;AAAA,IAAP;AAAA,MACC;AAAA,MACA,SAAS,EAAE,SAAS,GAAG,EAAE;AAAA,MACzB,aAAa,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,MAChC,UAAU,EAAE,MAAM,MAAM,QAAQ,QAAQ;AAAA,MACxC,YAAY,EAAE,UAAU,KAAK,OAAO,MAAM,SAAS;AAAA,MAElD;AAAA;AAAA,EACH;AAEJ;AAUO,SAAS,QAAQ,EAAE,UAAU,WAAW,eAAe,KAAK,GAAiB;AAClF,SACE;AAAA,IAAC,4BAAO;AAAA,IAAP;AAAA,MACC;AAAA,MACA,SAAQ;AAAA,MACR,aAAY;AAAA,MACZ,UAAU,EAAE,MAAM,MAAM,QAAQ,QAAQ;AAAA,MACxC,UAAU;AAAA,QACR,QAAQ,CAAC;AAAA,QACT,MAAM,EAAE,YAAY,EAAE,iBAAiB,aAAa,EAAE;AAAA,MACxD;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAEO,SAAS,YAAY,EAAE,UAAU,UAAU,GAAsD;AACtG,SACE;AAAA,IAAC,4BAAO;AAAA,IAAP;AAAA,MACC;AAAA,MACA,UAAU;AAAA,QACR,QAAQ,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,QAC5B,MAAM,EAAE,SAAS,GAAG,GAAG,GAAG,YAAY,EAAE,UAAU,MAAM,MAAM,SAAS,EAAE;AAAA,MAC3E;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAIO,SAAS,aAAa,EAAE,MAAM,UAAU,GAAyC;AACtF,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,SACE;AAAA,IAAC,4BAAO;AAAA,IAAP;AAAA,MACC;AAAA,MACA,SAAQ;AAAA,MACR,SAAQ;AAAA,MACR,UAAU;AAAA,QACR,QAAQ,CAAC;AAAA,QACT,MAAM,EAAE,YAAY,EAAE,iBAAiB,MAAM,eAAe,IAAI,EAAE;AAAA,MACpE;AAAA,MAEC,gBAAM,IAAI,CAAC,MAAM,MAChB;AAAA,QAAC,4BAAO;AAAA,QAAP;AAAA,UAEC,WAAU;AAAA,UACV,UAAU;AAAA,YACR,QAAQ,EAAE,SAAS,GAAG,GAAG,IAAI,SAAS,IAAI;AAAA,YAC1C,MAAM,EAAE,SAAS,GAAG,GAAG,GAAG,SAAS,GAAG,YAAY,EAAE,UAAU,KAAK,MAAM,SAAS,EAAE;AAAA,UACtF;AAAA,UAEC;AAAA;AAAA,QAPI;AAAA,MAQP,CACD;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -0,0 +1,36 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { HTMLMotionProps } from 'framer-motion';
3
+
4
+ declare const SPRING: {
5
+ readonly type: "spring";
6
+ readonly stiffness: 400;
7
+ readonly damping: 28;
8
+ };
9
+ declare const EASE_OUT: readonly [0.25, 0.46, 0.45, 0.94];
10
+ interface MotionCardProps extends HTMLMotionProps<"div"> {
11
+ children: React.ReactNode;
12
+ }
13
+ declare function MotionCard({ children, className, ...props }: MotionCardProps): react_jsx_runtime.JSX.Element;
14
+ interface FadeInProps {
15
+ children: React.ReactNode;
16
+ className?: string;
17
+ delay?: number;
18
+ y?: number;
19
+ }
20
+ declare function FadeIn({ children, className, delay, y }: FadeInProps): react_jsx_runtime.JSX.Element;
21
+ interface StaggerProps {
22
+ children: React.ReactNode;
23
+ className?: string;
24
+ staggerDelay?: number;
25
+ }
26
+ declare function Stagger({ children, className, staggerDelay }: StaggerProps): react_jsx_runtime.JSX.Element;
27
+ declare function StaggerItem({ children, className }: {
28
+ children: React.ReactNode;
29
+ className?: string;
30
+ }): react_jsx_runtime.JSX.Element;
31
+ declare function KineticWords({ text, className }: {
32
+ text: string;
33
+ className?: string;
34
+ }): react_jsx_runtime.JSX.Element;
35
+
36
+ export { EASE_OUT, FadeIn, KineticWords, MotionCard, SPRING, Stagger, StaggerItem };
@@ -0,0 +1,36 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { HTMLMotionProps } from 'framer-motion';
3
+
4
+ declare const SPRING: {
5
+ readonly type: "spring";
6
+ readonly stiffness: 400;
7
+ readonly damping: 28;
8
+ };
9
+ declare const EASE_OUT: readonly [0.25, 0.46, 0.45, 0.94];
10
+ interface MotionCardProps extends HTMLMotionProps<"div"> {
11
+ children: React.ReactNode;
12
+ }
13
+ declare function MotionCard({ children, className, ...props }: MotionCardProps): react_jsx_runtime.JSX.Element;
14
+ interface FadeInProps {
15
+ children: React.ReactNode;
16
+ className?: string;
17
+ delay?: number;
18
+ y?: number;
19
+ }
20
+ declare function FadeIn({ children, className, delay, y }: FadeInProps): react_jsx_runtime.JSX.Element;
21
+ interface StaggerProps {
22
+ children: React.ReactNode;
23
+ className?: string;
24
+ staggerDelay?: number;
25
+ }
26
+ declare function Stagger({ children, className, staggerDelay }: StaggerProps): react_jsx_runtime.JSX.Element;
27
+ declare function StaggerItem({ children, className }: {
28
+ children: React.ReactNode;
29
+ className?: string;
30
+ }): react_jsx_runtime.JSX.Element;
31
+ declare function KineticWords({ text, className }: {
32
+ text: string;
33
+ className?: string;
34
+ }): react_jsx_runtime.JSX.Element;
35
+
36
+ export { EASE_OUT, FadeIn, KineticWords, MotionCard, SPRING, Stagger, StaggerItem };