braid-ui 1.0.52 → 1.0.54

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 CHANGED
@@ -8435,21 +8435,10 @@ var formatCurrency2 = (value) => {
8435
8435
  minimumFractionDigits: 2
8436
8436
  }).format(numValue);
8437
8437
  };
8438
- var TRANSACTION_TYPES = [
8439
- { value: "transfer", label: "Transfer", icon: lucideReact.ArrowLeftRight },
8440
- { value: "adjustment", label: "Adjustment", icon: lucideReact.Settings },
8441
- { value: "ach", label: "ACH", icon: lucideReact.Building2 },
8442
- { value: "wire", label: "Wire", icon: lucideReact.Zap }
8443
- ];
8444
8438
  var ADJUSTMENT_DIRECTION_OPTIONS = [
8445
8439
  { value: "debit", label: "Debit" },
8446
8440
  { value: "credit", label: "Credit" }
8447
8441
  ];
8448
- var ADJUSTMENT_TYPE_OPTIONS = [
8449
- { value: "collection", label: "Collection" },
8450
- { value: "transaction_reversal", label: "Transaction Reversal" },
8451
- { value: "transaction_adjustment", label: "Transaction Adjustment" }
8452
- ];
8453
8442
  var NewTransactionView = ({
8454
8443
  form,
8455
8444
  accountLookedUp,
@@ -8478,12 +8467,18 @@ var NewTransactionView = ({
8478
8467
  onCounterpartySearchChange,
8479
8468
  onCounterpartySelect,
8480
8469
  onCounterpartyDropdownClose,
8470
+ counterpartyHasMore,
8471
+ counterpartyTotalResults,
8472
+ isLoadingMoreCounterparties,
8473
+ onLoadMoreCounterparties,
8481
8474
  receiverAccountLookedUp,
8482
8475
  receiverAccountData,
8483
8476
  isReceiverAccountLoading,
8484
8477
  onReceiverAccountLookup,
8485
8478
  onEditReceiverAccount,
8486
- isReviewReady
8479
+ isReviewReady,
8480
+ adjustmentTypeOptions,
8481
+ transactionTypeOptions
8487
8482
  }) => {
8488
8483
  const transactionType = form.watch("transactionType");
8489
8484
  const accountNumber = form.watch("accountNumber");
@@ -8533,11 +8528,11 @@ var NewTransactionView = ({
8533
8528
  }
8534
8529
  ] : [];
8535
8530
  const reviewItems = [
8536
- { label: "Transaction Type", value: TRANSACTION_TYPES.find((t) => t.value === transactionType)?.label || "-" },
8531
+ { label: "Transaction Type", value: transactionTypeOptions.find((t) => t.value === transactionType)?.label || "-" },
8537
8532
  { label: "Account Number", value: accountNumber || "-" },
8538
8533
  ...isAdjustment ? [
8539
8534
  { label: "Direction", value: adjustmentDirection === "debit" ? "Debit" : adjustmentDirection === "credit" ? "Credit" : "-" },
8540
- { label: "Adjustment Type", value: ADJUSTMENT_TYPE_OPTIONS.find((t) => t.value === adjustmentType)?.label || "-" }
8535
+ { label: "Adjustment Type", value: adjustmentTypeOptions.find((t) => t.value === adjustmentType)?.label || "-" }
8541
8536
  ] : [],
8542
8537
  ...isTransfer ? [{ label: "Receiver Account", value: receiverAccountNumber || "-" }] : [],
8543
8538
  ...requiresCounterparty ? [{ label: "Counterparty", value: counterpartyName || "-" }] : [],
@@ -8597,28 +8592,29 @@ var NewTransactionView = ({
8597
8592
  title: "Transaction Type",
8598
8593
  variant: "default",
8599
8594
  className: cn(!accountLookedUp && "opacity-50 pointer-events-none"),
8600
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-3 lg:gap-4", children: TRANSACTION_TYPES.map((type) => {
8595
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-3 lg:gap-4", children: transactionTypeOptions.map((type) => {
8601
8596
  const Icon2 = type.icon;
8602
8597
  const isSelected = transactionType === type.value;
8598
+ const isDisabled = !accountLookedUp || type.disabled;
8603
8599
  return /* @__PURE__ */ jsxRuntime.jsxs(
8604
8600
  "button",
8605
8601
  {
8606
8602
  type: "button",
8607
- onClick: () => onTransactionTypeChange(type.value),
8608
- disabled: !accountLookedUp,
8603
+ onClick: () => !type.disabled && onTransactionTypeChange(type.value),
8604
+ disabled: isDisabled,
8609
8605
  className: cn(
8610
8606
  "flex flex-col items-center justify-center p-4 lg:p-3 rounded-lg border-2 transition-all",
8611
- "hover:border-primary/50 hover:shadow-md",
8612
- isSelected ? "border-primary bg-primary/5 shadow-sm" : "border-border bg-card"
8607
+ isDisabled ? "opacity-50 cursor-not-allowed border-border bg-muted" : "hover:border-primary/50 hover:shadow-md",
8608
+ isSelected && !type.disabled ? "border-primary bg-primary/5 shadow-sm" : !isDisabled && "border-border bg-card"
8613
8609
  ),
8614
8610
  children: [
8615
8611
  /* @__PURE__ */ jsxRuntime.jsx(Icon2, { className: cn(
8616
8612
  "h-6 w-6 lg:h-5 lg:w-5 mb-2",
8617
- isSelected ? "text-primary" : "text-muted-foreground"
8613
+ isSelected && !type.disabled ? "text-primary" : "text-muted-foreground"
8618
8614
  ) }),
8619
8615
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
8620
8616
  "text-sm font-medium",
8621
- isSelected ? "text-primary" : "text-foreground"
8617
+ isSelected && !type.disabled ? "text-primary" : isDisabled ? "text-muted-foreground" : "text-foreground"
8622
8618
  ), children: type.label })
8623
8619
  ]
8624
8620
  },
@@ -8655,19 +8651,41 @@ var NewTransactionView = ({
8655
8651
  ),
8656
8652
  isCounterpartySearching && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-3 top-1/2 -translate-y-1/2", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" }) })
8657
8653
  ] }),
