create-cartbase 0.1.9 → 0.1.11
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/package.json
CHANGED
|
@@ -353,8 +353,13 @@ code-first through the error-copy maps, never raw API strings.
|
|
|
353
353
|
- **Props contract** — `{client, cart, customer, availableShippingMethods,
|
|
354
354
|
availablePaymentMethods, countryCode?, countries?, paymentMethodFilter?,
|
|
355
355
|
orderConfirmedPath?, onOrderPlaced?,
|
|
356
|
-
resolveTrackingMetadata?, logError?}`. `countries` is
|
|
357
|
-
|
|
356
|
+
resolveTrackingMetadata?, logError?}`. `countries` is OPTIONAL and is an
|
|
357
|
+
override: omit it and the hook calls `GET /api/store/countries` itself, so
|
|
358
|
+
the address form offers the countries the store's Markets declare, or the
|
|
359
|
+
whole catalogue when it declares none (0.11.0 — before that, omitting it
|
|
360
|
+
produced a ONE-country read-only field). A failure to load the list never
|
|
361
|
+
blocks a checkout: it falls back to `countryCode` and reports through
|
|
362
|
+
`logError` as `country_list_failed`. Fee prediction is never
|
|
358
363
|
hardcoded: each method LISTING entry carries its own
|
|
359
364
|
`fee_amount`/`fee_label`. `logError` replaces the legacy log writers
|
|
360
365
|
(all production log points preserved). Returns the full orchestration
|
|
@@ -412,9 +417,16 @@ code-first through the error-copy maps, never raw API strings.
|
|
|
412
417
|
`addressesInRegion`.
|
|
413
418
|
- **Props contract** — everything from the hook (`formData`,
|
|
414
419
|
`handleFormChange`, `handleFieldBlur`, `regionCountries`, `addressInput`,
|
|
415
|
-
`addressError`, `pulseFields`); `hideCountry?` for single-country stores
|
|
416
|
-
|
|
417
|
-
|
|
420
|
+
`addressError`, `pulseFields`); `hideCountry?` for single-country stores.
|
|
421
|
+
The country field is a NATIVE select carrying the chosen country's flag,
|
|
422
|
+
and it keeps `autocomplete="country"` on purpose: a custom listbox would
|
|
423
|
+
draw a flag per row but lose browser autofill and the phone's own picker,
|
|
424
|
+
and a checkout does not trade autofill for decoration. A list of exactly
|
|
425
|
+
one country still renders as a read-only name, which is right for a store
|
|
426
|
+
that truly sells to one country and is no longer the default for everyone
|
|
427
|
+
else (0.11.0).
|
|
428
|
+
- **Settings** — Admin → Settings → Markets → Regions, read through
|
|
429
|
+
`GET /api/store/countries`.
|
|
418
430
|
|
|
419
431
|
### `<CheckoutShippingMethodList />` — `checkout/shipping-method-list`
|
|
420
432
|
|
|
@@ -1092,12 +1104,27 @@ Shared storefront chrome, production-proven.
|
|
|
1092
1104
|
|
|
1093
1105
|
### `<CountrySelect regions value? onChange />` — `common/country-select`
|
|
1094
1106
|
|
|
1095
|
-
- **Purpose** —
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1107
|
+
- **Purpose** — the market picker for a header or footer. It lists REGIONS
|
|
1108
|
+
(`api/regions.listRegions`), valued by region id; persistence is app-owned
|
|
1109
|
+
via `onChange` (usually `carts.updateCart(client, cartId, {region_id})` +
|
|
1110
|
+
a cookie). The name is a leftover from the ported source and is wrong for
|
|
1111
|
+
what it does: it selects a market, not a country. Use
|
|
1112
|
+
`listCountries` + `CountryFlag` when you want a country.
|
|
1113
|
+
- **Settings** — Admin → Settings → Markets → Regions: which rows exist.
|
|
1114
|
+
|
|
1115
|
+
### `<CountryFlag code title? className? />` — `common/country-flag`
|
|
1116
|
+
|
|
1117
|
+
- **Purpose** — a country's flag from its ISO-3166 alpha-2 code, at the size
|
|
1118
|
+
of the text beside it. An unknown or empty code renders a neutral box that
|
|
1119
|
+
holds the same space, so a field does not jump when a shopper picks their
|
|
1120
|
+
country.
|
|
1121
|
+
- **Why a sprite and not an emoji** — Windows ships no flag glyphs, so an
|
|
1122
|
+
emoji flag reads as the two letters "BG" there. This draws `flag-icons`
|
|
1123
|
+
SVG under a CSS class, which renders the same on every platform, and it is
|
|
1124
|
+
the same sprite the Cartbase admin uses, so one country treatment runs
|
|
1125
|
+
across the admin and the storefront.
|
|
1126
|
+
- **Accessibility** — decorative and `aria-hidden`: a flag never carries
|
|
1127
|
+
meaning the name beside it does not. Pass `title` when it stands alone.
|
|
1101
1128
|
|
|
1102
1129
|
### `<LanguageSelect locales currentLocale onChange labels? />` — `common/language-select`
|
|
1103
1130
|
|
|
@@ -108,6 +108,69 @@ curl -s "$BASE/api/store/regions/reg_doesnotexist$RUN" \
|
|
|
108
108
|
|
|
109
109
|
---
|
|
110
110
|
|
|
111
|
+
## GET /api/store/countries
|
|
112
|
+
|
|
113
|
+
- **Purpose** — the countries a shopper may choose at checkout.
|
|
114
|
+
|
|
115
|
+
**The rule is the platform's, not your storefront's.** The store's own
|
|
116
|
+
Markets decide where it sells, and a store that has decided nothing yet
|
|
117
|
+
sells to the whole world. So this endpoint answers with:
|
|
118
|
+
|
|
119
|
+
- the countries the store's regions declare, when it has declared any
|
|
120
|
+
(`"restricted": true`), or
|
|
121
|
+
- the whole 250-entry ISO catalogue, when it has declared none
|
|
122
|
+
(`"restricted": false`).
|
|
123
|
+
|
|
124
|
+
Either way your code hardcodes no country list and invents no fallback of
|
|
125
|
+
its own. A merchant changes the answer in Admin → Settings → Markets →
|
|
126
|
+
Regions, where a region owns its countries.
|
|
127
|
+
|
|
128
|
+
```jsonc
|
|
129
|
+
// query (all optional)
|
|
130
|
+
{
|
|
131
|
+
"q": "bulg", // case-insensitive substring on the displayed name
|
|
132
|
+
"limit": 300, // 1–300, default 300 — the whole catalogue in one call
|
|
133
|
+
"offset": 0
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
- **Response** — ordered by `display_name`, the name a shopper reads.
|
|
138
|
+
|
|
139
|
+
```jsonc
|
|
140
|
+
{
|
|
141
|
+
"countries": [
|
|
142
|
+
{
|
|
143
|
+
"iso_2": "bg", // lowercase alpha-2: the cart address value
|
|
144
|
+
"display_name": "Bulgaria", // what a shopper reads
|
|
145
|
+
"name": "BULGARIA", // the catalogue's uppercase form
|
|
146
|
+
"region_id": "reg_01..." // null when the store has not placed it
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
"count": 250,
|
|
150
|
+
"offset": 0,
|
|
151
|
+
"limit": 300,
|
|
152
|
+
"restricted": false
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# every country the store offers, and which of the two lists you received
|
|
158
|
+
curl -s "$BASE/api/store/countries" -H "x-client-id: $CLIENT_ID" \
|
|
159
|
+
| grep -q '"restricted"'
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
- **SDK** — `listCountries(client, query?)` from
|
|
163
|
+
`@cartbase/storefront/api/regions`.
|
|
164
|
+
- **Components** — the checkout address form's country select.
|
|
165
|
+
`useCheckoutOrchestration` CALLS THIS FOR YOU when you do not pass a
|
|
166
|
+
`countries` list, so a new store offers every country with no wiring;
|
|
167
|
+
pass your own list only to override the store's answer. The chosen
|
|
168
|
+
country's flag is drawn by `CountryFlag`
|
|
169
|
+
(`@cartbase/storefront/common/country-flag`).
|
|
170
|
+
- **Settings** — Admin → Settings → Markets → Regions.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
111
174
|
## GET /api/store/currencies
|
|
112
175
|
|
|
113
176
|
- **Purpose** — list the currencies ENABLED on this store (the shared
|
|
@@ -32,8 +32,19 @@ export function CheckoutPageClient({
|
|
|
32
32
|
customer={null}
|
|
33
33
|
availableShippingMethods={shippingOptions}
|
|
34
34
|
availablePaymentMethods={paymentProviders}
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
// NO COUNTRY LIST HERE, on purpose (2026-09-13). This file is the
|
|
36
|
+
// seed for every scaffolded store, and it used to pass
|
|
37
|
+
// `countries={[{iso_2:"bg", display_name:"Bulgaria"}]}` with
|
|
38
|
+
// `countryCode="bg"`, so every store on earth shipped a checkout
|
|
39
|
+
// offering one country, Bulgaria, in a box the shopper could not
|
|
40
|
+
// change. The list belongs to the store, not to this file: omit the
|
|
41
|
+
// prop and the hook reads GET /api/store/countries, which answers
|
|
42
|
+
// with the countries the store's Markets declare, or with the whole
|
|
43
|
+
// world when it has declared none.
|
|
44
|
+
//
|
|
45
|
+
// A single-market store adds `countryCode="xx"` here to preselect
|
|
46
|
+
// its country, and a store that sells to exactly one country gets
|
|
47
|
+
// the read-only field automatically, because its Markets say so.
|
|
37
48
|
// Per-store rule (the documented paymentMethodFilter seam): this
|
|
38
49
|
// reference store checks out offline via its merchant methods only
|
|
39
50
|
// (pp_* kill: method entries carry payment_method_id, processors
|