@propeller-commerce/propeller-v2-vue-ui 0.3.36 → 0.3.38

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,42 @@ 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.3.38] - 2026-07-21
12
+
13
+ ### Fixed
14
+
15
+ - **`SearchBar` autosuggest orderlist scoping — real fix.** 0.3.37 set
16
+ `orderlistIds`/`applyOrderlists` on the flat `products` search input, but the
17
+ server's `products` resolver does not honour orderlist scoping (only the
18
+ `category.products` resolver does), so the preview still leaked the full
19
+ catalogue inside a contract. The debounced autosuggest now runs the **same
20
+ category term-search the grid uses** (`getCategory` over the base category)
21
+ instead of the flat `getProducts`, so contract scoping is applied server-side
22
+ and the preview matches the grid exactly. Requires
23
+ `configuration.baseCategoryId` (already provided by all consumers).
24
+
25
+ ## [0.3.37] - 2026-07-21
26
+
27
+ ### Fixed
28
+
29
+ - **`SearchBar` autosuggest now respects orderlist (contract) scoping.** The
30
+ debounced live-search query built a plain `ProductSearchInput` that never
31
+ passed `orderlistIds`/`applyOrderlists`, so the dropdown previewed the full
32
+ catalogue even inside a B2B contract catalogue (the submitted results were
33
+ already correctly scoped — only the preview leaked). It now threads the same
34
+ orderlist scope as the grid fetch, so previews and results agree and a PDP
35
+ outside the contract is no longer reachable from the preview.
36
+
37
+ ### Added
38
+
39
+ - **`SearchBar`: `#price` scoped slot + `showPrice` prop.** The scoped
40
+ `#price` slot (receives `{ result }`) replaces the price cell of each result
41
+ with custom content — e.g. a "Price by quotation" label for a contract
42
+ catalogue where prices are quote-only; it fully overrides the default price
43
+ rendering. `showPrice` (default `true`) is a simpler boolean to hide the
44
+ price column outright. Both default to the previous behaviour, so the change
45
+ is backward-compatible.
46
+
11
47
  ## [0.3.36] - 2026-07-21
12
48
 
13
49
  ### Added
