@loafmarkets/ui 0.1.56 → 0.1.57

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.js CHANGED
@@ -9416,191 +9416,6 @@ var SignInButton = styled25__default.default.button`
9416
9416
  background: rgba(240, 185, 11, 0.1);
9417
9417
  }
9418
9418
  `;
9419
- var slideIn = styled25.keyframes`
9420
- from { transform: translateX(110%); opacity: 0; }
9421
- to { transform: translateX(0); opacity: 1; }
9422
- `;
9423
- var slideOut = styled25.keyframes`
9424
- from { transform: translateX(0); opacity: 1; }
9425
- to { transform: translateX(110%); opacity: 0; }
9426
- `;
9427
- var progressShrink = styled25.keyframes`
9428
- from { width: 100%; }
9429
- to { width: 0%; }
9430
- `;
9431
- var VARIANT_COLORS = {
9432
- success: { accent: "#0ecb81", icon: "\u2713" },
9433
- error: { accent: "#f6465d", icon: "\u2715" },
9434
- info: { accent: "#E6C656", icon: "\u2139" },
9435
- pending: { accent: "#7EB3E6", icon: "\u25CC" }
9436
- };
9437
- var Wrapper = styled25__default.default.div`
9438
- position: relative;
9439
- display: flex;
9440
- flex-direction: column;
9441
- gap: 0;
9442
- width: 340px;
9443
- background: #0d0f1a;
9444
- border: 1px solid rgba(255, 255, 255, 0.08);
9445
- border-radius: 10px;
9446
- overflow: hidden;
9447
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.04);
9448
- animation: ${({ $exiting }) => $exiting ? styled25.css`${slideOut} 0.28s cubic-bezier(0.4,0,1,1) forwards` : styled25.css`${slideIn} 0.32s cubic-bezier(0,0,0.2,1) forwards`};
9449
- pointer-events: all;
9450
- `;
9451
- var Body = styled25__default.default.div`
9452
- display: flex;
9453
- align-items: flex-start;
9454
- gap: 12px;
9455
- padding: 14px 16px 12px;
9456
- `;
9457
- var IconDot = styled25__default.default.div`
9458
- flex-shrink: 0;
9459
- width: 28px;
9460
- height: 28px;
9461
- border-radius: 50%;
9462
- background: ${({ $color }) => $color}1a;
9463
- border: 1px solid ${({ $color }) => $color}55;
9464
- display: flex;
9465
- align-items: center;
9466
- justify-content: center;
9467
- font-size: 0.75rem;
9468
- font-weight: 700;
9469
- color: ${({ $color }) => $color};
9470
- margin-top: 1px;
9471
- `;
9472
- var Content = styled25__default.default.div`
9473
- flex: 1;
9474
- min-width: 0;
9475
- `;
9476
- var Title2 = styled25__default.default.p`
9477
- margin: 0 0 2px;
9478
- font-size: 0.8rem;
9479
- font-weight: 600;
9480
- color: #fff;
9481
- letter-spacing: 0.01em;
9482
- `;
9483
- var Amount = styled25__default.default.p`
9484
- margin: 0 0 6px;
9485
- font-size: 1.05rem;
9486
- font-weight: 700;
9487
- color: #E6C656;
9488
- letter-spacing: -0.01em;
9489
- `;
9490
- var TxRow = styled25__default.default.a`
9491
- display: inline-flex;
9492
- align-items: center;
9493
- gap: 5px;
9494
- font-family: 'IBM Plex Mono', 'Space Mono', monospace;
9495
- font-size: 0.68rem;
9496
- color: rgba(255, 255, 255, 0.4);
9497
- text-decoration: none;
9498
- transition: color 0.15s;
9499
- &:hover {
9500
- color: #7EB3E6;
9501
- }
9502
- `;
9503
- var TxArrow = styled25__default.default.span`
9504
- font-size: 0.6rem;
9505
- opacity: 0.6;
9506
- `;
9507
- var CloseBtn = styled25__default.default.button`
9508
- flex-shrink: 0;
9509
- background: none;
9510
- border: none;
9511
- padding: 2px 4px;
9512
- cursor: pointer;
9513
- color: rgba(255, 255, 255, 0.25);
9514
- font-size: 0.9rem;
9515
- line-height: 1;
9516
- transition: color 0.15s;
9517
- &:hover { color: rgba(255, 255, 255, 0.7); }
9518
- `;
9519
- var ProgressBar = styled25__default.default.div`
9520
- height: 2px;
9521
- background: rgba(255, 255, 255, 0.06);
9522
- position: relative;
9523
- &::after {
9524
- content: '';
9525
- position: absolute;
9526
- left: 0;
9527
- top: 0;
9528
- height: 100%;
9529
- background: ${({ $color }) => $color};
9530
- animation: ${styled25.css`${progressShrink} ${({ $duration }) => $duration}ms linear forwards`};
9531
- }
9532
- `;
9533
- var Container = styled25__default.default.div`
9534
- position: fixed;
9535
- bottom: 24px;
9536
- right: 24px;
9537
- z-index: 9999;
9538
- display: flex;
9539
- flex-direction: column-reverse;
9540
- gap: 10px;
9541
- pointer-events: none;
9542
- `;
9543
- var DEFAULT_EXPLORER = "https://sepolia.basescan.org/tx/";
9544
- function truncateHash(hash) {
9545
- return `${hash.slice(0, 6)}\u2026${hash.slice(-4)}`;
9546
- }
9547
- function ToastItem({ toast, onDismiss }) {
9548
- const [exiting, setExiting] = React5.useState(false);
9549
- const timerRef = React5.useRef(null);
9550
- const dismiss = React5.useCallback(() => {
9551
- setExiting(true);
9552
- setTimeout(() => onDismiss(toast.id), 280);
9553
- }, [onDismiss, toast.id]);
9554
- React5.useEffect(() => {
9555
- const duration2 = toast.duration ?? 6e3;
9556
- if (duration2 > 0) {
9557
- timerRef.current = setTimeout(dismiss, duration2);
9558
- }
9559
- return () => {
9560
- if (timerRef.current) clearTimeout(timerRef.current);
9561
- };
9562
- }, [dismiss, toast.duration]);
9563
- const { accent, icon } = VARIANT_COLORS[toast.variant];
9564
- const duration = toast.duration ?? 6e3;
9565
- const explorerBase = toast.explorerUrl ?? DEFAULT_EXPLORER;
9566
- const txUrl = toast.txHash ? `${explorerBase}${toast.txHash}` : void 0;
9567
- return /* @__PURE__ */ jsxRuntime.jsxs(Wrapper, { $exiting: exiting, children: [
9568
- /* @__PURE__ */ jsxRuntime.jsxs(Body, { children: [
9569
- /* @__PURE__ */ jsxRuntime.jsx(IconDot, { $color: accent, children: icon }),
9570
- /* @__PURE__ */ jsxRuntime.jsxs(Content, { children: [
9571
- /* @__PURE__ */ jsxRuntime.jsx(Title2, { children: toast.title }),
9572
- toast.amount && /* @__PURE__ */ jsxRuntime.jsx(Amount, { children: toast.amount }),
9573
- toast.txHash && txUrl && /* @__PURE__ */ jsxRuntime.jsxs(TxRow, { href: txUrl, target: "_blank", rel: "noopener noreferrer", children: [
9574
- truncateHash(toast.txHash),
9575
- /* @__PURE__ */ jsxRuntime.jsx(TxArrow, { children: "\u2197" })
9576
- ] })
9577
- ] }),
9578
- /* @__PURE__ */ jsxRuntime.jsx(CloseBtn, { type: "button", onClick: dismiss, "aria-label": "Dismiss", children: "\u2715" })
9579
- ] }),
9580
- duration > 0 && /* @__PURE__ */ jsxRuntime.jsx(ProgressBar, { $color: accent, $duration: duration })
9581
- ] });
9582
- }
9583
- var ToastContext = React5.createContext(null);
9584
- function ToastProvider({ children }) {
9585
- const [toasts, setToasts] = React5.useState([]);
9586
- const addToast = React5.useCallback((data) => {
9587
- const id = `toast-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
9588
- setToasts((prev) => [...prev, { ...data, id }]);
9589
- return id;
9590
- }, []);
9591
- const dismiss = React5.useCallback((id) => {
9592
- setToasts((prev) => prev.filter((t) => t.id !== id));
9593
- }, []);
9594
- return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value: { toast: addToast, dismiss }, children: [
9595
- children,
9596
- /* @__PURE__ */ jsxRuntime.jsx(Container, { children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsx(ToastItem, { toast: t, onDismiss: dismiss }, t.id)) })
9597
- ] });
9598
- }
9599
- function useToast() {
9600
- const ctx = React5.useContext(ToastContext);
9601
- if (!ctx) throw new Error("useToast must be used within a ToastProvider");
9602
- return ctx;
9603
- }
9604
9419
  function AssetSelectorBar({
9605
9420
  propertyName,
9606
9421
  tokenPrice,
@@ -9907,7 +9722,7 @@ function OfferingProgressCard({
9907
9722
  const interval = setInterval(() => setCountdown(calculateCountdown()), 1e3);
9908
9723
  return () => clearInterval(interval);
9909
9724
  }, [opensAt]);
9910
- return /* @__PURE__ */ jsxRuntime.jsxs(Container2, { children: [
9725
+ return /* @__PURE__ */ jsxRuntime.jsxs(Container, { children: [
9911
9726
  /* @__PURE__ */ jsxRuntime.jsxs(Header2, { children: [
9912
9727
  /* @__PURE__ */ jsxRuntime.jsxs("h3", { children: [
9913
9728
  /* @__PURE__ */ jsxRuntime.jsx(fa.FaChartLine, {}),
@@ -10008,7 +9823,7 @@ function OfferingProgressCard({
10008
9823
  ] })
10009
9824
  ] });
10010
9825
  }
10011
- var Container2 = styled25__default.default.div`
9826
+ var Container = styled25__default.default.div`
10012
9827
  background-color: var(--color-card-darker, #111);
10013
9828
  border-radius: 8px;
10014
9829
  padding: 1.5rem;
@@ -10544,6 +10359,191 @@ var LiveIndicatorDot = styled25__default.default.span`
10544
10359
  100% { box-shadow: 0 0 0 0 rgba(14,203,129,0); }
10545
10360
  }
10546
10361
  `;
10362
+ var slideIn = styled25.keyframes`
10363
+ from { transform: translateX(110%); opacity: 0; }
10364
+ to { transform: translateX(0); opacity: 1; }
10365
+ `;
10366
+ var slideOut = styled25.keyframes`
10367
+ from { transform: translateX(0); opacity: 1; }
10368
+ to { transform: translateX(110%); opacity: 0; }
10369
+ `;
10370
+ var progressShrink = styled25.keyframes`
10371
+ from { width: 100%; }
10372
+ to { width: 0%; }
10373
+ `;
10374
+ var VARIANT_COLORS = {
10375
+ success: { accent: "#0ecb81", icon: "\u2713" },
10376
+ error: { accent: "#f6465d", icon: "\u2715" },
10377
+ info: { accent: "#E6C656", icon: "\u2139" },
10378
+ pending: { accent: "#7EB3E6", icon: "\u25CC" }
10379
+ };
10380
+ var Wrapper = styled25__default.default.div`
10381
+ position: relative;
10382
+ display: flex;
10383
+ flex-direction: column;
10384
+ gap: 0;
10385
+ width: 340px;
10386
+ background: #0d0f1a;
10387
+ border: 1px solid rgba(255, 255, 255, 0.08);
10388
+ border-radius: 10px;
10389
+ overflow: hidden;
10390
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.04);
10391
+ animation: ${({ $exiting }) => $exiting ? styled25.css`${slideOut} 0.28s cubic-bezier(0.4,0,1,1) forwards` : styled25.css`${slideIn} 0.32s cubic-bezier(0,0,0.2,1) forwards`};
10392
+ pointer-events: all;
10393
+ `;
10394
+ var Body = styled25__default.default.div`
10395
+ display: flex;
10396
+ align-items: flex-start;
10397
+ gap: 12px;
10398
+ padding: 14px 16px 12px;
10399
+ `;
10400
+ var IconDot = styled25__default.default.div`
10401
+ flex-shrink: 0;
10402
+ width: 28px;
10403
+ height: 28px;
10404
+ border-radius: 50%;
10405
+ background: ${({ $color }) => $color}1a;
10406
+ border: 1px solid ${({ $color }) => $color}55;
10407
+ display: flex;
10408
+ align-items: center;
10409
+ justify-content: center;
10410
+ font-size: 0.75rem;
10411
+ font-weight: 700;
10412
+ color: ${({ $color }) => $color};
10413
+ margin-top: 1px;
10414
+ `;
10415
+ var Content = styled25__default.default.div`
10416
+ flex: 1;
10417
+ min-width: 0;
10418
+ `;
10419
+ var Title2 = styled25__default.default.p`
10420
+ margin: 0 0 2px;
10421
+ font-size: 0.8rem;
10422
+ font-weight: 600;
10423
+ color: #fff;
10424
+ letter-spacing: 0.01em;
10425
+ `;
10426
+ var Amount = styled25__default.default.p`
10427
+ margin: 0 0 6px;
10428
+ font-size: 1.05rem;
10429
+ font-weight: 700;
10430
+ color: #E6C656;
10431
+ letter-spacing: -0.01em;
10432
+ `;
10433
+ var TxRow = styled25__default.default.a`
10434
+ display: inline-flex;
10435
+ align-items: center;
10436
+ gap: 5px;
10437
+ font-family: 'IBM Plex Mono', 'Space Mono', monospace;
10438
+ font-size: 0.68rem;
10439
+ color: rgba(255, 255, 255, 0.4);
10440
+ text-decoration: none;
10441
+ transition: color 0.15s;
10442
+ &:hover {
10443
+ color: #7EB3E6;
10444
+ }
10445
+ `;
10446
+ var TxArrow = styled25__default.default.span`
10447
+ font-size: 0.6rem;
10448
+ opacity: 0.6;
10449
+ `;
10450
+ var CloseBtn = styled25__default.default.button`
10451
+ flex-shrink: 0;
10452
+ background: none;
10453
+ border: none;
10454
+ padding: 2px 4px;
10455
+ cursor: pointer;
10456
+ color: rgba(255, 255, 255, 0.25);
10457
+ font-size: 0.9rem;
10458
+ line-height: 1;
10459
+ transition: color 0.15s;
10460
+ &:hover { color: rgba(255, 255, 255, 0.7); }
10461
+ `;
10462
+ var ProgressBar = styled25__default.default.div`
10463
+ height: 2px;
10464
+ background: rgba(255, 255, 255, 0.06);
10465
+ position: relative;
10466
+ &::after {
10467
+ content: '';
10468
+ position: absolute;
10469
+ left: 0;
10470
+ top: 0;
10471
+ height: 100%;
10472
+ background: ${({ $color }) => $color};
10473
+ animation: ${styled25.css`${progressShrink} ${({ $duration }) => $duration}ms linear forwards`};
10474
+ }
10475
+ `;
10476
+ var Container2 = styled25__default.default.div`
10477
+ position: fixed;
10478
+ bottom: 24px;
10479
+ right: 24px;
10480
+ z-index: 9999;
10481
+ display: flex;
10482
+ flex-direction: column-reverse;
10483
+ gap: 10px;
10484
+ pointer-events: none;
10485
+ `;
10486
+ var DEFAULT_EXPLORER = "https://sepolia.basescan.org/tx/";
10487
+ function truncateHash(hash) {
10488
+ return `${hash.slice(0, 6)}\u2026${hash.slice(-4)}`;
10489
+ }
10490
+ function ToastItem({ toast, onDismiss }) {
10491
+ const [exiting, setExiting] = React5.useState(false);
10492
+ const timerRef = React5.useRef(null);
10493
+ const dismiss = React5.useCallback(() => {
10494
+ setExiting(true);
10495
+ setTimeout(() => onDismiss(toast.id), 280);
10496
+ }, [onDismiss, toast.id]);
10497
+ React5.useEffect(() => {
10498
+ const duration2 = toast.duration ?? 6e3;
10499
+ if (duration2 > 0) {
10500
+ timerRef.current = setTimeout(dismiss, duration2);
10501
+ }
10502
+ return () => {
10503
+ if (timerRef.current) clearTimeout(timerRef.current);
10504
+ };
10505
+ }, [dismiss, toast.duration]);
10506
+ const { accent, icon } = VARIANT_COLORS[toast.variant];
10507
+ const duration = toast.duration ?? 6e3;
10508
+ const explorerBase = toast.explorerUrl ?? DEFAULT_EXPLORER;
10509
+ const txUrl = toast.txHash ? `${explorerBase}${toast.txHash}` : void 0;
10510
+ return /* @__PURE__ */ jsxRuntime.jsxs(Wrapper, { $exiting: exiting, children: [
10511
+ /* @__PURE__ */ jsxRuntime.jsxs(Body, { children: [
10512
+ /* @__PURE__ */ jsxRuntime.jsx(IconDot, { $color: accent, children: icon }),
10513
+ /* @__PURE__ */ jsxRuntime.jsxs(Content, { children: [
10514
+ /* @__PURE__ */ jsxRuntime.jsx(Title2, { children: toast.title }),
10515
+ toast.amount && /* @__PURE__ */ jsxRuntime.jsx(Amount, { children: toast.amount }),
10516
+ toast.txHash && txUrl && /* @__PURE__ */ jsxRuntime.jsxs(TxRow, { href: txUrl, target: "_blank", rel: "noopener noreferrer", children: [
10517
+ truncateHash(toast.txHash),
10518
+ /* @__PURE__ */ jsxRuntime.jsx(TxArrow, { children: "\u2197" })
10519
+ ] })
10520
+ ] }),
10521
+ /* @__PURE__ */ jsxRuntime.jsx(CloseBtn, { type: "button", onClick: dismiss, "aria-label": "Dismiss", children: "\u2715" })
10522
+ ] }),
10523
+ duration > 0 && /* @__PURE__ */ jsxRuntime.jsx(ProgressBar, { $color: accent, $duration: duration })
10524
+ ] });
10525
+ }
10526
+ var ToastContext = React5.createContext(null);
10527
+ function ToastProvider({ children }) {
10528
+ const [toasts, setToasts] = React5.useState([]);
10529
+ const addToast = React5.useCallback((data) => {
10530
+ const id = `toast-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
10531
+ setToasts((prev) => [...prev, { ...data, id }]);
10532
+ return id;
10533
+ }, []);
10534
+ const dismiss = React5.useCallback((id) => {
10535
+ setToasts((prev) => prev.filter((t) => t.id !== id));
10536
+ }, []);
10537
+ return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value: { toast: addToast, dismiss }, children: [
10538
+ children,
10539
+ /* @__PURE__ */ jsxRuntime.jsx(Container2, { children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsx(ToastItem, { toast: t, onDismiss: dismiss }, t.id)) })
10540
+ ] });
10541
+ }
10542
+ function useToast() {
10543
+ const ctx = React5.useContext(ToastContext);
10544
+ if (!ctx) throw new Error("useToast must be used within a ToastProvider");
10545
+ return ctx;
10546
+ }
10547
10547
  function OrderPanel({
10548
10548
  statusLabel,
10549
10549
  statusColor,
@@ -10576,6 +10576,7 @@ function OrderPanel({
10576
10576
  tokenDisplayName,
10577
10577
  tokenSymbol
10578
10578
  }) {
10579
+ const { toast } = useToast();
10579
10580
  const [payInputValue, setPayInputValue] = React5.useState("");
10580
10581
  const [receiveInputValue, setReceiveInputValue] = React5.useState("");
10581
10582
  const [isPayInputFocused, setIsPayInputFocused] = React5.useState(false);
@@ -10586,6 +10587,14 @@ function OrderPanel({
10586
10587
  if (parsed <= 0) {
10587
10588
  setManualOrderAmount(null);
10588
10589
  setSliderValue(0);
10590
+ } else if (parsed < tokenPrice) {
10591
+ toast({
10592
+ variant: "error",
10593
+ title: "Amount too low",
10594
+ amount: `Minimum purchase is 1 token ($${tokenPrice.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })})`
10595
+ });
10596
+ setManualOrderAmount(null);
10597
+ setSliderValue(0);
10589
10598
  } else if (parsed >= availableBalance) {
10590
10599
  setManualOrderAmount(null);
10591
10600
  setSliderValue(100);
@@ -12582,7 +12591,6 @@ function PropertyBuy({
12582
12591
  onSelectorSelect,
12583
12592
  portfolioActivity
12584
12593
  }) {
12585
- const { toast } = useToast();
12586
12594
  const [sliderValue, setSliderValue] = React5.useState(0);
12587
12595
  const [availableBalance, setAvailableBalance] = React5.useState(walletUsdcBalance ?? 0);
12588
12596
  const [manualOrderAmount, setManualOrderAmount] = React5.useState(null);
@@ -12635,13 +12643,6 @@ function PropertyBuy({
12635
12643
  }, [walletPropertyTokenBalance]);
12636
12644
  const handleOrderButtonClick = () => {
12637
12645
  if (!ipoStarted || tokenQuantity === 0) {
12638
- if (rawSpend > 0 && tokenQuantity === 0) {
12639
- toast({
12640
- variant: "error",
12641
- title: "Amount too low",
12642
- amount: `Minimum purchase is 1 token ($${tokenPrice.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })})`
12643
- });
12644
- }
12645
12646
  return;
12646
12647
  }
12647
12648
  setShowOrderConfirmModal(true);