@lockerverse/react 0.2.99 → 0.2.100
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/README.md +89 -0
- package/dist/auction-item.d.ts +36 -0
- package/dist/auction-item.d.ts.map +1 -0
- package/dist/auction-item.js +2 -0
- package/dist/auction-item.js.map +1 -0
- package/dist/auctions.css +221 -0
- package/dist/auctions.d.ts +25 -0
- package/dist/auctions.d.ts.map +1 -0
- package/dist/auctions.js +2 -0
- package/dist/auctions.js.map +1 -0
- package/dist/format-money.js +2 -0
- package/dist/format-money.js.map +1 -0
- package/dist/host-callback.js +1 -1
- package/dist/host-callback.js.map +1 -1
- package/dist/immutable-resource-identity.js.map +1 -1
- package/dist/lockerverse-donate-launcher.js +1 -1
- package/dist/lockerverse-donate-launcher.js.map +1 -1
- package/dist/lockerverse-payment.js +1 -1
- package/dist/lockerverse-payment.js.map +1 -1
- package/dist/phone.js +2 -0
- package/dist/phone.js.map +1 -0
- package/dist/signup.js +1 -1
- package/dist/signup.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/use-lockerverse-widget.js +1 -1
- package/package.json +18 -3
package/README.md
CHANGED
|
@@ -325,3 +325,92 @@ const recovery = savedRecovery
|
|
|
325
325
|
```
|
|
326
326
|
|
|
327
327
|
Malformed host selections and invalid custom tips render customer-safe validation messages and do not call the Lockerverse API. Product selection remains owned by the host application.
|
|
328
|
+
|
|
329
|
+
## Auctions
|
|
330
|
+
|
|
331
|
+
Browse auctions and open the built-in item checkout. The catalog entry does not
|
|
332
|
+
load Stripe. The checkout entry uses the optional Stripe peers listed above.
|
|
333
|
+
Import `auctions.css` for both components. Built-in auction checkout accepts
|
|
334
|
+
cards only. The core SDK supports the backend confirmation-token flows for
|
|
335
|
+
custom payment UIs.
|
|
336
|
+
|
|
337
|
+
```tsx
|
|
338
|
+
import { useState } from "react";
|
|
339
|
+
import type { LockerverseAuction } from "@lockerverse/sdk/auctions";
|
|
340
|
+
import { LockerverseAuctions, useLockerverseAuctions } from "@lockerverse/react/auctions";
|
|
341
|
+
import { LockerverseAuctionItem } from "@lockerverse/react/auction-item";
|
|
342
|
+
import "@lockerverse/react/auctions.css";
|
|
343
|
+
|
|
344
|
+
export function AuctionPage() {
|
|
345
|
+
const auctions = useLockerverseAuctions({ communitySlug: "auburn" });
|
|
346
|
+
const [selected, setSelected] = useState<{
|
|
347
|
+
auction: LockerverseAuction;
|
|
348
|
+
itemId: string;
|
|
349
|
+
} | null>(null);
|
|
350
|
+
|
|
351
|
+
return selected ? (
|
|
352
|
+
<LockerverseAuctionItem
|
|
353
|
+
auction={selected.auction}
|
|
354
|
+
client={auctions.client}
|
|
355
|
+
itemId={selected.itemId}
|
|
356
|
+
onBidSubmitted={() => auctions.refresh()}
|
|
357
|
+
onPurchaseComplete={() => auctions.refresh()}
|
|
358
|
+
onUncertain={(kind) => {
|
|
359
|
+
// Show an unresolved-result message. Do not retry a bid.
|
|
360
|
+
console.info(`${kind} result is unknown`);
|
|
361
|
+
}}
|
|
362
|
+
theme="light"
|
|
363
|
+
/>
|
|
364
|
+
) : (
|
|
365
|
+
<LockerverseAuctions
|
|
366
|
+
auctions={auctions}
|
|
367
|
+
onSelectItem={(auction, item) => setSelected({ auction, itemId: item.id })}
|
|
368
|
+
theme="light"
|
|
369
|
+
/>
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Production is the default. Set `environment: "development"` on the hook only
|
|
375
|
+
when you intend to use the development backend. Auction data supplies the
|
|
376
|
+
publishable key and connected account for Stripe initialization. The backend
|
|
377
|
+
must include the auction `payment` configuration to use built-in checkout.
|
|
378
|
+
|
|
379
|
+
Both components accept `theme` and the existing `LockerverseStyle` CSS-variable
|
|
380
|
+
object. Use the hook data for your own item cards and open `LockerverseAuctionItem`
|
|
381
|
+
for checkout. No general headless workflow API is required.
|
|
382
|
+
|
|
383
|
+
`onBidSubmitted` means the bid request and any required Stripe action completed;
|
|
384
|
+
it does not mean the bid won or a charge occurred. `onPurchaseComplete` runs only
|
|
385
|
+
when Lockerverse reports `paid`. `onUncertain` means the result remains unknown.
|
|
386
|
+
Keep that state visible and use the checkout recovery action for a purchase.
|
|
387
|
+
Status checks call `client.getPurchaseStatus` without creating another payment;
|
|
388
|
+
the backend can reconcile Stripe status and send the purchase notification.
|
|
389
|
+
A `null` status lookup is not proof that an original in-flight request ended.
|
|
390
|
+
Any retry must keep the original `clientRequestId` and purchase details.
|
|
391
|
+
If a bid result is unknown, block a new bid and keep the support message visible.
|
|
392
|
+
Do not navigate away or unmount checkout while submission is in progress.
|
|
393
|
+
Never automatically retry a bid: the backend has no public bid recovery API.
|
|
394
|
+
|
|
395
|
+
For a host that needs recovery after navigation, connect
|
|
396
|
+
`onPurchaseRecoveryChange` and later pass its record as `resumePurchase`:
|
|
397
|
+
|
|
398
|
+
```tsx
|
|
399
|
+
<LockerverseAuctionItem
|
|
400
|
+
auction={auction}
|
|
401
|
+
client={client}
|
|
402
|
+
itemId={itemId}
|
|
403
|
+
onPurchaseRecoveryChange={savePrivateRecoveryRecord}
|
|
404
|
+
resumePurchase={previousRecoveryRecord}
|
|
405
|
+
/>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
The host owns storage. A recovery record captures the original item, payment
|
|
409
|
+
configuration, pricing, buyer contact data, and Stripe confirmation token. Keep it private; do not put it in URLs, analytics, logs, or
|
|
410
|
+
shared caches. Clear the stored record when the callback supplies `null`.
|
|
411
|
+
Resume only with the same auction, item, client, and payment environment. Keep
|
|
412
|
+
the original `clientRequestId` and purchase details. The public example stores
|
|
413
|
+
recovery in memory only and asks the customer to keep the page open.
|
|
414
|
+
|
|
415
|
+
The raw receipt endpoint returns amounts, not payment status. Do not use a
|
|
416
|
+
receipt response alone to show a payment as complete.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { n as LockerverseTheme, t as LockerverseStyle } from "./theme.js";
|
|
2
|
+
import { u as LockerverseStripeLoader } from "./types.js";
|
|
3
|
+
import { LockerverseAuction, LockerverseAuctionBidResult, LockerverseAuctionClient, LockerverseAuctionItem as LockerverseAuctionItem$1, LockerverseAuctionPricing, LockerverseAuctionPurchaseResult, LockerverseAuctionPurchaseSubmission } from "@lockerverse/sdk/auctions";
|
|
4
|
+
//#region src/auction-item-types.d.ts
|
|
5
|
+
/** Keep this record private. It includes buyer contact data and a Stripe token. */
|
|
6
|
+
type LockerverseAuctionPurchaseRecovery = {
|
|
7
|
+
auctionId: string;
|
|
8
|
+
itemId: string;
|
|
9
|
+
item: LockerverseAuctionItem$1;
|
|
10
|
+
payment: NonNullable<LockerverseAuction["payment"]>;
|
|
11
|
+
pricing: LockerverseAuctionPricing;
|
|
12
|
+
submission: LockerverseAuctionPurchaseSubmission;
|
|
13
|
+
};
|
|
14
|
+
type LockerverseAuctionItemProps = {
|
|
15
|
+
auction: LockerverseAuction;
|
|
16
|
+
client: LockerverseAuctionClient;
|
|
17
|
+
itemId: string;
|
|
18
|
+
className?: string;
|
|
19
|
+
theme?: LockerverseTheme;
|
|
20
|
+
style?: LockerverseStyle;
|
|
21
|
+
stripeLoader?: LockerverseStripeLoader;
|
|
22
|
+
/** A submitted bid is not a winning bid or a payment receipt. */
|
|
23
|
+
onBidSubmitted?: (result: LockerverseAuctionBidResult) => void;
|
|
24
|
+
/** Called only after Lockerverse reports a paid purchase. */
|
|
25
|
+
onPurchaseComplete?: (result: LockerverseAuctionPurchaseResult) => void;
|
|
26
|
+
onPurchaseRecoveryChange?: (recovery: LockerverseAuctionPurchaseRecovery | null) => void;
|
|
27
|
+
onUncertain?: (kind: "bid" | "purchase") => void;
|
|
28
|
+
/** Resume with the same auction, item, client, and payment environment. */
|
|
29
|
+
resumePurchase?: LockerverseAuctionPurchaseRecovery;
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/lockerverse-auction-item.d.ts
|
|
33
|
+
declare function LockerverseAuctionItem(props: LockerverseAuctionItemProps): import("react").JSX.Element;
|
|
34
|
+
//#endregion
|
|
35
|
+
export { LockerverseAuctionItem, type LockerverseAuctionItemProps, type LockerverseAuctionPurchaseRecovery, type LockerverseStyle, type LockerverseTheme };
|
|
36
|
+
//# sourceMappingURL=auction-item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auction-item.d.ts","names":[],"sources":["../src/auction-item-types.ts","../src/lockerverse-auction-item.tsx"],"mappings":";;;;;KAaY;EACV;EACA;EACA,MAAM;EACN,SAAS,YAAY;EACrB,SAAS;EACT,YAAY;;KAGF;EACV,SAAS;EACT,QAAQ;EACR;EACA;EACA,QAAQ;EACR,QAAQ;EACR,eAAe;;EAEf,kBAAkB,QAAQ;;EAE1B,sBAAsB,QAAQ;EAC9B,4BACE,UAAU;EAEZ,eAAe;;EAEf,iBAAiB;;;;iBC8LH,uBAAuB,OAAO,8CAA2B,IAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{c as e,s as t,t as n}from"./host-callback.js";import{t as r}from"./format-money.js";import{AddressElement as i,Elements as a,PaymentElement as o,useElements as s,useStripe as c}from"@stripe/react-stripe-js";import{loadStripe as l}from"@stripe/stripe-js/pure/index.js";import{useEffect as u,useId as d,useRef as f,useState as p}from"react";import{LockerverseSdkError as m,calculateLockerverseAuctionPricing as h,getLockerverseAuctionMinimumBid as g}from"@lockerverse/sdk/auctions";import{safeParse as _}from"valibot";import{Fragment as v,jsx as y,jsxs as b}from"react/jsx-runtime";function x(e,t,n){return h(e,t.saleMode===`buy_now`?(t.buyNowPriceAmount??0)*n.quantity:n.amount,n.includeServiceFee)}function S(e,t,n){if(e.status!==`active`||t.status!==`active`||Date.parse(e.endAt)<=Date.now())return`This item is not accepting bids or purchases.`;if(t.saleMode===`hybrid`)return`This item type is not supported for checkout.`;if(t.saleMode===`buy_now`){if(t.isSoldOut||t.availableQuantity===0)return`This item is sold out.`;if(!(t.buyNowPriceAmount&&Number.isSafeInteger(n.quantity))||n.quantity<1||t.availableQuantity!==null&&n.quantity>t.availableQuantity)return`Select an available quantity.`}else if(!Number.isSafeInteger(n.amount)||n.amount%100!=0||n.amount<g(t))return`Enter a whole-dollar bid at or above the minimum bid.`;return null}function C(e,t,n,r,i){return e.payment?.publishableKey!==t.payment?.publishableKey||e.payment?.connectedAccountId!==t.payment?.connectedAccountId||e.serviceFeeEnabled!==t.serviceFeeEnabled||n.saleMode!==r.saleMode||n.collectShippingAddress!==r.collectShippingAddress||JSON.stringify(x(e,n,i))!==JSON.stringify(x(t,r,i))}function w(e){return{expectedServiceFeeCents:e.serviceFeeCents,expectedSubtotalCents:e.subtotalCents,expectedTotalCents:e.totalCents}}async function ee({stripe:e,elements:t,email:n,phone:r,billing:i,shipping:a,collectShippingAddress:o}){if(!(i?.complete&&i.value.name.trim()))throw Error(`Complete your billing name and address.`);if(o&&!(a?.complete&&a.value.name.trim()))throw Error(`Complete your shipping name and address.`);let s=await t.submit();if(s.error)throw Error(s.error.message??`Check your payment details.`);let c=await e.createConfirmationToken({elements:t,params:{payment_method_data:{allow_redisplay:`always`,billing_details:{address:i.value.address,email:n,name:i.value.name,phone:r}},return_url:window.location.href,...o&&a?{shipping:{address:a.value.address,name:a.value.name,phone:r}}:void 0}});if(c.error||!c.confirmationToken)throw Error(c.error?.message??`Unable to prepare payment details.`);return c.confirmationToken.id}async function T(e,t){if(!t.requiresAction)return;if(!t.clientSecret)throw Error(`Payment confirmation is incomplete. Check its status before trying again.`);let n=await e.handleNextAction({clientSecret:t.clientSecret});if(n.error)throw Error(n.error.message??`Payment confirmation is incomplete.`)}function te(e,t,n,i){return e===`busy`?`Please wait…`:e===`retry`?`Retry original purchase`:t?`Check purchase status`:n?`Pay ${r(i)}`:`Place bid`}function E(a){let{auction:l,item:h,selection:g,client:E,onReview:D,onBack:O}=a,k=c(),A=s(),j=d(),[M,N]=p(``),[P,F]=p(``),[ne,I]=p(null),[L,re]=p(null),[R,ie]=p(a.resumePurchase??null),[z,B]=p(a.resumePurchase?`pending`:`ready`),[V,H]=p(null),U=f(a.resumePurchase?.submission.clientRequestId??null),W=z===`complete`||z===`uncertain`,G=f(!1),K=f(!0),q=f(a);q.current=a,u(()=>(K.current=!0,()=>{K.current=!1}),[]);let J=!!(R??a.resumePurchase)||h.saleMode===`buy_now`,Y=R?.pricing??a.resumePurchase?.pricing??x(l,h,g),ae=R?.payment??a.resumePurchase?.payment??l.payment;function X(e){K.current&&ie(e),n(q.current.onPurchaseRecoveryChange,e)}function Z(e){K.current&&(e.status===`paid`?(U.current=null,X(null),B(`complete`),H(`Purchase complete. Receipt: ${e.purchaseId}`),n(q.current.onPurchaseComplete,e)):e.status===`pending_payment`?(B(`pending`),H(`Your purchase is pending. Check its status before making another payment.`)):(U.current=null,X(null),B(`ready`),H(`This purchase is ${e.status.replaceAll(`_`,` `)}. You can start a new purchase.`)))}async function oe(){if(!(k&&A&&l.payment))throw Error(`Payment details are still loading.`);let n=_(t,M),r=_(e,P);if(!(n.success&&r.success))throw Error(`Enter a valid email and phone number with its country code.`);let i=await E.load(l.slug);if(!K.current)return null;let a=i.items.find(e=>e.id===h.id);if(!a)return D(i,`This item is no longer available.`),null;let o=S(i,a,g);if(o||C(l,i,h,a,g))return D(i,o??`The checkout details changed. Review them before continuing.`),null;let s=await ee({billing:ne,collectShippingAddress:h.collectShippingAddress,elements:A,email:n.output,phone:r.output,shipping:L,stripe:k});return K.current?{confirmationToken:s,email:n.output,includeServiceFee:g.includeServiceFee,phone:r.output,...w(Y)}:null}async function se(e){let t=await E.createBid(l.slug,h.id,{...e,amount:g.amount});K.current&&k&&(await T(k,t),K.current&&(B(`complete`),H(`Bid submitted. Watch your email for bid and auction updates.`),n(q.current.onBidSubmitted,t)))}async function Q(e,t){if(K.current&&k){if(e.requiresAction){if(await T(k,e),!K.current)return;let n=await E.getPurchaseStatus(l.slug,h.id,t.submission.clientRequestId);n?Z(n):(B(`pending`),H(`Payment status is not available yet. Check again shortly.`));return}Z(e)}}async function ce(e){let t=await E.getPurchaseStatus(l.slug,h.id,e.submission.clientRequestId);K.current&&(t?await Q(t,e):(B(`retry`),H(`No purchase is recorded yet. You can retry the original purchase with the same request ID.`)))}async function le(e,t){let n=await E.getPurchaseStatus(l.slug,h.id,t.submission.clientRequestId);if(K.current){if(n){await Q(n,t);return}X(null),B(`ready`),H(`The purchase was rejected. Review the item and payment details before trying again. (${e.status??`validation`})`)}}async function ue(e,t,r,i){if(!K.current)return;let a=t&&(!(e instanceof m)||e.recoveryRecommended);if(H(e instanceof Error?e.message:`Unable to complete this request.`),J&&r){if(!i&&e instanceof m&&!e.recoveryRecommended)try{await le(e,r);return}catch{}B(`pending`),H(`We could not confirm the purchase result. Check its status using the same purchase request.`),n(q.current.onUncertain,`purchase`)}else a?(B(`uncertain`),H(`We could not confirm your bid. Do not submit another bid until you check your email or contact the auction organizer.`),n(q.current.onUncertain,`bid`)):B(`ready`)}function de(){return U.current??=globalThis.crypto.randomUUID(),U.current}let $=k&&A&&ae;async function fe(e){if(e.preventDefault(),G.current||W)return;if(!$){H(`Payment details are still loading.`);return}let t=z===`retry`;G.current=!0,B(`busy`),H(null);let n=!1,r=R;try{if(!r){let e=await oe();if(!e)return;if(!J){n=!0,await se(e);return}r=Object.freeze({auctionId:l.id,item:h,itemId:h.id,payment:Object.freeze({...$}),pricing:Y,submission:Object.freeze({...e,clientRequestId:de(),paymentMethodTypes:Object.freeze([`card`]),quantity:g.quantity})}),X(r)}if(R&&!t){await ce(r);return}n=!0,await Q(await E.createPurchase(l.slug,h.id,r.submission),r)}catch(e){await ue(e,n,r,R!==null&&!t)}finally{G.current=!1}}let pe=te(z,R!==null,J,Y.totalCents),me=z!==`ready`;return b(`form`,{className:`lockerverse-auctions__checkout`,onSubmit:fe,children:[y(`h3`,{children:J?`Complete your purchase`:`Secure your bid`}),b(`p`,{children:[J?`Total`:`Bid including selected fees`,`:`,` `,y(`strong`,{children:r(Y.totalCents)})]}),!(R||W)&&b(`fieldset`,{disabled:me,children:[b(`label`,{className:`lockerverse-auctions__field`,htmlFor:`${j}-email`,children:[`Email`,y(`input`,{autoComplete:`email`,id:`${j}-email`,onChange:e=>N(e.target.value),required:!0,type:`email`,value:M})]}),b(`label`,{className:`lockerverse-auctions__field`,htmlFor:`${j}-phone`,children:[`Phone, including country code`,y(`input`,{autoComplete:`tel`,id:`${j}-phone`,onChange:e=>F(e.target.value),placeholder:`+1 555 123 4567`,required:!0,type:`tel`,value:P})]}),y(`h4`,{children:`Billing details`}),y(i,{onChange:I,options:{mode:`billing`}}),h.collectShippingAddress&&b(v,{children:[y(`h4`,{children:`Shipping details`}),y(i,{onChange:re,options:{mode:`shipping`}})]}),y(`h4`,{children:J?`Payment details`:`Card for the winning bid`}),y(o,{options:{fields:{billingDetails:{address:`never`,email:`never`,name:`never`,phone:`never`}}}}),!J&&y(`p`,{className:`lockerverse-auctions__notice`,children:`By placing this bid, you agree to save this card and charge the bid plus selected fees if you win. Placing a bid does not charge your card now.`})]}),V&&y(`p`,{"aria-live":`polite`,className:`lockerverse-auctions__notice`,role:`status`,children:V}),!W&&y(`button`,{className:`lockerverse-auctions__button`,disabled:z===`busy`||!k||!A,type:`submit`,children:pe}),z===`ready`&&y(`button`,{className:`lockerverse-auctions__button`,onClick:O,type:`button`,children:`Back to item`})]})}const D=new Intl.DateTimeFormat(`en-US`,{dateStyle:`medium`,timeStyle:`short`,timeZone:`UTC`});function O({auction:e,item:t}){let[n,r]=p(0),i=t.images[n]??t.image,a=e.status===`draft`?e.startAt:e.endAt,o=new Date(a);return b(`div`,{children:[i?y(`img`,{alt:t.name,className:`lockerverse-auctions__image`,height:600,src:i,width:768}):null,t.images.length>1?b(`fieldset`,{className:`lockerverse-auctions__gallery`,children:[y(`legend`,{children:`Item images`}),t.images.map((e,t)=>y(`button`,{"aria-label":`Show image ${t+1}`,"aria-pressed":n===t,onClick:()=>r(t),type:`button`,children:y(`img`,{alt:``,height:56,src:e,width:72})},e))]}):null,y(`p`,{className:`lockerverse-auctions__meta`,children:e.name}),y(`h2`,{children:t.name}),t.description?y(`p`,{children:t.description}):null,Number.isFinite(o.getTime())?b(`p`,{children:[e.status===`draft`?`Starts`:`Ends`,`:`,` `,b(`time`,{dateTime:a,children:[D.format(o),` UTC`]})]}):null]})}function k({item:e}){let t=e.saleMode===`buy_now`;return b(v,{children:[y(`h3`,{children:t?`Buy this item`:`Place a bid`}),b(`p`,{children:[t?`Price`:`Current bid`,`:`,` `,y(`strong`,{children:r(t?e.buyNowPriceAmount??0:e.maxBidAmount??0)})]}),t?null:b(`p`,{children:[`Minimum next bid: `,r(g(e))]}),t&&e.availableQuantity!==null?b(`p`,{children:[e.availableQuantity,` available`]}):null]})}function A({auction:e,item:t,value:n,onChange:r,includeFee:i,setIncludeFee:a}){let o=d(),s=t.saleMode===`buy_now`;return b(v,{children:[b(`label`,{className:`lockerverse-auctions__field`,htmlFor:o,children:[s?`Quantity`:`Your bid (USD)`,y(`input`,{id:o,max:s?t.availableQuantity??void 0:void 0,min:s?1:Math.ceil(g(t)/100),onChange:e=>r(e.target.value),required:!0,step:1,type:`number`,value:n})]}),e.serviceFeeEnabled?b(`label`,{className:`lockerverse-auctions__fee`,children:[y(`input`,{checked:i,onChange:e=>a(e.target.checked),type:`checkbox`}),`Cover the `,e.pricingPolicy.serviceFeeRateBasisPoints/100,`% service fee`]}):null,y(`button`,{className:`lockerverse-auctions__button`,disabled:!e.payment,type:`submit`,children:`Continue`}),e.payment?null:y(`p`,{role:`alert`,children:`Payments are not configured for this auction.`})]})}function j(e,t){return e.saleMode===`buy_now`?String(t?t.quantity:1):String(t?t.amount/100:Math.ceil(g(e)/100))}function M({auction:e,item:t,initialSelection:n,onContinue:r,onError:i}){let[a,o]=p(()=>j(t,n)),[s,c]=p(n?n.includeServiceFee:e.serviceFeeEnabled&&e.serviceFeeDefaultChecked),l=t.saleMode===`buy_now`,u=e.status===`active`&&t.status===`active`&&Date.parse(e.endAt)>Date.now()&&!t.isSoldOut&&t.saleMode!==`hybrid`;function d(n){n.preventDefault();let o={amount:l?0:Number(a)*100,includeServiceFee:e.serviceFeeEnabled&&s,quantity:l?Number(a):1},c=S(e,t,o);if(c){i(c);return}try{x(e,t,o)}catch{i(`Enter a valid amount or quantity.`);return}r(o)}return b(`form`,{className:`lockerverse-auctions__checkout`,onSubmit:d,children:[y(k,{item:t}),u?y(A,{auction:e,includeFee:s,item:t,onChange:o,setIncludeFee:c,value:a}):y(`p`,{role:`status`,children:t.isSoldOut?`This item is sold out.`:`This item is not open for bids or purchases.`})]})}function N(e){let{auction:t,item:n,selection:r,theme:i=`dark`,stripeLoader:o=l,style:s,onBack:c,resumePurchase:d}=e,[f,m]=p(null),[h,g]=p(!1),[_,v]=p(0),S=d?.payment??t.payment;if(u(()=>{let e=!0;if(!S){g(!0);return}return Promise.resolve().then(()=>o(S.publishableKey,S.connectedAccountId?{stripeAccount:S.connectedAccountId}:void 0)).then(t=>{e&&(m(t),g(!t))},()=>{e&&g(!0)}),()=>{e=!1}},[S,o,_]),h)return b(`div`,{children:[y(`p`,{role:`alert`,children:`Payment details could not load.`}),d?null:y(`button`,{onClick:c,type:`button`,children:`Back to item`}),y(`button`,{onClick:()=>{g(!1),m(null),v(e=>e+1)},type:`button`,children:`Try again`})]});if(!f)return b(`div`,{children:[y(`p`,{role:`status`,children:`Loading secure payment details…`}),d?null:y(`button`,{onClick:c,type:`button`,children:`Back to item`})]});let C={mode:`setup`,setupFutureUsage:`off_session`};d?C={amount:d.pricing.totalCents,currency:`usd`,mode:`payment`}:n.saleMode===`buy_now`&&(C={amount:x(t,n,r).totalCents,currency:`usd`,mode:`payment`});let w={...C,appearance:{theme:i===`dark`?`night`:`stripe`,variables:{...s?.[`--lockerverse-accent`]?{colorPrimary:s[`--lockerverse-accent`]}:void 0,...s?.[`--lockerverse-font-family`]?{fontFamily:s[`--lockerverse-font-family`]}:void 0}},currency:`usd`,paymentMethodTypes:[`card`]};return y(a,{options:w,stripe:f,children:y(E,{...e})})}function P(e){let{auction:t,item:n,resumePurchase:r,className:i,theme:a=`dark`,style:o}=e,[s,c]=p(t),l=s.items.find(e=>e.id===n.id)??r?.item,[u,d]=p(()=>r?{amount:0,includeServiceFee:r.submission.includeServiceFee??!1,quantity:r.submission.quantity}:null),[f,m]=p(!!r),[h,g]=p(null);function _(e,t){c(e),d(null),m(!1),g(t)}function v(e){g(null),d(e),m(!0)}return l?y(`section`,{className:[`lockerverse-auctions`,i].filter(Boolean).join(` `),"data-lockerverse-theme":a,style:o,children:b(`div`,{className:`lockerverse-auctions__detail`,children:[y(O,{auction:s,item:l}),b(`div`,{children:[h?y(`p`,{className:`lockerverse-auctions__notice`,role:`alert`,children:h}):null,f&&u?y(N,{...e,auction:s,item:l,onBack:()=>m(!1),onReview:_,selection:u}):y(M,{auction:s,initialSelection:u,item:l,onContinue:v,onError:g})]})]})}):y(`p`,{role:`alert`,children:`This auction item is no longer available.`})}function F(e){let t=f({auctionId:e.auction.id,client:e.client,itemId:e.itemId});if(t.current.client!==e.client||t.current.auctionId!==e.auction.id||t.current.itemId!==e.itemId)throw TypeError(`Auction item identity cannot change. Remount with a new React key.`);if(e.resumePurchase&&(e.resumePurchase.auctionId!==e.auction.id||e.resumePurchase.itemId!==e.itemId||e.resumePurchase.item.id!==e.itemId||e.resumePurchase.item.auctionId!==e.auction.id))throw TypeError(`The purchase recovery record belongs to a different auction item.`);let n=e.auction.items.find(t=>t.id===e.itemId)??e.resumePurchase?.item;return n?y(P,{...e,item:n}):y(`p`,{role:`alert`,children:`This auction item is not available.`})}export{F as LockerverseAuctionItem};
|
|
2
|
+
//# sourceMappingURL=auction-item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auction-item.js","names":[],"sources":["../src/auction-payment.ts","../src/auction-checkout.tsx","../src/auction-item-details.tsx","../src/auction-item-selection.tsx","../src/lockerverse-auction-item.tsx"],"sourcesContent":["import type {\n LockerverseAuction,\n LockerverseAuctionBidResult,\n LockerverseAuctionItem,\n LockerverseAuctionPricing,\n} from \"@lockerverse/sdk/auctions\";\nimport {\n calculateLockerverseAuctionPricing,\n getLockerverseAuctionMinimumBid,\n} from \"@lockerverse/sdk/auctions\";\nimport type {\n Stripe,\n StripeAddressElementChangeEvent,\n StripeElements,\n} from \"@stripe/stripe-js\";\n\nexport type AuctionSelection = {\n amount: number;\n quantity: number;\n includeServiceFee: boolean;\n};\n\nexport function getAuctionSelectionPricing(\n auction: LockerverseAuction,\n item: LockerverseAuctionItem,\n selection: AuctionSelection\n) {\n return calculateLockerverseAuctionPricing(\n auction,\n item.saleMode === \"buy_now\"\n ? (item.buyNowPriceAmount ?? 0) * selection.quantity\n : selection.amount,\n selection.includeServiceFee\n );\n}\n\nexport function getAuctionSelectionError(\n auction: LockerverseAuction,\n item: LockerverseAuctionItem,\n selection: AuctionSelection\n) {\n if (\n auction.status !== \"active\" ||\n item.status !== \"active\" ||\n Date.parse(auction.endAt) <= Date.now()\n ) {\n return \"This item is not accepting bids or purchases.\";\n }\n if (item.saleMode === \"hybrid\") {\n return \"This item type is not supported for checkout.\";\n }\n if (item.saleMode === \"buy_now\") {\n if (item.isSoldOut || item.availableQuantity === 0) {\n return \"This item is sold out.\";\n }\n if (\n !(item.buyNowPriceAmount && Number.isSafeInteger(selection.quantity)) ||\n selection.quantity < 1 ||\n (item.availableQuantity !== null &&\n selection.quantity > item.availableQuantity)\n ) {\n return \"Select an available quantity.\";\n }\n } else if (\n !Number.isSafeInteger(selection.amount) ||\n selection.amount % 100 !== 0 ||\n selection.amount < getLockerverseAuctionMinimumBid(item)\n ) {\n return \"Enter a whole-dollar bid at or above the minimum bid.\";\n }\n return null;\n}\n\nexport function hasAuctionCheckoutChanged(\n previous: LockerverseAuction,\n current: LockerverseAuction,\n item: LockerverseAuctionItem,\n nextItem: LockerverseAuctionItem,\n selection: AuctionSelection\n) {\n return (\n previous.payment?.publishableKey !== current.payment?.publishableKey ||\n previous.payment?.connectedAccountId !==\n current.payment?.connectedAccountId ||\n previous.serviceFeeEnabled !== current.serviceFeeEnabled ||\n item.saleMode !== nextItem.saleMode ||\n item.collectShippingAddress !== nextItem.collectShippingAddress ||\n JSON.stringify(getAuctionSelectionPricing(previous, item, selection)) !==\n JSON.stringify(getAuctionSelectionPricing(current, nextItem, selection))\n );\n}\n\nexport function auctionExpectedPricing(pricing: LockerverseAuctionPricing) {\n return {\n expectedServiceFeeCents: pricing.serviceFeeCents,\n expectedSubtotalCents: pricing.subtotalCents,\n expectedTotalCents: pricing.totalCents,\n };\n}\n\nexport async function createAuctionConfirmationToken({\n stripe,\n elements,\n email,\n phone,\n billing,\n shipping,\n collectShippingAddress,\n}: {\n stripe: Stripe;\n elements: StripeElements;\n email: string;\n phone: string;\n billing: StripeAddressElementChangeEvent | null;\n shipping: StripeAddressElementChangeEvent | null;\n collectShippingAddress: boolean;\n}) {\n if (!(billing?.complete && billing.value.name.trim())) {\n throw new Error(\"Complete your billing name and address.\");\n }\n if (\n collectShippingAddress &&\n !(shipping?.complete && shipping.value.name.trim())\n ) {\n throw new Error(\"Complete your shipping name and address.\");\n }\n const submitted = await elements.submit();\n if (submitted.error) {\n throw new Error(submitted.error.message ?? \"Check your payment details.\");\n }\n const result = await stripe.createConfirmationToken({\n elements,\n params: {\n payment_method_data: {\n allow_redisplay: \"always\",\n billing_details: {\n address: billing.value.address,\n email,\n name: billing.value.name,\n phone,\n },\n },\n return_url: window.location.href,\n ...(collectShippingAddress && shipping\n ? {\n shipping: {\n address: shipping.value.address,\n name: shipping.value.name,\n phone,\n },\n }\n : undefined),\n },\n });\n if (result.error || !result.confirmationToken) {\n throw new Error(\n result.error?.message ?? \"Unable to prepare payment details.\"\n );\n }\n return result.confirmationToken.id;\n}\n\nexport async function completeAuctionAction(\n stripe: Stripe,\n result: LockerverseAuctionBidResult\n) {\n if (!result.requiresAction) {\n return;\n }\n if (!result.clientSecret) {\n throw new Error(\n \"Payment confirmation is incomplete. Check its status before trying again.\"\n );\n }\n const action = await stripe.handleNextAction({\n clientSecret: result.clientSecret,\n });\n if (action.error) {\n throw new Error(\n action.error.message ?? \"Payment confirmation is incomplete.\"\n );\n }\n}\n","// biome-ignore-all lint/suspicious/noUnnecessaryConditions: React refs change in effect cleanup and event handlers outside this static control flow.\nimport {\n type LockerverseAuction,\n type LockerverseAuctionItem,\n type LockerverseAuctionPurchaseResult,\n LockerverseSdkError,\n} from \"@lockerverse/sdk/auctions\";\nimport {\n AddressElement,\n PaymentElement,\n useElements,\n useStripe,\n} from \"@stripe/react-stripe-js\";\nimport type { StripeAddressElementChangeEvent } from \"@stripe/stripe-js\";\nimport { type FormEvent, useEffect, useId, useRef, useState } from \"react\";\nimport { safeParse } from \"valibot\";\nimport type {\n LockerverseAuctionItemProps,\n LockerverseAuctionPurchaseRecovery,\n} from \"./auction-item-types.ts\";\nimport {\n type AuctionSelection,\n auctionExpectedPricing,\n completeAuctionAction,\n createAuctionConfirmationToken,\n getAuctionSelectionError,\n getAuctionSelectionPricing,\n hasAuctionCheckoutChanged,\n} from \"./auction-payment.ts\";\nimport {\n requiredEmailSchema,\n requiredPhoneSchema,\n} from \"./contact-validation.ts\";\nimport { formatMoney } from \"./format-money.ts\";\nimport { notifyHostCallback } from \"./host-callback.ts\";\n\ntype AuctionCheckoutProps = LockerverseAuctionItemProps & {\n item: LockerverseAuctionItem;\n selection: AuctionSelection;\n onReview: (auction: LockerverseAuction, message: string) => void;\n onBack: () => void;\n};\n\ntype CheckoutState =\n | \"ready\"\n | \"busy\"\n | \"pending\"\n | \"retry\"\n | \"complete\"\n | \"uncertain\";\n\nfunction getSubmitLabel(\n state: CheckoutState,\n hasRecovery: boolean,\n isPurchase: boolean,\n totalCents: number\n) {\n if (state === \"busy\") {\n return \"Please wait…\";\n }\n if (state === \"retry\") {\n return \"Retry original purchase\";\n }\n if (hasRecovery) {\n return \"Check purchase status\";\n }\n return isPurchase ? `Pay ${formatMoney(totalCents)}` : \"Place bid\";\n}\n\nexport function AuctionCheckout(props: AuctionCheckoutProps) {\n const { auction, item, selection, client, onReview, onBack } = props;\n const stripe = useStripe();\n const elements = useElements();\n const id = useId();\n const [email, setEmail] = useState(\"\");\n const [phone, setPhone] = useState(\"\");\n const [billing, setBilling] =\n useState<StripeAddressElementChangeEvent | null>(null);\n const [shipping, setShipping] =\n useState<StripeAddressElementChangeEvent | null>(null);\n const [recovery, setRecovery] = useState(props.resumePurchase ?? null);\n const [state, setState] = useState<CheckoutState>(\n props.resumePurchase ? \"pending\" : \"ready\"\n );\n const [message, setMessage] = useState<string | null>(null);\n const purchaseRequestId = useRef<string | null>(\n props.resumePurchase?.submission.clientRequestId ?? null\n );\n const isTerminal = state === \"complete\" || state === \"uncertain\";\n const busy = useRef<boolean>(false);\n const mounted = useRef<boolean>(true);\n const callbacks = useRef(props);\n callbacks.current = props;\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const isPurchase =\n Boolean(recovery ?? props.resumePurchase) || item.saleMode === \"buy_now\";\n const pricing =\n recovery?.pricing ??\n props.resumePurchase?.pricing ??\n getAuctionSelectionPricing(auction, item, selection);\n\n const payment =\n recovery?.payment ?? props.resumePurchase?.payment ?? auction.payment;\n\n function rememberPurchase(value: LockerverseAuctionPurchaseRecovery | null) {\n if (mounted.current) {\n setRecovery(value);\n }\n notifyHostCallback(callbacks.current.onPurchaseRecoveryChange, value);\n }\n\n function finishPurchase(result: LockerverseAuctionPurchaseResult) {\n if (!mounted.current) {\n return;\n }\n if (result.status === \"paid\") {\n purchaseRequestId.current = null;\n rememberPurchase(null);\n setState(\"complete\");\n setMessage(`Purchase complete. Receipt: ${result.purchaseId}`);\n notifyHostCallback(callbacks.current.onPurchaseComplete, result);\n } else if (result.status === \"pending_payment\") {\n setState(\"pending\");\n setMessage(\n \"Your purchase is pending. Check its status before making another payment.\"\n );\n } else {\n purchaseRequestId.current = null;\n rememberPurchase(null);\n setState(\"ready\");\n setMessage(\n `This purchase is ${result.status.replaceAll(\"_\", \" \")}. You can start a new purchase.`\n );\n }\n }\n\n async function prepareSubmission() {\n if (!(stripe && elements && auction.payment)) {\n throw new Error(\"Payment details are still loading.\");\n }\n const parsedEmail = safeParse(requiredEmailSchema, email);\n const parsedPhone = safeParse(requiredPhoneSchema, phone);\n if (!(parsedEmail.success && parsedPhone.success)) {\n throw new Error(\n \"Enter a valid email and phone number with its country code.\"\n );\n }\n const current = await client.load(auction.slug);\n if (!mounted.current) {\n return null;\n }\n const currentItem = current.items.find(\n (candidate) => candidate.id === item.id\n );\n if (!currentItem) {\n onReview(current, \"This item is no longer available.\");\n return null;\n }\n const selectionError = getAuctionSelectionError(\n current,\n currentItem,\n selection\n );\n if (\n selectionError ||\n hasAuctionCheckoutChanged(auction, current, item, currentItem, selection)\n ) {\n onReview(\n current,\n selectionError ??\n \"The checkout details changed. Review them before continuing.\"\n );\n return null;\n }\n const confirmationToken = await createAuctionConfirmationToken({\n billing,\n collectShippingAddress: item.collectShippingAddress,\n elements,\n email: parsedEmail.output,\n phone: parsedPhone.output,\n shipping,\n stripe,\n });\n if (!mounted.current) {\n return null;\n }\n return {\n confirmationToken,\n email: parsedEmail.output,\n includeServiceFee: selection.includeServiceFee,\n phone: parsedPhone.output,\n ...auctionExpectedPricing(pricing),\n };\n }\n\n async function sendBid(\n submission: NonNullable<Awaited<ReturnType<typeof prepareSubmission>>>\n ) {\n const result = await client.createBid(auction.slug, item.id, {\n ...submission,\n amount: selection.amount,\n });\n if (!(mounted.current && stripe)) {\n return;\n }\n await completeAuctionAction(stripe, result);\n if (!mounted.current) {\n return;\n }\n setState(\"complete\");\n setMessage(\"Bid submitted. Watch your email for bid and auction updates.\");\n notifyHostCallback(callbacks.current.onBidSubmitted, result);\n }\n\n async function resolvePurchase(\n result: LockerverseAuctionPurchaseResult,\n active: LockerverseAuctionPurchaseRecovery\n ) {\n if (!(mounted.current && stripe)) {\n return;\n }\n if (result.requiresAction) {\n await completeAuctionAction(stripe, result);\n if (!mounted.current) {\n return;\n }\n const updated = await client.getPurchaseStatus(\n auction.slug,\n item.id,\n active.submission.clientRequestId\n );\n if (updated) {\n finishPurchase(updated);\n } else {\n setState(\"pending\");\n setMessage(\"Payment status is not available yet. Check again shortly.\");\n }\n return;\n }\n finishPurchase(result);\n }\n\n async function checkPurchase(active: LockerverseAuctionPurchaseRecovery) {\n const result = await client.getPurchaseStatus(\n auction.slug,\n item.id,\n active.submission.clientRequestId\n );\n if (!mounted.current) {\n return;\n }\n if (result) {\n await resolvePurchase(result, active);\n } else {\n setState(\"retry\");\n setMessage(\n \"No purchase is recorded yet. You can retry the original purchase with the same request ID.\"\n );\n }\n }\n\n async function clearRejectedPurchase(\n error: LockerverseSdkError,\n active: LockerverseAuctionPurchaseRecovery\n ) {\n const result = await client.getPurchaseStatus(\n auction.slug,\n item.id,\n active.submission.clientRequestId\n );\n if (!mounted.current) {\n return;\n }\n if (result) {\n await resolvePurchase(result, active);\n return;\n }\n rememberPurchase(null);\n setState(\"ready\");\n setMessage(\n `The purchase was rejected. Review the item and payment details before trying again. (${error.status ?? \"validation\"})`\n );\n }\n\n async function handleFailure<Failure>(\n error: Failure,\n requestSent: boolean,\n active: LockerverseAuctionPurchaseRecovery | null,\n wasRecovery: boolean\n ) {\n if (!mounted.current) {\n return;\n }\n const uncertain =\n requestSent &&\n (!(error instanceof LockerverseSdkError) || error.recoveryRecommended);\n setMessage(\n error instanceof Error\n ? error.message\n : \"Unable to complete this request.\"\n );\n if (isPurchase && active) {\n if (\n !wasRecovery &&\n error instanceof LockerverseSdkError &&\n !error.recoveryRecommended\n ) {\n try {\n await clearRejectedPurchase(error, active);\n return;\n } catch {\n /* Keep the original request when status cannot be established. */\n }\n }\n setState(\"pending\");\n setMessage(\n \"We could not confirm the purchase result. Check its status using the same purchase request.\"\n );\n notifyHostCallback(callbacks.current.onUncertain, \"purchase\");\n } else if (uncertain) {\n setState(\"uncertain\");\n setMessage(\n \"We could not confirm your bid. Do not submit another bid until you check your email or contact the auction organizer.\"\n );\n notifyHostCallback(callbacks.current.onUncertain, \"bid\");\n } else {\n setState(\"ready\");\n }\n }\n\n function getPurchaseRequestId() {\n purchaseRequestId.current ??= globalThis.crypto.randomUUID();\n return purchaseRequestId.current;\n }\n\n const checkoutPayment = stripe && elements && payment;\n\n async function submit(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n if (busy.current || isTerminal) {\n return;\n }\n if (!checkoutPayment) {\n setMessage(\"Payment details are still loading.\");\n return;\n }\n const retryOriginal = state === \"retry\";\n busy.current = true;\n setState(\"busy\");\n setMessage(null);\n let requestSent = false;\n let activeRecovery = recovery;\n try {\n if (!activeRecovery) {\n const submission = await prepareSubmission();\n if (!submission) {\n return;\n }\n if (!isPurchase) {\n requestSent = true;\n await sendBid(submission);\n return;\n }\n activeRecovery = Object.freeze({\n auctionId: auction.id,\n item,\n itemId: item.id,\n payment: Object.freeze({ ...checkoutPayment }),\n pricing,\n submission: Object.freeze({\n ...submission,\n clientRequestId: getPurchaseRequestId(),\n paymentMethodTypes: Object.freeze([\"card\"] as const),\n quantity: selection.quantity,\n }),\n });\n rememberPurchase(activeRecovery);\n }\n if (recovery && !retryOriginal) {\n await checkPurchase(activeRecovery);\n return;\n }\n requestSent = true;\n const result = await client.createPurchase(\n auction.slug,\n item.id,\n activeRecovery.submission\n );\n await resolvePurchase(result, activeRecovery);\n } catch (error) {\n await handleFailure(\n error,\n requestSent,\n activeRecovery,\n recovery !== null && !retryOriginal\n );\n } finally {\n busy.current = false;\n }\n }\n\n const buttonText = getSubmitLabel(\n state,\n recovery !== null,\n isPurchase,\n pricing.totalCents\n );\n\n const locked = state !== \"ready\";\n return (\n <form className=\"lockerverse-auctions__checkout\" onSubmit={submit}>\n <h3>{isPurchase ? \"Complete your purchase\" : \"Secure your bid\"}</h3>\n <p>\n {isPurchase ? \"Total\" : \"Bid including selected fees\"}:{\" \"}\n <strong>{formatMoney(pricing.totalCents)}</strong>\n </p>\n {!(recovery || isTerminal) && (\n <fieldset disabled={locked}>\n <label\n className=\"lockerverse-auctions__field\"\n htmlFor={`${id}-email`}\n >\n Email\n <input\n autoComplete=\"email\"\n id={`${id}-email`}\n onChange={(event) => setEmail(event.target.value)}\n required\n type=\"email\"\n value={email}\n />\n </label>\n <label\n className=\"lockerverse-auctions__field\"\n htmlFor={`${id}-phone`}\n >\n Phone, including country code\n <input\n autoComplete=\"tel\"\n id={`${id}-phone`}\n onChange={(event) => setPhone(event.target.value)}\n placeholder=\"+1 555 123 4567\"\n required\n type=\"tel\"\n value={phone}\n />\n </label>\n <h4>Billing details</h4>\n <AddressElement onChange={setBilling} options={{ mode: \"billing\" }} />\n {item.collectShippingAddress && (\n <>\n <h4>Shipping details</h4>\n <AddressElement\n onChange={setShipping}\n options={{ mode: \"shipping\" }}\n />\n </>\n )}\n <h4>{isPurchase ? \"Payment details\" : \"Card for the winning bid\"}</h4>\n <PaymentElement\n options={{\n fields: {\n billingDetails: {\n address: \"never\",\n email: \"never\",\n name: \"never\",\n phone: \"never\",\n },\n },\n }}\n />\n {!isPurchase && (\n <p className=\"lockerverse-auctions__notice\">\n By placing this bid, you agree to save this card and charge the\n bid plus selected fees if you win. Placing a bid does not charge\n your card now.\n </p>\n )}\n </fieldset>\n )}\n {message && (\n <p\n aria-live=\"polite\"\n className=\"lockerverse-auctions__notice\"\n role=\"status\"\n >\n {message}\n </p>\n )}\n {!isTerminal && (\n <button\n className=\"lockerverse-auctions__button\"\n disabled={state === \"busy\" || !stripe || !elements}\n type=\"submit\"\n >\n {buttonText}\n </button>\n )}\n {state === \"ready\" && (\n <button\n className=\"lockerverse-auctions__button\"\n onClick={onBack}\n type=\"button\"\n >\n Back to item\n </button>\n )}\n </form>\n );\n}\n","import type {\n LockerverseAuction,\n LockerverseAuctionItem,\n} from \"@lockerverse/sdk/auctions\";\nimport { useState } from \"react\";\n\nconst dateFormatter = new Intl.DateTimeFormat(\"en-US\", {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n timeZone: \"UTC\",\n});\n\nexport function AuctionItemDetails({\n auction,\n item,\n}: {\n auction: LockerverseAuction;\n item: LockerverseAuctionItem;\n}) {\n const [imageIndex, setImageIndex] = useState(0);\n const itemImage = item.images[imageIndex] ?? item.image;\n const boundary = auction.status === \"draft\" ? auction.startAt : auction.endAt;\n const date = new Date(boundary);\n return (\n <div>\n {itemImage ? (\n <img\n alt={item.name}\n className=\"lockerverse-auctions__image\"\n height={600}\n src={itemImage}\n width={768}\n />\n ) : null}\n {item.images.length > 1 ? (\n <fieldset className=\"lockerverse-auctions__gallery\">\n <legend>Item images</legend>\n {item.images.map((image, index) => (\n <button\n aria-label={`Show image ${index + 1}`}\n aria-pressed={imageIndex === index}\n key={image}\n onClick={() => setImageIndex(index)}\n type=\"button\"\n >\n <img alt=\"\" height={56} src={image} width={72} />\n </button>\n ))}\n </fieldset>\n ) : null}\n <p className=\"lockerverse-auctions__meta\">{auction.name}</p>\n <h2>{item.name}</h2>\n {item.description ? <p>{item.description}</p> : null}\n {Number.isFinite(date.getTime()) ? (\n <p>\n {auction.status === \"draft\" ? \"Starts\" : \"Ends\"}:{\" \"}\n <time dateTime={boundary}>{dateFormatter.format(date)} UTC</time>\n </p>\n ) : null}\n </div>\n );\n}\n","import {\n getLockerverseAuctionMinimumBid,\n type LockerverseAuction,\n type LockerverseAuctionItem,\n} from \"@lockerverse/sdk/auctions\";\nimport { type FormEvent, useId, useState } from \"react\";\nimport {\n type AuctionSelection,\n getAuctionSelectionError,\n getAuctionSelectionPricing,\n} from \"./auction-payment.ts\";\nimport { formatMoney } from \"./format-money.ts\";\n\ntype SelectionProps = {\n auction: LockerverseAuction;\n item: LockerverseAuctionItem;\n initialSelection: AuctionSelection | null;\n onContinue: (selection: AuctionSelection) => void;\n onError: (message: string) => void;\n};\n\nfunction ItemPrice({ item }: { item: LockerverseAuctionItem }) {\n const buyNow = item.saleMode === \"buy_now\";\n return (\n <>\n <h3>{buyNow ? \"Buy this item\" : \"Place a bid\"}</h3>\n <p>\n {buyNow ? \"Price\" : \"Current bid\"}:{\" \"}\n <strong>\n {formatMoney(\n buyNow ? (item.buyNowPriceAmount ?? 0) : (item.maxBidAmount ?? 0)\n )}\n </strong>\n </p>\n {buyNow ? null : (\n <p>\n Minimum next bid: {formatMoney(getLockerverseAuctionMinimumBid(item))}\n </p>\n )}\n {buyNow && item.availableQuantity !== null ? (\n <p>{item.availableQuantity} available</p>\n ) : null}\n </>\n );\n}\n\nfunction SelectionControls({\n auction,\n item,\n value,\n onChange,\n includeFee,\n setIncludeFee,\n}: {\n auction: LockerverseAuction;\n item: LockerverseAuctionItem;\n value: string;\n onChange: (value: string) => void;\n includeFee: boolean;\n setIncludeFee: (value: boolean) => void;\n}) {\n const id = useId();\n const buyNow = item.saleMode === \"buy_now\";\n return (\n <>\n <label className=\"lockerverse-auctions__field\" htmlFor={id}>\n {buyNow ? \"Quantity\" : \"Your bid (USD)\"}\n <input\n id={id}\n max={buyNow ? (item.availableQuantity ?? undefined) : undefined}\n min={\n buyNow ? 1 : Math.ceil(getLockerverseAuctionMinimumBid(item) / 100)\n }\n onChange={(event) => onChange(event.target.value)}\n required\n step={1}\n type=\"number\"\n value={value}\n />\n </label>\n {auction.serviceFeeEnabled ? (\n <label className=\"lockerverse-auctions__fee\">\n <input\n checked={includeFee}\n onChange={(event) => setIncludeFee(event.target.checked)}\n type=\"checkbox\"\n />\n Cover the {auction.pricingPolicy.serviceFeeRateBasisPoints / 100}%\n service fee\n </label>\n ) : null}\n <button\n className=\"lockerverse-auctions__button\"\n disabled={!auction.payment}\n type=\"submit\"\n >\n Continue\n </button>\n {auction.payment ? null : (\n <p role=\"alert\">Payments are not configured for this auction.</p>\n )}\n </>\n );\n}\n\nfunction initialValue(\n item: LockerverseAuctionItem,\n selection: AuctionSelection | null\n) {\n if (item.saleMode === \"buy_now\") {\n return String(selection ? selection.quantity : 1);\n }\n return String(\n selection\n ? selection.amount / 100\n : Math.ceil(getLockerverseAuctionMinimumBid(item) / 100)\n );\n}\n\nexport function AuctionItemSelection({\n auction,\n item,\n initialSelection,\n onContinue,\n onError,\n}: SelectionProps) {\n const [value, setValue] = useState(() =>\n initialValue(item, initialSelection)\n );\n const [includeFee, setIncludeFee] = useState(\n initialSelection\n ? initialSelection.includeServiceFee\n : auction.serviceFeeEnabled && auction.serviceFeeDefaultChecked\n );\n const buyNow = item.saleMode === \"buy_now\";\n const isOpen =\n auction.status === \"active\" &&\n item.status === \"active\" &&\n Date.parse(auction.endAt) > Date.now() &&\n !item.isSoldOut &&\n item.saleMode !== \"hybrid\";\n function continueToPayment(event: FormEvent<HTMLFormElement>) {\n event.preventDefault();\n const selection = {\n amount: buyNow ? 0 : Number(value) * 100,\n includeServiceFee: auction.serviceFeeEnabled && includeFee,\n quantity: buyNow ? Number(value) : 1,\n };\n const error = getAuctionSelectionError(auction, item, selection);\n if (error) {\n onError(error);\n return;\n }\n try {\n getAuctionSelectionPricing(auction, item, selection);\n } catch {\n onError(\"Enter a valid amount or quantity.\");\n return;\n }\n onContinue(selection);\n }\n return (\n <form\n className=\"lockerverse-auctions__checkout\"\n onSubmit={continueToPayment}\n >\n <ItemPrice item={item} />\n {isOpen ? (\n <SelectionControls\n auction={auction}\n includeFee={includeFee}\n item={item}\n onChange={setValue}\n setIncludeFee={setIncludeFee}\n value={value}\n />\n ) : (\n <p role=\"status\">\n {item.isSoldOut\n ? \"This item is sold out.\"\n : \"This item is not open for bids or purchases.\"}\n </p>\n )}\n </form>\n );\n}\n","import type {\n LockerverseAuctionItem as AuctionItem,\n LockerverseAuction,\n} from \"@lockerverse/sdk/auctions\";\nimport { Elements } from \"@stripe/react-stripe-js\";\nimport type {\n StripeElementsOptions,\n StripeElementsOptionsMode,\n} from \"@stripe/stripe-js\";\nimport { loadStripe } from \"@stripe/stripe-js/pure\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { AuctionCheckout } from \"./auction-checkout.tsx\";\nimport { AuctionItemDetails } from \"./auction-item-details.tsx\";\nimport { AuctionItemSelection } from \"./auction-item-selection.tsx\";\nimport type { LockerverseAuctionItemProps } from \"./auction-item-types.ts\";\nimport {\n type AuctionSelection,\n getAuctionSelectionPricing,\n} from \"./auction-payment.ts\";\n\nfunction AuctionPayment(\n props: LockerverseAuctionItemProps & {\n item: AuctionItem;\n selection: AuctionSelection;\n onReview: (auction: LockerverseAuction, message: string) => void;\n onBack: () => void;\n }\n) {\n const {\n auction,\n item,\n selection,\n theme = \"dark\",\n stripeLoader = loadStripe,\n style,\n onBack,\n resumePurchase,\n } = props;\n const [stripe, setStripe] =\n useState<Awaited<ReturnType<typeof loadStripe>>>(null);\n const [failed, setFailed] = useState(false);\n const [revision, setRevision] = useState(0);\n const payment = resumePurchase?.payment ?? auction.payment;\n useEffect(() => {\n let active = true;\n if (!payment) {\n setFailed(true);\n return;\n }\n Promise.resolve()\n .then(() =>\n stripeLoader(\n payment.publishableKey,\n payment.connectedAccountId\n ? { stripeAccount: payment.connectedAccountId }\n : undefined\n )\n )\n .then(\n (loaded) => {\n if (active) {\n setStripe(loaded);\n setFailed(!loaded);\n }\n },\n () => {\n if (active) {\n setFailed(true);\n }\n }\n );\n return () => {\n active = false;\n };\n }, [payment, stripeLoader, revision]);\n if (failed) {\n return (\n <div>\n <p role=\"alert\">Payment details could not load.</p>\n {resumePurchase ? null : (\n <button onClick={onBack} type=\"button\">\n Back to item\n </button>\n )}\n <button\n onClick={() => {\n setFailed(false);\n setStripe(null);\n setRevision((value) => value + 1);\n }}\n type=\"button\"\n >\n Try again\n </button>\n </div>\n );\n }\n if (!stripe) {\n return (\n <div>\n <p role=\"status\">Loading secure payment details…</p>\n {resumePurchase ? null : (\n <button onClick={onBack} type=\"button\">\n Back to item\n </button>\n )}\n </div>\n );\n }\n let paymentOptions: StripeElementsOptionsMode = {\n mode: \"setup\",\n setupFutureUsage: \"off_session\",\n };\n if (resumePurchase) {\n paymentOptions = {\n amount: resumePurchase.pricing.totalCents,\n currency: \"usd\",\n mode: \"payment\",\n };\n } else if (item.saleMode === \"buy_now\") {\n paymentOptions = {\n amount: getAuctionSelectionPricing(auction, item, selection).totalCents,\n currency: \"usd\",\n mode: \"payment\",\n };\n }\n const options: StripeElementsOptions = {\n ...paymentOptions,\n appearance: {\n theme: theme === \"dark\" ? \"night\" : \"stripe\",\n variables: {\n ...(style?.[\"--lockerverse-accent\"]\n ? { colorPrimary: style[\"--lockerverse-accent\"] }\n : undefined),\n ...(style?.[\"--lockerverse-font-family\"]\n ? { fontFamily: style[\"--lockerverse-font-family\"] }\n : undefined),\n },\n },\n currency: \"usd\",\n paymentMethodTypes: [\"card\"],\n };\n return (\n <Elements options={options} stripe={stripe}>\n <AuctionCheckout {...props} />\n </Elements>\n );\n}\n\nfunction AuctionItemView(\n props: LockerverseAuctionItemProps & { item: AuctionItem }\n) {\n const {\n auction: initialAuction,\n item: initialItem,\n resumePurchase,\n className,\n theme = \"dark\",\n style,\n } = props;\n const [auction, setAuction] = useState(initialAuction);\n const item =\n auction.items.find((candidate) => candidate.id === initialItem.id) ??\n resumePurchase?.item;\n const [selection, setSelection] = useState<AuctionSelection | null>(() =>\n resumePurchase\n ? {\n amount: 0,\n includeServiceFee:\n resumePurchase.submission.includeServiceFee ?? false,\n quantity: resumePurchase.submission.quantity,\n }\n : null\n );\n const [paying, setPaying] = useState(Boolean(resumePurchase));\n const [notice, setNotice] = useState<string | null>(null);\n\n function review(current: LockerverseAuction, message: string) {\n setAuction(current);\n setSelection(null);\n setPaying(false);\n setNotice(message);\n }\n function continueToPayment(next: AuctionSelection) {\n setNotice(null);\n setSelection(next);\n setPaying(true);\n }\n if (!item) {\n return <p role=\"alert\">This auction item is no longer available.</p>;\n }\n return (\n <section\n className={[\"lockerverse-auctions\", className].filter(Boolean).join(\" \")}\n data-lockerverse-theme={theme}\n style={style}\n >\n <div className=\"lockerverse-auctions__detail\">\n <AuctionItemDetails auction={auction} item={item} />\n <div>\n {notice ? (\n <p className=\"lockerverse-auctions__notice\" role=\"alert\">\n {notice}\n </p>\n ) : null}\n {paying && selection ? (\n <AuctionPayment\n {...props}\n auction={auction}\n item={item}\n onBack={() => setPaying(false)}\n onReview={review}\n selection={selection}\n />\n ) : (\n <AuctionItemSelection\n auction={auction}\n initialSelection={selection}\n item={item}\n onContinue={continueToPayment}\n onError={setNotice}\n />\n )}\n </div>\n </div>\n </section>\n );\n}\n\nexport function LockerverseAuctionItem(props: LockerverseAuctionItemProps) {\n const identity = useRef({\n auctionId: props.auction.id,\n client: props.client,\n itemId: props.itemId,\n });\n if (\n identity.current.client !== props.client ||\n identity.current.auctionId !== props.auction.id ||\n identity.current.itemId !== props.itemId\n ) {\n throw new TypeError(\n \"Auction item identity cannot change. Remount with a new React key.\"\n );\n }\n if (\n props.resumePurchase &&\n (props.resumePurchase.auctionId !== props.auction.id ||\n props.resumePurchase.itemId !== props.itemId ||\n props.resumePurchase.item.id !== props.itemId ||\n props.resumePurchase.item.auctionId !== props.auction.id)\n ) {\n throw new TypeError(\n \"The purchase recovery record belongs to a different auction item.\"\n );\n }\n const item =\n props.auction.items.find((candidate) => candidate.id === props.itemId) ??\n props.resumePurchase?.item;\n if (!item) {\n return <p role=\"alert\">This auction item is not available.</p>;\n }\n return <AuctionItemView {...props} item={item} />;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
.lockerverse-auctions {
|
|
2
|
+
--lockerverse-accent: #5751f2;
|
|
3
|
+
--lockerverse-bg: #080808;
|
|
4
|
+
--lockerverse-border: rgb(255 255 255 / 12%);
|
|
5
|
+
--lockerverse-control: #101010;
|
|
6
|
+
--lockerverse-muted: rgb(255 255 255 / 66%);
|
|
7
|
+
--lockerverse-radius: 10px;
|
|
8
|
+
--lockerverse-text: #fff;
|
|
9
|
+
--lockerverse-font-family: ui-sans-serif, system-ui, sans-serif;
|
|
10
|
+
box-sizing: border-box;
|
|
11
|
+
width: 100%;
|
|
12
|
+
padding: clamp(16px, 4%, 24px);
|
|
13
|
+
font: 15px / 1.5 var(--lockerverse-font-family);
|
|
14
|
+
color: var(--lockerverse-text);
|
|
15
|
+
background: var(--lockerverse-bg);
|
|
16
|
+
border-radius: var(--lockerverse-radius);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.lockerverse-auctions[data-lockerverse-theme="light"] {
|
|
20
|
+
--lockerverse-bg: #fff;
|
|
21
|
+
--lockerverse-border: rgb(18 20 22 / 14%);
|
|
22
|
+
--lockerverse-control: #f5f6f7;
|
|
23
|
+
--lockerverse-muted: rgb(18 20 22 / 64%);
|
|
24
|
+
--lockerverse-text: #121416;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.lockerverse-auctions * {
|
|
28
|
+
box-sizing: border-box;
|
|
29
|
+
}
|
|
30
|
+
.lockerverse-auctions h2 {
|
|
31
|
+
margin: 0;
|
|
32
|
+
font-size: 24px;
|
|
33
|
+
line-height: 1.25;
|
|
34
|
+
text-wrap: balance;
|
|
35
|
+
}
|
|
36
|
+
.lockerverse-auctions h3 {
|
|
37
|
+
margin: 0;
|
|
38
|
+
font-size: 19px;
|
|
39
|
+
line-height: 1.3;
|
|
40
|
+
overflow-wrap: anywhere;
|
|
41
|
+
}
|
|
42
|
+
.lockerverse-auctions p {
|
|
43
|
+
margin: 8px 0;
|
|
44
|
+
color: var(--lockerverse-muted);
|
|
45
|
+
overflow-wrap: anywhere;
|
|
46
|
+
white-space: pre-line;
|
|
47
|
+
}
|
|
48
|
+
.lockerverse-auctions__header {
|
|
49
|
+
margin-bottom: 24px;
|
|
50
|
+
}
|
|
51
|
+
.lockerverse-auctions__grid {
|
|
52
|
+
display: grid;
|
|
53
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
|
|
54
|
+
gap: 20px;
|
|
55
|
+
padding: 0;
|
|
56
|
+
margin: 0;
|
|
57
|
+
list-style: none;
|
|
58
|
+
}
|
|
59
|
+
.lockerverse-auctions__card {
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-direction: column;
|
|
62
|
+
height: 100%;
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
background: var(--lockerverse-control);
|
|
65
|
+
border: 1px solid var(--lockerverse-border);
|
|
66
|
+
border-radius: var(--lockerverse-radius);
|
|
67
|
+
}
|
|
68
|
+
.lockerverse-auctions__image {
|
|
69
|
+
display: block;
|
|
70
|
+
width: 100%;
|
|
71
|
+
height: auto;
|
|
72
|
+
aspect-ratio: 1.28;
|
|
73
|
+
object-fit: cover;
|
|
74
|
+
}
|
|
75
|
+
.lockerverse-auctions__body {
|
|
76
|
+
display: flex;
|
|
77
|
+
flex: 1;
|
|
78
|
+
flex-direction: column;
|
|
79
|
+
gap: 12px;
|
|
80
|
+
padding: 20px;
|
|
81
|
+
}
|
|
82
|
+
.lockerverse-auctions__meta {
|
|
83
|
+
font-size: 13px;
|
|
84
|
+
color: var(--lockerverse-muted);
|
|
85
|
+
}
|
|
86
|
+
.lockerverse-auctions__metrics {
|
|
87
|
+
display: flex;
|
|
88
|
+
flex-wrap: wrap;
|
|
89
|
+
gap: 16px;
|
|
90
|
+
margin: 0 0 4px;
|
|
91
|
+
}
|
|
92
|
+
.lockerverse-auctions__metrics dt {
|
|
93
|
+
font-size: 13px;
|
|
94
|
+
color: var(--lockerverse-muted);
|
|
95
|
+
}
|
|
96
|
+
.lockerverse-auctions__metrics dd {
|
|
97
|
+
margin: 0;
|
|
98
|
+
font-size: 18px;
|
|
99
|
+
font-weight: 600;
|
|
100
|
+
font-variant-numeric: tabular-nums;
|
|
101
|
+
}
|
|
102
|
+
.lockerverse-auctions button {
|
|
103
|
+
min-height: 44px;
|
|
104
|
+
padding: 10px 16px;
|
|
105
|
+
font: inherit;
|
|
106
|
+
font-weight: 600;
|
|
107
|
+
color: var(--lockerverse-text);
|
|
108
|
+
touch-action: manipulation;
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
background: var(--lockerverse-control);
|
|
111
|
+
border: 1px solid var(--lockerverse-border);
|
|
112
|
+
border-radius: var(--lockerverse-radius);
|
|
113
|
+
}
|
|
114
|
+
.lockerverse-auctions button:hover {
|
|
115
|
+
border-color: var(--lockerverse-text);
|
|
116
|
+
}
|
|
117
|
+
.lockerverse-auctions button:focus-visible,
|
|
118
|
+
.lockerverse-auctions h2:focus-visible {
|
|
119
|
+
outline: 2px solid var(--lockerverse-accent);
|
|
120
|
+
outline-offset: 3px;
|
|
121
|
+
}
|
|
122
|
+
.lockerverse-auctions__body > button {
|
|
123
|
+
width: 100%;
|
|
124
|
+
margin-top: auto;
|
|
125
|
+
}
|
|
126
|
+
.lockerverse-auctions__back {
|
|
127
|
+
margin-bottom: 20px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.lockerverse-auctions__detail {
|
|
131
|
+
display: grid;
|
|
132
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
133
|
+
gap: 32px;
|
|
134
|
+
}
|
|
135
|
+
.lockerverse-auctions__gallery {
|
|
136
|
+
display: flex;
|
|
137
|
+
gap: 8px;
|
|
138
|
+
min-width: 0;
|
|
139
|
+
padding: 0;
|
|
140
|
+
margin-top: 12px;
|
|
141
|
+
overflow-x: auto;
|
|
142
|
+
border: 0;
|
|
143
|
+
}
|
|
144
|
+
.lockerverse-auctions__gallery button {
|
|
145
|
+
padding: 2px;
|
|
146
|
+
cursor: pointer;
|
|
147
|
+
background: none;
|
|
148
|
+
border: 2px solid transparent;
|
|
149
|
+
border-radius: 4px;
|
|
150
|
+
}
|
|
151
|
+
.lockerverse-auctions__gallery button[aria-pressed="true"] {
|
|
152
|
+
border-color: var(--lockerverse-accent);
|
|
153
|
+
}
|
|
154
|
+
.lockerverse-auctions__gallery img {
|
|
155
|
+
display: block;
|
|
156
|
+
object-fit: cover;
|
|
157
|
+
}
|
|
158
|
+
.lockerverse-auctions__checkout {
|
|
159
|
+
display: grid;
|
|
160
|
+
gap: 16px;
|
|
161
|
+
padding: 24px;
|
|
162
|
+
border: 1px solid var(--lockerverse-border);
|
|
163
|
+
border-radius: var(--lockerverse-radius);
|
|
164
|
+
}
|
|
165
|
+
.lockerverse-auctions__checkout fieldset {
|
|
166
|
+
display: grid;
|
|
167
|
+
gap: 16px;
|
|
168
|
+
min-width: 0;
|
|
169
|
+
padding: 0;
|
|
170
|
+
margin: 0;
|
|
171
|
+
border: 0;
|
|
172
|
+
}
|
|
173
|
+
.lockerverse-auctions__checkout h4 {
|
|
174
|
+
margin: 4px 0 0;
|
|
175
|
+
}
|
|
176
|
+
.lockerverse-auctions__field {
|
|
177
|
+
display: grid;
|
|
178
|
+
gap: 8px;
|
|
179
|
+
}
|
|
180
|
+
.lockerverse-auctions__field input {
|
|
181
|
+
width: 100%;
|
|
182
|
+
min-width: 0;
|
|
183
|
+
min-height: 48px;
|
|
184
|
+
padding: 10px 12px;
|
|
185
|
+
font: inherit;
|
|
186
|
+
font-size: 16px;
|
|
187
|
+
color: var(--lockerverse-text);
|
|
188
|
+
background: var(--lockerverse-control);
|
|
189
|
+
border: 1px solid var(--lockerverse-border);
|
|
190
|
+
border-radius: var(--lockerverse-radius);
|
|
191
|
+
}
|
|
192
|
+
.lockerverse-auctions__fee {
|
|
193
|
+
display: flex;
|
|
194
|
+
gap: 10px;
|
|
195
|
+
align-items: center;
|
|
196
|
+
min-height: 44px;
|
|
197
|
+
}
|
|
198
|
+
.lockerverse-auctions__fee input {
|
|
199
|
+
width: 20px;
|
|
200
|
+
height: 20px;
|
|
201
|
+
accent-color: var(--lockerverse-accent);
|
|
202
|
+
}
|
|
203
|
+
.lockerverse-auctions__notice {
|
|
204
|
+
padding: 12px;
|
|
205
|
+
border: 1px solid var(--lockerverse-border);
|
|
206
|
+
border-radius: var(--lockerverse-radius);
|
|
207
|
+
}
|
|
208
|
+
.lockerverse-auctions input:focus-visible,
|
|
209
|
+
.lockerverse-auctions__gallery button:focus-visible {
|
|
210
|
+
outline: 2px solid var(--lockerverse-accent);
|
|
211
|
+
outline-offset: 3px;
|
|
212
|
+
}
|
|
213
|
+
@media (max-width: 720px) {
|
|
214
|
+
.lockerverse-auctions__detail {
|
|
215
|
+
grid-template-columns: minmax(0, 1fr);
|
|
216
|
+
gap: 24px;
|
|
217
|
+
}
|
|
218
|
+
.lockerverse-auctions__checkout {
|
|
219
|
+
padding: 16px;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { n as LockerverseTheme, t as LockerverseStyle } from "./theme.js";
|
|
2
|
+
import { CreateLockerverseAuctionOptions, LockerverseAuction, LockerverseAuctionClient, LockerverseAuctionItem, LockerverseSdkError } from "@lockerverse/sdk/auctions";
|
|
3
|
+
//#region src/use-lockerverse-auctions.d.ts
|
|
4
|
+
type UseLockerverseAuctionsResult = {
|
|
5
|
+
client: LockerverseAuctionClient;
|
|
6
|
+
auctions: LockerverseAuction[] | null;
|
|
7
|
+
loading: boolean;
|
|
8
|
+
error: LockerverseSdkError | null;
|
|
9
|
+
refresh: () => void;
|
|
10
|
+
};
|
|
11
|
+
declare function useLockerverseAuctions(options: CreateLockerverseAuctionOptions): UseLockerverseAuctionsResult;
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/lockerverse-auctions.d.ts
|
|
14
|
+
type LockerverseAuctionsProps = {
|
|
15
|
+
auctions: UseLockerverseAuctionsResult;
|
|
16
|
+
onSelectItem: (auction: LockerverseAuction, item: LockerverseAuctionItem) => void;
|
|
17
|
+
theme?: LockerverseTheme;
|
|
18
|
+
style?: LockerverseStyle;
|
|
19
|
+
className?: string;
|
|
20
|
+
};
|
|
21
|
+
/** Optional catalog UI. Use onSelectItem to open your item view or LockerverseAuctionItem. */
|
|
22
|
+
declare function LockerverseAuctions({ auctions, onSelectItem, theme, style, className }: LockerverseAuctionsProps): import("react").JSX.Element;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { LockerverseAuctions, type LockerverseStyle, type LockerverseTheme, type UseLockerverseAuctionsResult, useLockerverseAuctions };
|
|
25
|
+
//# sourceMappingURL=auctions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auctions.d.ts","names":[],"sources":["../src/use-lockerverse-auctions.ts","../src/lockerverse-auctions.tsx"],"mappings":";;;KAUY;EACV,QAAQ;EACR,UAAU;EACV;EACA,OAAO;EACP;;iBAQc,uBACd,SAAS,kCACR;;;KCfS;EACV,UAAU;EACV,eACE,SAAS,oBACT,MAAM;EAER,QAAQ;EACR,QAAQ;EACR;;;iBAwIc,sBACd,UACA,cACA,OACA,OACA,aACC,2CAAwB,IAAA"}
|
package/dist/auctions.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{t as e}from"./format-money.js";import{t}from"./immutable-resource-identity.js";import{useCallback as n,useEffect as r,useRef as i,useState as a}from"react";import{createLockerverseAuctionClient as o}from"@lockerverse/sdk/auctions";import{jsx as s,jsxs as c}from"react/jsx-runtime";const l={active:`Live now`,draft:`Coming soon`,finished:`Closed`},u=new Intl.DateTimeFormat(`en-US`,{dateStyle:`medium`,timeStyle:`short`,timeZone:`UTC`});function d({auction:e}){let t=e.status===`draft`?e.startAt:e.endAt,n=new Date(t);if(!Number.isFinite(n.getTime()))return null;let r={active:`Ends`,draft:`Opens`,finished:`Ended`}[e.status];return c(`span`,{className:`lockerverse-auctions__meta`,children:[r,` `,c(`time`,{dateTime:t,children:[u.format(n),` UTC`]})]})}function f({src:e}){return e?s(`img`,{alt:``,className:`lockerverse-auctions__image`,height:250,loading:`lazy`,src:e,width:320}):null}function p({auction:e,onSelect:t}){return c(`article`,{className:`lockerverse-auctions__card`,children:[s(f,{src:e.configuration.image??e.items.find(e=>e.image)?.image}),c(`div`,{className:`lockerverse-auctions__body`,children:[c(`span`,{className:`lockerverse-auctions__meta`,children:[l[e.status],` · `,e.items.length,` `,e.items.length===1?`item`:`items`]}),s(`h3`,{children:e.name}),s(d,{auction:e}),s(`button`,{"aria-label":`View items in ${e.name}`,onClick:t,type:`button`,children:`View items`})]})]})}function m({auction:t,item:n,onSelect:r}){let i=t.status===`active`?n.status:t.status,a=n.saleMode!==`auction`,o=n.saleMode!==`buy_now`;return c(`article`,{className:`lockerverse-auctions__card`,children:[s(f,{src:n.image??n.images[0]??t.configuration.image}),c(`div`,{className:`lockerverse-auctions__body`,children:[s(`span`,{className:`lockerverse-auctions__meta`,children:a&&n.isSoldOut?`Sold out`:l[i]}),s(`h3`,{children:n.name}),c(`dl`,{className:`lockerverse-auctions__metrics`,children:[o?c(`div`,{children:[s(`dt`,{children:n.maxBidAmount===null?`Starting bid`:`Current bid`}),s(`dd`,{children:e(n.maxBidAmount??n.minBidAmount??0)})]}):null,a&&n.buyNowPriceAmount!==null?c(`div`,{children:[s(`dt`,{children:`Buy now`}),s(`dd`,{children:e(n.buyNowPriceAmount)})]}):null,a&&n.availableQuantity!==null?c(`div`,{children:[s(`dt`,{children:`Available`}),s(`dd`,{children:n.availableQuantity})]}):null]}),s(`button`,{"aria-label":`View ${n.name}`,onClick:r,type:`button`,children:`View item`})]})]})}function h({auctions:e,onSelectItem:t,theme:n=`dark`,style:o,className:l}){let[u,f]=a(null),h=i(null),g=i(u),_=e.auctions?.find(e=>e.id===u);return r(()=>{g.current!==u&&(h.current?.focus(),g.current=u)},[u]),c(`section`,{"aria-busy":e.loading,"aria-label":`Auctions`,className:[`lockerverse-auctions`,l].filter(Boolean).join(` `),"data-lockerverse-theme":n,style:o,children:[c(`header`,{className:`lockerverse-auctions__header`,children:[_?s(`button`,{className:`lockerverse-auctions__back`,onClick:()=>f(null),type:`button`,children:`Back to auctions`}):null,s(`h2`,{ref:h,tabIndex:-1,children:_?.name??`Auctions`}),_?.description?s(`p`,{children:_.description}):null,_?s(d,{auction:_}):null]}),e.loading?s(`p`,{role:`status`,children:`Loading auctions…`}):null,e.error?c(`div`,{role:`alert`,children:[s(`p`,{children:e.error.message}),s(`button`,{onClick:e.refresh,type:`button`,children:`Try again`})]}):null,_&&_.items.length===0?s(`p`,{children:`No items are available in this auction.`}):null,_&&_.items.length>0?s(`ul`,{className:`lockerverse-auctions__grid`,children:_.items.map(e=>s(`li`,{children:s(m,{auction:_,item:e,onSelect:()=>t(_,e)})},e.id))}):null,!_&&e.auctions?.length===0?s(`p`,{children:`No auctions are available.`}):null,!_&&e.auctions&&e.auctions.length>0?s(`ul`,{className:`lockerverse-auctions__grid`,children:e.auctions.map(e=>s(`li`,{children:s(p,{auction:e,onSelect:()=>f(e.id)})},e.id))}):null]})}function g(e){t(`auctions`,{apiBaseUrl:e.apiBaseUrl,communitySlug:e.communitySlug,environment:e.environment,slug:``});let s=i(e.onError);s.current=e.onError;let[c]=a(()=>o({...e,onError:e=>s.current?.(e)})),[l,u]=a(0),[d,f]=a({auctions:null,error:null});r(()=>{let e=!0;return c.list().then(t=>{e&&f({auctions:t,error:null})},t=>{e&&f({auctions:null,error:t})}),()=>{e=!1}},[c,l]);let p=n(()=>{f({auctions:null,error:null}),u(e=>e+1)},[]);return{...d,client:c,loading:d.auctions===null&&d.error===null,refresh:p}}export{h as LockerverseAuctions,g as useLockerverseAuctions};
|
|
2
|
+
//# sourceMappingURL=auctions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auctions.js","names":[],"sources":["../src/lockerverse-auctions.tsx","../src/use-lockerverse-auctions.ts"],"sourcesContent":["import type {\n LockerverseAuction,\n LockerverseAuctionItem,\n LockerverseAuctionStatus,\n} from \"@lockerverse/sdk/auctions\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { formatMoney } from \"./format-money.ts\";\nimport type { LockerverseStyle, LockerverseTheme } from \"./theme.ts\";\nimport type { UseLockerverseAuctionsResult } from \"./use-lockerverse-auctions.ts\";\n\nexport type LockerverseAuctionsProps = {\n auctions: UseLockerverseAuctionsResult;\n onSelectItem: (\n auction: LockerverseAuction,\n item: LockerverseAuctionItem\n ) => void;\n theme?: LockerverseTheme;\n style?: LockerverseStyle;\n className?: string;\n};\n\nconst STATUS_LABELS = {\n active: \"Live now\",\n draft: \"Coming soon\",\n finished: \"Closed\",\n} satisfies Record<LockerverseAuctionStatus, string>;\nconst dateFormatter = new Intl.DateTimeFormat(\"en-US\", {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n timeZone: \"UTC\",\n});\n\nfunction AuctionTiming({ auction }: { auction: LockerverseAuction }) {\n const boundary = auction.status === \"draft\" ? auction.startAt : auction.endAt;\n const date = new Date(boundary);\n if (!Number.isFinite(date.getTime())) {\n return null;\n }\n const label = { active: \"Ends\", draft: \"Opens\", finished: \"Ended\" }[\n auction.status\n ];\n return (\n <span className=\"lockerverse-auctions__meta\">\n {label} <time dateTime={boundary}>{dateFormatter.format(date)} UTC</time>\n </span>\n );\n}\n\nfunction CatalogImage({ src }: { src: string | null | undefined }) {\n return src ? (\n <img\n alt=\"\"\n className=\"lockerverse-auctions__image\"\n height={250}\n loading=\"lazy\"\n src={src}\n width={320}\n />\n ) : null;\n}\n\nfunction AuctionCard({\n auction,\n onSelect,\n}: {\n auction: LockerverseAuction;\n onSelect: () => void;\n}) {\n return (\n <article className=\"lockerverse-auctions__card\">\n <CatalogImage\n src={\n auction.configuration.image ??\n auction.items.find((item) => item.image)?.image\n }\n />\n <div className=\"lockerverse-auctions__body\">\n <span className=\"lockerverse-auctions__meta\">\n {STATUS_LABELS[auction.status]} · {auction.items.length}{\" \"}\n {auction.items.length === 1 ? \"item\" : \"items\"}\n </span>\n <h3>{auction.name}</h3>\n <AuctionTiming auction={auction} />\n <button\n aria-label={`View items in ${auction.name}`}\n onClick={onSelect}\n type=\"button\"\n >\n View items\n </button>\n </div>\n </article>\n );\n}\n\nfunction ItemCard({\n auction,\n item,\n onSelect,\n}: {\n auction: LockerverseAuction;\n item: LockerverseAuctionItem;\n onSelect: () => void;\n}) {\n const status = auction.status === \"active\" ? item.status : auction.status;\n const canBuyNow = item.saleMode !== \"auction\";\n const canBid = item.saleMode !== \"buy_now\";\n return (\n <article className=\"lockerverse-auctions__card\">\n <CatalogImage\n src={item.image ?? item.images[0] ?? auction.configuration.image}\n />\n <div className=\"lockerverse-auctions__body\">\n <span className=\"lockerverse-auctions__meta\">\n {canBuyNow && item.isSoldOut ? \"Sold out\" : STATUS_LABELS[status]}\n </span>\n <h3>{item.name}</h3>\n <dl className=\"lockerverse-auctions__metrics\">\n {canBid ? (\n <div>\n <dt>\n {item.maxBidAmount === null ? \"Starting bid\" : \"Current bid\"}\n </dt>\n <dd>\n {formatMoney(item.maxBidAmount ?? item.minBidAmount ?? 0)}\n </dd>\n </div>\n ) : null}\n {canBuyNow && item.buyNowPriceAmount !== null ? (\n <div>\n <dt>Buy now</dt>\n <dd>{formatMoney(item.buyNowPriceAmount)}</dd>\n </div>\n ) : null}\n {canBuyNow && item.availableQuantity !== null ? (\n <div>\n <dt>Available</dt>\n <dd>{item.availableQuantity}</dd>\n </div>\n ) : null}\n </dl>\n <button\n aria-label={`View ${item.name}`}\n onClick={onSelect}\n type=\"button\"\n >\n View item\n </button>\n </div>\n </article>\n );\n}\n\n/** Optional catalog UI. Use onSelectItem to open your item view or LockerverseAuctionItem. */\nexport function LockerverseAuctions({\n auctions,\n onSelectItem,\n theme = \"dark\",\n style,\n className,\n}: LockerverseAuctionsProps) {\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const headingRef = useRef<HTMLHeadingElement>(null);\n const previousId = useRef(selectedId);\n const selected = auctions.auctions?.find(\n (auction) => auction.id === selectedId\n );\n useEffect(() => {\n if (previousId.current !== selectedId) {\n headingRef.current?.focus();\n previousId.current = selectedId;\n }\n }, [selectedId]);\n return (\n <section\n aria-busy={auctions.loading}\n aria-label=\"Auctions\"\n className={[\"lockerverse-auctions\", className].filter(Boolean).join(\" \")}\n data-lockerverse-theme={theme}\n style={style}\n >\n <header className=\"lockerverse-auctions__header\">\n {selected ? (\n <button\n className=\"lockerverse-auctions__back\"\n onClick={() => setSelectedId(null)}\n type=\"button\"\n >\n Back to auctions\n </button>\n ) : null}\n <h2 ref={headingRef} tabIndex={-1}>\n {selected?.name ?? \"Auctions\"}\n </h2>\n {selected?.description ? <p>{selected.description}</p> : null}\n {selected ? <AuctionTiming auction={selected} /> : null}\n </header>\n {auctions.loading ? <p role=\"status\">Loading auctions…</p> : null}\n {auctions.error ? (\n <div role=\"alert\">\n <p>{auctions.error.message}</p>\n <button onClick={auctions.refresh} type=\"button\">\n Try again\n </button>\n </div>\n ) : null}\n {selected && selected.items.length === 0 ? (\n <p>No items are available in this auction.</p>\n ) : null}\n {selected && selected.items.length > 0 ? (\n <ul className=\"lockerverse-auctions__grid\">\n {selected.items.map((item) => (\n <li key={item.id}>\n <ItemCard\n auction={selected}\n item={item}\n onSelect={() => onSelectItem(selected, item)}\n />\n </li>\n ))}\n </ul>\n ) : null}\n {!selected && auctions.auctions?.length === 0 ? (\n <p>No auctions are available.</p>\n ) : null}\n {!selected && auctions.auctions && auctions.auctions.length > 0 ? (\n <ul className=\"lockerverse-auctions__grid\">\n {auctions.auctions.map((auction) => (\n <li key={auction.id}>\n <AuctionCard\n auction={auction}\n onSelect={() => setSelectedId(auction.id)}\n />\n </li>\n ))}\n </ul>\n ) : null}\n </section>\n );\n}\n","import {\n type CreateLockerverseAuctionOptions,\n createLockerverseAuctionClient,\n type LockerverseAuction,\n type LockerverseAuctionClient,\n type LockerverseSdkError,\n} from \"@lockerverse/sdk/auctions\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useImmutableResourceIdentity } from \"./immutable-resource-identity.ts\";\n\nexport type UseLockerverseAuctionsResult = {\n client: LockerverseAuctionClient;\n auctions: LockerverseAuction[] | null;\n loading: boolean;\n error: LockerverseSdkError | null;\n refresh: () => void;\n};\n\ntype AuctionLoadState = Pick<\n UseLockerverseAuctionsResult,\n \"auctions\" | \"error\"\n>;\n\nexport function useLockerverseAuctions(\n options: CreateLockerverseAuctionOptions\n): UseLockerverseAuctionsResult {\n useImmutableResourceIdentity(\"auctions\", {\n apiBaseUrl: options.apiBaseUrl,\n communitySlug: options.communitySlug,\n environment: options.environment,\n slug: \"\",\n });\n const onErrorRef = useRef(options.onError);\n onErrorRef.current = options.onError;\n const [client] = useState(() =>\n createLockerverseAuctionClient({\n ...options,\n onError: (error) => onErrorRef.current?.(error),\n })\n );\n const [revision, setRevision] = useState(0);\n const [state, setState] = useState<AuctionLoadState>({\n auctions: null,\n error: null,\n });\n useEffect(() => {\n let active = true;\n client.list().then(\n (auctions) => {\n if (active) {\n setState({ auctions, error: null });\n }\n },\n (error: LockerverseSdkError) => {\n if (active) {\n setState({ auctions: null, error });\n }\n }\n );\n return () => {\n active = false;\n };\n }, [client, revision]);\n const refresh = useCallback(() => {\n setState({ auctions: null, error: null });\n setRevision((value) => value + 1);\n }, []);\n return {\n ...state,\n client,\n loading: state.auctions === null && state.error === null,\n refresh,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-money.js","names":[],"sources":["../src/format-money.ts"],"sourcesContent":["const usdFormatter = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n});\n\nexport function formatMoney(amountCents: number) {\n return usdFormatter.format(amountCents / 100);\n}\n"],"mappings":"AAAA,MAAM,EAAe,IAAI,KAAK,aAAa,QAAS,CAClD,SAAU,MACV,MAAO,UACT,CAAC,EAED,SAAgB,EAAY,EAAqB,CAC/C,OAAO,EAAa,OAAO,EAAc,GAAG,CAC9C"}
|
package/dist/host-callback.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{email as e,nonEmpty as t,pipe as n,regex as r,string as i,transform as a,trim as o}from"valibot";const s=`Enter a valid email address.`,c=`Phone is required.`,l=`Enter a valid phone number.`,u=/^(?:$|[^\s@]+@[^\s@]+\.[^\s@]+)$/,d=/^\+[1-9]\d{6,14}$/,f=/^(?:$|\+[1-9]\d{6,14})$/;function p(e){return e.trim().replace(/[().\s-]/g,``)}const m=n(i(),o(),r(u,s)),h=n(i(),o(),t(`Email is required.`),e(s)),g=n(i(),o(),a(p),r(f,l)),_=n(i(),o(),t(c),a(p),r(d,l));function v(e,t){if(e)try{Promise.resolve(e(t)).catch(()=>void 0)}catch{}}export{m as a,_ as c,p as i,l as n,g as o,c as r,h as s,v as t};
|
|
2
2
|
//# sourceMappingURL=host-callback.js.map
|