@stapel/listings-react 0.9.0 → 0.10.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 (57) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/dist/api/generated/schema.d.ts +34 -2
  3. package/dist/api/generated/schema.d.ts.map +1 -1
  4. package/dist/default/FeedGrid.d.ts +42 -0
  5. package/dist/default/FeedGrid.d.ts.map +1 -0
  6. package/dist/default/FeedGrid.js +23 -0
  7. package/dist/default/FeedGrid.js.map +1 -0
  8. package/dist/default/ListingCard.d.ts +31 -0
  9. package/dist/default/ListingCard.d.ts.map +1 -1
  10. package/dist/default/ListingCard.js +12 -4
  11. package/dist/default/ListingCard.js.map +1 -1
  12. package/dist/default/ListingFeedCard.d.ts +77 -0
  13. package/dist/default/ListingFeedCard.d.ts.map +1 -0
  14. package/dist/default/ListingFeedCard.js +75 -0
  15. package/dist/default/ListingFeedCard.js.map +1 -0
  16. package/dist/default/ListingSerpCard.d.ts +114 -0
  17. package/dist/default/ListingSerpCard.d.ts.map +1 -0
  18. package/dist/default/ListingSerpCard.js +72 -0
  19. package/dist/default/ListingSerpCard.js.map +1 -0
  20. package/dist/default/favorite.d.ts +49 -0
  21. package/dist/default/favorite.d.ts.map +1 -0
  22. package/dist/default/favorite.js +25 -0
  23. package/dist/default/favorite.js.map +1 -0
  24. package/dist/default/icons.d.ts +17 -3
  25. package/dist/default/icons.d.ts.map +1 -1
  26. package/dist/default/icons.js +13 -1
  27. package/dist/default/icons.js.map +1 -1
  28. package/dist/default/index.d.ts +17 -1
  29. package/dist/default/index.d.ts.map +1 -1
  30. package/dist/default/index.js +14 -1
  31. package/dist/default/index.js.map +1 -1
  32. package/dist/i18n/es.d.ts.map +1 -1
  33. package/dist/i18n/es.js +4 -0
  34. package/dist/i18n/es.js.map +1 -1
  35. package/dist/i18n/keys.d.ts +11 -0
  36. package/dist/i18n/keys.d.ts.map +1 -1
  37. package/dist/i18n/keys.js +15 -0
  38. package/dist/i18n/keys.js.map +1 -1
  39. package/dist/i18n/ru.d.ts.map +1 -1
  40. package/dist/i18n/ru.js +4 -0
  41. package/dist/i18n/ru.js.map +1 -1
  42. package/llms.txt +3 -1
  43. package/manifest.json +45 -1
  44. package/nav-manifest.json +1 -1
  45. package/package.json +9 -9
  46. package/src/analytics/generated/events.json +1 -1
  47. package/src/api/generated/schema.ts +34 -2
  48. package/src/default/FeedGrid.tsx +70 -0
  49. package/src/default/ListingCard.tsx +21 -5
  50. package/src/default/ListingFeedCard.tsx +232 -0
  51. package/src/default/ListingSerpCard.tsx +374 -0
  52. package/src/default/favorite.tsx +91 -0
  53. package/src/default/icons.tsx +37 -3
  54. package/src/default/index.ts +24 -1
  55. package/src/i18n/es.ts +4 -0
  56. package/src/i18n/keys.ts +15 -0
  57. package/src/i18n/ru.ts +4 -0
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Flex, Typography } from "antd";
3
+ import { SkinTheme } from "@stapel/tokens-antd/skin";
4
+ import { useT } from "@stapel/core";
5
+ import { radii, spacing } from "@stapel/tokens";
6
+ import { lifecycleCaption } from "../model/status.js";
7
+ import { LISTINGS_I18N_KEYS } from "../i18n/keys.js";
8
+ import { FavoriteHeart } from "./favorite.js";
9
+ import { CARD_TARGET_STYLE_HREF, CardTarget, cardTargetCss, } from "./ListingCard.js";
10
+ import { ListingPhoto } from "./ListingPhoto.js";
11
+ import { ListingPrice } from "./ListingPrice.js";
12
+ /** Lines of title a tile draws before it clips. See the file header. */
13
+ const TITLE_LINES = 2;
14
+ /** The class the clamped title carries, for {@link feedCardCss}. */
15
+ export const FEED_TITLE_CLASS = "stapel-listing-feed-title";
16
+ /** The `href` the hoisted feed stylesheet is deduplicated by. */
17
+ export const FEED_CARD_STYLE_HREF = "stapel-listings-feed-card";
18
+ /**
19
+ * The clamp, as a real CSS rule rather than an inline style.
20
+ *
21
+ * `-webkit-line-clamp` and `-webkit-box-orient` are the two declarations that
22
+ * do not survive the trip through an inline style object: React's serializer
23
+ * and every DOM implementation that is not a browser drop them silently, so a
24
+ * tile written that way clamps in Chrome, does not clamp in a test, and
25
+ * nothing anywhere says which. A hoisted sheet keeps one copy for the document
26
+ * and makes the rule something a test can read.
27
+ */
28
+ export function feedCardCss() {
29
+ return (`.${FEED_TITLE_CLASS}{display:-webkit-box;-webkit-box-orient:vertical;` +
30
+ `-webkit-line-clamp:${String(TITLE_LINES)};overflow:hidden}`);
31
+ }
32
+ /** The tile. `position: relative` is what the heart and the badge overlay are
33
+ * pinned to; `minWidth: 0` keeps a long word inside its grid track. */
34
+ const TILE = { position: "relative", minWidth: 0 };
35
+ /** Pinned to the photo's leading corner: the container's own marking. */
36
+ const BADGE = {
37
+ position: "absolute",
38
+ insetBlockStart: spacing[2],
39
+ insetInlineStart: spacing[2],
40
+ };
41
+ /** Pinned to the photo's trailing corner. `alignItems: flex-end` so the
42
+ * pooled-or-not reason, when there is one, stacks under the heart against the
43
+ * same edge rather than pushing it inwards. */
44
+ const HEART = {
45
+ position: "absolute",
46
+ insetBlockStart: spacing[2],
47
+ insetInlineEnd: spacing[2],
48
+ alignItems: "flex-end",
49
+ };
50
+ export function ListingFeedCard(props) {
51
+ const t = useT();
52
+ const { listing } = props;
53
+ const status = listing.status === undefined ? undefined : lifecycleCaption(listing.status);
54
+ const title = listing.title ?? "";
55
+ const targetLabel = title.length > 0 ? title : t(LISTINGS_I18N_KEYS.cardUntitled);
56
+ return (_jsxs(SkinTheme, { surface: "bare", ...(props.mode !== undefined ? { mode: props.mode } : {}), children: [_jsx("style", { href: CARD_TARGET_STYLE_HREF, precedence: "default", children: cardTargetCss() }), _jsx("style", { href: FEED_CARD_STYLE_HREF, precedence: "default", children: feedCardCss() }), _jsxs("div", { style: TILE, "data-testid": "listings-feed-card", "data-listing-id": listing.id, ...(status !== undefined
57
+ ? { "data-listing-status": status.status }
58
+ : {}), children: [_jsx(CardTarget, { ...openProps(props), listingId: listing.id, label: targetLabel, testId: "listings-feed-open", bodyTestId: "listings-feed-body", children: _jsxs(Flex, { vertical: true, gap: spacing[1], children: [_jsx(ListingPhoto, { imageRef: listing.images?.[0], alt: title.length > 0 ? title : String(listing.id), style: { borderRadius: radii.lg } }), _jsx(Typography.Text, { className: FEED_TITLE_CLASS, "data-testid": "listings-feed-title", children: title }), _jsx(Typography.Text, { strong: true, "data-testid": "listings-feed-price", children: _jsx(ListingPrice, { amount: listing.price, ...(listing.currency !== undefined
59
+ ? { currency: listing.currency }
60
+ : {}) }) }), listing.location_label !== undefined &&
61
+ listing.location_label.length > 0 ? (_jsx(Typography.Text, { type: "secondary", ellipsis: true, "data-testid": "listings-feed-location", children: listing.location_label })) : null] }) }), props.badgeOverlay !== undefined && (_jsx("div", { style: BADGE, "data-testid": "listings-feed-badge", children: props.badgeOverlay })), props.showFavorite === false ? null : (_jsx(FavoriteHeart, { listingId: listing.id, favorited: listing.is_favorited, testId: "listings-feed-favorite", style: HEART }))] })] }));
62
+ }
63
+ /** The three-armed open union, narrowed out of this card's own props — see
64
+ * `<ListingSerpCard>`'s copy for why it is picked rather than spread. */
65
+ function openProps(props) {
66
+ if (props.href !== undefined) {
67
+ return props.linkComponent !== undefined
68
+ ? { href: props.href, linkComponent: props.linkComponent }
69
+ : { href: props.href };
70
+ }
71
+ if (props.onOpen !== undefined)
72
+ return { onOpen: props.onOpen };
73
+ return {};
74
+ }
75
+ //# sourceMappingURL=ListingFeedCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListingFeedCard.js","sourceRoot":"","sources":["../../src/default/ListingFeedCard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * `<ListingSerpCard>` — the one-column result card of a phone SERP.
3
+ *
4
+ * `<ListingCard>` is the GRID card: a photo, a price, a title and a place,
5
+ * sized so twenty-four of them tile a desktop catalogue. This is the other
6
+ * shape a classified needs and the one the mobile refs are drawn to (refs §3):
7
+ * one card per row, the full width of the screen, a swipeable photo strip, and
8
+ * a column of actions down the right-hand side. They are two components rather
9
+ * than a `variant` prop for the reason the fleet keeps writing down — a mode
10
+ * switch produces one component nobody can photograph either arm of, and here
11
+ * the two arms differ in reading ORDER, not only in size.
12
+ *
13
+ * ── The price is first, and it is the biggest thing on the card ────────────
14
+ *
15
+ * On a grid card the photo carries the layout. On a one-column result the
16
+ * photo is already full-bleed above the text, so the first LINE is where the
17
+ * eye lands — and on a classified that line is the price. Title at regular
18
+ * weight underneath it, the seller's own spec line muted under that. This is
19
+ * the ref's order and it is also the order the fleet's own storefront review
20
+ * asked for: a person scanning a SERP is comparing prices, not reading names.
21
+ *
22
+ * ── Why the photo strip is OUTSIDE the anchor ─────────────────────────────
23
+ *
24
+ * `<ListingCard>` puts its photo inside the card's anchor, because a still
25
+ * `<img>` inside a link is just a bigger link. A `<SkinCarousel>` is not: it
26
+ * is a scroll container with its own tab stop, and a horizontal swipe that
27
+ * ends inside an `<a>` is a swipe the browser may deliver as a click. Putting
28
+ * the strip in the anchor would mean every attempt to look at photo two
29
+ * navigated to the listing — the defect that makes phone galleries unusable.
30
+ *
31
+ * So the strip sits above the anchor as a sibling, exactly as the heart sits
32
+ * below it as a sibling, and for the same class of reason: a link may not
33
+ * contain a control, and a swipeable strip is a control. The anchor still
34
+ * covers the four things that identify the listing — price, title, specs,
35
+ * badges — so the card opens from everything a person reads.
36
+ *
37
+ * ── The two slots, and what they are honestly for ─────────────────────────
38
+ *
39
+ * `sellerSlot` is the seller's name and rating. It is a SLOT because a rating
40
+ * aggregate belongs to `@stapel/reviews-react` and this pair does not import
41
+ * another L2 pair; the container is the seam. **The caveat a host must know:**
42
+ * `<RatingBadge>` FETCHES — one request per card. On a page of twenty results
43
+ * that is twenty requests for a decoration. A container drawing this in a list
44
+ * should render the name plus a bare `<Rate>` from an aggregate the row
45
+ * already carries, and render nothing at all when the row carries none. It
46
+ * lives outside the anchor because a seller's name is usually a link to the
47
+ * seller, and a link inside a link is neither valid nor operable.
48
+ *
49
+ * `actionsRail` is the vertical column at the trailing edge — "call", "write"
50
+ * — filled by the container from `@stapel/chat-react` and from whatever the
51
+ * deployment uses for a phone number. The pair supplies the COLUMN and the
52
+ * favourite heart at the end of it, and nothing else: this package has no
53
+ * conversation and no telephone number, and the search projection carries no
54
+ * phone (gap G-2's neighbour, recorded in the wave spec §4).
55
+ *
56
+ * ── The price trend is a seam over data that does not exist yet ───────────
57
+ *
58
+ * `priceTrend` renders the ref's "was 1 800 000 ₽ ↓". The search projection
59
+ * carries no price history — no `price_was`, no direction — so nothing on a
60
+ * live SERP fills this today (wave gap **G-2**). It ships anyway, and the
61
+ * demos show it against fixture data, because the alternative is a card that
62
+ * has to be re-laid-out the day the projection grows the field. The seam is
63
+ * the honest half; the missing data is written down rather than faked.
64
+ */
65
+ import type { ReactElement, ReactNode } from "react";
66
+ import type { ListingCard as ListingCardData } from "../api/types.js";
67
+ import type { ListingCardOpenProps } from "./ListingCard.js";
68
+ import type { ThemeModeProp } from "./types.js";
69
+ /**
70
+ * A price that moved, as the ref draws it: the old figure struck through and
71
+ * an arrow saying which way.
72
+ *
73
+ * `oldPrice` is a decimal STRING in the listing's own currency — the same
74
+ * dialect `Listing.price` speaks — so it is formatted by the same
75
+ * `<ListingPrice>` and never by a template literal.
76
+ */
77
+ export interface ListingPriceTrend {
78
+ /** The previous asking price, as the wire spells money: a decimal string. */
79
+ readonly oldPrice: string;
80
+ /** Which way it moved. `"down"` is the one a classified shouts about. */
81
+ readonly direction: "down" | "up";
82
+ }
83
+ export interface ListingSerpCardBaseProps extends ThemeModeProp {
84
+ readonly listing: ListingCardData;
85
+ /**
86
+ * The seller's own one-line summary — "Petrol 1.5 (147 hp), robot, front".
87
+ *
88
+ * A STRING the host derived, not a projection this card reads: the ref's
89
+ * spec line is a deployment's editorial choice about which features belong
90
+ * on a result and in what order, and that is a decision no library can take
91
+ * for a category it has never seen. When the host has no opinion the card
92
+ * falls back to the row's `features_title` — the projection's own summary is
93
+ * a better default line than an empty one (§83: the default skin does the
94
+ * right thing before the host wires anything).
95
+ */
96
+ readonly specsLine?: string;
97
+ /** See the file header — a seam over data the projection does not carry. */
98
+ readonly priceTrend?: ListingPriceTrend;
99
+ /** The seller's name and rating. See the file header for the per-card fetch
100
+ * caveat a container has to avoid. */
101
+ readonly sellerSlot?: ReactNode;
102
+ /** The vertical action column at the trailing edge — call, write. The
103
+ * favourite heart is added at its end by this component. */
104
+ readonly actionsRail?: ReactNode;
105
+ /** Extra chrome above the price (a `promoted` tag from search — DSA Art. 26
106
+ * marking belongs to the pair that receives it). */
107
+ readonly badge?: ReactNode;
108
+ /** Hide the favourite entirely — for a surface where it makes no sense (the
109
+ * owner's own listings). NOT a way to hide it from visitors. */
110
+ readonly showFavorite?: boolean;
111
+ }
112
+ export type ListingSerpCardProps = ListingSerpCardBaseProps & ListingCardOpenProps;
113
+ export declare function ListingSerpCard(props: ListingSerpCardProps): ReactElement;
114
+ //# sourceMappingURL=ListingSerpCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListingSerpCard.d.ts","sourceRoot":"","sources":["../../src/default/ListingSerpCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,OAAO,KAAK,EAAiB,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMpE,OAAO,KAAK,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAetE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,wBAAyB,SAAQ,aAAa;IAC7D,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;IACxC;0CACsC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAC;IAChC;gEAC4D;IAC5D,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC;IACjC;wDACoD;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC3B;oEACgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,MAAM,oBAAoB,GAAG,wBAAwB,GAAG,oBAAoB,CAAC;AAUnF,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,YAAY,CAkNzE"}
@@ -0,0 +1,72 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Card, Flex, Typography, theme as antdTheme } from "antd";
3
+ import { SkinCarousel, SkinTheme } from "@stapel/tokens-antd/skin";
4
+ import { useT } from "@stapel/core";
5
+ import { fontSize, spacing } from "@stapel/tokens";
6
+ import { FeatureBadges } from "@stapel/attributes-react/default";
7
+ import { asFeatureDaoList, featuresDtoFromDaoList, featuresFromDaoList, } from "../model/features.js";
8
+ import { lifecycleCaption } from "../model/status.js";
9
+ import { LISTINGS_I18N_KEYS } from "../i18n/keys.js";
10
+ import { PriceTrendIcon } from "./icons.js";
11
+ import { FavoriteHeart } from "./favorite.js";
12
+ import { CARD_TARGET_STYLE_HREF, CardTarget, cardTargetCss, } from "./ListingCard.js";
13
+ import { LISTING_PHOTO_ASPECT, ListingPhoto } from "./ListingPhoto.js";
14
+ import { ListingPrice } from "./ListingPrice.js";
15
+ /** The trailing column. Fixed width contribution: it must not take room from
16
+ * the text as the actions grow. */
17
+ const RAIL = { flex: "0 0 auto" };
18
+ /** The reading column. `minWidth: 0` so a long unbroken word cannot push the
19
+ * rail off the card. */
20
+ const BODY = { flex: "1 1 auto", minWidth: 0 };
21
+ export function ListingSerpCard(props) {
22
+ const t = useT();
23
+ const { listing, priceTrend } = props;
24
+ const { token } = antdTheme.useToken();
25
+ const badgeDaos = asFeatureDaoList(listing.features_badges);
26
+ const badgeFeatures = featuresFromDaoList(badgeDaos);
27
+ const badgeValues = featuresDtoFromDaoList(badgeDaos);
28
+ // The fallback spec line when the host derived none: the row's own
29
+ // `features_title` projection, exactly the line `ListingCard` draws.
30
+ const titleDaos = props.specsLine !== undefined && props.specsLine.length > 0
31
+ ? []
32
+ : asFeatureDaoList(listing.features_title);
33
+ const status = listing.status === undefined ? undefined : lifecycleCaption(listing.status);
34
+ const title = listing.title ?? "";
35
+ const targetLabel = title.length > 0 ? title : t(LISTINGS_I18N_KEYS.cardUntitled);
36
+ const photos = listing.images ?? [];
37
+ const currency = listing.currency !== undefined ? { currency: listing.currency } : {};
38
+ // A one-photo strip gets neither a peek nor dots: the sliver of a next slide
39
+ // is an affordance for something that is there, and on a single photo it is
40
+ // just a strip of dead space at the trailing edge (`SkinCarousel` says the
41
+ // same thing from its own side).
42
+ const many = photos.length > 1;
43
+ const rail = props.actionsRail !== undefined || props.showFavorite !== false ? (_jsxs(Flex, { vertical: true, align: "flex-end", gap: spacing[2], style: RAIL, "data-testid": "listings-serp-actions", children: [props.actionsRail, props.showFavorite === false ? null : (_jsx(FavoriteHeart, { listingId: listing.id, favorited: listing.is_favorited, testId: "listings-serp-favorite" }))] })) : null;
44
+ return (_jsxs(SkinTheme, { surface: "bare", ...(props.mode !== undefined ? { mode: props.mode } : {}), children: [_jsx("style", { href: CARD_TARGET_STYLE_HREF, precedence: "default", children: cardTargetCss() }), _jsx(Card, { size: "small", "data-testid": "listings-serp-card", "data-listing-id": listing.id, ...(status !== undefined
45
+ ? { "data-listing-status": status.status }
46
+ : {}), styles: { body: { minWidth: 0, padding: token.paddingSM } }, style: { ["--listing-card-focus"]: token.colorPrimary }, children: _jsxs(Flex, { vertical: true, gap: spacing[3], children: [_jsx(SkinCarousel, { label: t(LISTINGS_I18N_KEYS.cardPhotos), aspectRatio: LISTING_PHOTO_ASPECT, peek: many, dots: many, "data-testid": "listings-serp-photos", children: photos.length === 0 ? (_jsx(ListingPhoto, { imageRef: undefined, alt: title.length > 0 ? title : String(listing.id) })) : (photos.map((reference, index) => (_jsx(ListingPhoto, { imageRef: reference, alt: t(LISTINGS_I18N_KEYS.detailPhotoAlt, {
47
+ index: index + 1,
48
+ total: photos.length,
49
+ }) }, reference)))) }), _jsxs(Flex, { gap: spacing[3], align: "flex-start", children: [_jsxs(Flex, { vertical: true, gap: spacing[1], style: BODY, children: [_jsxs(CardTarget, { ...openProps(props), listingId: listing.id, label: targetLabel, testId: "listings-serp-open", bodyTestId: "listings-serp-body", children: [props.badge, _jsxs(Flex, { align: "center", gap: spacing[2], wrap: true, children: [_jsx(Typography.Text, { strong: true, style: { fontSize: fontSize.xl.fontSize }, "data-testid": "listings-serp-price", children: _jsx(ListingPrice, { amount: listing.price, ...currency }) }), priceTrend !== undefined && (_jsx(PriceTrendIcon, { direction: priceTrend.direction, label: t(priceTrend.direction === "down"
50
+ ? LISTINGS_I18N_KEYS.cardPriceDropped
51
+ : LISTINGS_I18N_KEYS.cardPriceRaised) }))] }), priceTrend !== undefined && (_jsxs(Flex, { align: "baseline", gap: spacing[1], "data-testid": "listings-serp-old-price", children: [_jsx(Typography.Text, { type: "secondary", children: t(LISTINGS_I18N_KEYS.cardPriceWas) }), _jsx(Typography.Text, { type: "secondary", delete: true, children: _jsx(ListingPrice, { amount: priceTrend.oldPrice, ...currency }) })] })), _jsx(Typography.Text, { "data-testid": "listings-serp-title", children: title }), props.specsLine !== undefined && props.specsLine.length > 0 ? (_jsx(Typography.Text, { type: "secondary", ellipsis: true, "data-testid": "listings-serp-specs", children: props.specsLine })) : titleDaos.length > 0 ? (_jsx(Typography.Text, { type: "secondary", ellipsis: true, "data-testid": "listings-serp-specs", children: _jsx(FeatureBadges, { features: featuresFromDaoList(titleDaos).map((view) => view.feature), values: featuresDtoFromDaoList(titleDaos) }) })) : null, badgeFeatures.length > 0 ? (_jsx(FeatureBadges, { features: badgeFeatures.map((view) => view.feature), values: badgeValues })) : null] }), props.sellerSlot ?? null, listing.location_label !== undefined &&
52
+ listing.location_label.length > 0 ? (_jsx(Typography.Text, { type: "secondary", "data-testid": "listings-serp-location", children: listing.location_label })) : null] }), rail] })] }) })] }));
53
+ }
54
+ /**
55
+ * The three-armed open union, narrowed back out of this card's own props.
56
+ *
57
+ * Spreading `props` straight into `<CardTarget>` would hand it `listing`,
58
+ * `sellerSlot` and the rest as DOM attributes on the arms that render a plain
59
+ * `<a>`; picking the union's members explicitly keeps the anchor clean and
60
+ * keeps exactly one of the three arms reachable.
61
+ */
62
+ function openProps(props) {
63
+ if (props.href !== undefined) {
64
+ return props.linkComponent !== undefined
65
+ ? { href: props.href, linkComponent: props.linkComponent }
66
+ : { href: props.href };
67
+ }
68
+ if (props.onOpen !== undefined)
69
+ return { onOpen: props.onOpen };
70
+ return {};
71
+ }
72
+ //# sourceMappingURL=ListingSerpCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListingSerpCard.js","sourceRoot":"","sources":["../../src/default/ListingSerpCard.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The favourite heart, once — the control every card surface in this pair
3
+ * draws and none of them may draw differently.
4
+ *
5
+ * `<ListingCard>` had it inline, and the two phone cards added in the mobile
6
+ * wave (`<ListingSerpCard>`, `<ListingFeedCard>`) need exactly the same thing:
7
+ * the same hook, the same gate, the same `aria-pressed`, the same refusal
8
+ * printed as text rather than as a tooltip. Three copies of that is three
9
+ * places for the anonymous arm to drift apart in, and the anonymous arm is
10
+ * most of a storefront's traffic. So it lives here and the surfaces differ
11
+ * only in WHERE they put it.
12
+ *
13
+ * This module is deliberately NOT re-exported from `src/default/index.ts`: it
14
+ * is how this pair's own cards are built, not a control a host composes with.
15
+ * A host that wants a favourite button outside a card has `useFavoriteToggle`.
16
+ *
17
+ * ── The refusal, and why a grid needs a scope ──────────────────────────────
18
+ *
19
+ * `<GatedControl>` prints the gate's reason beside the control and wires
20
+ * `aria-describedby` to it. That is right for ONE card and wrong for forty:
21
+ * the same sentence forty times is the loudest thing on a results page. The
22
+ * substrate already answers this — `GateReasonScopeContext` (a `<PaneGate>`
23
+ * provides one) pools identical reasons and renders each once, and a
24
+ * `GatedControl` inside a scope renders no text of its own while keeping the
25
+ * `aria-describedby` pointed at the scope's single copy. A container drawing a
26
+ * list or a grid of these cards should wrap it in one.
27
+ */
28
+ import type { CSSProperties, ReactElement } from "react";
29
+ export interface FavoriteHeartProps {
30
+ readonly listingId: number;
31
+ /** `is_favorited` off the row. `null` is the third state — a search hit
32
+ * never says whether you saved it — and reads as "not saved". */
33
+ readonly favorited: boolean | null | undefined;
34
+ /** Test id of the button; the gate wrapper takes `${testId}-gate`. */
35
+ readonly testId: string;
36
+ /** `"inline"` puts the reason beside the heart, `"stack"` (default) under
37
+ * it — the choice belongs to the surface, which knows its own geometry. */
38
+ readonly layout?: "stack" | "inline";
39
+ readonly style?: CSSProperties;
40
+ }
41
+ /**
42
+ * The heart and its refusal. It is NEVER hidden from a visitor: it is blocked,
43
+ * the reason is on the page as ordinary text, and the container's sign-in door
44
+ * (`signIn`) is the surface's business, not this control's — a disabled antd
45
+ * button fires no pointer events, so a tooltip here would be a reason nobody
46
+ * could read on any device (`stapel/no-tooltip-in-skin`).
47
+ */
48
+ export declare function FavoriteHeart(props: FavoriteHeartProps): ReactElement;
49
+ //# sourceMappingURL=favorite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"favorite.d.ts","sourceRoot":"","sources":["../../src/default/favorite.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAQzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;qEACiE;IACjE,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/C,sEAAsE;IACtE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;+EAC2E;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;CAChC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,YAAY,CAmCrE"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Button } from "antd";
3
+ import { GatedControl } from "@stapel/tokens-antd/skin";
4
+ import { useT } from "@stapel/core";
5
+ import { useFavoriteToggle } from "../headless/Favorites.js";
6
+ import { LISTINGS_I18N_KEYS } from "../i18n/keys.js";
7
+ import { HeartIcon } from "./icons.js";
8
+ /**
9
+ * The heart and its refusal. It is NEVER hidden from a visitor: it is blocked,
10
+ * the reason is on the page as ordinary text, and the container's sign-in door
11
+ * (`signIn`) is the surface's business, not this control's — a disabled antd
12
+ * button fires no pointer events, so a tooltip here would be a reason nobody
13
+ * could read on any device (`stapel/no-tooltip-in-skin`).
14
+ */
15
+ export function FavoriteHeart(props) {
16
+ const t = useT();
17
+ const favorite = useFavoriteToggle(props.listingId, props.favorited);
18
+ const label = t(favorite.favorited
19
+ ? LISTINGS_I18N_KEYS.cardFavoriteRemove
20
+ : LISTINGS_I18N_KEYS.cardFavoriteAdd);
21
+ return (_jsx(GatedControl, { gate: favorite.gate, testId: `${props.testId}-gate`, ...(props.layout !== undefined ? { layout: props.layout } : {}), ...(props.style !== undefined ? { style: props.style } : {}), children: (bind) => (_jsx(Button, { shape: "circle", disabled: bind.disabled, "data-disabled-reason": "the enclosing <GatedControl> renders the gate's reason beside this button", ...(bind["aria-describedby"] !== undefined
22
+ ? { "aria-describedby": bind["aria-describedby"] }
23
+ : {}), "aria-label": label, "aria-pressed": favorite.favorited, "data-testid": props.testId, "data-favorited": String(favorite.favorited), "data-analytics": "none", "data-analytics-reason": "business action \u2014 host app wraps with its own tracked()", onClick: favorite.toggle, icon: _jsx(HeartIcon, { filled: favorite.favorited }) })) }));
24
+ }
25
+ //# sourceMappingURL=favorite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"favorite.js","sourceRoot":"","sources":["../../src/default/favorite.tsx"],"names":[],"mappings":";AA4BA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAevC;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACrE,MAAM,KAAK,GAAG,CAAC,CACb,QAAQ,CAAC,SAAS;QAChB,CAAC,CAAC,kBAAkB,CAAC,kBAAkB;QACvC,CAAC,CAAC,kBAAkB,CAAC,eAAe,CACvC,CAAC;IACF,OAAO,CACL,KAAC,YAAY,IACX,IAAI,EAAE,QAAQ,CAAC,IAAI,EACnB,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,OAAO,KAC1B,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAC5D,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,YAE5D,CAAC,IAAI,EAAE,EAAE,CAAC,CACT,KAAC,MAAM,IACL,KAAK,EAAC,QAAQ,EACd,QAAQ,EAAE,IAAI,CAAC,QAAQ,0BACF,2EAA2E,KAC5F,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,SAAS;gBACzC,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,CAAC,EAAE;gBAClD,CAAC,CAAC,EAAE,CAAC,gBACK,KAAK,kBACH,QAAQ,CAAC,SAAS,iBACnB,KAAK,CAAC,MAAM,oBACT,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,oBAC3B,MAAM,2BACC,8DAAyD,EAC/E,OAAO,EAAE,QAAQ,CAAC,MAAM,EACxB,IAAI,EAAE,KAAC,SAAS,IAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,GAAI,GAC/C,CACH,GACY,CAChB,CAAC;AACJ,CAAC"}
@@ -1,16 +1,30 @@
1
1
  /**
2
- * One inline glyph: the favourite heart, filled and outlined.
2
+ * The pair's inline glyphs: the favourite heart, and the price-trend arrow.
3
3
  *
4
4
  * No `@ant-design/icons` dependency — the house convention (profiles-react's
5
5
  * `icons.tsx`, shell-react's icon registry): a plain monochrome
6
6
  * `currentColor` SVG, so it inherits the theme instead of carrying a colour
7
7
  * of its own, and the pair stays one package lighter.
8
8
  *
9
- * `aria-hidden` on both: the button that holds them carries the label, and a
10
- * glyph announced beside its own label reads the action twice.
9
+ * `aria-hidden` on the heart: the button that holds it carries the label, and
10
+ * a glyph announced beside its own label reads the action twice. The TREND
11
+ * arrow is the opposite case — it is the only thing on the line saying which
12
+ * way the price moved, so it takes a name from the caller and is announced.
11
13
  */