8658
- showCounterpartyDropdown && counterpartySearchResults.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute z-50 w-full mt-1 bg-popover border border-border rounded-md shadow-lg max-h-60 overflow-auto", children: counterpartySearchResults.map((result) => /* @__PURE__ */ jsxRuntime.jsxs(
8659
- "button",
8660
- {
8661
- type: "button",
8662
- onClick: () => onCounterpartySelect(result),
8663
- className: "w-full px-3 py-2 text-left hover:bg-accent transition-colors",
8664
- children: [
8665
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-sm", children: result.name }),
8666
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground", children: result.id })
8667
- ]
8668
- },
8669
- result.id
8670
- )) }),
8654
+ showCounterpartyDropdown && counterpartySearchResults.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute z-50 w-full mt-1 bg-popover border border-border rounded-md shadow-lg max-h-60 overflow-hidden flex flex-col", children: [
8655
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-2 text-xs text-muted-foreground border-b bg-muted/50 flex-shrink-0", children: [
8656
+ "Showing ",
8657
+ counterpartySearchResults.length,
8658
+ " of ",
8659
+ counterpartyTotalResults,
8660
+ " results"
8661
+ ] }),
8662
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-auto flex-1", children: counterpartySearchResults.map((result) => /* @__PURE__ */ jsxRuntime.jsxs(
8663
+ "button",
8664
+ {
8665
+ type: "button",
8666
+ onClick: () => onCounterpartySelect(result),
8667
+ className: "w-full px-3 py-2 text-left hover:bg-accent transition-colors",
8668
+ children: [
8669
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-sm", children: result.name }),
8670
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground", children: result.id })
8671
+ ]
8672
+ },
8673
+ result.id
8674
+ )) }),
8675
+ counterpartyHasMore && /* @__PURE__ */ jsxRuntime.jsx(
8676
+ "button",
8677
+ {
8678
+ type: "button",
8679
+ onClick: onLoadMoreCounterparties,
8680
+ disabled: isLoadingMoreCounterparties,
8681
+ className: "w-full px-3 py-2 text-center text-sm text-primary hover:bg-accent border-t flex-shrink-0 disabled:opacity-50",
8682
+ children: isLoadingMoreCounterparties ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center justify-center gap-2", children: [
8683
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
8684
+ "Loading..."
8685
+ ] }) : "Load More"
8686
+ }
8687
+ )
8688
+ ] }),
8671
8689
  showCounterpartyDropdown && counterpartySearchResults.length === 0 && !isCounterpartySearching && counterpartyName.length >= 2 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute z-50 w-full mt-1 bg-popover border border-border rounded-md shadow-lg p-3", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
8672
8690
  'No counterparties found matching "',
8673
8691
  counterpartyName,
