@lockerverse/react 0.2.102 → 0.2.104
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 +4 -0
- package/dist/auction-base.css +12 -0
- package/dist/auction-catalog.css +1 -1
- package/dist/auction-checkout.css +8 -75
- package/dist/auction-data.js +1 -1
- package/dist/auction-data.js.map +1 -1
- package/dist/auction-item-layout.css +7 -3
- package/dist/auction-item.d.ts.map +1 -1
- package/dist/auction-item.js +1 -1
- package/dist/auction-item.js.map +1 -1
- package/dist/auctions.d.ts.map +1 -1
- package/dist/auctions.js +1 -1
- package/dist/auctions.js.map +1 -1
- package/dist/form-controls.css +114 -0
- package/dist/form-skeleton.js +2 -0
- package/dist/form-skeleton.js.map +1 -0
- package/dist/form-ui.css +25 -9
- 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 +1 -1
- package/dist/immutable-resource-identity.js.map +1 -1
- package/dist/lockerverse-auction.js +1 -1
- package/dist/lockerverse-auction.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/payment-form.d.ts +1 -0
- package/dist/payment-form.d.ts.map +1 -1
- package/dist/phone-field.css +89 -0
- package/dist/select-control.css +18 -0
- package/dist/signup.css +1 -60
- package/dist/signup.d.ts.map +1 -1
- package/dist/signup.js +1 -1
- package/dist/signup.js.map +1 -1
- package/dist/stripe-loader.js +2 -0
- package/dist/stripe-loader.js.map +1 -0
- package/dist/styles.css +6 -232
- package/dist/use-auction-boundary.js +1 -1
- package/dist/use-auction-boundary.js.map +1 -1
- package/dist/use-lockerverse-auctions.js +1 -1
- package/dist/use-lockerverse-auctions.js.map +1 -1
- package/package.json +5 -5
- package/dist/phone.js +0 -2
- package/dist/phone.js.map +0 -1
package/dist/auctions.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,s as t,t as n}from"./use-auction-boundary.js";import{a as r,i,n as a,o,r as s,s as c,t as l}from"./lockerverse-auction.js";import{t as u}from"./use-lockerverse-auctions.js";import{ArrowRight as d,Gavel as f,ListChecks as p}from"lucide-react";import{useEffect as m,useRef as h,useState as g}from"react";import{Fragment as _,jsx as v,jsxs as y}from"react/jsx-runtime";function b({auction:a,onSelect:s}){n(a.startAt,a.endAt);let l=a.configuration.image||a.items.find(e=>e.image||e.images.length)?.image||a.items.find(e=>e.images.length)?.images[0]||a.community?.banner||a.community?.thumbnail,u=a.description||{active:`Bidding is open across this auction's items.`,draft:`Preview the lineup before bidding opens.`,finished:`Bidding has wrapped. Review the completed items.`}[e(a)];return y(`article`,{className:`lockerverse-auctions__catalog-card`,children:[v(`button`,{"aria-label":`View items in ${a.name}`,className:`lockerverse-auctions__catalog-select`,"data-auction-id":a.id,onClick:s,type:`button`}),y(`div`,{className:`lockerverse-auctions__catalog-media`,children:[v(i,{fallback:l,name:a.name}),y(`div`,{className:`lockerverse-auctions__catalog-chips`,children:[v(`span`,{className:`lockerverse-auctions__catalog-chip`,children:o[e(a)]}),v(c,{auction:a})]}),y(`dl`,{className:`lockerverse-auctions__catalog-metrics`,children:[v(r,{icon:v(p,{"aria-hidden":`true`,size:16}),label:`Items`,value:String(a.items.length)}),v(r,{icon:v(f,{"aria-hidden":`true`,size:16}),label:`Bids`,value:String(a.items.reduce((e,t)=>e+t.bidCount,0))})]})]}),y(`div`,{className:`lockerverse-auctions__catalog-body`,children:[v(`h3`,{children:a.name}),v(t,{className:`lockerverse-auctions__catalog-description`,description:u
|
|
1
|
+
import{a as e,s as t,t as n}from"./use-auction-boundary.js";import{a as r,i,n as a,o,r as s,s as c,t as l}from"./lockerverse-auction.js";import{t as u}from"./use-lockerverse-auctions.js";import{ArrowRight as d,Gavel as f,ListChecks as p}from"lucide-react";import{useEffect as m,useRef as h,useState as g}from"react";import{Fragment as _,jsx as v,jsxs as y}from"react/jsx-runtime";function b({auction:a,onSelect:s}){n(a.startAt,a.endAt);let l=a.configuration.image||a.items.find(e=>e.image||e.images.length)?.image||a.items.find(e=>e.images.length)?.images[0]||a.community?.banner||a.community?.thumbnail,u=a.description||{active:`Bidding is open across this auction's items.`,draft:`Preview the lineup before bidding opens.`,finished:`Bidding has wrapped. Review the completed items.`}[e(a)];return y(`article`,{className:`lockerverse-auctions__catalog-card`,children:[v(`button`,{"aria-label":`View items in ${a.name}`,className:`lockerverse-auctions__catalog-select`,"data-auction-id":a.id,onClick:s,type:`button`}),y(`div`,{className:`lockerverse-auctions__catalog-media`,children:[v(i,{fallback:l,name:a.name}),y(`div`,{className:`lockerverse-auctions__catalog-chips`,children:[v(`span`,{className:`lockerverse-auctions__catalog-chip`,children:o[e(a)]}),v(c,{auction:a})]}),y(`dl`,{className:`lockerverse-auctions__catalog-metrics`,children:[v(r,{icon:v(p,{"aria-hidden":`true`,size:16}),label:`Items`,value:String(a.items.length)}),v(r,{icon:v(f,{"aria-hidden":`true`,size:16}),label:`Bids`,value:String(a.items.reduce((e,t)=>e+t.bidCount,0))})]})]}),y(`div`,{className:`lockerverse-auctions__catalog-body`,children:[v(`h3`,{children:a.name}),v(t,{className:`lockerverse-auctions__catalog-description`,description:u}),y(`div`,{className:`lockerverse-auctions__catalog-footer`,children:[v(`span`,{className:`lockerverse-auctions__catalog-cta`,children:e(a)===`draft`?`Preview items`:`View items`}),v(`span`,{className:`lockerverse-auctions__catalog-arrow`,children:v(d,{"aria-hidden":`true`,size:16})})]})]})]})}function x({auctions:e,onSelectItem:t,theme:n=`dark`,style:r,className:i,showFilters:a=!0,showHeader:o=!0,showLineup:s=!0,renderItem:c}){let[u,d]=g(null),f=h(null),p=h(null),_=h(u),b=e.auctions?.find(e=>e.id===u);return m(()=>{if(_.current!==u){if(u===null){let e=[...p.current?.querySelectorAll(`button[data-auction-id]`)??[]].find(e=>e.dataset.auctionId===_.current);(f.current??e??p.current)?.focus()}_.current=u}},[u]),y(`section`,{"aria-busy":e.loading,"aria-label":`Auctions`,className:[`lockerverse-auctions`,`lockerverse-auctions--catalog`,i].filter(Boolean).join(` `),"data-lockerverse-theme":n,ref:p,style:r,tabIndex:-1,children:[!b&&o?v(`header`,{className:`lockerverse-auctions__catalog-header`,children:v(`h2`,{ref:f,tabIndex:-1,children:`Auctions`})}):null,e.loading?v(`p`,{role:`status`,children:`Loading auctions…`}):null,e.error?y(`div`,{role:`alert`,children:[v(`p`,{children:e.error.message}),v(`button`,{onClick:e.refresh,type:`button`,children:`Try again`})]}):null,b?v(l,{auction:b,onBack:()=>d(null),onSelectItem:t,showFilters:a,showHeader:o,showLineup:s,theme:n,...r?{style:r}:{},...c?{renderItem:c}:{}},b.id):v(S,{auctions:e.auctions,onSelectAuction:d,showLineup:s})]})}function S({auctions:e,showLineup:t,onSelectAuction:n}){return e?e.length?y(_,{children:[t?y(`div`,{className:`lockerverse-auctions__catalog-lineup`,children:[y(`div`,{children:[v(`h3`,{children:`Auction lineup`}),v(`p`,{children:`Browse the current collection.`})]}),y(`span`,{children:[e.length,` `,e.length===1?`auction`:`auctions`]})]}):null,v(`ul`,{className:`lockerverse-auctions__catalog-grid`,children:e.map(e=>v(`li`,{children:v(b,{auction:e,onSelect:()=>n(e.id)})},e.id))})]}):y(`div`,{className:`lockerverse-auctions__catalog-empty`,children:[v(`h3`,{children:`No auctions yet.`}),v(`p`,{children:`Published auctions will appear here once they are available.`})]}):null}export{a as LockerverseAuction,s as LockerverseAuctionItemCard,x as LockerverseAuctions,u as useLockerverseAuctions};
|
|
2
2
|
//# sourceMappingURL=auctions.js.map
|
package/dist/auctions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auctions.js","names":[],"sources":["../src/lockerverse-auctions.tsx"],"sourcesContent":["import type { LockerverseAuction as Auction } from \"@lockerverse/sdk/auctions\";\nimport { ArrowRight, Gavel, ListChecks } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport {\n CatalogImage,\n Metric,\n STATUS_LABELS,\n Timing,\n} from \"./auction-catalog-parts.tsx\";\nimport { AuctionDescription } from \"./auction-description.tsx\";\nimport { getAuctionDisplayStatus } from \"./auction-display.ts\";\nimport {\n AuctionContent,\n type LockerverseAuctionProps,\n} from \"./lockerverse-auction.tsx\";\nimport { useAuctionBoundary } from \"./use-auction-boundary.ts\";\nimport type { UseLockerverseAuctionsResult } from \"./use-lockerverse-auctions.ts\";\n\nexport type LockerverseAuctionsProps = Omit<\n LockerverseAuctionProps,\n \"auction\" | \"onBack\"\n> & {\n auctions: UseLockerverseAuctionsResult;\n};\n\nfunction AuctionCard({\n auction,\n onSelect,\n}: {\n auction: Auction;\n onSelect: () => void;\n}) {\n useAuctionBoundary(auction.startAt, auction.endAt);\n const fallback =\n auction.configuration.image ||\n auction.items.find((item) => item.image || item.images.length)?.image ||\n auction.items.find((item) => item.images.length)?.images[0] ||\n auction.community?.banner ||\n auction.community?.thumbnail;\n const description =\n auction.description ||\n {\n active: \"Bidding is open across this auction's items.\",\n draft: \"Preview the lineup before bidding opens.\",\n finished: \"Bidding has wrapped. Review the completed items.\",\n }[getAuctionDisplayStatus(auction)];\n return (\n <article className=\"lockerverse-auctions__catalog-card\">\n <button\n aria-label={`View items in ${auction.name}`}\n className=\"lockerverse-auctions__catalog-select\"\n data-auction-id={auction.id}\n onClick={onSelect}\n type=\"button\"\n />\n <div className=\"lockerverse-auctions__catalog-media\">\n <CatalogImage fallback={fallback} name={auction.name} />\n <div className=\"lockerverse-auctions__catalog-chips\">\n <span className=\"lockerverse-auctions__catalog-chip\">\n {STATUS_LABELS[getAuctionDisplayStatus(auction)]}\n </span>\n <Timing auction={auction} />\n </div>\n <dl className=\"lockerverse-auctions__catalog-metrics\">\n <Metric\n icon={<ListChecks aria-hidden=\"true\" size={16} />}\n label=\"Items\"\n value={String(auction.items.length)}\n />\n <Metric\n icon={<Gavel aria-hidden=\"true\" size={16} />}\n label=\"Bids\"\n value={String(\n auction.items.reduce((sum, item) => sum + item.bidCount, 0)\n )}\n />\n </dl>\n </div>\n <div className=\"lockerverse-auctions__catalog-body\">\n <h3>{auction.name}</h3>\n <AuctionDescription\n className=\"lockerverse-auctions__catalog-description\"\n description={description}\n links={false}\n />\n <div className=\"lockerverse-auctions__catalog-footer\">\n <span className=\"lockerverse-auctions__catalog-cta\">\n {getAuctionDisplayStatus(auction) === \"draft\"\n ? \"Preview items\"\n : \"View items\"}\n </span>\n <span className=\"lockerverse-auctions__catalog-arrow\">\n <ArrowRight aria-hidden=\"true\" size={16} />\n </span>\n </div>\n </div>\n </article>\n );\n}\n\n/** Optional auction browser. Select an auction to show its items. */\nexport function LockerverseAuctions({\n auctions,\n onSelectItem,\n theme = \"dark\",\n style,\n className,\n showFilters = true,\n showHeader = true,\n showLineup = true,\n renderItem,\n}: LockerverseAuctionsProps) {\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const headingRef = useRef<HTMLHeadingElement>(null);\n const sectionRef = useRef<HTMLElement>(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 if (selectedId === null) {\n const card = [\n ...(sectionRef.current?.querySelectorAll<HTMLButtonElement>(\n \"button[data-auction-id]\"\n ) ?? []),\n ].find((button) => button.dataset.auctionId === previousId.current);\n (headingRef.current ?? card ?? sectionRef.current)?.focus();\n }\n previousId.current = selectedId;\n }\n }, [selectedId]);\n return (\n <section\n aria-busy={auctions.loading}\n aria-label=\"Auctions\"\n className={[\n \"lockerverse-auctions\",\n \"lockerverse-auctions--catalog\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n data-lockerverse-theme={theme}\n ref={sectionRef}\n style={style}\n tabIndex={-1}\n >\n {!selected && showHeader ? (\n <header className=\"lockerverse-auctions__catalog-header\">\n <h2 ref={headingRef} tabIndex={-1}>\n Auctions\n </h2>\n </header>\n ) : null}\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 ? (\n <AuctionContent\n auction={selected}\n key={selected.id}\n onBack={() => setSelectedId(null)}\n onSelectItem={onSelectItem}\n showFilters={showFilters}\n showHeader={showHeader}\n showLineup={showLineup}\n theme={theme}\n {...(style ? { style } : {})}\n {...(renderItem ? { renderItem } : {})}\n />\n ) : (\n <AuctionList\n auctions={auctions.auctions}\n onSelectAuction={setSelectedId}\n showLineup={showLineup}\n />\n )}\n </section>\n );\n}\n\nfunction AuctionList({\n auctions,\n showLineup,\n onSelectAuction,\n}: {\n auctions: Auction[] | null;\n showLineup: boolean;\n onSelectAuction: (id: string) => void;\n}) {\n if (!auctions) {\n return null;\n }\n if (!auctions.length) {\n return (\n <div className=\"lockerverse-auctions__catalog-empty\">\n <h3>No auctions yet.</h3>\n <p>Published auctions will appear here once they are available.</p>\n </div>\n );\n }\n return (\n <>\n {showLineup ? (\n <div className=\"lockerverse-auctions__catalog-lineup\">\n <div>\n <h3>Auction lineup</h3>\n <p>Browse the current collection.</p>\n </div>\n <span>\n {auctions.length} {auctions.length === 1 ? \"auction\" : \"auctions\"}\n </span>\n </div>\n ) : null}\n <ul className=\"lockerverse-auctions__catalog-grid\">\n {auctions.map((auction) => (\n <li key={auction.id}>\n <AuctionCard\n auction={auction}\n onSelect={() => onSelectAuction(auction.id)}\n />\n </li>\n ))}\n </ul>\n </>\n );\n}\n"],"mappings":"4XAyBA,SAAS,EAAY,CACnB,UACA,YAIC,CACD,EAAmB,EAAQ,QAAS,EAAQ,KAAK,EACjD,IAAM,EACJ,EAAQ,cAAc,OACtB,EAAQ,MAAM,KAAM,GAAS,EAAK,OAAS,EAAK,OAAO,MAAM,CAAC,EAAE,OAChE,EAAQ,MAAM,KAAM,GAAS,EAAK,OAAO,MAAM,CAAC,EAAE,OAAO,IACzD,EAAQ,WAAW,QACnB,EAAQ,WAAW,UACf,EACJ,EAAQ,aACR,CACE,OAAQ,+CACR,MAAO,2CACP,SAAU,kDACZ,EAAE,EAAwB,CAAO,GACnC,OACE,EAAC,UAAD,CAAS,UAAU,qCAAnB,SAAA,CACE,EAAC,SAAD,CACE,aAAY,iBAAiB,EAAQ,OACrC,UAAU,uCACV,kBAAiB,EAAQ,GACzB,QAAS,EACT,KAAK,QACN,CAAA,EACD,EAAC,MAAD,CAAK,UAAU,sCAAf,SAAA,CACE,EAAC,EAAD,CAAwB,WAAU,KAAM,EAAQ,IAAO,CAAA,EACvD,EAAC,MAAD,CAAK,UAAU,sCAAf,SAAA,CACE,EAAC,OAAD,CAAM,UAAU,qCACb,SAAA,EAAc,EAAwB,CAAO,EAC1C,CAAA,EACN,EAAC,EAAD,CAAiB,SAAU,CAAA,CACxB,IACL,EAAC,KAAD,CAAI,UAAU,wCAAd,SAAA,CACE,EAAC,EAAD,CACE,KAAM,EAAC,EAAD,CAAY,cAAY,OAAO,KAAM,EAAK,CAAA,EAChD,MAAM,QACN,MAAO,OAAO,EAAQ,MAAM,MAAM,CACnC,CAAA,EACD,EAAC,EAAD,CACE,KAAM,EAAC,EAAD,CAAO,cAAY,OAAO,KAAM,EAAK,CAAA,EAC3C,MAAM,OACN,MAAO,OACL,EAAQ,MAAM,QAAQ,EAAK,IAAS,EAAM,EAAK,SAAU,CAAC,CAC5D,CACD,CAAA,CACC,GACD,IACL,EAAC,MAAD,CAAK,UAAU,qCAAf,SAAA,CACE,EAAC,KAAD,CAAA,SAAK,EAAQ,IAAS,CAAA,EACtB,EAAC,EAAD,CACE,UAAU,4CACG,cACb,MAAO,EACR,CAAA,EACD,EAAC,MAAD,CAAK,UAAU,uCAAf,SAAA,CACE,EAAC,OAAD,CAAM,UAAU,oCACb,SAAA,EAAwB,CAAO,IAAM,QAClC,gBACA,YACA,CAAA,EACN,EAAC,OAAD,CAAM,UAAU,sCACd,SAAA,EAAC,EAAD,CAAY,cAAY,OAAO,KAAM,EAAK,CAAA,CACtC,CAAA,CACH,GACF,GACE,GAEb,CAGA,SAAgB,EAAoB,CAClC,WACA,eACA,QAAQ,OACR,QACA,YACA,cAAc,GACd,aAAa,GACb,aAAa,GACb,cAC2B,CAC3B,GAAM,CAAC,EAAY,GAAiB,EAAwB,IAAI,EAC1D,EAAa,EAA2B,IAAI,EAC5C,EAAa,EAAoB,IAAI,EACrC,EAAa,EAAO,CAAU,EAC9B,EAAW,EAAS,UAAU,KACjC,GAAY,EAAQ,KAAO,CAC9B,EAcA,OAbA,MAAgB,CACd,GAAI,EAAW,UAAY,EAAY,CACrC,GAAI,IAAe,KAAM,CACvB,IAAM,EAAO,CACX,GAAI,EAAW,SAAS,iBACtB,yBACF,GAAK,CAAC,CACR,CAAC,CAAC,KAAM,GAAW,EAAO,QAAQ,YAAc,EAAW,OAAO,GACjE,EAAW,SAAW,GAAQ,EAAW,QAAA,EAAU,MAAM,CAC5D,CACA,EAAW,QAAU,CACvB,CACF,EAAG,CAAC,CAAU,CAAC,EAEb,EAAC,UAAD,CACE,YAAW,EAAS,QACpB,aAAW,WACX,UAAW,CACT,uBACA,gCACA,CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,yBAAwB,EACxB,IAAK,EACE,QACP,SAAU,GAbZ,SAAA,CAeG,CAAC,GAAY,EACZ,EAAC,SAAD,CAAQ,UAAU,uCAChB,SAAA,EAAC,KAAD,CAAI,IAAK,EAAY,SAAU,GAAI,SAAA,UAE/B,CAAA,CACE,CAAA,EACN,KACH,EAAS,QAAU,EAAC,IAAD,CAAG,KAAK,SAAS,SAAA,mBAAoB,CAAA,EAAI,KAC5D,EAAS,MACR,EAAC,MAAD,CAAK,KAAK,QAAV,SAAA,CACE,EAAC,IAAD,CAAA,SAAI,EAAS,MAAM,OAAW,CAAA,EAC9B,EAAC,SAAD,CAAQ,QAAS,EAAS,QAAS,KAAK,SAAS,SAAA,WAEzC,CAAA,CACL,CACH,CAAA,EAAA,KACH,EACC,EAAC,EAAD,CACE,QAAS,EAET,WAAc,EAAc,IAAI,EAClB,eACD,cACD,aACA,aACL,QACP,GAAK,EAAQ,CAAE,OAAM,EAAI,CAAC,EAC1B,GAAK,EAAa,CAAE,YAAW,EAAI,CAAC,CACrC,EATM,EAAS,EASf,EAED,EAAC,EAAD,CACE,SAAU,EAAS,SACnB,gBAAiB,EACL,YACb,CAAA,CAEI,GAEb,CAEA,SAAS,EAAY,CACnB,WACA,aACA,mBAKC,CAYD,OAXK,EAGA,EAAS,OASZ,EAAA,EAAA,CAAA,SAAA,CACG,EACC,EAAC,MAAD,CAAK,UAAU,uCAAf,SAAA,CACE,EAAC,MAAD,CAAA,SAAA,CACE,EAAC,KAAD,CAAA,SAAI,gBAAkB,CAAA,EACtB,EAAC,IAAD,CAAA,SAAG,gCAAiC,CAAA,CACjC,CAAA,CAAA,EACL,EAAC,OAAD,CAAA,SAAA,CACG,EAAS,OAAO,IAAE,EAAS,SAAW,EAAI,UAAY,UACnD,CAAA,CAAA,CACH,CACH,CAAA,EAAA,KACJ,EAAC,KAAD,CAAI,UAAU,qCACX,SAAA,EAAS,IAAK,GACb,EAAC,KAAD,CAAA,SACE,EAAC,EAAD,CACW,UACT,aAAgB,EAAgB,EAAQ,EAAE,CAC3C,CAAA,CACC,EALK,EAAQ,EAKb,CACL,CACC,CAAA,CACJ,CAAA,CAAA,EA7BA,EAAC,MAAD,CAAK,UAAU,sCAAf,SAAA,CACE,EAAC,KAAD,CAAA,SAAI,kBAAoB,CAAA,EACxB,EAAC,IAAD,CAAA,SAAG,8DAA+D,CAAA,CAC/D,IAPA,IAmCX"}
|
|
1
|
+
{"version":3,"file":"auctions.js","names":[],"sources":["../src/lockerverse-auctions.tsx"],"sourcesContent":["import type { LockerverseAuction as Auction } from \"@lockerverse/sdk/auctions\";\nimport { ArrowRight, Gavel, ListChecks } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport {\n CatalogImage,\n Metric,\n STATUS_LABELS,\n Timing,\n} from \"./auction-catalog-parts.tsx\";\nimport { AuctionDescription } from \"./auction-description.tsx\";\nimport { getAuctionDisplayStatus } from \"./auction-display.ts\";\nimport {\n AuctionContent,\n type LockerverseAuctionProps,\n} from \"./lockerverse-auction.tsx\";\nimport { useAuctionBoundary } from \"./use-auction-boundary.ts\";\nimport type { UseLockerverseAuctionsResult } from \"./use-lockerverse-auctions.ts\";\n\nexport type LockerverseAuctionsProps = Omit<\n LockerverseAuctionProps,\n \"auction\" | \"onBack\"\n> & {\n auctions: UseLockerverseAuctionsResult;\n};\n\nfunction AuctionCard({\n auction,\n onSelect,\n}: {\n auction: Auction;\n onSelect: () => void;\n}) {\n useAuctionBoundary(auction.startAt, auction.endAt);\n const fallback =\n auction.configuration.image ||\n auction.items.find((item) => item.image || item.images.length)?.image ||\n auction.items.find((item) => item.images.length)?.images[0] ||\n auction.community?.banner ||\n auction.community?.thumbnail;\n const description =\n auction.description ||\n {\n active: \"Bidding is open across this auction's items.\",\n draft: \"Preview the lineup before bidding opens.\",\n finished: \"Bidding has wrapped. Review the completed items.\",\n }[getAuctionDisplayStatus(auction)];\n return (\n <article className=\"lockerverse-auctions__catalog-card\">\n <button\n aria-label={`View items in ${auction.name}`}\n className=\"lockerverse-auctions__catalog-select\"\n data-auction-id={auction.id}\n onClick={onSelect}\n type=\"button\"\n />\n <div className=\"lockerverse-auctions__catalog-media\">\n <CatalogImage fallback={fallback} name={auction.name} />\n <div className=\"lockerverse-auctions__catalog-chips\">\n <span className=\"lockerverse-auctions__catalog-chip\">\n {STATUS_LABELS[getAuctionDisplayStatus(auction)]}\n </span>\n <Timing auction={auction} />\n </div>\n <dl className=\"lockerverse-auctions__catalog-metrics\">\n <Metric\n icon={<ListChecks aria-hidden=\"true\" size={16} />}\n label=\"Items\"\n value={String(auction.items.length)}\n />\n <Metric\n icon={<Gavel aria-hidden=\"true\" size={16} />}\n label=\"Bids\"\n value={String(\n auction.items.reduce((sum, item) => sum + item.bidCount, 0)\n )}\n />\n </dl>\n </div>\n <div className=\"lockerverse-auctions__catalog-body\">\n <h3>{auction.name}</h3>\n <AuctionDescription\n className=\"lockerverse-auctions__catalog-description\"\n description={description}\n />\n <div className=\"lockerverse-auctions__catalog-footer\">\n <span className=\"lockerverse-auctions__catalog-cta\">\n {getAuctionDisplayStatus(auction) === \"draft\"\n ? \"Preview items\"\n : \"View items\"}\n </span>\n <span className=\"lockerverse-auctions__catalog-arrow\">\n <ArrowRight aria-hidden=\"true\" size={16} />\n </span>\n </div>\n </div>\n </article>\n );\n}\n\n/** Optional auction browser. Select an auction to show its items. */\nexport function LockerverseAuctions({\n auctions,\n onSelectItem,\n theme = \"dark\",\n style,\n className,\n showFilters = true,\n showHeader = true,\n showLineup = true,\n renderItem,\n}: LockerverseAuctionsProps) {\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const headingRef = useRef<HTMLHeadingElement>(null);\n const sectionRef = useRef<HTMLElement>(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 if (selectedId === null) {\n const card = [\n ...(sectionRef.current?.querySelectorAll<HTMLButtonElement>(\n \"button[data-auction-id]\"\n ) ?? []),\n ].find((button) => button.dataset.auctionId === previousId.current);\n (headingRef.current ?? card ?? sectionRef.current)?.focus();\n }\n previousId.current = selectedId;\n }\n }, [selectedId]);\n return (\n <section\n aria-busy={auctions.loading}\n aria-label=\"Auctions\"\n className={[\n \"lockerverse-auctions\",\n \"lockerverse-auctions--catalog\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n data-lockerverse-theme={theme}\n ref={sectionRef}\n style={style}\n tabIndex={-1}\n >\n {!selected && showHeader ? (\n <header className=\"lockerverse-auctions__catalog-header\">\n <h2 ref={headingRef} tabIndex={-1}>\n Auctions\n </h2>\n </header>\n ) : null}\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 ? (\n <AuctionContent\n auction={selected}\n key={selected.id}\n onBack={() => setSelectedId(null)}\n onSelectItem={onSelectItem}\n showFilters={showFilters}\n showHeader={showHeader}\n showLineup={showLineup}\n theme={theme}\n {...(style ? { style } : {})}\n {...(renderItem ? { renderItem } : {})}\n />\n ) : (\n <AuctionList\n auctions={auctions.auctions}\n onSelectAuction={setSelectedId}\n showLineup={showLineup}\n />\n )}\n </section>\n );\n}\n\nfunction AuctionList({\n auctions,\n showLineup,\n onSelectAuction,\n}: {\n auctions: Auction[] | null;\n showLineup: boolean;\n onSelectAuction: (id: string) => void;\n}) {\n if (!auctions) {\n return null;\n }\n if (!auctions.length) {\n return (\n <div className=\"lockerverse-auctions__catalog-empty\">\n <h3>No auctions yet.</h3>\n <p>Published auctions will appear here once they are available.</p>\n </div>\n );\n }\n return (\n <>\n {showLineup ? (\n <div className=\"lockerverse-auctions__catalog-lineup\">\n <div>\n <h3>Auction lineup</h3>\n <p>Browse the current collection.</p>\n </div>\n <span>\n {auctions.length} {auctions.length === 1 ? \"auction\" : \"auctions\"}\n </span>\n </div>\n ) : null}\n <ul className=\"lockerverse-auctions__catalog-grid\">\n {auctions.map((auction) => (\n <li key={auction.id}>\n <AuctionCard\n auction={auction}\n onSelect={() => onSelectAuction(auction.id)}\n />\n </li>\n ))}\n </ul>\n </>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
@import "./select-control.css";
|
|
2
|
+
|
|
3
|
+
.lockerverse-form__field {
|
|
4
|
+
display: grid;
|
|
5
|
+
gap: 8px;
|
|
6
|
+
align-content: start;
|
|
7
|
+
min-width: 0;
|
|
8
|
+
}
|
|
9
|
+
.lockerverse-form__field > label {
|
|
10
|
+
display: block;
|
|
11
|
+
margin: 0;
|
|
12
|
+
font-size: 14px;
|
|
13
|
+
font-weight: 500;
|
|
14
|
+
line-height: 1.45;
|
|
15
|
+
color: var(--lockerverse-text);
|
|
16
|
+
}
|
|
17
|
+
.lockerverse-form__control {
|
|
18
|
+
box-sizing: border-box;
|
|
19
|
+
width: 100%;
|
|
20
|
+
min-width: 0;
|
|
21
|
+
min-height: 48px;
|
|
22
|
+
padding: 11px 13px;
|
|
23
|
+
margin: 0;
|
|
24
|
+
font: inherit;
|
|
25
|
+
font-size: 16px;
|
|
26
|
+
line-height: 1.5;
|
|
27
|
+
color: var(--lockerverse-text);
|
|
28
|
+
outline: none;
|
|
29
|
+
background: var(--lockerverse-control, var(--lockerverse-bg));
|
|
30
|
+
border: 1px solid var(--lockerverse-border);
|
|
31
|
+
border-radius: var(--lockerverse-radius, 10px);
|
|
32
|
+
}
|
|
33
|
+
.lockerverse-form__control::placeholder {
|
|
34
|
+
color: var(--lockerverse-placeholder, var(--lockerverse-muted));
|
|
35
|
+
opacity: 1;
|
|
36
|
+
}
|
|
37
|
+
.lockerverse-form__control:focus-visible {
|
|
38
|
+
outline: 2px solid var(--lockerverse-accent);
|
|
39
|
+
outline-offset: 2px;
|
|
40
|
+
border-color: var(--lockerverse-accent);
|
|
41
|
+
}
|
|
42
|
+
.lockerverse-form__control[aria-invalid="true"] {
|
|
43
|
+
border-color: var(--lockerverse-danger, #c53545);
|
|
44
|
+
}
|
|
45
|
+
.lockerverse-form__field textarea.lockerverse-form__control {
|
|
46
|
+
min-height: 112px;
|
|
47
|
+
resize: vertical;
|
|
48
|
+
}
|
|
49
|
+
.lockerverse-form__field select.lockerverse-form__control {
|
|
50
|
+
padding-right: 32px;
|
|
51
|
+
appearance: auto;
|
|
52
|
+
}
|
|
53
|
+
.lockerverse-form__error {
|
|
54
|
+
display: block;
|
|
55
|
+
margin: 0;
|
|
56
|
+
font-size: 13px;
|
|
57
|
+
line-height: 1.45;
|
|
58
|
+
color: var(--lockerverse-danger, #c53545);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
input.lockerverse-form__checkbox {
|
|
62
|
+
box-sizing: border-box;
|
|
63
|
+
display: grid;
|
|
64
|
+
flex: 0 0 auto;
|
|
65
|
+
place-content: center;
|
|
66
|
+
width: 20px;
|
|
67
|
+
min-width: 20px;
|
|
68
|
+
height: 20px;
|
|
69
|
+
min-height: 20px;
|
|
70
|
+
padding: 0;
|
|
71
|
+
margin: 0;
|
|
72
|
+
color: var(--lockerverse-accent-contrast, #000);
|
|
73
|
+
appearance: none;
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
background: transparent;
|
|
76
|
+
border: 1px solid color-mix(in srgb, var(--lockerverse-text) 25%, transparent);
|
|
77
|
+
border-radius: calc(var(--lockerverse-radius, 10px) / 2);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
input.lockerverse-form__checkbox::before {
|
|
81
|
+
width: 11px;
|
|
82
|
+
height: 7px;
|
|
83
|
+
content: "";
|
|
84
|
+
border-bottom: 2.5px solid currentcolor;
|
|
85
|
+
border-left: 2.5px solid currentcolor;
|
|
86
|
+
opacity: 0;
|
|
87
|
+
transform: translateY(-1px) rotate(-45deg) scale(0.7);
|
|
88
|
+
transition:
|
|
89
|
+
opacity 100ms ease,
|
|
90
|
+
transform 100ms ease;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
input.lockerverse-form__checkbox:checked {
|
|
94
|
+
background: var(--lockerverse-accent);
|
|
95
|
+
border-color: var(--lockerverse-accent);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
input.lockerverse-form__checkbox:checked::before {
|
|
99
|
+
opacity: 1;
|
|
100
|
+
transform: translateY(-1px) rotate(-45deg) scale(1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
input.lockerverse-form__checkbox:focus-visible {
|
|
104
|
+
outline: 2px solid var(--lockerverse-focus, var(--lockerverse-accent));
|
|
105
|
+
outline-offset: 2px;
|
|
106
|
+
border-color: var(--lockerverse-accent);
|
|
107
|
+
}
|
|
108
|
+
input.lockerverse-form__checkbox[aria-invalid="true"] {
|
|
109
|
+
border-color: var(--lockerverse-danger, #c53545);
|
|
110
|
+
}
|
|
111
|
+
input.lockerverse-form__checkbox:disabled {
|
|
112
|
+
cursor: not-allowed;
|
|
113
|
+
opacity: 0.6;
|
|
114
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{d as e,h as t,m as n,p as r}from"./host-callback.js";import{jsx as i,jsxs as a}from"react/jsx-runtime";import{array as o,minLength as s,nonEmpty as c,pipe as l,safeParse as u,string as d,trim as f}from"valibot";const p=/^#([\da-f]{3}|[\da-f]{6})$/i,m=/^([\da-f]{3}|[\da-f]{6})$/i;function h(e){let t=e.trim();return m.test(t)?`#${t}`:t}function g(e){let t=p.exec(h(e));if(!t)return;let[,n]=t;if(!n)return;let r=n.length===3?Array.from(n,e=>`${e}${e}`).join(``):n;return[0,2,4].map(e=>Number.parseInt(r.slice(e,e+2),16))}function _([e,t,n]){let[r=0,i=0,a=0]=[e,t,n].map((e=0)=>{let t=e/255;return t<=.04045?t/12.92:((t+.055)/1.055)**2.4});return .2126*r+.7152*i+.0722*a}function v(e){let t=g(e);if(!t)return;let n=_(t);return(n+.05)/.05>=1.05/(n+.05)?`#000`:`#fff`}function y(e){return e.type===`checkbox`?!1:e.type===`checkboxes`||e.type===`multi_select`?[]:``}function b(e){let t={};for(let n of e)t[n.id]=y(n);return t}function x(e){let t=u(d(),e);return t.success?t.output:``}function S(e,t){return e.map(e=>{let n=t[e.id];return e.type===`checkbox`?{fieldId:e.id,value:n===!0}:e.type===`checkboxes`||e.type===`multi_select`?{fieldId:e.id,value:Array.isArray(n)?n:[]}:{fieldId:e.id,value:x(n)}})}function C(e,t){let n={};for(let r of e){if(!r.required)continue;let e=`${r.label} is required.`,i=t[r.id];if(r.type===`checkbox`){i!==!0&&(n[r.id]=e);continue}let a=r.type===`checkboxes`||r.type===`multi_select`?u(l(o(d()),s(1,e)),i??[]):u(l(d(),f(),c(e)),x(i));a.success||(n[r.id]=a.issues[0]?.message??e)}return n}function w({choiceClassName:e,errorClassName:t,errors:n,fields:r,idPrefix:a,onChange:o,values:s}){return r.map(r=>i(T,{choiceClassName:e,error:n[r.id],errorClassName:t,field:r,idPrefix:a,onChange:e=>o({...s,[r.id]:e}),value:s[r.id]},r.id))}function T(e){let{field:t,idPrefix:n}=e,r=`${n}-custom-${t.id}`,a=`${r}-error`,o={...e,controlId:r,errorId:a};switch(t.type){case`checkbox`:return i(E,{...o,field:t});case`text`:case`textarea`:return i(D,{...o,field:t});case`select`:case`multi_select`:return i(O,{...o,field:t});case`radio`:case`checkboxes`:return i(k,{...o,field:t});default:return null}}function E({choiceClassName:t,controlId:n,error:o,errorClassName:s,errorId:c,field:l,onChange:u,value:d}){return a(`label`,{className:t,htmlFor:n,children:[i(e,{"aria-describedby":o?c:void 0,"aria-invalid":o?`true`:void 0,checked:d===!0,id:n,name:`custom:${l.id}`,onChange:e=>u(e.currentTarget.checked),required:l.required}),i(`span`,{children:l.label}),i(r,{className:s,error:o,id:c})]})}function D({controlId:e,error:r,errorId:a,field:o,onChange:s,value:c}){let l={"aria-describedby":r?a:void 0,"aria-invalid":r?`true`:void 0,id:e,name:`custom:${o.id}`,onChange:e=>s(e.currentTarget.value),required:o.required,value:x(c)};return o.type===`textarea`?i(n,{error:r,errorId:a,id:e,label:o.label,children:i(`textarea`,{...l,className:`lockerverse-form__control`})}):i(t,{...l,error:r,errorId:a,label:o.label})}function O({controlId:e,error:t,errorId:r,field:o,onChange:s,value:c}){return i(n,{error:t,errorId:r,id:e,label:o.label,children:a(`select`,{"aria-describedby":t?r:void 0,"aria-invalid":t?`true`:void 0,className:`lockerverse-form__control`,id:e,multiple:o.type===`multi_select`,name:`custom:${o.id}`,onChange:e=>s(o.type===`multi_select`?[...e.currentTarget.selectedOptions].map(e=>e.value):e.currentTarget.value),required:o.required,value:c===!0||c===!1?``:c??(o.type===`multi_select`?[]:``),children:[o.type===`select`?i(`option`,{value:``,children:`Select…`}):null,o.options.map(e=>i(`option`,{value:e.id,children:e.label},e.id))]})})}function k({choiceClassName:e,controlId:t,error:n,errorClassName:o,errorId:s,field:c,onChange:l,value:u}){let d=Array.isArray(u)?u:[];return a(`fieldset`,{"aria-describedby":n?s:void 0,"aria-invalid":n?`true`:void 0,children:[i(`legend`,{children:c.label}),c.options.map((n,r)=>a(`label`,{className:e,children:[i(`input`,{checked:Array.isArray(u)?u.includes(n.id):u===n.id,className:c.type===`checkboxes`?`lockerverse-form__checkbox`:void 0,id:`${t}-${r}`,name:`custom:${c.id}`,onChange:e=>{if(c.type===`radio`){l(n.id);return}l(e.currentTarget.checked?[...d,n.id]:d.filter(e=>e!==n.id))},required:c.required&&c.type===`radio`,type:c.type===`radio`?`radio`:`checkbox`,value:n.id}),i(`span`,{children:n.label})]},n.id)),i(r,{className:o,error:n,id:s})]})}function A({fieldCount:e,label:t,sectionCount:n=0,showCheckbox:r=!1}){return a(`div`,{className:`lockerverse-form-skeleton__loading`,children:[i(`span`,{className:`lockerverse-form-skeleton__sr-only`,role:`status`,children:t}),a(`div`,{"aria-hidden":`true`,className:`lockerverse-form-skeleton`,children:[a(`div`,{className:`lockerverse-form-skeleton__branding`,children:[i(`span`,{className:`lockerverse-form-skeleton__avatar`}),i(`span`,{className:`lockerverse-form-skeleton__community`})]}),i(`div`,{className:`lockerverse-form-skeleton__fields`,children:Array.from({length:e},(e,t)=>a(`div`,{className:`lockerverse-form-skeleton__field`,children:[i(`span`,{className:`lockerverse-form-skeleton__label`}),i(`span`,{className:`lockerverse-form-skeleton__input`})]},t))}),Array.from({length:n},(e,t)=>a(`div`,{className:`lockerverse-form-skeleton__section`,children:[i(`span`,{className:`lockerverse-form-skeleton__section-label`}),a(`div`,{className:`lockerverse-form-skeleton__section-content`,children:[i(`span`,{className:`lockerverse-form-skeleton__section-full`}),a(`div`,{className:`lockerverse-form-skeleton__section-grid`,children:[i(`span`,{className:`lockerverse-form-skeleton__section-half`}),i(`span`,{className:`lockerverse-form-skeleton__section-half`})]})]})]},t)),a(`div`,{className:`lockerverse-form-skeleton__actions`,children:[r?i(`span`,{className:`lockerverse-form-skeleton__check-line`}):null,i(`span`,{className:`lockerverse-form-skeleton__button`})]})]})]})}export{C as a,b as i,w as n,v as o,S as r,h as s,A as t};
|
|
2
|
+
//# sourceMappingURL=form-skeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-skeleton.js","names":[],"sources":["../src/accent-contrast.ts","../src/custom-fields.tsx","../src/form-skeleton.tsx"],"sourcesContent":["const HEX_COLOR = /^#([\\da-f]{3}|[\\da-f]{6})$/i;\nconst UNPREFIXED_HEX_COLOR = /^([\\da-f]{3}|[\\da-f]{6})$/i;\n\nexport function normalizeAccentColor(color: string) {\n const trimmedColor = color.trim();\n return UNPREFIXED_HEX_COLOR.test(trimmedColor)\n ? `#${trimmedColor}`\n : trimmedColor;\n}\n\nfunction parseHexColor(color: string) {\n const match = HEX_COLOR.exec(normalizeAccentColor(color));\n if (!match) {\n return;\n }\n const [, value] = match;\n if (!value) {\n return;\n }\n const expanded =\n value.length === 3\n ? Array.from(value, (character) => `${character}${character}`).join(\"\")\n : value;\n return [0, 2, 4].map((offset) =>\n Number.parseInt(expanded.slice(offset, offset + 2), 16)\n );\n}\n\nfunction relativeLuminance([red, green, blue]: number[]) {\n const [linearRed = 0, linearGreen = 0, linearBlue = 0] = [\n red,\n green,\n blue,\n ].map((channel = 0) => {\n const normalized = channel / 255;\n return normalized <= 0.040_45\n ? normalized / 12.92\n : ((normalized + 0.055) / 1.055) ** 2.4;\n });\n return 0.2126 * linearRed + 0.7152 * linearGreen + 0.0722 * linearBlue;\n}\n\nexport function getAccentContrast(color: string) {\n const parsed = parseHexColor(color);\n if (!parsed) {\n return;\n }\n const luminance = relativeLuminance(parsed);\n const blackContrast = (luminance + 0.05) / 0.05;\n const whiteContrast = 1.05 / (luminance + 0.05);\n return blackContrast >= whiteContrast ? \"#000\" : \"#fff\";\n}\n","import type {\n LockerverseBooleanCustomField,\n LockerverseCustomField,\n LockerverseCustomFieldAnswer,\n LockerverseMultiOptionCustomField,\n LockerverseSingleOptionCustomField,\n} from \"@lockerverse/sdk/checkout\";\nimport {\n array,\n minLength,\n nonEmpty,\n pipe,\n safeParse,\n string,\n trim,\n} from \"valibot\";\nimport { Checkbox, FieldError, FormField, TextField } from \"./form-field.tsx\";\n\nexport type CustomFieldValues = Record<string, boolean | string | string[]>;\n\nfunction createCustomFieldValue(field: LockerverseCustomField) {\n if (field.type === \"checkbox\") {\n return false;\n }\n if (field.type === \"checkboxes\" || field.type === \"multi_select\") {\n return [];\n }\n return \"\";\n}\n\nexport function createCustomFieldValues(fields: LockerverseCustomField[]) {\n const values: CustomFieldValues = {};\n for (const field of fields) {\n values[field.id] = createCustomFieldValue(field);\n }\n return values;\n}\n\nfunction getStringValue(value: CustomFieldValues[string] | undefined) {\n const result = safeParse(string(), value);\n return result.success ? result.output : \"\";\n}\n\nexport function buildCustomFieldAnswers(\n fields: LockerverseCustomField[],\n values: CustomFieldValues\n): LockerverseCustomFieldAnswer[] {\n return fields.map((field): LockerverseCustomFieldAnswer => {\n const value = values[field.id];\n if (field.type === \"checkbox\") {\n return { fieldId: field.id, value: value === true };\n }\n if (field.type === \"checkboxes\" || field.type === \"multi_select\") {\n return { fieldId: field.id, value: Array.isArray(value) ? value : [] };\n }\n return {\n fieldId: field.id,\n value: getStringValue(value),\n };\n });\n}\n\nexport function validateCustomFields(\n fields: LockerverseCustomField[],\n values: CustomFieldValues\n) {\n const errors: Record<string, string> = {};\n for (const field of fields) {\n if (!field.required) {\n continue;\n }\n const message = `${field.label} is required.`;\n const value = values[field.id];\n if (field.type === \"checkbox\") {\n if (value !== true) {\n errors[field.id] = message;\n }\n continue;\n }\n const result =\n field.type === \"checkboxes\" || field.type === \"multi_select\"\n ? safeParse(pipe(array(string()), minLength(1, message)), value ?? [])\n : safeParse(\n pipe(string(), trim(), nonEmpty(message)),\n getStringValue(value)\n );\n if (!result.success) {\n errors[field.id] = result.issues[0]?.message ?? message;\n }\n }\n return errors;\n}\n\nexport function CustomFields({\n choiceClassName,\n errorClassName,\n errors,\n fields,\n idPrefix,\n onChange,\n values,\n}: {\n choiceClassName: string;\n errorClassName: string;\n errors: Record<string, string>;\n fields: LockerverseCustomField[];\n idPrefix: string;\n onChange: (values: CustomFieldValues) => void;\n values: CustomFieldValues;\n}) {\n return fields.map((field) => (\n <CustomField\n choiceClassName={choiceClassName}\n error={errors[field.id]}\n errorClassName={errorClassName}\n field={field}\n idPrefix={idPrefix}\n key={field.id}\n onChange={(value) => onChange({ ...values, [field.id]: value })}\n value={values[field.id]}\n />\n ));\n}\n\ntype CustomFieldProps = {\n choiceClassName: string;\n error: string | undefined;\n errorClassName: string;\n field: LockerverseCustomField;\n idPrefix: string;\n onChange: (value: boolean | string | string[]) => void;\n value: boolean | string | string[] | undefined;\n};\n\nfunction CustomField(props: CustomFieldProps) {\n const { field, idPrefix } = props;\n const controlId = `${idPrefix}-custom-${field.id}`;\n const errorId = `${controlId}-error`;\n const controlProps = { ...props, controlId, errorId };\n switch (field.type) {\n case \"checkbox\":\n return <BooleanCustomField {...controlProps} field={field} />;\n case \"text\":\n case \"textarea\":\n return <TextCustomField {...controlProps} field={field} />;\n case \"select\":\n case \"multi_select\":\n return <SelectCustomField {...controlProps} field={field} />;\n case \"radio\":\n case \"checkboxes\":\n return <ChoiceCustomField {...controlProps} field={field} />;\n default:\n return null;\n }\n}\n\nfunction BooleanCustomField({\n choiceClassName,\n controlId,\n error,\n errorClassName,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & { field: LockerverseBooleanCustomField }) {\n return (\n <label className={choiceClassName} htmlFor={controlId}>\n <Checkbox\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n checked={value === true}\n id={controlId}\n name={`custom:${field.id}`}\n onChange={(event) => onChange(event.currentTarget.checked)}\n required={field.required}\n />\n <span>{field.label}</span>\n <FieldError className={errorClassName} error={error} id={errorId} />\n </label>\n );\n}\n\ntype ControlProps = CustomFieldProps & {\n controlId: string;\n errorId: string;\n};\n\nfunction TextCustomField({\n controlId,\n error,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & {\n field: Extract<LockerverseCustomField, { type: \"text\" | \"textarea\" }>;\n}) {\n const commonProps = {\n \"aria-describedby\": error ? errorId : undefined,\n \"aria-invalid\": error ? (\"true\" as const) : undefined,\n id: controlId,\n name: `custom:${field.id}`,\n onChange: (\n event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>\n ) => onChange(event.currentTarget.value),\n required: field.required,\n value: getStringValue(value),\n };\n return field.type === \"textarea\" ? (\n <FormField\n error={error}\n errorId={errorId}\n id={controlId}\n label={field.label}\n >\n <textarea {...commonProps} className=\"lockerverse-form__control\" />\n </FormField>\n ) : (\n <TextField\n {...commonProps}\n error={error}\n errorId={errorId}\n label={field.label}\n />\n );\n}\n\nfunction SelectCustomField({\n controlId,\n error,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & {\n field: LockerverseMultiOptionCustomField | LockerverseSingleOptionCustomField;\n}) {\n return (\n <FormField\n error={error}\n errorId={errorId}\n id={controlId}\n label={field.label}\n >\n <select\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n className=\"lockerverse-form__control\"\n id={controlId}\n multiple={field.type === \"multi_select\"}\n name={`custom:${field.id}`}\n onChange={(event) =>\n onChange(\n field.type === \"multi_select\"\n ? [...event.currentTarget.selectedOptions].map(\n (option) => option.value\n )\n : event.currentTarget.value\n )\n }\n required={field.required}\n value={\n value === true || value === false\n ? \"\"\n : (value ?? (field.type === \"multi_select\" ? [] : \"\"))\n }\n >\n {field.type === \"select\" ? <option value=\"\">Select…</option> : null}\n {field.options.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n </FormField>\n );\n}\n\nfunction ChoiceCustomField({\n choiceClassName,\n controlId,\n error,\n errorClassName,\n errorId,\n field,\n onChange,\n value,\n}: ControlProps & {\n field: LockerverseMultiOptionCustomField | LockerverseSingleOptionCustomField;\n}) {\n const selectedValues = Array.isArray(value) ? value : [];\n return (\n <fieldset\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? \"true\" : undefined}\n >\n <legend>{field.label}</legend>\n {field.options.map((option, index) => (\n <label className={choiceClassName} key={option.id}>\n <input\n checked={\n Array.isArray(value)\n ? value.includes(option.id)\n : value === option.id\n }\n className={\n field.type === \"checkboxes\"\n ? \"lockerverse-form__checkbox\"\n : undefined\n }\n id={`${controlId}-${index}`}\n name={`custom:${field.id}`}\n onChange={(event) => {\n if (field.type === \"radio\") {\n onChange(option.id);\n return;\n }\n onChange(\n event.currentTarget.checked\n ? [...selectedValues, option.id]\n : selectedValues.filter((id) => id !== option.id)\n );\n }}\n required={field.required && field.type === \"radio\"}\n type={field.type === \"radio\" ? \"radio\" : \"checkbox\"}\n value={option.id}\n />\n <span>{option.label}</span>\n </label>\n ))}\n <FieldError className={errorClassName} error={error} id={errorId} />\n </fieldset>\n );\n}\n","export function FormSkeleton({\n fieldCount,\n label,\n sectionCount = 0,\n showCheckbox = false,\n}: {\n fieldCount: number;\n label: string;\n sectionCount?: number;\n showCheckbox?: boolean;\n}) {\n return (\n <div className=\"lockerverse-form-skeleton__loading\">\n <span className=\"lockerverse-form-skeleton__sr-only\" role=\"status\">\n {label}\n </span>\n <div aria-hidden=\"true\" className=\"lockerverse-form-skeleton\">\n <div className=\"lockerverse-form-skeleton__branding\">\n <span className=\"lockerverse-form-skeleton__avatar\" />\n <span className=\"lockerverse-form-skeleton__community\" />\n </div>\n <div className=\"lockerverse-form-skeleton__fields\">\n {Array.from({ length: fieldCount }, (_, index) => (\n <div className=\"lockerverse-form-skeleton__field\" key={index}>\n <span className=\"lockerverse-form-skeleton__label\" />\n <span className=\"lockerverse-form-skeleton__input\" />\n </div>\n ))}\n </div>\n {Array.from({ length: sectionCount }, (_, index) => (\n <div className=\"lockerverse-form-skeleton__section\" key={index}>\n <span className=\"lockerverse-form-skeleton__section-label\" />\n <div className=\"lockerverse-form-skeleton__section-content\">\n <span className=\"lockerverse-form-skeleton__section-full\" />\n <div className=\"lockerverse-form-skeleton__section-grid\">\n <span className=\"lockerverse-form-skeleton__section-half\" />\n <span className=\"lockerverse-form-skeleton__section-half\" />\n </div>\n </div>\n </div>\n ))}\n <div className=\"lockerverse-form-skeleton__actions\">\n {showCheckbox ? (\n <span className=\"lockerverse-form-skeleton__check-line\" />\n ) : null}\n <span className=\"lockerverse-form-skeleton__button\" />\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
package/dist/form-ui.css
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
@import "./form-controls.css";
|
|
2
|
+
@import "./phone-field.css";
|
|
3
|
+
|
|
1
4
|
.lockerverse-payment,
|
|
2
5
|
.lockerverse-signup {
|
|
3
6
|
--lockerverse-form-accent: var(--lockerverse-accent);
|
|
@@ -37,8 +40,11 @@
|
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
:is(.lockerverse-payment, .lockerverse-signup)
|
|
40
|
-
input:not([type="checkbox"]):not([type="radio"])
|
|
41
|
-
:
|
|
43
|
+
input:not([type="checkbox"]):not([type="radio"]):where(
|
|
44
|
+
:not(.lockerverse-form__control):not(.lockerverse-form__phone input)
|
|
45
|
+
),
|
|
46
|
+
:is(.lockerverse-payment, .lockerverse-signup)
|
|
47
|
+
select:where(:not(.lockerverse-form__control)),
|
|
42
48
|
:is(.lockerverse-payment, .lockerverse-signup) textarea {
|
|
43
49
|
width: 100%;
|
|
44
50
|
min-height: 48px;
|
|
@@ -58,7 +64,8 @@
|
|
|
58
64
|
box-shadow 140ms ease;
|
|
59
65
|
}
|
|
60
66
|
|
|
61
|
-
:is(.lockerverse-payment, .lockerverse-signup)
|
|
67
|
+
:is(.lockerverse-payment, .lockerverse-signup)
|
|
68
|
+
select:where(:not(.lockerverse-form__control)) {
|
|
62
69
|
padding-right: 38px;
|
|
63
70
|
background-image:
|
|
64
71
|
linear-gradient(45deg, transparent 50%, currentcolor 50%),
|
|
@@ -85,8 +92,11 @@
|
|
|
85
92
|
}
|
|
86
93
|
|
|
87
94
|
:is(.lockerverse-payment, .lockerverse-signup)
|
|
88
|
-
input:not([type="checkbox"]):not([type="radio"]):
|
|
89
|
-
:
|
|
95
|
+
input:not([type="checkbox"]):not([type="radio"]):where(
|
|
96
|
+
:not(.lockerverse-form__control):not(.lockerverse-form__phone input)
|
|
97
|
+
):focus,
|
|
98
|
+
:is(.lockerverse-payment, .lockerverse-signup)
|
|
99
|
+
select:where(:not(.lockerverse-form__control)):focus,
|
|
90
100
|
:is(.lockerverse-payment, .lockerverse-signup) textarea:focus,
|
|
91
101
|
:is(.lockerverse-payment, .lockerverse-signup) button:focus {
|
|
92
102
|
outline: none;
|
|
@@ -94,15 +104,21 @@
|
|
|
94
104
|
}
|
|
95
105
|
|
|
96
106
|
:is(.lockerverse-payment, .lockerverse-signup)
|
|
97
|
-
input:not([type="checkbox"]):not([type="radio"]):
|
|
98
|
-
:
|
|
107
|
+
input:not([type="checkbox"]):not([type="radio"]):where(
|
|
108
|
+
:not(.lockerverse-form__control):not(.lockerverse-form__phone input)
|
|
109
|
+
):focus,
|
|
110
|
+
:is(.lockerverse-payment, .lockerverse-signup)
|
|
111
|
+
select:where(:not(.lockerverse-form__control)):focus,
|
|
99
112
|
:is(.lockerverse-payment, .lockerverse-signup) textarea:focus {
|
|
100
113
|
box-shadow: 0 0 0 1px var(--lockerverse-form-accent);
|
|
101
114
|
}
|
|
102
115
|
|
|
103
116
|
:is(.lockerverse-payment, .lockerverse-signup)
|
|
104
|
-
input:not([type="checkbox"]):not([type="radio"]):
|
|
105
|
-
:
|
|
117
|
+
input:not([type="checkbox"]):not([type="radio"]):where(
|
|
118
|
+
:not(.lockerverse-form__control):not(.lockerverse-form__phone input)
|
|
119
|
+
):focus-visible,
|
|
120
|
+
:is(.lockerverse-payment, .lockerverse-signup)
|
|
121
|
+
select:where(:not(.lockerverse-form__control)):focus-visible,
|
|
106
122
|
:is(.lockerverse-payment, .lockerverse-signup) textarea:focus-visible,
|
|
107
123
|
:is(.lockerverse-payment, .lockerverse-signup) button:focus-visible {
|
|
108
124
|
box-shadow: 0 0 0 2px
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-money.js","names":[],"sources":["../src/format-money.ts"],"sourcesContent":["const formatters = new Map<number, Intl.NumberFormat>();\n\nexport function formatMoney(amountCents: number, minimumFractionDigits = 2) {\n let formatter = formatters.get(minimumFractionDigits);\n if (!formatter) {\n formatter = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n maximumFractionDigits: 2,\n minimumFractionDigits,\n style: \"currency\",\n });\n formatters.set(minimumFractionDigits, formatter);\n }\n return formatter.format(amountCents / 100);\n}\n"],"mappings":"AAAA,MAAM,EAAa,IAAI,IAEvB,SAAgB,EAAY,EAAqB,EAAwB,EAAG,CAC1E,IAAI,EAAY,EAAW,IAAI,CAAqB,EAUpD,OATK,IACH,EAAY,IAAI,KAAK,aAAa,QAAS,CACzC,SAAU,MACV,sBAAuB,EACvB,wBACA,MAAO,UACT,CAAC,EACD,EAAW,IAAI,EAAuB,CAAS,GAE1C,EAAU,OAAO,EAAc,GAAG,CAC3C"}
|
package/dist/host-callback.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{ChevronDown as e}from"lucide-react";import{useRef as t}from"react";import{jsx as n,jsxs as r}from"react/jsx-runtime";import{check as i,email as a,nonEmpty as o,pipe as s,regex as c,string as l,transform as u,trim as d}from"valibot";function f({className:e,error:t,id:r}){return t?n(`span`,{className:`lockerverse-form__error ${e??``}`,id:r,role:`alert`,children:t}):null}function p({children:e,error:t,errorId:i,id:a,label:o}){return r(`div`,{className:`lockerverse-form__field`,children:[n(`label`,{htmlFor:a,children:o}),e,n(f,{error:t,id:i??`${a}-error`})]})}function m({className:e,error:t,errorId:r,id:i,label:a,...o}){let s=r??`${i}-error`;return n(p,{error:t,errorId:s,id:i,label:a,children:n(`input`,{...o,"aria-describedby":t?s:o[`aria-describedby`],"aria-invalid":t?`true`:o[`aria-invalid`],className:`lockerverse-form__control ${e??``}`,id:i})})}function h(e){return n(m,{autoComplete:`email`,placeholder:`name@example.com`,...e,type:`email`})}function g({className:e,...t}){return n(`input`,{...t,className:[`lockerverse-form__checkbox`,e].filter(Boolean).join(` `),type:`checkbox`})}const _=`Enter a valid email address.`,v=`Phone is required.`,y=`Enter a valid phone number.`,b=/^(?:$|[^\s@]+@[^\s@]+\.[^\s@]+)$/,x=/^\+[1-9]\d{6,14}$/;function S(e){return x.test(e)}function C(e){return e.trim().replace(/[().\s-]/g,``)}const w=s(l(),d(),c(b,_)),T=s(l(),d(),o(`Email is required.`),a(_)),E=s(l(),d(),i(e=>e===``||C(e)!==``,y),u(C),i(e=>e===``||S(e),y)),D=s(l(),d(),o(v),u(C),i(S,y));function O(e){if(e===`PAYMENT_WIDGET_PHONE_REQUIRED`||e===`SIGN_UP_WIDGET_PHONE_REQUIRED`)return v;if(e===`PAYMENT_WIDGET_PHONE_INVALID`||e===`SIGN_UP_WIDGET_PHONE_INVALID`)return y}const k=[{callingCode:`+1`,label:`🇺🇸 +1`,value:`US`},{callingCode:`+52`,label:`🇲🇽 +52`,value:`MX`},{callingCode:`+380`,label:`🇺🇦 +380`,value:`UA`},{callingCode:`+48`,label:`🇵🇱 +48`,value:`PL`},{callingCode:`+1`,label:`🇨🇦 +1`,value:`CA`},{callingCode:`+49`,label:`🇩🇪 +49`,value:`DE`},{callingCode:`+44`,label:`🇬🇧 +44`,value:`GB`},{callingCode:`+46`,label:`🇸🇪 +46`,value:`SE`},{callingCode:`+358`,label:`🇫🇮 +358`,value:`FI`},{callingCode:`+1`,label:`🇵🇷 +1`,value:`PR`}];function A(e){return k.find(t=>t.value===e)??k[0]}function j(e,t){let n=`${t}${t}`,r=e;for(;r.startsWith(n);)r=`${t}${r.slice(n.length)}`;return r}function M(e,t){let n=C(e);if(!n)return``;let r=A(t),i=j(n,r.callingCode);return i.startsWith(`+`)?i:`${r.callingCode}${i}`}function N(e,t=`US`){let n=C(e),r=A(t);return n.startsWith(`+`)&&!n.startsWith(r.callingCode)?k.find(e=>n.startsWith(e.callingCode))?.value??r.value:r.value}function P({id:i,name:a,value:o,onChange:s,country:c,required:l,disabled:u,inputRef:d,error:f,errorId:p,placeholder:m=`(201) 555-0123`}){let h=t(null),g=A(c);return r(`div`,{className:`lockerverse-form__phone`,dir:`ltr`,children:[r(`div`,{className:`lockerverse-form__phone-country`,children:[r(`span`,{"aria-hidden":`true`,children:[n(`span`,{className:`lockerverse-form__phone-flag`,children:g.label.split(` `)[0]}),g.callingCode,n(e,{"aria-hidden":`true`,size:14})]}),n(`select`,{"aria-label":`Phone number country`,disabled:u,name:`phoneCountry`,onChange:e=>{s({country:A(e.target.value).value,value:o}),h.current?.focus()},value:g.value,children:k.map(e=>n(`option`,{value:e.value,children:e.label},e.value))})]}),n(`input`,{"aria-describedby":f?p:void 0,"aria-invalid":f?!0:void 0,autoComplete:`tel-national`,disabled:u,id:i,name:a,onChange:e=>{let t=e.target.value;s({country:N(t,c),value:t})},placeholder:m,ref:e=>{h.current=e,d&&(d.current=e)},required:l,type:`tel`,value:o})]})}function F(e,t){if(e)try{Promise.resolve(e(t)).catch(()=>void 0)}catch{}}export{O as a,E as c,g as d,h as f,m as h,N as i,T as l,p as m,P as n,C as o,f as p,M as r,w as s,F as t,D as u};
|
|
2
2
|
//# sourceMappingURL=host-callback.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-callback.js","names":[],"sources":["../src/contact-validation.ts","../src/host-callback.ts"],"sourcesContent":["import { email, nonEmpty, pipe, regex, string, transform, trim } from \"valibot\";\n\nexport const EMAIL_REQUIRED_MESSAGE = \"Email is required.\";\nexport const EMAIL_INVALID_MESSAGE = \"Enter a valid email address.\";\nexport const PHONE_REQUIRED_MESSAGE = \"Phone is required.\";\nexport const PHONE_INVALID_MESSAGE = \"Enter a valid phone number.\";\n\nconst OPTIONAL_EMAIL_PATTERN = /^(?:$|[^\\s@]+@[^\\s@]+\\.[^\\s@]+)$/;\nconst INTERNATIONAL_PHONE_PATTERN = /^\\+[1-9]\\d{6,14}$/;\nconst OPTIONAL_INTERNATIONAL_PHONE_PATTERN = /^(?:$|\\+[1-9]\\d{6,14})$/;\n\nexport function normalizePhone(input: string) {\n return input.trim().replace(/[().\\s-]/g, \"\");\n}\n\nexport const optionalEmailSchema = pipe(\n string(),\n trim(),\n regex(OPTIONAL_EMAIL_PATTERN, EMAIL_INVALID_MESSAGE)\n);\n\nexport const requiredEmailSchema = pipe(\n string(),\n trim(),\n nonEmpty(EMAIL_REQUIRED_MESSAGE),\n email(EMAIL_INVALID_MESSAGE)\n);\n\nexport const optionalPhoneSchema = pipe(\n string(),\n trim(),\n transform(normalizePhone),\n regex(OPTIONAL_INTERNATIONAL_PHONE_PATTERN, PHONE_INVALID_MESSAGE)\n);\n\nexport const requiredPhoneSchema = pipe(\n string(),\n trim(),\n nonEmpty(PHONE_REQUIRED_MESSAGE),\n transform(normalizePhone),\n regex(INTERNATIONAL_PHONE_PATTERN, PHONE_INVALID_MESSAGE)\n);\n","export function notifyHostCallback<Value>(\n callback: ((value: Value) => void) | undefined,\n value: Value\n) {\n if (!callback) {\n return;\n }\n try {\n Promise.resolve(callback(value)).catch(() => undefined);\n } catch {\n // Host callback failures must not change completed SDK state.\n }\n}\n"],"mappings":"wGAEA,MACa,EAAwB,+BACxB,EAAyB,qBACzB,EAAwB,8BAE/B,EAAyB,mCACzB,EAA8B,oBAC9B,EAAuC,0BAE7C,SAAgB,EAAe,EAAe,CAC5C,OAAO,EAAM,KAAK,CAAC,CAAC,QAAQ,YAAa,EAAE,CAC7C,CAEA,MAAa,EAAsB,EACjC,EAAO,EACP,EAAK,EACL,EAAM,EAAwB,CAAqB,CACrD,EAEa,EAAsB,EACjC,EAAO,EACP,EAAK,EACL,EAAS,oBAAsB,EAC/B,EAAM,CAAqB,CAC7B,EAEa,EAAsB,EACjC,EAAO,EACP,EAAK,EACL,EAAU,CAAc,EACxB,EAAM,EAAsC,CAAqB,CACnE,EAEa,EAAsB,EACjC,EAAO,EACP,EAAK,EACL,EAAS,CAAsB,EAC/B,EAAU,CAAc,EACxB,EAAM,EAA6B,CAAqB,CAC1D,ECzCA,SAAgB,EACd,EACA,EACA,CACK,KAGL,GAAI,CACF,QAAQ,QAAQ,EAAS,CAAK,CAAC,CAAC,CAAC,UAAY,IAAA,EAAS,CACxD,MAAQ,CAER,CACF"}
|
|
1
|
+
{"version":3,"file":"host-callback.js","names":[],"sources":["../src/form-field.tsx","../src/contact-validation.ts","../src/phone.ts","../src/phone-field.tsx","../src/host-callback.ts"],"sourcesContent":["import type { ComponentProps, ReactNode } from \"react\";\n\nexport function FieldError({\n className,\n error,\n id,\n}: {\n className?: string;\n error: string | undefined;\n id: string;\n}) {\n return error ? (\n <span\n className={`lockerverse-form__error ${className ?? \"\"}`}\n id={id}\n role=\"alert\"\n >\n {error}\n </span>\n ) : null;\n}\n\nexport function FormField({\n children,\n error,\n errorId,\n id,\n label,\n}: {\n children: ReactNode;\n error?: string | undefined;\n errorId?: string | undefined;\n id: string;\n label: string;\n}) {\n return (\n <div className=\"lockerverse-form__field\">\n <label htmlFor={id}>{label}</label>\n {children}\n <FieldError error={error} id={errorId ?? `${id}-error`} />\n </div>\n );\n}\n\ntype TextFieldProps = ComponentProps<\"input\"> & {\n error?: string | undefined;\n errorId?: string | undefined;\n id: string;\n label: string;\n};\n\nexport function TextField({\n className,\n error,\n errorId,\n id,\n label,\n ...inputProps\n}: TextFieldProps) {\n const messageId = errorId ?? `${id}-error`;\n return (\n <FormField error={error} errorId={messageId} id={id} label={label}>\n <input\n {...inputProps}\n aria-describedby={error ? messageId : inputProps[\"aria-describedby\"]}\n aria-invalid={error ? \"true\" : inputProps[\"aria-invalid\"]}\n className={`lockerverse-form__control ${className ?? \"\"}`}\n id={id}\n />\n </FormField>\n );\n}\n\nexport function EmailField(props: Omit<TextFieldProps, \"type\">) {\n return (\n <TextField\n autoComplete=\"email\"\n placeholder=\"name@example.com\"\n {...props}\n type=\"email\"\n />\n );\n}\n\n/** Native checkbox semantics with the shared SDK control appearance. */\nexport function Checkbox({\n className,\n ...props\n}: Omit<ComponentProps<\"input\">, \"type\">) {\n return (\n <input\n {...props}\n className={[\"lockerverse-form__checkbox\", className]\n .filter(Boolean)\n .join(\" \")}\n type=\"checkbox\"\n />\n );\n}\n","import {\n check,\n email,\n nonEmpty,\n pipe,\n regex,\n string,\n transform,\n trim,\n} from \"valibot\";\n\nexport const EMAIL_REQUIRED_MESSAGE = \"Email is required.\";\nexport const EMAIL_INVALID_MESSAGE = \"Enter a valid email address.\";\nexport const PHONE_REQUIRED_MESSAGE = \"Phone is required.\";\nexport const PHONE_INVALID_MESSAGE = \"Enter a valid phone number.\";\n\nconst OPTIONAL_EMAIL_PATTERN = /^(?:$|[^\\s@]+@[^\\s@]+\\.[^\\s@]+)$/;\nconst INTERNATIONAL_PHONE_PATTERN = /^\\+[1-9]\\d{6,14}$/;\n\nfunction isValidInternationalPhone(value: string) {\n return INTERNATIONAL_PHONE_PATTERN.test(value);\n}\n\nexport function normalizePhone(input: string) {\n return input.trim().replace(/[().\\s-]/g, \"\");\n}\n\nexport const optionalEmailSchema = pipe(\n string(),\n trim(),\n regex(OPTIONAL_EMAIL_PATTERN, EMAIL_INVALID_MESSAGE)\n);\n\nexport const requiredEmailSchema = pipe(\n string(),\n trim(),\n nonEmpty(EMAIL_REQUIRED_MESSAGE),\n email(EMAIL_INVALID_MESSAGE)\n);\n\nexport const optionalPhoneSchema = pipe(\n string(),\n trim(),\n check(\n (value) => value === \"\" || normalizePhone(value) !== \"\",\n PHONE_INVALID_MESSAGE\n ),\n transform(normalizePhone),\n check(\n (value) => value === \"\" || isValidInternationalPhone(value),\n PHONE_INVALID_MESSAGE\n )\n);\n\nexport const requiredPhoneSchema = pipe(\n string(),\n trim(),\n nonEmpty(PHONE_REQUIRED_MESSAGE),\n transform(normalizePhone),\n check(isValidInternationalPhone, PHONE_INVALID_MESSAGE)\n);\n\nexport function getPhoneServerError(serverCode: string | undefined) {\n if (\n serverCode === \"PAYMENT_WIDGET_PHONE_REQUIRED\" ||\n serverCode === \"SIGN_UP_WIDGET_PHONE_REQUIRED\"\n ) {\n return PHONE_REQUIRED_MESSAGE;\n }\n if (\n serverCode === \"PAYMENT_WIDGET_PHONE_INVALID\" ||\n serverCode === \"SIGN_UP_WIDGET_PHONE_INVALID\"\n ) {\n return PHONE_INVALID_MESSAGE;\n }\n}\n","import { normalizePhone } from \"./contact-validation.ts\";\n\nexport const PHONE_COUNTRIES = [\n {\n callingCode: \"+1\",\n label: \"🇺🇸 +1\",\n value: \"US\",\n },\n {\n callingCode: \"+52\",\n label: \"🇲🇽 +52\",\n value: \"MX\",\n },\n {\n callingCode: \"+380\",\n label: \"🇺🇦 +380\",\n value: \"UA\",\n },\n {\n callingCode: \"+48\",\n label: \"🇵🇱 +48\",\n value: \"PL\",\n },\n {\n callingCode: \"+1\",\n label: \"🇨🇦 +1\",\n value: \"CA\",\n },\n {\n callingCode: \"+49\",\n label: \"🇩🇪 +49\",\n value: \"DE\",\n },\n {\n callingCode: \"+44\",\n label: \"🇬🇧 +44\",\n value: \"GB\",\n },\n {\n callingCode: \"+46\",\n label: \"🇸🇪 +46\",\n value: \"SE\",\n },\n {\n callingCode: \"+358\",\n label: \"🇫🇮 +358\",\n value: \"FI\",\n },\n {\n callingCode: \"+1\",\n label: \"🇵🇷 +1\",\n value: \"PR\",\n },\n] as const;\n\nexport type PhoneCountry = (typeof PHONE_COUNTRIES)[number][\"value\"];\n\nexport function getPhoneCountry(country: string) {\n return (\n PHONE_COUNTRIES.find((option) => option.value === country) ??\n PHONE_COUNTRIES[0]\n );\n}\n\nfunction removeRepeatedCallingCode(phone: string, callingCode: string) {\n const repeatedCallingCode = `${callingCode}${callingCode}`;\n let normalizedPhone = phone;\n while (normalizedPhone.startsWith(repeatedCallingCode)) {\n normalizedPhone = `${callingCode}${normalizedPhone.slice(repeatedCallingCode.length)}`;\n }\n return normalizedPhone;\n}\n\nexport function getInternationalPhone(phone: string, country: string) {\n const normalizedPhone = normalizePhone(phone);\n if (!normalizedPhone) {\n return \"\";\n }\n\n const selectedCountry = getPhoneCountry(country);\n const phoneWithOneCallingCode = removeRepeatedCallingCode(\n normalizedPhone,\n selectedCountry.callingCode\n );\n\n return phoneWithOneCallingCode.startsWith(\"+\")\n ? phoneWithOneCallingCode\n : `${selectedCountry.callingCode}${phoneWithOneCallingCode}`;\n}\n\nexport function resolvePhoneCountry(phone: string, country = \"US\") {\n const normalized = normalizePhone(phone);\n const current = getPhoneCountry(country);\n return normalized.startsWith(\"+\") &&\n !normalized.startsWith(current.callingCode)\n ? (PHONE_COUNTRIES.find((option) =>\n normalized.startsWith(option.callingCode)\n )?.value ?? current.value)\n : current.value;\n}\n","import { ChevronDown } from \"lucide-react\";\nimport { type RefObject, useRef } from \"react\";\nimport {\n getPhoneCountry,\n PHONE_COUNTRIES,\n resolvePhoneCountry,\n} from \"./phone.ts\";\n\nexport type PhoneInputValue = { value: string; country: string };\n\nexport type PhoneInputProps = {\n country: string;\n disabled?: boolean | undefined;\n error?: string | boolean | undefined;\n errorId?: string | undefined;\n id: string;\n inputRef?: RefObject<HTMLInputElement | null> | undefined;\n name?: string | undefined;\n onChange: (value: PhoneInputValue) => void;\n placeholder?: string | undefined;\n required?: boolean | undefined;\n value: string;\n};\n\n/** Controlled raw input. The caller validates and normalizes it on submission. */\nexport function PhoneInput({\n id,\n name,\n value,\n onChange,\n country,\n required,\n disabled,\n inputRef,\n error,\n errorId,\n placeholder = \"(201) 555-0123\",\n}: PhoneInputProps) {\n const input = useRef<HTMLInputElement>(null);\n const selectedCountry = getPhoneCountry(country);\n\n return (\n <div className=\"lockerverse-form__phone\" dir=\"ltr\">\n <div className=\"lockerverse-form__phone-country\">\n <span aria-hidden=\"true\">\n <span className=\"lockerverse-form__phone-flag\">\n {selectedCountry.label.split(\" \")[0]}\n </span>\n {selectedCountry.callingCode}\n <ChevronDown aria-hidden=\"true\" size={14} />\n </span>\n <select\n aria-label=\"Phone number country\"\n disabled={disabled}\n name=\"phoneCountry\"\n onChange={(event) => {\n const nextCountry = getPhoneCountry(event.target.value);\n onChange({ country: nextCountry.value, value });\n input.current?.focus();\n }}\n value={selectedCountry.value}\n >\n {PHONE_COUNTRIES.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n <input\n aria-describedby={error ? errorId : undefined}\n aria-invalid={error ? true : undefined}\n autoComplete=\"tel-national\"\n disabled={disabled}\n id={id}\n name={name}\n onChange={(event) => {\n const raw = event.target.value;\n onChange({ country: resolvePhoneCountry(raw, country), value: raw });\n }}\n placeholder={placeholder}\n ref={(element) => {\n input.current = element;\n if (inputRef) {\n inputRef.current = element;\n }\n }}\n required={required}\n type=\"tel\"\n value={value}\n />\n </div>\n );\n}\n","export function notifyHostCallback<Value>(\n callback: ((value: Value) => void) | undefined,\n value: Value\n) {\n if (!callback) {\n return;\n }\n try {\n Promise.resolve(callback(value)).catch(() => undefined);\n } catch {\n // Host callback failures must not change completed SDK state.\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useRef as e}from"react";function t(e,t){return e.apiBaseUrl===t.apiBaseUrl&&e.communitySlug===t.communitySlug&&e.environment===t.environment&&e.slug===t.slug}function n(n,r){if(!t(e(r).current,r))throw TypeError(`Lockerverse ${n} identity cannot change after initialization. Remount with a new React key.`)}export{n as t};
|
|
1
|
+
import{useRef as e}from"react";function t(e,t){return e.apiBaseUrl===t.apiBaseUrl&&e.communitySlug===t.communitySlug&&e.mediaBaseUrl===t.mediaBaseUrl&&e.environment===t.environment&&e.slug===t.slug}function n(n,r){if(!t(e(r).current,r))throw TypeError(`Lockerverse ${n} identity cannot change after initialization. Remount with a new React key.`)}export{n as t};
|
|
2
2
|
//# sourceMappingURL=immutable-resource-identity.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"immutable-resource-identity.js","names":[],"sources":["../src/immutable-resource-identity.ts"],"sourcesContent":["import { useRef } from \"react\";\n\ntype LockerverseResourceIdentity = {\n apiBaseUrl: string | undefined;\n communitySlug: string;\n environment: string | undefined;\n slug: string;\n};\n\nfunction hasSameIdentity(\n initial: LockerverseResourceIdentity,\n current: LockerverseResourceIdentity\n) {\n return (\n initial.apiBaseUrl === current.apiBaseUrl &&\n initial.communitySlug === current.communitySlug &&\n initial.environment === current.environment &&\n initial.slug === current.slug\n );\n}\n\nexport function useImmutableResourceIdentity(\n resource: \"payment widget\" | \"signup\" | \"auctions\" | \"auction\",\n identity: LockerverseResourceIdentity\n) {\n const initial = useRef(identity);\n if (!hasSameIdentity(initial.current, identity)) {\n throw new TypeError(\n `Lockerverse ${resource} identity cannot change after initialization. Remount with a new React key.`\n );\n }\n}\n"],"mappings":"+
|
|
1
|
+
{"version":3,"file":"immutable-resource-identity.js","names":[],"sources":["../src/immutable-resource-identity.ts"],"sourcesContent":["import { useRef } from \"react\";\n\ntype LockerverseResourceIdentity = {\n apiBaseUrl: string | undefined;\n communitySlug: string;\n mediaBaseUrl?: string | undefined;\n environment: string | undefined;\n slug: string;\n};\n\nfunction hasSameIdentity(\n initial: LockerverseResourceIdentity,\n current: LockerverseResourceIdentity\n) {\n return (\n initial.apiBaseUrl === current.apiBaseUrl &&\n initial.communitySlug === current.communitySlug &&\n initial.mediaBaseUrl === current.mediaBaseUrl &&\n initial.environment === current.environment &&\n initial.slug === current.slug\n );\n}\n\nexport function useImmutableResourceIdentity(\n resource: \"payment widget\" | \"signup\" | \"auctions\" | \"auction\",\n identity: LockerverseResourceIdentity\n) {\n const initial = useRef(identity);\n if (!hasSameIdentity(initial.current, identity)) {\n throw new TypeError(\n `Lockerverse ${resource} identity cannot change after initialization. Remount with a new React key.`\n );\n }\n}\n"],"mappings":"+BAUA,SAAS,EACP,EACA,EACA,CACA,OACE,EAAQ,aAAe,EAAQ,YAC/B,EAAQ,gBAAkB,EAAQ,eAClC,EAAQ,eAAiB,EAAQ,cACjC,EAAQ,cAAgB,EAAQ,aAChC,EAAQ,OAAS,EAAQ,IAE7B,CAEA,SAAgB,EACd,EACA,EACA,CAEA,GAAI,CAAC,EADW,EAAO,CACI,CAAC,CAAC,QAAS,CAAQ,EAC5C,MAAU,UACR,eAAe,EAAS,4EAC1B,CAEJ"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./use-auction-boundary.js";import{ArrowRight as s,ChevronLeft as c,Clock3 as l,Gavel as u,ShoppingBag as d}from"lucide-react";import{useEffect as f,useMemo as p,useRef as m,useState as h}from"react";import{Fragment as g,jsx as _,jsxs as v}from"react/jsx-runtime";const y={active:`Live now`,draft:`Coming soon`,finished:`Closed`};function b({images:e,fallback:t,name:r}){let i=p(()=>{let n=[...new Set(e?.filter(Boolean))];return!n.length&&t&&n.push(t),n},[e,t]),[a,o]=h(0),{ref:s,visible:c}=n(),[l,u]=h(!0),[d,g]=h(!1),v=m(new Set),y=i.length,b=y?a%y:0;return f(()=>{let e=window.matchMedia(`(prefers-reduced-motion: reduce)`),t=()=>u(e.matches);t(),e.addEventListener(`change`,t);let n=s.current?.closest(`article`),r=()=>g(!!n?.matches(`:hover, :focus-within`)),i=e=>g(!!(n?.matches(`:hover`)||e.relatedTarget instanceof Node&&n?.contains(e.relatedTarget)));return r(),n?.addEventListener(`mouseenter`,r),n?.addEventListener(`mouseleave`,r),n?.addEventListener(`focusin`,r),n?.addEventListener(`focusout`,i),()=>{e.removeEventListener(`change`,t),n?.removeEventListener(`mouseenter`,r),n?.removeEventListener(`mouseleave`,r),n?.removeEventListener(`focusin`,r),n?.removeEventListener(`focusout`,i)}},[s]),f(()=>{if(y<2||!c||l||d)return;let e=window.setInterval(()=>{o(e=>v.current.has(i[(e+1)%y]??``)?(e+1)%y:e)},5e3);return()=>window.clearInterval(e)},[y,i,c,l,d]),_(`div`,{className:`lockerverse-auctions__catalog-images`,ref:s,children:y?[b,...y>1?[(b+1)%y]:[]].map(e=>_(`img`,{alt:e===b?r:``,"aria-hidden":e!==b,className:`lockerverse-auctions__catalog-photo`,"data-visible":e===b,height:500,loading:`lazy`,onLoad:()=>v.current.add(i[e]??``),src:i[e],width:640},i[e])):null})}function x({icon:e,label:t,value:n}){return v(`div`,{className:`lockerverse-auctions__catalog-metric`,children:[v(`dt`,{children:[e,t]}),_(`dd`,{children:n})]})}function S({auction:t,status:n=e(t),item:r=!1}){let a=``;return n===`draft`&&(a=`Opens `),n===`active`&&(a=r?`Closes `:`Ends `),v(`span`,{className:`lockerverse-auctions__catalog-timing`,children:[a,i(t,n)]})}function C(e,n){if(e.saleMode===`buy_now`){let i=r(e),a=n===`active`?`Buy now`:y[n];return{chip:i?`Sold out`:a,cta:i?`Sold out`:{active:`Buy now`,draft:`Preview item`,finished:`View item`}[n],price:t(e.buyNowPriceAmount??0),priceLabel:`Buy Now`,secondary:e.availableQuantity===null?`Available`:String(e.availableQuantity)}}return{chip:n===`active`?`Live`:y[n],cta:{active:`Bid now`,draft:`Preview item`,finished:`View item`}[n],price:n===`finished`&&!e.maxBidAmount?`No bids`:t(e.maxBidAmount??0),priceLabel:n===`finished`?`Final bid`:`Current`,secondary:t(e.minBidAmount??0)}}function w({auction:t,item:n,onSelect:r,theme:i=`dark`,className:c,style:f,showDescription:p=!0,showMetrics:m=!0,showTiming:h=!0}){o(t.startAt,t.endAt);let g=e(t,n),y=n.saleMode===`buy_now`,w=C(n,g);return _(`div`,{className:[`lockerverse-auctions`,`lockerverse-auctions--card`,c].filter(Boolean).join(` `),"data-lockerverse-theme":i,style:f,children:v(`article`,{className:`lockerverse-auctions__catalog-card`,children:[_(`button`,{"aria-label":`View ${n.name}`,className:`lockerverse-auctions__catalog-select`,onClick:r,type:`button`}),v(`div`,{className:`lockerverse-auctions__catalog-media`,children:[_(b,{fallback:n.image||t.configuration.image||t.community?.banner||t.community?.thumbnail,images:n.images,name:n.name}),v(`div`,{className:`lockerverse-auctions__catalog-chips`,children:[_(`span`,{className:`lockerverse-auctions__catalog-chip`,"data-live":g===`active`,children:w.chip}),h?_(S,{auction:n.finishedAt&&g===`finished`?{...t,endAt:n.finishedAt}:t,item:!0,status:g}):null]}),m?v(`dl`,{className:`lockerverse-auctions__catalog-metrics`,children:[_(x,{icon:_(y?d:u,{"aria-hidden":`true`,size:16}),label:w.priceLabel,value:w.price}),_(x,{icon:_(l,{"aria-hidden":`true`,size:16}),label:y?`Available`:`Floor`,value:w.secondary})]}):null]}),v(`div`,{className:`lockerverse-auctions__catalog-body`,children:[_(`h3`,{children:n.name}),p?_(a,{className:`lockerverse-auctions__catalog-description`,description:n.description||`View auction item details
|
|
1
|
+
import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./use-auction-boundary.js";import{ArrowRight as s,ChevronLeft as c,Clock3 as l,Gavel as u,ShoppingBag as d}from"lucide-react";import{useEffect as f,useMemo as p,useRef as m,useState as h}from"react";import{Fragment as g,jsx as _,jsxs as v}from"react/jsx-runtime";const y={active:`Live now`,draft:`Coming soon`,finished:`Closed`};function b({images:e,fallback:t,name:r}){let i=p(()=>{let n=[...new Set(e?.filter(Boolean))];return!n.length&&t&&n.push(t),n},[e,t]),[a,o]=h(0),{ref:s,visible:c}=n(),[l,u]=h(!0),[d,g]=h(!1),v=m(new Set),y=i.length,b=y?a%y:0;return f(()=>{let e=window.matchMedia(`(prefers-reduced-motion: reduce)`),t=()=>u(e.matches);t(),e.addEventListener(`change`,t);let n=s.current?.closest(`article`),r=()=>g(!!n?.matches(`:hover, :focus-within`)),i=e=>g(!!(n?.matches(`:hover`)||e.relatedTarget instanceof Node&&n?.contains(e.relatedTarget)));return r(),n?.addEventListener(`mouseenter`,r),n?.addEventListener(`mouseleave`,r),n?.addEventListener(`focusin`,r),n?.addEventListener(`focusout`,i),()=>{e.removeEventListener(`change`,t),n?.removeEventListener(`mouseenter`,r),n?.removeEventListener(`mouseleave`,r),n?.removeEventListener(`focusin`,r),n?.removeEventListener(`focusout`,i)}},[s]),f(()=>{if(y<2||!c||l||d)return;let e=window.setInterval(()=>{o(e=>v.current.has(i[(e+1)%y]??``)?(e+1)%y:e)},5e3);return()=>window.clearInterval(e)},[y,i,c,l,d]),_(`div`,{className:`lockerverse-auctions__catalog-images`,ref:s,children:y?[b,...y>1?[(b+1)%y]:[]].map(e=>_(`img`,{alt:e===b?r:``,"aria-hidden":e!==b,className:`lockerverse-auctions__catalog-photo`,"data-visible":e===b,height:500,loading:`lazy`,onLoad:()=>v.current.add(i[e]??``),src:i[e],width:640},i[e])):null})}function x({icon:e,label:t,value:n}){return v(`div`,{className:`lockerverse-auctions__catalog-metric`,children:[v(`dt`,{children:[e,t]}),_(`dd`,{children:n})]})}function S({auction:t,status:n=e(t),item:r=!1}){let a=``;return n===`draft`&&(a=`Opens `),n===`active`&&(a=r?`Closes `:`Ends `),v(`span`,{className:`lockerverse-auctions__catalog-timing`,children:[a,i(t,n)]})}function C(e,n){if(e.saleMode===`buy_now`){let i=r(e),a=n===`active`?`Buy now`:y[n];return{chip:i?`Sold out`:a,cta:i?`Sold out`:{active:`Buy now`,draft:`Preview item`,finished:`View item`}[n],price:t(e.buyNowPriceAmount??0),priceLabel:`Buy Now`,secondary:e.availableQuantity===null?`Available`:String(e.availableQuantity)}}return{chip:n===`active`?`Live`:y[n],cta:{active:`Bid now`,draft:`Preview item`,finished:`View item`}[n],price:n===`finished`&&!e.maxBidAmount?`No bids`:t(e.maxBidAmount??0),priceLabel:n===`finished`?`Final bid`:`Current`,secondary:t(e.minBidAmount??0)}}function w({auction:t,item:n,onSelect:r,theme:i=`dark`,className:c,style:f,showDescription:p=!0,showMetrics:m=!0,showTiming:h=!0}){o(t.startAt,t.endAt);let g=e(t,n),y=n.saleMode===`buy_now`,w=C(n,g);return _(`div`,{className:[`lockerverse-auctions`,`lockerverse-auctions--card`,c].filter(Boolean).join(` `),"data-lockerverse-theme":i,style:f,children:v(`article`,{className:`lockerverse-auctions__catalog-card`,children:[_(`button`,{"aria-label":`View ${n.name}`,className:`lockerverse-auctions__catalog-select`,onClick:r,type:`button`}),v(`div`,{className:`lockerverse-auctions__catalog-media`,children:[_(b,{fallback:n.image||t.configuration.image||t.community?.banner||t.community?.thumbnail,images:n.images,name:n.name}),v(`div`,{className:`lockerverse-auctions__catalog-chips`,children:[_(`span`,{className:`lockerverse-auctions__catalog-chip`,"data-live":g===`active`,children:w.chip}),h?_(S,{auction:n.finishedAt&&g===`finished`?{...t,endAt:n.finishedAt}:t,item:!0,status:g}):null]}),m?v(`dl`,{className:`lockerverse-auctions__catalog-metrics`,children:[_(x,{icon:_(y?d:u,{"aria-hidden":`true`,size:16}),label:w.priceLabel,value:w.price}),_(x,{icon:_(l,{"aria-hidden":`true`,size:16}),label:y?`Available`:`Floor`,value:w.secondary})]}):null]}),v(`div`,{className:`lockerverse-auctions__catalog-body`,children:[_(`h3`,{children:n.name}),p?_(a,{className:`lockerverse-auctions__catalog-description`,description:n.description||`View auction item details.`}):null,_(`div`,{className:`lockerverse-auctions__catalog-footer lockerverse-auctions__catalog-footer--item`,children:v(`span`,{className:`lockerverse-auctions__catalog-cta`,children:[w.cta,_(s,{"aria-hidden":`true`,size:16})]})})]})]})})}const T=[{label:`All`,value:`all`},{label:`Live`,value:`active`},{label:`Upcoming`,value:`draft`},{label:`Closed`,value:`finished`}];function E({auction:e,onSelectItem:t,theme:n=`dark`,style:r,className:i,showFilters:a=!0,showHeader:o=!0,showLineup:s=!0,onBack:c,renderItem:l}){return _(`section`,{"aria-label":e.name,className:[`lockerverse-auctions`,`lockerverse-auctions--catalog`,i].filter(Boolean).join(` `),"data-lockerverse-theme":n,style:r,children:_(D,{auction:e,onSelectItem:t,showFilters:a,showHeader:o,showLineup:s,theme:n,...r?{style:r}:{},...c?{onBack:c}:{},...l?{renderItem:l}:{}})})}function D({auction:t,onSelectItem:n,theme:r=`dark`,style:i,showFilters:s=!0,showHeader:l=!0,showLineup:u=!0,onBack:d,renderItem:p}){o(t.startAt,t.endAt);let[y,b]=h({auctionId:t.id,value:`all`}),x=m(null),S=m(null),C=s&&y.auctionId===t.id?y.value:`all`;f(()=>{b({auctionId:t.id,value:`all`})},[t.id,s]);let E=!!d;f(()=>{E&&(x.current??S.current)?.focus()},[t.id,E,l]);let D=i?Object.fromEntries(Object.entries(i).filter(([e])=>e.startsWith(`--lockerverse-`))):void 0,O=[...t.items].sort((e,t)=>e.position-t.position||e.createdAt.localeCompare(t.createdAt)),k=O.filter(n=>C===`all`||e(t,n)===C);return v(g,{children:[d?v(`button`,{className:`lockerverse-auctions__catalog-back`,onClick:d,ref:S,type:`button`,children:[_(c,{"aria-hidden":`true`,size:16}),`Auctions`]}):null,l?v(`header`,{className:`lockerverse-auctions__catalog-header`,children:[_(`h2`,{ref:x,tabIndex:-1,children:t.name}),t.description?_(a,{description:t.description}):null]}):null,u?v(`div`,{className:`lockerverse-auctions__catalog-lineup`,children:[v(`div`,{children:[_(`h3`,{children:`Auction lineup`}),_(`p`,{children:`Browse the current collection.`})]}),v(`span`,{children:[k.length,` `,k.length===1?`item`:`items`]})]}):null,s?_(`fieldset`,{"aria-label":`Filter auction items`,className:`lockerverse-auctions__catalog-filters`,children:T.map(n=>v(`button`,{"aria-pressed":C===n.value,onClick:()=>b({auctionId:t.id,value:n.value}),type:`button`,children:[n.label,_(`span`,{children:n.value===`all`?O.length:O.filter(r=>e(t,r)===n.value).length})]},n.value))}):null,k.length?_(`ul`,{className:`lockerverse-auctions__catalog-grid`,children:k.map(i=>{let a={auction:t,item:i,onSelect:()=>n(t,i),status:e(t,i),theme:r};return D&&(a.style=D),_(`li`,{children:p?p(a):_(w,{...a})},i.id)})}):_(`p`,{className:`lockerverse-auctions__catalog-empty`,children:`No items match this auction view.`})]})}export{x as a,b as i,E as n,y as o,w as r,S as s,D as t};
|
|
2
2
|
//# sourceMappingURL=lockerverse-auction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lockerverse-auction.js","names":["formatMoney"],"sources":["../src/auction-catalog-parts.tsx","../src/lockerverse-auction-item-card.tsx","../src/lockerverse-auction.tsx"],"sourcesContent":["import type {\n LockerverseAuction as Auction,\n LockerverseAuctionStatus,\n} from \"@lockerverse/sdk/auctions\";\nimport { type ReactNode, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n formatAuctionBoundary,\n getAuctionDisplayStatus,\n} from \"./auction-display.ts\";\nimport { useAuctionVisibility } from \"./use-auction-visibility.ts\";\nexport const STATUS_LABELS = {\n active: \"Live now\",\n draft: \"Coming soon\",\n finished: \"Closed\",\n} satisfies Record<LockerverseAuctionStatus, string>;\nexport function CatalogImage({\n images,\n fallback,\n name,\n}: {\n images?: string[];\n fallback?: string | null | undefined;\n name: string;\n}) {\n const photos = useMemo(() => {\n const unique = [...new Set(images?.filter(Boolean))];\n if (!unique.length && fallback) {\n unique.push(fallback);\n }\n return unique;\n }, [images, fallback]);\n const [index, setIndex] = useState(0);\n const { ref: imageRef, visible } = useAuctionVisibility<HTMLDivElement>();\n const [reducedMotion, setReducedMotion] = useState(true);\n const [interacting, setInteracting] = useState(false);\n const loaded = useRef(new Set<string>());\n const count = photos.length;\n const current = count ? index % count : 0;\n useEffect(() => {\n const motion = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const updateMotion = () => setReducedMotion(motion.matches);\n updateMotion();\n motion.addEventListener(\"change\", updateMotion);\n const card = imageRef.current?.closest(\"article\");\n const updateInteraction = () =>\n setInteracting(Boolean(card?.matches(\":hover, :focus-within\")));\n const leaveFocus = (event: FocusEvent) =>\n setInteracting(\n Boolean(\n card?.matches(\":hover\") ||\n (event.relatedTarget instanceof Node &&\n card?.contains(event.relatedTarget))\n )\n );\n updateInteraction();\n card?.addEventListener(\"mouseenter\", updateInteraction);\n card?.addEventListener(\"mouseleave\", updateInteraction);\n card?.addEventListener(\"focusin\", updateInteraction);\n card?.addEventListener(\"focusout\", leaveFocus);\n return () => {\n motion.removeEventListener(\"change\", updateMotion);\n card?.removeEventListener(\"mouseenter\", updateInteraction);\n card?.removeEventListener(\"mouseleave\", updateInteraction);\n card?.removeEventListener(\"focusin\", updateInteraction);\n card?.removeEventListener(\"focusout\", leaveFocus);\n };\n }, [imageRef]);\n useEffect(() => {\n if (count < 2 || !visible || reducedMotion || interacting) {\n return;\n }\n const timer = window.setInterval(() => {\n setIndex((previous) =>\n loaded.current.has(photos[(previous + 1) % count] ?? \"\")\n ? (previous + 1) % count\n : previous\n );\n }, 5000);\n return () => window.clearInterval(timer);\n }, [count, photos, visible, reducedMotion, interacting]);\n return (\n <div className=\"lockerverse-auctions__catalog-images\" ref={imageRef}>\n {count\n ? [current, ...(count > 1 ? [(current + 1) % count] : [])].map(\n (photo) => (\n <img\n alt={photo === current ? name : \"\"}\n aria-hidden={photo !== current}\n className=\"lockerverse-auctions__catalog-photo\"\n data-visible={photo === current}\n height={500}\n key={photos[photo]}\n loading=\"lazy\"\n onLoad={() => loaded.current.add(photos[photo] ?? \"\")}\n src={photos[photo]}\n width={640}\n />\n )\n )\n : null}\n </div>\n );\n}\nexport function Metric({\n icon,\n label,\n value,\n}: {\n icon: ReactNode;\n label: string;\n value: string;\n}) {\n return (\n <div className=\"lockerverse-auctions__catalog-metric\">\n <dt>\n {icon}\n {label}\n </dt>\n <dd>{value}</dd>\n </div>\n );\n}\nexport function Timing({\n auction,\n status = getAuctionDisplayStatus(auction),\n item = false,\n}: {\n auction: Auction;\n status?: LockerverseAuctionStatus;\n item?: boolean;\n}) {\n let label = \"\";\n if (status === \"draft\") {\n label = \"Opens \";\n }\n if (status === \"active\") {\n label = item ? \"Closes \" : \"Ends \";\n }\n return (\n <span className=\"lockerverse-auctions__catalog-timing\">\n {label}\n {formatAuctionBoundary(auction, status)}\n </span>\n );\n}\n","import type {\n LockerverseAuction as Auction,\n LockerverseAuctionItem as AuctionItem,\n LockerverseAuctionStatus,\n} from \"@lockerverse/sdk/auctions\";\nimport { ArrowRight, Clock3, Gavel, ShoppingBag } from \"lucide-react\";\nimport {\n CatalogImage,\n Metric,\n STATUS_LABELS,\n Timing,\n} from \"./auction-catalog-parts.tsx\";\nimport { AuctionDescription } from \"./auction-description.tsx\";\nimport {\n formatAuctionMoney as formatMoney,\n getAuctionDisplayStatus,\n isAuctionItemSoldOut,\n} from \"./auction-display.ts\";\nimport type { LockerverseStyle, LockerverseTheme } from \"./theme.ts\";\nimport { useAuctionBoundary } from \"./use-auction-boundary.ts\";\n\nexport type LockerverseAuctionItemCardProps = {\n auction: Auction;\n item: AuctionItem;\n onSelect: () => void;\n theme?: LockerverseTheme;\n /** Applied to the scoped card container. */\n className?: string;\n style?: LockerverseStyle;\n showDescription?: boolean;\n showMetrics?: boolean;\n showTiming?: boolean;\n};\nfunction itemCardDisplay(item: AuctionItem, status: LockerverseAuctionStatus) {\n if (item.saleMode === \"buy_now\") {\n const soldOut = isAuctionItemSoldOut(item);\n const availabilityLabel =\n status === \"active\" ? \"Buy now\" : STATUS_LABELS[status];\n const label = soldOut ? \"Sold out\" : availabilityLabel;\n return {\n chip: label,\n cta: soldOut\n ? \"Sold out\"\n : { active: \"Buy now\", draft: \"Preview item\", finished: \"View item\" }[\n status\n ],\n price: formatMoney(item.buyNowPriceAmount ?? 0),\n priceLabel: \"Buy Now\",\n secondary:\n item.availableQuantity === null\n ? \"Available\"\n : String(item.availableQuantity),\n };\n }\n return {\n chip: status === \"active\" ? \"Live\" : STATUS_LABELS[status],\n cta: { active: \"Bid now\", draft: \"Preview item\", finished: \"View item\" }[\n status\n ],\n price:\n status === \"finished\" && !item.maxBidAmount\n ? \"No bids\"\n : formatMoney(item.maxBidAmount ?? 0),\n priceLabel: status === \"finished\" ? \"Final bid\" : \"Current\",\n secondary: formatMoney(item.minBidAmount ?? 0),\n };\n}\nexport function LockerverseAuctionItemCard({\n auction,\n item,\n onSelect,\n theme = \"dark\",\n className,\n style,\n showDescription = true,\n showMetrics = true,\n showTiming = true,\n}: LockerverseAuctionItemCardProps) {\n useAuctionBoundary(auction.startAt, auction.endAt);\n const status = getAuctionDisplayStatus(auction, item);\n const buyNow = item.saleMode === \"buy_now\";\n const display = itemCardDisplay(item, status);\n return (\n <div\n className={[\n \"lockerverse-auctions\",\n \"lockerverse-auctions--card\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n data-lockerverse-theme={theme}\n style={style}\n >\n <article className=\"lockerverse-auctions__catalog-card\">\n <button\n aria-label={`View ${item.name}`}\n className=\"lockerverse-auctions__catalog-select\"\n onClick={onSelect}\n type=\"button\"\n />\n <div className=\"lockerverse-auctions__catalog-media\">\n <CatalogImage\n fallback={\n item.image ||\n auction.configuration.image ||\n auction.community?.banner ||\n auction.community?.thumbnail\n }\n images={item.images}\n name={item.name}\n />\n <div className=\"lockerverse-auctions__catalog-chips\">\n <span\n className=\"lockerverse-auctions__catalog-chip\"\n data-live={status === \"active\"}\n >\n {display.chip}\n </span>\n {showTiming ? (\n <Timing\n auction={\n item.finishedAt && status === \"finished\"\n ? { ...auction, endAt: item.finishedAt }\n : auction\n }\n item\n status={status}\n />\n ) : null}\n </div>\n {showMetrics ? (\n <dl className=\"lockerverse-auctions__catalog-metrics\">\n <Metric\n icon={\n buyNow ? (\n <ShoppingBag aria-hidden=\"true\" size={16} />\n ) : (\n <Gavel aria-hidden=\"true\" size={16} />\n )\n }\n label={display.priceLabel}\n value={display.price}\n />\n <Metric\n icon={<Clock3 aria-hidden=\"true\" size={16} />}\n label={buyNow ? \"Available\" : \"Floor\"}\n value={display.secondary}\n />\n </dl>\n ) : null}\n </div>\n <div className=\"lockerverse-auctions__catalog-body\">\n <h3>{item.name}</h3>\n {showDescription ? (\n <AuctionDescription\n className=\"lockerverse-auctions__catalog-description\"\n description={item.description || \"View auction item details.\"}\n links={false}\n />\n ) : null}\n <div className=\"lockerverse-auctions__catalog-footer lockerverse-auctions__catalog-footer--item\">\n <span className=\"lockerverse-auctions__catalog-cta\">\n {display.cta}\n <ArrowRight aria-hidden=\"true\" size={16} />\n </span>\n </div>\n </div>\n </article>\n </div>\n );\n}\n","import type {\n LockerverseAuction as Auction,\n LockerverseAuctionItem as AuctionItem,\n LockerverseAuctionStatus,\n} from \"@lockerverse/sdk/auctions\";\nimport { ChevronLeft } from \"lucide-react\";\nimport { type ReactNode, useEffect, useRef, useState } from \"react\";\nimport { AuctionDescription } from \"./auction-description.tsx\";\nimport { getAuctionDisplayStatus } from \"./auction-display.ts\";\nimport { LockerverseAuctionItemCard } from \"./lockerverse-auction-item-card.tsx\";\nimport type { LockerverseStyle, LockerverseTheme } from \"./theme.ts\";\nimport { useAuctionBoundary } from \"./use-auction-boundary.ts\";\n\nexport type LockerverseAuctionItemRenderContext = {\n auction: Auction;\n item: AuctionItem;\n /** Effective auction and item status, including elapsed closing dates. */\n status: LockerverseAuctionStatus;\n onSelect: () => void;\n /** Parent theme and Lockerverse CSS custom properties for default-card reuse. */\n theme: LockerverseTheme;\n style?: LockerverseStyle;\n};\nexport type LockerverseAuctionProps = {\n auction: Auction;\n onSelectItem: (auction: Auction, item: AuctionItem) => void;\n theme?: LockerverseTheme;\n style?: LockerverseStyle;\n className?: string;\n showFilters?: boolean;\n showHeader?: boolean;\n showLineup?: boolean;\n onBack?: () => void;\n /** Replace the card inside each list item. Keep onSelect connected to your item view. */\n renderItem?: (context: LockerverseAuctionItemRenderContext) => ReactNode;\n};\nconst FILTERS = [\n { label: \"All\", value: \"all\" },\n { label: \"Live\", value: \"active\" },\n { label: \"Upcoming\", value: \"draft\" },\n { label: \"Closed\", value: \"finished\" },\n] as const;\ntype ItemFilter = (typeof FILTERS)[number][\"value\"];\n\n/** Display one loaded auction. Fetching and item navigation stay with the host. */\nexport function LockerverseAuction({\n auction,\n onSelectItem,\n theme = \"dark\",\n style,\n className,\n showFilters = true,\n showHeader = true,\n showLineup = true,\n onBack,\n renderItem,\n}: LockerverseAuctionProps) {\n return (\n <section\n aria-label={auction.name}\n className={[\n \"lockerverse-auctions\",\n \"lockerverse-auctions--catalog\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n data-lockerverse-theme={theme}\n style={style}\n >\n <AuctionContent\n auction={auction}\n onSelectItem={onSelectItem}\n showFilters={showFilters}\n showHeader={showHeader}\n showLineup={showLineup}\n theme={theme}\n {...(style ? { style } : {})}\n {...(onBack ? { onBack } : {})}\n {...(renderItem ? { renderItem } : {})}\n />\n </section>\n );\n}\n\n/** Shared content without a second themed container when used in the browser. */\nexport function AuctionContent({\n auction,\n onSelectItem,\n theme = \"dark\",\n style,\n showFilters = true,\n showHeader = true,\n showLineup = true,\n onBack,\n renderItem,\n}: LockerverseAuctionProps) {\n useAuctionBoundary(auction.startAt, auction.endAt);\n const [filterState, setFilterState] = useState<{\n auctionId: string;\n value: ItemFilter;\n }>({ auctionId: auction.id, value: \"all\" });\n const headingRef = useRef<HTMLHeadingElement>(null);\n const backRef = useRef<HTMLButtonElement>(null);\n const filter =\n showFilters && filterState.auctionId === auction.id\n ? filterState.value\n : \"all\";\n useEffect(() => {\n setFilterState({ auctionId: auction.id, value: \"all\" });\n }, [auction.id, showFilters]);\n const focusHeading = Boolean(onBack);\n useEffect(() => {\n if (focusHeading) {\n (headingRef.current ?? backRef.current)?.focus();\n }\n }, [auction.id, focusHeading, showHeader]);\n const cardStyle = style\n ? Object.fromEntries(\n Object.entries(style).filter(([key]) =>\n key.startsWith(\"--lockerverse-\")\n )\n )\n : undefined;\n const items = [...auction.items].sort(\n (left, right) =>\n left.position - right.position ||\n left.createdAt.localeCompare(right.createdAt)\n );\n const filtered = items.filter(\n (item) =>\n filter === \"all\" || getAuctionDisplayStatus(auction, item) === filter\n );\n return (\n <>\n {onBack ? (\n <button\n className=\"lockerverse-auctions__catalog-back\"\n onClick={onBack}\n ref={backRef}\n type=\"button\"\n >\n <ChevronLeft aria-hidden=\"true\" size={16} />\n Auctions\n </button>\n ) : null}\n {showHeader ? (\n <header className=\"lockerverse-auctions__catalog-header\">\n <h2 ref={headingRef} tabIndex={-1}>\n {auction.name}\n </h2>\n {auction.description ? (\n <AuctionDescription description={auction.description} />\n ) : null}\n </header>\n ) : null}\n {showLineup ? (\n <div className=\"lockerverse-auctions__catalog-lineup\">\n <div>\n <h3>Auction lineup</h3>\n <p>Browse the current collection.</p>\n </div>\n <span>\n {filtered.length} {filtered.length === 1 ? \"item\" : \"items\"}\n </span>\n </div>\n ) : null}\n {showFilters ? (\n <fieldset\n aria-label=\"Filter auction items\"\n className=\"lockerverse-auctions__catalog-filters\"\n >\n {FILTERS.map((option) => (\n <button\n aria-pressed={filter === option.value}\n key={option.value}\n onClick={() =>\n setFilterState({ auctionId: auction.id, value: option.value })\n }\n type=\"button\"\n >\n {option.label}\n <span>\n {option.value === \"all\"\n ? items.length\n : items.filter(\n (item) =>\n getAuctionDisplayStatus(auction, item) === option.value\n ).length}\n </span>\n </button>\n ))}\n </fieldset>\n ) : null}\n {filtered.length ? (\n <ul className=\"lockerverse-auctions__catalog-grid\">\n {filtered.map((item) => {\n const context: LockerverseAuctionItemRenderContext = {\n auction,\n item,\n onSelect: () => onSelectItem(auction, item),\n status: getAuctionDisplayStatus(auction, item),\n theme,\n };\n if (cardStyle) {\n context.style = cardStyle;\n }\n return (\n <li key={item.id}>\n {renderItem ? (\n renderItem(context)\n ) : (\n <LockerverseAuctionItemCard {...context} />\n )}\n </li>\n );\n })}\n </ul>\n ) : (\n <p className=\"lockerverse-auctions__catalog-empty\">\n No items match this auction view.\n </p>\n )}\n </>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lockerverse-auction.js","names":["formatMoney"],"sources":["../src/auction-catalog-parts.tsx","../src/lockerverse-auction-item-card.tsx","../src/lockerverse-auction.tsx"],"sourcesContent":["import type {\n LockerverseAuction as Auction,\n LockerverseAuctionStatus,\n} from \"@lockerverse/sdk/auctions\";\nimport { type ReactNode, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n formatAuctionBoundary,\n getAuctionDisplayStatus,\n} from \"./auction-display.ts\";\nimport { useAuctionVisibility } from \"./use-auction-visibility.ts\";\nexport const STATUS_LABELS = {\n active: \"Live now\",\n draft: \"Coming soon\",\n finished: \"Closed\",\n} satisfies Record<LockerverseAuctionStatus, string>;\nexport function CatalogImage({\n images,\n fallback,\n name,\n}: {\n images?: string[];\n fallback?: string | null | undefined;\n name: string;\n}) {\n const photos = useMemo(() => {\n const unique = [...new Set(images?.filter(Boolean))];\n if (!unique.length && fallback) {\n unique.push(fallback);\n }\n return unique;\n }, [images, fallback]);\n const [index, setIndex] = useState(0);\n const { ref: imageRef, visible } = useAuctionVisibility<HTMLDivElement>();\n const [reducedMotion, setReducedMotion] = useState(true);\n const [interacting, setInteracting] = useState(false);\n const loaded = useRef(new Set<string>());\n const count = photos.length;\n const current = count ? index % count : 0;\n useEffect(() => {\n const motion = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const updateMotion = () => setReducedMotion(motion.matches);\n updateMotion();\n motion.addEventListener(\"change\", updateMotion);\n const card = imageRef.current?.closest(\"article\");\n const updateInteraction = () =>\n setInteracting(Boolean(card?.matches(\":hover, :focus-within\")));\n const leaveFocus = (event: FocusEvent) =>\n setInteracting(\n Boolean(\n card?.matches(\":hover\") ||\n (event.relatedTarget instanceof Node &&\n card?.contains(event.relatedTarget))\n )\n );\n updateInteraction();\n card?.addEventListener(\"mouseenter\", updateInteraction);\n card?.addEventListener(\"mouseleave\", updateInteraction);\n card?.addEventListener(\"focusin\", updateInteraction);\n card?.addEventListener(\"focusout\", leaveFocus);\n return () => {\n motion.removeEventListener(\"change\", updateMotion);\n card?.removeEventListener(\"mouseenter\", updateInteraction);\n card?.removeEventListener(\"mouseleave\", updateInteraction);\n card?.removeEventListener(\"focusin\", updateInteraction);\n card?.removeEventListener(\"focusout\", leaveFocus);\n };\n }, [imageRef]);\n useEffect(() => {\n if (count < 2 || !visible || reducedMotion || interacting) {\n return;\n }\n const timer = window.setInterval(() => {\n setIndex((previous) =>\n loaded.current.has(photos[(previous + 1) % count] ?? \"\")\n ? (previous + 1) % count\n : previous\n );\n }, 5000);\n return () => window.clearInterval(timer);\n }, [count, photos, visible, reducedMotion, interacting]);\n return (\n <div className=\"lockerverse-auctions__catalog-images\" ref={imageRef}>\n {count\n ? [current, ...(count > 1 ? [(current + 1) % count] : [])].map(\n (photo) => (\n <img\n alt={photo === current ? name : \"\"}\n aria-hidden={photo !== current}\n className=\"lockerverse-auctions__catalog-photo\"\n data-visible={photo === current}\n height={500}\n key={photos[photo]}\n loading=\"lazy\"\n onLoad={() => loaded.current.add(photos[photo] ?? \"\")}\n src={photos[photo]}\n width={640}\n />\n )\n )\n : null}\n </div>\n );\n}\nexport function Metric({\n icon,\n label,\n value,\n}: {\n icon: ReactNode;\n label: string;\n value: string;\n}) {\n return (\n <div className=\"lockerverse-auctions__catalog-metric\">\n <dt>\n {icon}\n {label}\n </dt>\n <dd>{value}</dd>\n </div>\n );\n}\nexport function Timing({\n auction,\n status = getAuctionDisplayStatus(auction),\n item = false,\n}: {\n auction: Auction;\n status?: LockerverseAuctionStatus;\n item?: boolean;\n}) {\n let label = \"\";\n if (status === \"draft\") {\n label = \"Opens \";\n }\n if (status === \"active\") {\n label = item ? \"Closes \" : \"Ends \";\n }\n return (\n <span className=\"lockerverse-auctions__catalog-timing\">\n {label}\n {formatAuctionBoundary(auction, status)}\n </span>\n );\n}\n","import type {\n LockerverseAuction as Auction,\n LockerverseAuctionItem as AuctionItem,\n LockerverseAuctionStatus,\n} from \"@lockerverse/sdk/auctions\";\nimport { ArrowRight, Clock3, Gavel, ShoppingBag } from \"lucide-react\";\nimport {\n CatalogImage,\n Metric,\n STATUS_LABELS,\n Timing,\n} from \"./auction-catalog-parts.tsx\";\nimport { AuctionDescription } from \"./auction-description.tsx\";\nimport {\n formatAuctionMoney as formatMoney,\n getAuctionDisplayStatus,\n isAuctionItemSoldOut,\n} from \"./auction-display.ts\";\nimport type { LockerverseStyle, LockerverseTheme } from \"./theme.ts\";\nimport { useAuctionBoundary } from \"./use-auction-boundary.ts\";\n\nexport type LockerverseAuctionItemCardProps = {\n auction: Auction;\n item: AuctionItem;\n onSelect: () => void;\n theme?: LockerverseTheme;\n /** Applied to the scoped card container. */\n className?: string;\n style?: LockerverseStyle;\n showDescription?: boolean;\n showMetrics?: boolean;\n showTiming?: boolean;\n};\nfunction itemCardDisplay(item: AuctionItem, status: LockerverseAuctionStatus) {\n if (item.saleMode === \"buy_now\") {\n const soldOut = isAuctionItemSoldOut(item);\n const availabilityLabel =\n status === \"active\" ? \"Buy now\" : STATUS_LABELS[status];\n const label = soldOut ? \"Sold out\" : availabilityLabel;\n return {\n chip: label,\n cta: soldOut\n ? \"Sold out\"\n : { active: \"Buy now\", draft: \"Preview item\", finished: \"View item\" }[\n status\n ],\n price: formatMoney(item.buyNowPriceAmount ?? 0),\n priceLabel: \"Buy Now\",\n secondary:\n item.availableQuantity === null\n ? \"Available\"\n : String(item.availableQuantity),\n };\n }\n return {\n chip: status === \"active\" ? \"Live\" : STATUS_LABELS[status],\n cta: { active: \"Bid now\", draft: \"Preview item\", finished: \"View item\" }[\n status\n ],\n price:\n status === \"finished\" && !item.maxBidAmount\n ? \"No bids\"\n : formatMoney(item.maxBidAmount ?? 0),\n priceLabel: status === \"finished\" ? \"Final bid\" : \"Current\",\n secondary: formatMoney(item.minBidAmount ?? 0),\n };\n}\nexport function LockerverseAuctionItemCard({\n auction,\n item,\n onSelect,\n theme = \"dark\",\n className,\n style,\n showDescription = true,\n showMetrics = true,\n showTiming = true,\n}: LockerverseAuctionItemCardProps) {\n useAuctionBoundary(auction.startAt, auction.endAt);\n const status = getAuctionDisplayStatus(auction, item);\n const buyNow = item.saleMode === \"buy_now\";\n const display = itemCardDisplay(item, status);\n return (\n <div\n className={[\n \"lockerverse-auctions\",\n \"lockerverse-auctions--card\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n data-lockerverse-theme={theme}\n style={style}\n >\n <article className=\"lockerverse-auctions__catalog-card\">\n <button\n aria-label={`View ${item.name}`}\n className=\"lockerverse-auctions__catalog-select\"\n onClick={onSelect}\n type=\"button\"\n />\n <div className=\"lockerverse-auctions__catalog-media\">\n <CatalogImage\n fallback={\n item.image ||\n auction.configuration.image ||\n auction.community?.banner ||\n auction.community?.thumbnail\n }\n images={item.images}\n name={item.name}\n />\n <div className=\"lockerverse-auctions__catalog-chips\">\n <span\n className=\"lockerverse-auctions__catalog-chip\"\n data-live={status === \"active\"}\n >\n {display.chip}\n </span>\n {showTiming ? (\n <Timing\n auction={\n item.finishedAt && status === \"finished\"\n ? { ...auction, endAt: item.finishedAt }\n : auction\n }\n item\n status={status}\n />\n ) : null}\n </div>\n {showMetrics ? (\n <dl className=\"lockerverse-auctions__catalog-metrics\">\n <Metric\n icon={\n buyNow ? (\n <ShoppingBag aria-hidden=\"true\" size={16} />\n ) : (\n <Gavel aria-hidden=\"true\" size={16} />\n )\n }\n label={display.priceLabel}\n value={display.price}\n />\n <Metric\n icon={<Clock3 aria-hidden=\"true\" size={16} />}\n label={buyNow ? \"Available\" : \"Floor\"}\n value={display.secondary}\n />\n </dl>\n ) : null}\n </div>\n <div className=\"lockerverse-auctions__catalog-body\">\n <h3>{item.name}</h3>\n {showDescription ? (\n <AuctionDescription\n className=\"lockerverse-auctions__catalog-description\"\n description={item.description || \"View auction item details.\"}\n />\n ) : null}\n <div className=\"lockerverse-auctions__catalog-footer lockerverse-auctions__catalog-footer--item\">\n <span className=\"lockerverse-auctions__catalog-cta\">\n {display.cta}\n <ArrowRight aria-hidden=\"true\" size={16} />\n </span>\n </div>\n </div>\n </article>\n </div>\n );\n}\n","import type {\n LockerverseAuction as Auction,\n LockerverseAuctionItem as AuctionItem,\n LockerverseAuctionStatus,\n} from \"@lockerverse/sdk/auctions\";\nimport { ChevronLeft } from \"lucide-react\";\nimport { type ReactNode, useEffect, useRef, useState } from \"react\";\nimport { AuctionDescription } from \"./auction-description.tsx\";\nimport { getAuctionDisplayStatus } from \"./auction-display.ts\";\nimport { LockerverseAuctionItemCard } from \"./lockerverse-auction-item-card.tsx\";\nimport type { LockerverseStyle, LockerverseTheme } from \"./theme.ts\";\nimport { useAuctionBoundary } from \"./use-auction-boundary.ts\";\n\nexport type LockerverseAuctionItemRenderContext = {\n auction: Auction;\n item: AuctionItem;\n /** Effective auction and item status, including elapsed closing dates. */\n status: LockerverseAuctionStatus;\n onSelect: () => void;\n /** Parent theme and Lockerverse CSS custom properties for default-card reuse. */\n theme: LockerverseTheme;\n style?: LockerverseStyle;\n};\nexport type LockerverseAuctionProps = {\n auction: Auction;\n onSelectItem: (auction: Auction, item: AuctionItem) => void;\n theme?: LockerverseTheme;\n style?: LockerverseStyle;\n className?: string;\n showFilters?: boolean;\n showHeader?: boolean;\n showLineup?: boolean;\n onBack?: () => void;\n /** Replace the card inside each list item. Keep onSelect connected to your item view. */\n renderItem?: (context: LockerverseAuctionItemRenderContext) => ReactNode;\n};\nconst FILTERS = [\n { label: \"All\", value: \"all\" },\n { label: \"Live\", value: \"active\" },\n { label: \"Upcoming\", value: \"draft\" },\n { label: \"Closed\", value: \"finished\" },\n] as const;\ntype ItemFilter = (typeof FILTERS)[number][\"value\"];\n\n/** Display one loaded auction. Fetching and item navigation stay with the host. */\nexport function LockerverseAuction({\n auction,\n onSelectItem,\n theme = \"dark\",\n style,\n className,\n showFilters = true,\n showHeader = true,\n showLineup = true,\n onBack,\n renderItem,\n}: LockerverseAuctionProps) {\n return (\n <section\n aria-label={auction.name}\n className={[\n \"lockerverse-auctions\",\n \"lockerverse-auctions--catalog\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n data-lockerverse-theme={theme}\n style={style}\n >\n <AuctionContent\n auction={auction}\n onSelectItem={onSelectItem}\n showFilters={showFilters}\n showHeader={showHeader}\n showLineup={showLineup}\n theme={theme}\n {...(style ? { style } : {})}\n {...(onBack ? { onBack } : {})}\n {...(renderItem ? { renderItem } : {})}\n />\n </section>\n );\n}\n\n/** Shared content without a second themed container when used in the browser. */\nexport function AuctionContent({\n auction,\n onSelectItem,\n theme = \"dark\",\n style,\n showFilters = true,\n showHeader = true,\n showLineup = true,\n onBack,\n renderItem,\n}: LockerverseAuctionProps) {\n useAuctionBoundary(auction.startAt, auction.endAt);\n const [filterState, setFilterState] = useState<{\n auctionId: string;\n value: ItemFilter;\n }>({ auctionId: auction.id, value: \"all\" });\n const headingRef = useRef<HTMLHeadingElement>(null);\n const backRef = useRef<HTMLButtonElement>(null);\n const filter =\n showFilters && filterState.auctionId === auction.id\n ? filterState.value\n : \"all\";\n useEffect(() => {\n setFilterState({ auctionId: auction.id, value: \"all\" });\n }, [auction.id, showFilters]);\n const focusHeading = Boolean(onBack);\n useEffect(() => {\n if (focusHeading) {\n (headingRef.current ?? backRef.current)?.focus();\n }\n }, [auction.id, focusHeading, showHeader]);\n const cardStyle = style\n ? Object.fromEntries(\n Object.entries(style).filter(([key]) =>\n key.startsWith(\"--lockerverse-\")\n )\n )\n : undefined;\n const items = [...auction.items].sort(\n (left, right) =>\n left.position - right.position ||\n left.createdAt.localeCompare(right.createdAt)\n );\n const filtered = items.filter(\n (item) =>\n filter === \"all\" || getAuctionDisplayStatus(auction, item) === filter\n );\n return (\n <>\n {onBack ? (\n <button\n className=\"lockerverse-auctions__catalog-back\"\n onClick={onBack}\n ref={backRef}\n type=\"button\"\n >\n <ChevronLeft aria-hidden=\"true\" size={16} />\n Auctions\n </button>\n ) : null}\n {showHeader ? (\n <header className=\"lockerverse-auctions__catalog-header\">\n <h2 ref={headingRef} tabIndex={-1}>\n {auction.name}\n </h2>\n {auction.description ? (\n <AuctionDescription description={auction.description} />\n ) : null}\n </header>\n ) : null}\n {showLineup ? (\n <div className=\"lockerverse-auctions__catalog-lineup\">\n <div>\n <h3>Auction lineup</h3>\n <p>Browse the current collection.</p>\n </div>\n <span>\n {filtered.length} {filtered.length === 1 ? \"item\" : \"items\"}\n </span>\n </div>\n ) : null}\n {showFilters ? (\n <fieldset\n aria-label=\"Filter auction items\"\n className=\"lockerverse-auctions__catalog-filters\"\n >\n {FILTERS.map((option) => (\n <button\n aria-pressed={filter === option.value}\n key={option.value}\n onClick={() =>\n setFilterState({ auctionId: auction.id, value: option.value })\n }\n type=\"button\"\n >\n {option.label}\n <span>\n {option.value === \"all\"\n ? items.length\n : items.filter(\n (item) =>\n getAuctionDisplayStatus(auction, item) === option.value\n ).length}\n </span>\n </button>\n ))}\n </fieldset>\n ) : null}\n {filtered.length ? (\n <ul className=\"lockerverse-auctions__catalog-grid\">\n {filtered.map((item) => {\n const context: LockerverseAuctionItemRenderContext = {\n auction,\n item,\n onSelect: () => onSelectItem(auction, item),\n status: getAuctionDisplayStatus(auction, item),\n theme,\n };\n if (cardStyle) {\n context.style = cardStyle;\n }\n return (\n <li key={item.id}>\n {renderItem ? (\n renderItem(context)\n ) : (\n <LockerverseAuctionItemCard {...context} />\n )}\n </li>\n );\n })}\n </ul>\n ) : (\n <p className=\"lockerverse-auctions__catalog-empty\">\n No items match this auction view.\n </p>\n )}\n </>\n );\n}\n"],"mappings":"+TAUA,MAAa,EAAgB,CAC3B,OAAQ,WACR,MAAO,cACP,SAAU,QACZ,EACA,SAAgB,EAAa,CAC3B,SACA,WACA,QAKC,CACD,IAAM,EAAS,MAAc,CAC3B,IAAM,EAAS,CAAC,GAAG,IAAI,IAAI,GAAQ,OAAO,OAAO,CAAC,CAAC,EAInD,MAHI,CAAC,EAAO,QAAU,GACpB,EAAO,KAAK,CAAQ,EAEf,CACT,EAAG,CAAC,EAAQ,CAAQ,CAAC,EACf,CAAC,EAAO,GAAY,EAAS,CAAC,EAC9B,CAAE,IAAK,EAAU,WAAY,EAAqC,EAClE,CAAC,EAAe,GAAoB,EAAS,EAAI,EACjD,CAAC,EAAa,GAAkB,EAAS,EAAK,EAC9C,EAAS,EAAO,IAAI,GAAa,EACjC,EAAQ,EAAO,OACf,EAAU,EAAQ,EAAQ,EAAQ,EA2CxC,OA1CA,MAAgB,CACd,IAAM,EAAS,OAAO,WAAW,kCAAkC,EAC7D,MAAqB,EAAiB,EAAO,OAAO,EAC1D,EAAa,EACb,EAAO,iBAAiB,SAAU,CAAY,EAC9C,IAAM,EAAO,EAAS,SAAS,QAAQ,SAAS,EAC1C,MACJ,EAAe,EAAQ,GAAM,QAAQ,uBAAuB,CAAE,EAC1D,EAAc,GAClB,EACE,GACE,GAAM,QAAQ,QAAQ,GACnB,EAAM,yBAAyB,MAC9B,GAAM,SAAS,EAAM,aAAa,EAE1C,EAMF,OALA,EAAkB,EAClB,GAAM,iBAAiB,aAAc,CAAiB,EACtD,GAAM,iBAAiB,aAAc,CAAiB,EACtD,GAAM,iBAAiB,UAAW,CAAiB,EACnD,GAAM,iBAAiB,WAAY,CAAU,MAChC,CACX,EAAO,oBAAoB,SAAU,CAAY,EACjD,GAAM,oBAAoB,aAAc,CAAiB,EACzD,GAAM,oBAAoB,aAAc,CAAiB,EACzD,GAAM,oBAAoB,UAAW,CAAiB,EACtD,GAAM,oBAAoB,WAAY,CAAU,CAClD,CACF,EAAG,CAAC,CAAQ,CAAC,EACb,MAAgB,CACd,GAAI,EAAQ,GAAK,CAAC,GAAW,GAAiB,EAC5C,OAEF,IAAM,EAAQ,OAAO,gBAAkB,CACrC,EAAU,GACR,EAAO,QAAQ,IAAI,GAAQ,EAAW,GAAK,IAAU,EAAE,GAClD,EAAW,GAAK,EACjB,CACN,CACF,EAAG,GAAI,EACP,UAAa,OAAO,cAAc,CAAK,CACzC,EAAG,CAAC,EAAO,EAAQ,EAAS,EAAe,CAAW,CAAC,EAErD,EAAC,MAAD,CAAK,UAAU,uCAAuC,IAAK,EACxD,SAAA,EACG,CAAC,EAAS,GAAI,EAAQ,EAAI,EAAE,EAAU,GAAK,CAAK,EAAI,CAAC,CAAE,CAAC,CAAC,IACtD,GACC,EAAC,MAAD,CACE,IAAK,IAAU,EAAU,EAAO,GAChC,cAAa,IAAU,EACvB,UAAU,sCACV,eAAc,IAAU,EACxB,OAAQ,IAER,QAAQ,OACR,WAAc,EAAO,QAAQ,IAAI,EAAO,IAAU,EAAE,EACpD,IAAK,EAAO,GACZ,MAAO,GACR,EALM,EAAO,EAKb,CAEL,EACA,IACD,CAAA,CAET,CACA,SAAgB,EAAO,CACrB,OACA,QACA,SAKC,CACD,OACE,EAAC,MAAD,CAAK,UAAU,uCAAf,SAAA,CACE,EAAC,KAAD,CAAA,SAAA,CACG,EACA,CACC,CAAA,CAAA,EACJ,EAAC,KAAD,CAAA,SAAK,CAAU,CAAA,CACZ,GAET,CACA,SAAgB,EAAO,CACrB,UACA,SAAS,EAAwB,CAAO,EACxC,OAAO,IAKN,CACD,IAAI,EAAQ,GAOZ,OANI,IAAW,UACb,EAAQ,UAEN,IAAW,WACb,EAAQ,EAAO,UAAY,SAG3B,EAAC,OAAD,CAAM,UAAU,uCAAhB,SAAA,CACG,EACA,EAAsB,EAAS,CAAM,CAClC,GAEV,CC/GA,SAAS,EAAgB,EAAmB,EAAkC,CAC5E,GAAI,EAAK,WAAa,UAAW,CAC/B,IAAM,EAAU,EAAqB,CAAI,EACnC,EACJ,IAAW,SAAW,UAAY,EAAc,GAElD,MAAO,CACL,KAFY,EAAU,WAAa,EAGnC,IAAK,EACD,WACA,CAAE,OAAQ,UAAW,MAAO,eAAgB,SAAU,WAAY,EAChE,GAEN,MAAOA,EAAY,EAAK,mBAAqB,CAAC,EAC9C,WAAY,UACZ,UACE,EAAK,oBAAsB,KACvB,YACA,OAAO,EAAK,iBAAiB,CACrC,CACF,CACA,MAAO,CACL,KAAM,IAAW,SAAW,OAAS,EAAc,GACnD,IAAK,CAAE,OAAQ,UAAW,MAAO,eAAgB,SAAU,WAAY,EACrE,GAEF,MACE,IAAW,YAAc,CAAC,EAAK,aAC3B,UACAA,EAAY,EAAK,cAAgB,CAAC,EACxC,WAAY,IAAW,WAAa,YAAc,UAClD,UAAWA,EAAY,EAAK,cAAgB,CAAC,CAC/C,CACF,CACA,SAAgB,EAA2B,CACzC,UACA,OACA,WACA,QAAQ,OACR,YACA,QACA,kBAAkB,GAClB,cAAc,GACd,aAAa,IACqB,CAClC,EAAmB,EAAQ,QAAS,EAAQ,KAAK,EACjD,IAAM,EAAS,EAAwB,EAAS,CAAI,EAC9C,EAAS,EAAK,WAAa,UAC3B,EAAU,EAAgB,EAAM,CAAM,EAC5C,OACE,EAAC,MAAD,CACE,UAAW,CACT,uBACA,6BACA,CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,yBAAwB,EACjB,QAEP,SAAA,EAAC,UAAD,CAAS,UAAU,qCAAnB,SAAA,CACE,EAAC,SAAD,CACE,aAAY,QAAQ,EAAK,OACzB,UAAU,uCACV,QAAS,EACT,KAAK,QACN,CAAA,EACD,EAAC,MAAD,CAAK,UAAU,sCAAf,SAAA,CACE,EAAC,EAAD,CACE,SACE,EAAK,OACL,EAAQ,cAAc,OACtB,EAAQ,WAAW,QACnB,EAAQ,WAAW,UAErB,OAAQ,EAAK,OACb,KAAM,EAAK,IACZ,CAAA,EACD,EAAC,MAAD,CAAK,UAAU,sCAAf,SAAA,CACE,EAAC,OAAD,CACE,UAAU,qCACV,YAAW,IAAW,SAErB,SAAA,EAAQ,IACL,CAAA,EACL,EACC,EAAC,EAAD,CACE,QACE,EAAK,YAAc,IAAW,WAC1B,CAAE,GAAG,EAAS,MAAO,EAAK,UAAW,EACrC,EAEN,KAAA,GACQ,QACT,CAAA,EACC,IACD,IACJ,EACC,EAAC,KAAD,CAAI,UAAU,wCAAd,SAAA,CACE,EAAC,EAAD,CACE,KAEI,EADF,EACG,EAEA,EAFD,CAAa,cAAY,OAAO,KAAM,EAAK,CAEN,EAGzC,MAAO,EAAQ,WACf,MAAO,EAAQ,KAChB,CAAA,EACD,EAAC,EAAD,CACE,KAAM,EAAC,EAAD,CAAQ,cAAY,OAAO,KAAM,EAAK,CAAA,EAC5C,MAAO,EAAS,YAAc,QAC9B,MAAO,EAAQ,SAChB,CAAA,CACC,CACF,CAAA,EAAA,IACD,IACL,EAAC,MAAD,CAAK,UAAU,qCAAf,SAAA,CACE,EAAC,KAAD,CAAA,SAAK,EAAK,IAAS,CAAA,EAClB,EACC,EAAC,EAAD,CACE,UAAU,4CACV,YAAa,EAAK,aAAe,4BAClC,CAAA,EACC,KACJ,EAAC,MAAD,CAAK,UAAU,kFACb,SAAA,EAAC,OAAD,CAAM,UAAU,oCAAhB,SAAA,CACG,EAAQ,IACT,EAAC,EAAD,CAAY,cAAY,OAAO,KAAM,EAAK,CAAA,CACtC,GACH,CAAA,CACF,GACE,GACN,CAAA,CAET,CCtIA,MAAM,EAAU,CACd,CAAE,MAAO,MAAO,MAAO,KAAM,EAC7B,CAAE,MAAO,OAAQ,MAAO,QAAS,EACjC,CAAE,MAAO,WAAY,MAAO,OAAQ,EACpC,CAAE,MAAO,SAAU,MAAO,UAAW,CACvC,EAIA,SAAgB,EAAmB,CACjC,UACA,eACA,QAAQ,OACR,QACA,YACA,cAAc,GACd,aAAa,GACb,aAAa,GACb,SACA,cAC0B,CAC1B,OACE,EAAC,UAAD,CACE,aAAY,EAAQ,KACpB,UAAW,CACT,uBACA,gCACA,CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,yBAAwB,EACjB,QAEP,SAAA,EAAC,EAAD,CACW,UACK,eACD,cACD,aACA,aACL,QACP,GAAK,EAAQ,CAAE,OAAM,EAAI,CAAC,EAC1B,GAAK,EAAS,CAAE,QAAO,EAAI,CAAC,EAC5B,GAAK,EAAa,CAAE,YAAW,EAAI,CAAC,CACrC,CAAA,CACM,CAAA,CAEb,CAGA,SAAgB,EAAe,CAC7B,UACA,eACA,QAAQ,OACR,QACA,cAAc,GACd,aAAa,GACb,aAAa,GACb,SACA,cAC0B,CAC1B,EAAmB,EAAQ,QAAS,EAAQ,KAAK,EACjD,GAAM,CAAC,EAAa,GAAkB,EAGnC,CAAE,UAAW,EAAQ,GAAI,MAAO,KAAM,CAAC,EACpC,EAAa,EAA2B,IAAI,EAC5C,EAAU,EAA0B,IAAI,EACxC,EACJ,GAAe,EAAY,YAAc,EAAQ,GAC7C,EAAY,MACZ,MACN,MAAgB,CACd,EAAe,CAAE,UAAW,EAAQ,GAAI,MAAO,KAAM,CAAC,CACxD,EAAG,CAAC,EAAQ,GAAI,CAAW,CAAC,EAC5B,IAAM,EAAe,EAAQ,EAC7B,MAAgB,CACV,IACD,EAAW,SAAW,EAAQ,QAAA,EAAU,MAAM,CAEnD,EAAG,CAAC,EAAQ,GAAI,EAAc,CAAU,CAAC,EACzC,IAAM,EAAY,EACd,OAAO,YACL,OAAO,QAAQ,CAAK,CAAC,CAAC,QAAQ,CAAC,KAC7B,EAAI,WAAW,gBAAgB,CACjC,CACF,EACA,IAAA,GACE,EAAQ,CAAC,GAAG,EAAQ,KAAK,CAAC,CAAC,MAC9B,EAAM,IACL,EAAK,SAAW,EAAM,UACtB,EAAK,UAAU,cAAc,EAAM,SAAS,CAChD,EACM,EAAW,EAAM,OACpB,GACC,IAAW,OAAS,EAAwB,EAAS,CAAI,IAAM,CACnE,EACA,OACE,EAAA,EAAA,CAAA,SAAA,CACG,EACC,EAAC,SAAD,CACE,UAAU,qCACV,QAAS,EACT,IAAK,EACL,KAAK,SAJP,SAAA,CAME,EAAC,EAAD,CAAa,cAAY,OAAO,KAAM,EAAK,CAAA,EAAC,UAEtC,CACN,CAAA,EAAA,KACH,EACC,EAAC,SAAD,CAAQ,UAAU,uCAAlB,SAAA,CACE,EAAC,KAAD,CAAI,IAAK,EAAY,SAAU,GAC5B,SAAA,EAAQ,IACP,CAAA,EACH,EAAQ,YACP,EAAC,EAAD,CAAoB,YAAa,EAAQ,WAAc,CAAA,EACrD,IACE,CACN,CAAA,EAAA,KACH,EACC,EAAC,MAAD,CAAK,UAAU,uCAAf,SAAA,CACE,EAAC,MAAD,CAAA,SAAA,CACE,EAAC,KAAD,CAAA,SAAI,gBAAkB,CAAA,EACtB,EAAC,IAAD,CAAA,SAAG,gCAAiC,CAAA,CACjC,CAAA,CAAA,EACL,EAAC,OAAD,CAAA,SAAA,CACG,EAAS,OAAO,IAAE,EAAS,SAAW,EAAI,OAAS,OAChD,CAAA,CAAA,CACH,CACH,CAAA,EAAA,KACH,EACC,EAAC,WAAD,CACE,aAAW,uBACX,UAAU,wCAET,SAAA,EAAQ,IAAK,GACZ,EAAC,SAAD,CACE,eAAc,IAAW,EAAO,MAEhC,YACE,EAAe,CAAE,UAAW,EAAQ,GAAI,MAAO,EAAO,KAAM,CAAC,EAE/D,KAAK,SANP,SAAA,CAQG,EAAO,MACR,EAAC,OAAD,CAAA,SACG,EAAO,QAAU,MACd,EAAM,OACN,EAAM,OACH,GACC,EAAwB,EAAS,CAAI,IAAM,EAAO,KACtD,CAAC,CAAC,MACF,CAAA,CACA,CAfD,EAAA,EAAO,KAeN,CACT,CACO,CAAA,EACR,KACH,EAAS,OACR,EAAC,KAAD,CAAI,UAAU,qCACX,SAAA,EAAS,IAAK,GAAS,CACtB,IAAM,EAA+C,CACnD,UACA,OACA,aAAgB,EAAa,EAAS,CAAI,EAC1C,OAAQ,EAAwB,EAAS,CAAI,EAC7C,OACF,EAIA,OAHI,IACF,EAAQ,MAAQ,GAGhB,EAAC,KAAD,CAAA,SACG,EACC,EAAW,CAAO,EAElB,EAAC,EAAD,CAA4B,GAAI,CAAU,CAAA,CAE1C,EANK,EAAK,EAMV,CAER,CAAC,CACC,CAAA,EAEJ,EAAC,IAAD,CAAG,UAAU,sCAAsC,SAAA,mCAEhD,CAAA,CAEL,CAAA,CAAA,CAEN"}
|