@agg-build/ui 2.0.0 → 2.1.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.
Files changed (42) hide show
  1. package/dist/{chunk-2UKDQ7WP.mjs → chunk-3OI2ZLLT.mjs} +94 -39
  2. package/dist/{chunk-4CM4F4S6.mjs → chunk-C5M2OOM3.mjs} +1 -1
  3. package/dist/{chunk-2ZS3BPSF.mjs → chunk-DXF2LMNN.mjs} +132 -81
  4. package/dist/{chunk-RWOF44TC.mjs → chunk-R6FBYAY5.mjs} +239 -183
  5. package/dist/{chunk-RF2EPYLN.mjs → chunk-Y6PVXAUQ.mjs} +27 -77
  6. package/dist/{chunk-R3U6YXSQ.mjs → chunk-YAEA6EDG.mjs} +31 -18
  7. package/dist/{chunk-HH7L3KLS.mjs → chunk-YMVD6Q2A.mjs} +1 -1
  8. package/dist/events.js +497 -462
  9. package/dist/events.mjs +3 -3
  10. package/dist/index.js +2116 -1990
  11. package/dist/index.mjs +9 -7
  12. package/dist/modals.js +278 -171
  13. package/dist/modals.mjs +5 -3
  14. package/dist/pages.js +1557 -1487
  15. package/dist/pages.mjs +6 -6
  16. package/dist/primitives.js +137 -86
  17. package/dist/primitives.mjs +1 -1
  18. package/dist/styles.css +1 -1
  19. package/dist/tailwind.css +1 -1
  20. package/dist/trading.js +28 -15
  21. package/dist/trading.mjs +4 -4
  22. package/dist/types/events/list/category-sidebar.d.mts +33 -0
  23. package/dist/types/events/list/category-sidebar.d.ts +33 -0
  24. package/dist/types/events/list/event-list-tabs.d.mts +2 -0
  25. package/dist/types/events/list/event-list-tabs.d.ts +2 -0
  26. package/dist/types/events/list/index.d.mts +1 -0
  27. package/dist/types/events/list/index.d.ts +1 -0
  28. package/dist/types/pages/event-market/event-market.types.d.mts +1 -0
  29. package/dist/types/pages/event-market/event-market.types.d.ts +1 -0
  30. package/dist/types/pages/user-profile/index.d.mts +1 -1
  31. package/dist/types/pages/user-profile/index.d.ts +1 -1
  32. package/dist/types/pages/user-profile/user-profile.types.d.mts +1 -0
  33. package/dist/types/pages/user-profile/user-profile.types.d.ts +1 -0
  34. package/dist/types/shared/use-horizontal-scroll-state.d.mts +15 -0
  35. package/dist/types/shared/use-horizontal-scroll-state.d.ts +15 -0
  36. package/dist/types/withdraw/index.d.mts +9 -1
  37. package/dist/types/withdraw/index.d.ts +9 -1
  38. package/dist/types/withdraw/steps/withdraw-amount.d.mts +10 -1
  39. package/dist/types/withdraw/steps/withdraw-amount.d.ts +10 -1
  40. package/dist/types/withdraw/withdraw-modal.types.d.mts +8 -0
  41. package/dist/types/withdraw/withdraw-modal.types.d.ts +8 -0
  42. package/package.json +3 -3
@@ -38,7 +38,7 @@ import {
38
38
  shortenAddress,
39
39
  useOptionalToast,
40
40
  venueLogoLabels
41
- } from "./chunk-2ZS3BPSF.mjs";
41
+ } from "./chunk-DXF2LMNN.mjs";
42
42
 
43
43
  // src/deposit/index.tsx
44
44
  import { useAggAuthState, useAggUiConfig, useDepositAddresses, useLabels as useLabels11 } from "@agg-build/hooks";
