@propeller-commerce/propeller-v2-react-ui 0.15.11 → 0.18.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 +107 -0
- package/README.md +17 -5
- package/dist/index.cjs +149 -114
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -5
- package/dist/index.d.ts +78 -5
- package/dist/index.js +149 -114
- package/dist/index.js.map +1 -1
- package/dist/pure.cjs +24 -19
- package/dist/pure.cjs.map +1 -1
- package/dist/pure.d.cts +10 -0
- package/dist/pure.d.ts +10 -0
- package/dist/pure.js +25 -20
- package/dist/pure.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,113 @@ once it reaches 1.0. Until then (the `0.x` line) the public API may change
|
|
|
8
8
|
between minor versions; breaking changes are called out below and in
|
|
9
9
|
[MIGRATION.md](./MIGRATION.md).
|
|
10
10
|
|
|
11
|
+
## [0.18.0] - 2026-08-20
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **After-hooks now say WHAT happened, not just that something did.** Three
|
|
16
|
+
callbacks reported success with no argument, which made them unusable for
|
|
17
|
+
anything that has to distinguish the outcome — analytics, audit trails, or
|
|
18
|
+
optimistic UI. All three arguments are optional, so existing zero-argument
|
|
19
|
+
callbacks keep working unchanged.
|
|
20
|
+
- `AddToFavorite.onFavoriteChanged(change?)` — `{ action: 'added' | 'removed',
|
|
21
|
+
listId, productId, clusterId }`. It fired identically for an add and a
|
|
22
|
+
removal, so a host could not report "added to wishlist" without inventing
|
|
23
|
+
the direction, and a wishlist metric that also counts removals is worse
|
|
24
|
+
than no metric.
|
|
25
|
+
- `FavoriteLists.onListChanged(change?)` / `useFavorites` — `{ action:
|
|
26
|
+
'created' | 'updated' | 'deleted', listId, name, isDefault }`. Note the
|
|
27
|
+
existing `onCreate` / `onEdit` / `onDelete` props are *overrides* that
|
|
28
|
+
replace the default mutation, so they were never usable as notifications.
|
|
29
|
+
- `QuickOrder.onTemplateDownload()` — the template link was a bare `<a>`, so
|
|
30
|
+
a buyer fetching the spreadsheet left no trace. Navigation is untouched.
|
|
31
|
+
|
|
32
|
+
### Notes
|
|
33
|
+
|
|
34
|
+
- `QuoteActions` deliberately gains no `afterReject`: the component has no
|
|
35
|
+
reject action to hook — only accept. A rejection callback would be dead API.
|
|
36
|
+
- `PurchaseAuthorizationRequests` needs no new prop either; the existing
|
|
37
|
+
`afterDeleteRequest` already covers the manager rejecting a request, which is
|
|
38
|
+
what "delete" means in that UI.
|
|
39
|
+
|
|
40
|
+
## [0.17.0] - 2026-08-20
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **A host `className` override could not beat the component's own utility
|
|
45
|
+
(PWP-942 #17).** Class lists were built by string-appending the override
|
|
46
|
+
after the package's defaults, which decides nothing — the cascade does, not
|
|
47
|
+
attribute order. `iconClassName="text-cocoa"` on `AccountIconAndMenu` (baked-in
|
|
48
|
+
`text-white`) produced an element carrying both and rendered white, while the
|
|
49
|
+
same override on `CartIconAndSidebar` appeared to work only because its
|
|
50
|
+
default happened to lose anyway. Every override site now merges through
|
|
51
|
+
`tailwind-merge`, so a conflicting utility is replaced rather than raced.
|
|
52
|
+
59 sites across 47 components; BEM hooks and non-conflicting utilities are
|
|
53
|
+
untouched.
|
|
54
|
+
|
|
55
|
+
- **Anonymous catalog listings were scoped differently on the client than on
|
|
56
|
+
the server (PWP-942 #22).** Listing hooks derived `userId` only from a
|
|
57
|
+
logged-in user and omitted the key entirely for guests, while a server-side
|
|
58
|
+
seed scopes anonymous queries to the channel's `anonymousUserId`. The two
|
|
59
|
+
therefore asked different questions, and the client refetch quietly replaced
|
|
60
|
+
a correctly-scoped product list with a differently-scoped one — assortment
|
|
61
|
+
rules, negative order lists in particular, are applied per user. All five
|
|
62
|
+
listing hooks (`useProductSearch` ×2, `useProductSlider`, `useQuickOrder`,
|
|
63
|
+
`useSpareParts`) now resolve the id through one shared helper. Hosts that
|
|
64
|
+
supply no `anonymousUserId` behave exactly as before.
|
|
65
|
+
|
|
66
|
+
### Added
|
|
67
|
+
|
|
68
|
+
- **`configuration.anonymousUserId`** — the channel's guest account, resolved
|
|
69
|
+
server-side and handed to the package so client-side listings can scope to
|
|
70
|
+
it. Same route `baseCategoryId` takes since PWP-913; no module guesses it.
|
|
71
|
+
|
|
72
|
+
## [0.16.0] - 2026-08-12
|
|
73
|
+
|
|
74
|
+
### Fixed
|
|
75
|
+
|
|
76
|
+
- **Localized names and slugs ignored the storefront language (PWP-936 /
|
|
77
|
+
PWP-940).** A localized array carries one entry per authored language in
|
|
78
|
+
catalog order, so `names[0]` / `slugs[0]` is the catalog's DEFAULT language,
|
|
79
|
+
not the storefront's. Thirteen sites read index 0 unconditionally while
|
|
80
|
+
eleven others resolved by language correctly. Now all of them go through
|
|
81
|
+
`getLocalizedValue`, which prefers the active language and falls back to any
|
|
82
|
+
translation that has a value:
|
|
83
|
+
- `ClusterOptions` — option group and option product names (PWP-936)
|
|
84
|
+
- `FavoriteListItem`, `FavoriteListDetails` — product and cluster names
|
|
85
|
+
- `ItemsOverview` — item, bundle-leader, bundle-item and child-option names
|
|
86
|
+
- `ProductBundles` — bundle item names
|
|
87
|
+
- `OrderItemCard` — item name, child-item names, and **the cluster/product
|
|
88
|
+
slugs used to build the item's link**
|
|
89
|
+
- `SearchBar` — **the slug used to build each autosuggest result's link**
|
|
90
|
+
|
|
91
|
+
The three slug sites are the ones that actually broke: they emitted
|
|
92
|
+
default-language URLs on every non-default locale.
|
|
93
|
+
- **`useCart` never adopted a cart id that arrived after mount (PWP-938 /
|
|
94
|
+
PWP-937).** The id was seeded once with `useState(options.cartId || '')` and
|
|
95
|
+
only reassigned from the hook's own cart-creation path, so a component that
|
|
96
|
+
mounted before the cart resolved held `''` permanently. `CartIconAndSidebar`
|
|
97
|
+
renders in the header on the first paint of every page, so its "Request
|
|
98
|
+
authorization" button rendered enabled, fired, and returned `err('No cart')`
|
|
99
|
+
with nothing sent — the reported "cannot submit purchase request". The id is
|
|
100
|
+
now derived from the prop on every render. `processCart` was affected the
|
|
101
|
+
same way.
|
|
102
|
+
|
|
103
|
+
### Changed
|
|
104
|
+
|
|
105
|
+
- **BREAKING (behavioural, hosts should act):** `OrderItemCard` gains a
|
|
106
|
+
`language` prop. The component is exported from the RSC-safe `/pure` entry
|
|
107
|
+
and reads no context by design, so a host that renders it directly must pass
|
|
108
|
+
`language` or it keeps resolving in the catalog's default language.
|
|
109
|
+
`OrderBonusItems` forwards its own resolved language automatically.
|
|
110
|
+
- `ClusterOptions` resolves `language` from `<PropellerProvider>` via
|
|
111
|
+
`useInfraProps`, like the other catalog components. Passing it explicitly
|
|
112
|
+
still wins.
|
|
113
|
+
- The favorites list's add-product button default now reads "Add product to
|
|
114
|
+
favorite list" instead of "Add product directly to this wishlist" (PWP-939).
|
|
115
|
+
Hosts that translate `FavoriteListDetails.addProductDirectly` should update
|
|
116
|
+
their own copy — "favorite list" is the agreed term, not "wishlist".
|
|
117
|
+
|
|
11
118
|
## [0.15.11] - 2026-08-11
|
|
12
119
|
|
|
13
120
|
### Fixed
|
package/README.md
CHANGED
|
@@ -307,9 +307,17 @@ and pass it once.
|
|
|
307
307
|
| `language` | `string` | Locale code used to resolve localized content (e.g. `'NL'`, `'EN'`). |
|
|
308
308
|
| `includeTax` | `boolean` | Whether displayed prices include tax. |
|
|
309
309
|
| `currency` | `string` | Currency symbol for price formatting. Default: `'€'`. |
|
|
310
|
-
| `configuration` | `unknown` |
|
|
310
|
+
| `configuration` | `unknown` | Config bag forwarded to components. Recognized keys: `baseCategoryId`, `anonymousUserId` (see below), image filters — plus anything of your own. |
|
|
311
311
|
| `portalMode` | `string` | Storefront mode (e.g. `'open'`, `'closed'`). |
|
|
312
312
|
|
|
313
|
+
**`configuration.anonymousUserId`** — the channel's guest account. Listing
|
|
314
|
+
hooks scope logged-out catalog queries to it, so the client asks the same
|
|
315
|
+
question your server-rendered seed did. Resolve it server-side (only the
|
|
316
|
+
server can reach the channel) and pass it in; when it's absent, anonymous
|
|
317
|
+
queries send no `userId` and the backend falls back to the api key's own
|
|
318
|
+
scope. Getting this wrong is invisible — the grid renders, just with the
|
|
319
|
+
wrong assortment.
|
|
320
|
+
|
|
313
321
|
The `value` object is reactive — when your auth/company/language state
|
|
314
322
|
changes, recompute it (memoize on those dependencies) and the provider
|
|
315
323
|
propagates the new value. Components re-render with fresh infra; service
|
|
@@ -584,15 +592,19 @@ cascade order — no `!important` needed:
|
|
|
584
592
|
.propeller-breadcrumbs__separator { display: none; }
|
|
585
593
|
```
|
|
586
594
|
|
|
587
|
-
**3. Per-instance `className`** — every component
|
|
588
|
-
|
|
595
|
+
**3. Per-instance `className`** — every component merges `props.className`
|
|
596
|
+
into its root classes, so a one-off override is a regular prop:
|
|
589
597
|
|
|
590
598
|
```tsx
|
|
591
599
|
<ProductCard product={p} className="ring-2 ring-yellow-400" />
|
|
592
600
|
```
|
|
593
601
|
|
|
594
|
-
|
|
595
|
-
|
|
602
|
+
The merge runs through [`tailwind-merge`](https://github.com/dcastil/tailwind-merge)
|
|
603
|
+
(since 0.17.0), so an override **replaces** the base utility it conflicts with
|
|
604
|
+
rather than racing it in the cascade — `iconClassName="text-cocoa"` on a
|
|
605
|
+
component whose default is `text-white` now renders cocoa. Non-conflicting
|
|
606
|
+
utilities and the BEM hooks are left untouched. To remove a default outright
|
|
607
|
+
(rather than override it), use a BEM hook.
|
|
596
608
|
|
|
597
609
|
See [STYLING.md](./STYLING.md) for the full token list, the complete BEM
|
|
598
610
|
hook catalog, and the cascade rationale.
|