@stapel/listings-react 0.23.0 → 0.25.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 (104) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/MODULE.md +4 -0
  3. package/README.md +75 -0
  4. package/dist/api/generated/schema.d.ts +126 -11
  5. package/dist/api/generated/schema.d.ts.map +1 -1
  6. package/dist/api/listingsApi.d.ts +5 -3
  7. package/dist/api/listingsApi.d.ts.map +1 -1
  8. package/dist/api/listingsApi.js.map +1 -1
  9. package/dist/api/types.d.ts +51 -4
  10. package/dist/api/types.d.ts.map +1 -1
  11. package/dist/api/types.js.map +1 -1
  12. package/dist/default/CardBadges.d.ts +47 -0
  13. package/dist/default/CardBadges.d.ts.map +1 -0
  14. package/dist/default/CardBadges.js +38 -0
  15. package/dist/default/CardBadges.js.map +1 -0
  16. package/dist/default/ListingCard.d.ts.map +1 -1
  17. package/dist/default/ListingCard.js +6 -6
  18. package/dist/default/ListingCard.js.map +1 -1
  19. package/dist/default/ListingDetailPane.d.ts.map +1 -1
  20. package/dist/default/ListingDetailPane.js +12 -19
  21. package/dist/default/ListingDetailPane.js.map +1 -1
  22. package/dist/default/ListingPhoto.d.ts.map +1 -1
  23. package/dist/default/ListingPhoto.js +12 -8
  24. package/dist/default/ListingPhoto.js.map +1 -1
  25. package/dist/default/ListingSerpCard.d.ts.map +1 -1
  26. package/dist/default/ListingSerpCard.js +3 -5
  27. package/dist/default/ListingSerpCard.js.map +1 -1
  28. package/dist/default/ListingSpecList.d.ts +74 -0
  29. package/dist/default/ListingSpecList.d.ts.map +1 -0
  30. package/dist/default/ListingSpecList.js +90 -0
  31. package/dist/default/ListingSpecList.js.map +1 -0
  32. package/dist/default/cardGallery.d.ts +81 -0
  33. package/dist/default/cardGallery.d.ts.map +1 -0
  34. package/dist/default/cardGallery.js +266 -0
  35. package/dist/default/cardGallery.js.map +1 -0
  36. package/dist/default/index.d.ts +6 -0
  37. package/dist/default/index.d.ts.map +1 -1
  38. package/dist/default/index.js +5 -0
  39. package/dist/default/index.js.map +1 -1
  40. package/dist/headless/ListingComposer.d.ts +20 -2
  41. package/dist/headless/ListingComposer.d.ts.map +1 -1
  42. package/dist/headless/ListingComposer.js +19 -4
  43. package/dist/headless/ListingComposer.js.map +1 -1
  44. package/dist/i18n/es.d.ts.map +1 -1
  45. package/dist/i18n/es.js +1 -0
  46. package/dist/i18n/es.js.map +1 -1
  47. package/dist/i18n/generated/errors.es.gen.d.ts +1 -1
  48. package/dist/i18n/generated/errors.es.gen.js +1 -1
  49. package/dist/i18n/generated/errors.gen.d.ts +6 -0
  50. package/dist/i18n/generated/errors.gen.d.ts.map +1 -1
  51. package/dist/i18n/generated/errors.gen.js +3 -0
  52. package/dist/i18n/generated/errors.gen.js.map +1 -1
  53. package/dist/i18n/generated/errors.ru.gen.d.ts +1 -1
  54. package/dist/i18n/generated/errors.ru.gen.js +1 -1
  55. package/dist/i18n/ru.d.ts.map +1 -1
  56. package/dist/i18n/ru.js +3 -0
  57. package/dist/i18n/ru.js.map +1 -1
  58. package/dist/index.d.ts +3 -0
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +3 -0
  61. package/dist/index.js.map +1 -1
  62. package/dist/model/cardBadges.d.ts +134 -0
  63. package/dist/model/cardBadges.d.ts.map +1 -0
  64. package/dist/model/cardBadges.js +131 -0
  65. package/dist/model/cardBadges.js.map +1 -0
  66. package/dist/model/draft.d.ts +10 -2
  67. package/dist/model/draft.d.ts.map +1 -1
  68. package/dist/model/draft.js +22 -4
  69. package/dist/model/draft.js.map +1 -1
  70. package/dist/model/featureText.d.ts +85 -0
  71. package/dist/model/featureText.d.ts.map +1 -0
  72. package/dist/model/featureText.js +153 -0
  73. package/dist/model/featureText.js.map +1 -0
  74. package/dist/model/features.d.ts.map +1 -1
  75. package/dist/model/features.js +59 -0
  76. package/dist/model/features.js.map +1 -1
  77. package/llms.txt +5 -2
  78. package/manifest.json +47 -1
  79. package/nav-manifest.json +1 -1
  80. package/package.json +10 -10
  81. package/src/analytics/generated/events.json +1 -1
  82. package/src/api/generated/schema.ts +126 -11
  83. package/src/api/listingsApi.ts +5 -3
  84. package/src/api/types.ts +60 -6
  85. package/src/default/CardBadges.tsx +105 -0
  86. package/src/default/ListingCard.tsx +7 -21
  87. package/src/default/ListingDetailPane.tsx +13 -37
  88. package/src/default/ListingPhoto.tsx +54 -26
  89. package/src/default/ListingSerpCard.tsx +10 -28
  90. package/src/default/ListingSpecList.tsx +195 -0
  91. package/src/default/cardGallery.ts +287 -0
  92. package/src/default/index.ts +22 -0
  93. package/src/headless/ListingComposer.tsx +39 -5
  94. package/src/i18n/es.ts +3 -0
  95. package/src/i18n/generated/errors.es.gen.ts +1 -1
  96. package/src/i18n/generated/errors.gen.ts +3 -0
  97. package/src/i18n/generated/errors.json +9 -0
  98. package/src/i18n/generated/errors.ru.gen.ts +1 -1
  99. package/src/i18n/ru.ts +5 -0
  100. package/src/index.ts +15 -0
  101. package/src/model/cardBadges.ts +237 -0
  102. package/src/model/draft.ts +23 -5
  103. package/src/model/featureText.ts +251 -0
  104. package/src/model/features.ts +60 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"featureText.js","sourceRoot":"","sources":["../../src/model/featureText.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/model/features.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiGG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AA0F7E;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;CACnD;AAiID;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,iBAAiB,EACtB,MAAM,GAAE,iBAAsB,GAC7B,kBAAkB,GAAG,SAAS,CAEhC;AAoED;;;mCAGmC;AACnC,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,EACrD,MAAM,GAAE,iBAAsB,GAC7B,SAAS,kBAAkB,EAAE,CAQ/B;AAED,qEAAqE;AACrE,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GACpD,MAAM,CAER;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GACpD,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAO3C;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,EACrD,MAAM,GAAE,iBAAsB,GAC7B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAM3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,iBAAiB,EAAE,CAE7E"}
