@swishapp/react 0.130.0 → 0.131.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/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { ApiError, ApiResponse, EditItemListsSuccessResponse, EditItemVariantSuccessResponse, EventName, Intent, IntentResponse, IntentToData, Item, PageInfo, PaginatedApiResponse, SaveItemSuccessResponse, SwishApp, SwishOptionsInput, UnsaveItemSuccessResponse } from "@swishapp/sdk";
1
+ import { ApiError, ApiResponse, EditItemListsSuccessResponse, EditItemVariantSuccessResponse, EventName, Intent, IntentResponse, IntentToData, Item, ItemMatch, PageInfo, PaginatedApiResponse, SaveItemSuccessResponse, SwishApp, SwishOptionsInput, UnsaveItemSuccessResponse } from "@swishapp/sdk";
2
2
  import { ReactNode } from "react";
3
3
  import * as react_jsx_runtime0 from "react/jsx-runtime";
4
- import * as _swishapp_api_client0 from "@swishapp/api-client";
4
+ import * as _swishapp_api_client3 from "@swishapp/api-client";
5
5
  export * from "@swishapp/sdk";
6
6
 
7
7
  //#region src/types.d.ts
@@ -57,8 +57,8 @@ declare const useSwishIntent: <I extends Intent = Intent>(intent: I, ...args: In
57
57
  //#region src/hooks/use-swish-lists.d.ts
58
58
  declare const useSwishLists: () => {
59
59
  loading: boolean;
60
- lists: _swishapp_api_client0.ListDetail[] | null;
61
- error: _swishapp_api_client0.ApiError | null;
60
+ lists: _swishapp_api_client3.ListDetail[] | null;
61
+ error: _swishapp_api_client3.ApiError | null;
62
62
  reset: () => void;
63
63
  };
64
64
  //#endregion
@@ -73,8 +73,8 @@ declare const useSwishItems: ({
73
73
  }?: UseSwishItemsOptions) => {
74
74
  loading: boolean;
75
75
  data: Item[];
76
- pageInfo: _swishapp_api_client0.PageInfo | null;
77
- error: _swishapp_api_client0.ApiError | null;
76
+ pageInfo: _swishapp_api_client3.PageInfo | null;
77
+ error: _swishapp_api_client3.ApiError | null;
78
78
  reset: () => void;
79
79
  hasMore: boolean;
80
80
  loadMore: () => void;
@@ -85,6 +85,13 @@ interface UseSwishItemProps {
85
85
  productId: string | number;
86
86
  variantId?: string | number;
87
87
  itemId?: string;
88
+ /**
89
+ * How to interpret saved state when `variantId` is set:
90
+ * - `"variant"`: only saved if the variant matches.
91
+ * - `"product"`: saved if any variant of the product is saved.
92
+ * - `"auto"` (default): variant-match when `variantId` is set, product-match otherwise.
93
+ */
94
+ match?: ItemMatch;
88
95
  onSave?: (data: SaveItemSuccessResponse["data"]) => void;
89
96
  onUnsave?: (data: UnsaveItemSuccessResponse["data"]) => void;
90
97
  onListsUpdate?: (data: EditItemListsSuccessResponse["data"]) => void;
@@ -94,6 +101,7 @@ declare const useSwishItem: ({
94
101
  productId,
95
102
  variantId,
96
103
  itemId,
104
+ match,
97
105
  onSave,
98
106
  onUnsave,
99
107
  onListsUpdate,
@@ -101,7 +109,11 @@ declare const useSwishItem: ({
101
109
  }: UseSwishItemProps) => {
102
110
  saved: boolean;
103
111
  loading: boolean;
104
- error: _swishapp_api_client0.ApiError | null;
112
+ saving: boolean;
113
+ unsaving: boolean;
114
+ error: _swishapp_api_client3.ApiError | null;
115
+ savedItemId: string | null;
116
+ savedItemIds: string[];
105
117
  save: () => Promise<void>;
106
118
  unsave: () => Promise<void>;
107
119
  updateLists: () => Promise<void>;
@@ -113,7 +125,7 @@ declare const useSwishItem: ({
113
125
  declare const useSwishItemCount: () => {
114
126
  count: number;
115
127
  loading: boolean;
116
- error: _swishapp_api_client0.ApiError | null;
128
+ error: _swishapp_api_client3.ApiError | null;
117
129
  };
118
130
  //#endregion
119
131
  export { SwishContextValue, SwishProvider, type SwishProviderProps, useSwish, useSwishIntent, useSwishItem, useSwishItemCount, useSwishItems, useSwishLists, useSwishQuery };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/context.tsx","../src/hooks/use-swish.ts","../src/hooks/use-swish-query.ts","../src/hooks/use-swish-intent.ts","../src/hooks/use-swish-lists.ts","../src/hooks/use-swish-items.ts","../src/hooks/use-swish-item.ts","../src/hooks/use-swish-item-count.ts"],"sourcesContent":[],"mappings":";;;;;;;UAEiB,iBAAA;SACR;;SAEA;;;;UCKQ,kBAAA;YACL;WACD;;EDVM,CAAA;;iBCaD,aAAA;;;;;;GAGb,qBAAkB,kBAAA,CAAA,GAAA,CAAA;;;iBCdL,QAAA,CAAA,GAAY;;;KCOhB,yCACH,6BACK,eACT,QAAQ;KAeR,YAAY;;;cAEJ,kCACO,mBAAmB,8CAG9B,QAAQ,WAAW;cAEZ;;EHnCC,OAAA,CAAA,EAAA,OAAA,GGqCO,SHrCU,EACzB;;;;ECOQ,KAAA,UAAA,GAAA,IAAkB;EAKnB,OAAA,EAAA,OAAa;EAC3B,KAAA,EAAA,GAAA,GAAA,IAAA;EACW,OAAA,EAAA,GAAA,GAAA,IAAA;EACV,UAAA,EAAA,OAAA;CAAkB;;;cGdR,2BAA4B,SAAS,gBACxC,YACC,aAAa,sCAAsC,aAAa;gBAUpC,QAAQ,eAAe;;;;;cCbjD;;SAyBZ,qBAAA,CAAA,UAAA;SAAA,qBAAA,CAAA,QAAA;;;;;UCxBgB,oBAAA;;;;cAKJ;;;IAGV;;;ENVc,QAAA,mCAGH,IAAA;;;;ECKG,QAAA,EAAA,GAAA,GAAA,IAAA;AAKjB,CAAA;;;UMJU,iBAAA;;;;kBAIQ;oBACE;yBACK;EPfR,eAAA,CAAA,EAAA,CAAA,IAAiB,EOgBP,8BPbb,CAAA,MAAA,CAAA,EAAA,GAAA,IAAA;;cOgBD;;;;;;;;GAQV;;ENnBc,OAAA,EAAA,OAAA;EAKD,KAAA,EMcI,qBAAA,CAAA,QAAA,GNdS,IAAA;EAC3B,IAAA,EAAA,GAAA,UAAA,CAAA,IAAA,CAAA;EACW,MAAA,EAAA,GAAA,UAAA,CAAA,IAAA,CAAA;EACV,WAAA,EAAA,GAAA,UAAA,CAAA,IAAA,CAAA;EAAkB,aAAA,EAAA,GAAA,UAAA,CAAA,IAAA,CAAA;EAAA,MAAA,EAAA,GAAA,UAAA,CAAA,IAAA,CAAA;;;;cOfR;;;SAYZ,qBAAA,CAAA,QAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/context.tsx","../src/hooks/use-swish.ts","../src/hooks/use-swish-query.ts","../src/hooks/use-swish-intent.ts","../src/hooks/use-swish-lists.ts","../src/hooks/use-swish-items.ts","../src/hooks/use-swish-item.ts","../src/hooks/use-swish-item-count.ts"],"sourcesContent":[],"mappings":";;;;;;;UAEiB,iBAAA;SACR;;SAEA;;;;UCKQ,kBAAA;YACL;WACD;;EDVM,CAAA;;iBCaD,aAAA;;;;;;GAGb,qBAAkB,kBAAA,CAAA,GAAA,CAAA;;;iBCdL,QAAA,CAAA,GAAY;;;KCOhB,yCACH,6BACK,eACT,QAAQ;KAeR,YAAY;;;cAEJ,kCACO,mBAAmB,8CAG9B,QAAQ,WAAW;cAEZ;;EHnCC,OAAA,CAAA,EAAA,OAAA,GGqCO,SHrCU,EACzB;;;;ECOQ,KAAA,UAAA,GAAA,IAAkB;EAKnB,OAAA,EAAA,OAAa;EAC3B,KAAA,EAAA,GAAA,GAAA,IAAA;EACW,OAAA,EAAA,GAAA,GAAA,IAAA;EACV,UAAA,EAAA,OAAA;CAAkB;;;cGdR,2BAA4B,SAAS,gBACxC,YACC,aAAa,sCAAsC,aAAa;gBAUpC,QAAQ,eAAe;;;;;cCbjD;;SAyBZ,qBAAA,CAAA,UAAA;SAAA,qBAAA,CAAA,QAAA;;;;;UCxBgB,oBAAA;;;;cAKJ;;;IAGV;;;ENVc,QAAA,mCAGH,IAAA;;;;ECKG,QAAA,EAAA,GAAA,GAAA,IAAA;AAKjB,CAAA;;;UMAU,iBAAA;;;;;;;APbV;;;UOuBU;ENfO,MAAA,CAAA,EAAA,CAAA,IAAA,EMgBC,uBNfN,CAAA,MACD,CAAA,EAAA,GAAA,IAAA;EAGK,QAAA,CAAA,EAAA,CAAA,IAAa,EMYT,yBNZS,CAAA,MAAA,CAAA,EAAA,GAAA,IAAA;EAC3B,aAAA,CAAA,EAAA,CAAA,IAAA,EMYuB,4BNZvB,CAAA,MAAA,CAAA,EAAA,GAAA,IAAA;EACW,eAAA,CAAA,EAAA,CAAA,IAAA,EMYc,8BNZd,CAAA,MAAA,CAAA,EAAA,GAAA,IAAA;;AACQ,cM6BR,YN7BQ,EAAA,CAAA;EAAA,SAAA;EAAA,SAAA;EAAA,MAAA;EAAA,KAAA;EAAA,MAAA;EAAA,QAAA;EAAA,aAAA;EAAA;AAAA,CAAA,EMsClB,iBNtCkB,EAAA,GAAA;EAAA,KAAA,EAAA,OAAA;;;;ECdL,KAAA,EKoDI,qBAAA,CAAA,QAAA,GLpDgB,IAAA;;;;ECOxB,MAAA,EAAA,GAAO,UAAA,CAAA,IAAA,CAAA;EACV,WAAA,EAAA,GAAA,UAAA,CAAA,IAAA,CAAA;EACK,aAAA,EAAA,GAAA,UAAA,CAAA,IAAA,CAAA;EACD,MAAA,EAAA,GAAA,UAAA,CAAA,IAAA,CAAA;CAAR;;;cKXQ;;;SAYZ,qBAAA,CAAA,QAAA"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { swishSdkUrl } from "@swishapp/sdk";
2
- import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
2
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
 
5
5
  //#region src/context.tsx
@@ -227,122 +227,70 @@ const useSwishItems = ({ listId, limit = 24 } = {}) => {
227
227
  ]);
228
228
  };
229
229
 
230
- //#endregion
231
- //#region src/utils/shopify-utils.ts
232
- const gidToId = (gid) => {
233
- return gid?.split("/").pop();
234
- };
235
-
236
230
  //#endregion
237
231
  //#region src/hooks/use-swish-item.ts
238
- const useSwishItem = ({ productId, variantId, itemId, onSave, onUnsave, onListsUpdate, onVariantUpdate }) => {
239
- const [savedItemId, setSavedItemId] = useState(itemId ?? null);
240
- const onUnsaveRef = useRef(onUnsave);
241
- const onSaveRef = useRef(onSave);
242
- const onListsUpdateRef = useRef(onListsUpdate);
243
- const onVariantUpdateRef = useRef(onVariantUpdate);
244
- onUnsaveRef.current = onUnsave;
245
- onSaveRef.current = onSave;
246
- onListsUpdateRef.current = onListsUpdate;
247
- onVariantUpdateRef.current = onVariantUpdate;
248
- const { invoke: saveItem, pending: creatingItem } = useSwishIntent("save:item", {
249
- productId,
250
- variantId
251
- });
252
- const { invoke: editItemLists } = useSwishIntent("edit:item-lists", { itemId: savedItemId ?? "" });
253
- const { invoke: editItemVariant } = useSwishIntent("edit:item-variant", {
254
- itemId: savedItemId ?? "",
232
+ const NOT_READY_SNAPSHOT = {
233
+ status: "unsaved",
234
+ saved: false,
235
+ saving: false,
236
+ unsaving: false,
237
+ loading: true,
238
+ submitting: false,
239
+ savedItemId: null,
240
+ savedItemIds: [],
241
+ error: null
242
+ };
243
+ const noop = () => {};
244
+ const noopAsync = async () => {};
245
+ const useSwishItem = ({ productId, variantId, itemId, match, onSave, onUnsave, onListsUpdate, onVariantUpdate }) => {
246
+ const swish = useSwish();
247
+ const state = useMemo(() => {
248
+ if (!swish) return null;
249
+ const context = swish.state.itemContextFromIds({
250
+ productId,
251
+ variantId,
252
+ itemId
253
+ });
254
+ return swish.state.itemState(context);
255
+ }, [
256
+ swish,
255
257
  productId,
256
- variantId
257
- });
258
- const { invoke: unsaveItem } = useSwishIntent("unsave:item", { itemId: savedItemId ?? "" });
259
- const { data: savedItems, loading: savedItemsLoading, error: savedItemsError } = useSwishQuery((api, variables) => api.items.list(variables), {
260
- refetch: [
261
- "item-create",
262
- "item-update",
263
- "item-delete"
264
- ],
265
- variables: {
266
- limit: 1,
267
- query: useMemo(() => {
268
- if (variantId) return `variant:${gidToId(variantId.toString())}`;
269
- return `product:${gidToId(productId.toString())}`;
270
- }, [productId, variantId])
271
- },
272
- skip: Boolean(itemId) || !productId
258
+ variantId,
259
+ itemId
260
+ ]);
261
+ if (state) state.setOptions({
262
+ onSave,
263
+ onUnsave,
264
+ onListsUpdate,
265
+ onVariantUpdate,
266
+ match
273
267
  });
274
- const saved = useMemo(() => Boolean(savedItemId), [savedItemId]);
275
- const error = useMemo(() => savedItemsError, [savedItemsError]);
276
- const loading = useMemo(() => savedItemsLoading || creatingItem, [savedItemsLoading, creatingItem]);
277
268
  useEffect(() => {
278
- if (itemId) return;
279
- if (savedItems?.[0]) setSavedItemId(savedItems[0].id);
280
- else setSavedItemId(null);
281
- }, [savedItems, itemId]);
282
- const unsave = useCallback(async () => {
283
- const response = await unsaveItem();
284
- if (response.code === "ok") {
285
- const data = response.data;
286
- setSavedItemId(null);
287
- onUnsaveRef.current?.(data);
288
- }
289
- }, [unsaveItem]);
290
- const updateLists = useCallback(async () => {
291
- const response = await editItemLists();
292
- if (response.code !== "ok") return;
293
- if (response.intent === "unsave:item") {
294
- const data = response.data;
295
- setSavedItemId(null);
296
- onUnsaveRef.current?.(data);
297
- } else {
298
- const data = response.data;
299
- onListsUpdateRef.current?.(data);
300
- }
301
- }, [editItemLists]);
302
- const updateVariant = useCallback(async () => {
303
- const response = await editItemVariant();
304
- if (response.code === "ok") {
305
- const data = response.data;
306
- onVariantUpdateRef.current?.(data);
307
- }
308
- }, [editItemVariant]);
309
- const save = useCallback(async () => {
310
- const response = await saveItem();
311
- if (response.code === "ok") {
312
- const data = response.data;
313
- setSavedItemId(data.item.id);
314
- onSaveRef.current?.(data);
315
- }
316
- }, [saveItem]);
317
- const toggle = useCallback(async () => {
318
- if (saved) await unsave();
319
- else await save();
320
- }, [
321
- saved,
322
- save,
323
- unsave
324
- ]);
269
+ if (!state) return;
270
+ return () => state.dispose();
271
+ }, [state]);
272
+ const subscribe = useCallback((notify) => {
273
+ if (!state) return noop;
274
+ return state.subscribe(() => notify());
275
+ }, [state]);
276
+ const getSnapshot = useCallback(() => state ? state.peek() : NOT_READY_SNAPSHOT, [state]);
277
+ const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
325
278
  return useMemo(() => {
326
279
  return {
327
- saved,
328
- loading,
329
- error,
330
- save,
331
- unsave,
332
- updateLists,
333
- updateVariant,
334
- toggle
280
+ saved: snapshot.saved,
281
+ loading: snapshot.loading,
282
+ saving: snapshot.saving,
283
+ unsaving: snapshot.unsaving,
284
+ error: snapshot.error,
285
+ savedItemId: snapshot.savedItemId,
286
+ savedItemIds: snapshot.savedItemIds,
287
+ save: state?.save ?? noopAsync,
288
+ unsave: state?.unsave ?? noopAsync,
289
+ updateLists: state?.updateLists ?? noopAsync,
290
+ updateVariant: state?.updateVariant ?? noopAsync,
291
+ toggle: state?.toggle ?? noopAsync
335
292
  };
336
- }, [
337
- saved,
338
- loading,
339
- error,
340
- save,
341
- unsave,
342
- updateLists,
343
- updateVariant,
344
- toggle
345
- ]);
293
+ }, [snapshot, state]);
346
294
  };
347
295
 
348
296
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["defaultSwishSdkUrl","swishSdkUrl","swish","value: SwishContextValue","defaultRefetchEvents: EventName[]","tokenUpdateEvent: EventName","error"],"sources":["../src/context.tsx","../src/hooks/use-swish.ts","../src/hooks/use-swish-query.ts","../src/hooks/use-swish-intent.ts","../src/hooks/use-swish-lists.ts","../src/hooks/use-swish-items.ts","../src/utils/shopify-utils.ts","../src/hooks/use-swish-item.ts","../src/hooks/use-swish-item-count.ts"],"sourcesContent":["import {\n type SwishApp,\n type SwishOptionsInput,\n swishSdkUrl as defaultSwishSdkUrl,\n} from \"@swishapp/sdk\";\nimport { createContext, ReactNode, useEffect, useRef, useState } from \"react\";\nimport type { SwishContextValue } from \"./types\";\n\nexport const SwishContext = createContext<SwishContextValue | null>(null);\n\nexport interface SwishProviderProps {\n children: ReactNode;\n options: SwishOptionsInput & { swishSdkUrl?: string };\n}\n\nexport function SwishProvider({\n children,\n options: { swishSdkUrl = defaultSwishSdkUrl, ...options },\n}: SwishProviderProps) {\n const [swish, setSwish] = useState<SwishApp | null>(null);\n const [isLoading, setIsLoading] = useState(typeof window !== \"undefined\");\n const [error, setError] = useState<Error | null>(null);\n const optionsRef = useRef<SwishOptionsInput>(options);\n\n useEffect(() => {\n if (typeof window === \"undefined\") {\n return;\n }\n\n let cancelled = false;\n\n const initializeSdk = async () => {\n try {\n setIsLoading(true);\n setError(null);\n\n const { createSwish } = await import(\n /* webpackIgnore: true */\n swishSdkUrl\n );\n const swish = await createSwish(optionsRef.current);\n\n if (!cancelled) {\n setSwish(swish);\n }\n } catch (err) {\n console.error(\"Failed to initialize Swish\", err);\n if (!cancelled) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to initialize Swish\")\n );\n }\n } finally {\n if (!cancelled) {\n setIsLoading(false);\n }\n }\n };\n\n initializeSdk();\n\n return () => {\n cancelled = true;\n };\n }, []);\n\n const value: SwishContextValue = {\n swish,\n isLoading,\n error,\n };\n\n return (\n <SwishContext.Provider value={value}>{children}</SwishContext.Provider>\n );\n}\n","import type { SwishApp } from \"@swishapp/sdk\";\nimport { useContext } from \"react\";\nimport { SwishContext } from \"../context\";\n\nexport function useSwish(): SwishApp | null {\n const context = useContext(SwishContext);\n\n if (typeof window !== \"undefined\" && window.swish) {\n return window.swish;\n }\n\n if (!context) {\n throw new Error(\"useSwish must be used within a SwishProvider\");\n }\n\n return context.swish;\n}\n","import type {\n ApiError,\n ApiResponse,\n EventName,\n PageInfo,\n PaginatedApiResponse,\n SwishApp,\n} from \"@swishapp/sdk\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useSwish } from \"./use-swish\";\n\nexport type FetchFn<TResponse, TVariables> = (\n swish: SwishApp[\"api\"],\n variables?: TVariables,\n) => Promise<TResponse>;\n\nconst defaultRefetchEvents: EventName[] = [\n \"item-create\",\n \"item-update\",\n \"item-delete\",\n \"item-lists-update\",\n \"list-create\",\n \"list-update\",\n \"list-delete\",\n \"token-update\",\n];\n\nconst tokenUpdateEvent: EventName = \"token-update\";\n\ntype DataOf<T> = T extends { data: infer D } ? D : never;\n\nexport const useSwishQuery = <\n TResponse extends ApiResponse<any> | PaginatedApiResponse<any>,\n TVariables,\n>(\n fetch: FetchFn<TResponse, TVariables>,\n options?: {\n variables?: TVariables;\n skip?: boolean;\n refetch?: boolean | EventName[];\n },\n) => {\n const swish = useSwish();\n const fetchRef = useRef<FetchFn<TResponse, TVariables>>(fetch);\n\n const [data, setData] = useState<DataOf<TResponse> | null>(null);\n const [pageInfo, setPageInfo] = useState<PageInfo | null>(null);\n const [error, setError] = useState<ApiError | null>(null);\n const [loading, setLoading] = useState(!options?.skip);\n const [initialized, setInitialized] = useState(false);\n const refetching = loading && initialized;\n\n const reset = useCallback(() => {\n setData(null);\n setPageInfo(null);\n setError(null);\n setLoading(false);\n setInitialized(false);\n }, []);\n\n const deps = options?.variables ? Object.values(options.variables) : [];\n const skip = !!options?.skip;\n const refetchEvents =\n options?.refetch === true ? defaultRefetchEvents\n : Array.isArray(options?.refetch) ? [...options.refetch, tokenUpdateEvent]\n : [];\n\n const refetchEventsRef = useRef(refetchEvents);\n refetchEventsRef.current = refetchEvents;\n\n // Stable string key so the effect re-subscribes only when events actually change\n const refetchEventsKey = refetchEvents.join(\",\");\n\n const executeFetch = useCallback(() => {\n if (!swish || skip) {\n return;\n }\n\n setLoading(true);\n\n fetchRef\n .current(swish.api, options?.variables)\n .then((response) => {\n setError(\"error\" in response ? response.error : null);\n setData(\"data\" in response ? response.data : null);\n setPageInfo(\"pageInfo\" in response ? response.pageInfo : null);\n })\n .catch((error) => setError(error))\n .finally(() => {\n setLoading(false);\n setInitialized(true);\n });\n }, [swish, skip, ...deps]);\n\n const refetch = useCallback(() => {\n executeFetch();\n }, [executeFetch]);\n\n useEffect(() => {\n if (!swish) {\n return;\n }\n\n executeFetch();\n\n const unsubscribe = swish.events.subscribe(refetchEventsRef.current, () => {\n refetch();\n });\n\n return () => unsubscribe();\n }, [executeFetch, refetch, refetchEventsKey]);\n\n return useMemo(\n () => ({\n data,\n pageInfo,\n error,\n loading,\n reset,\n refetch,\n refetching,\n }),\n [data, pageInfo, error, loading, reset, refetch, refetching],\n );\n};\n","import type { Intent, IntentResponse, IntentToData } from \"@swishapp/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useSwish } from \"./use-swish\";\n\nexport const useSwishIntent = <I extends Intent = Intent>(\n intent: I,\n ...args: IntentToData<I> extends void ? [] | [undefined] : [IntentToData<I>]\n) => {\n const swish = useSwish();\n const [pending, setPending] = useState(false);\n const dataRef = useRef(args);\n\n useEffect(() => {\n dataRef.current = args;\n }, [args]);\n\n const invoke = useCallback(async (): Promise<IntentResponse<I>> => {\n if (!swish) {\n throw new Error(\"Swish SDK not initialized\");\n }\n\n setPending(true);\n try {\n const activity = await swish.intents.invoke(intent, ...dataRef.current);\n const response = await activity.complete;\n return response as IntentResponse<I>;\n } finally {\n setPending(false);\n }\n }, [swish]);\n\n return { invoke, pending };\n};\n","import { useMemo } from \"react\";\nimport { useSwishQuery } from \"./use-swish-query\";\n\nexport const useSwishLists = () => {\n const {\n data: lists,\n loading,\n error,\n reset,\n } = useSwishQuery((api) => api.lists.list(), {\n refetch: [\n \"item-lists-update\",\n \"item-delete\",\n \"list-create\",\n \"list-update\",\n \"list-delete\",\n ],\n });\n\n return useMemo(\n () => ({\n loading,\n lists,\n error,\n reset,\n }),\n [lists, loading, error, reset]\n );\n};\n","import type { Item } from \"@swishapp/sdk\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useSwishQuery } from \"./use-swish-query\";\n\nexport interface UseSwishItemsOptions {\n listId?: string;\n limit?: number;\n}\n\nexport const useSwishItems = ({\n listId,\n limit = 24,\n}: UseSwishItemsOptions = {}) => {\n const [nextPage, setNextPage] = useState<string | null>(null);\n const [data, setData] = useState<Item[]>([]);\n\n const {\n data: remoteData,\n pageInfo,\n loading,\n error,\n reset: resetRemoteData,\n } = useSwishQuery((api, variables) => api.items.list(variables), {\n variables: {\n page: nextPage ?? undefined,\n limit,\n listId,\n },\n refetch: false,\n });\n\n const reset = useCallback(() => {\n setData([]);\n setNextPage(null);\n resetRemoteData();\n }, [resetRemoteData]);\n\n useEffect(() => {\n if (remoteData) {\n setData((prev) => [...prev, ...remoteData]);\n }\n }, [remoteData]);\n\n const loadMore = useCallback(() => {\n if (pageInfo?.next) {\n setNextPage(pageInfo.next);\n }\n }, [pageInfo?.next]);\n\n return useMemo(\n () => ({\n loading,\n data,\n pageInfo,\n error,\n reset,\n hasMore: !!pageInfo?.next,\n loadMore,\n }),\n [data, pageInfo, loading, error, reset, loadMore]\n );\n};\n","export const gidToId = (gid: string) => {\n return gid?.split(\"/\").pop();\n};\n","import type {\n SaveItemSuccessResponse,\n UnsaveItemSuccessResponse,\n EditItemListsSuccessResponse,\n EditItemVariantSuccessResponse,\n} from \"@swishapp/sdk\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { gidToId } from \"../utils/shopify-utils\";\nimport { useSwishIntent } from \"./use-swish-intent\";\nimport { useSwishQuery } from \"./use-swish-query\";\n\ninterface UseSwishItemProps {\n productId: string | number;\n variantId?: string | number;\n itemId?: string;\n onSave?: (data: SaveItemSuccessResponse[\"data\"]) => void;\n onUnsave?: (data: UnsaveItemSuccessResponse[\"data\"]) => void;\n onListsUpdate?: (data: EditItemListsSuccessResponse[\"data\"]) => void;\n onVariantUpdate?: (data: EditItemVariantSuccessResponse[\"data\"]) => void;\n}\n\nexport const useSwishItem = ({\n productId,\n variantId,\n itemId,\n onSave,\n onUnsave,\n onListsUpdate,\n onVariantUpdate,\n}: UseSwishItemProps) => {\n const [savedItemId, setSavedItemId] = useState<string | null>(itemId ?? null);\n\n const onUnsaveRef =\n useRef<NonNullable<UseSwishItemProps[\"onUnsave\"]>>(onUnsave);\n const onSaveRef = useRef<NonNullable<UseSwishItemProps[\"onSave\"]>>(onSave);\n const onListsUpdateRef =\n useRef<NonNullable<UseSwishItemProps[\"onListsUpdate\"]>>(onListsUpdate);\n const onVariantUpdateRef =\n useRef<NonNullable<UseSwishItemProps[\"onVariantUpdate\"]>>(onVariantUpdate);\n\n onUnsaveRef.current = onUnsave;\n onSaveRef.current = onSave;\n onListsUpdateRef.current = onListsUpdate;\n onVariantUpdateRef.current = onVariantUpdate;\n\n const { invoke: saveItem, pending: creatingItem } = useSwishIntent(\n \"save:item\",\n {\n productId,\n variantId,\n }\n );\n\n const { invoke: editItemLists } = useSwishIntent(\"edit:item-lists\", {\n itemId: savedItemId ?? \"\",\n });\n\n const { invoke: editItemVariant } = useSwishIntent(\"edit:item-variant\", {\n itemId: savedItemId ?? \"\",\n productId,\n variantId,\n });\n\n const { invoke: unsaveItem } = useSwishIntent(\"unsave:item\", {\n itemId: savedItemId ?? \"\",\n });\n\n const query = useMemo(() => {\n if (variantId) {\n return `variant:${gidToId(variantId.toString())}`;\n }\n return `product:${gidToId(productId.toString())}`;\n }, [productId, variantId]);\n\n // Load saved items for the product or variant\n const {\n data: savedItems,\n loading: savedItemsLoading,\n error: savedItemsError,\n } = useSwishQuery((api, variables) => api.items.list(variables), {\n refetch: [\"item-create\", \"item-update\", \"item-delete\"],\n variables: {\n limit: 1,\n query,\n },\n skip: Boolean(itemId) || !productId,\n });\n\n const saved = useMemo(() => Boolean(savedItemId), [savedItemId]);\n const error = useMemo(() => savedItemsError, [savedItemsError]);\n const loading = useMemo(\n () => savedItemsLoading || creatingItem,\n [savedItemsLoading, creatingItem]\n );\n\n useEffect(() => {\n if (itemId) return;\n\n if (savedItems?.[0]) {\n setSavedItemId(savedItems[0].id);\n } else {\n setSavedItemId(null);\n }\n }, [savedItems, itemId]);\n\n const unsave = useCallback(async () => {\n const response = await unsaveItem();\n\n if (response.code === \"ok\") {\n const data = response.data;\n setSavedItemId(null);\n onUnsaveRef.current?.(data);\n }\n }, [unsaveItem]);\n\n const updateLists = useCallback(async () => {\n const response = await editItemLists();\n if (response.code !== \"ok\") {\n return;\n }\n if (response.intent === \"unsave:item\") {\n // Item was unsaved from list-select\n const data = response.data as UnsaveItemSuccessResponse[\"data\"];\n setSavedItemId(null);\n onUnsaveRef.current?.(data);\n } else {\n const data = response.data as EditItemListsSuccessResponse[\"data\"];\n onListsUpdateRef.current?.(data);\n }\n }, [editItemLists]);\n\n const updateVariant = useCallback(async () => {\n const response = await editItemVariant();\n if (response.code === \"ok\") {\n const data = response.data;\n onVariantUpdateRef.current?.(data);\n }\n }, [editItemVariant]);\n\n const save = useCallback(async () => {\n const response = await saveItem();\n\n if (response.code === \"ok\") {\n const data = response.data;\n setSavedItemId(data.item.id);\n onSaveRef.current?.(data);\n }\n }, [saveItem]);\n\n const toggle = useCallback(async () => {\n if (saved) {\n await unsave();\n } else {\n await save();\n }\n }, [saved, save, unsave]);\n\n return useMemo(() => {\n return {\n saved,\n loading,\n error,\n save,\n unsave,\n updateLists,\n updateVariant,\n toggle,\n };\n }, [saved, loading, error, save, unsave, updateLists, updateVariant, toggle]);\n};\n","import { useMemo } from \"react\";\nimport { useSwishQuery } from \"./use-swish-query\";\n\nexport const useSwishItemCount = () => {\n const { data, loading, error } = useSwishQuery((api) => api.items.count(), {\n refetch: [\"item-create\", \"item-delete\"],\n });\n\n return useMemo(() => {\n return {\n count: data?.count ?? 0,\n loading,\n error,\n };\n }, [data, loading, error]);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["defaultSwishSdkUrl","swishSdkUrl","swish","value: SwishContextValue","defaultRefetchEvents: EventName[]","tokenUpdateEvent: EventName","error"],"sources":["../src/context.tsx","../src/hooks/use-swish.ts","../src/hooks/use-swish-query.ts","../src/hooks/use-swish-intent.ts","../src/hooks/use-swish-lists.ts","../src/hooks/use-swish-items.ts","../src/hooks/use-swish-item.ts","../src/hooks/use-swish-item-count.ts"],"sourcesContent":["import {\n type SwishApp,\n type SwishOptionsInput,\n swishSdkUrl as defaultSwishSdkUrl,\n} from \"@swishapp/sdk\";\nimport { createContext, ReactNode, useEffect, useRef, useState } from \"react\";\nimport type { SwishContextValue } from \"./types\";\n\nexport const SwishContext = createContext<SwishContextValue | null>(null);\n\nexport interface SwishProviderProps {\n children: ReactNode;\n options: SwishOptionsInput & { swishSdkUrl?: string };\n}\n\nexport function SwishProvider({\n children,\n options: { swishSdkUrl = defaultSwishSdkUrl, ...options },\n}: SwishProviderProps) {\n const [swish, setSwish] = useState<SwishApp | null>(null);\n const [isLoading, setIsLoading] = useState(typeof window !== \"undefined\");\n const [error, setError] = useState<Error | null>(null);\n const optionsRef = useRef<SwishOptionsInput>(options);\n\n useEffect(() => {\n if (typeof window === \"undefined\") {\n return;\n }\n\n let cancelled = false;\n\n const initializeSdk = async () => {\n try {\n setIsLoading(true);\n setError(null);\n\n const { createSwish } = await import(\n /* webpackIgnore: true */\n swishSdkUrl\n );\n const swish = await createSwish(optionsRef.current);\n\n if (!cancelled) {\n setSwish(swish);\n }\n } catch (err) {\n console.error(\"Failed to initialize Swish\", err);\n if (!cancelled) {\n setError(\n err instanceof Error ? err : new Error(\"Failed to initialize Swish\")\n );\n }\n } finally {\n if (!cancelled) {\n setIsLoading(false);\n }\n }\n };\n\n initializeSdk();\n\n return () => {\n cancelled = true;\n };\n }, []);\n\n const value: SwishContextValue = {\n swish,\n isLoading,\n error,\n };\n\n return (\n <SwishContext.Provider value={value}>{children}</SwishContext.Provider>\n );\n}\n","import type { SwishApp } from \"@swishapp/sdk\";\nimport { useContext } from \"react\";\nimport { SwishContext } from \"../context\";\n\nexport function useSwish(): SwishApp | null {\n const context = useContext(SwishContext);\n\n if (typeof window !== \"undefined\" && window.swish) {\n return window.swish;\n }\n\n if (!context) {\n throw new Error(\"useSwish must be used within a SwishProvider\");\n }\n\n return context.swish;\n}\n","import type {\n ApiError,\n ApiResponse,\n EventName,\n PageInfo,\n PaginatedApiResponse,\n SwishApp,\n} from \"@swishapp/sdk\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useSwish } from \"./use-swish\";\n\nexport type FetchFn<TResponse, TVariables> = (\n swish: SwishApp[\"api\"],\n variables?: TVariables,\n) => Promise<TResponse>;\n\nconst defaultRefetchEvents: EventName[] = [\n \"item-create\",\n \"item-update\",\n \"item-delete\",\n \"item-lists-update\",\n \"list-create\",\n \"list-update\",\n \"list-delete\",\n \"token-update\",\n];\n\nconst tokenUpdateEvent: EventName = \"token-update\";\n\ntype DataOf<T> = T extends { data: infer D } ? D : never;\n\nexport const useSwishQuery = <\n TResponse extends ApiResponse<any> | PaginatedApiResponse<any>,\n TVariables,\n>(\n fetch: FetchFn<TResponse, TVariables>,\n options?: {\n variables?: TVariables;\n skip?: boolean;\n refetch?: boolean | EventName[];\n },\n) => {\n const swish = useSwish();\n const fetchRef = useRef<FetchFn<TResponse, TVariables>>(fetch);\n\n const [data, setData] = useState<DataOf<TResponse> | null>(null);\n const [pageInfo, setPageInfo] = useState<PageInfo | null>(null);\n const [error, setError] = useState<ApiError | null>(null);\n const [loading, setLoading] = useState(!options?.skip);\n const [initialized, setInitialized] = useState(false);\n const refetching = loading && initialized;\n\n const reset = useCallback(() => {\n setData(null);\n setPageInfo(null);\n setError(null);\n setLoading(false);\n setInitialized(false);\n }, []);\n\n const deps = options?.variables ? Object.values(options.variables) : [];\n const skip = !!options?.skip;\n const refetchEvents =\n options?.refetch === true ? defaultRefetchEvents\n : Array.isArray(options?.refetch) ? [...options.refetch, tokenUpdateEvent]\n : [];\n\n const refetchEventsRef = useRef(refetchEvents);\n refetchEventsRef.current = refetchEvents;\n\n // Stable string key so the effect re-subscribes only when events actually change\n const refetchEventsKey = refetchEvents.join(\",\");\n\n const executeFetch = useCallback(() => {\n if (!swish || skip) {\n return;\n }\n\n setLoading(true);\n\n fetchRef\n .current(swish.api, options?.variables)\n .then((response) => {\n setError(\"error\" in response ? response.error : null);\n setData(\"data\" in response ? response.data : null);\n setPageInfo(\"pageInfo\" in response ? response.pageInfo : null);\n })\n .catch((error) => setError(error))\n .finally(() => {\n setLoading(false);\n setInitialized(true);\n });\n }, [swish, skip, ...deps]);\n\n const refetch = useCallback(() => {\n executeFetch();\n }, [executeFetch]);\n\n useEffect(() => {\n if (!swish) {\n return;\n }\n\n executeFetch();\n\n const unsubscribe = swish.events.subscribe(refetchEventsRef.current, () => {\n refetch();\n });\n\n return () => unsubscribe();\n }, [executeFetch, refetch, refetchEventsKey]);\n\n return useMemo(\n () => ({\n data,\n pageInfo,\n error,\n loading,\n reset,\n refetch,\n refetching,\n }),\n [data, pageInfo, error, loading, reset, refetch, refetching],\n );\n};\n","import type { Intent, IntentResponse, IntentToData } from \"@swishapp/sdk\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useSwish } from \"./use-swish\";\n\nexport const useSwishIntent = <I extends Intent = Intent>(\n intent: I,\n ...args: IntentToData<I> extends void ? [] | [undefined] : [IntentToData<I>]\n) => {\n const swish = useSwish();\n const [pending, setPending] = useState(false);\n const dataRef = useRef(args);\n\n useEffect(() => {\n dataRef.current = args;\n }, [args]);\n\n const invoke = useCallback(async (): Promise<IntentResponse<I>> => {\n if (!swish) {\n throw new Error(\"Swish SDK not initialized\");\n }\n\n setPending(true);\n try {\n const activity = await swish.intents.invoke(intent, ...dataRef.current);\n const response = await activity.complete;\n return response as IntentResponse<I>;\n } finally {\n setPending(false);\n }\n }, [swish]);\n\n return { invoke, pending };\n};\n","import { useMemo } from \"react\";\nimport { useSwishQuery } from \"./use-swish-query\";\n\nexport const useSwishLists = () => {\n const {\n data: lists,\n loading,\n error,\n reset,\n } = useSwishQuery((api) => api.lists.list(), {\n refetch: [\n \"item-lists-update\",\n \"item-delete\",\n \"list-create\",\n \"list-update\",\n \"list-delete\",\n ],\n });\n\n return useMemo(\n () => ({\n loading,\n lists,\n error,\n reset,\n }),\n [lists, loading, error, reset]\n );\n};\n","import type { Item } from \"@swishapp/sdk\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useSwishQuery } from \"./use-swish-query\";\n\nexport interface UseSwishItemsOptions {\n listId?: string;\n limit?: number;\n}\n\nexport const useSwishItems = ({\n listId,\n limit = 24,\n}: UseSwishItemsOptions = {}) => {\n const [nextPage, setNextPage] = useState<string | null>(null);\n const [data, setData] = useState<Item[]>([]);\n\n const {\n data: remoteData,\n pageInfo,\n loading,\n error,\n reset: resetRemoteData,\n } = useSwishQuery((api, variables) => api.items.list(variables), {\n variables: {\n page: nextPage ?? undefined,\n limit,\n listId,\n },\n refetch: false,\n });\n\n const reset = useCallback(() => {\n setData([]);\n setNextPage(null);\n resetRemoteData();\n }, [resetRemoteData]);\n\n useEffect(() => {\n if (remoteData) {\n setData((prev) => [...prev, ...remoteData]);\n }\n }, [remoteData]);\n\n const loadMore = useCallback(() => {\n if (pageInfo?.next) {\n setNextPage(pageInfo.next);\n }\n }, [pageInfo?.next]);\n\n return useMemo(\n () => ({\n loading,\n data,\n pageInfo,\n error,\n reset,\n hasMore: !!pageInfo?.next,\n loadMore,\n }),\n [data, pageInfo, loading, error, reset, loadMore]\n );\n};\n","import type {\n EditItemListsSuccessResponse,\n EditItemVariantSuccessResponse,\n ItemMatch,\n SaveItemSuccessResponse,\n UnsaveItemSuccessResponse,\n} from \"@swishapp/sdk\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useSyncExternalStore,\n} from \"react\";\nimport { useSwish } from \"./use-swish\";\n\ninterface UseSwishItemProps {\n productId: string | number;\n variantId?: string | number;\n itemId?: string;\n /**\n * How to interpret saved state when `variantId` is set:\n * - `\"variant\"`: only saved if the variant matches.\n * - `\"product\"`: saved if any variant of the product is saved.\n * - `\"auto\"` (default): variant-match when `variantId` is set, product-match otherwise.\n */\n match?: ItemMatch;\n onSave?: (data: SaveItemSuccessResponse[\"data\"]) => void;\n onUnsave?: (data: UnsaveItemSuccessResponse[\"data\"]) => void;\n onListsUpdate?: (data: EditItemListsSuccessResponse[\"data\"]) => void;\n onVariantUpdate?: (data: EditItemVariantSuccessResponse[\"data\"]) => void;\n}\n\nconst NOT_READY_SNAPSHOT = {\n status: \"unsaved\" as const,\n saved: false,\n saving: false,\n unsaving: false,\n loading: true,\n submitting: false,\n savedItemId: null,\n savedItemIds: [] as string[],\n error: null,\n};\n\nconst noop = () => {};\nconst noopAsync = async () => {};\n\nexport const useSwishItem = ({\n productId,\n variantId,\n itemId,\n match,\n onSave,\n onUnsave,\n onListsUpdate,\n onVariantUpdate,\n}: UseSwishItemProps) => {\n const swish = useSwish();\n\n const state = useMemo(() => {\n if (!swish) return null;\n const context = swish.state.itemContextFromIds({\n productId,\n variantId,\n itemId,\n });\n return swish.state.itemState(context);\n }, [swish, productId, variantId, itemId]);\n\n if (state) {\n state.setOptions({\n onSave,\n onUnsave,\n onListsUpdate,\n onVariantUpdate,\n match,\n });\n }\n\n useEffect(() => {\n if (!state) return;\n return () => state.dispose();\n }, [state]);\n\n const subscribe = useCallback(\n (notify: () => void) => {\n if (!state) return noop;\n return state.subscribe(() => notify());\n },\n [state],\n );\n const getSnapshot = useCallback(\n () => (state ? state.peek() : NOT_READY_SNAPSHOT),\n [state],\n );\n\n const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return useMemo(() => {\n return {\n saved: snapshot.saved,\n loading: snapshot.loading,\n saving: snapshot.saving,\n unsaving: snapshot.unsaving,\n error: snapshot.error,\n savedItemId: snapshot.savedItemId,\n savedItemIds: snapshot.savedItemIds,\n save: state?.save ?? noopAsync,\n unsave: state?.unsave ?? noopAsync,\n updateLists: state?.updateLists ?? noopAsync,\n updateVariant: state?.updateVariant ?? noopAsync,\n toggle: state?.toggle ?? noopAsync,\n };\n }, [snapshot, state]);\n};\n","import { useMemo } from \"react\";\nimport { useSwishQuery } from \"./use-swish-query\";\n\nexport const useSwishItemCount = () => {\n const { data, loading, error } = useSwishQuery((api) => api.items.count(), {\n refetch: [\"item-create\", \"item-delete\"],\n });\n\n return useMemo(() => {\n return {\n count: data?.count ?? 0,\n loading,\n error,\n };\n }, [data, loading, error]);\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swishapp/react",
3
- "version": "0.130.0",
3
+ "version": "0.131.0",
4
4
  "description": "React bindings for Swish SDK",
5
5
  "author": "Swish",
6
6
  "license": "UNLICENSED",
@@ -10,7 +10,7 @@
10
10
  "access": "public"
11
11
  },
12
12
  "dependencies": {
13
- "@swishapp/sdk": "0.130.0"
13
+ "@swishapp/sdk": "0.131.0"
14
14
  },
15
15
  "peerDependencies": {
16
16
  "react": ">=16.8.0 || >=17.0.0 || >=18.0.0",