@@ -8765,8 +8783,8 @@ var NewTransactionView = ({
8765
8783
  name: "adjustmentType",
8766
8784
  label: "Adjustment Type",
8767
8785
  placeholder: "Select type",
8768
- options: ADJUSTMENT_TYPE_OPTIONS,
8769
- disabled: !transactionType
8786
+ options: adjustmentTypeOptions,
8787
+ disabled: !transactionType || !adjustmentDirection
8770
8788
  }
8771
8789
  )
8772
8790
  ] }),
@@ -8870,7 +8888,7 @@ var NewTransactionView = ({
8870
8888
  ] }),
8871
8889
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-sm", children: [
8872
8890
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Type:" }),
8873
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: TRANSACTION_TYPES.find((t) => t.value === transactionType)?.label })
8891
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: transactionTypeOptions.find((t) => t.value === transactionType)?.label })
8874
8892
  ] }),
8875
8893
  requiresCounterparty && counterpartyName && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-sm", children: [
8876
8894
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Counterparty:" }),
@@ -14406,6 +14424,11 @@ function NewTransaction() {
14406
14424
  const [counterpartySearchResults, setCounterpartySearchResults] = React15.useState([]);
14407
14425
  const [isCounterpartySearching, setIsCounterpartySearching] = React15.useState(false);
14408
14426
  const [showCounterpartyDropdown, setShowCounterpartyDropdown] = React15.useState(false);
14427
+ const [counterpartySearchPage, setCounterpartySearchPage] = React15.useState(1);
14428
+ const [counterpartyHasMore, setCounterpartyHasMore] = React15.useState(false);
14429
+ const [counterpartyTotalResults, setCounterpartyTotalResults] = React15.useState(0);
14430
+ const [isLoadingMoreCounterparties, setIsLoadingMoreCounterparties] = React15.useState(false);
14431
+ const [currentSearchQuery, setCurrentSearchQuery] = React15.useState("");
14409
14432
  const [confirmationOpen, setConfirmationOpen] = React15.useState(false);
14410
14433
  const [submissionStatus, setSubmissionStatus] = React15.useState(null);
14411
14434
  const [errorMessage, setErrorMessage] = React15.useState("");
@@ -14425,11 +14448,35 @@ function NewTransaction() {
14425
14448
  amount: "",
14426
14449
  description: "",
14427
14450
  certifyInformation: false,
14428
- adjustmentDirection: "",
14451
+ adjustmentDirection: "debit",
14429
14452
  adjustmentType: "",
14430
14453
  receiverAccountNumber: ""
14431
14454
  }
14432
14455
  });