@@ -1873,8 +1873,30 @@ var WithdrawMethodStep = ({
1873
1873
  };
1874
1874
 
1875
1875
  // src/withdraw/steps/withdraw-amount.tsx
1876
- import { useLabels as useLabels13, useWithdrawEstimate as useWithdrawEstimate2 } from "@agg-build/hooks";
1876
+ import { useLabels as useLabels13, useWithdrawPreview } from "@agg-build/hooks";
1877
1877
  import { Fragment as Fragment8, jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
1878
+ var formatRawTokenAmount = (rawAmount, decimals) => {
1879
+ if (!rawAmount) return "0";
1880
+ const raw = BigInt(rawAmount);
1881
+ const divisor = BigInt(`1${"0".repeat(decimals)}`);
1882
+ const whole = raw / divisor;
1883
+ const remainder = raw % divisor;
1884
+ if (remainder === BigInt(0)) return whole.toString();
1885
+ return `${whole.toString()}.${remainder.toString().padStart(decimals, "0").replace(/0+$/, "")}`;
1886
+ };
1887
+ var parseTokenAmountToRaw = (amount, decimals) => {
1888
+ const normalizedAmount = amount.trim();
1889
+ if (!normalizedAmount || !/^\d*(?:\.\d*)?$/.test(normalizedAmount)) return null;
1890
+ const [wholePart = "0", fractionalPart = ""] = normalizedAmount.split(".");
1891
+ if (fractionalPart.length > decimals) return null;
1892
+ const normalizedWhole = wholePart === "" ? "0" : wholePart;
1893
+ const normalizedFraction = fractionalPart.padEnd(decimals, "0");
1894
+ try {
1895
+ return `${BigInt(normalizedWhole)}${normalizedFraction}`.replace(/^0+(?=\d)/, "");
1896
+ } catch (e) {
1897
+ return null;
1898
+ }
1899
+ };
1878
1900
  var WithdrawAmountStep = ({
1879
1901
  amount,
1880
1902
  destinationWallet,
@@ -1883,8 +1905,10 @@ var WithdrawAmountStep = ({
1883
1905
  networkOptions,
1884
1906
  selectedToken,
1885
1907
  selectedNetwork,
1908
+ destDecimals,
1886
1909
  isConfirming = false,
1887
1910
  error,
1911
+ max = false,
1888
1912
  onBack,
1889
1913
  onAmountChange,
1890
1914
  onDestinationChange,
@@ -1893,18 +1917,31 @@ var WithdrawAmountStep = ({
1893
1917
  onMaxClick,
1894
1918
  onContinue
1895
1919
  }) => {
1920
+ var _a, _b, _c, _d;
1896
1921
  const labels = useLabels13();
1897
1922
  const SOLANA_CHAIN_ID = "792703809";
1898
1923
  const isSolanaDest = selectedNetwork === SOLANA_CHAIN_ID;
1899
1924
  const trimmedDestination = destinationWallet.trim();
1900
1925
  const isValidAddress = isSolanaDest ? /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(trimmedDestination) : /^0x[a-fA-F0-9]{40}$/.test(trimmedDestination);
1901
1926
  const isValid = Number(amount) > 0 && isValidAddress;
1902
- const isDisabled = !isValid || isConfirming;
1903
- const withdrawEstimate = useWithdrawEstimate2({
1904
- amount,
1905
- selectedToken,
1906
- selectedNetwork
1927
+ const amountRaw = amount && Number(amount) > 0 ? parseTokenAmountToRaw(amount, destDecimals) : null;
1928
+ const destinationChainId = Number(selectedNetwork) || null;
1929
+ const preview = useWithdrawPreview({
1930
+ amountRaw,
1931
+ tokenSymbol: selectedToken || null,
1932
+ destinationChainId,
1933
+ destinationAddress: trimmedDestination || null,
1934
+ max
1907
1935
  });
1936
+ const previewUnviable = ((_a = preview.data) == null ? void 0 : _a.pricingStatus) === "unviable";
1937
+ const previewUnviableMessage = previewUnviable ? ((_b = preview.data) == null ? void 0 : _b.maxDeliverableRaw) != null && BigInt(preview.data.maxDeliverableRaw) > BigInt(0) ? `Amount exceeds your withdrawable balance. Max: ~${formatRawTokenAmount(preview.data.maxDeliverableRaw, destDecimals)} ${selectedToken}` : (_d = (_c = preview.data) == null ? void 0 : _c.unviableReason) != null ? _d : "This amount can't be withdrawn right now." : null;
1938
+ const previewLoading = preview.isFetching;
1939
+ const isDisabled = !isValid || isConfirming || previewUnviable || previewLoading;
1940
+ const withdrawEstimate = preview.data && preview.data.pricingStatus === "quoted" ? {
1941
+ estimatedFees: preview.data.feeRaw != null ? `~${formatRawTokenAmount(preview.data.feeRaw, destDecimals)} ${selectedToken}` : "\u2014",
1942
+ networkReserve: preview.data.networkFeeRaw != null ? `~${formatRawTokenAmount(preview.data.networkFeeRaw, destDecimals)} ${selectedToken}` : "\u2014",
1943
+ youReceive: preview.data.receiveAmountRaw != null ? `~${formatRawTokenAmount(preview.data.receiveAmountRaw, destDecimals)} ${selectedToken}` : "\u2014"
1944
+ } : null;
1908
1945
  const shouldShowWithdrawEstimate = Boolean(withdrawEstimate);
1909
1946
  return /* @__PURE__ */ jsxs14(Fragment8, { children: [
1910
1947
  /* @__PURE__ */ jsx14(
@@ -2007,17 +2044,19 @@ var WithdrawAmountStep = ({
2007
2044
  )
2008
2045
  ] })
2009
2046
  ] }),
2010
- shouldShowWithdrawEstimate && withdrawEstimate ? /* @__PURE__ */ jsx14(TransferFeeSummary, { estimate: withdrawEstimate, view: "withdraw" }) : null
2047
+ shouldShowWithdrawEstimate && withdrawEstimate ? /* @__PURE__ */ jsx14(TransferFeeSummary, { estimate: withdrawEstimate, view: "withdraw" }) : null,
2048
+ previewUnviableMessage ? /* @__PURE__ */ jsx14("p", { className: "agg-type-label text-agg-error", role: "alert", children: previewUnviableMessage }) : null
2011
2049
  ] }),
2012
2050
  /* @__PURE__ */ jsx14(
2013
2051
  Button,
2014
2052
  {
2015
- variant: isValid && !isConfirming ? "primary" : "secondary",
2053
+ variant: isValid && !isConfirming && !previewUnviable && !previewLoading ? "primary" : "secondary",
2016
2054
  size: "large",
2017
2055
  className: "w-full",
2018
2056
  disabled: isDisabled,
2057
+ prefix: previewLoading && !isConfirming ? /* @__PURE__ */ jsx14(LoadingIcon, { size: "small", className: "mr-2 text-current" }) : void 0,
2019
2058
  onClick: onContinue,
2020
- children: isConfirming ? labels.common.loading : labels.withdraw.walletFlow.confirm
2059
+ children: isConfirming ? labels.common.loading : previewLoading ? labels.withdraw.walletFlow.calculatingFees : labels.withdraw.walletFlow.confirm
2021
2060
  }
2022
2061
  ),
2023
2062
  error ? /* @__PURE__ */ jsx14("p", { className: "agg-type-label text-agg-error text-center", role: "alert", children: error }) : null
@@ -2247,7 +2286,7 @@ var getTokenDecimals = (tokenSymbol, chainId) => {
2247
2286
  }
2248
2287
  return (_a = TOKEN_DECIMALS_BY_SYMBOL[normalizedSymbol]) != null ? _a : DEFAULT_TOKEN_DECIMALS;
2249
2288
  };
2250
- var formatRawTokenAmount = (rawAmount, decimals) => {
2289
+ var formatRawTokenAmount2 = (rawAmount, decimals) => {
2251
2290
  const raw = BigInt(rawAmount);
2252
2291
  const divisor = BigInt(`1${"0".repeat(decimals)}`);
2253
2292
  const whole = raw / divisor;
@@ -2259,11 +2298,12 @@ var formatLifecycleTokenAmount = ({
2259
2298
  rawAmount,
2260
2299
  tokenSymbol,
2261
2300
  chainId
2262
- }) => `${formatRawTokenAmount(rawAmount, getTokenDecimals(tokenSymbol, chainId))} ${tokenSymbol}`;
2301
+ }) => `${formatRawTokenAmount2(rawAmount, getTokenDecimals(tokenSymbol, chainId))} ${tokenSymbol}`;
2263
2302
  var buildTerminalSummary = ({
2264
2303
  fallbackSummary,
2265
2304
  lifecycleCompletedAmountRaw,
2266
2305
  lifecycleRequestedAmountRaw,
2306
+ lifecycleFeeRaw,
2267
2307
  tokenSymbol,
2268
2308
  chainId
2269
2309
  }) => {
@@ -2273,24 +2313,25 @@ var buildTerminalSummary = ({
2273
2313
  tokenSymbol,
2274
2314
  chainId
2275
2315
  });
2276
- if (!lifecycleRequestedAmountRaw) {
2277
- return __spreadProps(__spreadValues({}, fallbackSummary), { amountReceived });
2278
- }
2279
- try {
2280
- const requestedRaw = BigInt(lifecycleRequestedAmountRaw);
2281
- const completedRaw = BigInt(lifecycleCompletedAmountRaw);
2282
- const feeRaw = requestedRaw > completedRaw ? requestedRaw - completedRaw : BigInt(0);
2283
- return __spreadProps(__spreadValues({}, fallbackSummary), {
2284
- amountReceived,
2285
- fees: formatLifecycleTokenAmount({
2286
- rawAmount: feeRaw.toString(),
2287
- tokenSymbol,
2288
- chainId
2289
- })
2290
- });
2291
- } catch (e) {
2292
- return __spreadProps(__spreadValues({}, fallbackSummary), { amountReceived });
2316
+ let feeRaw = lifecycleFeeRaw;
2317
+ if (feeRaw == null && lifecycleRequestedAmountRaw) {
2318
+ try {
2319
+ const r = BigInt(lifecycleRequestedAmountRaw);
2320
+ const c = BigInt(lifecycleCompletedAmountRaw);
2321
+ feeRaw = (r > c ? r - c : BigInt(0)).toString();
2322
+ } catch (e) {
2323
+ feeRaw = null;
2324
+ }
2293
2325
  }
2326
+ return __spreadValues(__spreadProps(__spreadValues({}, fallbackSummary), {
2327
+ amountReceived
2328
+ }), feeRaw != null ? {
2329
+ fees: formatLifecycleTokenAmount({
2330
+ rawAmount: feeRaw,
2331
+ tokenSymbol,
2332
+ chainId
2333
+ })
2334
+ } : {});
2294
2335
  };
2295
2336
  function isControlledWithdrawModalProps(props) {
2296
2337
  return "withdrawFlow" in props;
@@ -2394,6 +2435,7 @@ function WithdrawModalControlled({
2394
2435
  fallbackSummary: withdrawFlow.purchaseSummary,
2395
2436
  lifecycleCompletedAmountRaw: withdrawalLifecycleState.completedAmountRaw,
2396
2437
  lifecycleRequestedAmountRaw: withdrawalLifecycleState.requestedAmountRaw,
2438
+ lifecycleFeeRaw: withdrawalLifecycleState.feeRaw,
2397
2439
  tokenSymbol: withdrawFlow.selectedToken,
2398
2440
  chainId: withdrawFlow.selectedNetwork
2399
2441
  });
@@ -2415,8 +2457,13 @@ function WithdrawModalControlled({
2415
2457
  networkOptions: withdrawNetworkOptions,
2416
2458
  selectedToken: withdrawFlow.selectedToken,
2417
2459
  selectedNetwork: withdrawFlow.selectedNetwork,
2460
+ destDecimals: getTokenDecimals(
2461
+ withdrawFlow.selectedToken,
2462
+ withdrawFlow.selectedNetwork
2463
+ ),
2418
2464
  isConfirming,
2419
2465
  error: confirmError,
2466
+ max: withdrawFlow.isMax,
2420
2467
  onBack: handleBack,
2421
2468
  onAmountChange: onWithdrawAmountChange,
2422
2469
  onDestinationChange: onWithdrawDestinationChange,
@@ -3577,9 +3624,9 @@ var AccountsWalletsTab = ({
3577
3624
  )
3578
3625
  ] })
3579
3626
  ] }),
3580
- /* @__PURE__ */ jsxs24("div", { className: "agg-wallets-section flex flex-col gap-3", children: [
3627
+ wallets.length > 0 ? /* @__PURE__ */ jsxs24("div", { className: "agg-wallets-section flex flex-col gap-3", children: [
3581
3628
  /* @__PURE__ */ jsx24(SectionTitle, { children: "Wallets" }),
3582
- /* @__PURE__ */ jsx24("div", { className: "flex flex-col gap-2", children: wallets.length > 0 ? wallets.map((wallet) => {
3629
+ /* @__PURE__ */ jsx24("div", { className: "flex flex-col gap-2", children: wallets.map((wallet) => {
3583
3630
  var _a;
3584
3631
  return /* @__PURE__ */ jsx24(AccountRow, { className: "gap-4", children: /* @__PURE__ */ jsxs24("div", { className: "flex min-w-0 items-center gap-3", children: [
3585
3632
  /* @__PURE__ */ jsx24(
@@ -3592,8 +3639,8 @@ var AccountsWalletsTab = ({
3592
3639
  ),
3593
3640
  /* @__PURE__ */ jsx24(VerifiedBadge, {})
3594
3641
  ] }) }, `${wallet.chain}:${wallet.address}`);
3595
- }) : null })
3596
- ] })
3642
+ }) })
3643
+ ] }) : null
3597
3644
  ] });
3598
3645
  };
3599
3646
  AccountsWalletsTab.displayName = "AccountsWalletsTab";
@@ -4016,15 +4063,22 @@ var ProfileModal = ({
4016
4063
  const resolvedWallets = useMemo3(() => {
4017
4064
  var _a2, _b2;
4018
4065
  if (wallets) return wallets;
4019
- return (_b2 = (_a2 = user == null ? void 0 : user.wallets) == null ? void 0 : _a2.map((wallet) => {
4066
+ const walletAccounts = (_b2 = (_a2 = user == null ? void 0 : user.accounts) == null ? void 0 : _a2.filter((account) => {
4020
4067
  var _a3;
4068
+ const provider = (_a3 = account.provider) == null ? void 0 : _a3.toLowerCase();
4069
+ return provider === "wallet" || provider === "solana_wallet";
4070
+ })) != null ? _b2 : [];
4071
+ return walletAccounts.filter((account) => Boolean(account.providerAccountId)).map((account) => {
4072
+ var _a3, _b3;
4073
+ const chain = ((_a3 = account.provider) == null ? void 0 : _a3.toLowerCase()) === "solana_wallet" ? "solana" : "evm";
4074
+ const address = account.providerAccountId;
4021
4075
  return {
4022
- chain: wallet.chain,
4023
- address: wallet.address,
4024
- displayAddress: (_a3 = shortenAddress(wallet.address, { chain: wallet.chain })) != null ? _a3 : wallet.address
4076
+ chain,
4077
+ address,
4078
+ displayAddress: (_b3 = shortenAddress(address, { chain })) != null ? _b3 : address
4025
4079
  };
4026
- })) != null ? _b2 : [];
4027
- }, [user == null ? void 0 : user.wallets, wallets]);
4080
+ });
4081
+ }, [user == null ? void 0 : user.accounts, wallets]);
4028
4082
  return /* @__PURE__ */ jsx26(Modal, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs26(
4029
4083
  Modal.Container,
4030
4084
  {
@@ -4227,6 +4281,7 @@ export {
4227
4281
  clearPendingCardSession,
4228
4282
  getPendingCardSession,
4229
4283
  DepositModal,
4284
+ buildTerminalSummary,
4230
4285
  WithdrawModal,
4231
4286
  HowItWorksStep,
4232
4287
  ProfileSetupStep,
@@ -17,7 +17,7 @@ import {
17
17
  selectPrimaryVenueMarket,
18
18
  skeletonViews,
19
19
  sortOutcomes
20
- } from "./chunk-2ZS3BPSF.mjs";
20
+ } from "./chunk-DXF2LMNN.mjs";
21
21
 
22
22
  // src/trading/trading-context/index.tsx
23
23
  import { useEventTradingContext } from "@agg-build/hooks";
@@ -4955,7 +4955,7 @@ var Footer = ({
4955
4955
  "div",
4956
4956
  {
4957
4957
  className: cn(
4958
- "agg-footer-inner mx-auto flex h-10 w-full max-w-[1360px] px-6 lg:px-10 items-center justify-between",
4958
+ "agg-footer-inner mx-auto flex h-10 w-full max-w-[1440px] px-6 lg:px-10 items-center justify-between",
4959
4959
  classNames == null ? void 0 : classNames.inner
4960
4960
  ),
4961
4961
  children: [
@@ -7516,7 +7516,7 @@ var Header = ({
7516
7516
  "div",
7517
7517
  {
7518
7518
  className: cn(
7519
- "agg-header-inner mx-auto flex h-auto w-full max-w-[1360px] px-6 lg:px-10 items-center gap-2 md:gap-4 py-5",
7519
+ "agg-header-inner mx-auto flex h-auto w-full max-w-[1440px] px-6 lg:px-10 items-center gap-2 md:gap-4 py-5",
7520
7520
  classNames == null ? void 0 : classNames.inner
7521
7521
  ),
7522
7522
  children: [
@@ -8558,7 +8558,37 @@ StateMessage.displayName = "StateMessage";
8558
8558
 
8559
8559
  // src/primitives/tabs/index.tsx
8560
8560
  import { useLabels as useLabels16, useSdkUiConfig as useSdkUiConfig15 } from "@agg-build/hooks";
8561
- import { useCallback as useCallback5, useEffect as useEffect8, useLayoutEffect as useLayoutEffect3, useMemo as useMemo7, useRef as useRef8, useState as useState9 } from "react";
8561
+ import { useCallback as useCallback6, useEffect as useEffect9, useLayoutEffect as useLayoutEffect3, useMemo as useMemo7, useRef as useRef9, useState as useState10 } from "react";
8562
+
8563
+ // src/shared/use-horizontal-scroll-state.ts
8564
+ import { useCallback as useCallback5, useEffect as useEffect8, useRef as useRef8, useState as useState9 } from "react";
8565
+ var useHorizontalScrollState = () => {
8566
+ const containerRef = useRef8(null);
8567
+ const [canScrollLeft, setCanScrollLeft] = useState9(false);
8568
+ const [canScrollRight, setCanScrollRight] = useState9(false);
8569
+ const update = useCallback5(() => {
8570
+ const el = containerRef.current;
8571
+ if (!el) return;
8572
+ const maxScroll = el.scrollWidth - el.clientWidth;
8573
+ setCanScrollLeft(el.scrollLeft > 4);
8574
+ setCanScrollRight(maxScroll - el.scrollLeft > 4);
8575
+ }, []);
8576
+ useEffect8(() => {
8577
+ const el = containerRef.current;
8578
+ if (!el) return;
8579
+ el.addEventListener("scroll", update, { passive: true });
8580
+ return () => el.removeEventListener("scroll", update);
8581
+ }, [update]);
8582
+ useEffect8(() => {
8583
+ if (typeof ResizeObserver === "undefined") return;
8584
+ const el = containerRef.current;
8585
+ if (!el) return;
8586
+ const ro = new ResizeObserver(() => update());
8587
+ ro.observe(el);
8588
+ return () => ro.disconnect();
8589
+ }, [update]);
8590
+ return { containerRef, canScrollLeft, canScrollRight, update };
8591
+ };
8562
8592
 
8563
8593
  // src/primitives/tabs/tabs.constants.ts
8564
8594
  var MOBILE_TABS_MEDIA_QUERY = "(max-width: 736px)";
@@ -8632,8 +8662,8 @@ var Tabs = ({
8632
8662
  const {
8633
8663
  features: { enableAnimations }
8634
8664
  } = useSdkUiConfig15();
8635
- const buttonRefs = useRef8([]);
8636
- const dragStateRef = useRef8({
8665
+ const buttonRefs = useRef9([]);
8666
+ const dragStateRef = useRef9({
8637
8667
  isPointerDown: false,
8638
8668
  isDragging: false,
8639
8669
  pointerId: null,
@@ -8641,20 +8671,21 @@ var Tabs = ({
8641
8671
  startClientY: 0,
8642
8672
  startScrollLeft: 0
8643
8673
  });
8644
- const suppressClickRef = useRef8(false);
8674
+ const suppressClickRef = useRef9(false);
8645
8675
  const resolvedAriaLabel = ariaLabel != null ? ariaLabel : labels.common.tabsAria;
8646
- const [isMobileViewport, setIsMobileViewport] = useState9(false);
8647
- const [isDraggingTabs, setIsDraggingTabs] = useState9(false);
8648
- const [activeUnderlineStyle, setActiveUnderlineStyle] = useState9({
8676
+ const [isMobileViewport, setIsMobileViewport] = useState10(false);
8677
+ const [isDraggingTabs, setIsDraggingTabs] = useState10(false);
8678
+ const [activeUnderlineStyle, setActiveUnderlineStyle] = useState10({
8649
8679
  transform: "translateX(0px)",
8650
8680
  width: 0,
8651
8681
  opacity: 0
8652
8682
  });
8653
- const [scrollAffordanceState, setScrollAffordanceState] = useState9({
8654
- showStart: false,
8655
- showEnd: false
8656
- });
8657
- const tabListRef = useRef8(null);
8683
+ const {
8684
+ containerRef: tabListRef,
8685
+ canScrollLeft,
8686
+ canScrollRight,
8687
+ update: updateScrollState
8688
+ } = useHorizontalScrollState();
8658
8689
  const isBarVariant = variant === "bar";
8659
8690
  const resolvedOverflowBehavior = useMemo7(() => {
8660
8691
  if (overflowBehavior) return overflowBehavior;
@@ -8663,7 +8694,7 @@ var Tabs = ({
8663
8694
  }, [isBarVariant, isMobileViewport, overflowBehavior]);
8664
8695
  const shouldUseOverflowScroll = resolvedOverflowBehavior === "scroll";
8665
8696
  const shouldUseOverflowSelect = resolvedOverflowBehavior === "select";
8666
- useEffect8(() => {
8697
+ useEffect9(() => {
8667
8698
  if (typeof window === "undefined") return;
8668
8699
  const mediaQueryList = window.matchMedia(MOBILE_TABS_MEDIA_QUERY);
8669
8700
  const handleMediaQueryChange = (event) => {
@@ -8681,22 +8712,6 @@ var Tabs = ({
8681
8712
  mediaQueryList.removeListener(handleMediaQueryChange);
8682
8713
  };
8683
8714
  }, []);
8684
- const updateScrollAffordances = useCallback5(() => {
8685
- if (!shouldUseOverflowScroll) {
8686
- setScrollAffordanceState({
8687
- showStart: false,
8688
- showEnd: false
8689
- });
8690
- return;
8691
- }
8692
- const tabListElement = tabListRef.current;
8693
- if (!tabListElement) return;
8694
- const maxScrollLeft = tabListElement.scrollWidth - tabListElement.clientWidth;
8695
- setScrollAffordanceState({
8696
- showStart: tabListElement.scrollLeft > 4,
8697
- showEnd: maxScrollLeft - tabListElement.scrollLeft > 4
8698
- });
8699
- }, [shouldUseOverflowScroll]);
8700
8715
  const renderedItems = useMemo7(() => {
8701
8716
  return items.map((item) => __spreadProps(__spreadValues({}, item), {
8702
8717
  disabled: item.disabled || item.isComingSoon
@@ -8835,7 +8850,7 @@ var Tabs = ({
8835
8850
  event == null ? void 0 : event.stopPropagation();
8836
8851
  suppressClickRef.current = false;
8837
8852
  };
8838
- const updateActiveUnderline = useCallback5(() => {
8853
+ const updateActiveUnderline = useCallback6(() => {
8839
8854
  if (isBarVariant) {
8840
8855
  setActiveUnderlineStyle({
8841
8856
  transform: "translateX(0px)",
@@ -8861,39 +8876,36 @@ var Tabs = ({
8861
8876
  useLayoutEffect3(() => {
8862
8877
  updateActiveUnderline();
8863
8878
  }, [updateActiveUnderline]);
8864
- useEffect8(() => {
8879
+ useEffect9(() => {
8865
8880
  if (isBarVariant || !shouldUseOverflowScroll) return;
8866
8881
  const tabListElement = tabListRef.current;
8867
8882
  if (!tabListElement) return;
8868
8883
  const handleScroll = () => {
8869
8884
  updateActiveUnderline();
8870
- updateScrollAffordances();
8871
8885
  };
8872
8886
  tabListElement.addEventListener("scroll", handleScroll, { passive: true });
8873
- updateScrollAffordances();
8874
8887
  return () => {
8875
8888
  tabListElement.removeEventListener("scroll", handleScroll);
8876
8889
  };
8877
- }, [isBarVariant, shouldUseOverflowScroll, updateActiveUnderline, updateScrollAffordances]);
8878
- useEffect8(() => {
8890
+ }, [isBarVariant, shouldUseOverflowScroll, tabListRef, updateActiveUnderline]);
8891
+ useEffect9(() => {
8879
8892
  if (!shouldUseOverflowScroll) return;
8880
- updateScrollAffordances();
8881
- }, [renderedItems, shouldUseOverflowScroll, updateScrollAffordances, value]);
8882
- useEffect8(() => {
8883
- if (isBarVariant && !shouldUseOverflowScroll) return;
8893
+ updateScrollState();
8894
+ }, [renderedItems, shouldUseOverflowScroll, updateScrollState, value]);
8895
+ useEffect9(() => {
8896
+ if (isBarVariant || !shouldUseOverflowScroll) return;
8884
8897
  if (typeof ResizeObserver === "undefined") return;
8885
8898
  const tabListElement = tabListRef.current;
8886
8899
  if (!tabListElement) return;
8887
8900
  const resizeObserver = new ResizeObserver(() => {
8888
8901
  updateActiveUnderline();
8889
- updateScrollAffordances();
8890
8902
  });
8891
8903
  resizeObserver.observe(tabListElement);
8892
8904
  return () => {
8893
8905
  resizeObserver.disconnect();
8894
8906
  };
8895
- }, [isBarVariant, shouldUseOverflowScroll, updateActiveUnderline, updateScrollAffordances]);
8896
- useEffect8(() => {
8907
+ }, [isBarVariant, shouldUseOverflowScroll, tabListRef, updateActiveUnderline]);
8908
+ useEffect9(() => {
8897
8909
  if (!shouldUseOverflowScroll) return;
8898
8910
  const tabListElement = tabListRef.current;
8899
8911
  if (!tabListElement) return;
@@ -9040,7 +9052,7 @@ var Tabs = ({
9040
9052
  "agg-tab-scroll-start",
9041
9053
  "pointer-events-none absolute top-0 bottom-0 left-0 z-10 w-12 md:w-18 bg-linear-to-r from-agg-secondary via-agg-secondary to-transparent",
9042
9054
  getMotionClassName(enableAnimations, "transition-opacity duration-200"),
9043
- scrollAffordanceState.showStart ? "opacity-100" : "opacity-0"
9055
+ canScrollLeft ? "opacity-100" : "opacity-0"
9044
9056
  )
9045
9057
  }
9046
9058
  ),
@@ -9052,24 +9064,63 @@ var Tabs = ({
9052
9064
  "agg-tab-scroll-end",
9053
9065
  "pointer-events-none absolute top-0 right-0 bottom-0 z-10 w-12 md:w-18 bg-linear-to-l from-agg-secondary via-agg-secondary to-transparent",
9054
9066
  getMotionClassName(enableAnimations, "transition-opacity duration-200"),
9055
- scrollAffordanceState.showEnd ? "opacity-100" : "opacity-0"
9067
+ canScrollRight ? "opacity-100" : "opacity-0"
9056
9068
  )
9057
9069
  }
9058
9070
  )
9059
9071
  ] }) : null,
9060
- shouldUseOverflowScroll && isBarVariant ? /* @__PURE__ */ jsx127(
9061
- "span",
9062
- {
9063
- "aria-hidden": true,
9064
- className: cn(
9065
- "agg-tab-scroll-end",
9066
- "pointer-events-none absolute top-0 right-0 bottom-0 z-10 w-[120px] overflow-hidden rounded-r-[8px] bg-linear-to-l from-agg-secondary from-[20%] via-agg-secondary/85 to-transparent",
9067
- getMotionClassName(enableAnimations, "transition-opacity duration-200"),
9068
- scrollAffordanceState.showEnd ? "opacity-100" : "opacity-0"
9069
- ),
9070
- children: /* @__PURE__ */ jsx127("span", { className: "absolute inset-y-0 right-3 inline-flex items-center text-agg-foreground", children: /* @__PURE__ */ jsx127(Icon, { name: "chevron-right", size: "small", color: "currentColor" }) })
9071
- }
9072
- ) : null
9072
+ shouldUseOverflowScroll && isBarVariant ? /* @__PURE__ */ jsxs120(Fragment9, { children: [
9073
+ /* @__PURE__ */ jsx127(
9074
+ "button",
9075
+ {
9076
+ type: "button",
9077
+ "aria-label": labels.common.scrollTabsLeft,
9078
+ tabIndex: -1,
9079
+ className: cn(
9080
+ "agg-tab-scroll-start",
9081
+ "absolute top-0 bottom-0 left-0 z-10 w-20 rounded-l-agg-lg",
9082
+ "inline-flex items-center justify-start pl-2",
9083
+ "bg-linear-to-r from-agg-secondary from-[25%] via-agg-secondary/80 to-transparent",
9084
+ "cursor-pointer",
9085
+ getMotionClassName(enableAnimations, "transition-opacity duration-200"),
9086
+ canScrollLeft ? "opacity-100" : "opacity-0 pointer-events-none"
9087
+ ),
9088
+ onClick: () => {
9089
+ var _a;
9090
+ (_a = tabListRef.current) == null ? void 0 : _a.scrollBy({
9091
+ left: -200,
9092
+ behavior: getScrollBehavior(enableAnimations)
9093
+ });
9094
+ },
9095
+ children: /* @__PURE__ */ jsx127(Icon, { name: "chevron-left", size: "small", color: "currentColor" })
9096
+ }
9097
+ ),
9098
+ /* @__PURE__ */ jsx127(
9099
+ "button",
9100
+ {
9101
+ type: "button",
9102
+ "aria-label": labels.common.scrollTabsRight,
9103
+ tabIndex: -1,
9104
+ className: cn(
9105
+ "agg-tab-scroll-end",
9106
+ "absolute top-0 right-0 bottom-0 z-10 w-20 rounded-r-agg-lg",
9107
+ "inline-flex items-center justify-end pr-2",
9108
+ "bg-linear-to-l from-agg-secondary from-[25%] via-agg-secondary/80 to-transparent",
9109
+ "cursor-pointer",
9110
+ getMotionClassName(enableAnimations, "transition-opacity duration-200"),
9111
+ canScrollRight ? "opacity-100" : "opacity-0 pointer-events-none"
9112
+ ),
9113
+ onClick: () => {
9114
+ var _a;
9115
+ (_a = tabListRef.current) == null ? void 0 : _a.scrollBy({
9116
+ left: 200,
9117
+ behavior: getScrollBehavior(enableAnimations)
9118
+ });
9119
+ },
9120
+ children: /* @__PURE__ */ jsx127(Icon, { name: "chevron-right", size: "small", color: "currentColor" })
9121
+ }
9122
+ )
9123
+ ] }) : null
9073
9124
  ]
9074
9125
  }
9075
9126
  );
@@ -9080,11 +9131,11 @@ Tabs.displayName = "Tabs";
9080
9131
  import * as RadixToast from "@radix-ui/react-toast";
9081
9132
  import {
9082
9133
  createContext,
9083
- useCallback as useCallback6,
9134
+ useCallback as useCallback7,
9084
9135
  useContext,
9085
- useEffect as useEffect9,
9086
- useRef as useRef9,
9087
- useState as useState10
9136
+ useEffect as useEffect10,
9137
+ useRef as useRef10,
9138
+ useState as useState11
9088
9139
  } from "react";
9089
9140
  import { jsx as jsx128, jsxs as jsxs121 } from "react/jsx-runtime";
9090
9141
  var DEFAULT_DURATION_MS = 5e3;
@@ -9109,12 +9160,12 @@ function ToastProvider({
9109
9160
  swipeThreshold = 50,
9110
9161
  viewportClassName
9111
9162
  }) {
9112
- const [toasts, setToasts] = useState10([]);
9113
- const idRef = useRef9(0);
9114
- const dismiss = useCallback6((id) => {
9163
+ const [toasts, setToasts] = useState11([]);
9164
+ const idRef = useRef10(0);
9165
+ const dismiss = useCallback7((id) => {
9115
9166
  setToasts((current) => current.filter((entry) => entry.id !== id));
9116
9167
  }, []);
9117
- const toast = useCallback6(
9168
+ const toast = useCallback7(
9118
9169
  (message, options) => {
9119
9170
  const id = ++idRef.current;
9120
9171
  setToasts((current) => {
@@ -9159,31 +9210,31 @@ function ToastProvider({
9159
9210
  ] }) });
9160
9211
  }
9161
9212
  function ToastRow({ entry, onOpenChange }) {
9162
- const [isOpen, setIsOpen] = useState10(true);
9213
+ const [isOpen, setIsOpen] = useState11(true);
9163
9214
  const hasAutoDismiss = entry.durationMs > 0 && Number.isFinite(entry.durationMs);
9164
9215
  const duration = hasAutoDismiss ? entry.durationMs : Number.POSITIVE_INFINITY;
9165
- const timeoutRef = useRef9(null);
9166
- const closeTimeoutRef = useRef9(null);
9167
- const remainingMsRef = useRef9(duration);
9168
- const timerStartedAtRef = useRef9(null);
9169
- const onOpenChangeRef = useRef9(onOpenChange);
9216
+ const timeoutRef = useRef10(null);
9217
+ const closeTimeoutRef = useRef10(null);
9218
+ const remainingMsRef = useRef10(duration);
9219
+ const timerStartedAtRef = useRef10(null);
9220
+ const onOpenChangeRef = useRef10(onOpenChange);
9170
9221
  const rootStyle = {
9171
9222
  "--agg-toast-duration": `${duration}ms`
9172
9223
  };
9173
- useEffect9(() => {
9224
+ useEffect10(() => {
9174
9225
  onOpenChangeRef.current = onOpenChange;
9175
9226
  }, [onOpenChange]);
9176
- const clearDismissTimer = useCallback6(() => {
9227
+ const clearDismissTimer = useCallback7(() => {
9177
9228
  if (!timeoutRef.current) return;
9178
9229
  clearTimeout(timeoutRef.current);
9179
9230
  timeoutRef.current = null;
9180
9231
  }, []);
9181
- const clearCloseTimer = useCallback6(() => {
9232
+ const clearCloseTimer = useCallback7(() => {
9182
9233
  if (!closeTimeoutRef.current) return;
9183
9234
  clearTimeout(closeTimeoutRef.current);
9184
9235
  closeTimeoutRef.current = null;
9185
9236
  }, []);
9186
- const handleOpenChange = useCallback6(
9237
+ const handleOpenChange = useCallback7(
9187
9238
  (open) => {
9188
9239
  if (open) {
9189
9240
  clearCloseTimer();
@@ -9200,7 +9251,7 @@ function ToastRow({ entry, onOpenChange }) {
9200
9251
  },
9201
9252
  [clearCloseTimer, clearDismissTimer]
9202
9253
  );
9203
- const startDismissTimer = useCallback6(() => {
9254
+ const startDismissTimer = useCallback7(() => {
9204
9255
  if (!hasAutoDismiss) return;
9205
9256
  clearDismissTimer();
9206
9257
  timerStartedAtRef.current = Date.now();
@@ -9208,18 +9259,18 @@ function ToastRow({ entry, onOpenChange }) {
9208
9259
  handleOpenChange(false);
9209
9260
  }, remainingMsRef.current);
9210
9261
  }, [clearDismissTimer, handleOpenChange, hasAutoDismiss]);
9211
- const handlePauseDismissTimer = useCallback6(() => {
9262
+ const handlePauseDismissTimer = useCallback7(() => {
9212
9263
  if (!hasAutoDismiss || timerStartedAtRef.current === null) return;
9213
9264
  const elapsedMs = Date.now() - timerStartedAtRef.current;
9214
9265
  remainingMsRef.current = Math.max(0, remainingMsRef.current - elapsedMs);
9215
9266
  timerStartedAtRef.current = null;
9216
9267
  clearDismissTimer();
9217
9268
  }, [clearDismissTimer, hasAutoDismiss]);
9218
- const handleResumeDismissTimer = useCallback6(() => {
9269
+ const handleResumeDismissTimer = useCallback7(() => {
9219
9270
  if (!hasAutoDismiss || timerStartedAtRef.current !== null) return;
9220
9271
  startDismissTimer();
9221
9272
  }, [hasAutoDismiss, startDismissTimer]);
9222
- useEffect9(() => {
9273
+ useEffect10(() => {
9223
9274
  remainingMsRef.current = duration;
9224
9275
  startDismissTimer();
9225
9276
  return () => {