@@ -61,6 +61,17 @@ export interface SearchBarProps {
61
61
  * Omit to keep the button fallback.
62
62
  */
63
63
  getViewAllHref?: (term: string) => string;
64
+ /**
65
+ * Show the price column on each autosuggest result. Defaults to `true`.
66
+ * Set `false` to hide prices entirely in the dropdown — e.g. a B2B
67
+ * contract-catalogue context where prices are quote-only and shouldn't
68
+ * appear in the live preview. Ignored when the `price` slot is provided.
69
+ *
70
+ * For custom per-result price content (e.g. a "Price by quotation" label),
71
+ * use the scoped `#price` slot instead — it receives `{ result }` and fully
72
+ * overrides the default price cell.
73
+ */
74
+ showPrice?: boolean;
64
75
  /** Custom price formatting function */
65
76
  formatPrice?: (price: number) => string;
66
77
  /** Labels for the component */
@@ -107,5 +118,32 @@ export interface SearchBarProps {
107
118
  */
108
119
  clearSignal?: number;
109
120
  }
110
- declare const _default: import('vue').DefineComponent<SearchBarProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<SearchBarProps> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
121
+ declare function __VLS_template(): {
122
+ attrs: Partial<{}>;
123
+ slots: {
124
+ price?(_: {
125
+ result: {
126
+ id: number | string;
127
+ name: string;
128
+ sku?: string | undefined;
129
+ price?: number | undefined;
130
+ priceNet?: number | undefined;
131
+ priceGross?: number | undefined;
132
+ imageUrl?: string | undefined;
133
+ url?: string | undefined;
134
+ isCluster?: boolean | undefined;
135
+ };
136
+ }): any;
137
+ };
138
+ refs: {};
139
+ rootEl: HTMLDivElement;
140
+ };
141
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
142
+ declare const __VLS_component: import('vue').DefineComponent<SearchBarProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<SearchBarProps> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
143
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
111
144
  export default _default;
145
+ type __VLS_WithTemplateSlots<T, S> = T & {
146
+ new (): {
147
+ $slots: S;
148
+ };
149
+ };
package/dist/index.cjs CHANGED
@@ -2190,10 +2190,24 @@ function useProductSearch(options) {
2190
2190
  if (!graphqlClient) return;
2191
2191
  searchLoading.value = true;
2192
2192
  try {
2193
- const service = index.createServices(graphqlClient).product;
2194
2193
  const lang = languageRef.value || "NL";
2195
- const input = {
2196
- term,
2194
+ const service = index.createServices(graphqlClient).category;
2195
+ const catId = configuration?.baseCategoryId ?? 0;
2196
+ if (!catId) {
2197
+ searchResults.value = [];
2198
+ searchItemsFound.value = 0;
2199
+ return;
2200
+ }
2201
+ const searchOrderlistIds = options.orderlistIds?.value;
2202
+ const orderlistScope = searchOrderlistIds && searchOrderlistIds.length > 0 ? {
2203
+ applyOrderlists: options.applyOrderlists?.value !== false,
2204
+ orderlistIds: searchOrderlistIds
2205
+ } : { applyOrderlists: false };
2206
+ const user = userRef.value;
2207
+ const userId = user && "contactId" in user ? user.contactId : user && "customerId" in user ? user.customerId : void 0;
2208
+ const contactId = user && "contactId" in user ? user.contactId : void 0;
2209
+ const customerId = user && "customerId" in user ? user.customerId : void 0;
2210
+ const categoryProductSearchInput = {
2197
2211
  language: lang,
2198
2212
  page: 1,
2199
2213
  offset: 10,
@@ -2203,7 +2217,8 @@ function useProductSearch(options) {
2203
2217
  propellerSdkV2.ProductStatus.T,
2204
2218
  propellerSdkV2.ProductStatus.S
2205
2219
  ],
2206
- sortInputs: [{ field: propellerSdkV2.ProductSortField.RELEVANCE, order: propellerSdkV2.SortOrder.DESC }],
2220
+ hidden: false,
2221
+ term,
2207
2222
  searchFields: [
2208
2223
  {
2209
2224
  fieldNames: [
@@ -2230,16 +2245,30 @@ function useProductSearch(options) {
2230
2245
  ],
2231
2246
  boost: 1
2232
2247
  }
2233
- ]
2248
+ ],
2249
+ sortInputs: [{ field: propellerSdkV2.ProductSortField.RELEVANCE, order: propellerSdkV2.SortOrder.DESC }],
2250
+ ...companyIdRef.value && { companyId: companyIdRef.value },
2251
+ ...userId !== void 0 && { userId },
2252
+ ...orderlistScope
2253
+ };
2254
+ const priceCalculateProductInput = {
2255
+ taxZone,
2256
+ ...companyIdRef.value && { companyId: companyIdRef.value },
2257
+ ...contactId !== void 0 && { contactId },
2258
+ ...customerId !== void 0 && { customerId }
2234
2259
  };
2235
2260
  const variables = {
2236
- input,
2261
+ categoryId: catId,
2237
2262
  language: lang,
2263
+ categoryProductSearchInput,
2264
+ priceCalculateProductInput,
2265
+ imageSearchFilters: configuration?.imageSearchFiltersGrid,
2238
2266
  imageVariantFilters: configuration?.imageVariantFiltersMedium
2239
2267
  };
2240
- const result = await service.getProducts(variables);
2241
- searchResults.value = result?.items ?? [];
2242
- searchItemsFound.value = result?.itemsFound ?? searchResults.value.length;
2268
+ const response = await service.getCategory(variables);
2269
+ const productsResponse = response?.products;
2270
+ searchResults.value = productsResponse?.items ?? [];
2271
+ searchItemsFound.value = productsResponse?.itemsFound ?? searchResults.value.length;
2243
2272
  } catch {
2244
2273
  searchResults.value = [];
2245
2274
  searchItemsFound.value = 0;
@@ -19937,7 +19966,7 @@ const _hoisted_11$1 = {
19937
19966
  class: "propeller-search-bar__result-sku text-sm text-muted-foreground"
19938
19967
  };
19939
19968
  const _hoisted_12$1 = {
19940
- key: 1,
19969
+ key: 2,
19941
19970
  class: "propeller-search-bar__result-price text-sm font-semibold text-foreground flex-shrink-0 text-right"
19942
19971
  };
19943
19972
  const _hoisted_13$1 = { class: "propeller-search-bar__result-price-value" };
@@ -19964,6 +19993,7 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
19964
19993
  onViewAllClick: { type: Function },
19965
19994
  getResultHref: { type: Function },
19966
19995
  getViewAllHref: { type: Function },
19996
+ showPrice: { type: Boolean },
19967
19997
  formatPrice: { type: Function },
19968
19998
  labels: {},
19969
19999
  includeTax: { type: Boolean },
@@ -20196,7 +20226,10 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
20196
20226
  vue.createElementVNode("div", _hoisted_10$1, vue.toDisplayString(result.name), 1),
20197
20227
  result.sku ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_11$1, "SKU: " + vue.toDisplayString(result.sku), 1)) : vue.createCommentVNode("", true)
20198
20228
  ]),
20199
- result.price !== void 0 && result.price !== null ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_12$1, [
20229
+ _ctx.$slots.price ? vue.renderSlot(_ctx.$slots, "price", {
20230
+ key: 1,
20231
+ result
20232
+ }) : __props.showPrice !== false && result.price !== void 0 && result.price !== null ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_12$1, [
20200
20233
  vue.createElementVNode("span", _hoisted_13$1, vue.toDisplayString(formatItemPrice(leadingPrice(result))), 1),
20201
20234
  vue.createElementVNode("span", _hoisted_14$1, vue.toDisplayString(priceTaxLabel()), 1)
20202
20235
  ])) : vue.createCommentVNode("", true)