@meaple-com/react-headless-components 1.0.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.cjs ADDED
@@ -0,0 +1,461 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Cart: () => Cart,
24
+ CartProvider: () => CartProvider,
25
+ Coupon: () => Coupon,
26
+ GetOrder: () => GetOrder,
27
+ ListCategories: () => ListCategories,
28
+ ListEventProducts: () => ListEventProducts,
29
+ ListEventTickets: () => ListEventTickets,
30
+ ListEvents: () => ListEvents,
31
+ ListUserEventTickets: () => ListUserEventTickets,
32
+ ListUserEvents: () => ListUserEvents,
33
+ ListUserOrders: () => ListUserOrders,
34
+ TicketQuantityController: () => TicketQuantityController,
35
+ useCart: () => useCart,
36
+ useTicketQuantity: () => useTicketQuantity
37
+ });
38
+ module.exports = __toCommonJS(index_exports);
39
+
40
+ // src/components/Cart.tsx
41
+ var import_react2 = require("react");
42
+
43
+ // src/contexts/CartContext.tsx
44
+ var import_react = require("react");
45
+ var import_jsx_runtime = require("react/jsx-runtime");
46
+ var CartContext = (0, import_react.createContext)({});
47
+ var CartProvider = ({ children, initialCoupon }) => {
48
+ const [items, setItems] = (0, import_react.useState)([]);
49
+ const [coupon, setCoupon] = (0, import_react.useState)(initialCoupon);
50
+ const incrementToCart = (0, import_react.useCallback)((item) => {
51
+ setItems((prevItems) => {
52
+ const itemExists = prevItems.find((prevItem) => prevItem.id === item.id);
53
+ if (!itemExists)
54
+ return [
55
+ ...prevItems,
56
+ {
57
+ ...item,
58
+ amount: 1,
59
+ seats: item.seat ? [item.seat] : void 0
60
+ }
61
+ ];
62
+ return prevItems.map((prevItem) => {
63
+ if (prevItem.id === item.id) {
64
+ return {
65
+ ...prevItem,
66
+ amount: prevItem.amount + 1,
67
+ seats: item.seat ? [...prevItem.seats ?? [], item.seat] : prevItem.seats
68
+ };
69
+ }
70
+ return prevItem;
71
+ });
72
+ });
73
+ }, []);
74
+ const decrementFromCart = (0, import_react.useCallback)((item) => {
75
+ setItems((prevItems) => {
76
+ return prevItems.map((prevItem) => {
77
+ if (prevItem.id === item.id) {
78
+ return {
79
+ ...prevItem,
80
+ amount: prevItem.amount - 1,
81
+ seats: prevItem.seats ? prevItem.seats.filter((seat) => seat.id !== item.seat?.id) : prevItem.seats
82
+ };
83
+ }
84
+ return prevItem;
85
+ }).filter((prevItem) => prevItem.amount > 0);
86
+ });
87
+ }, []);
88
+ const getItem = (0, import_react.useCallback)(
89
+ (itemId) => {
90
+ return items.find((item) => item.id === itemId);
91
+ },
92
+ [items]
93
+ );
94
+ const clearCart = (0, import_react.useCallback)(() => {
95
+ setItems([]);
96
+ }, []);
97
+ const applyCoupon = (0, import_react.useCallback)((coupon2) => {
98
+ setCoupon(coupon2);
99
+ }, []);
100
+ const computeItemDiscount = (0, import_react.useCallback)(
101
+ (item) => {
102
+ if (!coupon) return 0;
103
+ if (coupon.ticketIds.length > 0 && !coupon.ticketIds.includes(item.id))
104
+ return 0;
105
+ if (coupon.type === `PERCENTAGE`)
106
+ return item.amount * item.price * (coupon.value / 100);
107
+ return item.amount * coupon.value;
108
+ },
109
+ [coupon]
110
+ );
111
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
112
+ CartContext.Provider,
113
+ {
114
+ value: {
115
+ items,
116
+ getItem,
117
+ incrementToCart,
118
+ decrementFromCart,
119
+ clearCart,
120
+ coupon,
121
+ computeItemDiscount,
122
+ applyCoupon
123
+ },
124
+ children
125
+ }
126
+ );
127
+ };
128
+ function useCart() {
129
+ const context = (0, import_react.useContext)(CartContext);
130
+ if (!context) {
131
+ throw new Error(`useCart must be used within a CartProvider`);
132
+ }
133
+ return context;
134
+ }
135
+
136
+ // src/components/Cart.tsx
137
+ var Cart = ({
138
+ children,
139
+ feeType = `DIGITAL`,
140
+ platformFee
141
+ }) => {
142
+ const cart = useCart();
143
+ const totalAmount = (0, import_react2.useMemo)(
144
+ () => cart.items.reduce((acc, item) => acc + item.amount, 0),
145
+ [cart.items]
146
+ );
147
+ const totalDiscount = (0, import_react2.useMemo)(() => {
148
+ return cart.items.reduce(
149
+ (acc, item) => acc + Math.min(cart.computeItemDiscount(item), item.price * item.amount),
150
+ 0
151
+ );
152
+ }, [cart]);
153
+ const rawPrice = (0, import_react2.useMemo)(() => {
154
+ return cart.items.reduce((acc, item) => {
155
+ return acc + item.price * item.amount;
156
+ }, 0);
157
+ }, [cart.items]);
158
+ const rawFeeAmount = (0, import_react2.useMemo)(() => {
159
+ if (!platformFee) return 0;
160
+ const fee = feeType === `POS` && platformFee.pos ? platformFee.pos.fee : platformFee.fee;
161
+ return cart.items.reduce(
162
+ (acc, item) => acc + item.price * item.amount * fee,
163
+ 0
164
+ );
165
+ }, [platformFee, cart.items, feeType]);
166
+ const totalFee = (0, import_react2.useMemo)(() => {
167
+ if (!platformFee) return 0;
168
+ const { fee, minFeeAmount, thresholdAmount } = feeType === `POS` && platformFee.pos ? platformFee.pos : platformFee;
169
+ if (fee === 0) return 0;
170
+ if (rawFeeAmount <= 0) return 0;
171
+ if (rawFeeAmount < minFeeAmount && rawPrice < thresholdAmount) {
172
+ return minFeeAmount;
173
+ }
174
+ return rawFeeAmount;
175
+ }, [feeType, platformFee, rawFeeAmount, rawPrice]);
176
+ const totalPrice = Math.max(rawPrice - totalDiscount, 0) + totalFee;
177
+ return children({
178
+ totalAmount,
179
+ totalDiscount,
180
+ rawPrice,
181
+ rawFeeAmount,
182
+ totalFee,
183
+ totalPrice,
184
+ items: cart.items,
185
+ clearCart: cart.clearCart
186
+ });
187
+ };
188
+
189
+ // src/components/Coupon.tsx
190
+ var import_react3 = require("react");
191
+ var import_react_query = require("@meaple-com/react-query");
192
+ var import_jsx_runtime2 = require("react/jsx-runtime");
193
+ function mapCouponData(cart, couponState) {
194
+ const { coupon, applyCoupon } = cart;
195
+ return {
196
+ coupon,
197
+ applyCoupon,
198
+ // Cupom functions
199
+ isCheckingCoupon: couponState.isChecking,
200
+ couponError: couponState.error,
201
+ isCouponValid: couponState.isSuccess,
202
+ checkCoupon: couponState.checkCoupon,
203
+ clearCoupon: couponState.clearCoupon,
204
+ currentCouponCode: couponState.currentCouponCode,
205
+ setCouponCode: couponState.setCouponCode
206
+ };
207
+ }
208
+ var Coupon = ({ children, eventId, options }) => {
209
+ const cart = useCart();
210
+ const { mutateAsync: checkCouponFn, ...checkCoupon } = (0, import_react_query.useCheckCoupon)(options);
211
+ const [currentCouponCode, setCurrentCouponCode] = (0, import_react3.useState)(cart.coupon?.code);
212
+ const handleCheckCoupon = (0, import_react3.useCallback)(
213
+ async (couponCode) => {
214
+ try {
215
+ const data2 = await checkCouponFn({ eventId, couponCode });
216
+ console.log("data", data2);
217
+ console.log(typeof data2.ticketIds);
218
+ cart.applyCoupon(data2);
219
+ setCurrentCouponCode(couponCode);
220
+ } catch (err) {
221
+ }
222
+ },
223
+ [cart, checkCouponFn, eventId]
224
+ );
225
+ const handleClearCoupon = (0, import_react3.useCallback)(() => {
226
+ setCurrentCouponCode(``);
227
+ cart.applyCoupon(null);
228
+ }, [cart]);
229
+ const couponState = {
230
+ isChecking: checkCoupon.isPending,
231
+ error: checkCoupon.error,
232
+ isSuccess: checkCoupon.isSuccess,
233
+ checkCoupon: handleCheckCoupon,
234
+ clearCoupon: handleClearCoupon,
235
+ currentCouponCode,
236
+ setCouponCode: setCurrentCouponCode
237
+ };
238
+ const data = mapCouponData(cart, couponState);
239
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: children(data) });
240
+ };
241
+
242
+ // src/components/GetOrder.tsx
243
+ var import_react_query2 = require("@meaple-com/react-query");
244
+ var GetOrder = ({ children, orderId, options }) => {
245
+ const { data, isPending, error } = (0, import_react_query2.useOrder)(orderId, options);
246
+ return children({
247
+ order: data?.order ?? null,
248
+ paidTickets: data?.paidTickets ?? null,
249
+ paymentIntent: data?.paymentIntent,
250
+ isPending,
251
+ error
252
+ });
253
+ };
254
+
255
+ // src/components/ListCategories.tsx
256
+ var import_react_query3 = require("@meaple-com/react-query");
257
+ var ListCategories = ({ children, options }) => {
258
+ const { data, isPending, error } = (0, import_react_query3.useCategories)(options);
259
+ return children({
260
+ categories: data ?? [],
261
+ isPending,
262
+ error
263
+ });
264
+ };
265
+
266
+ // src/components/ListEventProducts.tsx
267
+ var import_react_query4 = require("@meaple-com/react-query");
268
+ var ListEventProducts = ({
269
+ children,
270
+ eventId,
271
+ privateToken,
272
+ options
273
+ }) => {
274
+ const { data, isPending, error } = (0, import_react_query4.useEventProducts)(
275
+ eventId,
276
+ privateToken,
277
+ options
278
+ );
279
+ return children({
280
+ products: data?.products ?? [],
281
+ isPending,
282
+ error
283
+ });
284
+ };
285
+
286
+ // src/components/ListEvents.tsx
287
+ var import_react_query5 = require("@meaple-com/react-query");
288
+ var ListEvents = ({ children, channelId, options }) => {
289
+ const { data, isPending, error } = (0, import_react_query5.useChannelEvents)({ channelId }, options);
290
+ return children({
291
+ events: data ?? [],
292
+ isPending,
293
+ error
294
+ });
295
+ };
296
+
297
+ // src/components/ListEventTickets.tsx
298
+ var import_react_query6 = require("@meaple-com/react-query");
299
+ var ListEventTickets = ({
300
+ children,
301
+ eventId,
302
+ privateToken,
303
+ predecessorIds,
304
+ options
305
+ }) => {
306
+ const { data, isPending, error } = (0, import_react_query6.useEventTickets)(
307
+ eventId,
308
+ privateToken,
309
+ predecessorIds,
310
+ options
311
+ );
312
+ return children({
313
+ tickets: data?.tickets ?? [],
314
+ groups: data?.groups ?? [],
315
+ isPending,
316
+ error
317
+ });
318
+ };
319
+
320
+ // src/components/ListUserEvents.tsx
321
+ var import_react_query7 = require("@meaple-com/react-query");
322
+ var ListUserEvents = ({ children, type, options }) => {
323
+ const { data, isPending, error } = (0, import_react_query7.useUserEvents)(
324
+ {
325
+ type: type ?? "coming_soon"
326
+ },
327
+ options
328
+ );
329
+ const events = Array.isArray(data) ? data : [];
330
+ return children({ events, isPending, error });
331
+ };
332
+
333
+ // src/components/ListUserEventTickets.tsx
334
+ var import_react_query8 = require("@meaple-com/react-query");
335
+ var ListUserEventTickets = ({
336
+ children,
337
+ eventId,
338
+ options
339
+ }) => {
340
+ const { data, isPending, error } = (0, import_react_query8.useUserEventTickets)(
341
+ eventId,
342
+ void 0,
343
+ options
344
+ );
345
+ return children({
346
+ userTickets: data?.userTickets ?? [],
347
+ isPending,
348
+ error
349
+ });
350
+ };
351
+
352
+ // src/components/ListUserOrders.tsx
353
+ var import_react_query9 = require("@meaple-com/react-query");
354
+ var ListUserOrders = ({
355
+ children,
356
+ status,
357
+ eventId,
358
+ options
359
+ }) => {
360
+ const { data, isPending, error } = (0, import_react_query9.useUserOrders)(
361
+ { status, eventId },
362
+ options
363
+ );
364
+ return children({
365
+ orders: data ?? [],
366
+ isPending,
367
+ error
368
+ });
369
+ };
370
+
371
+ // src/components/TicketQuantityController.tsx
372
+ var import_react4 = require("react");
373
+ var TicketQuantityController = ({
374
+ ticket,
375
+ onSoldOut,
376
+ children
377
+ }) => {
378
+ const cart = useCart();
379
+ const item = cart.getItem(ticket.id);
380
+ const amount = item?.amount ?? 0;
381
+ const incrementAmount = ticket.minBuy ?? 1;
382
+ const isMaxLimitReached = amount + incrementAmount > (ticket.maxBuy ?? Infinity);
383
+ const eventMaxBuy = ticket.maxBuy ?? Infinity;
384
+ const disabled = ticket.availableAmount === 0 || eventMaxBuy === 0;
385
+ const increment = (0, import_react4.useCallback)(() => {
386
+ if (disabled) return;
387
+ if (amount + incrementAmount >= ticket.availableAmount && onSoldOut)
388
+ onSoldOut();
389
+ for (let i = 0; i < incrementAmount; i++) {
390
+ cart.incrementToCart(ticket);
391
+ }
392
+ }, [amount, incrementAmount, ticket, onSoldOut, cart, disabled]);
393
+ const decrement = (0, import_react4.useCallback)(() => {
394
+ if (disabled) return;
395
+ for (let i = 0; i < incrementAmount; i++) {
396
+ cart.decrementFromCart({ id: ticket.id });
397
+ }
398
+ }, [cart, ticket.id, incrementAmount, disabled]);
399
+ return children({
400
+ amount,
401
+ isMaxLimitReached: isMaxLimitReached || !!disabled,
402
+ increment,
403
+ decrement,
404
+ disabled
405
+ });
406
+ };
407
+
408
+ // src/hooks/useTicketQuantity.ts
409
+ var import_react5 = require("react");
410
+ function useTicketQuantity({
411
+ ticket,
412
+ disabled,
413
+ onSoldOut
414
+ }) {
415
+ const cart = useCart();
416
+ const item = cart.getItem(ticket.id);
417
+ const amount = item?.amount ?? 0;
418
+ const incrementAmount = ticket.minBuy ?? 1;
419
+ const isMaxLimitReached = amount + incrementAmount > (ticket.maxBuy ?? Infinity);
420
+ const increment = (0, import_react5.useCallback)(() => {
421
+ if (disabled) return;
422
+ if (amount + incrementAmount >= ticket.availableAmount && onSoldOut)
423
+ onSoldOut();
424
+ for (let i = 0; i < incrementAmount; i++) {
425
+ cart.incrementToCart(ticket);
426
+ }
427
+ }, [amount, incrementAmount, ticket, onSoldOut, cart, disabled]);
428
+ const decrement = (0, import_react5.useCallback)(() => {
429
+ if (disabled) return;
430
+ for (let i = 0; i < incrementAmount; i++) {
431
+ cart.decrementFromCart({ id: ticket.id });
432
+ }
433
+ }, [cart, ticket.id, incrementAmount, disabled]);
434
+ return (0, import_react5.useMemo)(
435
+ () => ({
436
+ amount,
437
+ isMaxLimitReached: isMaxLimitReached || !!disabled,
438
+ increment,
439
+ decrement,
440
+ disabled: !!disabled
441
+ }),
442
+ [amount, isMaxLimitReached, increment, decrement, disabled]
443
+ );
444
+ }
445
+ // Annotate the CommonJS export names for ESM import in node:
446
+ 0 && (module.exports = {
447
+ Cart,
448
+ CartProvider,
449
+ Coupon,
450
+ GetOrder,
451
+ ListCategories,
452
+ ListEventProducts,
453
+ ListEventTickets,
454
+ ListEvents,
455
+ ListUserEventTickets,
456
+ ListUserEvents,
457
+ ListUserOrders,
458
+ TicketQuantityController,
459
+ useCart,
460
+ useTicketQuantity
461
+ });
@@ -0,0 +1,223 @@
1
+ import { ReactNode } from 'react';
2
+ import * as _meaple_com_types from '@meaple-com/types';
3
+ import { TicketProps, GroupProps as GroupProps$1, CouponProps, GetOrderProps as GetOrderProps$1, CategoryProps, EventProps, UserTicketProps, UserOrderProps } from '@meaple-com/types';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
5
+ import { useCheckCoupon, useOrder, useCategories, useEventProducts, useChannelEvents, useEventTickets, useUserEvents, useUserEventTickets, useUserOrders } from '@meaple-com/react-query';
6
+
7
+ type ItemProps$1 = Pick<TicketProps, 'id' | 'name' | 'price' | 'amount' | 'type'> & {
8
+ group?: Pick<GroupProps$1, 'name'>;
9
+ };
10
+ type PlatformFeeData = {
11
+ fee: number;
12
+ minFeeAmount: number;
13
+ thresholdAmount: number;
14
+ pos?: {
15
+ fee: number;
16
+ minFeeAmount: number;
17
+ thresholdAmount: number;
18
+ };
19
+ };
20
+ type CartProps = {
21
+ children: (props: {
22
+ totalAmount: number;
23
+ totalDiscount: number;
24
+ rawPrice: number;
25
+ rawFeeAmount: number;
26
+ totalFee: number;
27
+ totalPrice: number;
28
+ clearCart: () => void;
29
+ items: ItemProps$1[];
30
+ }) => ReactNode;
31
+ eventId?: string;
32
+ channelId?: string;
33
+ feeType?: 'POS' | 'DIGITAL';
34
+ platformFee?: PlatformFeeData;
35
+ };
36
+ declare const Cart: ({ children, feeType, platformFee, }: CartProps) => ReactNode;
37
+
38
+ type ItemProps = Pick<TicketProps, 'id' | 'name' | 'price' | 'amount' | 'type'> & {
39
+ group?: Pick<GroupProps$1, 'name'>;
40
+ };
41
+ type SeatProps = {
42
+ id: string;
43
+ label: string;
44
+ };
45
+ type MyItemsProps = ItemProps & {
46
+ seats?: SeatProps[];
47
+ };
48
+ type IncrementToCartProps = Omit<ItemProps, 'amount'> & {
49
+ seat?: SeatProps;
50
+ };
51
+ type DecrementToCartProps = Pick<ItemProps, 'id'> & {
52
+ seat?: SeatProps;
53
+ };
54
+ interface CartContextProps {
55
+ children: ReactNode;
56
+ initialCoupon: CouponProps | null;
57
+ }
58
+ interface CartContextData {
59
+ items: MyItemsProps[];
60
+ getItem: (itemId: string) => ItemProps | undefined;
61
+ incrementToCart: (item: IncrementToCartProps) => void;
62
+ decrementFromCart: (item: DecrementToCartProps) => void;
63
+ clearCart: () => void;
64
+ coupon: CouponProps | null;
65
+ computeItemDiscount: (item: Omit<ItemProps, 'name'>) => number;
66
+ applyCoupon: (coupon: CouponProps | null) => void;
67
+ }
68
+ declare const CartProvider: ({ children, initialCoupon }: CartContextProps) => react_jsx_runtime.JSX.Element;
69
+ declare function useCart(): CartContextData;
70
+
71
+ type CouponHeadlessProps = {
72
+ children: (props: ReturnType<typeof mapCouponData>) => ReactNode;
73
+ eventId: string;
74
+ options?: Parameters<typeof useCheckCoupon>[0];
75
+ };
76
+ declare function mapCouponData(cart: ReturnType<typeof useCart>, couponState: {
77
+ isChecking: boolean;
78
+ error: Error | null;
79
+ isSuccess: boolean;
80
+ checkCoupon: (couponCode: string) => Promise<void>;
81
+ clearCoupon: () => void;
82
+ currentCouponCode: string | undefined;
83
+ setCouponCode: (code: string) => void;
84
+ }): {
85
+ coupon: _meaple_com_types.CouponProps | null;
86
+ applyCoupon: (coupon: _meaple_com_types.CouponProps | null) => void;
87
+ isCheckingCoupon: boolean;
88
+ couponError: Error | null;
89
+ isCouponValid: boolean;
90
+ checkCoupon: (couponCode: string) => Promise<void>;
91
+ clearCoupon: () => void;
92
+ currentCouponCode: string | undefined;
93
+ setCouponCode: (code: string) => void;
94
+ };
95
+ declare const Coupon: ({ children, eventId, options }: CouponHeadlessProps) => react_jsx_runtime.JSX.Element;
96
+
97
+ type GetOrderProps = {
98
+ children: (props: {
99
+ order: GetOrderProps$1['order'] | null;
100
+ paidTickets: GetOrderProps$1['paidTickets'] | null;
101
+ paymentIntent: GetOrderProps$1['paymentIntent'];
102
+ isPending: boolean;
103
+ error: Error | null;
104
+ }) => ReactNode;
105
+ orderId: string;
106
+ options?: Parameters<typeof useOrder>[1];
107
+ };
108
+ declare const GetOrder: ({ children, orderId, options }: GetOrderProps) => ReactNode;
109
+
110
+ type ListCategoriesProps = {
111
+ children: (props: {
112
+ categories: CategoryProps[];
113
+ isPending: boolean;
114
+ error: Error | null;
115
+ }) => ReactNode;
116
+ options?: Parameters<typeof useCategories>[0];
117
+ };
118
+ declare const ListCategories: ({ children, options }: ListCategoriesProps) => ReactNode;
119
+
120
+ type ListEventProductsProps = {
121
+ children: (props: {
122
+ products: TicketProps[];
123
+ isPending: boolean;
124
+ error: Error | null;
125
+ }) => ReactNode;
126
+ eventId: string;
127
+ privateToken?: string | null;
128
+ options?: Parameters<typeof useEventProducts>[2];
129
+ };
130
+ declare const ListEventProducts: ({ children, eventId, privateToken, options, }: ListEventProductsProps) => ReactNode;
131
+
132
+ type ListEventsProps = {
133
+ children: (props: {
134
+ events: EventProps[];
135
+ isPending: boolean;
136
+ error: Error | null;
137
+ }) => ReactNode;
138
+ channelId: string;
139
+ options?: Parameters<typeof useChannelEvents>[1];
140
+ };
141
+ declare const ListEvents: ({ children, channelId, options }: ListEventsProps) => ReactNode;
142
+
143
+ type GroupProps = GroupProps$1 & {
144
+ maxBuyAmount?: number;
145
+ };
146
+ type ListEventTicketsProps = {
147
+ children: (props: {
148
+ tickets: TicketProps[];
149
+ groups: GroupProps[];
150
+ isPending: boolean;
151
+ error: Error | null;
152
+ }) => ReactNode;
153
+ eventId: string;
154
+ privateToken?: string | null;
155
+ predecessorIds?: string[];
156
+ options?: Parameters<typeof useEventTickets>[3];
157
+ };
158
+ declare const ListEventTickets: ({ children, eventId, privateToken, predecessorIds, options, }: ListEventTicketsProps) => ReactNode;
159
+
160
+ type SectionType = 'coming_soon' | 'past' | 'awards';
161
+ type ListUserEventsProps = {
162
+ children: (props: {
163
+ events: EventProps[];
164
+ isPending: boolean;
165
+ error: Error | null;
166
+ }) => ReactNode;
167
+ type?: SectionType;
168
+ options?: Parameters<typeof useUserEvents>[1];
169
+ };
170
+ declare const ListUserEvents: ({ children, type, options }: ListUserEventsProps) => ReactNode;
171
+
172
+ type ListUserEventTicketsProps = {
173
+ children: (props: {
174
+ userTickets: UserTicketProps[];
175
+ isPending: boolean;
176
+ error: Error | null;
177
+ }) => ReactNode;
178
+ eventId: string;
179
+ options?: Parameters<typeof useUserEventTickets>[2];
180
+ };
181
+ declare const ListUserEventTickets: ({ children, eventId, options, }: ListUserEventTicketsProps) => ReactNode;
182
+
183
+ type SectionStatus = 'PAID' | 'REFUNDED';
184
+ type ListUserOrdersProps = {
185
+ children: (props: {
186
+ orders: UserOrderProps[];
187
+ isPending: boolean;
188
+ error: Error | null;
189
+ }) => ReactNode;
190
+ status: SectionStatus;
191
+ eventId?: string;
192
+ options?: Parameters<typeof useUserOrders>[1];
193
+ };
194
+ declare const ListUserOrders: ({ children, status, eventId, options, }: ListUserOrdersProps) => ReactNode;
195
+
196
+ type ControllerProps = {
197
+ ticket: Pick<TicketProps, 'id' | 'name' | 'price' | 'type' | 'minBuy' | 'maxBuy' | 'availableAmount'>;
198
+ disabled?: boolean;
199
+ onSoldOut?: () => void;
200
+ children: (props: {
201
+ amount: number;
202
+ isMaxLimitReached: boolean;
203
+ increment: () => void;
204
+ decrement: () => void;
205
+ disabled: boolean;
206
+ }) => ReactNode;
207
+ };
208
+ declare const TicketQuantityController: ({ ticket, onSoldOut, children, }: ControllerProps) => ReactNode;
209
+
210
+ type UseTicketQuantityParams = {
211
+ ticket: Pick<TicketProps, 'id' | 'name' | 'price' | 'type' | 'minBuy' | 'maxBuy' | 'availableAmount'>;
212
+ disabled?: boolean;
213
+ onSoldOut?: () => void;
214
+ };
215
+ declare function useTicketQuantity({ ticket, disabled, onSoldOut, }: UseTicketQuantityParams): {
216
+ amount: number;
217
+ isMaxLimitReached: boolean;
218
+ increment: () => void;
219
+ decrement: () => void;
220
+ disabled: boolean;
221
+ };
222
+
223
+ export { Cart, type CartContextData, type CartProps, CartProvider, Coupon, GetOrder, ListCategories, ListEventProducts, ListEventTickets, ListEvents, ListUserEventTickets, ListUserEvents, ListUserOrders, type PlatformFeeData, TicketQuantityController, useCart, useTicketQuantity };
@@ -0,0 +1,223 @@
1
+ import { ReactNode } from 'react';
2
+ import * as _meaple_com_types from '@meaple-com/types';
3
+ import { TicketProps, GroupProps as GroupProps$1, CouponProps, GetOrderProps as GetOrderProps$1, CategoryProps, EventProps, UserTicketProps, UserOrderProps } from '@meaple-com/types';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
5
+ import { useCheckCoupon, useOrder, useCategories, useEventProducts, useChannelEvents, useEventTickets, useUserEvents, useUserEventTickets, useUserOrders } from '@meaple-com/react-query';
6
+
7
+ type ItemProps$1 = Pick<TicketProps, 'id' | 'name' | 'price' | 'amount' | 'type'> & {
8
+ group?: Pick<GroupProps$1, 'name'>;
9
+ };
10
+ type PlatformFeeData = {
11
+ fee: number;
12
+ minFeeAmount: number;
13
+ thresholdAmount: number;
14
+ pos?: {
15
+ fee: number;
16
+ minFeeAmount: number;
17
+ thresholdAmount: number;
18
+ };
19
+ };
20
+ type CartProps = {
21
+ children: (props: {
22
+ totalAmount: number;
23
+ totalDiscount: number;
24
+ rawPrice: number;
25
+ rawFeeAmount: number;
26
+ totalFee: number;
27
+ totalPrice: number;
28
+ clearCart: () => void;
29
+ items: ItemProps$1[];
30
+ }) => ReactNode;
31
+ eventId?: string;
32
+ channelId?: string;
33
+ feeType?: 'POS' | 'DIGITAL';
34
+ platformFee?: PlatformFeeData;
35
+ };
36
+ declare const Cart: ({ children, feeType, platformFee, }: CartProps) => ReactNode;
37
+
38
+ type ItemProps = Pick<TicketProps, 'id' | 'name' | 'price' | 'amount' | 'type'> & {
39
+ group?: Pick<GroupProps$1, 'name'>;
40
+ };
41
+ type SeatProps = {
42
+ id: string;
43
+ label: string;
44
+ };
45
+ type MyItemsProps = ItemProps & {
46
+ seats?: SeatProps[];
47
+ };
48
+ type IncrementToCartProps = Omit<ItemProps, 'amount'> & {
49
+ seat?: SeatProps;
50
+ };
51
+ type DecrementToCartProps = Pick<ItemProps, 'id'> & {
52
+ seat?: SeatProps;
53
+ };
54
+ interface CartContextProps {
55
+ children: ReactNode;
56
+ initialCoupon: CouponProps | null;
57
+ }
58
+ interface CartContextData {
59
+ items: MyItemsProps[];
60
+ getItem: (itemId: string) => ItemProps | undefined;
61
+ incrementToCart: (item: IncrementToCartProps) => void;
62
+ decrementFromCart: (item: DecrementToCartProps) => void;
63
+ clearCart: () => void;
64
+ coupon: CouponProps | null;
65
+ computeItemDiscount: (item: Omit<ItemProps, 'name'>) => number;
66
+ applyCoupon: (coupon: CouponProps | null) => void;
67
+ }
68
+ declare const CartProvider: ({ children, initialCoupon }: CartContextProps) => react_jsx_runtime.JSX.Element;
69
+ declare function useCart(): CartContextData;
70
+
71
+ type CouponHeadlessProps = {
72
+ children: (props: ReturnType<typeof mapCouponData>) => ReactNode;
73
+ eventId: string;
74
+ options?: Parameters<typeof useCheckCoupon>[0];
75
+ };
76
+ declare function mapCouponData(cart: ReturnType<typeof useCart>, couponState: {
77
+ isChecking: boolean;
78
+ error: Error | null;
79
+ isSuccess: boolean;
80
+ checkCoupon: (couponCode: string) => Promise<void>;
81
+ clearCoupon: () => void;
82
+ currentCouponCode: string | undefined;
83
+ setCouponCode: (code: string) => void;
84
+ }): {
85
+ coupon: _meaple_com_types.CouponProps | null;
86
+ applyCoupon: (coupon: _meaple_com_types.CouponProps | null) => void;
87
+ isCheckingCoupon: boolean;
88
+ couponError: Error | null;
89
+ isCouponValid: boolean;
90
+ checkCoupon: (couponCode: string) => Promise<void>;
91
+ clearCoupon: () => void;
92
+ currentCouponCode: string | undefined;
93
+ setCouponCode: (code: string) => void;
94
+ };
95
+ declare const Coupon: ({ children, eventId, options }: CouponHeadlessProps) => react_jsx_runtime.JSX.Element;
96
+
97
+ type GetOrderProps = {
98
+ children: (props: {
99
+ order: GetOrderProps$1['order'] | null;
100
+ paidTickets: GetOrderProps$1['paidTickets'] | null;
101
+ paymentIntent: GetOrderProps$1['paymentIntent'];
102
+ isPending: boolean;
103
+ error: Error | null;
104
+ }) => ReactNode;
105
+ orderId: string;
106
+ options?: Parameters<typeof useOrder>[1];
107
+ };
108
+ declare const GetOrder: ({ children, orderId, options }: GetOrderProps) => ReactNode;
109
+
110
+ type ListCategoriesProps = {
111
+ children: (props: {
112
+ categories: CategoryProps[];
113
+ isPending: boolean;
114
+ error: Error | null;
115
+ }) => ReactNode;
116
+ options?: Parameters<typeof useCategories>[0];
117
+ };
118
+ declare const ListCategories: ({ children, options }: ListCategoriesProps) => ReactNode;
119
+
120
+ type ListEventProductsProps = {
121
+ children: (props: {
122
+ products: TicketProps[];
123
+ isPending: boolean;
124
+ error: Error | null;
125
+ }) => ReactNode;
126
+ eventId: string;
127
+ privateToken?: string | null;
128
+ options?: Parameters<typeof useEventProducts>[2];
129
+ };
130
+ declare const ListEventProducts: ({ children, eventId, privateToken, options, }: ListEventProductsProps) => ReactNode;
131
+
132
+ type ListEventsProps = {
133
+ children: (props: {
134
+ events: EventProps[];
135
+ isPending: boolean;
136
+ error: Error | null;
137
+ }) => ReactNode;
138
+ channelId: string;
139
+ options?: Parameters<typeof useChannelEvents>[1];
140
+ };
141
+ declare const ListEvents: ({ children, channelId, options }: ListEventsProps) => ReactNode;
142
+
143
+ type GroupProps = GroupProps$1 & {
144
+ maxBuyAmount?: number;
145
+ };
146
+ type ListEventTicketsProps = {
147
+ children: (props: {
148
+ tickets: TicketProps[];
149
+ groups: GroupProps[];
150
+ isPending: boolean;
151
+ error: Error | null;
152
+ }) => ReactNode;
153
+ eventId: string;
154
+ privateToken?: string | null;
155
+ predecessorIds?: string[];
156
+ options?: Parameters<typeof useEventTickets>[3];
157
+ };
158
+ declare const ListEventTickets: ({ children, eventId, privateToken, predecessorIds, options, }: ListEventTicketsProps) => ReactNode;
159
+
160
+ type SectionType = 'coming_soon' | 'past' | 'awards';
161
+ type ListUserEventsProps = {
162
+ children: (props: {
163
+ events: EventProps[];
164
+ isPending: boolean;
165
+ error: Error | null;
166
+ }) => ReactNode;
167
+ type?: SectionType;
168
+ options?: Parameters<typeof useUserEvents>[1];
169
+ };
170
+ declare const ListUserEvents: ({ children, type, options }: ListUserEventsProps) => ReactNode;
171
+
172
+ type ListUserEventTicketsProps = {
173
+ children: (props: {
174
+ userTickets: UserTicketProps[];
175
+ isPending: boolean;
176
+ error: Error | null;
177
+ }) => ReactNode;
178
+ eventId: string;
179
+ options?: Parameters<typeof useUserEventTickets>[2];
180
+ };
181
+ declare const ListUserEventTickets: ({ children, eventId, options, }: ListUserEventTicketsProps) => ReactNode;
182
+
183
+ type SectionStatus = 'PAID' | 'REFUNDED';
184
+ type ListUserOrdersProps = {
185
+ children: (props: {
186
+ orders: UserOrderProps[];
187
+ isPending: boolean;
188
+ error: Error | null;
189
+ }) => ReactNode;
190
+ status: SectionStatus;
191
+ eventId?: string;
192
+ options?: Parameters<typeof useUserOrders>[1];
193
+ };
194
+ declare const ListUserOrders: ({ children, status, eventId, options, }: ListUserOrdersProps) => ReactNode;
195
+
196
+ type ControllerProps = {
197
+ ticket: Pick<TicketProps, 'id' | 'name' | 'price' | 'type' | 'minBuy' | 'maxBuy' | 'availableAmount'>;
198
+ disabled?: boolean;
199
+ onSoldOut?: () => void;
200
+ children: (props: {
201
+ amount: number;
202
+ isMaxLimitReached: boolean;
203
+ increment: () => void;
204
+ decrement: () => void;
205
+ disabled: boolean;
206
+ }) => ReactNode;
207
+ };
208
+ declare const TicketQuantityController: ({ ticket, onSoldOut, children, }: ControllerProps) => ReactNode;
209
+
210
+ type UseTicketQuantityParams = {
211
+ ticket: Pick<TicketProps, 'id' | 'name' | 'price' | 'type' | 'minBuy' | 'maxBuy' | 'availableAmount'>;
212
+ disabled?: boolean;
213
+ onSoldOut?: () => void;
214
+ };
215
+ declare function useTicketQuantity({ ticket, disabled, onSoldOut, }: UseTicketQuantityParams): {
216
+ amount: number;
217
+ isMaxLimitReached: boolean;
218
+ increment: () => void;
219
+ decrement: () => void;
220
+ disabled: boolean;
221
+ };
222
+
223
+ export { Cart, type CartContextData, type CartProps, CartProvider, Coupon, GetOrder, ListCategories, ListEventProducts, ListEventTickets, ListEvents, ListUserEventTickets, ListUserEvents, ListUserOrders, type PlatformFeeData, TicketQuantityController, useCart, useTicketQuantity };
package/dist/index.js ADDED
@@ -0,0 +1,426 @@
1
+ // src/components/Cart.tsx
2
+ import { useMemo } from "react";
3
+
4
+ // src/contexts/CartContext.tsx
5
+ import {
6
+ createContext,
7
+ useCallback,
8
+ useContext,
9
+ useState
10
+ } from "react";
11
+ import { jsx } from "react/jsx-runtime";
12
+ var CartContext = createContext({});
13
+ var CartProvider = ({ children, initialCoupon }) => {
14
+ const [items, setItems] = useState([]);
15
+ const [coupon, setCoupon] = useState(initialCoupon);
16
+ const incrementToCart = useCallback((item) => {
17
+ setItems((prevItems) => {
18
+ const itemExists = prevItems.find((prevItem) => prevItem.id === item.id);
19
+ if (!itemExists)
20
+ return [
21
+ ...prevItems,
22
+ {
23
+ ...item,
24
+ amount: 1,
25
+ seats: item.seat ? [item.seat] : void 0
26
+ }
27
+ ];
28
+ return prevItems.map((prevItem) => {
29
+ if (prevItem.id === item.id) {
30
+ return {
31
+ ...prevItem,
32
+ amount: prevItem.amount + 1,
33
+ seats: item.seat ? [...prevItem.seats ?? [], item.seat] : prevItem.seats
34
+ };
35
+ }
36
+ return prevItem;
37
+ });
38
+ });
39
+ }, []);
40
+ const decrementFromCart = useCallback((item) => {
41
+ setItems((prevItems) => {
42
+ return prevItems.map((prevItem) => {
43
+ if (prevItem.id === item.id) {
44
+ return {
45
+ ...prevItem,
46
+ amount: prevItem.amount - 1,
47
+ seats: prevItem.seats ? prevItem.seats.filter((seat) => seat.id !== item.seat?.id) : prevItem.seats
48
+ };
49
+ }
50
+ return prevItem;
51
+ }).filter((prevItem) => prevItem.amount > 0);
52
+ });
53
+ }, []);
54
+ const getItem = useCallback(
55
+ (itemId) => {
56
+ return items.find((item) => item.id === itemId);
57
+ },
58
+ [items]
59
+ );
60
+ const clearCart = useCallback(() => {
61
+ setItems([]);
62
+ }, []);
63
+ const applyCoupon = useCallback((coupon2) => {
64
+ setCoupon(coupon2);
65
+ }, []);
66
+ const computeItemDiscount = useCallback(
67
+ (item) => {
68
+ if (!coupon) return 0;
69
+ if (coupon.ticketIds.length > 0 && !coupon.ticketIds.includes(item.id))
70
+ return 0;
71
+ if (coupon.type === `PERCENTAGE`)
72
+ return item.amount * item.price * (coupon.value / 100);
73
+ return item.amount * coupon.value;
74
+ },
75
+ [coupon]
76
+ );
77
+ return /* @__PURE__ */ jsx(
78
+ CartContext.Provider,
79
+ {
80
+ value: {
81
+ items,
82
+ getItem,
83
+ incrementToCart,
84
+ decrementFromCart,
85
+ clearCart,
86
+ coupon,
87
+ computeItemDiscount,
88
+ applyCoupon
89
+ },
90
+ children
91
+ }
92
+ );
93
+ };
94
+ function useCart() {
95
+ const context = useContext(CartContext);
96
+ if (!context) {
97
+ throw new Error(`useCart must be used within a CartProvider`);
98
+ }
99
+ return context;
100
+ }
101
+
102
+ // src/components/Cart.tsx
103
+ var Cart = ({
104
+ children,
105
+ feeType = `DIGITAL`,
106
+ platformFee
107
+ }) => {
108
+ const cart = useCart();
109
+ const totalAmount = useMemo(
110
+ () => cart.items.reduce((acc, item) => acc + item.amount, 0),
111
+ [cart.items]
112
+ );
113
+ const totalDiscount = useMemo(() => {
114
+ return cart.items.reduce(
115
+ (acc, item) => acc + Math.min(cart.computeItemDiscount(item), item.price * item.amount),
116
+ 0
117
+ );
118
+ }, [cart]);
119
+ const rawPrice = useMemo(() => {
120
+ return cart.items.reduce((acc, item) => {
121
+ return acc + item.price * item.amount;
122
+ }, 0);
123
+ }, [cart.items]);
124
+ const rawFeeAmount = useMemo(() => {
125
+ if (!platformFee) return 0;
126
+ const fee = feeType === `POS` && platformFee.pos ? platformFee.pos.fee : platformFee.fee;
127
+ return cart.items.reduce(
128
+ (acc, item) => acc + item.price * item.amount * fee,
129
+ 0
130
+ );
131
+ }, [platformFee, cart.items, feeType]);
132
+ const totalFee = useMemo(() => {
133
+ if (!platformFee) return 0;
134
+ const { fee, minFeeAmount, thresholdAmount } = feeType === `POS` && platformFee.pos ? platformFee.pos : platformFee;
135
+ if (fee === 0) return 0;
136
+ if (rawFeeAmount <= 0) return 0;
137
+ if (rawFeeAmount < minFeeAmount && rawPrice < thresholdAmount) {
138
+ return minFeeAmount;
139
+ }
140
+ return rawFeeAmount;
141
+ }, [feeType, platformFee, rawFeeAmount, rawPrice]);
142
+ const totalPrice = Math.max(rawPrice - totalDiscount, 0) + totalFee;
143
+ return children({
144
+ totalAmount,
145
+ totalDiscount,
146
+ rawPrice,
147
+ rawFeeAmount,
148
+ totalFee,
149
+ totalPrice,
150
+ items: cart.items,
151
+ clearCart: cart.clearCart
152
+ });
153
+ };
154
+
155
+ // src/components/Coupon.tsx
156
+ import { useCallback as useCallback2, useState as useState2 } from "react";
157
+ import { useCheckCoupon } from "@meaple-com/react-query";
158
+ import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
159
+ function mapCouponData(cart, couponState) {
160
+ const { coupon, applyCoupon } = cart;
161
+ return {
162
+ coupon,
163
+ applyCoupon,
164
+ // Cupom functions
165
+ isCheckingCoupon: couponState.isChecking,
166
+ couponError: couponState.error,
167
+ isCouponValid: couponState.isSuccess,
168
+ checkCoupon: couponState.checkCoupon,
169
+ clearCoupon: couponState.clearCoupon,
170
+ currentCouponCode: couponState.currentCouponCode,
171
+ setCouponCode: couponState.setCouponCode
172
+ };
173
+ }
174
+ var Coupon = ({ children, eventId, options }) => {
175
+ const cart = useCart();
176
+ const { mutateAsync: checkCouponFn, ...checkCoupon } = useCheckCoupon(options);
177
+ const [currentCouponCode, setCurrentCouponCode] = useState2(cart.coupon?.code);
178
+ const handleCheckCoupon = useCallback2(
179
+ async (couponCode) => {
180
+ try {
181
+ const data2 = await checkCouponFn({ eventId, couponCode });
182
+ console.log("data", data2);
183
+ console.log(typeof data2.ticketIds);
184
+ cart.applyCoupon(data2);
185
+ setCurrentCouponCode(couponCode);
186
+ } catch (err) {
187
+ }
188
+ },
189
+ [cart, checkCouponFn, eventId]
190
+ );
191
+ const handleClearCoupon = useCallback2(() => {
192
+ setCurrentCouponCode(``);
193
+ cart.applyCoupon(null);
194
+ }, [cart]);
195
+ const couponState = {
196
+ isChecking: checkCoupon.isPending,
197
+ error: checkCoupon.error,
198
+ isSuccess: checkCoupon.isSuccess,
199
+ checkCoupon: handleCheckCoupon,
200
+ clearCoupon: handleClearCoupon,
201
+ currentCouponCode,
202
+ setCouponCode: setCurrentCouponCode
203
+ };
204
+ const data = mapCouponData(cart, couponState);
205
+ return /* @__PURE__ */ jsx2(Fragment, { children: children(data) });
206
+ };
207
+
208
+ // src/components/GetOrder.tsx
209
+ import { useOrder } from "@meaple-com/react-query";
210
+ var GetOrder = ({ children, orderId, options }) => {
211
+ const { data, isPending, error } = useOrder(orderId, options);
212
+ return children({
213
+ order: data?.order ?? null,
214
+ paidTickets: data?.paidTickets ?? null,
215
+ paymentIntent: data?.paymentIntent,
216
+ isPending,
217
+ error
218
+ });
219
+ };
220
+
221
+ // src/components/ListCategories.tsx
222
+ import { useCategories } from "@meaple-com/react-query";
223
+ var ListCategories = ({ children, options }) => {
224
+ const { data, isPending, error } = useCategories(options);
225
+ return children({
226
+ categories: data ?? [],
227
+ isPending,
228
+ error
229
+ });
230
+ };
231
+
232
+ // src/components/ListEventProducts.tsx
233
+ import { useEventProducts } from "@meaple-com/react-query";
234
+ var ListEventProducts = ({
235
+ children,
236
+ eventId,
237
+ privateToken,
238
+ options
239
+ }) => {
240
+ const { data, isPending, error } = useEventProducts(
241
+ eventId,
242
+ privateToken,
243
+ options
244
+ );
245
+ return children({
246
+ products: data?.products ?? [],
247
+ isPending,
248
+ error
249
+ });
250
+ };
251
+
252
+ // src/components/ListEvents.tsx
253
+ import { useChannelEvents } from "@meaple-com/react-query";
254
+ var ListEvents = ({ children, channelId, options }) => {
255
+ const { data, isPending, error } = useChannelEvents({ channelId }, options);
256
+ return children({
257
+ events: data ?? [],
258
+ isPending,
259
+ error
260
+ });
261
+ };
262
+
263
+ // src/components/ListEventTickets.tsx
264
+ import { useEventTickets } from "@meaple-com/react-query";
265
+ var ListEventTickets = ({
266
+ children,
267
+ eventId,
268
+ privateToken,
269
+ predecessorIds,
270
+ options
271
+ }) => {
272
+ const { data, isPending, error } = useEventTickets(
273
+ eventId,
274
+ privateToken,
275
+ predecessorIds,
276
+ options
277
+ );
278
+ return children({
279
+ tickets: data?.tickets ?? [],
280
+ groups: data?.groups ?? [],
281
+ isPending,
282
+ error
283
+ });
284
+ };
285
+
286
+ // src/components/ListUserEvents.tsx
287
+ import { useUserEvents } from "@meaple-com/react-query";
288
+ var ListUserEvents = ({ children, type, options }) => {
289
+ const { data, isPending, error } = useUserEvents(
290
+ {
291
+ type: type ?? "coming_soon"
292
+ },
293
+ options
294
+ );
295
+ const events = Array.isArray(data) ? data : [];
296
+ return children({ events, isPending, error });
297
+ };
298
+
299
+ // src/components/ListUserEventTickets.tsx
300
+ import { useUserEventTickets } from "@meaple-com/react-query";
301
+ var ListUserEventTickets = ({
302
+ children,
303
+ eventId,
304
+ options
305
+ }) => {
306
+ const { data, isPending, error } = useUserEventTickets(
307
+ eventId,
308
+ void 0,
309
+ options
310
+ );
311
+ return children({
312
+ userTickets: data?.userTickets ?? [],
313
+ isPending,
314
+ error
315
+ });
316
+ };
317
+
318
+ // src/components/ListUserOrders.tsx
319
+ import { useUserOrders } from "@meaple-com/react-query";
320
+ var ListUserOrders = ({
321
+ children,
322
+ status,
323
+ eventId,
324
+ options
325
+ }) => {
326
+ const { data, isPending, error } = useUserOrders(
327
+ { status, eventId },
328
+ options
329
+ );
330
+ return children({
331
+ orders: data ?? [],
332
+ isPending,
333
+ error
334
+ });
335
+ };
336
+
337
+ // src/components/TicketQuantityController.tsx
338
+ import { useCallback as useCallback3 } from "react";
339
+ var TicketQuantityController = ({
340
+ ticket,
341
+ onSoldOut,
342
+ children
343
+ }) => {
344
+ const cart = useCart();
345
+ const item = cart.getItem(ticket.id);
346
+ const amount = item?.amount ?? 0;
347
+ const incrementAmount = ticket.minBuy ?? 1;
348
+ const isMaxLimitReached = amount + incrementAmount > (ticket.maxBuy ?? Infinity);
349
+ const eventMaxBuy = ticket.maxBuy ?? Infinity;
350
+ const disabled = ticket.availableAmount === 0 || eventMaxBuy === 0;
351
+ const increment = useCallback3(() => {
352
+ if (disabled) return;
353
+ if (amount + incrementAmount >= ticket.availableAmount && onSoldOut)
354
+ onSoldOut();
355
+ for (let i = 0; i < incrementAmount; i++) {
356
+ cart.incrementToCart(ticket);
357
+ }
358
+ }, [amount, incrementAmount, ticket, onSoldOut, cart, disabled]);
359
+ const decrement = useCallback3(() => {
360
+ if (disabled) return;
361
+ for (let i = 0; i < incrementAmount; i++) {
362
+ cart.decrementFromCart({ id: ticket.id });
363
+ }
364
+ }, [cart, ticket.id, incrementAmount, disabled]);
365
+ return children({
366
+ amount,
367
+ isMaxLimitReached: isMaxLimitReached || !!disabled,
368
+ increment,
369
+ decrement,
370
+ disabled
371
+ });
372
+ };
373
+
374
+ // src/hooks/useTicketQuantity.ts
375
+ import { useCallback as useCallback4, useMemo as useMemo2 } from "react";
376
+ function useTicketQuantity({
377
+ ticket,
378
+ disabled,
379
+ onSoldOut
380
+ }) {
381
+ const cart = useCart();
382
+ const item = cart.getItem(ticket.id);
383
+ const amount = item?.amount ?? 0;
384
+ const incrementAmount = ticket.minBuy ?? 1;
385
+ const isMaxLimitReached = amount + incrementAmount > (ticket.maxBuy ?? Infinity);
386
+ const increment = useCallback4(() => {
387
+ if (disabled) return;
388
+ if (amount + incrementAmount >= ticket.availableAmount && onSoldOut)
389
+ onSoldOut();
390
+ for (let i = 0; i < incrementAmount; i++) {
391
+ cart.incrementToCart(ticket);
392
+ }
393
+ }, [amount, incrementAmount, ticket, onSoldOut, cart, disabled]);
394
+ const decrement = useCallback4(() => {
395
+ if (disabled) return;
396
+ for (let i = 0; i < incrementAmount; i++) {
397
+ cart.decrementFromCart({ id: ticket.id });
398
+ }
399
+ }, [cart, ticket.id, incrementAmount, disabled]);
400
+ return useMemo2(
401
+ () => ({
402
+ amount,
403
+ isMaxLimitReached: isMaxLimitReached || !!disabled,
404
+ increment,
405
+ decrement,
406
+ disabled: !!disabled
407
+ }),
408
+ [amount, isMaxLimitReached, increment, decrement, disabled]
409
+ );
410
+ }
411
+ export {
412
+ Cart,
413
+ CartProvider,
414
+ Coupon,
415
+ GetOrder,
416
+ ListCategories,
417
+ ListEventProducts,
418
+ ListEventTickets,
419
+ ListEvents,
420
+ ListUserEventTickets,
421
+ ListUserEvents,
422
+ ListUserOrders,
423
+ TicketQuantityController,
424
+ useCart,
425
+ useTicketQuantity
426
+ };
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@meaple-com/react-headless-components",
3
+ "version": "1.0.0",
4
+ "description": "Headless React components for Meaple SDK",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "license": "MIT",
18
+ "publishConfig": {
19
+ "access": "public",
20
+ "registry": "https://registry.npmjs.org/"
21
+ },
22
+ "scripts": {
23
+ "build": "tsup",
24
+ "build:packages": "tsup",
25
+ "dev": "tsup --watch",
26
+ "lint": "eslint \"src/**/*.{ts,tsx}\"",
27
+ "lint:fix": "eslint --fix \"src/**/*.{ts,tsx}\"",
28
+ "clean": "rimraf dist"
29
+ },
30
+ "dependencies": {
31
+ "@meaple-com/types": "workspace:*"
32
+ },
33
+ "devDependencies": {
34
+ "@eslint/js": "^9.36.0",
35
+ "@meaple-com/react-query": "workspace:*",
36
+ "@types/react": "^19.0.0",
37
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
38
+ "@typescript-eslint/parser": "^7.18.0",
39
+ "eslint": "^9.36.0",
40
+ "globals": "^16.4.0",
41
+ "tsup": "^8.0.0",
42
+ "typescript": "^5.0.0",
43
+ "typescript-eslint": "^8.44.1",
44
+ "rimraf": "^5.0.5"
45
+ },
46
+ "peerDependencies": {
47
+ "@meaple-com/react-query": "^1.0.0",
48
+ "react": "^19.0.0"
49
+ },
50
+ "files": [
51
+ "dist"
52
+ ]
53
+ }