14456
+ const transactionTypeOptions = React15.useMemo(() => [
14457
+ { value: "transfer", label: "Transfer", icon: lucideReact.ArrowLeftRight, disabled: false },
14458
+ { value: "adjustment", label: "Adjustment", icon: lucideReact.Settings, disabled: false },
14459
+ { value: "ach", label: "ACH", icon: lucideReact.Building2, disabled: true },
14460
+ { value: "wire", label: "Wire", icon: lucideReact.Zap, disabled: false }
14461
+ ], []);
14462
+ const adjustmentDirection = form.watch("adjustmentDirection");
14463
+ const adjustmentTypeOptions = React15.useMemo(() => {
14464
+ if (adjustmentDirection === "credit") {
14465
+ return [
14466
+ { value: "interest_credit", label: "Interest Credit" },
14467
+ { value: "fee_reversal", label: "Fee Reversal" },
14468
+ { value: "promotional_credit", label: "Promotional Credit" }
14469
+ ];
14470
+ }
14471
+ return [
14472
+ { value: "collection", label: "Collection" },
14473
+ { value: "transaction_reversal", label: "Transaction Reversal" },
14474
+ { value: "transaction_adjustment", label: "Transaction Adjustment" }
14475
+ ];
14476
+ }, [adjustmentDirection]);
14477
+ React15.useEffect(() => {
14478
+ form.setValue("adjustmentType", "");
14479
+ }, [adjustmentDirection, form]);
14433
14480
  const handleAccountLookup = async () => {
14434
14481
  const accNum = form.getValues("accountNumber");
14435
14482
  if (!accNum) {
@@ -14453,37 +14500,60 @@ function NewTransaction() {
14453
14500
  { id: "CP-1234", name: "Global Industries LLC", type: "Business", paymentInstrumentType: "ach" },
14454
14501
  { id: "CP-9012", name: "GlobalCorp Partners", type: "Business", paymentInstrumentType: "both" },
14455
14502
  { id: "CP-3456", name: "Acme Corporation", type: "Business", paymentInstrumentType: "wire" },
14456
- { id: "CP-7890", name: "Tech Innovations Ltd", type: "Business", paymentInstrumentType: "ach" }
14503
+ { id: "CP-7890", name: "Tech Innovations Ltd", type: "Business", paymentInstrumentType: "ach" },
14504
+ { id: "CP-1111", name: "Global Enterprises", type: "Business", paymentInstrumentType: "wire" },
14505
+ { id: "CP-2222", name: "Global Finance Group", type: "Business", paymentInstrumentType: "both" },
14506
+ { id: "CP-3333", name: "Global Trade Inc.", type: "Business", paymentInstrumentType: "wire" },
14507
+ { id: "CP-4444", name: "Global Services Co.", type: "Business", paymentInstrumentType: "ach" },
14508
+ { id: "CP-5555", name: "Global Ventures Ltd", type: "Business", paymentInstrumentType: "both" }
14457
14509
  ];
14510
+ const PAGE_SIZE = 5;
14458
14511
  const isCounterpartyCompatible = (instrumentType, transactionType) => {
14459
14512
  if (instrumentType === "both") return true;
14460
14513
  if (transactionType === "ach" && instrumentType === "ach") return true;
14461
14514
  if (transactionType === "wire" && instrumentType === "wire") return true;
14462
14515
  return false;
14463
14516
  };
14517
+ const filterByTransactionType = (results, txType) => {
14518
+ if (txType === "ach") {
14519
+ return results.filter(
14520
+ (cp) => cp.paymentInstrumentType === "ach" || cp.paymentInstrumentType === "both"
14521
+ );
14522
+ } else if (txType === "wire") {
14523
+ return results.filter(
14524
+ (cp) => cp.paymentInstrumentType === "wire" || cp.paymentInstrumentType === "both"
14525
+ );
14526
+ }
14527
+ return results;
14528
+ };
14464
14529
  const debouncedSearch = React15.useMemo(
14465
- () => lodash.debounce(async (query, txType) => {
14530
+ () => lodash.debounce(async (query, txType, page = 1) => {
14466
14531
  if (query.length < 2) {
14467
14532
  setCounterpartySearchResults([]);
14468
14533
  setShowCounterpartyDropdown(false);
14534
+ setCounterpartyHasMore(false);
14535
+ setCounterpartyTotalResults(0);
14469
14536
  return;
14470
14537
  }
14471
- setIsCounterpartySearching(true);
14538
+ if (page === 1) {
14539
+ setIsCounterpartySearching(true);
14540
+ }
14472
14541
  try {
14473
14542
  await new Promise((resolve) => setTimeout(resolve, 350));
14474
- let results = mockSearchResults.filter(
14543
+ let filteredResults = mockSearchResults.filter(
14475
14544
  (cp) => cp.name.toLowerCase().includes(query.toLowerCase())
14476
14545
  );
14477
- if (txType === "ach") {
14478
- results = results.filter(
14479
- (cp) => cp.paymentInstrumentType === "ach" || cp.paymentInstrumentType === "both"
14480
- );
14481
- } else if (txType === "wire") {
14482
- results = results.filter(
14483
- (cp) => cp.paymentInstrumentType === "wire" || cp.paymentInstrumentType === "both"
14484
- );
14546
+ filteredResults = filterByTransactionType(filteredResults, txType);
14547
+ const startIndex = (page - 1) * PAGE_SIZE;
14548
+ const paginatedResults = filteredResults.slice(startIndex, startIndex + PAGE_SIZE);
14549
+ if (page === 1) {
14550
+ setCounterpartySearchResults(paginatedResults);
14551
+ } else {
14552
+ setCounterpartySearchResults((prev) => [...prev, ...paginatedResults]);
14485
14553
  }
14486
- setCounterpartySearchResults(results);
14554
+ setCounterpartyTotalResults(filteredResults.length);
14555
+ setCounterpartyHasMore(startIndex + PAGE_SIZE < filteredResults.length);
14556
+ setCounterpartySearchPage(page);
14487
14557
  setShowCounterpartyDropdown(true);
14488
14558
  } finally {
14489
14559
  setIsCounterpartySearching(false);
@@ -14498,11 +14568,19 @@ function NewTransaction() {
14498
14568
  }, [debouncedSearch]);
14499
14569
  const handleCounterpartySearchChange = (value) => {
14500
14570
  form.setValue("counterpartyName", value);
14571
+ setCurrentSearchQuery(value);
14572
+ setCounterpartySearchPage(1);
14501
14573
  if (counterpartyLookedUp) {
14502
14574
  setCounterpartyLookedUp(false);
14503
14575
  setCounterpartyData(null);
14504
14576
  }
14505
- debouncedSearch(value, form.getValues("transactionType"));
14577
+ debouncedSearch(value, form.getValues("transactionType"), 1);
14578
+ };
14579
+ const handleLoadMoreCounterparties = async () => {
14580
+ setIsLoadingMoreCounterparties(true);
14581
+ const txType = form.getValues("transactionType");
14582
+ await debouncedSearch(currentSearchQuery, txType, counterpartySearchPage + 1);
14583
+ setIsLoadingMoreCounterparties(false);
14506
14584
  };
14507
14585
  const handleTransactionTypeChange = (newType) => {
14508
14586
  form.setValue("transactionType", newType);
@@ -14558,7 +14636,7 @@ function NewTransaction() {
14558
14636
  form.setValue("counterpartyName", "");
14559
14637
  form.setValue("amount", "");
14560
14638
  form.setValue("description", "");
14561
- form.setValue("adjustmentDirection", "");
14639
+ form.setValue("adjustmentDirection", "debit");
14562
14640
  form.setValue("adjustmentType", "");
14563
14641
  setReceiverAccountLookedUp(false);
14564
14642
  setReceiverAccountData(null);
@@ -14634,7 +14712,7 @@ function NewTransaction() {
14634
14712
  setIsSubmitting(true);
14635
14713
  try {
14636
14714
  await new Promise((resolve) => setTimeout(resolve, 1500));
14637
- const hasError = Math.random() > 0.7;
14715
+ const hasError = Math.random() > 0.1;
14638
14716
  if (hasError) {
14639
14717
  const errorScenarios = [
14640
14718
  "Insufficient funds. Current balance: $125,450.00, Required: $" + parseFloat(data.amount).toFixed(2),
@@ -14662,7 +14740,7 @@ function NewTransaction() {
14662
14740
  amount: "",
14663
14741
  description: "",
14664
14742
  certifyInformation: false,
14665
- adjustmentDirection: "",
14743
+ adjustmentDirection: "debit",
14666
14744
  adjustmentType: "",
14667
14745
  receiverAccountNumber: ""
14668
14746
  });
@@ -14728,6 +14806,10 @@ function NewTransaction() {
14728
14806
  onCounterpartySearchChange: handleCounterpartySearchChange,
14729
14807
  onCounterpartySelect: handleCounterpartySelect,
14730
14808
  onCounterpartyDropdownClose: () => setShowCounterpartyDropdown(false),
14809
+ counterpartyHasMore,
14810
+ counterpartyTotalResults,
14811
+ isLoadingMoreCounterparties,
14812
+ onLoadMoreCounterparties: handleLoadMoreCounterparties,
14731
14813
  onEditCounterparty: handleEditCounterparty,
14732
14814
  onTransactionTypeChange: handleTransactionTypeChange,
14733
14815
  onSubmit: handleSubmit,
@@ -14740,7 +14822,9 @@ function NewTransaction() {
14740
14822
  isReceiverAccountLoading,
14741
14823
  onReceiverAccountLookup: handleReceiverAccountLookup,
14742
14824
  onEditReceiverAccount: handleEditReceiverAccount,
14743
- isReviewReady
14825
+ isReviewReady,
14826
+ adjustmentTypeOptions,
14827
+ transactionTypeOptions
14744
14828
  }
14745
14829
  );
14746
14830
  }
@@ -16778,7 +16862,6 @@ exports.ACHBasicInfoCard = ACHBasicInfoCard;
16778
16862
  exports.ACHDetailsSection = ACHDetailsSection;
16779
16863
  exports.ACHTransferSection = ACHTransferSection;
16780
16864
  exports.ADJUSTMENT_DIRECTION_OPTIONS = ADJUSTMENT_DIRECTION_OPTIONS;
16781
- exports.ADJUSTMENT_TYPE_OPTIONS = ADJUSTMENT_TYPE_OPTIONS;
16782
16865
  exports.AccountCard = AccountCard;
16783
16866
  exports.AccountDetail = AccountDetail_default;
16784
16867
  exports.Accounts = Accounts_default;
@@ -16938,7 +17021,6 @@ exports.Statement = Statement;
16938
17021
  exports.StatementHeader = StatementHeader;
16939
17022
  exports.StatementView = StatementView;
16940
17023
  exports.StatusBadge = StatusBadge;
16941
- exports.TRANSACTION_TYPES = TRANSACTION_TYPES;
16942
17024
  exports.Table = Table;
16943
17025
  exports.TableBody = TableBody;
16944
17026
  exports.TableCaption = TableCaption;