12
14
  import type { ReactElement } from "react";
13
15
  export declare function HeartIcon(props: {
14
16
  filled: boolean;
15
17
  }): ReactElement;
18
+ /**
19
+ * Which way the asking price moved — an arrow, and a NAME for it.
20
+ *
21
+ * The arrow is the whole message ("this got cheaper"), so unlike the heart it
22
+ * is not `aria-hidden`: it carries `role="img"` and the sentence the caller
23
+ * resolved from its own key registry. A glyph that means something and is
24
+ * hidden from assistive tech means nothing to the people who need it stated.
25
+ */
26
+ export declare function PriceTrendIcon(props: {
27
+ direction: "down" | "up";
28
+ label: string;
29
+ }): ReactElement;
16
30
  //# sourceMappingURL=icons.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/default/icons.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,YAAY,CAiBlE"}
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/default/icons.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,wBAAgB,SAAS,CAAC,KAAK,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG,YAAY,CAiBlE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,YAAY,CAmBf"}
@@ -1,5 +1,17 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  export function HeartIcon(props) {
3
3
  return (_jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: props.filled ? "currentColor" : "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", role: "img", "aria-hidden": "true", children: _jsx("path", { d: "M20.8 4.6a5.5 5.5 0 0 0-7.8 0L12 5.7l-1-1.1a5.5 5.5 0 0 0-7.8 7.8l1.1 1L12 21l7.7-7.6 1.1-1a5.5 5.5 0 0 0 0-7.8z" }) }));
