@bunnyapp/components 1.8.0-beta.12 → 1.8.0-beta.14

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/cjs/index.js CHANGED
@@ -1219,6 +1219,11 @@ const QueryKeyFactory = {
1219
1219
  entityId,
1220
1220
  ...(token ? [token] : []),
1221
1221
  ],
1222
+ quotesKey: (filter, token) => [
1223
+ 'quotes',
1224
+ ...(filter ? [filter] : []),
1225
+ ...(token ? [token] : []),
1226
+ ],
1222
1227
  createFormattedInvoiceKey: ({ id, token }) => [
1223
1228
  'formattedInvoice',
1224
1229
  id,
@@ -1283,7 +1288,7 @@ const DEFAULT_CONFIG = {
1283
1288
  };
1284
1289
 
1285
1290
  // This will be replaced at build time by rollup-plugin-replace
1286
- const PACKAGE_VERSION = '1.8.0-beta.11';
1291
+ const PACKAGE_VERSION = '1.8.0-beta.13';
1287
1292
  const createRequestHeaders = (token) => {
1288
1293
  const headers = createClientDevHeaders({ token });
1289
1294
  // Add the components version header
@@ -20561,6 +20566,8 @@ function PaymentProvider({ children, quote: maskedQuote, invoice: maskedInvoice,
20561
20566
  const invoice = readFragment(PaymentProvider_InvoiceFragment, maskedInvoice);
20562
20567
  // State
20563
20568
  const [isPaid, setIsPaid] = react.useState(false);
20569
+ const [isPaying, setIsPaying] = react.useState(false);
20570
+ const [isApprovingHold, setIsApprovingHold] = react.useState(false);
20564
20571
  const getAmountDue = () => {
20565
20572
  return quote ? getQuoteAmountDue(quote) : invoice === null || invoice === void 0 ? void 0 : invoice.amountDue;
20566
20573
  };
@@ -20596,7 +20603,11 @@ function PaymentProvider({ children, quote: maskedQuote, invoice: maskedInvoice,
20596
20603
  amountDue: amountDue !== null && amountDue !== void 0 ? amountDue : undefined,
20597
20604
  formattedAmountDue: formattedAmountDueValue,
20598
20605
  isPaid,
20599
- setIsPaid
20606
+ setIsPaid,
20607
+ isPaying,
20608
+ setIsPaying,
20609
+ isApprovingHold,
20610
+ setIsApprovingHold,
20600
20611
  }, children: children }));
20601
20612
  }
20602
20613
 
@@ -21100,7 +21111,7 @@ function Pay(props = {}) {
21100
21111
  const isMobile = useIsMobile();
21101
21112
  const { onPaymentSuccess, onPaymentHoldSuccess, onSavePaymentMethod, paymentHoldPrecondition } = usePaymentFormCallbacks();
21102
21113
  const selectedPlugin = useSelectedPlugin();
21103
- const { quoteId, invoiceId, paymentHold, paymentType, setIsPaid } = usePayable();
21114
+ const { quoteId, invoiceId, paymentHold, paymentType, setIsPaid, setIsPaying, setIsApprovingHold } = usePayable();
21104
21115
  const accountId = useAccountId();
21105
21116
  const { defaultPaymentMethod } = usePaymentMethod({ accountId });
21106
21117
  const [showPaymentDetailsForm, setShowPaymentDetailsForm] = useShowPaymentDetails();
@@ -21175,6 +21186,14 @@ function Pay(props = {}) {
21175
21186
  return;
21176
21187
  }
21177
21188
  }
21189
+ react.useEffect(() => {
21190
+ setIsPaying(isPaying);
21191
+ return () => setIsPaying(false);
21192
+ }, [isPaying, setIsPaying]);
21193
+ react.useEffect(() => {
21194
+ setIsApprovingHold(isApprovingHold);
21195
+ return () => setIsApprovingHold(false);
21196
+ }, [isApprovingHold, setIsApprovingHold]);
21178
21197
  return (jsxRuntime.jsx(antd.Button, { className: "bunny-w-full", disabled: isPaying || isApprovingHold || isSaving || disabled, loading: isPaying || isApprovingHold || isSaving, onClick: handlePayment, size: isMobile ? 'large' : 'middle', type: "primary", children: paymentButtonText }));
21179
21198
  }
