@propeller-commerce/propeller-v2-react-ui 0.26.0 → 0.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,32 @@ 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.26.1] - 2026-09-28
12
+
13
+ ### Fixed
14
+
15
+ - **A quoted-price product could still be added to the cart from a grid.**
16
+ 0.26.0 guarded the PRICE on `ProductCard` but not the ACTION beside it, so a
17
+ listing showed "Price on request" next to a working quantity stepper and
18
+ add-to-cart button — and the line went in at 0. The card now offers
19
+ "Request a price", linking to the product page that owns the quote flow;
20
+ `FavoriteListItem` suppresses add-to-cart for these products outright. The
21
+ check sits before the injected-component branch, so a host-supplied control
22
+ is gated too.
23
+
24
+ - **Popovers inherited the host header’s text colour.** The search input, the
25
+ autosuggest dropdown, the cart sidebar and the cart popover each set their own
26
+ background but not their own text colour, so a shop with a dark header — which
27
+ has to colour that bar to style the triggers inside it — got white text on
28
+ their light surfaces. They are DOM children of those triggers, so the colour
29
+ cascaded straight in. Each now sets `text-foreground` explicitly, as
30
+ `AccountIconAndMenu` already did.
31
+
32
+ ### Changed
33
+
34
+ - `RequestPriceButton` uses a price-tag icon rather than a quote bubble, which
35
+ read as a comment action.
36
+
11
37
  ## [0.26.0] - 2026-09-28
12
38
 
13
39
  ### Added
@@ -42,15 +68,15 @@ between minor versions; breaking changes are called out below and in
42
68
  `priceOnRequest` renders in its place, and a card for such a product may
43
69
  carry no price object at all. Existing callers are unaffected.
44
70
 
45
- - **The PDP gates add-to-cart in the WordPress plugin's order**: `orderable`
46
- first, then the display mode. A non-orderable product gets neither control, a
47
- quoted one gets the request button, and an anonymous visitor gets the log-in
48
- action rather than a list they cannot be quoted from.
71
+ - **The PDP gates add-to-cart on `orderable` before the display mode.** A
72
+ non-orderable product gets neither control, a quoted one gets the request
73
+ button, and an anonymous visitor gets the log-in action rather than a list they
74
+ cannot be quoted from.
49
75
 
50
76
  - **Quick order excludes quoted products.** A bulk upload reports the code as
51
77
  unresolved instead of adding a line priced at 0; picking one from the
52
- typeahead clears the row with a notice. Matches the plugin, which drops them
53
- from quick-order search results server-side.
78
+ typeahead clears the row with a notice. Bulk flows have nowhere to show a
79
+ price and would submit the line at 0.
54
80
 
55
81
  ## [0.25.0] - 2026-09-25
56
82
 
package/dist/index.cjs CHANGED
@@ -7658,7 +7658,7 @@ function CartIconAndSidebar(rawProps) {
7658
7658
  ]
7659
7659
  }
7660
7660
  ),
7661
- props.showTotals && isHovered && totalItems > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-cart-icon__popover absolute top-full right-0 mt-1 z-40 bg-popover border border-border rounded-container shadow-lg px-3 py-2 min-w-[140px] text-sm whitespace-nowrap", children: [
7661
+ props.showTotals && isHovered && totalItems > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-cart-icon__popover absolute top-full right-0 mt-1 z-40 bg-popover text-foreground border border-border rounded-container shadow-lg px-3 py-2 min-w-[140px] text-sm whitespace-nowrap", children: [
7662
7662
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between gap-4", children: [
7663
7663
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "propeller-cart-icon__popover-label text-muted-foreground", children: totalLabel("totalLabel") }),
7664
7664
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "propeller-cart-icon__popover-total font-semibold text-foreground", children: totalPrice })
@@ -7686,7 +7686,7 @@ function CartIconAndSidebar(rawProps) {
7686
7686
  "aria-modal": "true",
7687
7687
  "aria-label": sidebarTitle,
7688
7688
  "data-open": sidebarOpen ? "true" : "false",
7689
- className: cn(`propeller-cart-icon__sidebar fixed inset-y-0 right-0 z-[70] w-full max-w-md bg-card shadow-2xl transform transition-transform duration-300 ease-in-out border-l border-border${sidebarOpen ? " translate-x-0" : " translate-x-full"}${props.sidebarClassName ? " " + props.sidebarClassName : ""}`),
7689
+ className: cn(`propeller-cart-icon__sidebar fixed inset-y-0 right-0 z-[70] w-full max-w-md bg-card text-foreground shadow-2xl transform transition-transform duration-300 ease-in-out border-l border-border${sidebarOpen ? " translate-x-0" : " translate-x-full"}${props.sidebarClassName ? " " + props.sidebarClassName : ""}`),
7690
7690
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col h-full", children: isMounted ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7691
7691
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-cart-icon__sidebar-header flex items-center justify-between px-5 py-4 border-b border-border", children: [
7692
7692
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
@@ -9347,7 +9347,7 @@ function ProductCardPrice(props) {
9347
9347
  ) });