4
4
  }
5
+ /**
6
+ * Which way the asking price moved — an arrow, and a NAME for it.
7
+ *
8
+ * The arrow is the whole message ("this got cheaper"), so unlike the heart it
9
+ * is not `aria-hidden`: it carries `role="img"` and the sentence the caller
10
+ * resolved from its own key registry. A glyph that means something and is
11
+ * hidden from assistive tech means nothing to the people who need it stated.
12
+ */
13
+ export function PriceTrendIcon(props) {
14
+ const down = props.direction === "down";
15
+ return (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", role: "img", "aria-label": props.label, children: [_jsx("path", { d: down ? "M12 5v14" : "M12 19V5" }), _jsx("path", { d: down ? "M6 13l6 6 6-6" : "M6 11l6-6 6 6" })] }));
16
+ }
5
17
  //# sourceMappingURL=icons.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"icons.js","sourceRoot":"","sources":["../../src/default/icons.tsx"],"names":[],"mappings":";AAaA,MAAM,UAAU,SAAS,CAAC,KAA0B;IAClD,OAAO,CACL,cACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,EAC5C,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,IAAI,EAAC,KAAK,iBACE,MAAM,YAElB,eAAM,CAAC,EAAC,kHAAkH,GAAG,GACzH,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"icons.js","sourceRoot":"","sources":["../../src/default/icons.tsx"],"names":[],"mappings":";AAeA,MAAM,UAAU,SAAS,CAAC,KAA0B;IAClD,OAAO,CACL,cACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,EAC5C,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,IAAI,EAAC,KAAK,iBACE,MAAM,YAElB,eAAM,CAAC,EAAC,kHAAkH,GAAG,GACzH,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,KAG9B;IACC,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC;IACxC,OAAO,CACL,eACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,IAAI,EAAC,KAAK,gBACE,KAAK,CAAC,KAAK,aAEvB,eAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,GAAI,EAC3C,eAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe,GAAI,IACjD,CACP,CAAC;AACJ,CAAC"}
@@ -1,7 +1,17 @@
1
1
  /**
2
- * `@stapel/listings-react/default` — the antd skin: the card another pair
2
+ * `@stapel/listings-react/default` — the antd skin: the cards another pair
3
3
  * renders, the listing page, the composer and the seller's dashboard.
4
4
  *
5
+ * ── Three cards, because a classified has three shelves ────────────────────
6
+ *
7
+ * `ListingCard` is the grid card (a bordered surface, photo-led, twenty-four
8
+ * to a desktop catalogue). `ListingSerpCard` is the phone result row (one per
9
+ * line, a swipeable photo strip, PRICE first, a vertical action rail).
10
+ * `ListingFeedCard` + `FeedGrid` are the home feed (borderless, two across,
11
+ * the photo carried on the page's own ground). They are three components and
12
+ * not one with a `variant`, because they differ in READING ORDER and in what
13
+ * may live inside the card's anchor — not merely in size.
14
+ *
5
15
  * A separate entry point (the convention every pair's `/default` follows) so
6
16
  * a host rendering its own visuals over the bags never pulls `antd` into its
7
17
  * bundle.
@@ -25,6 +35,12 @@
25
35
  */
26
36
  export { ListingCard } from "./ListingCard.js";
27
37
  export type { ListingCardProps, ListingCardBaseProps, ListingCardOpenProps, ListingCardBlockedReason, } from "./ListingCard.js";
38
+ export { ListingSerpCard } from "./ListingSerpCard.js";
39
+ export type { ListingSerpCardProps, ListingSerpCardBaseProps, ListingPriceTrend, } from "./ListingSerpCard.js";
40
+ export { ListingFeedCard } from "./ListingFeedCard.js";
41
+ export type { ListingFeedCardProps, ListingFeedCardBaseProps, } from "./ListingFeedCard.js";
42
+ export { FeedGrid, FEED_GRID_COLUMNS } from "./FeedGrid.js";
43
+ export type { FeedGridProps } from "./FeedGrid.js";
28
44
  export { ListingDetailPane, DETAIL_MEASURE, DETAIL_PHOTO_MIN } from "./ListingDetailPane.js";
29
45
  export type { ListingDetailPaneProps } from "./ListingDetailPane.js";
30
46
  export { ListingComposerPage, COMPOSER_MEASURE } from "./ListingComposerPage.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC7F,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjF,YAAY,EACV,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACvE,YAAY,EACV,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACnF,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACvE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EACV,oBAAoB,EACpB,wBAAwB,EACxB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EACV,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAC5D,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC7F,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjF,YAAY,EACV,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACvE,YAAY,EACV,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACnF,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACvE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -1,7 +1,17 @@
1
1
  /**
2
- * `@stapel/listings-react/default` — the antd skin: the card another pair
2
+ * `@stapel/listings-react/default` — the antd skin: the cards another pair
3
3
  * renders, the listing page, the composer and the seller's dashboard.
4
4
  *
5
+ * ── Three cards, because a classified has three shelves ────────────────────
6
+ *
7
+ * `ListingCard` is the grid card (a bordered surface, photo-led, twenty-four
8
+ * to a desktop catalogue). `ListingSerpCard` is the phone result row (one per
9
+ * line, a swipeable photo strip, PRICE first, a vertical action rail).
10
+ * `ListingFeedCard` + `FeedGrid` are the home feed (borderless, two across,
11
+ * the photo carried on the page's own ground). They are three components and
12
+ * not one with a `variant`, because they differ in READING ORDER and in what
13
+ * may live inside the card's anchor — not merely in size.
14
+ *
5
15
  * A separate entry point (the convention every pair's `/default` follows) so
6
16
  * a host rendering its own visuals over the bags never pulls `antd` into its
7
17
  * bundle.
@@ -24,6 +34,9 @@
24
34
  * `<SkinTheme>` from the substrate instead — same props, plus a `surface`.
25
35
  */
26
36
  export { ListingCard } from "./ListingCard.js";
37
+ export { ListingSerpCard } from "./ListingSerpCard.js";
38
+ export { ListingFeedCard } from "./ListingFeedCard.js";
39
+ export { FeedGrid, FEED_GRID_COLUMNS } from "./FeedGrid.js";
27
40
  export { ListingDetailPane, DETAIL_MEASURE, DETAIL_PHOTO_MIN } from "./ListingDetailPane.js";
28
41
  export { ListingComposerPage, COMPOSER_MEASURE } from "./ListingComposerPage.js";
29
42
  export { MyListingsPane } from "./MyListingsPane.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAO/C,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE7F,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AASjF,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAMvE,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/default/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAO/C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAMvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAKvD,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE5D,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE7F,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AASjF,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAMvE,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../src/i18n/es.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,EAAE,cAqMlC,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAG7D"}
