@propeller-commerce/propeller-v2-react-ui 0.9.0 → 0.10.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,30 @@ 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.10.1] - 2026-07-30
12
+
13
+ ### Fixed
14
+
15
+ - **`<SearchBar>` autosuggest ignored orderlist scoping.** The component
16
+ resolves `user` like every other infra prop but never passed it to
17
+ `useProductSearch`, and the backend drives orderlist scoping off the user id —
18
+ so `orderlistIds` alone had no effect on the autosuggest query. The dropdown
19
+ returned the whole catalogue while the grid below it, which does pass `user`,
20
+ showed only the contract's products. Forwarding `user` makes the two agree.
21
+
22
+ ## [0.10.0] - 2026-07-29
23
+
24
+ ### Added
25
+
26
+ - **Magic-token authentication in `useAuth`.** `magicLogin(token)` exchanges a
27
+ backend-issued magic token for a session (via
28
+ `MagicTokenService.magicTokenLogin`), sets the in-memory Bearer header — never
29
+ `setAccessToken` — and loads the viewer, mirroring `login()`. This is the
30
+ passwordless / punchout deep-link handoff. `createMagicToken(input)` issues a
31
+ magic token for a contact/customer (`MagicTokenCreateInput`, authenticated).
32
+ Both return the standard `Result` and are exposed on `UseAuthReturn`. No new
33
+ runtime dependency — the SDK's `MagicTokenService` ships in 0.14.0.
34
+
11
35
  ## [0.9.0] - 2026-07-29
12
36
 
13
37
  ### Changed
package/dist/index.cjs CHANGED
@@ -307,6 +307,66 @@ function useAuth(options) {
307
307
  setLoading(false);
308
308
  }
309
309
  }, [graphqlClient, language, onAuthHeaderUpdate, configuration]);
310
+ const magicLogin = React6.useCallback(async (token) => {
311
+ setLoading(true);
312
+ setError(null);
313
+ try {
314
+ const loginResult = await new propellerSdkV2.MagicTokenService(graphqlClient).magicTokenLogin(token);
315
+ const session = loginResult?.session;
316
+ const accessToken = session?.accessToken;
317
+ const refreshToken = session?.refreshToken;
318
+ const expiresAt = session?.expirationTime;
319
+ if (accessToken) {
320
+ const cfg = graphqlClient.getConfig();
321
+ graphqlClient.updateConfig({
322
+ headers: { ...cfg.headers, Authorization: `Bearer ${accessToken}` }
323
+ });
324
+ onAuthHeaderUpdate?.(accessToken);
325
+ }
326
+ const userService = propellerV2CoreUi.createServices(graphqlClient).user;
327
+ const viewerInput = {
328
+ ...configuration?.contactTrackAttributes?.length && {
329
+ contactAttributesInput: { attributeDescription: { names: configuration.contactTrackAttributes } }
330
+ },
331
+ ...configuration?.customerTrackAttributes?.length && {
332
+ customerAttributesInput: { attributeDescription: { names: configuration.customerTrackAttributes } }
333
+ },
334
+ ...configuration?.companyTrackAttributes?.length && {
335
+ companyAttributesInput: { attributeDescription: { names: configuration.companyTrackAttributes } }
336
+ },
337
+ // See isViewerSearchInput — an empty array `[]` is truthy but 400s the viewer.
338
+ ...isViewerSearchInput(configuration?.contactPAConfigInput) && {
339
+ contactPAConfigInput: configuration.contactPAConfigInput
340
+ },
341
+ ...isViewerSearchInput(configuration?.contactCompaniesSearchInput) && {
342
+ contactCompaniesSearchInput: configuration.contactCompaniesSearchInput
343
+ }
344
+ };
345
+ const viewer = await userService.getViewer(viewerInput);
346
+ const user = viewer;
347
+ return propellerV2CoreUi.ok({ user, accessToken, refreshToken, expiresAt });
348
+ } catch (e) {
349
+ const msg = e instanceof Error ? e.message : "Magic-token login failed";
350
+ setError(msg);
351
+ return propellerV2CoreUi.err(msg);
352
+ } finally {
353
+ setLoading(false);
354
+ }
355
+ }, [graphqlClient, onAuthHeaderUpdate, configuration]);
356
+ const createMagicToken = React6.useCallback(async (input) => {
357
+ setLoading(true);
358
+ setError(null);
359
+ try {
360
+ const token = await new propellerSdkV2.MagicTokenService(graphqlClient).createMagicToken(input);
361
+ return propellerV2CoreUi.ok(token);
362
+ } catch (e) {
363
+ const msg = e instanceof Error ? e.message : "Failed to create magic token";
364
+ setError(msg);
365
+ return propellerV2CoreUi.err(msg);
366
+ } finally {
367
+ setLoading(false);
368
+ }
369
+ }, [graphqlClient]);
310
370
  const registerContact = React6.useCallback(async (input, preferredLanguage = language, autoLogin = true) => {
311
371
  setLoading(true);
312
372
  setError(null);
@@ -553,7 +613,7 @@ function useAuth(options) {
553
613
  setLoading(false);
554
614
  }
555
615
  }, [graphqlClient]);
556
- return { loading, error, login, registerContact, registerCustomer, forgotPassword };
616
+ return { loading, error, login, magicLogin, createMagicToken, registerContact, registerCustomer, forgotPassword };
557
617
  }
558
618
  async function initCart(config) {
559
619
  const {
@@ -18400,6 +18460,12 @@ function SearchBar(rawProps) {
18400
18460
  graphqlClient: props.graphqlClient,
18401
18461
  language: props.language,
18402
18462
  configuration: props.configuration || {},
18463
+ // `user` supplies userId/contactId/customerId to the autosuggest query.
18464
+ // Without it the dropdown's results diverge from the grid's: orderlist
18465
+ // scoping is driven by userId, so `orderlistIds` alone is ignored by the
18466
+ // backend and the dropdown shows the whole catalogue while the grid below
18467
+ // shows only the contract's products.
18468
+ user: props.user,
18403
18469
  companyId: props.companyId,
18404
18470
  orderlistIds: props.orderlistIds,
18405
18471
  applyOrderlists: props.applyOrderlists