@stapel/listings-react 0.15.0 → 0.15.1
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/CHANGELOG.md +10 -0
- package/dist/default/ListingDetailPane.d.ts +10 -0
- package/dist/default/ListingDetailPane.d.ts.map +1 -1
- package/dist/default/ListingDetailPane.js +4 -3
- package/dist/default/ListingDetailPane.js.map +1 -1
- package/llms.txt +1 -1
- package/manifest.json +1 -1
- package/nav-manifest.json +1 -1
- package/package.json +3 -3
- package/src/analytics/generated/events.json +1 -1
- package/src/default/ListingDetailPane.tsx +24 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @stapel/listings-react
|
|
2
2
|
|
|
3
|
+
## 0.15.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 47b23c8: `<ListingDetailPane>` takes `signIn` — the same `SignInCta` seam its three
|
|
8
|
+
card skins already take — and renders the container's sign-in door beside the
|
|
9
|
+
blocked favourite's reason. Measured on a live storefront: the pane's heart
|
|
10
|
+
said "sign in to do this" with the nearest sign-in a screen-corner away,
|
|
11
|
+
which is exactly the gap `signIn` closed on the cards.
|
|
12
|
+
|
|
3
13
|
## 0.15.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
* page whose only verb is "save".
|
|
35
35
|
*/
|
|
36
36
|
import type { ReactElement, ReactNode } from "react";
|
|
37
|
+
import type { SignInCta } from "@stapel/core";
|
|
37
38
|
import type { CategoryFeaturesProp, ThemeModeProp } from "./types.js";
|
|
38
39
|
/** The reading measure of the page body. A detail page is prose plus a spec
|
|
39
40
|
* table; past this it stops being one column and starts being a stripe across
|
|
@@ -64,6 +65,15 @@ export interface ListingDetailPaneProps extends ThemeModeProp, CategoryFeaturesP
|
|
|
64
65
|
* button). Cross-pair navigation is the container's job (spec §6.2 item 5),
|
|
65
66
|
* so this pair takes nodes rather than routes. */
|
|
66
67
|
readonly actions?: ReactNode;
|
|
68
|
+
/**
|
|
69
|
+
* The container's sign-in door, rendered beside the favourite's refusal —
|
|
70
|
+
* the same `SignInCta` seam the three card skins already take. The pane was
|
|
71
|
+
* the one heart in this pair whose "sign in to do this" had no door next to
|
|
72
|
+
* it (measured on a live storefront: the sentence, and the nearest sign-in
|
|
73
|
+
* a screen-corner away), which is exactly the gap `signIn` closed on the
|
|
74
|
+
* cards. Absent: the reason stands alone, as before.
|
|
75
|
+
*/
|
|
76
|
+
readonly signIn?: SignInCta;
|
|
67
77
|
readonly footer?: ReactNode;
|
|
68
78
|
}
|
|
69
79
|
export declare function ListingDetailPane(props: ListingDetailPaneProps): ReactElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListingDetailPane.d.ts","sourceRoot":"","sources":["../../src/default/ListingDetailPane.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ListingDetailPane.d.ts","sourceRoot":"","sources":["../../src/default/ListingDetailPane.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAerD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAa9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEtE;;oBAEoB;AACpB,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC;;;;iCAIiC;AACjC,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC,MAAM,WAAW,sBACf,SAAQ,aAAa,EACnB,oBAAoB;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;6BAEyB;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC;IACjC;6EACyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC;;sDAEkD;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;CAC7B;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,YAAY,CAsT7E"}
|
|
@@ -9,6 +9,7 @@ import { useListingDetail } from "../headless/ListingDetail.js";
|
|
|
9
9
|
import { useListingActions } from "../headless/ListingActions.js";
|
|
10
10
|
import { asFeatureDaoList, featureValuesForDisplay } from "../model/features.js";
|
|
11
11
|
import { LISTINGS_I18N_KEYS } from "../i18n/keys.js";
|
|
12
|
+
import { SignInLink } from "./SignInLink.js";
|
|
12
13
|
import { HeartIcon } from "./icons.js";
|
|
13
14
|
import { ListingPhoto } from "./ListingPhoto.js";
|
|
14
15
|
import { ListingPrice } from "./ListingPrice.js";
|
|
@@ -63,9 +64,9 @@ export function ListingDetailPane(props) {
|
|
|
63
64
|
? { currency: listing.currency }
|
|
64
65
|
: {}) }) }), _jsxs(Flex, { wrap: true, gap: spacing[3], align: "flex-start", "data-testid": "listings-detail-actions", children: [owner ? (_jsxs(_Fragment, { children: [_jsx(GatedButton, { gate: editGate, type: "primary", testId: "listings-detail-edit", "data-analytics": "none", "data-analytics-reason": "business action \u2014 host app wraps with its own tracked()", onClick: () => {
|
|
65
66
|
props.onEdit?.(props.id);
|
|
66
|
-
}, children: t(LISTINGS_I18N_KEYS.detailEdit) }), _jsx(GatedButton, { gate: actions.archive, danger: true, testId: "listings-detail-take-down", "data-analytics": "none", "data-analytics-reason": "business action \u2014 host app wraps with its own tracked()", onClick: actions.doArchive, children: t(LISTINGS_I18N_KEYS.detailTakeDown) })] })) : (_jsx("div", { "data-testid": "listings-detail-contact", children: props.contactSlot ?? _jsx(SlotPlaceholder, { name: "contactSlot" }) })), owner ? null : (_jsx(GatedControl, { gate: bag.favoriteGate, testId: "listings-detail-favorite-gate", children: (bind) => (_jsx(Button, { disabled: bind.disabled, "data-disabled-reason": "the enclosing <GatedControl> renders the gate's reason beside this button", ...(bind["aria-describedby"] !== undefined
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
}, children: t(LISTINGS_I18N_KEYS.detailEdit) }), _jsx(GatedButton, { gate: actions.archive, danger: true, testId: "listings-detail-take-down", "data-analytics": "none", "data-analytics-reason": "business action \u2014 host app wraps with its own tracked()", onClick: actions.doArchive, children: t(LISTINGS_I18N_KEYS.detailTakeDown) })] })) : (_jsx("div", { "data-testid": "listings-detail-contact", children: props.contactSlot ?? _jsx(SlotPlaceholder, { name: "contactSlot" }) })), owner ? null : (_jsxs(Flex, { vertical: true, gap: spacing[1], children: [_jsx(GatedControl, { gate: bag.favoriteGate, testId: "listings-detail-favorite-gate", children: (bind) => (_jsx(Button, { disabled: bind.disabled, "data-disabled-reason": "the enclosing <GatedControl> renders the gate's reason beside this button", ...(bind["aria-describedby"] !== undefined
|
|
68
|
+
? { "aria-describedby": bind["aria-describedby"] }
|
|
69
|
+
: {}), "aria-label": favoriteLabel, "aria-pressed": bag.isFavorited === true, icon: _jsx(HeartIcon, { filled: bag.isFavorited === true }), "data-testid": "listings-detail-favorite", "data-analytics": "none", "data-analytics-reason": "business action \u2014 host app wraps with its own tracked()", onClick: bag.toggleFavorite, children: favoriteLabel })) }), bag.favoriteGate.available ? null : (_jsx(Typography.Text, { type: "secondary", "data-testid": "listings-detail-favorite-blocked", children: _jsx(SignInLink, { cta: props.signIn, testId: "listings-detail-sign-in" }) }))] })), props.actions] }), actions.error !== undefined && actions.error !== null ? (_jsx(ErrorAlert, { testId: "listings-detail-action-error", thrown: actions.error, variant: "inline" })) : null, _jsx(Divider, {}), _jsx(Typography.Title, { level: 5, children: t(LISTINGS_I18N_KEYS.detailDescription) }), _jsx(Typography.Paragraph, { "data-testid": "listings-detail-description", children: listing.description ?? "" }), _jsx(Typography.Title, { level: 5, children: t(LISTINGS_I18N_KEYS.detailSpecs) }), bag.features.length === 0 ? (_jsx(Typography.Text, { type: "secondary", "data-testid": "listings-detail-no-specs", children: t(LISTINGS_I18N_KEYS.detailNoSpecs) })) : (_jsx(FeatureValueList, { features: bag.features.map((view) => view.feature),
|
|
69
70
|
// The DISPLAY envelope, not the edit one: a redacted row
|
|
70
71
|
// keeps its place in the table and says the seller supplied
|
|
71
72
|
// the value. `featuresDtoFromDaoList` deliberately drops a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListingDetailPane.js","sourceRoot":"","sources":["../../src/default/ListingDetailPane.tsx"],"names":[],"mappings":";AAoCA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvE,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,SAAS,GACV,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,eAAe,EACf,SAAS,EACT,OAAO,EACP,IAAI,GACL,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"ListingDetailPane.js","sourceRoot":"","sources":["../../src/default/ListingDetailPane.tsx"],"names":[],"mappings":"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"}
|
package/llms.txt
CHANGED
package/manifest.json
CHANGED
package/nav-manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stapel/listings-react",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Headless React pair for stapel-listings: a typed client over the draft twin, the composer that turns a category schema into a submittable listing, and the owner's dashboard. Two independent axes are rendered as two — lifecycle `status` decides visibility and `moderation_status` decides nothing about it, so an edit to a live listing stays live and says 'under review' instead of vanishing. Feature values are drawn and mirrored by @stapel/attributes-react; photos arrive as an injected upload bag whose `refs` ARE `images_draft` and whose `settled` gates the submit; a publish refusal is routed onto the control that caused it by slug. Zero visual opinion in the main entry; an opt-in /default subpath ships the antd skin.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -102,13 +102,13 @@
|
|
|
102
102
|
"size-limit": "^11.2.0",
|
|
103
103
|
"typescript": "^5.8.3",
|
|
104
104
|
"vitest": "^3.2.4",
|
|
105
|
-
"@stapel/attributes-react": "^0.
|
|
105
|
+
"@stapel/attributes-react": "^0.11.0",
|
|
106
106
|
"@stapel/core": "^0.23.0",
|
|
107
107
|
"@stapel/currencies-react": "^0.3.0",
|
|
108
108
|
"@stapel/image": "^0.4.2",
|
|
109
109
|
"@stapel/showcase": "^0.3.0",
|
|
110
110
|
"@stapel/tokens": "^0.6.0",
|
|
111
|
-
"@stapel/tokens-antd": "^0.
|
|
111
|
+
"@stapel/tokens-antd": "^0.13.0"
|
|
112
112
|
},
|
|
113
113
|
"engines": {
|
|
114
114
|
"node": ">=22"
|
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
useI18n,
|
|
49
49
|
useT,
|
|
50
50
|
} from "@stapel/core";
|
|
51
|
+
import type { SignInCta } from "@stapel/core";
|
|
51
52
|
import { spacing } from "@stapel/tokens";
|
|
52
53
|
import { FeatureValueList } from "@stapel/attributes-react/default";
|
|
53
54
|
import { formatFeatureValue, isRedactedValue } from "@stapel/attributes-react";
|
|
@@ -55,6 +56,7 @@ import { useListingDetail } from "../headless/ListingDetail.js";
|
|
|
55
56
|
import { useListingActions } from "../headless/ListingActions.js";
|
|
56
57
|
import { asFeatureDaoList, featureValuesForDisplay } from "../model/features.js";
|
|
57
58
|
import { LISTINGS_I18N_KEYS } from "../i18n/keys.js";
|
|
59
|
+
import { SignInLink } from "./SignInLink.js";
|
|
58
60
|
import { HeartIcon } from "./icons.js";
|
|
59
61
|
import { ListingPhoto } from "./ListingPhoto.js";
|
|
60
62
|
import { ListingPrice } from "./ListingPrice.js";
|
|
@@ -94,6 +96,15 @@ export interface ListingDetailPaneProps
|
|
|
94
96
|
* button). Cross-pair navigation is the container's job (spec §6.2 item 5),
|
|
95
97
|
* so this pair takes nodes rather than routes. */
|
|
96
98
|
readonly actions?: ReactNode;
|
|
99
|
+
/**
|
|
100
|
+
* The container's sign-in door, rendered beside the favourite's refusal —
|
|
101
|
+
* the same `SignInCta` seam the three card skins already take. The pane was
|
|
102
|
+
* the one heart in this pair whose "sign in to do this" had no door next to
|
|
103
|
+
* it (measured on a live storefront: the sentence, and the nearest sign-in
|
|
104
|
+
* a screen-corner away), which is exactly the gap `signIn` closed on the
|
|
105
|
+
* cards. Absent: the reason stands alone, as before.
|
|
106
|
+
*/
|
|
107
|
+
readonly signIn?: SignInCta;
|
|
97
108
|
readonly footer?: ReactNode;
|
|
98
109
|
}
|
|
99
110
|
|
|
@@ -285,6 +296,7 @@ export function ListingDetailPane(props: ListingDetailPaneProps): ReactElement {
|
|
|
285
296
|
{/* Favouriting your own listing is not a thing anyone does;
|
|
286
297
|
for everyone else it is the secondary it always was. */}
|
|
287
298
|
{owner ? null : (
|
|
299
|
+
<Flex vertical gap={spacing[1]}>
|
|
288
300
|
<GatedControl
|
|
289
301
|
gate={bag.favoriteGate}
|
|
290
302
|
testId="listings-detail-favorite-gate"
|
|
@@ -308,6 +320,18 @@ export function ListingDetailPane(props: ListingDetailPaneProps): ReactElement {
|
|
|
308
320
|
</Button>
|
|
309
321
|
)}
|
|
310
322
|
</GatedControl>
|
|
323
|
+
{/* The door. `GatedControl` prints the reason; where a
|
|
324
|
+
visitor signs in is the container's, and arrives as
|
|
325
|
+
`signIn` — the cards' own pattern, verbatim. */}
|
|
326
|
+
{bag.favoriteGate.available ? null : (
|
|
327
|
+
<Typography.Text
|
|
328
|
+
type="secondary"
|
|
329
|
+
data-testid="listings-detail-favorite-blocked"
|
|
330
|
+
>
|
|
331
|
+
<SignInLink cta={props.signIn} testId="listings-detail-sign-in" />
|
|
332
|
+
</Typography.Text>
|
|
333
|
+
)}
|
|
334
|
+
</Flex>
|
|
311
335
|
)}
|
|
312
336
|
|
|
313
337
|
{props.actions}
|