@mohasinac/appkit 4.52.0 → 4.52.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.build-stamp.json +3 -3
- package/dist/_internal/client/features/digital-code/CodeRevealPanel.js +4 -4
- package/dist/_internal/server/features/products/list-public.js +37 -1
- package/dist/features/about/components/PolicyPageView.js +1 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +2 -2
- package/dist/features/auth/components/SocialAuthButtons.js +1 -1
- package/dist/features/categories/components/CategoryBundlesListing.js +1 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +8 -7
- package/dist/features/categories/constants/category-tabs.d.ts +9 -1
- package/dist/features/categories/constants/category-tabs.js +11 -1
- package/dist/features/checkout/components/CheckoutStepper.js +1 -1
- package/dist/features/faq/components/FAQAccordion.js +1 -1
- package/dist/features/filters/FilterFacetSection.js +1 -1
- package/dist/features/filters/RangeFilter.js +1 -1
- package/dist/features/filters/SwitchFilter.js +1 -1
- package/dist/features/homepage/components/BeforeAfterCard.js +2 -2
- package/dist/features/homepage/components/CharacterHotspot.js +1 -1
- package/dist/features/homepage/components/FAQSection.js +1 -1
- package/dist/features/homepage/components/HeroBanner.js +1 -1
- package/dist/features/homepage/components/HeroCarousel.js +4 -4
- package/dist/features/homepage/components/HowItWorksSection.js +1 -1
- package/dist/features/homepage/components/SectionCarousel.js +1 -1
- package/dist/features/homepage/components/SecurityHighlightsSection.js +1 -1
- package/dist/features/homepage/components/TrustBadges.js +1 -1
- package/dist/features/homepage/components/WelcomeSection.js +1 -1
- package/dist/features/layout/BottomActions.js +1 -1
- package/dist/features/live/components/LiveItemDetailPageView.js +1 -1
- package/dist/features/products/hooks/useProducts.js +18 -1
- package/dist/features/reviews/components/ReviewDetailShell.js +2 -1
- package/dist/features/reviews/components/ReviewSummary.js +1 -1
- package/dist/features/tester/seed-data/_happy-path.js +1 -1
- package/dist/features/tester/seed-data/authored/admin__catalog-listings.js +1 -1
- package/dist/features/tester/seed-data/authored/content-discovery__category-brand-relations.js +3 -3
- package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.js +152 -0
- package/dist/features/tester/seed-data/authored/design-ux__rich-text-readability.d.ts +2 -0
- package/dist/features/tester/seed-data/authored/design-ux__rich-text-readability.js +84 -0
- package/dist/features/tester/seed-data/authored/index.js +4 -0
- package/dist/features/tester/seed-data/authored/public-pages__core-listing-pages.js +2 -2
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +77 -3
- package/dist/styles.css +73 -0
- package/dist/ui/rich-text/RichText.style.css +73 -0
- package/package.json +1 -1
package/dist/.build-stamp.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"stampVersion": 1,
|
|
3
|
-
"version": "4.52.
|
|
4
|
-
"head": "
|
|
3
|
+
"version": "4.52.2",
|
|
4
|
+
"head": "797172e6302080e045fb4ec752483fc0f7f09968",
|
|
5
5
|
"branch": "main",
|
|
6
6
|
"dirty": false,
|
|
7
|
-
"builtAt": "2026-10-
|
|
7
|
+
"builtAt": "2026-10-14T23:59:51.686Z"
|
|
8
8
|
}
|
|
@@ -36,9 +36,9 @@ export function CodeRevealPanel({ orderId, redemptionInstructions, fetchCode, })
|
|
|
36
36
|
setCopied(true);
|
|
37
37
|
setTimeout(() => setCopied(false), 2000);
|
|
38
38
|
}
|
|
39
|
-
return (_jsx(Div, { className: `border border-border bg-
|
|
39
|
+
return (_jsx(Div, { className: `border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-raised)] ${__P.p4}`, rounded: "lg", children: _jsxs(Stack, { gap: "sm", children: [_jsx(Text, { weight: "medium", children: revealed && (revealed.contentKind ?? "code") !== "code"
|
|
40
40
|
? "Your Digital Content"
|
|
41
|
-
: "Your Digital Code" }), !revealed ? (_jsxs(Stack, { gap: "sm", children: [error && _jsx(Text, { className: "text-
|
|
41
|
+
: "Your Digital Code" }), !revealed ? (_jsxs(Stack, { gap: "sm", children: [error && _jsx(Text, { className: "text-error", size: "sm", children: error }), _jsx(Button, { type: "button", variant: "primary", size: "lg", isLoading: pending, disabled: pending, onClick: handleReveal, className: "w-full", children: "Reveal Code" })] })) : (_jsxs(Stack, { gap: "sm", children: [(revealed.contentKind ?? "code") === "code" ? (_jsxs(Row, { textSize: "lg", className: "border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] font-mono", padding: "inlineSm", align: "center", gap: "sm", rounded: "md", children: [_jsx(Span, { className: "flex-1 select-all", children: revealed.code }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: handleCopy, className: "shrink-0", children: copied ? "Copied!" : "Copy" })] })) : (
|
|
42
42
|
/*
|
|
43
43
|
* 🛑 A LINK, not an <img>/<MediaImage>. Rendering the asset inline
|
|
44
44
|
* would need a URL a browser can GET without our session
|
|
@@ -53,8 +53,8 @@ export function CodeRevealPanel({ orderId, redemptionInstructions, fetchCode, })
|
|
|
53
53
|
* the browser own the download, including resume and the file
|
|
54
54
|
* name, and never materialises the bytes in JS memory.
|
|
55
55
|
*/
|
|
56
|
-
_jsxs(Row, { className: "border border-border bg-
|
|
56
|
+
_jsxs(Row, { className: "border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)]", padding: "inlineSm", align: "center", gap: "sm", rounded: "md", children: [_jsx(Span, { className: "flex-1 truncate", children: revealed.fileName ?? "Your download" }), _jsx(Button, { type: "button", variant: "primary", size: "sm", className: "shrink-0", onClick: () => {
|
|
57
57
|
if (revealed.downloadUrl)
|
|
58
58
|
window.location.assign(revealed.downloadUrl);
|
|
59
|
-
}, children: "Download" })] })), (redemptionInstructions ?? revealed.redemptionInstructions) && (_jsx(Text, { className: "text-muted
|
|
59
|
+
}, children: "Download" })] })), (redemptionInstructions ?? revealed.redemptionInstructions) && (_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: redemptionInstructions ?? revealed.redemptionInstructions }))] }))] }) }));
|
|
60
60
|
}
|
|
@@ -39,6 +39,7 @@ import { normalizeError } from "../../../../errors/normalize.js";
|
|
|
39
39
|
import { serverLogger } from "../../../../monitoring/server-logger.js";
|
|
40
40
|
import { PRODUCT_FIELDS } from "../../../../constants/field-names.js";
|
|
41
41
|
import { TABLE_KEYS } from "../../../../constants/table-keys.js";
|
|
42
|
+
import { LISTING_PARAM_NAMES } from "../../../../utils/listing-params.js";
|
|
42
43
|
import { sortBy } from "../../../../constants/sort.js";
|
|
43
44
|
import { SIEVE_OP, sieveAnd, sieveFilter, expandSieveParam, } from "../../../../utils/sieve-builder.js";
|
|
44
45
|
import { planSearchTxt } from "../../../../utils/search-txt-query.js";
|
|
@@ -228,7 +229,42 @@ export function parsePublicProductParams(params, defaults) {
|
|
|
228
229
|
dateTo: get(TABLE_KEYS.DATE_TO) || undefined,
|
|
229
230
|
page: num(get(TABLE_KEYS.PAGE)) ?? DEFAULT_PAGE,
|
|
230
231
|
pageSize: num(get(TABLE_KEYS.PAGE_SIZE)) ?? defaults?.pageSize ?? DEFAULT_PAGE_SIZE,
|
|
231
|
-
|
|
232
|
+
/*
|
|
233
|
+
* 🛑 THREE SPELLINGS, and the middle one is what every client actually
|
|
234
|
+
* sends. This read `get(TABLE_KEYS.SORT)` — i.e. `"sort"` — alone, while
|
|
235
|
+
* `useProducts` puts the value on the wire as `sorts`
|
|
236
|
+
* (`sp.set("sorts", params.sort)`). So EVERY client-side fetch from a
|
|
237
|
+
* product listing page arrived with a sort this parser could not see, fell
|
|
238
|
+
* through to `DEFAULT_SORTS` (`-createdAt`), and came back newest-first
|
|
239
|
+
* while the dropdown displayed the sort the user had picked.
|
|
240
|
+
*
|
|
241
|
+
* Measured against the live dev server — identical row order for
|
|
242
|
+
* `?sorts=auctionEndDate` and for no sort at all, versus a correctly
|
|
243
|
+
* ordered result for `?sort=auctionEndDate`.
|
|
244
|
+
*
|
|
245
|
+
* It survived because the SSR paint IS correct: the listing views pass
|
|
246
|
+
* `sorts` through `defaults`, and an anonymous visitor with `initialData`
|
|
247
|
+
* never refetches (`staleTime: Infinity`), so the first paint is right and
|
|
248
|
+
* stays right. The bug only surfaces once something refetches — touching
|
|
249
|
+
* the Sort control, paging, or simply being signed in as a tester/admin,
|
|
250
|
+
* who are handed no `initialData` by design. That is Root Cause #30 with
|
|
251
|
+
* the two sides swapped: not a default that disagrees, a KEY that does.
|
|
252
|
+
*
|
|
253
|
+
* `LISTING_PARAM_NAMES.sorts` already settled this question — short `s`,
|
|
254
|
+
* long `sorts`, legacy `sort` — and `/api/stores`, `/api/events` and
|
|
255
|
+
* `/api/faqs` all accept the full set through `parseListingParams`.
|
|
256
|
+
* `/api/products` was the one listing route that did not, so it is aligned
|
|
257
|
+
* here rather than by changing what one client sends: any OTHER caller
|
|
258
|
+
* using the documented spelling was equally broken and is now fixed too.
|
|
259
|
+
*
|
|
260
|
+
* Order is widest-to-narrowest to match `parseListingParams`: short form
|
|
261
|
+
* wins, then the long form, then the legacy key.
|
|
262
|
+
*/
|
|
263
|
+
sorts: get(LISTING_PARAM_NAMES.sorts.short) ||
|
|
264
|
+
get(LISTING_PARAM_NAMES.sorts.long) ||
|
|
265
|
+
get(TABLE_KEYS.SORT) ||
|
|
266
|
+
defaults?.sorts ||
|
|
267
|
+
DEFAULT_SORTS,
|
|
232
268
|
};
|
|
233
269
|
}
|
|
234
270
|
// ---------------------------------------------------------------------------
|
|
@@ -93,5 +93,5 @@ export async function PolicyPageView({ policy, }) {
|
|
|
93
93
|
}));
|
|
94
94
|
return (_jsxs(Div, { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", children: [_jsx(Section, { color: "inverse", tone: "accent-banner", padding: "banner", children: _jsxs(Div, { className: `${page.container.sm}`, children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-3", children: t("title") }), _jsx(Text, { color: "inverse", variant: "none", className: "/80", size: "sm", children: t("lastUpdated") })] }) }), _jsxs(Div, { className: `${page.container.sm}`, padding: "content-banner", children: [adminHtml ? (
|
|
95
95
|
/* Admin-set HTML takes priority */
|
|
96
|
-
_jsx(Div, { className: "prose
|
|
96
|
+
_jsx(Div, { className: "prose max-w-none", dangerouslySetInnerHTML: { __html: adminHtml } })) : (_jsxs(_Fragment, { children: [t.has("intro") && (_jsx(Text, { variant: "secondary", className: "mb-10 leading-relaxed", size: "base", children: t("intro") })), _jsx(Stack, { gap: "xl", children: sections.map((section, i) => (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-3", children: section.heading }), _jsx(Text, { variant: "secondary", className: "leading-relaxed whitespace-pre-line", children: section.body })] }, i))) })] })), relatedLinks.length > 0 && (_jsxs(Div, { className: `mt-14 border-t`, border: "default", padding: "t-xl", children: [_jsx(Heading, { level: 3, className: "mb-3 uppercase tracking-wide", color: "muted", size: "sm", weight: "semibold", children: t("relatedTitle") }), _jsx(Row, { wrap: true, gap: "md", children: relatedLinks.map((l) => (_jsx(TextLink, { href: l.href, variant: "muted", size: "sm", children: l.label }, l.href))) })] }))] })] }));
|
|
97
97
|
}
|
|
@@ -25,11 +25,11 @@ function renderAuctionCardHero(props) {
|
|
|
25
25
|
}
|
|
26
26
|
function renderAuctionCardInfoList(props) {
|
|
27
27
|
const { product, auctionHref, displayBid, bidCount, isEnded, remaining, inWishlist, wishlistLoading, wishlistActions, countdownClass, mergedLabels, handleWishlist, handleNavigate } = props;
|
|
28
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Row, { className: "min-w-0", align: "start", justify: "between", gap: "sm", children: [_jsx(TextLink, { href: auctionHref ?? "#", className: `flex-1 leading-snug transition-colors hover:text-primary`, color: "primary", truncate: 2, size: "sm", weight: "medium", children: product.title }), wishlistActions ? (_jsx(WishlistHeartButton, { size: "inline", inWishlist: inWishlist, isLoading: wishlistLoading, addLabel: mergedLabels.addToWishlist, removeLabel: mergedLabels.removeFromWishlist, onToggle: handleWishlist })) : null] }), _jsx(CardStoreLine, { storeName: product.storeName, storeId: product.storeId }), _jsxs(Row, { align: "center", gap: "sm", wrap: true, children: [_jsx(Text, { className: "text-primary", size: "sm", weight: "bold", children: _jsx(GatedPrice, { label: "Sign in to see the bid", children: formatCurrency(displayBid, getDefaultCurrency()) }) }), _jsxs(Div, { layout: "inline-flex", gap: "1", textWeight: "semibold", className: `
|
|
28
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Row, { className: "min-w-0", align: "start", justify: "between", gap: "sm", children: [_jsx(TextLink, { href: auctionHref ?? "#", className: `flex-1 leading-snug transition-colors hover:text-primary`, color: "primary", truncate: 2, size: "sm", weight: "medium", children: product.title }), wishlistActions ? (_jsx(WishlistHeartButton, { size: "inline", inWishlist: inWishlist, isLoading: wishlistLoading, addLabel: mergedLabels.addToWishlist, removeLabel: mergedLabels.removeFromWishlist, onToggle: handleWishlist })) : null] }), _jsx(CardStoreLine, { storeName: product.storeName, storeId: product.storeId }), _jsxs(Row, { align: "center", gap: "sm", wrap: true, children: [_jsx(Text, { className: "text-primary", size: "sm", weight: "bold", children: _jsx(GatedPrice, { label: "Sign in to see the bid", children: formatCurrency(displayBid, getDefaultCurrency()) }) }), _jsxs(Div, { layout: "inline-flex", gap: "1", textWeight: "semibold", align: "center", className: `py-[0.125rem] text-[11px] ${countdownClass}`, padding: "x-xs", rounded: "full", children: [_jsx(Clock, { className: "h-2.5 w-2.5" }), _jsx(Span, { children: formatCountdownLabel(remaining, mergedLabels.ended) })] }), bidCount > 0 && _jsx(Caption, { className: "text-[11px]", children: mergedLabels.totalBids(bidCount) })] }), !isEnded && (_jsxs(Button, { gap: "xs", type: "button", variant: "warning", size: "sm", textSize: "xs", className: "self-start px-[0.625rem] mt-0.5", onClick: handleNavigate, children: [_jsx(Gavel, { className: "h-3 w-3" }), _jsx(Span, { children: mergedLabels.placeBid })] }))] }));
|
|
29
29
|
}
|
|
30
30
|
function renderAuctionCardInfoGrid(props) {
|
|
31
31
|
const { product, auctionHref, displayBid, bidCount, hasCurrentBid, isEnded, remaining, resolvedBuyoutPrice, inWishlist, wishlistLoading, wishlistActions, countdownClass, mergedLabels, handleWishlist, handleNavigate } = props;
|
|
32
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Row, { align: "start", gap: "sm", children: [_jsx(TextLink, { href: auctionHref ?? "#", className: "min-w-0 flex-1 leading-snug transition-colors hover:text-primary", color: "primary", size: "sm", weight: "medium", children: product.title }), wishlistActions ? (_jsx(WishlistHeartButton, { size: "inline", inWishlist: inWishlist, isLoading: wishlistLoading, addLabel: mergedLabels.addToWishlist, removeLabel: mergedLabels.removeFromWishlist, onToggle: handleWishlist })) : null] }), _jsx(CardStoreLine, { storeName: product.storeName, storeId: product.storeId }), _jsxs(Div, { children: [_jsx(Caption, { children: isEnded && hasCurrentBid ? mergedLabels.winningBid : hasCurrentBid ? mergedLabels.currentBid : mergedLabels.startingBid }), _jsx(Text, { className: "leading-none text-primary", size: "base", weight: "bold", children: _jsx(GatedPrice, { label: "Sign in to see the bid", children: formatCurrency(displayBid, getDefaultCurrency()) }) }), isEnded && product.winnerDisplayName && (_jsxs(Caption, { className: "mt-0.5", color: "muted", children: [mergedLabels.wonBy, ": ", maskDisplayName(product.winnerDisplayName)] }))] }), _jsxs(Row, { wrap: true, justify: "between", gap: "sm", className: "gap-x-2 gap-y-1", children: [_jsxs(Div, { layout: "inline-flex", gap: "1", textWeight: "semibold", textSize: "xs",
|
|
32
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Row, { align: "start", gap: "sm", children: [_jsx(TextLink, { href: auctionHref ?? "#", className: "min-w-0 flex-1 leading-snug transition-colors hover:text-primary", color: "primary", size: "sm", weight: "medium", children: product.title }), wishlistActions ? (_jsx(WishlistHeartButton, { size: "inline", inWishlist: inWishlist, isLoading: wishlistLoading, addLabel: mergedLabels.addToWishlist, removeLabel: mergedLabels.removeFromWishlist, onToggle: handleWishlist })) : null] }), _jsx(CardStoreLine, { storeName: product.storeName, storeId: product.storeId }), _jsxs(Div, { children: [_jsx(Caption, { children: isEnded && hasCurrentBid ? mergedLabels.winningBid : hasCurrentBid ? mergedLabels.currentBid : mergedLabels.startingBid }), _jsx(Text, { className: "leading-none text-primary", size: "base", weight: "bold", children: _jsx(GatedPrice, { label: "Sign in to see the bid", children: formatCurrency(displayBid, getDefaultCurrency()) }) }), isEnded && product.winnerDisplayName && (_jsxs(Caption, { className: "mt-0.5", color: "muted", children: [mergedLabels.wonBy, ": ", maskDisplayName(product.winnerDisplayName)] }))] }), _jsxs(Row, { wrap: true, justify: "between", gap: "sm", className: "gap-x-2 gap-y-1", children: [_jsxs(Div, { layout: "inline-flex", gap: "1", textWeight: "semibold", textSize: "xs", align: "center", className: `${countdownClass}`, paddingY: "y-2xs", paddingX: "x-xs", rounded: "full", children: [_jsx(Clock, { className: "h-3 w-3" }), _jsx(Span, { children: formatCountdownLabel(remaining, mergedLabels.ended) })] }), _jsx(Caption, { children: mergedLabels.totalBids(bidCount) })] }), _jsx(Row, { wrap: true, gap: "xs", className: "mt-auto", children: isEnded ? (_jsx(Button, { gap: "xs", type: "button", variant: "ghost", size: "sm", textSize: "xs", paddingX: "xs", className: "flex-1 cursor-not-allowed opacity-60", disabled: true, children: _jsx(Span, { children: mergedLabels.ended }) })) : (_jsxs(_Fragment, { children: [_jsxs(Button, { gap: "xs", type: "button", variant: "warning", size: "sm", textSize: "xs", paddingX: "xs", className: "flex-1", onClick: handleNavigate, children: [_jsx(Gavel, { className: "h-3 w-3" }), _jsx(Span, { children: mergedLabels.placeBid })] }), resolvedBuyoutPrice ? (
|
|
33
33
|
/* `secondary`, not `danger` — this button only navigates to the
|
|
34
34
|
PDP, and `danger` is reserved for destructive actions (Rule #7
|
|
35
35
|
kinds). ACTIONS.AUCTION["buy-it-now"] is itself `secondary`. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Button, Div, Row, Span } from "../../../ui/index.js";
|
|
3
3
|
export function SocialAuthButtons({ onGoogle, disabled, dividerLabel, googleLabel, }) {
|
|
4
|
-
return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: "relative", children: [_jsx(Row, { className: "absolute inset-0", align: "center", children: _jsx(Div, { className: "w-full border-t border-neutral-200" }) }), _jsx(Row, { textSize: "sm", className: "relative", justify: "center", children: _jsx(Span, { padding: "x-xs", surface: "default", color: "muted", children: dividerLabel }) })] }), _jsx(Div, { layout: "grid", gap: "3", className: "grid-cols-1", children: _jsxs(Button, { rounded: "md", type: "button", onClick: onGoogle, disabled: disabled, variant: "outline", paddingX: "md", paddingY: "sm", textSize: "sm", weight: "medium",
|
|
4
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: "relative", children: [_jsx(Row, { className: "absolute inset-0", align: "center", children: _jsx(Div, { className: "w-full border-t border-neutral-200" }) }), _jsx(Row, { textSize: "sm", className: "relative", justify: "center", children: _jsx(Span, { padding: "x-xs", surface: "default", color: "muted", children: dividerLabel }) })] }), _jsx(Div, { layout: "grid", gap: "3", className: "grid-cols-1", children: _jsxs(Button, { rounded: "md", type: "button", onClick: onGoogle, disabled: disabled, variant: "outline", paddingX: "md", paddingY: "sm", textSize: "sm", weight: "medium", justify: "center", className: "border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] text-[var(--appkit-color-text)] hover:bg-surface-hover disabled:cursor-not-allowed disabled:opacity-50", children: [_jsxs("svg", { className: "mr-2 h-5 w-5 shrink-0", viewBox: "0 0 24 24", "aria-hidden": "true", children: [_jsx("path", { fill: "currentColor", d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" }), _jsx("path", { fill: "currentColor", d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" }), _jsx("path", { fill: "currentColor", d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" }), _jsx("path", { fill: "currentColor", d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" })] }), googleLabel] }) })] }));
|
|
5
5
|
}
|
|
@@ -93,5 +93,5 @@ export function CategoryBundlesListing({ initialBundles, brandName, onBuyNow, })
|
|
|
93
93
|
// Apply → close. <FilterDrawer> below stays available for parity
|
|
94
94
|
// with every other listing page's filter affordance.
|
|
95
95
|
{ label: "Show out-of-stock", active: showOutOfStock, onChange: (next) => table.setMany({ showOutOfStock: next ? "true" : "", page: "1" }) },
|
|
96
|
-
] }), totalPages > 1 && (_jsx(StickyToolbar, { offset: "header+pagination", tone: "translucent", border: true, padding: "toolbar", children: _jsx(Row, { justify: "center", children: _jsx(Pagination, { currentPage: safePage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) }) })), _jsx(Div, { padding: "y-lg", children: pageItems.length === 0 ? (_jsxs(Text, { paddingY: "4xl", color: "muted", size: "sm", align: "start", children: ["No bundles match your search", brandName ? ` for ${brandName}` : "", "."] })) : (_jsx(Grid, { cols: "cards", gap: "lg", children: pageItems.map((bundle) => (_jsxs(Stack, { children: [_jsx(MarketplaceBundleCard, { bundle: bundle }), onBuyNow && (_jsx(Div, { border: "default", surface: "default", className: "-mt-px border-t border-t-0 border-[var(--appkit-color-border)] pt-[0.5rem] pb-[0.75rem]", padding: "x-sm", roundedBottom: "lg", children: _jsx(BundleBuyNowCta, { bundleSlug: bundle.slug, outOfStock: bundle.bundleStockStatus === "out_of_stock", onBuyNow: onBuyNow, compact: true }) }))] }, bundle.id))) })) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: () => setPendingShowOutOfStock(false), activeCount: filterActiveCount, hideTrigger: true, children: _jsx(Stack, { className: `${__P.p4}`, gap: "md", children: _jsxs(Label, { layout: "flex", gap: "lg", className: "justify-
|
|
96
|
+
] }), totalPages > 1 && (_jsx(StickyToolbar, { offset: "header+pagination", tone: "translucent", border: true, padding: "toolbar", children: _jsx(Row, { justify: "center", children: _jsx(Pagination, { currentPage: safePage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) }) })), _jsx(Div, { padding: "y-lg", children: pageItems.length === 0 ? (_jsxs(Text, { paddingY: "4xl", color: "muted", size: "sm", align: "start", children: ["No bundles match your search", brandName ? ` for ${brandName}` : "", "."] })) : (_jsx(Grid, { cols: "cards", gap: "lg", children: pageItems.map((bundle) => (_jsxs(Stack, { children: [_jsx(MarketplaceBundleCard, { bundle: bundle }), onBuyNow && (_jsx(Div, { border: "default", surface: "default", className: "-mt-px border-t border-t-0 border-[var(--appkit-color-border)] pt-[0.5rem] pb-[0.75rem]", padding: "x-sm", roundedBottom: "lg", children: _jsx(BundleBuyNowCta, { bundleSlug: bundle.slug, outOfStock: bundle.bundleStockStatus === "out_of_stock", onBuyNow: onBuyNow, compact: true }) }))] }, bundle.id))) })) }), _jsx(FilterDrawer, { open: filterOpen, onOpen: openFilters, onClose: () => setFilterOpen(false), onApply: applyFilters, onReset: () => setPendingShowOutOfStock(false), activeCount: filterActiveCount, hideTrigger: true, children: _jsx(Stack, { className: `${__P.p4}`, gap: "md", children: _jsxs(Label, { layout: "flex", gap: "lg", className: /* audit-variant-ok: <Label> exposes no flex `justify` prop */ "justify-between cursor-pointer", children: [_jsx(Span, { size: "sm", weight: "medium", color: "muted", children: "Show out-of-stock bundles" }), _jsx(Toggle, { checked: pendingShowOutOfStock, onChange: setPendingShowOutOfStock, size: "sm" })] }) }) })] }));
|
|
97
97
|
}
|
|
@@ -423,11 +423,12 @@ export async function CategoryDetailPageView({ slug }) {
|
|
|
423
423
|
imageUrl: coverOf(b),
|
|
424
424
|
countLabel: countOf(b),
|
|
425
425
|
} }) }) }));
|
|
426
|
-
})(), childCategories.length > 0 && (_jsx(Section, { border: "subtle", surface: "default", className: "border-b", children: _jsx(Div, { className: __W, padding: "inline", children:
|
|
427
|
-
.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
426
|
+
})(), childCategories.length > 0 && (_jsx(Section, { border: "subtle", surface: "default", className: "border-b", children: _jsx(Div, { className: __W, padding: "inline", children: (() => {
|
|
427
|
+
const directChildren = childCategories.filter((c) => c.tier === (category?.tier ?? 0) + 1);
|
|
428
|
+
if (directChildren.length === 0)
|
|
429
|
+
return null;
|
|
430
|
+
return (_jsxs(Div, { padding: "b-2xs", children: [_jsx(Text, { size: "xs", color: "muted", weight: "medium", className: "mb-[var(--appkit-space-1-5)]", children: "Subcategories" }), _jsx(Div, { layout: "flex", gap: "2", className: `${__O.xAuto} [scrollbar-width:none]`, padding: "b-2xs", children: directChildren.map((child) => (_jsxs(Link, { href: String(ROUTES.PUBLIC.CATEGORY_DETAIL(child.slug)),
|
|
431
|
+
// audit-responsive-wrap-ok: deliberate horizontal-scroll chip row (parent has overflow-x-auto) — each chip staying single-line is the intended design, not hidden content
|
|
432
|
+
className: "flex-shrink-0 flex items-center gap-[var(--appkit-space-1-5)] rounded-full border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-elevated)] px-[var(--appkit-space-4)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-sm)] font-medium text-[var(--appkit-color-text-muted)] hover:border-primary hover:text-primary transition-colors whitespace-nowrap", children: [child.display?.icon && (_jsx(Span, { className: "leading-none", children: child.display.icon })), child.name, (child.metrics?.totalProductCount ?? child.metrics?.productCount ?? 0) > 0 && (_jsx(Span, { size: "xs", color: "muted", children: (child.metrics?.totalProductCount ?? child.metrics?.productCount ?? 0).toLocaleString() }))] }, child.id))) })] }));
|
|
433
|
+
})() }) })), _jsx(Section, { padding: "y-lg", children: _jsx(Container, { size: "xl", children: _jsx(CategoryDetailTabs, { categorySlug: slug, categoryId: category?.id, initialProductsData: productsResult ?? undefined, initialBundles: bundlesResult ?? [], initialStores: categoryStores, counts: counts, enabledListingTypes: enabledListingTypes(settings), enabledCategoryTypes: enabledCategoryTypes(settings) }) }) }), groupedListings.length > 0 && (_jsx(Section, { padding: "y-lg", children: _jsx(Container, { size: "xl", children: _jsx(GroupedListingsCarousel, { groups: groupedListings }) }) })), relatedCategories.length > 0 && (_jsx(Section, { border: "subtle", surface: "default", className: "border-t", padding: "y-lg", children: _jsxs(Container, { size: "xl", children: [_jsx(Heading, { level: 2, className: "mb-4", size: "xl", weight: "semibold", children: "Related Categories" }), _jsx(CategoryGrid, { categories: relatedCategories, getHref: (c) => String(ROUTES.PUBLIC.CATEGORY_DETAIL(c.slug)) })] }) }))] }));
|
|
433
434
|
}
|
|
@@ -51,7 +51,15 @@ interface TabbableCategory {
|
|
|
51
51
|
parentIds?: readonly string[] | null;
|
|
52
52
|
isLeaf?: boolean | null;
|
|
53
53
|
}
|
|
54
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* A LEAF whose ancestry passes through a `*-parts` node.
|
|
56
|
+
*
|
|
57
|
+
* 🛑 `isLeaf` is required, not incidental. Without it the tab also matches the
|
|
58
|
+
* 20 classification NODES — "Attack Rings", "Weight Disks" — because their own
|
|
59
|
+
* `parentIds` include a `*-parts` node too, giving 772 entries that mix groups
|
|
60
|
+
* with the parts inside them. A part is a leaf by itself; the classification is
|
|
61
|
+
* a branch you reach by drilling down.
|
|
62
|
+
*/
|
|
55
63
|
export declare function isPartCategory(c: TabbableCategory): boolean;
|
|
56
64
|
/**
|
|
57
65
|
* Does this row belong on the given tab?
|
|
@@ -51,10 +51,20 @@ export const CATEGORY_TABS = [
|
|
|
51
51
|
];
|
|
52
52
|
export const DEFAULT_CATEGORY_TAB = "categories";
|
|
53
53
|
const typeOf = (c) => String(c.categoryType ?? "");
|
|
54
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* A LEAF whose ancestry passes through a `*-parts` node.
|
|
56
|
+
*
|
|
57
|
+
* 🛑 `isLeaf` is required, not incidental. Without it the tab also matches the
|
|
58
|
+
* 20 classification NODES — "Attack Rings", "Weight Disks" — because their own
|
|
59
|
+
* `parentIds` include a `*-parts` node too, giving 772 entries that mix groups
|
|
60
|
+
* with the parts inside them. A part is a leaf by itself; the classification is
|
|
61
|
+
* a branch you reach by drilling down.
|
|
62
|
+
*/
|
|
55
63
|
export function isPartCategory(c) {
|
|
56
64
|
if (typeOf(c))
|
|
57
65
|
return false; // brand / bundle / franchise / sublisting
|
|
66
|
+
if (c.isLeaf !== true)
|
|
67
|
+
return false;
|
|
58
68
|
return (c.parentIds ?? []).some((p) => PART_PARENT_IDS.includes(String(p)));
|
|
59
69
|
}
|
|
60
70
|
/**
|
|
@@ -6,6 +6,6 @@ export function CheckoutStepper({ steps, current }) {
|
|
|
6
6
|
return (_jsx(Nav, { "aria-label": "Checkout steps", layout: "flex", gap: "xs", children: steps.map((step, idx) => {
|
|
7
7
|
const isDone = idx < currentIdx;
|
|
8
8
|
const isActive = step.id === current;
|
|
9
|
-
return (_jsxs(React.Fragment, { children: [_jsxs(Row, { gap: "2.5", children: [_jsx(Span, { layout: "flex", color: "inverse", className: `h-6 w-6 justify-
|
|
9
|
+
return (_jsxs(React.Fragment, { children: [_jsxs(Row, { gap: "2.5", children: [_jsx(Span, { layout: "flex", color: "inverse", className: /* audit-variant-ok: <Span> has `layout`+`gap` but no flex `justify`; its `align` is text-align */ `h-6 w-6 justify-center ${isDone ? "bg-success " : isActive ? "bg-neutral-900 " : "bg-neutral-200 dark:bg-[var(--appkit-color-surface-elevated)] text-[var(--appkit-color-text-muted)] dark:text-[var(--appkit-color-text-faint)]"}`, rounded: "full", size: "xs", weight: "semibold", children: isDone ? "✓" : idx + 1 }), _jsx(Span, { className: `${isActive ? "text-[var(--appkit-color-text)] dark:text-[var(--appkit-color-text)]" : isDone ? "text-[var(--appkit-color-text-muted)] dark:text-[var(--appkit-color-text-faint)]" : "text-[var(--appkit-color-text-faint)]"}`, size: "sm", weight: "medium", children: step.label })] }), idx < steps.length - 1 && (_jsx(Span, { className: "h-px flex-1 bg-neutral-200" }))] }, step.id));
|
|
10
10
|
}) }));
|
|
11
11
|
}
|
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useState } from "react";
|
|
4
4
|
import { Button, Div, RichText, Row, Span, Tabs, TabsList, TabsTrigger, Text } from "../../../ui/index.js";
|
|
5
5
|
function FAQAccordionItem({ faq, isOpen, onToggle, renderExpandedFooter, }) {
|
|
6
|
-
return (_jsxs(Div, { className: "border-b border-neutral-200 last:border-0", children: [_jsxs(Button, { variant: "ghost", onClick: onToggle, "aria-expanded": isOpen, className: "w-full
|
|
6
|
+
return (_jsxs(Div, { className: "border-b border-neutral-200 last:border-0", children: [_jsxs(Button, { variant: "ghost", onClick: onToggle, "aria-expanded": isOpen, justify: "between", className: "w-full gap-[1rem] py-[1rem] text-left text-[0.875rem] font-[500] text-[var(--appkit-color-text)] dark:text-[var(--appkit-color-text)] transition hover:text-primary", children: [_jsx(Span, { children: faq.question }), _jsx(Span, { className: `flex-shrink-0 transition-transform ${isOpen ? "rotate-180" : ""}`, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M4 6l4 4 4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] }), isOpen && (_jsxs(Div, { textSize: "sm", className: "text-[var(--appkit-color-text-muted)]", padding: "b-md", children: [faq.tags && faq.tags.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", className: "mb-3", children: faq.tags.map((tag) => (_jsx(Span, { className: "bg-[var(--appkit-color-surface)] py-[0.25rem] text-[var(--appkit-color-text-muted)]", rounded: "md", padding: "x-xs", size: "xs", children: tag }, tag))) })), faq.answer.format === "html" ? (_jsx(RichText, { html: faq.answer.text, className: "prose-sm" })) : (_jsx(Text, { className: "whitespace-pre-line", children: faq.answer.text })), renderExpandedFooter?.(faq)] }))] }));
|
|
7
7
|
}
|
|
8
8
|
export function FAQAccordion({ faqs, className = "", renderExpandedFooter, labels, }) {
|
|
9
9
|
const [openId, setOpenId] = useState(null);
|
|
@@ -83,7 +83,7 @@ export function FilterFacetSection({ title, options, selected, onChange, selecti
|
|
|
83
83
|
}), filtered.length === 0 && (_jsx(Text, { paddingY: "xs", paddingX: "x-sm", color: "faint", size: "xs", children: "No results" }))] }), hasValue && (_jsx(Div, { border: "subtle", className: "border-t p-[0.25rem]", children: _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: CLS_CLEAR_BTN, onClick: () => { onChange([]); onClear?.(); setDropdownOpen(false); }, children: "Clear" }) }))] }))] }));
|
|
84
84
|
}
|
|
85
85
|
// ── Accordion variant (default) ─────────────────────────────────────────
|
|
86
|
-
return (_jsxs(Div, { className: cn("p-[var(--appkit-space-4)] border-b border-[var(--appkit-color-border)] last:border-b-0", className), children: [_jsxs(Row, { gap: "xs", children: [_jsxs(Button, { type: "button", onClick: handleToggle, variant: "ghost", size: "sm", className: "flex-1
|
|
86
|
+
return (_jsxs(Div, { className: cn("p-[var(--appkit-space-4)] border-b border-[var(--appkit-color-border)] last:border-b-0", className), children: [_jsxs(Row, { gap: "xs", children: [_jsxs(Button, { type: "button", onClick: handleToggle, variant: "ghost", size: "sm", justify: "between", className: "flex-1 text-[0.875rem] font-[600] text-[var(--appkit-color-text)] py-[0.25rem] hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsxs(Row, { as: Span, gap: "xs", children: [title, hasValue && (_jsx(Span, { size: "xs", className: CLS_BADGE_COUNT, children: selected.length }))] }), _jsx("svg", { className: cn("w-4 h-4 shrink-0 text-[var(--appkit-color-text-muted)] transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), onClear && hasValue && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: CLS_CLEAR_ICON, "aria-label": "Clear filter", children: _jsx("svg", { className: "w-3 h-3 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), isCollapsed && hasValue && (_jsxs(Row, { wrap: true, gap: "xs", className: "mt-2", children: [selectedLabels.map((label) => (_jsx(Span, { layout: "inline-flex", size: "xs", className: "border border-[var(--appkit-color-border)]", rounded: "full", padding: "pill-xs", surface: "subtle", color: "muted", children: label }, label))), selected.length > 3 && (_jsxs(Span, { layout: "inline-flex", size: "xs", rounded: "full", padding: "pill-xs", color: "faint", children: ["+", selected.length - 3, " more"] }))] })), searchable && (_jsx(Div, { className: "mt-2", children: _jsx(Input, { type: "search", placeholder: "Search\u2026", value: search, onChange: (e) => handleSearch(e.target.value), className: "w-full rounded-md border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-input)] px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] text-[var(--appkit-color-text)] focus:outline-none focus:ring-2 focus:ring-primary-500/20 " }) })), !isCollapsed && (_jsxs(Stack, { className: "mt-3", gap: "xs", children: [filtered.map((option) => {
|
|
87
87
|
const isSelected = selected.includes(option.value);
|
|
88
88
|
return (_jsxs(Row, { gap: "2.5", className: "cursor-pointer group", padding: "y-2xs", children: [selectionMode === "single" ? (_jsx(Checkbox, { bare: true, type: "radio", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: cn("flex-shrink-0 border-[var(--appkit-color-border)] cursor-pointer", "w-4 h-4 rounded-full text-primary-600 dark:text-secondary-500", "focus:ring-primary-500/30 dark:focus:ring-secondary-400/30") })) : (_jsx(Checkbox, { bare: true, type: "checkbox", checked: isSelected, onChange: () => toggle(option.value), "aria-label": option.label, className: cn("flex-shrink-0 border-[var(--appkit-color-border)] cursor-pointer", "w-4 h-4 rounded text-primary-600 dark:text-secondary-500 checked:bg-primary-600 dark:checked:bg-secondary-500", "focus:ring-primary-500/30 dark:focus:ring-secondary-400/30") })), _jsx(Span, { size: "sm", className: "flex-1 group-hover:text-[var(--appkit-color-text)] transition-colors truncate", color: "muted", children: option.label }), option.count !== undefined && (_jsx(Span, { size: "xs", className: "tabular-nums flex-shrink-0", color: "faint", children: option.count }))] }, option.value));
|
|
89
89
|
}), filtered.length === 0 && (_jsx(Text, { paddingY: "2xs", color: "faint", size: "xs", children: "No results" }))] }))] }));
|
|
@@ -63,5 +63,5 @@ export function RangeFilter({ title, minLabel, maxLabel, minValue, maxValue, onM
|
|
|
63
63
|
onMaxChange("");
|
|
64
64
|
});
|
|
65
65
|
const inputClass = "w-full rounded-md border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface-input)] px-[var(--appkit-space-2-5)] py-[var(--appkit-space-1-5)] text-[length:var(--appkit-text-xs)] text-[var(--appkit-color-text)] focus:outline-none focus:ring-2 focus:ring-primary-500/20 ";
|
|
66
|
-
return (_jsxs(Div, { role: "group", "aria-labelledby": `rf-${title}`, className: cn("p-[var(--appkit-space-4)] border-b border-[var(--appkit-color-border)] last:border-b-0", className), children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsxs(Button, { type: "button", id: `rf-${title}`, onClick: handleToggle, variant: "ghost", size: "sm", className: "flex-1
|
|
66
|
+
return (_jsxs(Div, { role: "group", "aria-labelledby": `rf-${title}`, className: cn("p-[var(--appkit-space-4)] border-b border-[var(--appkit-color-border)] last:border-b-0", className), children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsxs(Button, { type: "button", id: `rf-${title}`, onClick: handleToggle, variant: "ghost", size: "sm", justify: "between", className: "flex-1 text-[0.875rem] font-[600] text-[var(--appkit-color-text)] py-[0.25rem] hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsxs(Span, { layout: "flex", gap: "md", children: [title, hasValue && (_jsx(Span, { size: "xs", className: CLS_BADGE_COUNT, children: "1" }))] }), _jsx("svg", { className: cn("w-4 h-4 shrink-0 text-[var(--appkit-color-text-muted)] transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), hasValue && (_jsx(Button, { type: "button", onClick: handleClear, variant: "ghost", size: "sm", className: CLS_CLEAR_BTN, "aria-label": "Clear", children: _jsx("svg", { className: "w-3 h-3 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), !isCollapsed && (_jsxs(Stack, { gap: "3", className: "mt-3", children: [canShowSlider && (_jsx(DualSlider, { minValue: minValue, maxValue: maxValue, onMinChange: onMinChange, onMaxChange: onMaxChange, minBound: minBound, maxBound: maxBound, step: step, prefix: prefix })), _jsxs(Row, { align: "end", gap: "sm", children: [_jsxs(Div, { className: "flex-1 min-w-0", children: [minLabel && (_jsx(Text, { className: "mb-1", color: "muted", size: "xs", children: minLabel })), _jsxs(Div, { className: "relative", children: [prefix && (_jsx(Span, { size: "xs", className: "absolute left-2 top-1/2 -translate-y-1/2 pointer-events-none", color: "faint", children: prefix })), _jsx(Input, { type: type, value: minValue, onChange: (e) => onMinChange(e.target.value), placeholder: minPlaceholder ?? (type === "date" ? "From" : "Min"), className: cn(inputClass, prefix ? "pl-5" : "") })] })] }), _jsx(Span, { size: "xs", className: "flex-shrink-0 pb-[0.375rem]", color: "faint", children: "-" }), _jsxs(Div, { className: "flex-1 min-w-0", children: [maxLabel && (_jsx(Text, { className: "mb-1", color: "muted", size: "xs", children: maxLabel })), _jsxs(Div, { className: "relative", children: [prefix && (_jsx(Span, { size: "xs", className: "absolute left-2 top-1/2 -translate-y-1/2 pointer-events-none", color: "faint", children: prefix })), _jsx(Input, { type: type, value: maxValue, onChange: (e) => onMaxChange(e.target.value), placeholder: maxPlaceholder ?? (type === "date" ? "To" : "Max"), className: cn(inputClass, prefix ? "pl-5" : "") })] })] })] })] }))] }));
|
|
67
67
|
}
|
|
@@ -14,5 +14,5 @@ export function SwitchFilter({ title, label, checked, onChange, defaultCollapsed
|
|
|
14
14
|
else
|
|
15
15
|
setInternalCollapsed((c) => !c);
|
|
16
16
|
};
|
|
17
|
-
return (_jsxs(Div, { role: "group", "aria-labelledby": `sf-${title}`, className: cn("p-[var(--appkit-space-4)] border-b border-[var(--appkit-color-border)] last:border-b-0", className), children: [_jsxs(Row, { gap: "sm", children: [_jsxs(Button, { type: "button", id: `sf-${title}`, onClick: handleToggle, variant: "ghost", size: "sm", className: "flex-1
|
|
17
|
+
return (_jsxs(Div, { role: "group", "aria-labelledby": `sf-${title}`, className: cn("p-[var(--appkit-space-4)] border-b border-[var(--appkit-color-border)] last:border-b-0", className), children: [_jsxs(Row, { gap: "sm", children: [_jsxs(Button, { type: "button", id: `sf-${title}`, onClick: handleToggle, variant: "ghost", size: "sm", justify: "between", className: "flex-1 text-[0.875rem] font-[600] text-[var(--appkit-color-text)] py-[0.25rem] hover:opacity-80 transition-opacity", "aria-expanded": !isCollapsed, children: [_jsx(Text, { size: "sm", weight: "semibold", color: "primary", children: title }), _jsx("svg", { className: cn("w-4 h-4 shrink-0 text-[var(--appkit-color-text-muted)] transition-transform duration-200", isCollapsed ? "" : "rotate-180"), fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) })] }), checked && onClear && (_jsx(Button, { type: "button", onClick: onClear, variant: "ghost", size: "sm", className: CLS_CLEAR_BTN, "aria-label": "Clear", children: _jsx("svg", { className: "w-3 h-3 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }))] }), !isCollapsed && (_jsxs(Row, { className: "mt-3", align: "center", justify: "between", gap: "3", children: [_jsx(Span, { size: "sm", color: "muted", children: label }), _jsx(Toggle, { checked: checked, onChange: onChange, size: "sm" })] }))] }));
|
|
18
18
|
}
|
|
@@ -58,7 +58,7 @@ export function BeforeAfterCard({ item, beforeLabel = "Before", afterLabel = "Af
|
|
|
58
58
|
window.removeEventListener("touchcancel", onUp);
|
|
59
59
|
};
|
|
60
60
|
}, [dragging, updatePosition]);
|
|
61
|
-
return (_jsxs(Div, { className: `border-border ${__O.hidden} border bg-
|
|
61
|
+
return (_jsxs(Div, { className: `border-[var(--appkit-color-border)] ${__O.hidden} border bg-[var(--appkit-color-surface)]`, rounded: "2xl", shadow: "sm", children: [_jsxs(Div, { ref: containerRef, className: "relative aspect-[4/3] cursor-col-resize overflow-hidden select-none", onMouseDown: (e) => {
|
|
62
62
|
setDragging(true);
|
|
63
63
|
updatePosition(e.clientX);
|
|
64
64
|
}, onTouchStart: (e) => {
|
|
@@ -69,5 +69,5 @@ export function BeforeAfterCard({ item, beforeLabel = "Before", afterLabel = "Af
|
|
|
69
69
|
setPosition((p) => Math.max(0, p - 2));
|
|
70
70
|
if (e.key === "ArrowRight")
|
|
71
71
|
setPosition((p) => Math.min(100, p + 2));
|
|
72
|
-
}, children: [_jsx(Image, { src: resolveMediaUrl(item.afterImage), alt: afterLabel, fill: true, sizes: "(max-width: 640px) 100vw, 50vw", className: "object-cover" }), _jsx(Div, { ref: beforeClipRef, className: "absolute inset-0 overflow-hidden", children: _jsx(Image, { src: resolveMediaUrl(item.beforeImage), alt: beforeLabel, fill: true, sizes: "(max-width: 640px) 100vw, 50vw", className: "object-cover" }) }), _jsx(Div, { ref: dividerRef, shadow: "md", className: "absolute top-0 bottom-0 z-10 w-0.5 bg-[var(--appkit-color-surface)]", children: _jsx(Row, { className: "absolute top-1/2 left-1/2 h-8 w-8 -translate-x-1/2 -translate-y-1/2 bg-
|
|
72
|
+
}, children: [_jsx(Image, { src: resolveMediaUrl(item.afterImage), alt: afterLabel, fill: true, sizes: "(max-width: 640px) 100vw, 50vw", className: "object-cover" }), _jsx(Div, { ref: beforeClipRef, className: "absolute inset-0 overflow-hidden", children: _jsx(Image, { src: resolveMediaUrl(item.beforeImage), alt: beforeLabel, fill: true, sizes: "(max-width: 640px) 100vw, 50vw", className: "object-cover" }) }), _jsx(Div, { ref: dividerRef, shadow: "md", className: "absolute top-0 bottom-0 z-10 w-0.5 bg-[var(--appkit-color-surface)]", children: _jsx(Row, { className: "absolute top-1/2 left-1/2 h-8 w-8 -translate-x-1/2 -translate-y-1/2 bg-[var(--appkit-color-surface)]", align: "center", justify: "center", rounded: "full", shadow: "lg", children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M4 8L1 5M4 8L1 11M4 8H12M12 8L15 5M12 8L15 11", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }) }), _jsx(Span, { surface: "overlay-sm", color: "inverse", size: "xs", weight: "medium", className: "absolute top-3 left-3 z-10", padding: "pill-sm", rounded: "full", children: beforeLabel }), _jsx(Span, { surface: "overlay-sm", color: "inverse", size: "xs", weight: "medium", className: "absolute top-3 right-3 z-10", padding: "pill-sm", rounded: "full", children: afterLabel })] }), _jsx(Div, { className: `${__P.p4}`, children: _jsx(Text, { className: "text-[var(--appkit-color-text)]", size: "sm", weight: "medium", children: item.caption }) })] }));
|
|
73
73
|
}
|
|
@@ -319,7 +319,7 @@ function CharacterHotspotInner({ panoramicImage, panoramicAlt, hotspots, univers
|
|
|
319
319
|
borderTop: "3px solid var(--dark-section-bg)",
|
|
320
320
|
borderBottom: "3px solid var(--dark-section-bg)",
|
|
321
321
|
overflow: "hidden",
|
|
322
|
-
}, children: [_jsxs(Div, { ref: containerRef, className: "relative w-full", style: { aspectRatio: "16/9", minHeight: "420px" }, children: [_jsx(HotspotHeaderOverlay, { heading: heading, subheading: subheading, shopAllHref: shopAllHref }), _jsx(HotspotImageLayer, { panoramicImage: panoramicImage, panoramicAlt: panoramicAlt }), _jsx(Div, { className: "hidden sm:flex absolute left-0 right-0 justify-
|
|
322
|
+
}, children: [_jsxs(Div, { ref: containerRef, className: "relative w-full", style: { aspectRatio: "16/9", minHeight: "420px" }, children: [_jsx(HotspotHeaderOverlay, { heading: heading, subheading: subheading, shopAllHref: shopAllHref }), _jsx(HotspotImageLayer, { panoramicImage: panoramicImage, panoramicAlt: panoramicAlt }), _jsx(Div, { className: /* audit-variant-ok: flex only from `sm`; align/justify props are base-breakpoint only */ "hidden sm:flex absolute left-0 right-0 justify-around items-start pointer-events-none", style: { top: "clamp(120px, 18vh, 165px)", zIndex: 5 }, children: [
|
|
323
323
|
{ label: "MARVEL", color: BRAND_MARVEL },
|
|
324
324
|
{ label: "DC COMICS", color: BRAND_DC },
|
|
325
325
|
{ label: "ANIME", color: BRAND_ANIME_YELLOW },
|
|
@@ -61,5 +61,5 @@ export function FAQSection({ title, subtitle, items, tabs: tabsProp, showCategor
|
|
|
61
61
|
return (_jsx(Section, { paddingX: "x-md-2xl", className: className, surface: "subtle", paddingY: "y-4xl", children: _jsxs(Div, { className: "w-full max-w-4xl mx-auto", children: [_jsxs(Div, { className: "text-left mb-10", children: [_jsx(Heading, { level: 2, variant: "none", gradient: "brand", className: "mb-3", mdSize: "4xl", size: "3xl", weight: "bold", children: title }), subtitle && (_jsx(Text, { className: `max-w-xl ${themed.textSecondary}`, size: "base", children: subtitle }))] }), showTabs && (_jsx(Tabs, { value: activeTab, onChange: setActiveTab, className: "mb-8", children: _jsxs(TabsList, { children: [_jsx(TabsTrigger, { value: "all", children: "All" }), derivedTabs.map((tab) => (_jsx(TabsTrigger, { value: tab.value, children: tab.label }, tab.value)))] }) })), _jsxs(Stack, { gap: "none", rounded: "xl", className: `${themed.bgPrimary} ${__O.hidden} border ${themed.border}`, children: [visibleItems.length === 0 && (_jsx(Text, { paddingY: "3xl", align: "start", className: themed.textSecondary, children: "No FAQs in this category yet." })), visibleItems.map((faq, index) => {
|
|
62
62
|
const isOpen = openIds.has(faq.id);
|
|
63
63
|
return (_jsxs(Div, { className: `transition-colors duration-200 ${index < visibleItems.length - 1 ? "border-b border-[var(--appkit-color-border)]" : ""} ${isOpen ? "bg-[var(--appkit-color-surface-elevated)]" : ""}`, children: [_jsxs(Button, { variant: "ghost", rounded: "none", className: `w-full text-left px-[1.25rem] py-[1rem] ${flex.between} gap-[1rem] hover:${themed.bgTertiary} transition-colors`, onClick: () => toggle(faq.id), "aria-expanded": isOpen, children: [_jsx(Span, { size: "sm", weight: "medium", className: `flex-1 leading-snug ${isOpen ? "text-primary" : themed.textPrimary}`, children: faq.question }), _jsx(ChevronDown, { className: `w-4 h-4 flex-shrink-0 transition-transform duration-250 ${isOpen ? "rotate-180 text-primary" : themed.textSecondary}` })] }), _jsx(Div, { layout: "grid", className: `transition-all duration-300 ease-out ${isOpen ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0"}`, children: _jsx(Div, { className: `${__O.hidden}`, children: _jsx(Div, { paddingY: "b-md-lg", padding: "x-md", children: isHtml(faq.answer) ? (_jsx(RichText, { html: faq.answer, proseClass: "prose prose-sm max-w-none dark:prose-invert" })) : (_jsx(Text, { className: `leading-relaxed ${themed.textSecondary}`, size: "sm", children: faq.answer })) }) }) })] }, faq.id));
|
|
64
|
-
})] }), viewMoreHref && (_jsx(Div, { className: "text-left mt-10", children: _jsxs(TextLink, { rounded: "full", paddingX: "xl", paddingY: "sm", href: viewMoreHref,
|
|
64
|
+
})] }), viewMoreHref && (_jsx(Div, { className: "text-left mt-10", children: _jsxs(TextLink, { rounded: "full", paddingX: "xl", paddingY: "sm", href: viewMoreHref, layout: "inline-flex", align: "center", className: "gap-[0.5rem] bg-primary/10 text-primary hover:bg-primary/20 dark:bg-primary/15 transition-colors", size: "sm", weight: "medium", children: [viewMoreLabel, hasMore && moreCount > 0 && (_jsxs(Span, { color: "inverse", size: "xs", className: "bg-primary", rounded: "full", padding: "pill-xs", children: ["+", moreCount] }))] }) }))] }) }));
|
|
65
65
|
}
|
|
@@ -39,5 +39,5 @@ export function HeroBanner({ banners, autoplayMs = 5000 }) {
|
|
|
39
39
|
}, [banner.backgroundColor, banner.textColor]);
|
|
40
40
|
if (banners.length === 0)
|
|
41
41
|
return null;
|
|
42
|
-
return (_jsxs(Div, { ref: rootRef, className: "relative overflow-hidden min-h-svh [background:var(--hero-bg,var(--dark-section-deep))]", children: [banners.map((b, i) => (_jsx(Div, { className: `absolute inset-0 transition-opacity duration-700 z-[1] ${i === current ? "opacity-100" : "opacity-0"}`, children: b.backgroundImage && (_jsx(Image, { src: resolveMediaUrl(b.backgroundImage), alt: b.title, fill: true, className: "object-cover object-center", priority: i === 0, sizes: "100vw" })) }, b.id))), _jsx(Div, { className: "absolute inset-0 z-[2] [background:linear-gradient(110deg,rgba(0,0,0,0.82)_0%,rgba(0,0,0,0.45)_55%,rgba(0,0,0,0.18)_100%)]" }), _jsx(Div, { className: "absolute inset-0 z-[3] [background:linear-gradient(to_bottom,rgba(0,0,0,0.08)_0%,transparent_30%,rgba(0,0,0,0.55)_100%)]" }), _jsxs(Stack, { justify: "end", className: "relative pb-[4rem] sm:px-[3rem] sm:pb-[6rem] lg:px-[5rem] min-h-svh z-[10] pt-[var(--header-height,4rem)]", padding: "x-md", children: [banner.subtitle && (_jsx(Div, { className: "mb-3", children: _jsx(Span, { className: "inline-block font-black uppercase tracking-[0.18em] bg-[var(--color-red)] text-white [font-family:var(--font-bangers,Bangers,cursive)] tracking-[0.16em]", padding: "pill-md", size: "xs", children: banner.subtitle }) })), _jsx(Heading, { level: 2, textShadow: "soft-dark", className: "mb-5 max-w-xl leading-none [font-family:var(--font-bangers,Bangers,cursive)] text-[clamp(3rem,9vw,6.5rem)] tracking-[0.04em] text-[var(--hero-text,white)]", children: banner.title }), banner.ctaLabel && banner.ctaUrl && (_jsx(Row, { wrap: true, gap: "md", children: _jsxs(Link, { href: banner.ctaUrl, className: "inline-flex items-center gap-[var(--appkit-space-2)] sm:gap-[var(--appkit-space-3)] px-[var(--appkit-space-5)] py-[var(--appkit-space-3)] sm:px-[var(--appkit-space-8)] sm:py-[var(--appkit-space-3-5)] font-black uppercase transition-all hover:-translate-y-0.5 [font-family:var(--font-bangers,Bangers,cursive)] tracking-[0.1em] text-[clamp(0.85rem,2.5vw,1.1rem)] bg-[var(--color-yellow)] text-[var(--appkit-color-text)] [box-shadow:0_4px_24px_rgba(255,229,0,0.35)]", children: [banner.ctaLabel, _jsx(Span, { "aria-hidden": "true", className: "leading-none", smSize: "xl", size: "lg", children: "\u2192" })] }) }))] }), banners.length > 1 && (_jsxs(_Fragment, { children: [_jsx(Button, { rounded: "full", onClick: prev, "aria-label": "Previous slide", variant: "ghost", size: "sm", className: "absolute left-3 sm:left-6 top-1/2 -translate-y-1/2
|
|
42
|
+
return (_jsxs(Div, { ref: rootRef, className: "relative overflow-hidden min-h-svh [background:var(--hero-bg,var(--dark-section-deep))]", children: [banners.map((b, i) => (_jsx(Div, { className: `absolute inset-0 transition-opacity duration-700 z-[1] ${i === current ? "opacity-100" : "opacity-0"}`, children: b.backgroundImage && (_jsx(Image, { src: resolveMediaUrl(b.backgroundImage), alt: b.title, fill: true, className: "object-cover object-center", priority: i === 0, sizes: "100vw" })) }, b.id))), _jsx(Div, { className: "absolute inset-0 z-[2] [background:linear-gradient(110deg,rgba(0,0,0,0.82)_0%,rgba(0,0,0,0.45)_55%,rgba(0,0,0,0.18)_100%)]" }), _jsx(Div, { className: "absolute inset-0 z-[3] [background:linear-gradient(to_bottom,rgba(0,0,0,0.08)_0%,transparent_30%,rgba(0,0,0,0.55)_100%)]" }), _jsxs(Stack, { justify: "end", className: "relative pb-[4rem] sm:px-[3rem] sm:pb-[6rem] lg:px-[5rem] min-h-svh z-[10] pt-[var(--header-height,4rem)]", padding: "x-md", children: [banner.subtitle && (_jsx(Div, { className: "mb-3", children: _jsx(Span, { className: "inline-block font-black uppercase tracking-[0.18em] bg-[var(--color-red)] text-white [font-family:var(--font-bangers,Bangers,cursive)] tracking-[0.16em]", padding: "pill-md", size: "xs", children: banner.subtitle }) })), _jsx(Heading, { level: 2, textShadow: "soft-dark", className: "mb-5 max-w-xl leading-none [font-family:var(--font-bangers,Bangers,cursive)] text-[clamp(3rem,9vw,6.5rem)] tracking-[0.04em] text-[var(--hero-text,white)]", children: banner.title }), banner.ctaLabel && banner.ctaUrl && (_jsx(Row, { wrap: true, gap: "md", children: _jsxs(Link, { href: banner.ctaUrl, className: "inline-flex items-center gap-[var(--appkit-space-2)] sm:gap-[var(--appkit-space-3)] px-[var(--appkit-space-5)] py-[var(--appkit-space-3)] sm:px-[var(--appkit-space-8)] sm:py-[var(--appkit-space-3-5)] font-black uppercase transition-all hover:-translate-y-0.5 [font-family:var(--font-bangers,Bangers,cursive)] tracking-[0.1em] text-[clamp(0.85rem,2.5vw,1.1rem)] bg-[var(--color-yellow)] text-[var(--appkit-color-text)] [box-shadow:0_4px_24px_rgba(255,229,0,0.35)]", children: [banner.ctaLabel, _jsx(Span, { "aria-hidden": "true", className: "leading-none", smSize: "xl", size: "lg", children: "\u2192" })] }) }))] }), banners.length > 1 && (_jsxs(_Fragment, { children: [_jsx(Button, { rounded: "full", onClick: prev, "aria-label": "Previous slide", variant: "ghost", size: "sm", justify: "center", className: "absolute left-3 sm:left-6 top-1/2 -translate-y-1/2 transition-all hover:scale-105 z-[15] w-10 h-10 bg-[rgba(255,255,255,0.12)] border border-white/20 text-white backdrop-blur-sm", children: _jsx("svg", { className: "h-4 w-4 sm:h-5 sm:w-5 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M15 19l-7-7 7-7" }) }) }), _jsx(Button, { rounded: "full", onClick: next, "aria-label": "Next slide", variant: "ghost", size: "sm", justify: "center", className: "absolute right-3 sm:right-6 top-1/2 -translate-y-1/2 transition-all hover:scale-105 z-[15] w-10 h-10 bg-[rgba(255,255,255,0.12)] border border-white/20 text-white backdrop-blur-sm", children: _jsx("svg", { className: "h-4 w-4 sm:h-5 sm:w-5 shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M9 5l7 7-7 7" }) }) })] })), banners.length > 1 && (_jsxs(Row, { className: "absolute bottom-8 right-6 sm:right-12 z-[15]", gap: "3", children: [_jsxs(Span, { className: "font-black tabular-nums text-white/60 [font-family:var(--font-bangers,Bangers,cursive)] tracking-[0.1em]", size: "xs", children: [String(current + 1).padStart(2, "0"), " /", " ", String(banners.length).padStart(2, "0")] }), _jsx(Row, { gap: "xs", className: "", children: banners.map((_, i) => (_jsx(Button, { onClick: () => goTo(i), "aria-label": `Go to slide ${i + 1}`, variant: "ghost", size: "sm", className: `transition-all h-[3px] rounded-[2px] ${i === current ? "w-7 bg-[var(--color-yellow)]" : "w-2.5 bg-white/35"}` }, i))) })] })), _jsx(Stack, { className: "absolute bottom-6 left-1/2 -translate-x-1/2 z-[15] opacity-50", align: "center", gap: "xs", "aria-hidden": "true", children: _jsx(Div, { className: "h-8 w-px [background:linear-gradient(to_bottom,rgba(255,255,255,0),rgba(255,255,255,0.8))]" }) })] }));
|
|
43
43
|
}
|
|
@@ -117,10 +117,10 @@ function CarouselCardRenderer({ card, isMobile, push, }) {
|
|
|
117
117
|
gridRow: String(gridPos.gridRow),
|
|
118
118
|
gridColumn: String(gridPos.gridColumn),
|
|
119
119
|
minHeight: isMobile ? 100 : 140,
|
|
120
|
-
}, children: [_jsx(CardBackground, { bg: card.background }), !card.isButtonOnly && (_jsxs(_Fragment, { children: [_jsx(Scrim, { direction: "bottom-up", intensity: "strong", className: POSITION_FILL }), _jsxs(Stack, { justify: "end", className: `${POSITION_FILL} md:p-[1.5rem] ${textAlignClass}`, padding: "xs", children: [card.content?.eyebrow && (_jsx(Text, { color: "inverse", shadow: "sm", className: "text-[10px]
|
|
120
|
+
}, children: [_jsx(CardBackground, { bg: card.background }), !card.isButtonOnly && (_jsxs(_Fragment, { children: [_jsx(Scrim, { direction: "bottom-up", intensity: "strong", className: POSITION_FILL }), _jsxs(Stack, { justify: "end", className: `${POSITION_FILL} md:p-[1.5rem] ${textAlignClass}`, padding: "xs", children: [card.content?.eyebrow && (_jsx(Text, { color: "inverse", shadow: "sm", className: "text-[10px] opacity-70 mb-0.5 tracking-wider", mdSize: "xs", transform: "uppercase", children: card.content.eyebrow })), card.content?.subtitle && (_jsx(Text, { color: "inverse", shadow: "sm", className: "hidden md:block opacity-90 mb-0.5 md:mb-2", mdSize: "sm", size: "xs", children: card.content.subtitle })), card.content?.title && (
|
|
121
121
|
// level={3}: a card sits INSIDE a slide, so it is subordinate to
|
|
122
122
|
// that slide's own h2 overlay title rather than a sibling of it.
|
|
123
|
-
_jsx(Heading, { level: 3, className: `text-[11px] mb-0.5 md:mb-3`, truncate: 2, weight: "bold", shadow: "md", mdSize: "2xl", lgSize: "3xl", style: { color: card.content.textColor ?? "white" }, children: card.content.title })), card.content?.description && (_jsx(Text, { color: "inverse", shadow: "sm", className: `text-[10px] md:text-[0.875rem]
|
|
123
|
+
_jsx(Heading, { level: 3, className: `text-[11px] mb-0.5 md:mb-3`, truncate: 2, weight: "bold", shadow: "md", mdSize: "2xl", lgSize: "3xl", style: { color: card.content.textColor ?? "white" }, children: card.content.title })), card.content?.description && (_jsx(Text, { color: "inverse", shadow: "sm", className: `text-[10px] md:text-[0.875rem] opacity-80 mb-1 md:mb-4`, truncate: true, children: card.content.description })), (card.buttons?.length ?? 0) > 0 && (_jsx(Row, { wrap: true, gap: "xs", className: "md:gap-[var(--appkit-space-2)]", children: (card.buttons ?? []).map((btn, i) => {
|
|
124
124
|
const variant = btn.variant === "link" || btn.variant === "ghost"
|
|
125
125
|
? "ghost"
|
|
126
126
|
: btn.variant;
|
|
@@ -194,13 +194,13 @@ export function HeroCarousel({ initialSlides, push, height, defaultAutoplayDelay
|
|
|
194
194
|
onMouseEnter: pauseOnHover ? () => setIsPaused(true) : undefined, onMouseLeave: pauseOnHover ? () => setIsPaused(false) : undefined, onFocus: () => setIsPaused(true), onBlur: () => setIsPaused(false), tabIndex: 0, children: [_jsx(Div, { "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: `Slide ${currentSlide + 1} of ${slides.length}` }), _jsx(Div, { className: POSITION_FILL, children: _jsx(Div, { layout: "flex", ref: slidesRef, onScroll: handleSlidesScroll, className: "h-full overflow-x-auto scroll-smooth snap-x snap-mandatory [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", style: { gap: 0 }, children: slides.map((slide, slideIndex) => {
|
|
195
195
|
const slideHeightClass = getSlideHeightClass(slide.settings?.height);
|
|
196
196
|
const hasCards = slide.cards && slide.cards.length > 0;
|
|
197
|
-
return (_jsxs(Div, { className: `snap-start flex-none w-full relative self-stretch bg-neutral-900 ${slideHeightClass}`, children: [_jsx(Div, { className: POSITION_FILL, children: _jsx(SlideBackground, { bg: slide.background, legacy: slide.media, mobileLegacy: slide.mobileMedia, isMobile: isMobile, priority: slideIndex === 0 }) }), slide.overlay && (_jsxs(Div, { layout: "flex-col", align: "start", justify: "center", className: `${POSITION_FILL} text-left md:px-[4rem] lg:px-[8rem]`, padding: "x-lg", children: [slide.overlay.subtitle && (_jsx(Text, { color: "inverse", shadow: "sm", className: "stagger-1
|
|
197
|
+
return (_jsxs(Div, { className: `snap-start flex-none w-full relative self-stretch bg-neutral-900 ${slideHeightClass}`, children: [_jsx(Div, { className: POSITION_FILL, children: _jsx(SlideBackground, { bg: slide.background, legacy: slide.media, mobileLegacy: slide.mobileMedia, isMobile: isMobile, priority: slideIndex === 0 }) }), slide.overlay && (_jsxs(Div, { layout: "flex-col", align: "start", justify: "center", className: `${POSITION_FILL} text-left md:px-[4rem] lg:px-[8rem]`, padding: "x-lg", children: [slide.overlay.subtitle && (_jsx(Text, { color: "inverse", shadow: "sm", className: "stagger-1 opacity-80 mb-1 md:mb-2 tracking-widest", mdSize: "sm", size: "xs", transform: "uppercase", children: slide.overlay.subtitle })), slide.overlay.title && (
|
|
198
198
|
// level={2}, NOT 1. The welcome section above this
|
|
199
199
|
// carousel owns the page's single <h1>; a carousel that
|
|
200
200
|
// emits one <h1> per slide gives the document as many
|
|
201
201
|
// h1s as it has slides. `size` is independent of `level`,
|
|
202
202
|
// so this changes the outline and not one pixel.
|
|
203
|
-
_jsx(Heading, { color: "inverse", level: 2, className: "stagger-2 font-display ! mb-2 md:mb-4 break-words", size: "4xl", shadow: "2xl", mdSize: "6xl", lgSize: "8xl", children: slide.overlay.title })), slide.overlay.description && (_jsx(Text, { color: "inverse", shadow: "sm", className: "stagger-3
|
|
203
|
+
_jsx(Heading, { color: "inverse", level: 2, className: "stagger-2 font-display ! mb-2 md:mb-4 break-words", size: "4xl", shadow: "2xl", mdSize: "6xl", lgSize: "8xl", children: slide.overlay.title })), slide.overlay.description && (_jsx(Text, { color: "inverse", shadow: "sm", className: "stagger-3 opacity-90 mb-4 md:mb-8 max-w-2xl", mdSize: "lg", lgSize: "xl", size: "sm", children: slide.overlay.description })), slide.overlay.button && (_jsx(Div, { className: "stagger-4", children: _jsx(Button, { variant: slide.overlay.button.variant, size: "sm", onClick: makeButtonClickHandler(slide.overlay.button.link, slide.overlay.button.openInNewTab, push), children: slide.overlay.button.text }) }))] })), hasCards && (_jsx(Div, { className: `${POSITION_FILL} grid gap-[var(--appkit-space-2)] md:gap-[var(--appkit-space-4)] md:p-[var(--appkit-space-8)]`, padding: "md", style: {
|
|
204
204
|
gridTemplateRows: "repeat(2, 1fr)",
|
|
205
205
|
gridTemplateColumns: isMobile ? "1fr" : "repeat(3, 1fr)",
|
|
206
206
|
alignContent: "center",
|
|
@@ -36,5 +36,5 @@ export function HowItWorksSection({ title, subtitle, pillLabel, ctaLabel, onCtaC
|
|
|
36
36
|
observer.observe(el);
|
|
37
37
|
return () => observer.disconnect();
|
|
38
38
|
}, []);
|
|
39
|
-
return (_jsx(Section, { ref: sectionRef, className: `${className}`, surface: "muted", padding: "xl", children: _jsxs(Div, { className: "max-w-6xl mx-auto", children: [_jsxs(Div, { className: `text-left mb-12 transition-all duration-700 ${visible ? CLS_VISIBLE : "opacity-0 translate-y-4"}`, children: [pillLabel && (_jsx(Div, { layout: "inline-flex", gap: "2", align: "center", textWeight: "medium", textSize: "xs", className: "mb-4 border border-primary-
|
|
39
|
+
return (_jsx(Section, { ref: sectionRef, className: `${className}`, surface: "muted", padding: "xl", children: _jsxs(Div, { className: "max-w-6xl mx-auto", children: [_jsxs(Div, { className: `text-left mb-12 transition-all duration-700 ${visible ? CLS_VISIBLE : "opacity-0 translate-y-4"}`, children: [pillLabel && (_jsx(Div, { layout: "inline-flex", gap: "2", align: "center", textWeight: "medium", textSize: "xs", className: /* audit-variant-ok: colour+alpha border (primary-500/30); the `border` variant takes a token name, not an rgba step */ "mb-4 border border-primary-500/30 bg-primary-500/10 py-[0.375rem] tracking-[0.2em] uppercase text-primary-700 dark:text-primary-400 backdrop-blur-sm", padding: "x-md", rounded: "full", children: pillLabel })), _jsx(Heading, { level: 2, className: `${themed.textPrimary} mb-3`, size: "3xl", mdSize: "4xl", weight: "bold", children: title }), subtitle && (_jsx(Text, { className: `${themed.textSecondary} max-w-xl`, size: "base", children: subtitle }))] }), _jsx(Grid, { gap: "lg", className: "grid-cols-1 md:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-3 mb-10", children: steps.map((step, i) => (_jsx(StepCard, { step: step, visible: visible, delayClass: STEP_DELAYS[Math.min(i, STEP_DELAYS.length - 1)] }, step.number))) }), ctaLabel && onCtaClick && (_jsx(Div, { className: `text-left transition-all duration-700 delay-500 ${visible ? CLS_VISIBLE : "opacity-0 translate-y-4"}`, children: _jsx(Button, { variant: "primary", size: "lg", onClick: onCtaClick, children: ctaLabel }) }))] }) }));
|
|
40
40
|
}
|
|
@@ -48,5 +48,5 @@ export function SectionCarousel({ title, description, headingVariant = "editoria
|
|
|
48
48
|
// Double-row grids (e.g. the homepage Auctions section's
|
|
49
49
|
// rows:2 config) get the full-height sliver arrows — much
|
|
50
50
|
// easier to hit than a small circle when the track is tall.
|
|
51
|
-
arrowStyle: rows > 1 ? "full-height" : "circle", snapToItems: true, showScrollbar: false, pauseOnHover: true })), viewMoreHref && !isLoading && (_jsx(Row, { className: "mt-6", justify: hand === "left" ? "end" : "start", children: _jsx(TextLink, { rounded: "lg", paddingX: "xl", paddingY: "sm", href: viewMoreHref, shadow: useLightText ? "lg" : "none",
|
|
51
|
+
arrowStyle: rows > 1 ? "full-height" : "circle", snapToItems: true, showScrollbar: false, pauseOnHover: true })), viewMoreHref && !isLoading && (_jsx(Row, { className: "mt-6", justify: hand === "left" ? "end" : "start", children: _jsx(TextLink, { rounded: "lg", paddingX: "xl", paddingY: "sm", href: viewMoreHref, shadow: useLightText ? "lg" : "none", layout: "inline-flex", align: "center", className: "gap-[0.375rem] transition-colors bg-primary text-white hover:bg-primary-600", size: "sm", weight: "semibold", children: viewMoreLabel }) }))] })] }));
|
|
52
52
|
}
|
|
@@ -35,5 +35,5 @@ export function SecurityHighlightsSection({ title, subtitle, pillLabel, items, l
|
|
|
35
35
|
observer.observe(el);
|
|
36
36
|
return () => observer.disconnect();
|
|
37
37
|
}, []);
|
|
38
|
-
return (_jsx(Section, { ref: sectionRef, paddingY: "y-2-5xl", className: className, surface: "muted", paddingX: "x-md", children: _jsxs(Div, { className: "max-w-6xl mx-auto", children: [_jsxs(Div, { className: "text-left mb-10", children: [pillLabel && (_jsx(Span, { layout: "inline-flex", gap: "md", size: "xs", weight: "medium", className: "border border-primary-
|
|
38
|
+
return (_jsx(Section, { ref: sectionRef, paddingY: "y-2-5xl", className: className, surface: "muted", paddingX: "x-md", children: _jsxs(Div, { className: "max-w-6xl mx-auto", children: [_jsxs(Div, { className: "text-left mb-10", children: [pillLabel && (_jsx(Span, { layout: "inline-flex", gap: "md", size: "xs", weight: "medium", className: /* audit-variant-ok: colour+alpha border (primary-500/30); the `border` variant takes a token name, not an rgba step */ "border border-primary-500/30 bg-primary-500/10 px-[1.25rem] py-[0.375rem] tracking-[0.2em] text-primary-700 dark:text-primary-400 backdrop-blur-sm", rounded: "full", transform: "uppercase", children: pillLabel })), _jsx(Heading, { level: 2, className: `mt-4 ${themed.textPrimary}`, size: "3xl", mdSize: "4xl", weight: "bold", children: title }), subtitle && (_jsx(Text, { variant: "secondary", className: "mt-2 max-w-xl", children: subtitle }))] }), _jsx(Grid, { cols: "cards", gap: "xl", children: items.map((item, index) => (_jsx(SecurityCard, { item: item, visible: visible, delayClass: CARD_DELAYS[Math.min(index, CARD_DELAYS.length - 1)] }, item.key))) }), learnMoreHref && (_jsx(Div, { className: "text-left mt-8", children: _jsx(TextLink, { href: learnMoreHref, children: learnMoreLabel }) }))] }) }));
|
|
39
39
|
}
|
|
@@ -42,5 +42,5 @@ const FALLBACK_BADGES = [
|
|
|
42
42
|
];
|
|
43
43
|
export function TrustBadges({ badges }) {
|
|
44
44
|
const items = badges && badges.length > 0 ? badges : FALLBACK_BADGES;
|
|
45
|
-
return (_jsx(Section, { className: "bg-[var(--section-bg)] [border-top:var(--section-border)] [border-bottom:var(--section-border)]", children: _jsx(Div, { className: "mx-auto max-w-7xl sm:py-[2.5rem]", paddingY: "y-lg", paddingX: "x-md", children: _jsx(Grid, { cols: "statTiles", gap: "lg", children: items.map((badge) => (_jsxs(Stack, { className: "text-left [flex-direction:row]
|
|
45
|
+
return (_jsx(Section, { className: "bg-[var(--section-bg)] [border-top:var(--section-border)] [border-bottom:var(--section-border)]", children: _jsx(Div, { className: "mx-auto max-w-7xl sm:py-[2.5rem]", paddingY: "y-lg", paddingX: "x-md", children: _jsx(Grid, { cols: "statTiles", gap: "lg", children: items.map((badge) => (_jsxs(Stack, { className: "text-left [flex-direction:row] gap-[1rem]", align: "center", gap: "sm", children: [_jsx(Row, { className: "h-12 w-12 shrink-0 bg-[rgba(240,196,23,0.12)] text-[var(--color-red)] [border:2px_solid_var(--border-ink)]", align: "center", justify: "center", rounded: "full", children: BADGE_ICONS[badge.iconKey] }), _jsxs(Div, { children: [_jsx(Text, { className: "font-black uppercase tracking-wide text-[var(--section-title-color)]", size: "sm", children: badge.title }), _jsx(Text, { className: "text-[var(--color-muted)]", size: "xs", weight: "medium", children: badge.sub })] })] }, badge.id))) }) }) }));
|
|
46
46
|
}
|
|
@@ -9,5 +9,5 @@ export function WelcomeSection({ title, subtitle, pillLabel, showCTA = true, cta
|
|
|
9
9
|
if (isLoading) {
|
|
10
10
|
return (_jsx(Section, { className: `relative overflow-hidden pt-[0px] pb-[var(--appkit-space-16)] md:pt-[0px] md:pb-[6rem] ${className}`, paddingX: "x-md", children: _jsxs(Div, { className: "animate-pulse max-w-4xl mx-auto text-left", children: [_jsx(Div, { className: "h-6 w-52 mb-6", surface: "subtle", rounded: "full" }), _jsx(Div, { className: "h-20 mb-4 max-w-2xl", surface: "subtle", rounded: "lg" }), _jsx(Div, { className: "h-6 mb-8 max-w-lg", surface: "subtle", rounded: "lg" }), _jsxs(Row, { justify: "start", gap: "md", children: [_jsx(Div, { className: "h-12 w-36", surface: "subtle", rounded: "xl" }), _jsx(Div, { className: "h-12 w-36", surface: "subtle", rounded: "xl" })] })] }) }));
|
|
11
11
|
}
|
|
12
|
-
return (_jsxs(Section, { className: `relative overflow-hidden pt-[0px] pb-[var(--appkit-space-20)] md:pt-[0px] md:pb-[7rem] ${className}`, paddingX: "x-md", children: [_jsx(Div, { className: "pointer-events-none absolute -top-32 -left-32 w-[28rem] h-[28rem] bg-primary/10 blur-3xl", rounded: "full", "aria-hidden": "true" }), _jsx(Div, { className: "pointer-events-none absolute -bottom-40 -right-40 w-[36rem] h-[36rem] bg-secondary/10 dark:bg-secondary/15 blur-3xl", rounded: "full", "aria-hidden": "true" }), _jsx(Div, { className: "relative z-10 max-w-7xl mx-auto", children: _jsxs(Grid, { align: "center", gap: "2xl", className: "grid-cols-1 lg:grid-cols-2 xl:grid-cols-2 2xl:grid-cols-2", children: [_jsxs(Div, { className: "text-left", children: [pillLabel && (_jsx(Div, { children: _jsxs(Span, { layout: "inline-flex", gap: "md", size: "xs", weight: "medium", className: "border border-primary-
|
|
12
|
+
return (_jsxs(Section, { className: `relative overflow-hidden pt-[0px] pb-[var(--appkit-space-20)] md:pt-[0px] md:pb-[7rem] ${className}`, paddingX: "x-md", children: [_jsx(Div, { className: "pointer-events-none absolute -top-32 -left-32 w-[28rem] h-[28rem] bg-primary/10 blur-3xl", rounded: "full", "aria-hidden": "true" }), _jsx(Div, { className: "pointer-events-none absolute -bottom-40 -right-40 w-[36rem] h-[36rem] bg-secondary/10 dark:bg-secondary/15 blur-3xl", rounded: "full", "aria-hidden": "true" }), _jsx(Div, { className: "relative z-10 max-w-7xl mx-auto", children: _jsxs(Grid, { align: "center", gap: "2xl", className: "grid-cols-1 lg:grid-cols-2 xl:grid-cols-2 2xl:grid-cols-2", children: [_jsxs(Div, { className: "text-left", children: [pillLabel && (_jsx(Div, { children: _jsxs(Span, { layout: "inline-flex", gap: "md", size: "xs", weight: "medium", className: /* audit-variant-ok: colour+alpha border (primary-500/30); the `border` variant takes a token name, not an rgba step */ "border border-primary-500/30 bg-primary-500/10 px-[1.25rem] py-[0.375rem] tracking-[0.2em] text-primary-700 dark:text-primary-400 backdrop-blur-sm", rounded: "full", transform: "uppercase", children: [_jsx(Span, { className: "w-1.5 h-1.5 bg-primary-500 inline-block", rounded: "full", "aria-hidden": "true" }), pillLabel, _jsx(Span, { className: "w-1.5 h-1.5 bg-primary-500 inline-block", rounded: "full", "aria-hidden": "true" })] }) })), _jsx(Heading, { level: 1, variant: "none", gradient: "brand-tri", className: "mt-4 font-display leading-[1.1] tracking-tight break-words", size: "5xl", mdSize: "6xl", lgSize: "7xl", xlSize: "7xl", children: title }), subtitle && (_jsx(Text, { className: `mt-4 ${themed.textSecondary} max-w-xl leading-relaxed`, size: "xl", children: subtitle })), showCTA && (_jsxs(Row, { wrap: true, gap: "md", className: "mt-8", justify: "start", children: [ctaHref ? (_jsx(TextLink, { rounded: "xl", href: ctaHref, layout: "inline-flex", align: "center", justify: "center", className: "px-[2rem] py-[0.875rem] !bg-primary hover:!bg-primary-600 text-white dark:!bg-primary dark:hover:!bg-primary-600 dark:text-white btn-glow transition-all hover:scale-[1.02]", size: "base", weight: "bold", children: ctaLabel })) : (_jsx(Button, { variant: "primary", size: "lg", onClick: onCtaClick, children: ctaLabel })), secondaryCtaHref ? (_jsx(TextLink, { rounded: "xl", href: secondaryCtaHref, layout: "inline-flex", align: "center", justify: "center", className: "border-2 border-cobalt/40 dark:border-cobalt-400/40 px-[2rem] py-[0.875rem] text-cobalt-700 dark:text-cobalt-300 hover:bg-primary-surface transition-all hover:scale-[1.02]", size: "base", weight: "semibold", children: secondaryCtaLabel })) : (_jsx(Button, { variant: "outline", size: "lg", onClick: onSecondaryCtaClick, children: secondaryCtaLabel }))] })), trustChips.length > 0 && (_jsx(Row, { wrap: true, gap: "sm", className: "mt-6", justify: "start", children: trustChips.map((chip) => (_jsxs(Span, { layout: "inline-flex", gap: "xs", size: "xs", weight: "medium", className: "border border-[var(--appkit-color-border)] px-[0.875rem] py-[0.375rem]", rounded: "full", surface: "subtle", color: "muted", children: [chip.emoji, " ", chip.label] }, chip.key))) }))] }), _jsx(Div, { className: "hidden lg:block", children: _jsxs(Div, { className: `relative overflow-hidden aspect-[4/3] bg-[image:var(--appkit-gradient-section-mesh)]`, shadow: "2xl", border: "default", rounded: "3xl", children: [_jsx(Div, { className: "absolute inset-0 bg-[image:var(--appkit-gradient-glass)]" }), _jsxs(Stack, { centered: true, gap: "sm", className: `absolute inset-0 ${flex.center} p-[2.5rem]`, children: [_jsx(SiteMark, { title: brandLogoText || "LetItRip.in", size: "xl" }), _jsx(SiteLogo, { title: brandLogoText || "LetItRip.in", size: "xl" })] })] }) })] }) })] }));
|
|
13
13
|
}
|