@loafmarkets/ui 0.1.40 → 0.1.42

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.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React5 from 'react';
2
- import React5__default, { createContext, useState, useEffect, useMemo, useRef, useCallback, useContext } from 'react';
2
+ import React5__default, { createContext, useState, useEffect, useMemo, useCallback, useRef, useContext } from 'react';
3
3
  import { Slot } from '@radix-ui/react-slot';
4
4
  import { cva } from 'class-variance-authority';
5
5
  import { clsx } from 'clsx';
@@ -1984,7 +1984,7 @@ function DesktopOrderbookLayout({
1984
1984
  /* @__PURE__ */ jsx(
1985
1985
  "div",
1986
1986
  {
1987
- className: "divide-y divide-white/5 overflow-y-auto",
1987
+ className: "flex flex-col justify-end divide-y divide-white/5 overflow-y-auto",
1988
1988
  style: { height: `${sectionHeight}px`, scrollbarGutter: "stable" },
1989
1989
  children: asks.map((l, idx) => /* @__PURE__ */ jsx(
1990
1990
  DepthRow,
@@ -4850,8 +4850,9 @@ var Header = ({
4850
4850
  const portfolioActive = resolvedActiveTab === "portfolio";
4851
4851
  const learnActive = resolvedActiveTab === "learn";
4852
4852
  return /* @__PURE__ */ jsxs(Fragment, { children: [
4853
+ /* @__PURE__ */ jsx(SafeAreaCover, {}),
4853
4854
  /* @__PURE__ */ jsx(Overlay, { $isOpen: isMobileMenuOpen, onClick: () => setIsMobileMenuOpen(false) }),
4854
- /* @__PURE__ */ jsxs(HeaderContainer, { children: [
4855
+ /* @__PURE__ */ jsxs(HeaderContainer, { id: "loaf-header", children: [
4855
4856
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [
4856
4857
  /* @__PURE__ */ jsxs(Logo, { children: [
4857
4858
  /* @__PURE__ */ jsx(LogoLink, { href: logoHref ?? resolvedHomePath, onClick: handleLogoNavigation, children: /* @__PURE__ */ jsx("img", { src: Loaf_logo_Banner_default, alt: "LOAF Logo" }) }),
@@ -5089,6 +5090,7 @@ var Header = ({
5089
5090
  )
5090
5091
  ] })
5091
5092
  ] }),
5093
+ /* @__PURE__ */ jsx(HeaderSpacer, {}),
5092
5094
  LoginPopupComponent && showLoginPopup && /* @__PURE__ */ jsx(
5093
5095
  LoginPopupComponent,
5094
5096
  {
@@ -5099,6 +5101,17 @@ var Header = ({
5099
5101
  ] });
5100
5102
  };
5101
5103
  Header.displayName = "Header";
5104
+ var SafeAreaCover = styled24.div`
5105
+ position: fixed;
5106
+ top: 0;
5107
+ left: 0;
5108
+ right: 0;
5109
+ height: env(safe-area-inset-top, 0px);
5110
+ min-height: env(safe-area-inset-top, 0px);
5111
+ background-color: #0d1117;
5112
+ z-index: 1001;
5113
+ pointer-events: none;
5114
+ `;
5102
5115
  var Overlay = styled24.div`
5103
5116
  display: ${(props) => props.$isOpen ? "block" : "none"};
5104
5117
  position: fixed;
@@ -5145,22 +5158,34 @@ var HeaderContainer = styled24.header`
5145
5158
  display: flex;
5146
5159
  justify-content: space-between;
5147
5160
  align-items: center;
5161
+ /* Split padding so browsers that don't support env() inside shorthand
5162
+ still get the horizontal padding — only the top falls back to 0 */
5148
5163
  padding: 0 2rem;
5164
+ padding-top: env(safe-area-inset-top, 0px);
5149
5165
  background-color: #0d1117;
5150
5166
  border-bottom: 1px solid #232a32;
5151
- position: sticky;
5167
+ position: fixed;
5152
5168
  top: 0;
5153
5169
  left: 0;
5154
5170
  right: 0;
5155
5171
  z-index: 1000;
5156
5172
  width: 100%;
5157
- height: 56px;
5173
+ /* Fallback min-height for browsers that can't evaluate calc+env */
5174
+ min-height: 56px;
5175
+ min-height: calc(56px + env(safe-area-inset-top, 0px));
5158
5176
  box-sizing: border-box;
5159
5177
 
5160
5178
  @media (max-width: 768px) {
5161
5179
  padding: 0 1rem;
5180
+ padding-top: env(safe-area-inset-top, 0px);
5162
5181
  }
5163
5182
  `;
5183
+ var HeaderSpacer = styled24.div`
5184
+ width: 100%;
5185
+ min-height: 56px;
5186
+ min-height: calc(56px + env(safe-area-inset-top, 0px));
5187
+ flex-shrink: 0;
5188
+ `;
5164
5189
  var Logo = styled24.div`
5165
5190
  display: flex;
5166
5191
  align-items: center;
@@ -5213,10 +5238,12 @@ var Nav = styled24.nav`
5213
5238
  @media (max-width: 1300px) {
5214
5239
  position: fixed;
5215
5240
  top: 56px;
5241
+ top: calc(56px + env(safe-area-inset-top, 0px));
5216
5242
  right: ${(props) => props.$isOpen ? "0" : "-100%"} ;
5217
5243
  width: 280px;
5218
5244
  max-width: 280px;
5219
5245
  height: calc(100vh - 56px);
5246
+ height: calc(100vh - 56px - env(safe-area-inset-top, 0px));
5220
5247
  background: linear-gradient(180deg, #0f1419 0%, #0a0e13 100%);
5221
5248
  z-index: 1000;
5222
5249
  transition: right 0.3s ease;
@@ -9756,6 +9783,7 @@ function OrderPanel({
9756
9783
  displayedOwnedTokens,
9757
9784
  ownedTokensJustUpdated,
9758
9785
  lastOrderQuantity,
9786
+ orderPendingAllocation,
9759
9787
  orderPlacedSuccess,
9760
9788
  lastOrderDetails,
9761
9789
  tokenQuantity,
@@ -9818,7 +9846,40 @@ function OrderPanel({
9818
9846
  statusLabel
9819
9847
  ] })
9820
9848
  ] }),
9821
- orderPlacedSuccess ? /* @__PURE__ */ jsxs(OrderSuccessCard, { children: [
9849
+ orderPendingAllocation ? /* @__PURE__ */ jsxs(OrderPendingCard, { children: [
9850
+ /* @__PURE__ */ jsxs("div", { className: "pending-header", children: [
9851
+ /* @__PURE__ */ jsx("div", { className: "spinner" }),
9852
+ /* @__PURE__ */ jsxs("div", { children: [
9853
+ /* @__PURE__ */ jsx("p", { children: "Processing Order" }),
9854
+ /* @__PURE__ */ jsx("small", { children: "Awaiting allocation..." })
9855
+ ] })
9856
+ ] }),
9857
+ /* @__PURE__ */ jsxs("div", { className: "pending-body", children: [
9858
+ [
9859
+ { label: "Units Requested", value: /* @__PURE__ */ jsxs(Fragment, { children: [
9860
+ lastOrderDetails?.tokens?.toFixed(2) || "0.00",
9861
+ " ",
9862
+ /* @__PURE__ */ jsx("span", { style: { color: "rgba(255,255,255,0.4)", fontWeight: 400 }, children: tokenSymbol })
9863
+ ] }) },
9864
+ { label: "Price Per Unit", value: `$${tokenPrice.toFixed(2)}` },
9865
+ {
9866
+ label: `${tokenDisplayName} Exposure`,
9867
+ value: `${((lastOrderDetails?.tokens ?? 0) / supplyToSell * 100).toFixed(3)}%`
9868
+ }
9869
+ ].map((row) => /* @__PURE__ */ jsxs("div", { className: "pending-row", children: [
9870
+ /* @__PURE__ */ jsx("span", { children: row.label }),
9871
+ /* @__PURE__ */ jsx("strong", { children: row.value })
9872
+ ] }, row.label)),
9873
+ /* @__PURE__ */ jsxs("div", { className: "pending-total", children: [
9874
+ /* @__PURE__ */ jsx("span", { children: "Total Investment" }),
9875
+ /* @__PURE__ */ jsxs("strong", { children: [
9876
+ "$",
9877
+ lastOrderDetails?.total?.toLocaleString() || "0"
9878
+ ] })
9879
+ ] })
9880
+ ] }),
9881
+ /* @__PURE__ */ jsx("div", { className: "pending-footnote", children: "Your order has been submitted and is being processed. This usually takes a few seconds." })
9882
+ ] }) : orderPlacedSuccess ? /* @__PURE__ */ jsxs(OrderSuccessCard, { children: [
9822
9883
  /* @__PURE__ */ jsxs("div", { className: "success-header", children: [
9823
9884
  /* @__PURE__ */ jsx("div", { className: "icon", children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "#D4AF37", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" }) }) }),
9824
9885
  /* @__PURE__ */ jsxs("div", { children: [
@@ -9997,7 +10058,7 @@ function OrderPanel({
9997
10058
  ] })
9998
10059
  ] })
9999
10060
  ] }),
10000
- !orderPlacedSuccess && /* @__PURE__ */ jsx(
10061
+ !orderPlacedSuccess && !orderPendingAllocation && /* @__PURE__ */ jsx(
10001
10062
  SubscribeButton,
10002
10063
  {
10003
10064
  type: "button",
@@ -10320,6 +10381,110 @@ var BalanceSub = styled24.div`
10320
10381
  color: var(--color-text-secondary);
10321
10382
  margin-top: 0.25rem;
10322
10383
  `;
10384
+ var OrderPendingCard = styled24.div`
10385
+ margin-bottom: 1.5rem;
10386
+ background: linear-gradient(180deg, rgba(25,27,31,0.95) 0%, rgba(18,20,24,0.98) 100%);
10387
+ border: 1px solid rgba(212,175,55,0.08);
10388
+ border-radius: 12px;
10389
+ overflow: hidden;
10390
+ box-shadow: 0 4px 20px rgba(0,0,0,0.3);
10391
+
10392
+ @keyframes spin {
10393
+ to { transform: rotate(360deg); }
10394
+ }
10395
+
10396
+ @keyframes pulse {
10397
+ 0%, 100% { opacity: 1; }
10398
+ 50% { opacity: 0.6; }
10399
+ }
10400
+
10401
+ .pending-header {
10402
+ border-bottom: 1px solid rgba(255,255,255,0.06);
10403
+ padding: 1.25rem 1.5rem;
10404
+ display: flex;
10405
+ align-items: center;
10406
+ gap: 0.875rem;
10407
+ background: linear-gradient(135deg, rgba(212,175,55,0.04) 0%, transparent 100%);
10408
+
10409
+ .spinner {
10410
+ width: 32px;
10411
+ height: 32px;
10412
+ border-radius: 50%;
10413
+ border: 2.5px solid rgba(212,175,55,0.15);
10414
+ border-top-color: #D4AF37;
10415
+ animation: spin 0.8s linear infinite;
10416
+ flex-shrink: 0;
10417
+ }
10418
+
10419
+ p {
10420
+ font-size: 0.95rem;
10421
+ font-weight: 600;
10422
+ color: #fff;
10423
+ margin: 0;
10424
+ animation: pulse 2s ease-in-out infinite;
10425
+ }
10426
+ small {
10427
+ font-size: 0.7rem;
10428
+ color: rgba(255,255,255,0.4);
10429
+ }
10430
+ }
10431
+
10432
+ .pending-body {
10433
+ padding: 1.25rem 1.5rem;
10434
+ }
10435
+ .pending-row {
10436
+ display: flex;
10437
+ justify-content: space-between;
10438
+ align-items: center;
10439
+ padding-bottom: 0.875rem;
10440
+ margin-bottom: 0.875rem;
10441
+ border-bottom: 1px solid rgba(255,255,255,0.06);
10442
+ span {
10443
+ font-size: 0.75rem;
10444
+ color: rgba(255,255,255,0.4);
10445
+ text-transform: uppercase;
10446
+ letter-spacing: 0.05em;
10447
+ font-weight: 500;
10448
+ }
10449
+ strong {
10450
+ font-size: 0.95rem;
10451
+ font-weight: 500;
10452
+ color: rgba(255,255,255,0.5);
10453
+ font-family: monospace;
10454
+ }
10455
+ }
10456
+ .pending-total {
10457
+ display: flex;
10458
+ justify-content: space-between;
10459
+ align-items: center;
10460
+ padding: 0.875rem;
10461
+ background: rgba(212,175,55,0.03);
10462
+ border-radius: 8px;
10463
+ border: 1px solid rgba(212,175,55,0.06);
10464
+ span {
10465
+ font-size: 0.75rem;
10466
+ color: rgba(255,255,255,0.5);
10467
+ text-transform: uppercase;
10468
+ letter-spacing: 0.05em;
10469
+ font-weight: 500;
10470
+ }
10471
+ strong {
10472
+ font-size: 1.05rem;
10473
+ font-weight: 700;
10474
+ color: rgba(212,175,55,0.7);
10475
+ font-family: monospace;
10476
+ }
10477
+ }
10478
+ .pending-footnote {
10479
+ padding: 1rem 1.5rem;
10480
+ border-top: 1px solid rgba(255,255,255,0.06);
10481
+ background: rgba(0,0,0,0.2);
10482
+ font-size: 0.75rem;
10483
+ color: rgba(255,255,255,0.4);
10484
+ line-height: 1.6;
10485
+ animation: pulse 2s ease-in-out infinite;
10486
+ }
10487
+ `;
10323
10488
  var OrderSuccessCard = styled24.div`
10324
10489
  margin-bottom: 1.5rem;
10325
10490
  background: linear-gradient(180deg, rgba(25,27,31,0.95) 0%, rgba(18,20,24,0.98) 100%);
@@ -11175,6 +11340,7 @@ function OrderConfirmationModal({
11175
11340
  tokenQuantity,
11176
11341
  tokenPrice,
11177
11342
  propertyName,
11343
+ tokenSymbol,
11178
11344
  estExposure,
11179
11345
  orderTotal,
11180
11346
  availableBalance,
@@ -11189,7 +11355,7 @@ function OrderConfirmationModal({
11189
11355
  /* @__PURE__ */ jsx(ModalBody, { children: [
11190
11356
  { label: "Order Type", value: "Primary Offering" },
11191
11357
  { label: "Property", value: propertyName },
11192
- { label: "Units", value: `${tokenQuantity.toLocaleString()} MUS`, highlight: true },
11358
+ { label: "Units", value: `${tokenQuantity.toLocaleString()} ${tokenSymbol}`, highlight: true },
11193
11359
  {
11194
11360
  label: "Unit Price",
11195
11361
  value: `$${tokenPrice.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`
@@ -11220,7 +11386,9 @@ function OrderConfirmationModal({
11220
11386
  "Your order for ",
11221
11387
  /* @__PURE__ */ jsxs("strong", { children: [
11222
11388
  tokenQuantity.toLocaleString(),
11223
- " MUS units"
11389
+ " ",
11390
+ tokenSymbol,
11391
+ " units"
11224
11392
  ] }),
11225
11393
  " in the",
11226
11394
  " ",
@@ -11449,6 +11617,7 @@ function PropertyBuy({
11449
11617
  const [displayedOwnedTokens, setDisplayedOwnedTokens] = useState(0);
11450
11618
  const [ownedTokensJustUpdated, setOwnedTokensJustUpdated] = useState(false);
11451
11619
  const [lastOrderQuantity, setLastOrderQuantity] = useState(0);
11620
+ const [orderPendingAllocation, setOrderPendingAllocation] = useState(false);
11452
11621
  const [orderPlacedSuccess, setOrderPlacedSuccess] = useState(false);
11453
11622
  const [lastOrderDetails, setLastOrderDetails] = useState(null);
11454
11623
  const [showOrderConfirmModal, setShowOrderConfirmModal] = useState(false);
@@ -11496,12 +11665,23 @@ function PropertyBuy({
11496
11665
  }
11497
11666
  setShowOrderConfirmModal(true);
11498
11667
  };
11499
- const isPurchaseInFlight = purchaseStatus === "checking-allowance" || purchaseStatus === "approving" || purchaseStatus === "purchasing";
11668
+ useEffect(() => {
11669
+ if (purchaseStatus === "success" && orderPendingAllocation) {
11670
+ setOrderPendingAllocation(false);
11671
+ setOrderPlacedSuccess(true);
11672
+ }
11673
+ }, [purchaseStatus, orderPendingAllocation]);
11674
+ const handlePlaceAnotherOrder = useCallback(() => {
11675
+ setOrderPlacedSuccess(false);
11676
+ setOrderPendingAllocation(false);
11677
+ }, []);
11678
+ const isPurchaseInFlight = purchaseStatus === "checking-allowance" || purchaseStatus === "approving" || purchaseStatus === "purchasing" || purchaseStatus === "pending-allocation";
11500
11679
  const getOrderButtonText = () => {
11501
11680
  if (!isAuthenticated) return "Sign In to Invest";
11502
11681
  if (purchaseStatus === "checking-allowance") return "Checking allowance\u2026";
11503
11682
  if (purchaseStatus === "approving") return "Approving USDC\u2026";
11504
11683
  if (purchaseStatus === "purchasing") return "Confirming purchase\u2026";
11684
+ if (purchaseStatus === "pending-allocation") return "Awaiting allocation\u2026";
11505
11685
  if (ipoStatus === "PENDING" && !isPrivateClient) return "Sale Not Open Yet";
11506
11686
  if (ipoStatus === "CLOSED") return "Sale Completed";
11507
11687
  if (ipoStatus === "CANCELLED") return "Sale Cancelled";
@@ -11544,7 +11724,7 @@ function PropertyBuy({
11544
11724
  total: orderTotal,
11545
11725
  price: tokenPrice
11546
11726
  });
11547
- setOrderPlacedSuccess(true);
11727
+ setOrderPendingAllocation(true);
11548
11728
  setSliderValue(0);
11549
11729
  setManualOrderAmount(null);
11550
11730
  };
@@ -11630,6 +11810,7 @@ function PropertyBuy({
11630
11810
  displayedOwnedTokens,
11631
11811
  ownedTokensJustUpdated,
11632
11812
  lastOrderQuantity,
11813
+ orderPendingAllocation,
11633
11814
  orderPlacedSuccess,
11634
11815
  lastOrderDetails,
11635
11816
  tokenQuantity,
@@ -11644,7 +11825,7 @@ function PropertyBuy({
11644
11825
  orderButtonText: getOrderButtonText(),
11645
11826
  isOrderButtonDisabled: isOrderButtonDisabled(),
11646
11827
  hasInsufficientFunds,
11647
- onPlaceAnotherOrder: () => setOrderPlacedSuccess(false),
11828
+ onPlaceAnotherOrder: handlePlaceAnotherOrder,
11648
11829
  onDeposit
11649
11830
  }
11650
11831
  ),
@@ -11678,6 +11859,7 @@ function PropertyBuy({
11678
11859
  tokenQuantity,
11679
11860
  tokenPrice,
11680
11861
  propertyName,
11862
+ tokenSymbol,
11681
11863
  estExposure,
11682
11864
  orderTotal,
11683
11865
  availableBalance,