@betterstore/react 0.1.1 → 0.1.3

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
@@ -1,5 +1,17 @@
1
1
  # @betterstore/sdk
2
2
 
3
+ ## 0.1.3
4
+
5
+ ### Patch Changes
6
+
7
+ - usecart hook added
8
+
9
+ ## 0.1.2
10
+
11
+ ### Patch Changes
12
+
13
+ - architecture redone
14
+
3
15
  ## 0.1.1
4
16
 
5
17
  ### Patch Changes
@@ -0,0 +1,31 @@
1
+ interface LineItem {
2
+ id: string;
3
+ quantity: number;
4
+ productId: string;
5
+ variantOptions: {
6
+ name: string;
7
+ value: string;
8
+ }[];
9
+ metadata?: string;
10
+ }
11
+ type LineItemWithoutId = Omit<LineItem, "id">;
12
+ interface Cart {
13
+ lineItems: LineItem[];
14
+ addItem: (item: LineItemWithoutId) => void;
15
+ removeItem: (id: string) => void;
16
+ updateQuantity: (id: string, quantity: number) => void;
17
+ getProductQuantity: (productId: string) => number;
18
+ clearCart: () => void;
19
+ }
20
+ export declare const useCart: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<Cart>, "persist"> & {
21
+ persist: {
22
+ setOptions: (options: Partial<import("zustand/middleware").PersistOptions<Cart, Cart>>) => void;
23
+ clearStorage: () => void;
24
+ rehydrate: () => Promise<void> | void;
25
+ hasHydrated: () => boolean;
26
+ onHydrate: (fn: (state: Cart) => void) => () => void;
27
+ onFinishHydration: (fn: (state: Cart) => void) => () => void;
28
+ getOptions: () => Partial<import("zustand/middleware").PersistOptions<Cart, Cart>>;
29
+ };
30
+ }>;
31
+ export {};
@@ -0,0 +1,8 @@
1
+ import BetterStore from "@betterstore/sdk";
2
+ import React from "react";
3
+ declare function CheckoutEmbed({ betterStore, checkoutId, }: {
4
+ betterStore: InstanceType<typeof BetterStore>;
5
+ checkoutId: string;
6
+ }): React.JSX.Element;
7
+ declare const _default: React.MemoExoticComponent<typeof CheckoutEmbed>;
8
+ export default _default;
@@ -0,0 +1,4 @@
1
+ export { useCart } from "./cart/useCart";
2
+ export { default as CheckoutEmbed } from "./checkout-embed";
3
+ export { default as PaymentElement } from "./payment-element";
4
+ export { useCheckout } from "./payment-element/useCheckout";
package/dist/index.cjs.js CHANGED
@@ -2,6 +2,273 @@
2
2
 
3
3
  var React = require('react');
4
4
 