21180
21199
 
@@ -21331,6 +21350,7 @@ function PaymentMethodDetailsRoot(props = {}) {
21331
21350
  const accountId = useAccountId();
21332
21351
  const { paymentMethods } = usePaymentMethod({ accountId });
21333
21352
  const { paymentPlugins } = usePaymentPlugins(accountId);
21353
+ const { isPaying, isApprovingHold } = usePayable();
21334
21354
  function handleClickAddPaymentMethod() {
21335
21355
  if ((paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.length) === 0) {
21336
21356
  showErrorNotification$6('No payment plugins available', 'Error adding payment method');
@@ -21349,7 +21369,7 @@ function PaymentMethodDetailsRoot(props = {}) {
21349
21369
  {
21350
21370
  key: '1',
21351
21371
  showArrow: false,
21352
- label: !showPaymentMethodForm ? (jsxRuntime.jsx("div", { className: "bunny-pt-2", children: jsxRuntime.jsx(antd.Button, { onClick: handleClickAddPaymentMethod, type: "default", className: "bunny-w-full", id: "addPaymentMethod", children: "Add payment method" }) })) : null,
21372
+ label: !showPaymentMethodForm ? (jsxRuntime.jsx("div", { className: "bunny-pt-2", children: jsxRuntime.jsx(antd.Button, { onClick: handleClickAddPaymentMethod, type: "default", className: "bunny-w-full", id: "addPaymentMethod", disabled: isPaying || isApprovingHold, children: "Add payment method" }) })) : null,
21353
21373
  children: (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-mt-2", children: [jsxRuntime.jsx(PaymentMethodSelector, {}), selectedPlugin && (jsxRuntime.jsx("div", { className: "bunny-flex bunny-flex-col", children: getPaymentMethodForm((_b = (_a = selectedPlugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0].name) })), footer] })),
21354
21374
  },
21355
21375
  ] }) }));
@@ -22150,6 +22170,7 @@ const QuoteButtons_FormattedQuoteFragment = t(`
22150
22170
  currency
22151
22171
  amount
22152
22172
  expiresAt
22173
+ state
22153
22174
  }
22154
22175
  `);
