@loafmarkets/ui 0.1.88 → 0.1.89

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, useCallback, useContext, useRef } from 'react';
2
+ import React5__default, { createContext, useState, useEffect, useCallback, useContext, useMemo, useRef } 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';
@@ -6115,6 +6115,191 @@ var PropertySubheader = React5.forwardRef(
6115
6115
  }
6116
6116
  );
6117
6117
  PropertySubheader.displayName = "PropertySubheader";
6118
+ var slideIn = keyframes`
6119
+ from { transform: translateX(110%); opacity: 0; }
6120
+ to { transform: translateX(0); opacity: 1; }
6121
+ `;
6122
+ var slideOut = keyframes`
6123
+ from { transform: translateX(0); opacity: 1; }
6124
+ to { transform: translateX(110%); opacity: 0; }
6125
+ `;
6126
+ var progressShrink = keyframes`
6127
+ from { width: 100%; }
6128
+ to { width: 0%; }
6129
+ `;
6130
+ var VARIANT_COLORS = {
6131
+ success: { accent: "#0ecb81", icon: "\u2713" },
6132
+ error: { accent: "#f6465d", icon: "\u2715" },
6133
+ info: { accent: "#E6C656", icon: "\u2139" },
6134
+ pending: { accent: "#7EB3E6", icon: "\u25CC" }
6135
+ };
6136
+ var Wrapper = styled25.div`
6137
+ position: relative;
6138
+ display: flex;
6139
+ flex-direction: column;
6140
+ gap: 0;
6141
+ width: 340px;
6142
+ background: #0d0f1a;
6143
+ border: 1px solid rgba(255, 255, 255, 0.08);
6144
+ border-radius: 10px;
6145
+ overflow: hidden;
6146
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.04);
6147
+ animation: ${({ $exiting }) => $exiting ? css`${slideOut} 0.28s cubic-bezier(0.4,0,1,1) forwards` : css`${slideIn} 0.32s cubic-bezier(0,0,0.2,1) forwards`};
6148
+ pointer-events: all;
6149
+ `;
6150
+ var Body = styled25.div`
6151
+ display: flex;
6152
+ align-items: flex-start;
6153
+ gap: 12px;
6154
+ padding: 14px 16px 12px;
6155
+ `;
6156
+ var IconDot = styled25.div`
6157
+ flex-shrink: 0;
6158
+ width: 28px;
6159
+ height: 28px;
6160
+ border-radius: 50%;
6161
+ background: ${({ $color }) => $color}1a;
6162
+ border: 1px solid ${({ $color }) => $color}55;
6163
+ display: flex;
6164
+ align-items: center;
6165
+ justify-content: center;
6166
+ font-size: 0.75rem;
6167
+ font-weight: 700;
6168
+ color: ${({ $color }) => $color};
6169
+ margin-top: 1px;
6170
+ `;
6171
+ var Content = styled25.div`
6172
+ flex: 1;
6173
+ min-width: 0;
6174
+ `;
6175
+ var Title = styled25.p`
6176
+ margin: 0 0 2px;
6177
+ font-size: 0.8rem;
6178
+ font-weight: 600;
6179
+ color: #fff;
6180
+ letter-spacing: 0.01em;
6181
+ `;
6182
+ var Amount = styled25.p`
6183
+ margin: 0 0 6px;
6184
+ font-size: 1.05rem;
6185
+ font-weight: 700;
6186
+ color: #E6C656;
6187
+ letter-spacing: -0.01em;
6188
+ `;
6189
+ var TxRow = styled25.a`
6190
+ display: inline-flex;
6191
+ align-items: center;
6192
+ gap: 5px;
6193
+ font-family: 'IBM Plex Mono', 'Space Mono', monospace;
6194
+ font-size: 0.68rem;
6195
+ color: rgba(255, 255, 255, 0.4);
6196
+ text-decoration: none;
6197
+ transition: color 0.15s;
6198
+ &:hover {
6199
+ color: #7EB3E6;
6200
+ }
6201
+ `;
6202
+ var TxArrow = styled25.span`
6203
+ font-size: 0.6rem;
6204
+ opacity: 0.6;
6205
+ `;
6206
+ var CloseBtn = styled25.button`
6207
+ flex-shrink: 0;
6208
+ background: none;
6209
+ border: none;
6210
+ padding: 2px 4px;
6211
+ cursor: pointer;
6212
+ color: rgba(255, 255, 255, 0.25);
6213
+ font-size: 0.9rem;
6214
+ line-height: 1;
6215
+ transition: color 0.15s;
6216
+ &:hover { color: rgba(255, 255, 255, 0.7); }
6217
+ `;
6218
+ var ProgressBar = styled25.div`
6219
+ height: 2px;
6220
+ background: rgba(255, 255, 255, 0.06);
6221
+ position: relative;
6222
+ &::after {
6223
+ content: '';
6224
+ position: absolute;
6225
+ left: 0;
6226
+ top: 0;
6227
+ height: 100%;
6228
+ background: ${({ $color }) => $color};
6229
+ animation: ${css`${progressShrink} ${({ $duration }) => $duration}ms linear forwards`};
6230
+ }
6231
+ `;
6232
+ var Container = styled25.div`
6233
+ position: fixed;
6234
+ bottom: 24px;
6235
+ right: 24px;
6236
+ z-index: 9999;
6237
+ display: flex;
6238
+ flex-direction: column-reverse;
6239
+ gap: 10px;
6240
+ pointer-events: none;
6241
+ `;
6242
+ var DEFAULT_EXPLORER = "https://sepolia.basescan.org/tx/";
6243
+ function truncateHash(hash) {
6244
+ return `${hash.slice(0, 6)}\u2026${hash.slice(-4)}`;
6245
+ }
6246
+ function ToastItem({ toast, onDismiss }) {
6247
+ const [exiting, setExiting] = useState(false);
6248
+ const timerRef = useRef(null);
6249
+ const dismiss = useCallback(() => {
6250
+ setExiting(true);
6251
+ setTimeout(() => onDismiss(toast.id), 280);
6252
+ }, [onDismiss, toast.id]);
6253
+ useEffect(() => {
6254
+ const duration2 = toast.duration ?? 6e3;
6255
+ if (duration2 > 0) {
6256
+ timerRef.current = setTimeout(dismiss, duration2);
6257
+ }
6258
+ return () => {
6259
+ if (timerRef.current) clearTimeout(timerRef.current);
6260
+ };
6261
+ }, [dismiss, toast.duration]);
6262
+ const { accent, icon } = VARIANT_COLORS[toast.variant];
6263
+ const duration = toast.duration ?? 6e3;
6264
+ const explorerBase = toast.explorerUrl ?? DEFAULT_EXPLORER;
6265
+ const txUrl = toast.txHash ? `${explorerBase}${toast.txHash}` : void 0;
6266
+ return /* @__PURE__ */ jsxs(Wrapper, { $exiting: exiting, children: [
6267
+ /* @__PURE__ */ jsxs(Body, { children: [
6268
+ /* @__PURE__ */ jsx(IconDot, { $color: accent, children: icon }),
6269
+ /* @__PURE__ */ jsxs(Content, { children: [
6270
+ /* @__PURE__ */ jsx(Title, { children: toast.title }),
6271
+ toast.amount && /* @__PURE__ */ jsx(Amount, { children: toast.amount }),
6272
+ toast.txHash && txUrl && /* @__PURE__ */ jsxs(TxRow, { href: txUrl, target: "_blank", rel: "noopener noreferrer", children: [
6273
+ truncateHash(toast.txHash),
6274
+ /* @__PURE__ */ jsx(TxArrow, { children: "\u2197" })
6275
+ ] })
6276
+ ] }),
6277
+ /* @__PURE__ */ jsx(CloseBtn, { type: "button", onClick: dismiss, "aria-label": "Dismiss", children: "\u2715" })
6278
+ ] }),
6279
+ duration > 0 && /* @__PURE__ */ jsx(ProgressBar, { $color: accent, $duration: duration })
6280
+ ] });
6281
+ }
6282
+ var ToastContext = createContext(null);
6283
+ function ToastProvider({ children }) {
6284
+ const [toasts, setToasts] = useState([]);
6285
+ const addToast = useCallback((data) => {
6286
+ const id = `toast-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
6287
+ setToasts((prev) => [...prev, { ...data, id }]);
6288
+ return id;
6289
+ }, []);
6290
+ const dismiss = useCallback((id) => {
6291
+ setToasts((prev) => prev.filter((t) => t.id !== id));
6292
+ }, []);
6293
+ return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: { toast: addToast, dismiss }, children: [
6294
+ children,
6295
+ /* @__PURE__ */ jsx(Container, { children: toasts.map((t) => /* @__PURE__ */ jsx(ToastItem, { toast: t, onDismiss: dismiss }, t.id)) })
6296
+ ] });
6297
+ }
6298
+ function useToast() {
6299
+ const ctx = useContext(ToastContext);
6300
+ if (!ctx) throw new Error("useToast must be used within a ToastProvider");
6301
+ return ctx;
6302
+ }
6118
6303
  var DEFAULT_LOGO_SRC = Loaf_logo_Banner_default;
6119
6304
  var DEFAULT_LOGO_ALT = "Loaf";
6120
6305
  var OTP_INPUT_LENGTH = 6;
@@ -6142,6 +6327,7 @@ var LoginPopup = ({
6142
6327
  const [error, setError] = useState("");
6143
6328
  const [loading, setLoading] = useState(false);
6144
6329
  const [isSignUp, setIsSignUp] = useState(false);
6330
+ const { toast } = useToast();
6145
6331
  const [fundingAmount] = useState("");
6146
6332
  const [kycLoading, setKycLoading] = useState(false);
6147
6333
  const [showKycWidget, setShowKycWidget] = useState(false);
@@ -6362,10 +6548,19 @@ var LoginPopup = ({
6362
6548
  };
6363
6549
  const handleKycWidgetResult = (result) => {
6364
6550
  setShowKycWidget(false);
6551
+ onClose();
6365
6552
  if (result.passed) {
6366
- setView("kyc-success");
6553
+ toast({
6554
+ variant: "success",
6555
+ title: "KYC submitted \u2014 pending review",
6556
+ amount: "Your documents are under review. Please check back in a few minutes."
6557
+ });
6367
6558
  } else {
6368
- setView("kyc-failed");
6559
+ toast({
6560
+ variant: "error",
6561
+ title: "Verification unsuccessful",
6562
+ amount: "Your identity check didn't pass. Please contact support if you believe this is an error."
6563
+ });
6369
6564
  }
6370
6565
  };
6371
6566
  const handleKycWidgetClose = () => {
@@ -6456,7 +6651,7 @@ var LoginPopup = ({
6456
6651
  if (view === "main") {
6457
6652
  return /* @__PURE__ */ jsx(Overlay2, { onClick: onClose, children: /* @__PURE__ */ jsxs(PopupContainer, { onClick: (event) => event.stopPropagation(), children: [
6458
6653
  /* @__PURE__ */ jsx(CloseButton, { onClick: onClose, "aria-label": "Close login popup", children: /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) }) }),
6459
- /* @__PURE__ */ jsxs(Title, { children: [
6654
+ /* @__PURE__ */ jsxs(Title2, { children: [
6460
6655
  /* @__PURE__ */ jsx(LogoContainer3, { children: /* @__PURE__ */ jsx(LogoImage, { src: logoSrc, alt: logoAlt }) }),
6461
6656
  "Welcome to Loaf"
6462
6657
  ] }),
@@ -6517,7 +6712,7 @@ var LoginPopup = ({
6517
6712
  /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" }) }),
6518
6713
  "Back"
6519
6714
  ] }),
6520
- /* @__PURE__ */ jsxs(Title, { children: [
6715
+ /* @__PURE__ */ jsxs(Title2, { children: [
6521
6716
  /* @__PURE__ */ jsx(LogoContainer3, { children: /* @__PURE__ */ jsx(LogoImage, { src: logoSrc, alt: logoAlt }) }),
6522
6717
  isSignUp ? "Sign up with Email" : "Sign in with Email"
6523
6718
  ] }),
@@ -6556,7 +6751,7 @@ var LoginPopup = ({
6556
6751
  /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" }) }),
6557
6752
  "Back"
6558
6753
  ] }),
6559
- /* @__PURE__ */ jsxs(Title, { children: [
6754
+ /* @__PURE__ */ jsxs(Title2, { children: [
6560
6755
  /* @__PURE__ */ jsx(LogoContainer3, { children: /* @__PURE__ */ jsx(LogoImage, { src: logoSrc, alt: logoAlt }) }),
6561
6756
  "Enter Verification Code"
6562
6757
  ] }),
@@ -6827,7 +7022,7 @@ var CloseButton = styled25.button`
6827
7022
  color: var(--color-accent, #e6c656);
6828
7023
  }
6829
7024
  `;
6830
- var Title = styled25.h2`
7025
+ var Title2 = styled25.h2`
6831
7026
  font-size: 1.75rem;
6832
7027
  font-weight: 600;
6833
7028
  color: var(--color-text, #eaecef);
@@ -9634,7 +9829,7 @@ function OfferingProgressCard({
9634
9829
  const interval = setInterval(() => setCountdown(calculateCountdown()), 1e3);
9635
9830
  return () => clearInterval(interval);
9636
9831
  }, [opensAt]);
9637
- return /* @__PURE__ */ jsxs(Container, { style, className, children: [
9832
+ return /* @__PURE__ */ jsxs(Container2, { style, className, children: [
9638
9833
  /* @__PURE__ */ jsxs(Header2, { children: [
9639
9834
  /* @__PURE__ */ jsxs("h3", { children: [
9640
9835
  /* @__PURE__ */ jsx(FaChartLine, {}),
@@ -9735,7 +9930,7 @@ function OfferingProgressCard({
9735
9930
  ] })
9736
9931
  ] });
9737
9932
  }
9738
- var Container = styled25.div`
9933
+ var Container2 = styled25.div`
9739
9934
  background-color: var(--color-card-darker, #111);
9740
9935
  border-radius: 8px;
9741
9936
  padding: 1.5rem;
@@ -10271,191 +10466,6 @@ var LiveIndicatorDot = styled25.span`
10271
10466
  100% { box-shadow: 0 0 0 0 rgba(14,203,129,0); }
10272
10467
  }
10273
10468
  `;
10274
- var slideIn = keyframes`
10275
- from { transform: translateX(110%); opacity: 0; }
10276
- to { transform: translateX(0); opacity: 1; }
10277
- `;
10278
- var slideOut = keyframes`
10279
- from { transform: translateX(0); opacity: 1; }
10280
- to { transform: translateX(110%); opacity: 0; }
10281
- `;
10282
- var progressShrink = keyframes`
10283
- from { width: 100%; }
10284
- to { width: 0%; }
10285
- `;
10286
- var VARIANT_COLORS = {
10287
- success: { accent: "#0ecb81", icon: "\u2713" },
10288
- error: { accent: "#f6465d", icon: "\u2715" },
10289
- info: { accent: "#E6C656", icon: "\u2139" },
10290
- pending: { accent: "#7EB3E6", icon: "\u25CC" }
10291
- };
10292
- var Wrapper = styled25.div`
10293
- position: relative;
10294
- display: flex;
10295
- flex-direction: column;
10296
- gap: 0;
10297
- width: 340px;
10298
- background: #0d0f1a;
10299
- border: 1px solid rgba(255, 255, 255, 0.08);
10300
- border-radius: 10px;
10301
- overflow: hidden;
10302
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.04);
10303
- animation: ${({ $exiting }) => $exiting ? css`${slideOut} 0.28s cubic-bezier(0.4,0,1,1) forwards` : css`${slideIn} 0.32s cubic-bezier(0,0,0.2,1) forwards`};
10304
- pointer-events: all;
10305
- `;
10306
- var Body = styled25.div`
10307
- display: flex;
10308
- align-items: flex-start;
10309
- gap: 12px;
10310
- padding: 14px 16px 12px;
10311
- `;
10312
- var IconDot = styled25.div`
10313
- flex-shrink: 0;
10314
- width: 28px;
10315
- height: 28px;
10316
- border-radius: 50%;
10317
- background: ${({ $color }) => $color}1a;
10318
- border: 1px solid ${({ $color }) => $color}55;
10319
- display: flex;
10320
- align-items: center;
10321
- justify-content: center;
10322
- font-size: 0.75rem;
10323
- font-weight: 700;
10324
- color: ${({ $color }) => $color};
10325
- margin-top: 1px;
10326
- `;
10327
- var Content = styled25.div`
10328
- flex: 1;
10329
- min-width: 0;
10330
- `;
10331
- var Title2 = styled25.p`
10332
- margin: 0 0 2px;
10333
- font-size: 0.8rem;
10334
- font-weight: 600;
10335
- color: #fff;
10336
- letter-spacing: 0.01em;
10337
- `;
10338
- var Amount = styled25.p`
10339
- margin: 0 0 6px;
10340
- font-size: 1.05rem;
10341
- font-weight: 700;
10342
- color: #E6C656;
10343
- letter-spacing: -0.01em;
10344
- `;
10345
- var TxRow = styled25.a`
10346
- display: inline-flex;
10347
- align-items: center;
10348
- gap: 5px;
10349
- font-family: 'IBM Plex Mono', 'Space Mono', monospace;
10350
- font-size: 0.68rem;
10351
- color: rgba(255, 255, 255, 0.4);
10352
- text-decoration: none;
10353
- transition: color 0.15s;
10354
- &:hover {
10355
- color: #7EB3E6;
10356
- }
10357
- `;
10358
- var TxArrow = styled25.span`
10359
- font-size: 0.6rem;
10360
- opacity: 0.6;
10361
- `;
10362
- var CloseBtn = styled25.button`
10363
- flex-shrink: 0;
10364
- background: none;
10365
- border: none;
10366
- padding: 2px 4px;
10367
- cursor: pointer;
10368
- color: rgba(255, 255, 255, 0.25);
10369
- font-size: 0.9rem;
10370
- line-height: 1;
10371
- transition: color 0.15s;
10372
- &:hover { color: rgba(255, 255, 255, 0.7); }
10373
- `;
10374
- var ProgressBar = styled25.div`
10375
- height: 2px;
10376
- background: rgba(255, 255, 255, 0.06);
10377
- position: relative;
10378
- &::after {
10379
- content: '';
10380
- position: absolute;
10381
- left: 0;
10382
- top: 0;
10383
- height: 100%;
10384
- background: ${({ $color }) => $color};
10385
- animation: ${css`${progressShrink} ${({ $duration }) => $duration}ms linear forwards`};
10386
- }
10387
- `;
10388
- var Container2 = styled25.div`
10389
- position: fixed;
10390
- bottom: 24px;
10391
- right: 24px;
10392
- z-index: 9999;
10393
- display: flex;
10394
- flex-direction: column-reverse;
10395
- gap: 10px;
10396
- pointer-events: none;
10397
- `;
10398
- var DEFAULT_EXPLORER = "https://sepolia.basescan.org/tx/";
10399
- function truncateHash(hash) {
10400
- return `${hash.slice(0, 6)}\u2026${hash.slice(-4)}`;
10401
- }
10402
- function ToastItem({ toast, onDismiss }) {
10403
- const [exiting, setExiting] = useState(false);
10404
- const timerRef = useRef(null);
10405
- const dismiss = useCallback(() => {
10406
- setExiting(true);
10407
- setTimeout(() => onDismiss(toast.id), 280);
10408
- }, [onDismiss, toast.id]);
10409
- useEffect(() => {
10410
- const duration2 = toast.duration ?? 6e3;
10411
- if (duration2 > 0) {
10412
- timerRef.current = setTimeout(dismiss, duration2);
10413
- }
10414
- return () => {
10415
- if (timerRef.current) clearTimeout(timerRef.current);
10416
- };
10417
- }, [dismiss, toast.duration]);
10418
- const { accent, icon } = VARIANT_COLORS[toast.variant];
10419
- const duration = toast.duration ?? 6e3;
10420
- const explorerBase = toast.explorerUrl ?? DEFAULT_EXPLORER;
10421
- const txUrl = toast.txHash ? `${explorerBase}${toast.txHash}` : void 0;
10422
- return /* @__PURE__ */ jsxs(Wrapper, { $exiting: exiting, children: [
10423
- /* @__PURE__ */ jsxs(Body, { children: [
10424
- /* @__PURE__ */ jsx(IconDot, { $color: accent, children: icon }),
10425
- /* @__PURE__ */ jsxs(Content, { children: [
10426
- /* @__PURE__ */ jsx(Title2, { children: toast.title }),
10427
- toast.amount && /* @__PURE__ */ jsx(Amount, { children: toast.amount }),
10428
- toast.txHash && txUrl && /* @__PURE__ */ jsxs(TxRow, { href: txUrl, target: "_blank", rel: "noopener noreferrer", children: [
10429
- truncateHash(toast.txHash),
10430
- /* @__PURE__ */ jsx(TxArrow, { children: "\u2197" })
10431
- ] })
10432
- ] }),
10433
- /* @__PURE__ */ jsx(CloseBtn, { type: "button", onClick: dismiss, "aria-label": "Dismiss", children: "\u2715" })
10434
- ] }),
10435
- duration > 0 && /* @__PURE__ */ jsx(ProgressBar, { $color: accent, $duration: duration })
10436
- ] });
10437
- }
10438
- var ToastContext = createContext(null);
10439
- function ToastProvider({ children }) {
10440
- const [toasts, setToasts] = useState([]);
10441
- const addToast = useCallback((data) => {
10442
- const id = `toast-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
10443
- setToasts((prev) => [...prev, { ...data, id }]);
10444
- return id;
10445
- }, []);
10446
- const dismiss = useCallback((id) => {
10447
- setToasts((prev) => prev.filter((t) => t.id !== id));
10448
- }, []);
10449
- return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: { toast: addToast, dismiss }, children: [
10450
- children,
10451
- /* @__PURE__ */ jsx(Container2, { children: toasts.map((t) => /* @__PURE__ */ jsx(ToastItem, { toast: t, onDismiss: dismiss }, t.id)) })
10452
- ] });
10453
- }
10454
- function useToast() {
10455
- const ctx = useContext(ToastContext);
10456
- if (!ctx) throw new Error("useToast must be used within a ToastProvider");
10457
- return ctx;
10458
- }
10459
10469
  function OrderPanel({
10460
10470
  statusLabel,
10461
10471
  statusColor,