class MarketGrid extends Shadow { listings; constructor(listings) { super() this.listings = listings } boldUntilFirstSpace(text) { if(!text) return const index = text.indexOf(' '); if (index === -1) { // No spaces — bold the whole thing return `${text}`; } return `${text.slice(0, index)}${text.slice(index)}`; } render() { VStack(() => { h3("Results") .marginTop(0.1, em) .marginBottom(1, em) .marginLeft(0.4, em) .color("var(--accent)") .opacity(0.7) if (this.listings.length > 0) { ZStack(() => { // BuyModal() for (let i = 0; i < this.listings.length; i++) { const rating = this.listings[i].stars const percent = (rating / 5) VStack(() => { img(this.listings[i].image) .marginBottom(0.5, em) p(this.listings[i].company) .marginBottom(0.5, em) p(this.listings[i].title) .fontSize(1.2, em) .fontWeight("bold") .marginBottom(0.5, em) HStack(() => { p(this.listings[i].stars) .marginRight(0.2, em) ZStack(() => { div("★★★★★") // Empty stars (background) .color("#ccc") div("★★★★★") // Filled stars (foreground, clipped by width) .color("#ffa500") .position("absolute") .top(0) .left(0) .whiteSpace("nowrap") .overflow("hidden") .width(percent * 5, em) }) .display("inline-block") .position("relative") .fontSize(1.2, em) .lineHeight(1) p(this.listings[i].reviews) .marginLeft(0.2, em) }) .marginBottom(0.5, em) p(this.listings[i].price) .fontSize(1.75, em) .marginBottom(0.5, em) button("Buy Now") .onClick((finished) => { if(finished) { } }) }) .padding(1, em) .border("1px solid var(--accent2)") .borderRadius(5, "px") } }) .display("grid") .gridTemplateColumns("repeat(auto-fill, minmax(250px, 1fr))") .gap(1, em) } else { p("No Listings!") } }) .height(100, vh) .paddingLeft(2, em) .paddingRight(2, em) .gap(0, em) .width(100, "%") } } register(MarketGrid)