22155
22176
  const PaymentHoldDisplay_QuoteButtonsFragment = t(`
@@ -22166,10 +22187,11 @@ function QuoteButtons({ isAccepted, formattedQuote: maskedFormattedQuote, isMobi
22166
22187
  const { secondaryColor } = useBrand();
22167
22188
  const downloadFile = useDownloadFile(id);
22168
22189
  const isExpired = useIsExpired(formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.expiresAt);
22190
+ const isRejected = (formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.state) === 'REJECTED';
22169
22191
  const signingPlugins = useSigningPlugins({ apiHost, token });
22170
22192
  return (jsxRuntime.jsxs("div", { className: "flex flex-row justify-end items-center gap-4", id: "acceptance", style: {
22171
22193
  color: secondaryColor,
22172
- }, children: [isAccepted && formattedQuote.acceptedAt ? (jsxRuntime.jsx(Text$y, { children: `Quote was accepted by ${formattedQuote.acceptedByName} on ${formatDate(formattedQuote.acceptedAt)}` })) : null, (!isMobile || !isAccepted) && (jsxRuntime.jsxs("div", { className: isMobile ? 'flex w-full justify-end gap-2' : 'flex items-center justify-end gap-2', children: [paymentHold ? (jsxRuntime.jsx(PaymentHoldDisplay, { paymentHold: paymentHold, currency: formattedQuote.currency, amount: formattedQuote.amount })) : null, !isMobile && !hideDownloadButton ? (jsxRuntime.jsx(antd.Button, { icon: jsxRuntime.jsx(icons.DownloadOutlined, {}), onClick: () => downloadFile(apiHost + '/api/pdf/quote', token), children: "Download" })) : null, shouldDoPaymentHold && !paymentHoldCompleted ? (jsxRuntime.jsx(antd.Button, { disabled: isExpired, onClick: () => setPaymentHoldModalVisible(true), type: "primary", loading: isSendAcceptPending, children: "Pay and sign" })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: !isAccepted ? (jsxRuntime.jsx(antd.Button, { disabled: isExpired || isAccepting, onClick: handleClickAccept, type: "primary", children: isExpired
22194
+ }, children: [isAccepted && formattedQuote.acceptedAt ? (jsxRuntime.jsx(Text$y, { children: `Quote was accepted by ${formattedQuote.acceptedByName} on ${formatDate(formattedQuote.acceptedAt)}` })) : null, (!isMobile || !isAccepted) && (jsxRuntime.jsxs("div", { className: isMobile ? 'flex w-full justify-end gap-2' : 'flex items-center justify-end gap-2', children: [paymentHold ? (jsxRuntime.jsx(PaymentHoldDisplay, { paymentHold: paymentHold, currency: formattedQuote.currency, amount: formattedQuote.amount })) : null, !isMobile && !hideDownloadButton ? (jsxRuntime.jsx(antd.Button, { icon: jsxRuntime.jsx(icons.DownloadOutlined, {}), onClick: () => downloadFile(apiHost + '/api/pdf/quote', token), children: "Download" })) : null, shouldDoPaymentHold && !paymentHoldCompleted ? (jsxRuntime.jsx(antd.Button, { disabled: isExpired, onClick: () => setPaymentHoldModalVisible(true), type: "primary", loading: isSendAcceptPending, children: "Pay and sign" })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: !isAccepted && !isRejected ? (jsxRuntime.jsx(antd.Button, { disabled: isExpired || isAccepting, onClick: handleClickAccept, type: "primary", children: isExpired
22173
22195
  ? 'Quote is expired'
22174
22196
  : (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length)
22175
22197
  ? 'Start signing'
@@ -22969,7 +22991,7 @@ function TransactionsDisplay({ transactions, onSearchValueChanged, search, }) {
22969
22991
  onTransactionDisplayClose === null || onTransactionDisplayClose === void 0 ? void 0 : onTransactionDisplayClose(selectedTransaction);
22970
22992
  setDrawerOpen(false);
22971
22993
  }
22972
- return (jsxRuntime.jsxs("div", { style: style, children: [jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-w-full bunny-shadow-padding-xb bunny-gap-2 ${isMobile ? 'bunny-overflow-hidden' : ''} ${className}`, children: [showTitle || showSearchBar ? (jsxRuntime.jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col bunny-gap-1' : 'bunny-flex-row bunny-items-center'} bunny-justify-between`, children: [showTitle ? (jsxRuntime.jsx(Text$s, { className: "bunny-shrink-0 bunny-font-medium", style: { color: darkMode ? undefined : secondaryColor }, children: title })) : (jsxRuntime.jsx("div", {}) // Empty div so justify-between works
22994
+ return (jsxRuntime.jsxs("div", { style: style, children: [jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-w-full bunny-gap-2 ${isMobile ? 'bunny-overflow-hidden' : ''} ${className}`, children: [showTitle || showSearchBar ? (jsxRuntime.jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col bunny-gap-1' : 'bunny-flex-row bunny-items-center'} bunny-justify-between`, children: [showTitle ? (jsxRuntime.jsx(Text$s, { className: "bunny-shrink-0 bunny-font-medium", style: { color: darkMode ? undefined : secondaryColor }, children: title })) : (jsxRuntime.jsx("div", {}) // Empty div so justify-between works
22973
22995
  ), showSearchBar && (jsxRuntime.jsx("div", { className: `${isMobile ? 'bunny-w-full' : ''}`, children: jsxRuntime.jsx(antd.Input, { className: searchBarClassName ? searchBarClassName : '', onChange: e => {
22974
22996
  const value = e.target.value;
22975
22997
  // Allow empty string, numbers, and decimal point
@@ -22987,6 +23009,7 @@ function TransactionsDisplay({ transactions, onSearchValueChanged, search, }) {
22987
23009
 
22988
23010
  function Quotes({ className, columns = ['date', 'title', 'amount', 'download', 'state'], filter, filterQuotes, sort = (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(), noQuotesMessage = 'There are no quotes', onQuoteClick, renderQuote, searchBarClassName, shadow = 'shadow-md', showSearchBar = true, showTitle = true, title = 'Past quotes', style, suppressQuoteDisplay = false, useModal = false, }) {
22989
23011
  const { apiHost } = react.useContext(BunnyContext);
23012
+ const queryClient = reactQuery.useQueryClient();
22990
23013
  const [component, setComponent] = react.useState(null);
22991
23014
  const contextValues = {
22992
23015
  columns,
@@ -23039,7 +23062,9 @@ function Quotes({ className, columns = ['date', 'title', 'amount', 'download', '
23039
23062
  setComponent(renderQuote(quote));
23040
23063
  }
23041
23064
  else {
23042
- setComponent(jsxRuntime.jsx(Quote, { id: quote === null || quote === void 0 ? void 0 : quote.transactionableId }));
23065
+ setComponent(jsxRuntime.jsx(Quote, { id: quote === null || quote === void 0 ? void 0 : quote.transactionableId, onQuoteAccepted: () => {
23066
+ queryClient.invalidateQueries({ queryKey: QueryKeyFactory.quotesKey() });
23067
+ } }));
23043
23068
  }
23044
23069
  }
23045
23070
  return (jsxRuntime.jsx(TransactionsListContext.Provider, { value: contextValues, children: jsxRuntime.jsx(QuotesWrapper, {}) }));
@@ -23053,7 +23078,7 @@ function QuotesWrapper() {
23053
23078
  const filter = filterFromContext || (search ? `filter: "quote.id is ${search}"` : '');
23054
23079
  // Queries
23055
23080
  const { data } = reactQuery.useQuery({
23056
- queryKey: ['quotes', token, filter],
23081
+ queryKey: QueryKeyFactory.quotesKey(filter, token),
23057
23082
  queryFn: () => getQuotes({ token, apiHost, filter }),
23058
23083
  placeholderData: reactQuery.keepPreviousData,
23059
23084
  });
@@ -13,6 +13,10 @@ declare const PayableProvider: ({ value, children }: {
13
13
  formattedAmountDue: string | undefined;
14
14
  isPaid: boolean;
15
15
  setIsPaid: React.Dispatch<React.SetStateAction<boolean>>;
16
+ isPaying: boolean;
17
+ setIsPaying: React.Dispatch<React.SetStateAction<boolean>>;
18
+ isApprovingHold: boolean;
19
+ setIsApprovingHold: React.Dispatch<React.SetStateAction<boolean>>;
16
20
  };
17
21
  children?: import("react").ReactNode;
18
22
  }) => import("react/jsx-runtime").JSX.Element, usePayable: () => {
@@ -27,6 +31,10 @@ declare const PayableProvider: ({ value, children }: {
27
31
  formattedAmountDue: string | undefined;
28
32
  isPaid: boolean;
29
33
  setIsPaid: React.Dispatch<React.SetStateAction<boolean>>;
34
+ isPaying: boolean;
35
+ setIsPaying: React.Dispatch<React.SetStateAction<boolean>>;
36
+ isApprovingHold: boolean;
37
+ setIsApprovingHold: React.Dispatch<React.SetStateAction<boolean>>;
30
38
  };
31
39
  export { PayableProvider, usePayable, };
32
40
  export declare const PaymentProvider_QuoteFragment: import("gql.tada").TadaDocumentNode<{
@@ -5,6 +5,7 @@ export declare const QuoteButtons_FormattedQuoteFragment: import("gql.tada").Tad
5
5
  currency: string | null;
6
6
  amount: number;
7
7
  expiresAt: unknown;
8
+ state: "APPROVED" | "REJECTED" | "DRAFT" | "SHARED" | "VIEWED" | "ACCEPTED" | "IN_APPROVAL" | "UNDONE";
8
9
  }, {}, {
9
10
  fragment: "QuoteButtons_FormattedQuoteFragment";
10
11
  on: "FormattedQuote";
@@ -78,6 +78,7 @@ declare const QueryKeyFactory: {
78
78
  brandingKey: (token?: string) => string[];
79
79
  calculatedPricesKey: ({ priceListId, quantity, token }: CalculatedPricesKeyParams) => (string | number)[];
80
80
  createEventsKey: ({ entityId, pluralType, token }: EventsKeyParams) => string[];
81
+ quotesKey: (filter?: string, token?: string) => string[];
81
82
  createFormattedInvoiceKey: ({ id, token }: FormattedInvoiceKeyParams) => (string | null | undefined)[];
82
83
  createInvoiceKey: ({ id, token }: InvoiceKeyParams) => (string | undefined)[];
83
84
  createObjectKey: ({ id, objectName, token }: ObjectKeyParams) => string[];
package/dist/esm/index.js CHANGED
@@ -1217,6 +1217,11 @@ const QueryKeyFactory = {
1217
1217
  entityId,
1218
1218
  ...(token ? [token] : []),
1219
1219
  ],
1220
+ quotesKey: (filter, token) => [
1221
+ 'quotes',
1222
+ ...(filter ? [filter] : []),
1223
+ ...(token ? [token] : []),
1224
+ ],
1220
1225
  createFormattedInvoiceKey: ({ id, token }) => [
1221
1226
  'formattedInvoice',
1222
1227
  id,
@@ -1281,7 +1286,7 @@ const DEFAULT_CONFIG = {
1281
1286
  };
1282
1287
 
1283
1288
  // This will be replaced at build time by rollup-plugin-replace
1284
- const PACKAGE_VERSION = '1.8.0-beta.11';
1289
+ const PACKAGE_VERSION = '1.8.0-beta.13';
1285
1290
  const createRequestHeaders = (token) => {
1286
1291
  const headers = createClientDevHeaders({ token });
1287
1292
  // Add the components version header
@@ -20559,6 +20564,8 @@ function PaymentProvider({ children, quote: maskedQuote, invoice: maskedInvoice,
20559
20564
  const invoice = readFragment(PaymentProvider_InvoiceFragment, maskedInvoice);
20560
20565
  // State
20561
20566
  const [isPaid, setIsPaid] = useState(false);
20567
+ const [isPaying, setIsPaying] = useState(false);
20568
+ const [isApprovingHold, setIsApprovingHold] = useState(false);
20562
20569
  const getAmountDue = () => {
20563
20570
  return quote ? getQuoteAmountDue(quote) : invoice === null || invoice === void 0 ? void 0 : invoice.amountDue;
20564
20571
  };
@@ -20594,7 +20601,11 @@ function PaymentProvider({ children, quote: maskedQuote, invoice: maskedInvoice,
20594
20601
  amountDue: amountDue !== null && amountDue !== void 0 ? amountDue : undefined,
20595
20602
  formattedAmountDue: formattedAmountDueValue,
20596
20603
  isPaid,
20597
- setIsPaid
20604
+ setIsPaid,
20605
+ isPaying,
20606
+ setIsPaying,
20607
+ isApprovingHold,
20608
+ setIsApprovingHold,
20598
20609
  }, children: children }));
20599
20610
  }
20600
20611
 
@@ -21098,7 +21109,7 @@ function Pay(props = {}) {
21098
21109
  const isMobile = useIsMobile();
21099
21110
  const { onPaymentSuccess, onPaymentHoldSuccess, onSavePaymentMethod, paymentHoldPrecondition } = usePaymentFormCallbacks();
21100
21111
  const selectedPlugin = useSelectedPlugin();
21101
- const { quoteId, invoiceId, paymentHold, paymentType, setIsPaid } = usePayable();
21112
+ const { quoteId, invoiceId, paymentHold, paymentType, setIsPaid, setIsPaying, setIsApprovingHold } = usePayable();
21102
21113
  const accountId = useAccountId();
21103
21114
  const { defaultPaymentMethod } = usePaymentMethod({ accountId });
21104
21115
  const [showPaymentDetailsForm, setShowPaymentDetailsForm] = useShowPaymentDetails();
@@ -21173,6 +21184,14 @@ function Pay(props = {}) {
21173
21184
  return;
21174
21185
  }
21175
21186
  }
21187
+ useEffect(() => {
21188
+ setIsPaying(isPaying);
21189
+ return () => setIsPaying(false);
21190
+ }, [isPaying, setIsPaying]);
21191
+ useEffect(() => {
21192
+ setIsApprovingHold(isApprovingHold);
21193
+ return () => setIsApprovingHold(false);
21194
+ }, [isApprovingHold, setIsApprovingHold]);
21176
21195
  return (jsx(Button, { className: "bunny-w-full", disabled: isPaying || isApprovingHold || isSaving || disabled, loading: isPaying || isApprovingHold || isSaving, onClick: handlePayment, size: isMobile ? 'large' : 'middle', type: "primary", children: paymentButtonText }));
21177
21196
  }
21178
21197
 
@@ -21329,6 +21348,7 @@ function PaymentMethodDetailsRoot(props = {}) {
21329
21348
  const accountId = useAccountId();
21330
21349
  const { paymentMethods } = usePaymentMethod({ accountId });
21331
21350
  const { paymentPlugins } = usePaymentPlugins(accountId);
21351
+ const { isPaying, isApprovingHold } = usePayable();
21332
21352
  function handleClickAddPaymentMethod() {
21333
21353
  if ((paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.length) === 0) {
21334
21354
  showErrorNotification$6('No payment plugins available', 'Error adding payment method');
@@ -21347,7 +21367,7 @@ function PaymentMethodDetailsRoot(props = {}) {
21347
21367
  {
21348
21368
  key: '1',
21349
21369
  showArrow: false,
21350
- label: !showPaymentMethodForm ? (jsx("div", { className: "bunny-pt-2", children: jsx(Button, { onClick: handleClickAddPaymentMethod, type: "default", className: "bunny-w-full", id: "addPaymentMethod", children: "Add payment method" }) })) : null,
21370
+ label: !showPaymentMethodForm ? (jsx("div", { className: "bunny-pt-2", children: jsx(Button, { onClick: handleClickAddPaymentMethod, type: "default", className: "bunny-w-full", id: "addPaymentMethod", disabled: isPaying || isApprovingHold, children: "Add payment method" }) })) : null,
21351
21371
  children: (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-mt-2", children: [jsx(PaymentMethodSelector, {}), selectedPlugin && (jsx("div", { className: "bunny-flex bunny-flex-col", children: getPaymentMethodForm((_b = (_a = selectedPlugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0].name) })), footer] })),
21352
21372
  },
21353
21373
  ] }) }));
@@ -22148,6 +22168,7 @@ const QuoteButtons_FormattedQuoteFragment = t(`
22148
22168
  currency
22149
22169
  amount
22150
22170
  expiresAt
22171
+ state
22151
22172
  }
22152
22173
  `);
22153
22174
  const PaymentHoldDisplay_QuoteButtonsFragment = t(`
@@ -22164,10 +22185,11 @@ function QuoteButtons({ isAccepted, formattedQuote: maskedFormattedQuote, isMobi
22164
22185
  const { secondaryColor } = useBrand();
22165
22186
  const downloadFile = useDownloadFile(id);
22166
22187
  const isExpired = useIsExpired(formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.expiresAt);
22188
+ const isRejected = (formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.state) === 'REJECTED';
22167
22189
  const signingPlugins = useSigningPlugins({ apiHost, token });
22168
22190
  return (jsxs("div", { className: "flex flex-row justify-end items-center gap-4", id: "acceptance", style: {
22169
22191
  color: secondaryColor,
22170
- }, children: [isAccepted && formattedQuote.acceptedAt ? (jsx(Text$y, { children: `Quote was accepted by ${formattedQuote.acceptedByName} on ${formatDate(formattedQuote.acceptedAt)}` })) : null, (!isMobile || !isAccepted) && (jsxs("div", { className: isMobile ? 'flex w-full justify-end gap-2' : 'flex items-center justify-end gap-2', children: [paymentHold ? (jsx(PaymentHoldDisplay, { paymentHold: paymentHold, currency: formattedQuote.currency, amount: formattedQuote.amount })) : null, !isMobile && !hideDownloadButton ? (jsx(Button, { icon: jsx(DownloadOutlined, {}), onClick: () => downloadFile(apiHost + '/api/pdf/quote', token), children: "Download" })) : null, shouldDoPaymentHold && !paymentHoldCompleted ? (jsx(Button, { disabled: isExpired, onClick: () => setPaymentHoldModalVisible(true), type: "primary", loading: isSendAcceptPending, children: "Pay and sign" })) : (jsx(Fragment, { children: !isAccepted ? (jsx(Button, { disabled: isExpired || isAccepting, onClick: handleClickAccept, type: "primary", children: isExpired
22192
+ }, children: [isAccepted && formattedQuote.acceptedAt ? (jsx(Text$y, { children: `Quote was accepted by ${formattedQuote.acceptedByName} on ${formatDate(formattedQuote.acceptedAt)}` })) : null, (!isMobile || !isAccepted) && (jsxs("div", { className: isMobile ? 'flex w-full justify-end gap-2' : 'flex items-center justify-end gap-2', children: [paymentHold ? (jsx(PaymentHoldDisplay, { paymentHold: paymentHold, currency: formattedQuote.currency, amount: formattedQuote.amount })) : null, !isMobile && !hideDownloadButton ? (jsx(Button, { icon: jsx(DownloadOutlined, {}), onClick: () => downloadFile(apiHost + '/api/pdf/quote', token), children: "Download" })) : null, shouldDoPaymentHold && !paymentHoldCompleted ? (jsx(Button, { disabled: isExpired, onClick: () => setPaymentHoldModalVisible(true), type: "primary", loading: isSendAcceptPending, children: "Pay and sign" })) : (jsx(Fragment, { children: !isAccepted && !isRejected ? (jsx(Button, { disabled: isExpired || isAccepting, onClick: handleClickAccept, type: "primary", children: isExpired
22171
22193
  ? 'Quote is expired'
22172
22194
  : (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length)
22173
22195
  ? 'Start signing'
@@ -22967,7 +22989,7 @@ function TransactionsDisplay({ transactions, onSearchValueChanged, search, }) {
22967
22989
  onTransactionDisplayClose === null || onTransactionDisplayClose === void 0 ? void 0 : onTransactionDisplayClose(selectedTransaction);
22968
22990
  setDrawerOpen(false);
22969
22991
  }
22970
- return (jsxs("div", { style: style, children: [jsxs("div", { className: `bunny-flex bunny-flex-col bunny-w-full bunny-shadow-padding-xb bunny-gap-2 ${isMobile ? 'bunny-overflow-hidden' : ''} ${className}`, children: [showTitle || showSearchBar ? (jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col bunny-gap-1' : 'bunny-flex-row bunny-items-center'} bunny-justify-between`, children: [showTitle ? (jsx(Text$s, { className: "bunny-shrink-0 bunny-font-medium", style: { color: darkMode ? undefined : secondaryColor }, children: title })) : (jsx("div", {}) // Empty div so justify-between works
22992
+ return (jsxs("div", { style: style, children: [jsxs("div", { className: `bunny-flex bunny-flex-col bunny-w-full bunny-gap-2 ${isMobile ? 'bunny-overflow-hidden' : ''} ${className}`, children: [showTitle || showSearchBar ? (jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col bunny-gap-1' : 'bunny-flex-row bunny-items-center'} bunny-justify-between`, children: [showTitle ? (jsx(Text$s, { className: "bunny-shrink-0 bunny-font-medium", style: { color: darkMode ? undefined : secondaryColor }, children: title })) : (jsx("div", {}) // Empty div so justify-between works
22971
22993
  ), showSearchBar && (jsx("div", { className: `${isMobile ? 'bunny-w-full' : ''}`, children: jsx(Input, { className: searchBarClassName ? searchBarClassName : '', onChange: e => {
22972
22994
  const value = e.target.value;
22973
22995
  // Allow empty string, numbers, and decimal point
@@ -22985,6 +23007,7 @@ function TransactionsDisplay({ transactions, onSearchValueChanged, search, }) {
22985
23007
 
22986
23008
  function Quotes({ className, columns = ['date', 'title', 'amount', 'download', 'state'], filter, filterQuotes, sort = (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(), noQuotesMessage = 'There are no quotes', onQuoteClick, renderQuote, searchBarClassName, shadow = 'shadow-md', showSearchBar = true, showTitle = true, title = 'Past quotes', style, suppressQuoteDisplay = false, useModal = false, }) {
22987
23009
  const { apiHost } = useContext(BunnyContext);
23010
+ const queryClient = useQueryClient();
22988
23011
  const [component, setComponent] = useState(null);
22989
23012
  const contextValues = {
22990
23013
  columns,
@@ -23037,7 +23060,9 @@ function Quotes({ className, columns = ['date', 'title', 'amount', 'download', '
23037
23060
  setComponent(renderQuote(quote));
23038
23061
  }
23039
23062
  else {
23040
- setComponent(jsx(Quote, { id: quote === null || quote === void 0 ? void 0 : quote.transactionableId }));
23063
+ setComponent(jsx(Quote, { id: quote === null || quote === void 0 ? void 0 : quote.transactionableId, onQuoteAccepted: () => {
23064
+ queryClient.invalidateQueries({ queryKey: QueryKeyFactory.quotesKey() });
23065
+ } }));
23041
23066
  }
23042
23067
  }
23043
23068
  return (jsx(TransactionsListContext.Provider, { value: contextValues, children: jsx(QuotesWrapper, {}) }));
@@ -23051,7 +23076,7 @@ function QuotesWrapper() {
23051
23076
  const filter = filterFromContext || (search ? `filter: "quote.id is ${search}"` : '');
23052
23077
  // Queries
23053
23078
  const { data } = useQuery({
23054
- queryKey: ['quotes', token, filter],
23079
+ queryKey: QueryKeyFactory.quotesKey(filter, token),
23055
23080
  queryFn: () => getQuotes({ token, apiHost, filter }),
23056
23081
  placeholderData: keepPreviousData,
23057
23082
  });
@@ -13,6 +13,10 @@ declare const PayableProvider: ({ value, children }: {
13
13
  formattedAmountDue: string | undefined;
14
14
  isPaid: boolean;
15
15
  setIsPaid: React.Dispatch<React.SetStateAction<boolean>>;
16
+ isPaying: boolean;
17
+ setIsPaying: React.Dispatch<React.SetStateAction<boolean>>;
18
+ isApprovingHold: boolean;
19
+ setIsApprovingHold: React.Dispatch<React.SetStateAction<boolean>>;
16
20
  };
17
21
  children?: import("react").ReactNode;
18
22
  }) => import("react/jsx-runtime").JSX.Element, usePayable: () => {
@@ -27,6 +31,10 @@ declare const PayableProvider: ({ value, children }: {
27
31
  formattedAmountDue: string | undefined;
28
32
  isPaid: boolean;
29
33
  setIsPaid: React.Dispatch<React.SetStateAction<boolean>>;
34
+ isPaying: boolean;
35
+ setIsPaying: React.Dispatch<React.SetStateAction<boolean>>;
36
+ isApprovingHold: boolean;
37
+ setIsApprovingHold: React.Dispatch<React.SetStateAction<boolean>>;
30
38
  };
31
39
  export { PayableProvider, usePayable, };
32
40
  export declare const PaymentProvider_QuoteFragment: import("gql.tada").TadaDocumentNode<{
@@ -5,6 +5,7 @@ export declare const QuoteButtons_FormattedQuoteFragment: import("gql.tada").Tad
5
5
  currency: string | null;
6
6
  amount: number;
7
7
  expiresAt: unknown;
8
+ state: "APPROVED" | "REJECTED" | "DRAFT" | "SHARED" | "VIEWED" | "ACCEPTED" | "IN_APPROVAL" | "UNDONE";
8
9
  }, {}, {
9
10
  fragment: "QuoteButtons_FormattedQuoteFragment";
10
11
  on: "FormattedQuote";
@@ -78,6 +78,7 @@ declare const QueryKeyFactory: {
78
78
  brandingKey: (token?: string) => string[];
79
79
  calculatedPricesKey: ({ priceListId, quantity, token }: CalculatedPricesKeyParams) => (string | number)[];
80
80
  createEventsKey: ({ entityId, pluralType, token }: EventsKeyParams) => string[];
81
+ quotesKey: (filter?: string, token?: string) => string[];
81
82
  createFormattedInvoiceKey: ({ id, token }: FormattedInvoiceKeyParams) => (string | null | undefined)[];
82
83
  createInvoiceKey: ({ id, token }: InvoiceKeyParams) => (string | undefined)[];
83
84
  createObjectKey: ({ id, objectName, token }: ObjectKeyParams) => string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunnyapp/components",
3
- "version": "1.8.0-beta.12",
3
+ "version": "1.8.0-beta.14",
4
4
  "description": "Components from the Bunny portal to embed Bunny UI functionality into your application.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",