1
+ {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/model/features.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiGG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AA0F7E;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;CACnD;AA2LD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,iBAAiB,EACtB,MAAM,GAAE,iBAAsB,GAC7B,kBAAkB,GAAG,SAAS,CAEhC;AAsED;;;mCAGmC;AACnC,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,EACrD,MAAM,GAAE,iBAAsB,GAC7B,SAAS,kBAAkB,EAAE,CAQ/B;AAED,qEAAqE;AACrE,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GACpD,MAAM,CAER;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GACpD,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAO3C;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,EACrD,MAAM,GAAE,iBAAsB,GAC7B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAM3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,iBAAiB,EAAE,CAE7E"}
@@ -186,6 +186,62 @@ function selectOptions(dao, config, categoryDef) {
186
186
  return undefined;
187
187
  return [...table].map(([value, label]) => ({ value, label }));
188
188
  }
189
+ /**
190
+ * The config keys that carry a value's UNIT, in the order they belong to.
191
+ *
192
+ * There is no generic `unit` key anywhere in this contract — the unit of an
193
+ * `int`/`float` is its `postfix` (free text on the type's config, with
194
+ * `postfix1000` as the abbreviated unit the engine switches to at a
195
+ * thousand), and `convertible_unit` states its own with `unitType`/`unit_m`/
196
+ * `unit_i`. `prefix` rides along because it is the same fact on the other
197
+ * side of the number (a currency mark, a «~»).
198
+ *
199
+ * `precision` is deliberately NOT here. `dto_to_dao` writes it on every
200
+ * numeric row (defaulted, never absent), so it could only ever be adopted
201
+ * onto a row from some older server — where the stored value has already
202
+ * been ROUNDED to the precision it was written with, and re-rendering it at
203
+ * today's would print decimals the record does not contain.
204
+ */
205
+ const UNIT_KEYS = [
206
+ "prefix",
207
+ "postfix",
208
+ "postfix1000",
209
+ "unitType",
210
+ "unit_m",
211
+ "unit_i",
212
+ ];
213
+ /**
214
+ * The unit the CATEGORY declares, for a stored row that carries none.
215
+ *
216
+ * Measured on the live listing page: "Power 173", "Mileage 20000" — bare
217
+ * numbers, in a deployment whose detail page holds the category's own feature
218
+ * defs and passes them in for exactly this kind of repair. `dto_to_dao`
219
+ * copies `postfix` at WRITE time, so a listing published before its category
220
+ * gained a unit keeps printing without one for the rest of its life, and so
221
+ * does every row written by a server that predates the key.
222
+ *
223
+ * Same rule as the option table two functions up, and for the same reason:
224
+ * the stored row wins wherever it said anything, because it is what the
225
+ * listing was published with, and the category fills only the silence. An
226
+ * empty string counts as silence — `dto_to_dao` writes `postfix=None` as
227
+ * absent, but a catalogue that once held `""` should not out-rank a
228
+ * catalogue that now holds "km".
229
+ */
230
+ function adoptedUnits(config, categoryDef) {
231
+ const declared = categoryDef?.config;
232
+ if (declared === undefined)
233
+ return undefined;
234
+ const out = {};
235
+ for (const key of UNIT_KEYS) {
236
+ const stored = config[key];
237
+ if (typeof stored === "string" && stored.length > 0)
238
+ continue;
239
+ const value = declared[key];
240
+ if (typeof value === "string" && value.length > 0)
241
+ out[key] = value;
242
+ }
243
+ return Object.keys(out).length === 0 ? undefined : out;
244
+ }
189
245
  /**
190
246
  * The category's option TREE, adopted whole for a `hierarchical_select` that
191
247
  * stored none — see {@link TREE_VALUED}.
@@ -225,6 +281,9 @@ function featureView(dao, defs) {
225
281
  const options = selectOptions(dao, config, categoryDef) ?? adoptedTree(dao, config, categoryDef);
226
282
  if (options !== undefined)
227
283
  config["options"] = options;
284
+ const units = adoptedUnits(config, categoryDef);
285
+ if (units !== undefined)
286
+ Object.assign(config, units);
228
287
  const visibility = storedVisibility(dao.visibility);
229
288
  const feature = {
230
289
  slug: dao.slug,
@@ -1 +1 @@
1
- {"version":3,"file":"features.js","sourceRoot":"","sources":["../../src/model/features.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"features.js","sourceRoot":"","sources":["../../src/model/features.ts"],"names":[],"mappings":"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"}
package/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # @stapel/listings-react 0.23.0
1
+ # @stapel/listings-react 0.25.0
2
2
 
3
3
  Headless React flow pair for stapel-listings (contract >=0.21 <0.22) — business + state, zero visual opinion.
4
4
  Built on @stapel/core: typed client + StapelApiError envelope, auth token refresh,
@@ -25,6 +25,7 @@ Paths are relative to `/listings/api/v1/`.
25
25
  - listings_api_v1_listings_complete_create: POST /listings/{id}/complete/
26
26
  - listings_api_v1_listings_create: POST /listings/
27
27
  - listings_api_v1_listings_destroy: DELETE /listings/{id}/
28
+ - listings_api_v1_listings_draft_retrieve: GET /listings/{id}/draft/
28
29
  - listings_api_v1_listings_engagement_retrieve: GET /listings/engagement/
29
30
  - listings_api_v1_listings_favorite_create: POST /listings/{id}/favorite/
30
31
  - listings_api_v1_listings_list: GET /listings/
@@ -60,7 +61,7 @@ Paths are relative to `/listings/api/v1/`.
60
61
  - useValidateDraft (query) → validateDraft
61
62
 
62
63
  ## Errors (render t(code, params); UX from remediation)
63
- 68 keys (full catalog: manifest.json §errors). By remediation: fix_input 39 · retry 16 · verify 5 · wait_and_retry 5 · contact_support 2 · reauthenticate 1.
64
+ 69 keys (full catalog: manifest.json §errors). By remediation: fix_input 40 · retry 16 · verify 5 · wait_and_retry 5 · contact_support 2 · reauthenticate 1.
64
65
  Param-bearing keys (interpolation slots matter):
65
66
  - error.400.description_too_long [400] → fix_input {max_length}
66
67
  - error.400.description_too_short [400] → fix_input {min_length}
@@ -86,6 +87,7 @@ Param-bearing keys (interpolation slots matter):
86
87
  - error.400.field.null [400] → fix_input {field}
87
88
  - error.400.field.required [400] → fix_input {field}
88
89
  - error.400.field.unique [400] → fix_input {field}
90
+ - error.400.listing_draft_meta_too_large [400] → fix_input {max_bytes}
89
91
  - error.400.listing_feature_not_allowed [400] → fix_input {feature}
90
92
  - error.400.listing_invalid_status_filter [400] → fix_input {status}
91
93
  - error.409.invalid_listing_transition [409] → fix_input {from_status}
@@ -121,6 +123,7 @@ const { tracked } = useTracked();
121
123
  - listings.parts → <ListingStatusBlock> [default|tags|notes|media|door] demo/ListingParts.demo.tsx
122
124
  - listings.photo-strip → <ListingPhotoStrip> [default|single|no photos] demo/ListingPhotoStrip.demo.tsx
123
125
  - listings.serp-card → <ListingSerpCard> [default|trend|visitor|desktop row|bare] demo/ListingSerpCard.demo.tsx
126
+ - listings.spec-parts → <CardBadges> [contract|legacy|specs|specs-split] demo/ListingSpecParts.demo.tsx
124
127
  Each source file is the canonical usage snippet (open the default variant).
125
128
 
126
129
  ## Snippets
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$generated": "by scripts/gen-manifest.mjs — do not edit; drift-gated (pnpm gen:manifest:check)",
3
3
  "package": "@stapel/listings-react",
4
- "version": "0.23.0",
4
+ "version": "0.25.0",
5
5
  "backend": {
6
6
  "module": "stapel-listings",
7
7
  "contract": ">=0.21 <0.22"
@@ -44,6 +44,13 @@
44
44
  "request": null,
45
45
  "response": "DeleteResponse"
46
46
  },
47
+ "listings_api_v1_listings_draft_retrieve": {
48
+ "method": "GET",
49
+ "path": "/listings/api/v1/listings/{id}/draft/",
50
+ "tag": "listings",
51
+ "request": null,
52
+ "response": "ListingDraft"
53
+ },
47
54
  "listings_api_v1_listings_engagement_retrieve": {
48
55
  "method": "GET",
49
56
  "path": "/listings/api/v1/listings/engagement/",
@@ -501,6 +508,13 @@
501
508
  "params": [],
502
509
  "remediation": "fix_input"
503
510
  },
511
+ "error.400.listing_draft_meta_too_large": {
512
+ "status": 400,
513
+ "params": [
514
+ "max_bytes"
515
+ ],
516
+ "remediation": "fix_input"
517
+ },
504
518
  "error.400.listing_feature_not_allowed": {
505
519
  "status": 400,
506
520
  "params": [
@@ -899,6 +913,27 @@
899
913
  "bare"
900
914
  ],
901
915
  "source": "demo/ListingSerpCard.demo.tsx"
916
+ },
917
+ {
918
+ "id": "listings.spec-parts",
919
+ "title": "Badges and specs",
920
+ "description": "A badge says which question it answers, and a spec sheet is a definition list rather than a table. Both are drawn by the SERVER's decision about presentation, not by a client-side heuristic: the right badge for a value depends on the category — '3 rooms' wants its name, 'Brick' is a boolean whose name IS the badge, and '20 000 km' wants its unit and no name at all.",
921
+ "component": "CardBadges",
922
+ "covers": [
923
+ "CardSpecLine",
924
+ "ListingSpecColumns",
925
+ "ListingSpecList"
926
+ ],
927
+ "tokens": [
928
+ "text-subtle"
929
+ ],
930
+ "variants": [
931
+ "contract",
932
+ "legacy",
933
+ "specs",
934
+ "specs-split"
935
+ ],
936
+ "source": "demo/ListingSpecParts.demo.tsx"
902
937
  }
903
938
  ],
904
939
  "i18nKeys": [
@@ -933,6 +968,7 @@
933
968
  "error.400.field.unique",
934
969
  "error.400.image_required",
935
970
  "error.400.invalid_ad_id",
971
+ "error.400.listing_draft_meta_too_large",
936
972
  "error.400.listing_feature_not_allowed",
937
973
  "error.400.listing_invalid_status_filter",
938
974
  "error.400.listing_location_required",
@@ -1153,8 +1189,12 @@
1153
1189
  "PRICE_FIELD",
1154
1190
  "TITLE_FIELD",
1155
1191
  "asFeatureDaoList",
1192
+ "badgePresentation",
1193
+ "badgeValueText",
1156
1194
  "canDelete",
1157
1195
  "canTransition",
1196
+ "cardBadgeText",
1197
+ "cardBadgeTexts",
1158
1198
  "createDraftBody",
1159
1199
  "createListingsApi",
1160
1200
  "createListingsRuntime",
@@ -1170,10 +1210,13 @@
1170
1210
  "explainListingsError",
1171
1211
  "failedResults",
1172
1212
  "featureFromDao",
1213
+ "featureUnit",
1173
1214
  "featureValuesForDisplay",
1174
1215
  "featuresDtoFromDaoList",
1175
1216
  "featuresFromDaoList",
1176
1217
  "flowEndpoints",
1218
+ "formatSpecValue",
1219
+ "hasCardBadgeContract",
1177
1220
  "isBatchValid",
1178
1221
  "isListingViewed",
1179
1222
  "isPubliclyVisible",
@@ -1233,6 +1276,9 @@
1233
1276
  "withEngagement"
1234
1277
  ],
1235
1278
  "types": [
1279
+ "CardBadgeContract",
1280
+ "CardBadgePresentation",
1281
+ "CardBadgeRow",
1236
1282
  "ComposeStage",
1237
1283
  "CreateListingsRuntimeOptions",
1238
1284
  "DeleteResponse",
package/nav-manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "@stapel/listings-react",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
4
4
  "entries": [
5
5
  {
6
6
  "id": "listings.detail",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stapel/listings-react",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
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": {
@@ -48,14 +48,14 @@
48
48
  ],
49
49
  "size-limit": [
50
50
  {
51
- "name": "index — the headless pair (client + status axes + draft model + hooks): no antd. Raised 11 -> 12 KB for the elevation gate (useElevatableMandateGate + core's useElevation): the anonymous arm can now mint an identity for a named action instead of refusing, and that is a state hook the gate did not previously carry. Raised 11.5 -> 12 KB for envelopeFieldErrors and its API-field -> control table: a save-draft/create 400 names its field in the envelope rather than in a publish batch, and without the table the refusal had nowhere to land — which is how one over-precise coordinate painted two unreadable banners and left every control clean. Thirty-six bytes of routing table is what a legible refusal costs. Raised 12 -> 13 KB for two seams the mobile wave needed in the HEADLESS half: the category-feature copy source in model/features.ts (the option table a stored select does not carry, so a published listing prints \"Second-hand\" and not \"b-u\"), and firstUnsatisfied (the field a \"10 required details are still empty\" count actually points at, in the order the form asks). Both are model, not skin: a headless host renders its own controls and needs the same two answers. Raised 13 -> 14 KB (measured 12.91) for the engagement overlay: a batch read, its normalized key, and the scope that runs it once for a page and hands every card its own entry. It is a whole new READ rather than a flag — and it is the read that makes the viewed/saved state visible at all on a feed and a SERP, which come from the search index and carry no per-viewer field. Landing at 12.91 of 13 would have been a budget passed by rounding",
51
+ "name": "index — the headless pair (client + status axes + draft model + hooks): no antd. Raised 11 -> 12 KB for the elevation gate (useElevatableMandateGate + core's useElevation): the anonymous arm can now mint an identity for a named action instead of refusing, and that is a state hook the gate did not previously carry. Raised 11.5 -> 12 KB for envelopeFieldErrors and its API-field -> control table: a save-draft/create 400 names its field in the envelope rather than in a publish batch, and without the table the refusal had nowhere to land — which is how one over-precise coordinate painted two unreadable banners and left every control clean. Thirty-six bytes of routing table is what a legible refusal costs. Raised 12 -> 13 KB for two seams the mobile wave needed in the HEADLESS half: the category-feature copy source in model/features.ts (the option table a stored select does not carry, so a published listing prints \"Second-hand\" and not \"b-u\"), and firstUnsatisfied (the field a \"10 required details are still empty\" count actually points at, in the order the form asks). Both are model, not skin: a headless host renders its own controls and needs the same two answers. Raised 13 -> 14 KB (measured 12.91) for the engagement overlay: a batch read, its normalized key, and the scope that runs it once for a page and hands every card its own entry. It is a whole new READ rather than a flag — and it is the read that makes the viewed/saved state visible at all on a feed and a SERP, which come from the search index and carry no per-viewer field. Landing at 12.91 of 13 would have been a budget passed by rounding. Raised 14 -> 15 KB (measured 14.39) for the two model modules the listing-page wave added to the HEADLESS half: model/featureText.ts, which typesets a numeric value instead of stringifying it (its unit resolved from the definition, its digits through Intl.NumberFormat — the live page read 'Power 173' and 'Mileage 20000'), and model/cardBadges.ts, the card badge contract's four presentations plus the detector that falls back to the old rendering on an older backend. Both are answers a headless host needs as much as the skin does: a container drawing its own spec rows has the same value and the same missing unit.",
52
52
  "path": "dist/index.js",
53
- "limit": "14 KB"
53
+ "limit": "15 KB"
54
54
  },
55
55
  {
56
- "name": "default — the antd skin (three cards, detail, composer, dashboard, the named slots and the delete confirmation) must stay out of the main bundle. Raised 17 -> 19 KB for the mobile wave: <ListingSerpCard> (photo strip + price-first block + action rail), <ListingFeedCard> and <FeedGrid> are two more card surfaces on the same shared target/favourite/photo parts, not three copies of one Raised 19 -> 20 KB for the desktop wave of the detail page: layout=\"split\" is a second ASSEMBLY of the money page (the sticky buy column, the two-column spec table, the widened measure) over the same parts, and GateReasonPopover is the blocked heart's third volume — the reason and the door disclosed on interaction, with the visually-hidden copy that keeps the refusal in the accessibility tree. Both are geometry and wiring, not new widgets. Raised 20 -> 21 KB (measured 20.22) for the engagement wave, which is four small things and no new component: the disclosure became a controlled open/close so a pointer that hovers and then clicks does not shut the only explanation the control has; the heart draws a filled accent when saved and states a failed save through the shared ErrorAlert; an already-seen card dims through one rule in the sheet all three cards already hoist; and the listing page gained a view-count row. 216 bytes is what a control that reports its own outcome costs. Raised 21 -> 22 KB for the seller's board becoming a door in both directions: the transition route and useTransitionListing, OWNER_TRANSITIONS/ownerMoves as the fallback mirror, ListingActionsBag.moves drawn in a stable order, listingHref/linkComponent on the cabinet pane, the refusal that stops quoting the wire, and the row that fits a phone. Measured on a clean tree, this package's src reverted to the previous commit with dependencies held constant: 20.82 -> 21.60 KB. The old ceiling had 180 B of room and the work needs 780; none of it is copy, and a fourth axis of owner state is not a rounding error",
56
+ "name": "default — the antd skin (three cards, detail, composer, dashboard, the named slots and the delete confirmation) must stay out of the main bundle. Raised 17 -> 19 KB for the mobile wave: <ListingSerpCard> (photo strip + price-first block + action rail), <ListingFeedCard> and <FeedGrid> are two more card surfaces on the same shared target/favourite/photo parts, not three copies of one Raised 19 -> 20 KB for the desktop wave of the detail page: layout=\"split\" is a second ASSEMBLY of the money page (the sticky buy column, the two-column spec table, the widened measure) over the same parts, and GateReasonPopover is the blocked heart's third volume — the reason and the door disclosed on interaction, with the visually-hidden copy that keeps the refusal in the accessibility tree. Both are geometry and wiring, not new widgets. Raised 20 -> 21 KB (measured 20.22) for the engagement wave, which is four small things and no new component: the disclosure became a controlled open/close so a pointer that hovers and then clicks does not shut the only explanation the control has; the heart draws a filled accent when saved and states a failed save through the shared ErrorAlert; an already-seen card dims through one rule in the sheet all three cards already hoist; and the listing page gained a view-count row. 216 bytes is what a control that reports its own outcome costs. Raised 21 -> 22 KB for the seller's board becoming a door in both directions: the transition route and useTransitionListing, OWNER_TRANSITIONS/ownerMoves as the fallback mirror, ListingActionsBag.moves drawn in a stable order, listingHref/linkComponent on the cabinet pane, the refusal that stops quoting the wire, and the row that fits a phone. Measured on a clean tree, this package's src reverted to the previous commit with dependencies held constant: 20.82 -> 21.60 KB. The old ceiling had 180 B of room and the work needs 780; none of it is copy, and a fourth axis of owner state is not a rounding error. Raised 22 -> 25 KB (measured 23.94) for the three surfaces of the same wave: <ListingSpecList>/<ListingSpecColumns>, which is a REPLACEMENT of antd's <Descriptions> with a paragraph row (an inline muted label and the value in one text flow, so a long answer wraps at the measure instead of stacking inside a third-of-a-page cell) and therefore carries its own hoisted sheet; <CardBadges>/<CardSpecLine>, one badge renderer for all three card surfaces with the pre-contract path kept whole beside it; and cardGallery.ts, the hover-scrub and swipe gestures — a segment map, a horizontal-intent threshold, the pointer-capability gate and the touch-action rule that leaves the page's vertical scroll to the browser. A gallery a card did not have and a spec list rebuilt from a table are not a rounding error.",
57
57
  "path": "dist/default/index.js",
58
- "limit": "22 KB"
58
+ "limit": "25 KB"
59
59
  },
60
60
  {
61
61
  "name": "i18n/ru — the Russian bundle is opt-in, not carried by the main entry",
@@ -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.15.0",
106
- "@stapel/core": "^0.25.0",
107
- "@stapel/currencies-react": "^0.3.0",
105
+ "@stapel/attributes-react": "^0.16.0",
106
+ "@stapel/core": "^0.25.1",
107
+ "@stapel/currencies-react": "^0.4.0",
108
108
  "@stapel/image": "^0.4.2",
109
109
  "@stapel/showcase": "^0.3.0",
110
- "@stapel/tokens": "^0.7.0",
111
- "@stapel/tokens-antd": "^0.16.1"
110
+ "@stapel/tokens-antd": "^0.17.0",
111
+ "@stapel/tokens": "^0.7.0"
112
112
  },
113
113
  "engines": {
114
114
  "node": ">=22"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$generated": "by scripts/gen-events.mjs — do not edit; drift-gated (pnpm gen:events:check)",
3
3
  "package": "@stapel/listings-react",
4
- "version": "0.23.0",
4
+ "version": "0.25.0",
5
5
  "defined": [],
6
6
  "flows": []
7
7
  }
@@ -159,6 +159,50 @@ export interface paths {
159
159
  patch?: never;
160
160
  trace?: never;
161
161
  };
162
+ "/listings/api/v1/listings/{id}/draft/": {
163
+ parameters: {
164
+ query?: never;
165
+ header?: never;
166
+ path?: never;
167
+ cookie?: never;
168
+ };
169
+ /**
170
+ * @description Read back the draft twins — the reopen half of ``save-draft``.
171
+ *
172
+ * Every user-editable field on this module is a ``*_draft`` column
173
+ * (``title_draft``, ``description_draft``, ``images_draft``,
174
+ * ``features_draft``, the location trio, ...) and until now the only
175
+ * call that ever returned one was the write itself: ``create``,
176
+ * ``update`` and ``save-draft`` echo the bag back, and no READ did. So a
177
+ * composer reopening a listing by id had exactly one source, the detail
178
+ * read, which serves the PUBLISHED fields — empty on everything that has
179
+ * never been published. The seller pressed «продолжить», got a blank
180
+ * form, and their text and photos were sitting in the row the whole
181
+ * time.
182
+ *
183
+ * Deliberately a separate route rather than draft columns bolted onto
184
+ * the detail read: the detail read is the PUBLIC one (a stranger and a
185
+ * crawler read it without a session), and a shape whose key set depends
186
+ * on who is asking is the shape a redaction bug hides in. Here the
187
+ * answer is structural — ``_get_own`` is the module's one ownership
188
+ * gate, 403 for someone else's listing, 404 for one that is absent or
189
+ * soft-deleted — so no draft field can reach a non-owner by omission.
190
+ *
191
+ * The payload is ``ListingDraftSerializer``, byte for byte what
192
+ * ``save-draft`` returns, so a client reopens with the mapper it already
193
+ * has for the write's response instead of a second one.
194
+ *
195
+ * **Permissions:** `IsAuthenticated`
196
+ */
197
+ get: operations["listings_api_v1_listings_draft_retrieve"];
198
+ put?: never;
199
+ post?: never;
200
+ delete?: never;
201
+ options?: never;
202
+ head?: never;
203
+ patch?: never;
204
+ trace?: never;
205
+ };
162
206
  "/listings/api/v1/listings/{id}/favorite/": {
163
207
  parameters: {
164
208
  query?: never;
@@ -285,6 +329,15 @@ export interface paths {
285
329
  * and the set the server accepts are one object, not two that agree
286
330
  * today.
287
331
  *
332
+ * One edge is not a lifecycle hop: ARCHIVED -> PUBLISHED is
333
+ * «опубликовать снова», and it runs the publish service (validate,
334
+ * promote, re-submit for review — see ``RESTORE_EDGES``). So it can
335
+ * answer 400 when the draft is not publishable, and the ``status`` it
336
+ * returns is where the deployment's moderation policy put the listing,
337
+ * which under the default pre-moderation gate is ``pending`` and not the
338
+ * ``published`` that was asked for. Read the status from the response,
339
+ * never from the request.
340
+ *
288
341
  * **Permissions:** `IsAuthenticated`
289
342
  */
290
343
  post: operations["listings_api_v1_listings_transition_create"];
@@ -815,7 +868,13 @@ export interface components {
815
868
  price_base?: string | null;
816
869
  currency?: string;
817
870
  readonly images: string[] | null;
818
- readonly features_title: (components["schemas"]["FeatureDao"] | {
871
+ readonly features_title: ((Omit<components["schemas"]["FeatureDao"], "type"> & {
872
+ label: string;
873
+ unit?: string;
874
+ name: string;
875
+ /** @enum {unknown} */
876
+ presentation: "value" | "value_unit" | "name_value" | "name";
877
+ }) | {
819
878
  slug?: string;
820
879
  type?: string;
821
880
  name?: string | null;
@@ -830,7 +889,13 @@ export interface components {
830
889
  redacted: true;
831
890
  present: boolean;
832
891
  })[];
833
- readonly features_badges: (components["schemas"]["FeatureDao"] | {
892
+ readonly features_badges: ((Omit<components["schemas"]["FeatureDao"], "type"> & {
893
+ label: string;
894
+ unit?: string;
895
+ name: string;
896
+ /** @enum {unknown} */
897
+ presentation: "value" | "value_unit" | "name_value" | "name";
898
+ }) | {
834
899
  slug?: string;
835
900
  type?: string;
836
901
  name?: string | null;
@@ -869,7 +934,7 @@ export interface components {
869
934
  readonly id: number;
870
935
  /** Format: uuid */
871
936
  owner: string;
872
- category_id: string;
937
+ category_id?: (string) | null;
873
938
  title?: string;
874
939
  description?: string;
875
940
  language?: string;
@@ -906,7 +971,13 @@ export interface components {
906
971
  redacted: true;
907
972
  present: boolean;
908
973
  })[];
909
- readonly features_title: (components["schemas"]["FeatureDao"] | {
974
+ readonly features_title: ((Omit<components["schemas"]["FeatureDao"], "type"> & {
975
+ label: string;
976
+ unit?: string;
977
+ name: string;
978
+ /** @enum {unknown} */
979
+ presentation: "value" | "value_unit" | "name_value" | "name";
980
+ }) | {
910
981
  slug?: string;
911
982
  type?: string;
912
983
  name?: string | null;
@@ -921,7 +992,13 @@ export interface components {
921
992
  redacted: true;
922
993
  present: boolean;
923
994
  })[];
924
- readonly features_badges: (components["schemas"]["FeatureDao"] | {
995
+ readonly features_badges: ((Omit<components["schemas"]["FeatureDao"], "type"> & {
996
+ label: string;
997
+ unit?: string;
998
+ name: string;
999
+ /** @enum {unknown} */
1000
+ presentation: "value" | "value_unit" | "name_value" | "name";
1001
+ }) | {
925
1002
  slug?: string;
926
1003
  type?: string;
927
1004
  name?: string | null;
@@ -964,7 +1041,7 @@ export interface components {
964
1041
  */
965
1042
  ListingDraft: {
966
1043
  readonly id: number;
967
- category_id: string;
1044
+ category_id?: (string) | null;
968
1045
  currency?: string;
969
1046
  language?: string;
970
1047
  title_draft?: string;
@@ -982,6 +1059,7 @@ export interface components {
982
1059
  features_draft?: {
983
1060
  [key: string]: components["schemas"]["FeatureDto"];
984
1061
  } | null;
1062
+ draft_meta?: unknown;
985
1063
  auto_republish?: boolean;
986
1064
  countable?: boolean;
987
1065
  /** Format: int64 */
@@ -1085,7 +1163,13 @@ export interface components {
1085
1163
  price_base?: string | null;
1086
1164
  currency?: string;
1087
1165
  readonly images: string[] | null;
1088
- readonly features_title: (components["schemas"]["FeatureDao"] | {
1166
+ readonly features_title: ((Omit<components["schemas"]["FeatureDao"], "type"> & {
1167
+ label: string;
1168
+ unit?: string;
1169
+ name: string;
1170
+ /** @enum {unknown} */
1171
+ presentation: "value" | "value_unit" | "name_value" | "name";
1172
+ }) | {
1089
1173
  slug?: string;
1090
1174
  type?: string;
1091
1175
  name?: string | null;
@@ -1100,7 +1184,13 @@ export interface components {
1100
1184
  redacted: true;
1101
1185
  present: boolean;
1102
1186
  })[];
1103
- readonly features_badges: (components["schemas"]["FeatureDao"] | {
1187
+ readonly features_badges: ((Omit<components["schemas"]["FeatureDao"], "type"> & {
1188
+ label: string;
1189
+ unit?: string;
1190
+ name: string;
1191
+ /** @enum {unknown} */
1192
+ presentation: "value" | "value_unit" | "name_value" | "name";
1193
+ }) | {
1104
1194
  slug?: string;
1105
1195
  type?: string;
1106
1196
  name?: string | null;
@@ -1181,7 +1271,7 @@ export interface components {
1181
1271
  */
1182
1272
  PatchedListingDraft: {
1183
1273
  readonly id?: number;
1184
- category_id?: string;
1274
+ category_id?: (string) | null;
1185
1275
  currency?: string;
1186
1276
  language?: string;
1187
1277
  title_draft?: string;
@@ -1199,6 +1289,7 @@ export interface components {
1199
1289
  features_draft?: {
1200
1290
  [key: string]: components["schemas"]["FeatureDto"];
1201
1291
  } | null;
1292
+ draft_meta?: unknown;
1202
1293
  auto_republish?: boolean;
1203
1294
  countable?: boolean;
1204
1295
  /** Format: int64 */
@@ -1266,6 +1357,8 @@ export interface components {
1266
1357
  labels?: string[];
1267
1358
  vocabulary?: string | null;
1268
1359
  level?: string | null;
1360
+ prefix?: string | null;
1361
+ postfix?: string | null;
1269
1362
  };
1270
1363
  /** @description Serializer for the ref_select feature DTO. */
1271
1364
  RefSelectDto: {
@@ -1486,7 +1579,7 @@ export interface operations {
1486
1579
  path?: never;
1487
1580
  cookie?: never;
1488
1581
  };
1489
- requestBody: {
1582
+ requestBody?: {
1490
1583
  content: {
1491
1584
  "application/json": components["schemas"]["ListingDraft"];
1492
1585
  "application/x-www-form-urlencoded": components["schemas"]["ListingDraft"];
@@ -1536,7 +1629,7 @@ export interface operations {
1536
1629
  };
1537
1630
  cookie?: never;
1538
1631
  };
1539
- requestBody: {
1632
+ requestBody?: {
1540
1633
  content: {
1541
1634
  "application/json": components["schemas"]["ListingDraft"];
1542
1635
  "application/x-www-form-urlencoded": components["schemas"]["ListingDraft"];
@@ -1648,6 +1741,28 @@ export interface operations {
1648
1741
  };
1649
1742
  };
1650
1743
  };
1744
+ listings_api_v1_listings_draft_retrieve: {
1745
+ parameters: {
1746
+ query?: never;
1747
+ header?: never;
1748
+ path: {
1749
+ /** @description A unique integer value identifying this listing. */
1750
+ id: number;
1751
+ };
1752
+ cookie?: never;
1753
+ };
1754
+ requestBody?: never;
1755
+ responses: {
1756
+ 200: {
1757
+ headers: {
1758
+ [name: string]: unknown;
1759
+ };
1760
+ content: {
1761
+ "application/json": components["schemas"]["ListingDraft"];
1762
+ };
1763
+ };
1764
+ };
1765
+ };
1651
1766
  listings_api_v1_listings_favorite_create: {
1652
1767
  parameters: {
1653
1768
  query?: never;
@@ -154,9 +154,11 @@ export interface ListingsApi {
154
154
  ): Promise<ListingEngagementBatch>;
155
155
 
156
156
  /**
157
- * Start a draft. `category_id` is the only required member: the server
158
- * forces `owner=request.user` and `status=draft` in `perform_create`, so a
159
- * body that tried to set either is writing a field it does not own.
157
+ * Start a draft. Every member is optional `{}` creates the row, since
158
+ * stapel-listings 0.21.4 made `category_id` nullable on the draft half — and
159
+ * the server forces `owner=request.user` and `status=draft` in
160
+ * `perform_create`, so a body that tried to set either is writing a field it
161
+ * does not own.
160
162
  */
161
163
  createDraft(body: ListingDraftPatch): Promise<ListingDraft>;
162
164