5
+ const createStoreImpl = (createState) => {
6
+ let state;
7
+ const listeners = /* @__PURE__ */ new Set();
8
+ const setState = (partial, replace) => {
9
+ const nextState = typeof partial === "function" ? partial(state) : partial;
10
+ if (!Object.is(nextState, state)) {
11
+ const previousState = state;
12
+ state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
13
+ listeners.forEach((listener) => listener(state, previousState));
14
+ }
15
+ };
16
+ const getState = () => state;
17
+ const getInitialState = () => initialState;
18
+ const subscribe = (listener) => {
19
+ listeners.add(listener);
20
+ return () => listeners.delete(listener);
21
+ };
22
+ const api = { setState, getState, getInitialState, subscribe };
23
+ const initialState = state = createState(setState, getState, api);
24
+ return api;
25
+ };
26
+ const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
27
+
28
+ const identity = (arg) => arg;
29
+ function useStore(api, selector = identity) {
30
+ const slice = React.useSyncExternalStore(
31
+ api.subscribe,
32
+ () => selector(api.getState()),
33
+ () => selector(api.getInitialState())
34
+ );
35
+ React.useDebugValue(slice);
36
+ return slice;
37
+ }
38
+ const createImpl = (createState) => {
39
+ const api = createStore(createState);
40
+ const useBoundStore = (selector) => useStore(api, selector);
41
+ Object.assign(useBoundStore, api);
42
+ return useBoundStore;
43
+ };
44
+ const create = (createState) => createState ? createImpl(createState) : createImpl;
45
+
46
+ function createJSONStorage(getStorage, options) {
47
+ let storage;
48
+ try {
49
+ storage = getStorage();
50
+ } catch (e) {
51
+ return;
52
+ }
53
+ const persistStorage = {
54
+ getItem: (name) => {
55
+ var _a;
56
+ const parse = (str2) => {
57
+ if (str2 === null) {
58
+ return null;
59
+ }
60
+ return JSON.parse(str2, undefined );
61
+ };
62
+ const str = (_a = storage.getItem(name)) != null ? _a : null;
63
+ if (str instanceof Promise) {
64
+ return str.then(parse);
65
+ }
66
+ return parse(str);
67
+ },
68
+ setItem: (name, newValue) => storage.setItem(
69
+ name,
70
+ JSON.stringify(newValue, undefined )
71
+ ),
72
+ removeItem: (name) => storage.removeItem(name)
73
+ };
74
+ return persistStorage;
75
+ }
76
+ const toThenable = (fn) => (input) => {
77
+ try {
78
+ const result = fn(input);
79
+ if (result instanceof Promise) {
80
+ return result;
81
+ }
82
+ return {
83
+ then(onFulfilled) {
84
+ return toThenable(onFulfilled)(result);
85
+ },
86
+ catch(_onRejected) {
87
+ return this;
88
+ }
89
+ };
90
+ } catch (e) {
91
+ return {
92
+ then(_onFulfilled) {
93
+ return this;
94
+ },
95
+ catch(onRejected) {
96
+ return toThenable(onRejected)(e);
97
+ }
98
+ };
99
+ }
100
+ };
101
+ const persistImpl = (config, baseOptions) => (set, get, api) => {
102
+ let options = {
103
+ storage: createJSONStorage(() => localStorage),
104
+ partialize: (state) => state,
105
+ version: 0,
106
+ merge: (persistedState, currentState) => ({
107
+ ...currentState,
108
+ ...persistedState
109
+ }),
110
+ ...baseOptions
111
+ };
112
+ let hasHydrated = false;
113
+ const hydrationListeners = /* @__PURE__ */ new Set();
114
+ const finishHydrationListeners = /* @__PURE__ */ new Set();
115
+ let storage = options.storage;
116
+ if (!storage) {
117
+ return config(
118
+ (...args) => {
119
+ console.warn(
120
+ `[zustand persist middleware] Unable to update item '${options.name}', the given storage is currently unavailable.`
121
+ );
122
+ set(...args);
123
+ },
124
+ get,
125
+ api
126
+ );
127
+ }
128
+ const setItem = () => {
129
+ const state = options.partialize({ ...get() });
130
+ return storage.setItem(options.name, {
131
+ state,
132
+ version: options.version
133
+ });
134
+ };
135
+ const savedSetState = api.setState;
136
+ api.setState = (state, replace) => {
137
+ savedSetState(state, replace);
138
+ void setItem();
139
+ };
140
+ const configResult = config(
141
+ (...args) => {
142
+ set(...args);
143
+ void setItem();
144
+ },
145
+ get,
146
+ api
147
+ );
148
+ api.getInitialState = () => configResult;
149
+ let stateFromStorage;
150
+ const hydrate = () => {
151
+ var _a, _b;
152
+ if (!storage) return;
153
+ hasHydrated = false;
154
+ hydrationListeners.forEach((cb) => {
155
+ var _a2;
156
+ return cb((_a2 = get()) != null ? _a2 : configResult);
157
+ });
158
+ const postRehydrationCallback = ((_b = options.onRehydrateStorage) == null ? undefined : _b.call(options, (_a = get()) != null ? _a : configResult)) || undefined;
159
+ return toThenable(storage.getItem.bind(storage))(options.name).then((deserializedStorageValue) => {
160
+ if (deserializedStorageValue) {
161
+ if (typeof deserializedStorageValue.version === "number" && deserializedStorageValue.version !== options.version) {
162
+ if (options.migrate) {
163
+ const migration = options.migrate(
164
+ deserializedStorageValue.state,
165
+ deserializedStorageValue.version
166
+ );
167
+ if (migration instanceof Promise) {
168
+ return migration.then((result) => [true, result]);
169
+ }
170
+ return [true, migration];
171
+ }
172
+ console.error(
173
+ `State loaded from storage couldn't be migrated since no migrate function was provided`
174
+ );
175
+ } else {
176
+ return [false, deserializedStorageValue.state];
177
+ }
178
+ }
179
+ return [false, undefined];
180
+ }).then((migrationResult) => {
181
+ var _a2;
182
+ const [migrated, migratedState] = migrationResult;
183
+ stateFromStorage = options.merge(
184
+ migratedState,
185
+ (_a2 = get()) != null ? _a2 : configResult
186
+ );
187
+ set(stateFromStorage, true);
188
+ if (migrated) {
189
+ return setItem();
190
+ }
191
+ }).then(() => {
192
+ postRehydrationCallback == null ? undefined : postRehydrationCallback(stateFromStorage, undefined);
193
+ stateFromStorage = get();
194
+ hasHydrated = true;
195
+ finishHydrationListeners.forEach((cb) => cb(stateFromStorage));
196
+ }).catch((e) => {
197
+ postRehydrationCallback == null ? undefined : postRehydrationCallback(undefined, e);
198
+ });
199
+ };
200
+ api.persist = {
201
+ setOptions: (newOptions) => {
202
+ options = {
203
+ ...options,
204
+ ...newOptions
205
+ };
206
+ if (newOptions.storage) {
207
+ storage = newOptions.storage;
208
+ }
209
+ },
210
+ clearStorage: () => {
211
+ storage == null ? undefined : storage.removeItem(options.name);
212
+ },
213
+ getOptions: () => options,
214
+ rehydrate: () => hydrate(),
215
+ hasHydrated: () => hasHydrated,
216
+ onHydrate: (cb) => {
217
+ hydrationListeners.add(cb);
218
+ return () => {
219
+ hydrationListeners.delete(cb);
220
+ };
221
+ },
222
+ onFinishHydration: (cb) => {
223
+ finishHydrationListeners.add(cb);
224
+ return () => {
225
+ finishHydrationListeners.delete(cb);
226
+ };
227
+ }
228
+ };
229
+ if (!options.skipHydration) {
230
+ hydrate();
231
+ }
232
+ return stateFromStorage || configResult;
233
+ };
234
+ const persist = persistImpl;
235
+
236
+ const generateLineItemId = (item) => {
237
+ return btoa(JSON.stringify({
238
+ productId: item.productId,
239
+ variantOptions: item.variantOptions,
240
+ metadata: item.metadata,
241
+ }));
242
+ };
243
+ const useCart = create()(persist((set, get) => ({
244
+ lineItems: [],
245
+ addItem: (newItem) => set((state) => {
246
+ const id = generateLineItemId(newItem);
247
+ const existingItemIndex = state.lineItems.findIndex((item) => item.id === id);
248
+ if (existingItemIndex !== -1) {
249
+ const updatedItems = [...state.lineItems];
250
+ updatedItems[existingItemIndex] = Object.assign(Object.assign({}, updatedItems[existingItemIndex]), { quantity: updatedItems[existingItemIndex].quantity + newItem.quantity });
251
+ return { lineItems: updatedItems };
252
+ }
253
+ return {
254
+ lineItems: [...state.lineItems, Object.assign(Object.assign({}, newItem), { id })],
255
+ };
256
+ }),
257
+ removeItem: (id) => set((state) => ({
258
+ lineItems: state.lineItems.filter((i) => i.id !== id),
259
+ })),
260
+ updateQuantity: (id, quantity) => set((state) => ({
261
+ lineItems: state.lineItems.map((i) => i.id === id ? Object.assign(Object.assign({}, i), { quantity }) : i),
262
+ })),
263
+ getProductQuantity: (productId) => {
264
+ const items = get().lineItems.filter((item) => item.productId === productId);
265
+ return items.reduce((acc, item) => acc + item.quantity, 0);
266
+ },
267
+ clearCart: () => set({ lineItems: [] }),
268
+ }), {
269
+ name: "cart",
270
+ }));
271
+
5
272
  /******************************************************************************
6
273
  Copyright (c) Microsoft Corporation.
7
274
 
@@ -76,18 +343,38 @@ function CheckoutSummary({ lineItems, shipping, tax, currency, }) {
76
343
  React.createElement("span", { className: "text-2xl font-bold" }, formatPrice(total)))))));
77
344
  }
78
345
 
79
- function CheckoutEmbed(_a) {
80
- return __awaiter(this, arguments, void 0, function* ({ betterStore, checkoutId, }) {
81
- const checkout = yield betterStore.checkout.retrieve(checkoutId);
82
- if (!checkout) {
83
- return React.createElement("div", null, "Checkout not found");
346
+ function CheckoutEmbed({ betterStore, checkoutId, }) {
347
+ const [checkout, setCheckout] = React.useState(null);
348
+ const [loading, setLoading] = React.useState(true);
349
+ React.useEffect(() => {
350
+ function fetchCheckout() {
351
+ return __awaiter(this, void 0, void 0, function* () {
352
+ try {
353
+ const data = yield betterStore.checkout.retrieve(checkoutId);
354
+ setCheckout(data);
355
+ }
356
+ catch (error) {
357
+ console.error("Failed to fetch checkout:", error);
358
+ }
359
+ finally {
360
+ setLoading(false);
361
+ }
362
+ });
84
363
  }
85
- return (React.createElement("div", { className: "grid md:grid-cols-2 gap-4" },
86
- React.createElement("div", null, "forms heres"),
87
- React.createElement("div", null,
88
- React.createElement(CheckoutSummary, { currency: checkout.currency, lineItems: checkout.lineItems, shipping: checkout === null || checkout === void 0 ? void 0 : checkout.shipping, tax: checkout === null || checkout === void 0 ? void 0 : checkout.tax }))));
89
- });
364
+ fetchCheckout();
365
+ }, [betterStore, checkoutId]);
366
+ if (loading) {
367
+ return React.createElement("div", null, "Loading...");
368
+ }
369
+ if (!checkout) {
370
+ return React.createElement("div", null, "Checkout not found");
371
+ }
372
+ return (React.createElement("div", { className: "grid md:grid-cols-2 gap-4" },
373
+ React.createElement("div", null, "forms here"),
374
+ React.createElement("div", null,
375
+ React.createElement(CheckoutSummary, { currency: checkout.currency, lineItems: checkout.lineItems, shipping: checkout === null || checkout === void 0 ? void 0 : checkout.shipping, tax: checkout === null || checkout === void 0 ? void 0 : checkout.tax }))));
90
376
  }
377
+ var index$1 = React.memo(CheckoutEmbed);
91
378
 
92
379
  function getDefaultExportFromCjs (x) {
93
380
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
@@ -2196,47 +2483,6 @@ var loadStripe = function loadStripe() {
2196
2483
  });
2197
2484
  };
2198
2485
 
2199
- const createStoreImpl = (createState) => {
2200
- let state;
2201
- const listeners = /* @__PURE__ */ new Set();
2202
- const setState = (partial, replace) => {
2203
- const nextState = typeof partial === "function" ? partial(state) : partial;
2204
- if (!Object.is(nextState, state)) {
2205
- const previousState = state;
2206
- state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
2207
- listeners.forEach((listener) => listener(state, previousState));
2208
- }
2209
- };
2210
- const getState = () => state;
2211
- const getInitialState = () => initialState;
2212
- const subscribe = (listener) => {
2213
- listeners.add(listener);
2214
- return () => listeners.delete(listener);
2215
- };
2216
- const api = { setState, getState, getInitialState, subscribe };
2217
- const initialState = state = createState(setState, getState, api);
2218
- return api;
2219
- };
2220
- const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
2221
-
2222
- const identity = (arg) => arg;
2223
- function useStore(api, selector = identity) {
2224
- const slice = React.useSyncExternalStore(
2225
- api.subscribe,
2226
- () => selector(api.getState()),
2227
- () => selector(api.getInitialState())
2228
- );
2229
- React.useDebugValue(slice);
2230
- return slice;
2231
- }
2232
- const createImpl = (createState) => {
2233
- const api = createStore(createState);
2234
- const useBoundStore = (selector) => useStore(api, selector);
2235
- Object.assign(useBoundStore, api);
2236
- return useBoundStore;
2237
- };
2238
- const create = (createState) => createState ? createImpl(createState) : createImpl;
2239
-
2240
2486
  const useCheckout = create((set) => ({
2241
2487
  isSubmitting: false,
2242
2488
  setIsSubmitting: (isSubmitting) => set({ isSubmitting }),
@@ -2285,8 +2531,9 @@ function PaymentElement({ paymentSecret, checkoutAppearance, onSuccess, onError,
2285
2531
  return (React.createElement(Elements, { stripe: stripePromise, options: options },
2286
2532
  React.createElement(CheckoutForm$1, { onSuccess: onSuccess, onError: onError, children: children })));
2287
2533
  }
2288
- var paymentElement = React.memo(PaymentElement);
2534
+ var index = React.memo(PaymentElement);
2289
2535
 
2290
- exports.CheckoutEmbed = CheckoutEmbed;
2291
- exports.PaymentElement = paymentElement;
2536
+ exports.CheckoutEmbed = index$1;
2537
+ exports.PaymentElement = index;
2538
+ exports.useCart = useCart;
2292
2539
  exports.useCheckout = useCheckout;
package/dist/index.d.ts CHANGED
@@ -1,3 +1 @@
1
- export { default as CheckoutEmbed } from "./checkout-embed";
2
- export { default as PaymentElement } from "./checkout/payment-element";
3
- export { useCheckout } from "./checkout/useCheckout";
1
+ export * from "./components";
package/dist/index.esm.js CHANGED
@@ -1,4 +1,271 @@
1
- import React, { memo, useState } from 'react';
1
+ import React, { memo, useState, useEffect } from 'react';
2
+
3
+ const createStoreImpl = (createState) => {
4
+ let state;
5
+ const listeners = /* @__PURE__ */ new Set();
6
+ const setState = (partial, replace) => {
7
+ const nextState = typeof partial === "function" ? partial(state) : partial;
8
+ if (!Object.is(nextState, state)) {
9
+ const previousState = state;
10
+ state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
11
+ listeners.forEach((listener) => listener(state, previousState));
12
+ }
13
+ };
14
+ const getState = () => state;
15
+ const getInitialState = () => initialState;
16
+ const subscribe = (listener) => {
17
+ listeners.add(listener);
18
+ return () => listeners.delete(listener);
19
+ };
20
+ const api = { setState, getState, getInitialState, subscribe };
21
+ const initialState = state = createState(setState, getState, api);
22
+ return api;
23
+ };
24
+ const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
25
+
26
+ const identity = (arg) => arg;
27
+ function useStore(api, selector = identity) {
28
+ const slice = React.useSyncExternalStore(
29
+ api.subscribe,
30
+ () => selector(api.getState()),
31
+ () => selector(api.getInitialState())
32
+ );
33
+ React.useDebugValue(slice);
34
+ return slice;
35
+ }
36
+ const createImpl = (createState) => {
37
+ const api = createStore(createState);
38
+ const useBoundStore = (selector) => useStore(api, selector);
39
+ Object.assign(useBoundStore, api);
40
+ return useBoundStore;
41
+ };
42
+ const create = (createState) => createState ? createImpl(createState) : createImpl;
43
+
44
+ function createJSONStorage(getStorage, options) {
45
+ let storage;
46
+ try {
47
+ storage = getStorage();
48
+ } catch (e) {
49
+ return;
50
+ }
51
+ const persistStorage = {
52
+ getItem: (name) => {
53
+ var _a;
54
+ const parse = (str2) => {
55
+ if (str2 === null) {
56
+ return null;
57
+ }
58
+ return JSON.parse(str2, undefined );
59
+ };
60
+ const str = (_a = storage.getItem(name)) != null ? _a : null;
61
+ if (str instanceof Promise) {
62
+ return str.then(parse);
63
+ }
64
+ return parse(str);
65
+ },
66
+ setItem: (name, newValue) => storage.setItem(
67
+ name,
68
+ JSON.stringify(newValue, undefined )
69
+ ),
70
+ removeItem: (name) => storage.removeItem(name)
71
+ };
72
+ return persistStorage;
73
+ }
74
+ const toThenable = (fn) => (input) => {
75
+ try {
76
+ const result = fn(input);
77
+ if (result instanceof Promise) {
78
+ return result;
79
+ }
80
+ return {
81
+ then(onFulfilled) {
82
+ return toThenable(onFulfilled)(result);
83
+ },
84
+ catch(_onRejected) {
85
+ return this;
86
+ }
87
+ };
88
+ } catch (e) {
89
+ return {
90
+ then(_onFulfilled) {
91
+ return this;
92
+ },
93
+ catch(onRejected) {
94
+ return toThenable(onRejected)(e);
95
+ }
96
+ };
97
+ }
98
+ };
99
+ const persistImpl = (config, baseOptions) => (set, get, api) => {
100
+ let options = {
101
+ storage: createJSONStorage(() => localStorage),
102
+ partialize: (state) => state,
103
+ version: 0,
104
+ merge: (persistedState, currentState) => ({
105
+ ...currentState,
106
+ ...persistedState
107
+ }),
108
+ ...baseOptions
109
+ };
110
+ let hasHydrated = false;
111
+ const hydrationListeners = /* @__PURE__ */ new Set();
112
+ const finishHydrationListeners = /* @__PURE__ */ new Set();
113
+ let storage = options.storage;
114
+ if (!storage) {
115
+ return config(
116
+ (...args) => {
117
+ console.warn(
118
+ `[zustand persist middleware] Unable to update item '${options.name}', the given storage is currently unavailable.`
119
+ );
120
+ set(...args);
121
+ },
122
+ get,
123
+ api
124
+ );
125
+ }
126
+ const setItem = () => {
127
+ const state = options.partialize({ ...get() });
128
+ return storage.setItem(options.name, {
129
+ state,
130
+ version: options.version
131
+ });
132
+ };
133
+ const savedSetState = api.setState;
134
+ api.setState = (state, replace) => {
135
+ savedSetState(state, replace);
136
+ void setItem();
137
+ };
138
+ const configResult = config(
139
+ (...args) => {
140
+ set(...args);
141
+ void setItem();
142
+ },
143
+ get,
144
+ api
145
+ );
146
+ api.getInitialState = () => configResult;
147
+ let stateFromStorage;
148
+ const hydrate = () => {
149
+ var _a, _b;
150
+ if (!storage) return;
151
+ hasHydrated = false;
152
+ hydrationListeners.forEach((cb) => {
153
+ var _a2;
154
+ return cb((_a2 = get()) != null ? _a2 : configResult);
155
+ });
156
+ const postRehydrationCallback = ((_b = options.onRehydrateStorage) == null ? undefined : _b.call(options, (_a = get()) != null ? _a : configResult)) || undefined;
157
+ return toThenable(storage.getItem.bind(storage))(options.name).then((deserializedStorageValue) => {
158
+ if (deserializedStorageValue) {
159
+ if (typeof deserializedStorageValue.version === "number" && deserializedStorageValue.version !== options.version) {
160
+ if (options.migrate) {
161
+ const migration = options.migrate(
162
+ deserializedStorageValue.state,
163
+ deserializedStorageValue.version
164
+ );
165
+ if (migration instanceof Promise) {
166
+ return migration.then((result) => [true, result]);
167
+ }
168
+ return [true, migration];
169
+ }
170
+ console.error(
171
+ `State loaded from storage couldn't be migrated since no migrate function was provided`
172
+ );
173
+ } else {
174
+ return [false, deserializedStorageValue.state];
175
+ }
176
+ }
177
+ return [false, undefined];
178
+ }).then((migrationResult) => {
179
+ var _a2;
180
+ const [migrated, migratedState] = migrationResult;
181
+ stateFromStorage = options.merge(
182
+ migratedState,
183
+ (_a2 = get()) != null ? _a2 : configResult
184
+ );
185
+ set(stateFromStorage, true);
186
+ if (migrated) {
187
+ return setItem();
188
+ }
189
+ }).then(() => {
190
+ postRehydrationCallback == null ? undefined : postRehydrationCallback(stateFromStorage, undefined);
191
+ stateFromStorage = get();
192
+ hasHydrated = true;
193
+ finishHydrationListeners.forEach((cb) => cb(stateFromStorage));
194
+ }).catch((e) => {
195
+ postRehydrationCallback == null ? undefined : postRehydrationCallback(undefined, e);
196
+ });
197
+ };
198
+ api.persist = {
199
+ setOptions: (newOptions) => {
200
+ options = {
201
+ ...options,
202
+ ...newOptions
203
+ };
204
+ if (newOptions.storage) {
205
+ storage = newOptions.storage;
206
+ }
207
+ },
208
+ clearStorage: () => {
209
+ storage == null ? undefined : storage.removeItem(options.name);
210
+ },
211
+ getOptions: () => options,
212
+ rehydrate: () => hydrate(),
213
+ hasHydrated: () => hasHydrated,
214
+ onHydrate: (cb) => {
215
+ hydrationListeners.add(cb);
216
+ return () => {
217
+ hydrationListeners.delete(cb);
218
+ };
219
+ },
220
+ onFinishHydration: (cb) => {
221
+ finishHydrationListeners.add(cb);
222
+ return () => {
223
+ finishHydrationListeners.delete(cb);
224
+ };
225
+ }
226
+ };
227
+ if (!options.skipHydration) {
228
+ hydrate();
229
+ }
230
+ return stateFromStorage || configResult;
231
+ };
232
+ const persist = persistImpl;
233
+
234
+ const generateLineItemId = (item) => {
235
+ return btoa(JSON.stringify({
236
+ productId: item.productId,
237
+ variantOptions: item.variantOptions,
238
+ metadata: item.metadata,
239
+ }));
240
+ };
241
+ const useCart = create()(persist((set, get) => ({
242
+ lineItems: [],
243
+ addItem: (newItem) => set((state) => {
244
+ const id = generateLineItemId(newItem);
245
+ const existingItemIndex = state.lineItems.findIndex((item) => item.id === id);
246
+ if (existingItemIndex !== -1) {
247
+ const updatedItems = [...state.lineItems];
248
+ updatedItems[existingItemIndex] = Object.assign(Object.assign({}, updatedItems[existingItemIndex]), { quantity: updatedItems[existingItemIndex].quantity + newItem.quantity });
249
+ return { lineItems: updatedItems };
250
+ }
251
+ return {
252
+ lineItems: [...state.lineItems, Object.assign(Object.assign({}, newItem), { id })],
253
+ };
254
+ }),
255
+ removeItem: (id) => set((state) => ({
256
+ lineItems: state.lineItems.filter((i) => i.id !== id),
257
+ })),
258
+ updateQuantity: (id, quantity) => set((state) => ({
259
+ lineItems: state.lineItems.map((i) => i.id === id ? Object.assign(Object.assign({}, i), { quantity }) : i),
260
+ })),
261
+ getProductQuantity: (productId) => {
262
+ const items = get().lineItems.filter((item) => item.productId === productId);
263
+ return items.reduce((acc, item) => acc + item.quantity, 0);
264
+ },
265
+ clearCart: () => set({ lineItems: [] }),
266
+ }), {
267
+ name: "cart",
268
+ }));
2
269
 
3
270
  /******************************************************************************
4
271
  Copyright (c) Microsoft Corporation.
@@ -74,18 +341,38 @@ function CheckoutSummary({ lineItems, shipping, tax, currency, }) {
74
341
  React.createElement("span", { className: "text-2xl font-bold" }, formatPrice(total)))))));
75
342
  }
76
343
 
77
- function CheckoutEmbed(_a) {
78
- return __awaiter(this, arguments, void 0, function* ({ betterStore, checkoutId, }) {
79
- const checkout = yield betterStore.checkout.retrieve(checkoutId);
80
- if (!checkout) {
81
- return React.createElement("div", null, "Checkout not found");
344
+ function CheckoutEmbed({ betterStore, checkoutId, }) {
345
+ const [checkout, setCheckout] = useState(null);
346
+ const [loading, setLoading] = useState(true);
347
+ useEffect(() => {
348
+ function fetchCheckout() {
349
+ return __awaiter(this, void 0, void 0, function* () {
350
+ try {
351
+ const data = yield betterStore.checkout.retrieve(checkoutId);
352
+ setCheckout(data);
353
+ }
354
+ catch (error) {
355
+ console.error("Failed to fetch checkout:", error);
356
+ }
357
+ finally {
358
+ setLoading(false);
359
+ }
360
+ });
82
361
  }
83
- return (React.createElement("div", { className: "grid md:grid-cols-2 gap-4" },
84
- React.createElement("div", null, "forms heres"),
85
- React.createElement("div", null,
86
- React.createElement(CheckoutSummary, { currency: checkout.currency, lineItems: checkout.lineItems, shipping: checkout === null || checkout === void 0 ? void 0 : checkout.shipping, tax: checkout === null || checkout === void 0 ? void 0 : checkout.tax }))));
87
- });
362
+ fetchCheckout();
363
+ }, [betterStore, checkoutId]);
364
+ if (loading) {
365
+ return React.createElement("div", null, "Loading...");
366
+ }
367
+ if (!checkout) {
368
+ return React.createElement("div", null, "Checkout not found");
369
+ }
370
+ return (React.createElement("div", { className: "grid md:grid-cols-2 gap-4" },
371
+ React.createElement("div", null, "forms here"),
372
+ React.createElement("div", null,
373
+ React.createElement(CheckoutSummary, { currency: checkout.currency, lineItems: checkout.lineItems, shipping: checkout === null || checkout === void 0 ? void 0 : checkout.shipping, tax: checkout === null || checkout === void 0 ? void 0 : checkout.tax }))));
88
374
  }
375
+ var index$1 = memo(CheckoutEmbed);
89
376
 
90
377
  function getDefaultExportFromCjs (x) {
91
378
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
@@ -2194,47 +2481,6 @@ var loadStripe = function loadStripe() {
2194
2481
  });
2195
2482
  };
2196
2483
 
2197
- const createStoreImpl = (createState) => {
2198
- let state;
2199
- const listeners = /* @__PURE__ */ new Set();
2200
- const setState = (partial, replace) => {
2201
- const nextState = typeof partial === "function" ? partial(state) : partial;
2202
- if (!Object.is(nextState, state)) {
2203
- const previousState = state;
2204
- state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
2205
- listeners.forEach((listener) => listener(state, previousState));
2206
- }
2207
- };
2208
- const getState = () => state;
2209
- const getInitialState = () => initialState;
2210
- const subscribe = (listener) => {
2211
- listeners.add(listener);
2212
- return () => listeners.delete(listener);
2213
- };
2214
- const api = { setState, getState, getInitialState, subscribe };
2215
- const initialState = state = createState(setState, getState, api);
2216
- return api;
2217
- };
2218
- const createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
2219
-
2220
- const identity = (arg) => arg;
2221
- function useStore(api, selector = identity) {
2222
- const slice = React.useSyncExternalStore(
2223
- api.subscribe,
2224
- () => selector(api.getState()),
2225
- () => selector(api.getInitialState())
2226
- );
2227
- React.useDebugValue(slice);
2228
- return slice;
2229
- }
2230
- const createImpl = (createState) => {
2231
- const api = createStore(createState);
2232
- const useBoundStore = (selector) => useStore(api, selector);
2233
- Object.assign(useBoundStore, api);
2234
- return useBoundStore;
2235
- };
2236
- const create = (createState) => createState ? createImpl(createState) : createImpl;
2237
-
2238
2484
  const useCheckout = create((set) => ({
2239
2485
  isSubmitting: false,
2240
2486
  setIsSubmitting: (isSubmitting) => set({ isSubmitting }),
@@ -2283,6 +2529,6 @@ function PaymentElement({ paymentSecret, checkoutAppearance, onSuccess, onError,
2283
2529
  return (React.createElement(Elements, { stripe: stripePromise, options: options },
2284
2530
  React.createElement(CheckoutForm$1, { onSuccess: onSuccess, onError: onError, children: children })));
2285
2531
  }
2286
- var paymentElement = memo(PaymentElement);
2532
+ var index = memo(PaymentElement);
2287
2533
 
2288
- export { CheckoutEmbed, paymentElement as PaymentElement, useCheckout };
2534
+ export { index$1 as CheckoutEmbed, index as PaymentElement, useCart, useCheckout };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@betterstore/react",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "E-commerce for Developers",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -1,6 +0,0 @@
1
- import BetterStore from "@betterstore/sdk";
2
- import React from "react";
3
- export default function CheckoutEmbed({ betterStore, checkoutId, }: {
4
- betterStore: InstanceType<typeof BetterStore>;
5
- checkoutId: string;
6
- }): Promise<React.JSX.Element>;