9348
9348
  }
9349
9349
  function ProductCardAddToCart(props) {
9350
- const { product, resolved } = useProductCard();
9350
+ const { product, derived, resolved, handleProductClick } = useProductCard();
9351
9351
  if (propellerV2CoreUi.isContentHidden(resolved.portalMode, resolved.user, resolved.isAuthenticated)) {
9352
9352
  return /* @__PURE__ */ jsxRuntime.jsx(
9353
9353
  LoginToOrderButton_default,
@@ -9358,6 +9358,19 @@ function ProductCardAddToCart(props) {
9358
9358
  }
9359
9359
  );
9360
9360
  }
9361
+ if (isPriceOnRequest(product)) {
9362
+ return /* @__PURE__ */ jsxRuntime.jsx(
9363
+ "a",
9364
+ {
9365
+ href: derived.productUrl,
9366
+ onClick: handleProductClick,
9367
+ className: cn(
9368
+ `propeller-product-card__view-product inline-flex h-10 w-full items-center justify-center rounded-control bg-primary px-4 text-sm font-medium text-primary-foreground transition-opacity hover:opacity-90 ${props.className || ""}`
9369
+ ),
9370
+ children: propellerV2CoreUi.getLabel(resolved.priceLabels, "requestPrice", "Request a price")
9371
+ }
9372
+ );
9373
+ }
9361
9374
  const InjectedAddToCart = resolved.addToCartComponent;
9362
9375
  if (InjectedAddToCart) {
9363
9376
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -11913,7 +11926,7 @@ function FavoriteListItemActions(props) {
11913
11926
  className: props.className ?? "propeller-favorite-list-item__actions flex items-center gap-2 flex-shrink-0",
11914
11927
  onClick: (e) => e.stopPropagation(),
11915
11928
  children: [
11916
- resolved.allowAddToCart !== false && isProduct && !!resolved.graphqlClient ? /* @__PURE__ */ jsxRuntime.jsx(
11929
+ resolved.allowAddToCart !== false && isProduct && !!resolved.graphqlClient && !isPriceOnRequest(product) ? /* @__PURE__ */ jsxRuntime.jsx(
11917
11930
  AddToCart_default,
11918
11931
  {
11919
11932
  className: "flex items-center gap-2",
@@ -14676,7 +14689,7 @@ function RequestPriceButton(props) {
14676
14689
  if (props.onRequestPrice) props.onRequestPrice();
14677
14690
  },
14678
14691
  children: [
14679
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquareQuote, { className: "propeller-request-price__icon w-4 h-4", "aria-hidden": "true" }),
14692
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Tag, { className: "propeller-request-price__icon w-4 h-4", "aria-hidden": "true" }),
14680
14693
  label
14681
14694
  ]
14682
14695
  }
@@ -19352,7 +19365,7 @@ function SearchBar(rawProps) {
19352
19365
  // boilerplate's dark header band happened to make work: on a
19353
19366
  // light header `bg-white/95 border-white/20` rendered as an
19354
19367
  // invisible input.
19355
- "propeller-search-bar__input w-full pl-10 pr-10 py-2 bg-card border border-input rounded-container focus:outline-none focus:ring-2 focus:ring-secondary placeholder:text-muted-foreground",
19368
+ "propeller-search-bar__input w-full pl-10 pr-10 py-2 bg-card text-foreground border border-input rounded-container focus:outline-none focus:ring-2 focus:ring-secondary placeholder:text-muted-foreground",
19356
19369
  props.inputClassName
19357
19370
  ),
19358
19371
  placeholder: props.placeholder || "Search products...",
@@ -19362,7 +19375,7 @@ function SearchBar(rawProps) {
19362
19375
  ),
19363
19376
  searchLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "propeller-search-bar__spinner-wrapper absolute right-3 top-1/2 transform -translate-y-1/2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "propeller-search-bar__spinner animate-spin rounded-full h-5 w-5 border-b-2 border-primary" }) }) : null
19364
19377
  ] }) }),
19365
- showDropdown ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-search-bar__dropdown absolute top-full left-0 right-0 mt-2 bg-card rounded-container shadow-xl border border-border z-50 flex flex-col max-h-96", children: [
19378
+ showDropdown ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "propeller-search-bar__dropdown absolute top-full left-0 right-0 mt-2 bg-card text-foreground rounded-container shadow-xl border border-border z-50 flex flex-col max-h-96", children: [
19366
19379
  results.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
19367
19380
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "propeller-search-bar__results flex-1 overflow-y-auto", children: results?.map((result, index) => {
19368
19381
  const ResultTag = props.getResultHref ? "a" : "div";