@stapel/listings-react 0.4.0 → 0.8.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.
- package/CHANGELOG.md +180 -0
- package/dist/api/generated/schema.d.ts +94 -4
- package/dist/api/generated/schema.d.ts.map +1 -1
- package/dist/default/FavoritesPane.d.ts +40 -3
- package/dist/default/FavoritesPane.d.ts.map +1 -1
- package/dist/default/FavoritesPane.js +30 -18
- package/dist/default/FavoritesPane.js.map +1 -1
- package/dist/default/ListingCard.d.ts +81 -4
- package/dist/default/ListingCard.d.ts.map +1 -1
- package/dist/default/ListingCard.js +97 -27
- package/dist/default/ListingCard.js.map +1 -1
- package/dist/default/ListingComposerPage.d.ts +163 -23
- package/dist/default/ListingComposerPage.d.ts.map +1 -1
- package/dist/default/ListingComposerPage.js +85 -43
- package/dist/default/ListingComposerPage.js.map +1 -1
- package/dist/default/ListingDetailPane.d.ts +41 -4
- package/dist/default/ListingDetailPane.d.ts.map +1 -1
- package/dist/default/ListingDetailPane.js +38 -25
- package/dist/default/ListingDetailPane.js.map +1 -1
- package/dist/default/ListingPhoto.d.ts +13 -1
- package/dist/default/ListingPhoto.d.ts.map +1 -1
- package/dist/default/ListingPhoto.js +47 -9
- package/dist/default/ListingPhoto.js.map +1 -1
- package/dist/default/ListingPrice.d.ts +13 -0
- package/dist/default/ListingPrice.d.ts.map +1 -0
- package/dist/default/ListingPrice.js +60 -0
- package/dist/default/ListingPrice.js.map +1 -0
- package/dist/default/MyListingsPane.d.ts +7 -28
- package/dist/default/MyListingsPane.d.ts.map +1 -1
- package/dist/default/MyListingsPane.js +136 -67
- package/dist/default/MyListingsPane.js.map +1 -1
- package/dist/default/SignInLink.js +8 -7
- package/dist/default/SignInLink.js.map +1 -1
- package/dist/default/StatusTags.d.ts +16 -5
- package/dist/default/StatusTags.d.ts.map +1 -1
- package/dist/default/StatusTags.js +19 -13
- package/dist/default/StatusTags.js.map +1 -1
- package/dist/default/index.d.ts +15 -9
- package/dist/default/index.d.ts.map +1 -1
- package/dist/default/index.js +13 -6
- package/dist/default/index.js.map +1 -1
- package/dist/headless/Favorites.d.ts +6 -0
- package/dist/headless/Favorites.d.ts.map +1 -1
- package/dist/headless/Favorites.js +23 -7
- package/dist/headless/Favorites.js.map +1 -1
- package/dist/headless/ListingActions.d.ts +12 -0
- package/dist/headless/ListingActions.d.ts.map +1 -1
- package/dist/headless/ListingActions.js +3 -0
- package/dist/headless/ListingActions.js.map +1 -1
- package/dist/headless/ListingComposer.d.ts +23 -0
- package/dist/headless/ListingComposer.d.ts.map +1 -1
- package/dist/headless/ListingComposer.js +33 -7
- package/dist/headless/ListingComposer.js.map +1 -1
- package/dist/headless/ListingDetail.d.ts.map +1 -1
- package/dist/headless/ListingDetail.js +7 -5
- package/dist/headless/ListingDetail.js.map +1 -1
- package/dist/headless/useMandateGate.d.ts +33 -2
- package/dist/headless/useMandateGate.d.ts.map +1 -1
- package/dist/headless/useMandateGate.js +42 -4
- package/dist/headless/useMandateGate.js.map +1 -1
- package/dist/i18n/es.d.ts +6 -1
- package/dist/i18n/es.d.ts.map +1 -1
- package/dist/i18n/es.js +23 -5
- package/dist/i18n/es.js.map +1 -1
- package/dist/i18n/generated/errors.es.gen.d.ts +1 -1
- package/dist/i18n/generated/errors.es.gen.js +1 -1
- package/dist/i18n/generated/errors.gen.d.ts +6 -0
- package/dist/i18n/generated/errors.gen.d.ts.map +1 -1
- package/dist/i18n/generated/errors.gen.js +3 -0
- package/dist/i18n/generated/errors.gen.js.map +1 -1
- package/dist/i18n/generated/errors.ru.gen.d.ts +1 -1
- package/dist/i18n/generated/errors.ru.gen.js +1 -1
- package/dist/i18n/keys.d.ts +30 -3
- package/dist/i18n/keys.d.ts.map +1 -1
- package/dist/i18n/keys.js +47 -7
- package/dist/i18n/keys.js.map +1 -1
- package/dist/i18n/ru.d.ts +16 -1
- package/dist/i18n/ru.d.ts.map +1 -1
- package/dist/i18n/ru.js +35 -5
- package/dist/i18n/ru.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/model/draft.d.ts +9 -6
- package/dist/model/draft.d.ts.map +1 -1
- package/dist/model/draft.js +3 -1
- package/dist/model/draft.js.map +1 -1
- package/dist/model/features.d.ts +21 -7
- package/dist/model/features.d.ts.map +1 -1
- package/dist/model/features.js +26 -0
- package/dist/model/features.js.map +1 -1
- package/llms.txt +9 -8
- package/manifest.json +82 -31
- package/nav-manifest.json +1 -1
- package/package.json +19 -14
- package/src/analytics/generated/events.json +1 -1
- package/src/api/generated/schema.ts +94 -4
- package/src/default/FavoritesPane.tsx +156 -82
- package/src/default/ListingCard.tsx +283 -116
- package/src/default/ListingComposerPage.tsx +403 -187
- package/src/default/ListingDetailPane.tsx +200 -98
- package/src/default/ListingPhoto.tsx +89 -16
- package/src/default/ListingPrice.tsx +77 -0
- package/src/default/MyListingsPane.tsx +286 -228
- package/src/default/SignInLink.tsx +4 -4
- package/src/default/StatusTags.tsx +36 -18
- package/src/default/index.ts +18 -7
- package/src/headless/Favorites.tsx +36 -7
- package/src/headless/ListingActions.tsx +19 -0
- package/src/headless/ListingComposer.tsx +56 -5
- package/src/headless/ListingDetail.tsx +12 -5
- package/src/headless/useMandateGate.ts +49 -5
- package/src/i18n/es.ts +29 -5
- package/src/i18n/generated/errors.es.gen.ts +1 -1
- package/src/i18n/generated/errors.gen.ts +3 -0
- package/src/i18n/generated/errors.json +7 -0
- package/src/i18n/generated/errors.ru.gen.ts +1 -1
- package/src/i18n/keys.ts +54 -7
- package/src/i18n/ru.ts +41 -5
- package/src/index.ts +5 -1
- package/src/model/draft.ts +12 -7
- package/src/model/features.ts +48 -7
- package/dist/default/ErrorAlert.d.ts +0 -9
- package/dist/default/ErrorAlert.d.ts.map +0 -1
- package/dist/default/ErrorAlert.js +0 -27
- package/dist/default/ErrorAlert.js.map +0 -1
- package/dist/default/theme.d.ts +0 -25
- package/dist/default/theme.d.ts.map +0 -1
- package/dist/default/theme.js +0 -40
- package/dist/default/theme.js.map +0 -1
- package/src/default/ErrorAlert.tsx +0 -46
- package/src/default/theme.tsx +0 -67
|
@@ -74,6 +74,7 @@ export const LISTINGS_ERRORS = {
|
|
|
74
74
|
"error.401.unauthorized": { status: 401, params: [], remediation: "reauthenticate", en: "Authentication required" },
|
|
75
75
|
"error.402.payment_required": { status: 402, params: [], remediation: "retry", en: "Payment required" },
|
|
76
76
|
"error.403.forbidden": { status: 403, params: [], remediation: "retry", en: "You do not have permission to perform this action" },
|
|
77
|
+
"error.403.listing_anonymous_not_allowed": { status: 403, params: [], remediation: "retry", en: "A guest account may not publish a listing" },
|
|
77
78
|
"error.403.listing_not_owner": { status: 403, params: [], remediation: "retry", en: "Not your listing" },
|
|
78
79
|
"error.403.network_blocked": { status: 403, params: [], remediation: "contact_support", en: "Requests from this network are not allowed" },
|
|
79
80
|
"error.403.verification_enrollment_required": { status: 403, params: [], remediation: "verify", en: "Verification factor enrollment required" },
|
|
@@ -144,6 +145,7 @@ export const LISTINGS_ERROR_CODES: readonly ListingsErrorCode[] = [
|
|
|
144
145
|
"error.401.unauthorized",
|
|
145
146
|
"error.402.payment_required",
|
|
146
147
|
"error.403.forbidden",
|
|
148
|
+
"error.403.listing_anonymous_not_allowed",
|
|
147
149
|
"error.403.listing_not_owner",
|
|
148
150
|
"error.403.network_blocked",
|
|
149
151
|
"error.403.verification_enrollment_required",
|
|
@@ -216,6 +218,7 @@ export const listingsErrorBundleEn: Record<ListingsErrorCode, string> = {
|
|
|
216
218
|
"error.401.unauthorized": "Authentication required",
|
|
217
219
|
"error.402.payment_required": "Payment required",
|
|
218
220
|
"error.403.forbidden": "You do not have permission to perform this action",
|
|
221
|
+
"error.403.listing_anonymous_not_allowed": "A guest account may not publish a listing",
|
|
219
222
|
"error.403.listing_not_owner": "Not your listing",
|
|
220
223
|
"error.403.network_blocked": "Requests from this network are not allowed",
|
|
221
224
|
"error.403.verification_enrollment_required": "Verification factor enrollment required",
|
|
@@ -326,6 +326,13 @@
|
|
|
326
326
|
"remediation": "retry",
|
|
327
327
|
"en": "You do not have permission to perform this action"
|
|
328
328
|
},
|
|
329
|
+
{
|
|
330
|
+
"code": "error.403.listing_anonymous_not_allowed",
|
|
331
|
+
"status": 403,
|
|
332
|
+
"params": [],
|
|
333
|
+
"remediation": "retry",
|
|
334
|
+
"en": "A guest account may not publish a listing"
|
|
335
|
+
},
|
|
329
336
|
{
|
|
330
337
|
"code": "error.403.listing_not_owner",
|
|
331
338
|
"status": 403,
|
|
@@ -8,7 +8,7 @@ import type { ListingsErrorCode } from "./errors.gen.js";
|
|
|
8
8
|
/**
|
|
9
9
|
* `ru` texts for the backend error codes this catalog carries.
|
|
10
10
|
*
|
|
11
|
-
* PARTIAL, and deliberately typed to say so:
|
|
11
|
+
* PARTIAL, and deliberately typed to say so: 23 key(s) owned by
|
|
12
12
|
* stapel_attributes, stapel_listings are absent, because that owner ships no locale catalog
|
|
13
13
|
* (ERRORS_LOCALE_EXEMPT_OWNERS). English for them still comes from the registry
|
|
14
14
|
* artifact via the en bundle; the pair layers its own authored `ru`
|
package/src/i18n/keys.ts
CHANGED
|
@@ -62,7 +62,17 @@ export const LISTINGS_I18N_KEYS = {
|
|
|
62
62
|
cardPriceAbsent: "listings.card.price_absent",
|
|
63
63
|
cardFavoriteAdd: "listings.card.favorite_add",
|
|
64
64
|
cardFavoriteRemove: "listings.card.favorite_remove",
|
|
65
|
-
|
|
65
|
+
/**
|
|
66
|
+
* The accessible name of a card whose listing has no title.
|
|
67
|
+
*
|
|
68
|
+
* The whole card is ONE anchor now, and an anchor's name is its `aria-label`
|
|
69
|
+
* — so a titleless listing would otherwise be a link announced as nothing at
|
|
70
|
+
* all, in a list of forty.
|
|
71
|
+
*
|
|
72
|
+
* This replaces `listings.card.open` (retired), which named a separate
|
|
73
|
+
* "Open" control that no longer exists: the card itself is the control.
|
|
74
|
+
*/
|
|
75
|
+
cardUntitled: "listings.card.untitled",
|
|
66
76
|
/** The door beside a blocked favourite: the container supplies WHERE. */
|
|
67
77
|
cardSignIn: "listings.card.sign_in",
|
|
68
78
|
|
|
@@ -88,6 +98,9 @@ export const LISTINGS_I18N_KEYS = {
|
|
|
88
98
|
* quantity in the value cell, so this key carries no `{count}` — it used to,
|
|
89
99
|
* and the live page printed the placeholder. */
|
|
90
100
|
detailStock: "listings.detail.stock",
|
|
101
|
+
/** The owner's two primaries on their own listing page. */
|
|
102
|
+
detailEdit: "listings.detail.edit",
|
|
103
|
+
detailTakeDown: "listings.detail.take_down",
|
|
91
104
|
|
|
92
105
|
// ── composer ─────────────────────────────────────────────────────────────
|
|
93
106
|
composeNewTitle: "listings.compose.new_title",
|
|
@@ -103,8 +116,7 @@ export const LISTINGS_I18N_KEYS = {
|
|
|
103
116
|
composePriceInvalid: "listings.compose.price_invalid",
|
|
104
117
|
composeCurrencyLabel: "listings.compose.currency_label",
|
|
105
118
|
composeLocationLabel: "listings.compose.location_label",
|
|
106
|
-
|
|
107
|
-
composeLonLabel: "listings.compose.lon_label",
|
|
119
|
+
composeLocationHelp: "listings.compose.location_help",
|
|
108
120
|
composeGeoIncomplete: "listings.compose.geo_incomplete",
|
|
109
121
|
composePhotos: "listings.compose.photos",
|
|
110
122
|
composeTooManyImages: "listings.compose.too_many_images",
|
|
@@ -132,6 +144,10 @@ export const LISTINGS_I18N_KEYS = {
|
|
|
132
144
|
composeBlockedNoDraft: "listings.compose.blocked.no_draft",
|
|
133
145
|
composeBlockedBusy: "listings.compose.blocked.busy",
|
|
134
146
|
composeBlockedMirror: "listings.compose.blocked.mirror",
|
|
147
|
+
/** The same refusal BEFORE anything is marked: "fix the highlighted fields"
|
|
148
|
+
* pointed at nothing highlighted, because the mirror only becomes visible
|
|
149
|
+
* once the person has tried to publish. */
|
|
150
|
+
composeBlockedIncomplete: "listings.compose.blocked.incomplete",
|
|
135
151
|
composeBlockedDetailsUnavailable: "listings.compose.blocked.details_unavailable",
|
|
136
152
|
|
|
137
153
|
// ── the owner's dashboard ────────────────────────────────────────────────
|
|
@@ -158,12 +174,18 @@ export const LISTINGS_I18N_KEYS = {
|
|
|
158
174
|
mineArchive: "listings.mine.archive",
|
|
159
175
|
mineComplete: "listings.mine.complete",
|
|
160
176
|
mineDelete: "listings.mine.delete",
|
|
177
|
+
/** Deleting is irreversible, so it asks — through the shared SkinConfirm,
|
|
178
|
+
* which is a bottom sheet on a phone. */
|
|
179
|
+
mineDeleteConfirmTitle: "listings.mine.delete_confirm_title",
|
|
180
|
+
mineDeleteConfirmBody: "listings.mine.delete_confirm_body",
|
|
161
181
|
|
|
162
182
|
// ── favourites ───────────────────────────────────────────────────────────
|
|
163
183
|
favoritesTitle: "listings.favorites.title",
|
|
164
184
|
favoritesLoading: "listings.favorites.loading",
|
|
165
185
|
favoritesLoadFailed: "listings.favorites.load_failed",
|
|
166
186
|
favoritesEmpty: "listings.favorites.empty",
|
|
187
|
+
favoritesEmptyHint: "listings.favorites.empty_hint",
|
|
188
|
+
favoritesSignInHint: "listings.favorites.sign_in_hint",
|
|
167
189
|
|
|
168
190
|
// ── gates shared by every action a visitor cannot take ───────────────────
|
|
169
191
|
blockedSignIn: "listings.blocked.sign_in",
|
|
@@ -174,10 +196,15 @@ export const LISTINGS_I18N_KEYS = {
|
|
|
174
196
|
blockedTransition: "listings.blocked.transition",
|
|
175
197
|
blockedDeleteActive: "listings.blocked.delete_active",
|
|
176
198
|
blockedInFlight: "listings.blocked.in_flight",
|
|
199
|
+
/** Editing is a SCREEN, not an endpoint: whether this app has one is the
|
|
200
|
+
* container's fact, and a host that wires no `onEdit` gets a switched-off
|
|
201
|
+
* button that says so instead of one that silently does nothing. */
|
|
202
|
+
blockedNoEditor: "listings.blocked.no_editor",
|
|
177
203
|
|
|
178
204
|
// ── keyset pagination ────────────────────────────────────────────────────
|
|
179
205
|
pagePrev: "listings.page.prev",
|
|
180
206
|
pageNext: "listings.page.next",
|
|
207
|
+
pageIndicator: "listings.page.indicator",
|
|
181
208
|
|
|
182
209
|
// ── nav labels ───────────────────────────────────────────────────────────
|
|
183
210
|
navDetail: "listings.nav.detail",
|
|
@@ -229,7 +256,7 @@ export const listingsI18nBundleEn: Record<string, string> = {
|
|
|
229
256
|
"listings.card.price_absent": "Price on request",
|
|
230
257
|
"listings.card.favorite_add": "Save to favourites",
|
|
231
258
|
"listings.card.favorite_remove": "Remove from favourites",
|
|
232
|
-
"listings.card.
|
|
259
|
+
"listings.card.untitled": "Untitled listing",
|
|
233
260
|
"listings.card.sign_in": "Sign in",
|
|
234
261
|
|
|
235
262
|
"listings.detail.loading": "Loading the listing…",
|
|
@@ -252,6 +279,8 @@ export const listingsI18nBundleEn: Record<string, string> = {
|
|
|
252
279
|
"listings.detail.published_at": "Published {date}",
|
|
253
280
|
"listings.detail.expires_at": "Listed until {date}",
|
|
254
281
|
"listings.detail.stock": "In stock",
|
|
282
|
+
"listings.detail.edit": "Edit listing",
|
|
283
|
+
"listings.detail.take_down": "Take it down",
|
|
255
284
|
|
|
256
285
|
"listings.compose.new_title": "New listing",
|
|
257
286
|
"listings.compose.edit_title": "Edit listing",
|
|
@@ -270,8 +299,8 @@ export const listingsI18nBundleEn: Record<string, string> = {
|
|
|
270
299
|
"Enter a price as a number, with at most two decimals",
|
|
271
300
|
"listings.compose.currency_label": "Currency",
|
|
272
301
|
"listings.compose.location_label": "Where it is",
|
|
273
|
-
"listings.compose.
|
|
274
|
-
|
|
302
|
+
"listings.compose.location_help":
|
|
303
|
+
"Buyers filter by distance, so a listing with no place is a listing they will not find",
|
|
275
304
|
"listings.compose.geo_incomplete":
|
|
276
305
|
"A latitude needs a longitude beside it — half a coordinate points nowhere",
|
|
277
306
|
"listings.compose.photos": "Photos",
|
|
@@ -300,14 +329,18 @@ export const listingsI18nBundleEn: Record<string, string> = {
|
|
|
300
329
|
|
|
301
330
|
"listings.compose.blocked.no_category":
|
|
302
331
|
"Choose a category — the rest of the form depends on it",
|
|
332
|
+
// No `{types}`: the editor type is this build's vocabulary (`size_grid`),
|
|
333
|
+
// and a seller can do nothing with it. The fact they CAN act on is that
|
|
334
|
+
// this listing has to be finished somewhere else.
|
|
303
335
|
"listings.compose.blocked.unsupported_type":
|
|
304
|
-
"This category asks for a kind of detail this app cannot show yet
|
|
336
|
+
"This category asks for a kind of detail this app cannot show yet, so the listing cannot be completed here",
|
|
305
337
|
"listings.compose.blocked.photos_pending":
|
|
306
338
|
"Wait for the photos to finish uploading",
|
|
307
339
|
"listings.compose.blocked.no_draft": "The draft has not been created yet",
|
|
308
340
|
"listings.compose.blocked.busy": "One moment — the last change is still saving",
|
|
309
341
|
"listings.compose.blocked.mirror":
|
|
310
342
|
"Fix the highlighted fields first",
|
|
343
|
+
"listings.compose.blocked.incomplete": "{count} required details are still empty",
|
|
311
344
|
"listings.compose.blocked.details_unavailable":
|
|
312
345
|
"We could not load what this category asks for, so we cannot check the form",
|
|
313
346
|
|
|
@@ -325,6 +358,10 @@ export const listingsI18nBundleEn: Record<string, string> = {
|
|
|
325
358
|
"listings.mine.empty.archived": "Nothing archived, paused, expired or sold yet",
|
|
326
359
|
"listings.mine.blocked.title":
|
|
327
360
|
"{count} of your listings were taken down by moderation",
|
|
361
|
+
"listings.mine.blocked.title.one":
|
|
362
|
+
"One of your listings was taken down by moderation",
|
|
363
|
+
"listings.mine.blocked.title.other":
|
|
364
|
+
"{count} of your listings were taken down by moderation",
|
|
328
365
|
"listings.mine.blocked.load_failed":
|
|
329
366
|
"We could not check whether any of your listings were taken down",
|
|
330
367
|
"listings.mine.live_under_review":
|
|
@@ -333,11 +370,18 @@ export const listingsI18nBundleEn: Record<string, string> = {
|
|
|
333
370
|
"listings.mine.archive": "Archive",
|
|
334
371
|
"listings.mine.complete": "Mark sold",
|
|
335
372
|
"listings.mine.delete": "Delete",
|
|
373
|
+
"listings.mine.delete_confirm_title": "Delete this listing?",
|
|
374
|
+
"listings.mine.delete_confirm_body":
|
|
375
|
+
"It disappears from your dashboard and cannot be brought back. Archiving keeps it.",
|
|
336
376
|
|
|
337
377
|
"listings.favorites.title": "Favourites",
|
|
338
378
|
"listings.favorites.loading": "Loading your favourites…",
|
|
339
379
|
"listings.favorites.load_failed": "We could not load your favourites",
|
|
340
380
|
"listings.favorites.empty": "You have not saved anything yet",
|
|
381
|
+
"listings.favorites.empty_hint":
|
|
382
|
+
"Tap the heart on any listing and it will be waiting here.",
|
|
383
|
+
"listings.favorites.sign_in_hint":
|
|
384
|
+
"Favourites are kept with your account, so they follow you between devices.",
|
|
341
385
|
|
|
342
386
|
"listings.blocked.sign_in": "Sign in to do this",
|
|
343
387
|
"listings.blocked.guest":
|
|
@@ -349,9 +393,12 @@ export const listingsI18nBundleEn: Record<string, string> = {
|
|
|
349
393
|
"listings.blocked.delete_active":
|
|
350
394
|
"Archive it first — a listing that is on sale cannot be deleted",
|
|
351
395
|
"listings.blocked.in_flight": "One moment — that is already under way",
|
|
396
|
+
"listings.blocked.no_editor":
|
|
397
|
+
"This app has no screen for editing a listing yet",
|
|
352
398
|
|
|
353
399
|
"listings.page.prev": "Previous",
|
|
354
400
|
"listings.page.next": "Next",
|
|
401
|
+
"listings.page.indicator": "Page {page}",
|
|
355
402
|
|
|
356
403
|
"listings.nav.detail": "Listing",
|
|
357
404
|
"listings.nav.compose": "Post a listing",
|
package/src/i18n/ru.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { I18nDictionary, I18nEngine } from "@stapel/core";
|
|
2
|
+
import { registerAttributesI18nRu } from "@stapel/attributes-react/i18n/ru";
|
|
2
3
|
import { listingsErrorBundleRu } from "./generated/errors.ru.gen.js";
|
|
3
4
|
|
|
4
5
|
export { listingsErrorBundleRu } from "./generated/errors.ru.gen.js";
|
|
@@ -47,6 +48,8 @@ export const listingsI18nBundleRu: I18nDictionary = {
|
|
|
47
48
|
"Неизвестный статус объявления: «{status}»",
|
|
48
49
|
"error.400.publish_validation_failed":
|
|
49
50
|
"Объявление не прошло проверку и не опубликовано",
|
|
51
|
+
"error.403.listing_anonymous_not_allowed":
|
|
52
|
+
"Чтобы подать объявление, войдите или зарегистрируйтесь",
|
|
50
53
|
"error.403.listing_not_owner": "Это не ваше объявление",
|
|
51
54
|
"error.404.listing_not_found": "Объявление не найдено",
|
|
52
55
|
"error.409.already_favorited": "Объявление уже в избранном",
|
|
@@ -87,7 +90,7 @@ export const listingsI18nBundleRu: I18nDictionary = {
|
|
|
87
90
|
"listings.card.price_absent": "Цена по запросу",
|
|
88
91
|
"listings.card.favorite_add": "В избранное",
|
|
89
92
|
"listings.card.favorite_remove": "Убрать из избранного",
|
|
90
|
-
"listings.card.
|
|
93
|
+
"listings.card.untitled": "Объявление без названия",
|
|
91
94
|
"listings.card.sign_in": "Войти",
|
|
92
95
|
|
|
93
96
|
"listings.detail.loading": "Загружаем объявление…",
|
|
@@ -110,6 +113,8 @@ export const listingsI18nBundleRu: I18nDictionary = {
|
|
|
110
113
|
"listings.detail.published_at": "Опубликовано {date}",
|
|
111
114
|
"listings.detail.expires_at": "В продаже до {date}",
|
|
112
115
|
"listings.detail.stock": "В наличии",
|
|
116
|
+
"listings.detail.edit": "Редактировать объявление",
|
|
117
|
+
"listings.detail.take_down": "Снять с публикации",
|
|
113
118
|
|
|
114
119
|
"listings.compose.new_title": "Новое объявление",
|
|
115
120
|
"listings.compose.edit_title": "Редактирование объявления",
|
|
@@ -128,8 +133,8 @@ export const listingsI18nBundleRu: I18nDictionary = {
|
|
|
128
133
|
"Введите цену числом, не более двух знаков после запятой",
|
|
129
134
|
"listings.compose.currency_label": "Валюта",
|
|
130
135
|
"listings.compose.location_label": "Где находится",
|
|
131
|
-
"listings.compose.
|
|
132
|
-
|
|
136
|
+
"listings.compose.location_help":
|
|
137
|
+
"Покупатели ищут по расстоянию — объявление без места они просто не найдут",
|
|
133
138
|
"listings.compose.geo_incomplete":
|
|
134
139
|
"Рядом с широтой нужна долгота — половина координаты никуда не указывает",
|
|
135
140
|
"listings.compose.photos": "Фотографии",
|
|
@@ -160,12 +165,13 @@ export const listingsI18nBundleRu: I18nDictionary = {
|
|
|
160
165
|
"listings.compose.blocked.no_category":
|
|
161
166
|
"Выберите категорию — от неё зависит остальная форма",
|
|
162
167
|
"listings.compose.blocked.unsupported_type":
|
|
163
|
-
"Эта категория спрашивает характеристику, которую приложение пока не умеет
|
|
168
|
+
"Эта категория спрашивает характеристику, которую приложение пока не умеет показывать, поэтому закончить объявление здесь нельзя",
|
|
164
169
|
"listings.compose.blocked.photos_pending":
|
|
165
170
|
"Дождитесь окончания загрузки фотографий",
|
|
166
171
|
"listings.compose.blocked.no_draft": "Черновик ещё не создан",
|
|
167
172
|
"listings.compose.blocked.busy":
|
|
168
173
|
"Секунду — предыдущее изменение ещё сохраняется",
|
|
174
|
+
"listings.compose.blocked.incomplete": "Не заполнено обязательных деталей: {count}",
|
|
169
175
|
"listings.compose.blocked.mirror": "Сначала поправьте отмеченные поля",
|
|
170
176
|
"listings.compose.blocked.details_unavailable":
|
|
171
177
|
"Не удалось загрузить характеристики категории, поэтому проверить форму нельзя",
|
|
@@ -184,6 +190,10 @@ export const listingsI18nBundleRu: I18nDictionary = {
|
|
|
184
190
|
"listings.mine.empty.archived": "Пока ничего не в архиве, не снято, не истекло и не продано",
|
|
185
191
|
"listings.mine.blocked.title":
|
|
186
192
|
"Модерация сняла ваших объявлений: {count}",
|
|
193
|
+
"listings.mine.blocked.title.one": "Модерация сняла одно ваше объявление",
|
|
194
|
+
"listings.mine.blocked.title.few": "Модерация сняла {count} ваших объявления",
|
|
195
|
+
"listings.mine.blocked.title.many": "Модерация сняла {count} ваших объявлений",
|
|
196
|
+
"listings.mine.blocked.title.other": "Модерация сняла ваших объявлений: {count}",
|
|
187
197
|
"listings.mine.blocked.load_failed":
|
|
188
198
|
"Не удалось проверить, снимала ли модерация ваши объявления",
|
|
189
199
|
"listings.mine.live_under_review": "Опубликовано, правки на проверке",
|
|
@@ -191,11 +201,18 @@ export const listingsI18nBundleRu: I18nDictionary = {
|
|
|
191
201
|
"listings.mine.archive": "В архив",
|
|
192
202
|
"listings.mine.complete": "Отметить проданным",
|
|
193
203
|
"listings.mine.delete": "Удалить",
|
|
204
|
+
"listings.mine.delete_confirm_title": "Удалить объявление?",
|
|
205
|
+
"listings.mine.delete_confirm_body":
|
|
206
|
+
"Оно исчезнет из кабинета, и вернуть его будет нельзя. Архив сохраняет его.",
|
|
194
207
|
|
|
195
208
|
"listings.favorites.title": "Избранное",
|
|
196
209
|
"listings.favorites.loading": "Загружаем избранное…",
|
|
197
210
|
"listings.favorites.load_failed": "Не удалось загрузить избранное",
|
|
198
211
|
"listings.favorites.empty": "Вы ещё ничего не сохранили",
|
|
212
|
+
"listings.favorites.empty_hint":
|
|
213
|
+
"Нажмите на сердечко в любом объявлении — оно будет ждать здесь.",
|
|
214
|
+
"listings.favorites.sign_in_hint":
|
|
215
|
+
"Избранное хранится в аккаунте, поэтому переходит с вами на другие устройства.",
|
|
199
216
|
|
|
200
217
|
"listings.blocked.sign_in": "Войдите, чтобы сделать это",
|
|
201
218
|
"listings.blocked.guest":
|
|
@@ -207,9 +224,12 @@ export const listingsI18nBundleRu: I18nDictionary = {
|
|
|
207
224
|
"listings.blocked.delete_active":
|
|
208
225
|
"Сначала уберите в архив — объявление в продаже удалить нельзя",
|
|
209
226
|
"listings.blocked.in_flight": "Секунду — это уже выполняется",
|
|
227
|
+
"listings.blocked.no_editor":
|
|
228
|
+
"В этом приложении пока нет экрана редактирования объявления",
|
|
210
229
|
|
|
211
230
|
"listings.page.prev": "Назад",
|
|
212
231
|
"listings.page.next": "Дальше",
|
|
232
|
+
"listings.page.indicator": "Страница {page}",
|
|
213
233
|
|
|
214
234
|
"listings.nav.detail": "Объявление",
|
|
215
235
|
"listings.nav.compose": "Подать объявление",
|
|
@@ -217,7 +237,23 @@ export const listingsI18nBundleRu: I18nDictionary = {
|
|
|
217
237
|
"listings.nav.favorites": "Избранное",
|
|
218
238
|
};
|
|
219
239
|
|
|
220
|
-
/**
|
|
240
|
+
/**
|
|
241
|
+
* Register the Russian bundle into a core i18n engine — AND the twelve
|
|
242
|
+
* `stapel_attributes` sentences this pair deliberately does not author.
|
|
243
|
+
*
|
|
244
|
+
* The split of ownership is right and stays: two packages must not give one
|
|
245
|
+
* refusal two sentences. What was wrong was leaving the JOIN to a README. A
|
|
246
|
+
* host that registered only this bundle got twelve of the composer's most
|
|
247
|
+
* common refusals ("this value is below the minimum", "the description is too
|
|
248
|
+
* long") in English on a Russian page, and nothing failed anywhere to say so.
|
|
249
|
+
*
|
|
250
|
+
* `@stapel/attributes-react` is a peer of this pair and its editors are what
|
|
251
|
+
* RAISE those twelve, so a listings-ru host is an attributes-ru host by
|
|
252
|
+
* construction; chaining the registration states that instead of asking. It is
|
|
253
|
+
* idempotent — a host that also registers the bundle itself simply writes the
|
|
254
|
+
* same keys twice.
|
|
255
|
+
*/
|
|
221
256
|
export function registerListingsI18nRu(i18n: I18nEngine): void {
|
|
257
|
+
registerAttributesI18nRu(i18n);
|
|
222
258
|
i18n.registerBundle("ru", listingsI18nBundleRu);
|
|
223
259
|
}
|
package/src/index.ts
CHANGED
|
@@ -214,7 +214,11 @@ export type {
|
|
|
214
214
|
|
|
215
215
|
// ── headless (renderless components + their bags) ────────────────────────────
|
|
216
216
|
export { ListingsProvider } from "./headless/ListingsProvider.js";
|
|
217
|
-
export {
|
|
217
|
+
export {
|
|
218
|
+
useMandateGate,
|
|
219
|
+
useElevatableMandateGate,
|
|
220
|
+
LISTINGS_ELEVATION_ACTIONS,
|
|
221
|
+
} from "./headless/useMandateGate.js";
|
|
218
222
|
export { ListingDetail, useListingDetail } from "./headless/ListingDetail.js";
|
|
219
223
|
export type {
|
|
220
224
|
ListingDetailBag,
|
package/src/model/draft.ts
CHANGED
|
@@ -29,12 +29,14 @@ import { DEFAULT_LISTING_CURRENCY } from "../api/types.js";
|
|
|
29
29
|
* `geohash` that disagrees with the coordinates beside it is worse than no
|
|
30
30
|
* geohash — the pin and the bucket point at different places.
|
|
31
31
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
32
|
+
* `geohash` is SERVER-COMPUTED and read-only since stapel-listings 0.7.1.
|
|
33
|
+
* `Listing.save()` stamps `geohash_draft` from `lat_draft`/`lon_draft` through
|
|
34
|
+
* the `geo.geohash_encode` comm function, and `ListingDraftSerializer` marks
|
|
35
|
+
* the field `readOnly` — a value sent in the request body is silently ignored.
|
|
36
|
+
* So this member is something the composer READS BACK (a reopened draft, a
|
|
37
|
+
* published listing) and never something it sends: `draftPatchFromValues`
|
|
38
|
+
* omits it, and a picker that happens to know a geohash may keep it for its
|
|
39
|
+
* own display without expecting the wire to carry it.
|
|
38
40
|
*/
|
|
39
41
|
export interface ListingLocation {
|
|
40
42
|
/** Opaque id from whatever place directory the deployment uses. */
|
|
@@ -45,6 +47,7 @@ export interface ListingLocation {
|
|
|
45
47
|
* `55.796100` into `55.7961` and change what was submitted. */
|
|
46
48
|
readonly lat: string | null;
|
|
47
49
|
readonly lon: string | null;
|
|
50
|
+
/** Read-only: the server computes it from `lat`/`lon` (0.7.1). Never sent. */
|
|
48
51
|
readonly geohash: string;
|
|
49
52
|
}
|
|
50
53
|
|
|
@@ -242,7 +245,9 @@ export function draftPatchFromValues(
|
|
|
242
245
|
images_draft: [...values.images],
|
|
243
246
|
location_id_draft: values.location.locationId,
|
|
244
247
|
location_label_draft: values.location.locationLabel,
|
|
245
|
-
geohash_draft
|
|
248
|
+
// No `geohash_draft`: stapel-listings 0.7.1 computes it in `Listing.save()`
|
|
249
|
+
// from the coordinates and marks the serializer field read-only, so a value
|
|
250
|
+
// sent here is discarded. Sending one would be a claim the wire ignores.
|
|
246
251
|
lat_draft: values.location.lat,
|
|
247
252
|
lon_draft: values.location.lon,
|
|
248
253
|
features_draft: toWireFeatures(features, values.features),
|
package/src/model/features.ts
CHANGED
|
@@ -22,14 +22,28 @@
|
|
|
22
22
|
* `order`, `title`, `badge`) are simply ignored by every formatter. Copying a
|
|
23
23
|
* hand-picked subset instead would be a list to keep in step with ten types.
|
|
24
24
|
*
|
|
25
|
-
* ── What a DAO does NOT carry
|
|
25
|
+
* ── What a DAO does NOT carry, and the one line that repairs it ────────────
|
|
26
26
|
*
|
|
27
|
-
* `select`'s `options`. `
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* `
|
|
27
|
+
* `select`'s `options`. `SelectType.dto_to_dao` stores the chosen VALUES and
|
|
28
|
+
* the ui config, never the option table — the table lives on the CATEGORY, and
|
|
29
|
+
* not needing it is the whole point of the projection.
|
|
30
|
+
*
|
|
31
|
+
* The consequence was a defect the visual pass caught on every card and every
|
|
32
|
+
* spec row: `formatFeatureValue` resolves an option's copy by looking the
|
|
33
|
+
* value up in `config.options`, and with no table it falls through to
|
|
34
|
+
* `String(value)`. The stored value of a translatable catalogue IS a
|
|
35
|
+
* translation key, so a listing page printed `demo.condition.used` and
|
|
36
|
+
* `demo.brand.bosch` at people. (The server does not have this problem: its
|
|
37
|
+
* own `format_value` has the category's config in hand.)
|
|
38
|
+
*
|
|
39
|
+
* So the split below synthesizes the IDENTITY table — `{value: v, label: v}`
|
|
40
|
+
* for each stored value — which is exactly the table a translatable catalogue
|
|
41
|
+
* would have produced, since its labels ARE the keys. `formatFeatureValue`
|
|
42
|
+
* then runs the value through the host's `t` and a bundle carrying the
|
|
43
|
+
* catalogue copy reads "Used". A bundle that does not still shows the key, on
|
|
44
|
+
* purpose: a visible `option.condition.used` gets fixed, an invented "Used"
|
|
45
|
+
* ships wrong. A NON-translatable catalogue stores literal labels, `t` returns
|
|
46
|
+
* an unknown key unchanged, and the output is what it always was.
|
|
33
47
|
*/
|
|
34
48
|
import type { FeatureDef, FeatureValueDto } from "@stapel/attributes-react";
|
|
35
49
|
import type { ListingFeatureDao, ListingFeatureView } from "../api/types.js";
|
|
@@ -37,6 +51,31 @@ import type { ListingFeatureDao, ListingFeatureView } from "../api/types.js";
|
|
|
37
51
|
/** Keys that belong to the DAO envelope rather than to the type's config. */
|
|
38
52
|
const ENVELOPE = new Set(["slug", "value", "name", "order", "title", "badge"]);
|
|
39
53
|
|
|
54
|
+
/** The two types whose stored `value` is an option key rather than the thing
|
|
55
|
+
* itself. `hierarchical_select` is deliberately absent: its formatter joins
|
|
56
|
+
* the path with " / " and never consults an option table at all. */
|
|
57
|
+
const OPTION_VALUED = new Set(["select"]);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The identity option table for a stored `select` — see the module header.
|
|
61
|
+
*
|
|
62
|
+
* Returns `undefined` when there is nothing to add (another type, a config
|
|
63
|
+
* that already carries a table, a value that is not a list of strings), so the
|
|
64
|
+
* common path allocates nothing and a DAO that DOES carry options is left
|
|
65
|
+
* exactly as it arrived.
|
|
66
|
+
*/
|
|
67
|
+
function synthesizedOptions(
|
|
68
|
+
dao: ListingFeatureDao,
|
|
69
|
+
config: Readonly<Record<string, unknown>>
|
|
70
|
+
): readonly { value: string; label: string }[] | undefined {
|
|
71
|
+
if (typeof dao.type !== "string" || !OPTION_VALUED.has(dao.type)) return undefined;
|
|
72
|
+
if (Array.isArray(config["options"])) return undefined;
|
|
73
|
+
const raw = Array.isArray(dao.value) ? dao.value : [dao.value];
|
|
74
|
+
const values = raw.filter((item): item is string => typeof item === "string");
|
|
75
|
+
if (values.length === 0) return undefined;
|
|
76
|
+
return values.map((value) => ({ value, label: value }));
|
|
77
|
+
}
|
|
78
|
+
|
|
40
79
|
/**
|
|
41
80
|
* One DAO row → the definition/value pair the display half consumes.
|
|
42
81
|
*
|
|
@@ -54,6 +93,8 @@ export function featureFromDao(
|
|
|
54
93
|
for (const [key, value] of Object.entries(dao)) {
|
|
55
94
|
if (!ENVELOPE.has(key)) config[key] = value;
|
|
56
95
|
}
|
|
96
|
+
const options = synthesizedOptions(dao, config);
|
|
97
|
+
if (options !== undefined) config["options"] = options;
|
|
57
98
|
|
|
58
99
|
const feature: FeatureDef = {
|
|
59
100
|
slug: dao.slug,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties, ReactElement, ReactNode } from "react";
|
|
2
|
-
import type { FlowErrorDisplay } from "@stapel/core";
|
|
3
|
-
export declare function ErrorAlert(props: {
|
|
4
|
-
error: FlowErrorDisplay | undefined;
|
|
5
|
-
style?: CSSProperties | undefined;
|
|
6
|
-
testId?: string | undefined;
|
|
7
|
-
action?: ReactNode;
|
|
8
|
-
}): ReactElement | null;
|
|
9
|
-
//# sourceMappingURL=ErrorAlert.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorAlert.d.ts","sourceRoot":"","sources":["../../src/default/ErrorAlert.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpC,KAAK,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB,GAAG,YAAY,GAAG,IAAI,CAsBtB"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* The one error surface this pair's default skin renders, so the split copy
|
|
4
|
-
* core produces reaches a screen the same way everywhere (mirrors the
|
|
5
|
-
* docs/notifications/workspaces etalon).
|
|
6
|
-
*
|
|
7
|
-
* Core's `describeFlowError` splits a failure into the sentence a person
|
|
8
|
-
* reads and the technical detail a support agent quotes (owner report
|
|
9
|
-
* 2026-08-09: the status used to be spliced into the sentence, ending in a
|
|
10
|
-
* bare `" (500)"`). The split only helps if a skin renders both halves at
|
|
11
|
-
* their own weights: `message` at normal weight, `detail` muted and small.
|
|
12
|
-
*
|
|
13
|
-
* `undefined` in — including a `detail` core left `undefined` because there
|
|
14
|
-
* was nothing worth quoting — renders nothing rather than an empty line.
|
|
15
|
-
*/
|
|
16
|
-
import { Alert, Typography } from "antd";
|
|
17
|
-
export function ErrorAlert(props) {
|
|
18
|
-
const { error } = props;
|
|
19
|
-
if (!error)
|
|
20
|
-
return null;
|
|
21
|
-
return (_jsx(Alert, { type: "error", showIcon: true, ...(props.style ? { style: props.style } : {}), ...(props.testId ? { "data-testid": props.testId } : {}), ...(props.action ? { action: props.action } : {}), message: error.message, ...(error.detail
|
|
22
|
-
? {
|
|
23
|
-
description: (_jsx(Typography.Text, { type: "secondary", style: { fontSize: 12 }, children: error.detail })),
|
|
24
|
-
}
|
|
25
|
-
: {}) }));
|
|
26
|
-
}
|
|
27
|
-
//# sourceMappingURL=ErrorAlert.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorAlert.js","sourceRoot":"","sources":["../../src/default/ErrorAlert.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAIzC,MAAM,UAAU,UAAU,CAAC,KAK1B;IACC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IACxB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,CACL,KAAC,KAAK,IACJ,IAAI,EAAC,OAAO,EACZ,QAAQ,WACJ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAC3C,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KACrD,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAClD,OAAO,EAAE,KAAK,CAAC,OAAO,KAClB,CAAC,KAAK,CAAC,MAAM;YACf,CAAC,CAAC;gBACE,WAAW,EAAE,CACX,KAAC,UAAU,CAAC,IAAI,IAAC,IAAI,EAAC,WAAW,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,YACtD,KAAK,CAAC,MAAM,GACG,CACnB;aACF;YACH,CAAC,CAAC,EAAE,CAAC,GACP,CACH,CAAC;AACJ,CAAC"}
|
package/dist/default/theme.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties, ReactElement, ReactNode } from "react";
|
|
2
|
-
import type { ThemeMode } from "@stapel/tokens-antd";
|
|
3
|
-
export interface ListingsSkinThemeProps {
|
|
4
|
-
/**
|
|
5
|
-
* Light or dark. Defaults to the mode the host's document declares
|
|
6
|
-
* (`resolveThemeMode()`). Pass explicitly to pin a side.
|
|
7
|
-
*/
|
|
8
|
-
readonly mode?: ThemeMode;
|
|
9
|
-
/** Extra styles merged onto the themed root element (layout only — colors
|
|
10
|
-
* come from the mode). */
|
|
11
|
-
readonly style?: CSSProperties;
|
|
12
|
-
readonly children: ReactNode;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* `<ListingsSkinTheme/>` — the self-theming wrapper of
|
|
16
|
-
* `@stapel/listings-react/default`. Standalone use is supported (wrap any
|
|
17
|
-
* composition of the skin's parts once); the shipped surfaces
|
|
18
|
-
* (`ListingCard`, `ListingDetailPane`, `ListingComposerPage`,
|
|
19
|
-
* `MyListingsPane`, `FavoritesPane`)
|
|
20
|
-
* each already wrap themselves, and nested antd
|
|
21
|
-
* `ConfigProvider`s merge, so composing them under one `ListingsSkinTheme`
|
|
22
|
-
* stays correct.
|
|
23
|
-
*/
|
|
24
|
-
export declare function ListingsSkinTheme(props: ListingsSkinThemeProps): ReactElement;
|
|
25
|
-
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/default/theme.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B;8BAC0B;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,YAAY,CAmB7E"}
|
package/dist/default/theme.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* The default skin's INTERNAL theme provider — every `/default` surface wraps
|
|
4
|
-
* itself in this, so the skin is readable no matter what the host supplies
|
|
5
|
-
* (tracker #26: a skin set with no internal provider once inherited a theme
|
|
6
|
-
* bridge serving light-mode values inside a dark document — text on
|
|
7
|
-
* background at 1.00:1). The theme derives from `@stapel/tokens` via
|
|
8
|
-
* `@stapel/tokens-antd`'s `toAntdThemeConfig(mode)`; `mode` defaults to what
|
|
9
|
-
* the HOST's document declares (`resolveThemeMode()` — the `data-theme`
|
|
10
|
-
* attribute `tokens.css` keys its dark block on), never to a hardcoded side.
|
|
11
|
-
*
|
|
12
|
-
* This is also what "override styles" means for this pair: a storefront
|
|
13
|
-
* retheming through the §68 token JSON regenerates its `--stapel-*` custom
|
|
14
|
-
* properties and the result page follows with zero code — a far better deal
|
|
15
|
-
* than a prop-per-colour API, and the reason the skin has none.
|
|
16
|
-
*/
|
|
17
|
-
import { useMemo } from "react";
|
|
18
|
-
import { ConfigProvider } from "antd";
|
|
19
|
-
import { resolveThemeMode, toAntdTheme, toAntdThemeConfig, } from "@stapel/tokens-antd";
|
|
20
|
-
/**
|
|
21
|
-
* `<ListingsSkinTheme/>` — the self-theming wrapper of
|
|
22
|
-
* `@stapel/listings-react/default`. Standalone use is supported (wrap any
|
|
23
|
-
* composition of the skin's parts once); the shipped surfaces
|
|
24
|
-
* (`ListingCard`, `ListingDetailPane`, `ListingComposerPage`,
|
|
25
|
-
* `MyListingsPane`, `FavoritesPane`)
|
|
26
|
-
* each already wrap themselves, and nested antd
|
|
27
|
-
* `ConfigProvider`s merge, so composing them under one `ListingsSkinTheme`
|
|
28
|
-
* stays correct.
|
|
29
|
-
*/
|
|
30
|
-
export function ListingsSkinTheme(props) {
|
|
31
|
-
const mode = props.mode ?? resolveThemeMode();
|
|
32
|
-
const theme = useMemo(() => toAntdThemeConfig(mode), [mode]);
|
|
33
|
-
const token = useMemo(() => toAntdTheme(mode), [mode]);
|
|
34
|
-
return (_jsx(ConfigProvider, { theme: theme, children: _jsx("div", { "data-listings-skin-root": true, "data-listings-skin-mode": mode, style: {
|
|
35
|
-
color: token.colorText,
|
|
36
|
-
backgroundColor: token.colorBgContainer,
|
|
37
|
-
...props.style,
|
|
38
|
-
}, children: props.children }) }));
|
|
39
|
-
}
|
|
40
|
-
//# sourceMappingURL=theme.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/default/theme.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAe7B;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAA6B;IAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,gBAAgB,EAAE,CAAC;IAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,OAAO,CACL,KAAC,cAAc,IAAC,KAAK,EAAE,KAAK,YAC1B,0EAE2B,IAAI,EAC7B,KAAK,EAAE;gBACL,KAAK,EAAE,KAAK,CAAC,SAAS;gBACtB,eAAe,EAAE,KAAK,CAAC,gBAAgB;gBACvC,GAAG,KAAK,CAAC,KAAK;aACf,YAEA,KAAK,CAAC,QAAQ,GACX,GACS,CAClB,CAAC;AACJ,CAAC"}
|