1
+ {"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../src/i18n/es.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,EAAE,cAyMlC,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAG7D"}
package/dist/i18n/es.js CHANGED
@@ -54,6 +54,10 @@ export const listingsI18nBundleEs = {
54
54
  "listings.card.favorite_remove": "Quitar de favoritos",
55
55
  "listings.card.untitled": "Anuncio sin título",
56
56
  "listings.card.sign_in": "Iniciar sesión",
57
+ "listings.card.photos": "Fotos de este anuncio",
58
+ "listings.card.price_was": "Antes",
59
+ "listings.card.price_dropped": "El precio ha bajado",
60
+ "listings.card.price_raised": "El precio ha subido",
57
61
  "listings.detail.loading": "Cargando el anuncio…",
58
62
  "listings.detail.load_failed": "No pudimos cargar este anuncio",
59
63
  "listings.detail.retry": "Reintentar",
@@ -1 +1 @@
1
- {"version":3,"file":"es.js","sourceRoot":"","sources":["../../src/i18n/es.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"es.js","sourceRoot":"","sources":["../../src/i18n/es.ts"],"names":[],"mappings":"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"}
@@ -67,6 +67,17 @@ export declare const LISTINGS_I18N_KEYS: {
67
67
  readonly cardUntitled: "listings.card.untitled";
68
68
  /** The door beside a blocked favourite: the container supplies WHERE. */
69
69
  readonly cardSignIn: "listings.card.sign_in";
70
+ /** The accessible name of `<ListingSerpCard>`'s photo strip. `SkinCarousel`
71
+ * requires one — an unnamed scrollable region is announced as nothing — and
72
+ * the token bridge owns no i18n engine, so the copy is this pair's. */
73
+ readonly cardPhotos: "listings.card.photos";
74
+ /** The label on the struck-through previous price. The strike is styling and
75
+ * a screen reader announces none of it, so the word is on the line. */
76
+ readonly cardPriceWas: "listings.card.price_was";
77
+ /** The name of the trend arrow — the whole message of a glyph that would
78
+ * otherwise be a decoration nobody can read. */
79
+ readonly cardPriceDropped: "listings.card.price_dropped";
80
+ readonly cardPriceRaised: "listings.card.price_raised";
70
81
  readonly detailLoading: "listings.detail.loading";
71
82
  readonly detailLoadFailed: "listings.detail.load_failed";
72
83
  readonly detailRetry: "listings.detail.retry";
@@ -1 +1 @@
1
- {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/i18n/keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;IAe7B,+CAA+C;;IAE/C,qEAAqE;;IAErE,yEAAyE;;;;;IAKzE,oEAAoE;;;;;;;IASpE;;;;;;;;;OASG;;IAEH,yEAAyE;;;;;;IAQzE,oEAAoE;;IAEpE,8EAA8E;;;;;;;;;;;IAW9E;;oDAEgD;;IAEhD,2DAA2D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8C3D;;+CAE2C;;;;;;;;;;;;IAc3C;iEAC6D;;;;IAI7D;iEAC6D;;;;;;;;IAQ7D;6CACyC;;;;;;;;;;;;IAgBzC;yCACqC;;;;IAIrC;;wEAEoE;;;;;;;;;CAa5D,CAAC;AAEX,MAAM,MAAM,eAAe,GACzB,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC;AAE/D;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAuLvD,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAE3D"}
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/i18n/keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;IAe7B,+CAA+C;;IAE/C,qEAAqE;;IAErE,yEAAyE;;;;;IAKzE,oEAAoE;;;;;;;IASpE;;;;;;;;;OASG;;IAEH,yEAAyE;;IAEzE;;2EAEuE;;IAEvE;2EACuE;;IAEvE;oDACgD;;;;;;;IAShD,oEAAoE;;IAEpE,8EAA8E;;;;;;;;;;;IAW9E;;oDAEgD;;IAEhD,2DAA2D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8C3D;;+CAE2C;;;;;;;;;;;;IAc3C;iEAC6D;;;;IAI7D;iEAC6D;;;;;;;;IAQ7D;6CACyC;;;;;;;;;;;;IAgBzC;yCACqC;;;;IAIrC;;wEAEoE;;;;;;;;;CAa5D,CAAC;AAEX,MAAM,MAAM,eAAe,GACzB,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,OAAO,kBAAkB,CAAC,CAAC;AAE/D;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA2LvD,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAE3D"}