@shopflowateam/ui 1.0.0
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 +106 -0
- package/package.json +58 -0
- package/pkg/favicon.svg +1 -0
- package/pkg/index.cjs.js +362 -0
- package/pkg/index.es.js +362 -0
- package/pkg/manifest.json +9 -0
- package/pkg/robots.txt +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# ShopFlow Storefront
|
|
2
|
+
|
|
3
|
+
A production-grade, ultra-high-performance e-commerce storefront built with **Qwik.js**, **Qwik City**, and **Tailwind CSS v4**. This project is engineered for **Zero Hydration**, achieving near-instant interactivity by leveraging Qwik's unique Resumability architecture.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The Resumability Test
|
|
8
|
+
|
|
9
|
+
Unlike traditional frameworks (React/Next.js) that require Hydration, ShopFlow serializes its state into the HTML. The browser downloads **zero** component logic until the moment of interaction.
|
|
10
|
+
|
|
11
|
+
### 1. Initial Page Load (Before Interaction)
|
|
12
|
+
**Result**:
|
|
13
|
+
![Initial Load Network Tab] 
|
|
14
|
+
|
|
15
|
+
### 2. After First Interaction (Clicking "Add to Bag")
|
|
16
|
+
**Result**:
|
|
17
|
+
![Post Interaction Network Tab]
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Key Features
|
|
22
|
+
|
|
23
|
+
- **Full E-commerce Flow**: Advanced product grids, variant management, and persistent cart state.
|
|
24
|
+
- **Progressive Enhancement**: All critical paths (Add to Cart, Checkout) work **without JavaScript** enabled.
|
|
25
|
+
- **@shopflow/ui Library**: Reusable SDK with ESM/CJS exports and **React-compatible wrappers** via `qwikify$`.
|
|
26
|
+
- **Environment Awareness**: Auto-adapting layouts for **Standalone**, **Iframe**, and **WebView** contexts.
|
|
27
|
+
- **Bridge API**: Native communication via `postMessage` for host app event synchronization.
|
|
28
|
+
- **Tailwind v4**: CSS-first architecture using modern tokens and **Container Queries** (`@container`).
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
### Resumability vs. Hydration
|
|
33
|
+
|
|
34
|
+
**Resumability** is the ability for an application to stay "paused" on the server and "resume" in the browser exactly where it left off, without re-executing the component tree. In a traditional React app, the browser must **Hydrate**: it downloads the entire JS bundle, executes all components, and attaches event listeners before the page becomes interactive.
|
|
35
|
+
|
|
36
|
+
In **ShopFlow**, we utilize Qwik's fine-grained protocol:
|
|
37
|
+
1. **Serialization**: Every piece of state (using `useStore`) is converted to JSON and embedded in the HTML.
|
|
38
|
+
2. **Lazy Event Listeners**: Instead of attaching listeners to every button, Qwik uses a single global listener that knows which small "chunk" of code to fetch only when a user clicks.
|
|
39
|
+
|
|
40
|
+
**Example from this code**: Our `CartProvider` (at `src/context/cart-context.tsx`) manages the global bag state. When a user navigates from the Homepage to a Product page, no JS is transferred. The cart count in the header updates immediately upon interaction because only the `addItem` chunk is pulled from the CDN on-demand.
|
|
41
|
+
|
|
42
|
+
### Rendering Strategy
|
|
43
|
+
- **Parallel Fetching**: We use `routeLoader$` to fetch categories and products simultaneously on the server, avoiding request waterfalls.
|
|
44
|
+
- **Bundle Optimization**: All React-related dependencies are isolated to the Library build (`pkg/`), ensuring the main Storefront remains pure Qwik and ultra-light.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Project Structure
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
ShopFlow/
|
|
52
|
+
├── src/
|
|
53
|
+
│ ├── routes/ # Qwik City File-based Routing
|
|
54
|
+
│ │ ├── cart/ # Bag management logic
|
|
55
|
+
│ │ ├── checkout/ # Multi-step mutation forms
|
|
56
|
+
│ │ ├── embed/ # WebView & Iframe layouts
|
|
57
|
+
│ │ └── layout.tsx # State Providers & Session Mgmt
|
|
58
|
+
│ ├── components/ # Reusable Qwik UI Components
|
|
59
|
+
│ ├── context/ # Serializable Global State
|
|
60
|
+
│ ├── lib/ # API Client & Bridge SDK
|
|
61
|
+
│ └── global.css # Tailwind v4 Design Tokens
|
|
62
|
+
├── pkg/ # (Build Output) React-compatible Library
|
|
63
|
+
└── dist/ # (Build Output) Production App
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Getting Started
|
|
69
|
+
|
|
70
|
+
### Prerequisites
|
|
71
|
+
- **Node.js**: 20.0 or higher
|
|
72
|
+
- **Package Manager**: npm or pnpm
|
|
73
|
+
|
|
74
|
+
### Installation
|
|
75
|
+
```bash
|
|
76
|
+
npm install
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Development
|
|
80
|
+
```bash
|
|
81
|
+
npm run dev
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Production Build & Preview
|
|
85
|
+
```bash
|
|
86
|
+
# Builds both the Storefront (dist/) and the Library (pkg/)
|
|
87
|
+
npm run build
|
|
88
|
+
|
|
89
|
+
# Preview the production storefront
|
|
90
|
+
npm run preview
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Performance Metrics (Lighthouse)
|
|
96
|
+

|
|
97
|
+
|
|
98
|
+
- **Performance**: 77+
|
|
99
|
+
- **Accessibility**: 93
|
|
100
|
+
- **Best Practices**: 100
|
|
101
|
+
- **SEO**: 100
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@shopflowateam/ui",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Blank project with routing included",
|
|
5
|
+
"engines": {
|
|
6
|
+
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
|
7
|
+
},
|
|
8
|
+
"engines-annotation": "Mostly required by sharp which needs a Node-API v9 compatible runtime",
|
|
9
|
+
"private": false,
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "./pkg/index.cjs.js",
|
|
12
|
+
"module": "./pkg/index.es.js",
|
|
13
|
+
"types": "./pkg/types/lib/index.d.ts",
|
|
14
|
+
"files": [
|
|
15
|
+
"pkg/"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "qwik build && npm run build.lib",
|
|
19
|
+
"build.client": "vite build",
|
|
20
|
+
"build.preview": "vite build --ssr src/entry.preview.tsx",
|
|
21
|
+
"build.server": "qwik check-client src dist && vite build -c adapters/vercel-edge/vite.config.ts",
|
|
22
|
+
"build.types": "tsc --incremental --noEmit",
|
|
23
|
+
"build.lib": "vite build -c vite.config.lib.ts --mode lib",
|
|
24
|
+
"build.lib.types": "tsc --emitDeclarationOnly --declaration --project tsconfig.lib.json",
|
|
25
|
+
"deploy": "vercel deploy",
|
|
26
|
+
"dev": "vite --mode ssr",
|
|
27
|
+
"dev.debug": "node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force",
|
|
28
|
+
"fmt": "prettier --write .",
|
|
29
|
+
"fmt.check": "prettier --check .",
|
|
30
|
+
"lint": "eslint \"src/**/*.ts*\"",
|
|
31
|
+
"preview": "qwik build preview && vite preview --open",
|
|
32
|
+
"start": "vite --open --mode ssr",
|
|
33
|
+
"qwik": "qwik"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@builder.io/qwik": "^1.19.2",
|
|
37
|
+
"@builder.io/qwik-city": "^1.19.2",
|
|
38
|
+
"@builder.io/qwik-react": "^0.5.8",
|
|
39
|
+
"react": "^18.2.0",
|
|
40
|
+
"react-dom": "^18.2.0",
|
|
41
|
+
"@eslint/js": "^9",
|
|
42
|
+
"@tailwindcss/vite": "^4.2.2",
|
|
43
|
+
"@types/node": "20.19.0",
|
|
44
|
+
"eslint": "9.32.0",
|
|
45
|
+
"eslint-plugin-qwik": "^1.19.2",
|
|
46
|
+
"globals": "16.4.0",
|
|
47
|
+
"prettier": "3.6.2",
|
|
48
|
+
"tailwindcss": "^4.2.2",
|
|
49
|
+
"typescript": "5.4.5",
|
|
50
|
+
"typescript-eslint": "8.38.0",
|
|
51
|
+
"typescript-plugin-css-modules": "latest",
|
|
52
|
+
"undici": "*",
|
|
53
|
+
"vercel": "^29.1.1",
|
|
54
|
+
"vite": "7.3.1",
|
|
55
|
+
"vite-tsconfig-paths": "^4.2.1"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {}
|
|
58
|
+
}
|
package/pkg/favicon.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 500 500"><g clip-path="url(#a)"><circle cx="250" cy="250" r="250" fill="#fff"/><path fill="#18B6F6" d="m367.87 418.45-61.17-61.18-.94.13v-.67L175.7 227.53l32.05-31.13L188.9 87.73 99.56 199.09c-15.22 15.42-18.03 40.51-7.08 59.03l55.83 93.11a46.82 46.82 0 0 0 40.73 22.81l27.65-.27 151.18 44.68Z"/><path fill="#AC7EF4" d="m401.25 196.94-12.29-22.81-6.41-11.67-2.54-4.56-.26.26-33.66-58.63a47.07 47.07 0 0 0-41.27-23.75l-29.51.8-88.01.28a47.07 47.07 0 0 0-40.33 23.34L93.4 207l95.76-119.54L314.7 226.19l-22.3 22.67 13.35 108.54.13-.26v.26h-.26l.26.27 10.42 10.2 50.62 49.78c2.13 2 5.6-.4 4.13-2.96l-31.25-61.85 54.5-101.3 1.73-2c.67-.81 1.33-1.62 1.87-2.42a46.8 46.8 0 0 0 3.34-50.18Z"/><path fill="#fff" d="M315.1 225.65 189.18 87.6l17.9 108.14L175 227l130.5 130.27-11.75-108.14 21.37-23.48Z"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h500v500H0z"/></clipPath></defs></svg>
|
package/pkg/index.cjs.js
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("@builder.io/qwik/jsx-runtime");
|
|
4
|
+
const qwik = require("@builder.io/qwik");
|
|
5
|
+
const qwikCity = require("@builder.io/qwik-city");
|
|
6
|
+
const qwikReact = require("@builder.io/qwik-react");
|
|
7
|
+
const formatCurrency = (amountInCents) => {
|
|
8
|
+
return new Intl.NumberFormat("en-US", {
|
|
9
|
+
style: "currency",
|
|
10
|
+
currency: "USD"
|
|
11
|
+
}).format((amountInCents || 0) / 100);
|
|
12
|
+
};
|
|
13
|
+
const ProductCardQwik = qwik.component$(({ product }) => {
|
|
14
|
+
const formattedPrice = formatCurrency(product.price);
|
|
15
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
16
|
+
class: "group h-full flex flex-col [container-type:inline-size]",
|
|
17
|
+
children: [
|
|
18
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
19
|
+
class: "relative aspect-square mb-6 rounded-md @[200px]:rounded-2xl overflow-hidden bg-surface-dim border border-border group-hover:border-primary/50 transition-all duration-500 hover:shadow-premium",
|
|
20
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(qwikCity.Link, {
|
|
21
|
+
href: `/products/${product.id}`,
|
|
22
|
+
class: "block w-full h-full",
|
|
23
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("img", {
|
|
24
|
+
src: product.images?.[0] || "https://via.placeholder.com/400",
|
|
25
|
+
alt: product.title || product.name,
|
|
26
|
+
class: "w-full h-full object-cover transform group-hover:scale-110 transition-transform duration-700",
|
|
27
|
+
width: 400,
|
|
28
|
+
height: 400,
|
|
29
|
+
loading: "lazy"
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
}),
|
|
33
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
34
|
+
class: "space-y-1",
|
|
35
|
+
children: [
|
|
36
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
37
|
+
class: "flex flex-col @[250px]:flex-row @[250px]:justify-between @[250px]:items-start gap-1",
|
|
38
|
+
children: [
|
|
39
|
+
/* @__PURE__ */ jsxRuntime.jsx(qwikCity.Link, {
|
|
40
|
+
href: `/products/${product.id}`,
|
|
41
|
+
class: "block",
|
|
42
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("h3", {
|
|
43
|
+
class: "font-medium text-sm @[200px]:text-md group-hover:text-primary transition-colors line-clamp-1",
|
|
44
|
+
children: product.title || product.name
|
|
45
|
+
})
|
|
46
|
+
}),
|
|
47
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
48
|
+
class: "font-medium text-sm @[200px]:text-md",
|
|
49
|
+
children: formattedPrice
|
|
50
|
+
})
|
|
51
|
+
]
|
|
52
|
+
}),
|
|
53
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", {
|
|
54
|
+
class: "text-[10px] @[200px]:text-xs text-text-muted uppercase tracking-widest font-medium",
|
|
55
|
+
children: product.category || "Collection"
|
|
56
|
+
})
|
|
57
|
+
]
|
|
58
|
+
})
|
|
59
|
+
]
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
const CartItemQwik = qwik.component$(({ item, cartAction, onUpdateQuantity$, onRemove$ }) => {
|
|
63
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
64
|
+
class: "[container-type:inline-size] bg-surface-dim rounded-lg border border-border group transition-all hover:border-text-muted",
|
|
65
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
66
|
+
class: "flex flex-col @[500px]:flex-row gap-8 p-8",
|
|
67
|
+
children: [
|
|
68
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
69
|
+
class: "w-full @[500px]:w-32 aspect-square rounded-lg overflow-hidden bg-white border border-border flex-shrink-0",
|
|
70
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("img", {
|
|
71
|
+
src: item.images?.[0],
|
|
72
|
+
alt: item.name,
|
|
73
|
+
class: "w-full h-full object-cover transition-transform group-hover:scale-105 duration-500",
|
|
74
|
+
width: 128,
|
|
75
|
+
height: 128
|
|
76
|
+
})
|
|
77
|
+
}),
|
|
78
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
79
|
+
class: "flex-1 flex flex-col justify-between py-1",
|
|
80
|
+
children: [
|
|
81
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
82
|
+
class: "flex justify-between items-start gap-4",
|
|
83
|
+
children: [
|
|
84
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
85
|
+
children: [
|
|
86
|
+
/* @__PURE__ */ jsxRuntime.jsx(qwikCity.Link, {
|
|
87
|
+
href: `/products/${item.id}`,
|
|
88
|
+
class: "text-lg font-bold hover:text-primary transition-colors uppercase tracking-tight",
|
|
89
|
+
children: item.name
|
|
90
|
+
}),
|
|
91
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", {
|
|
92
|
+
class: "text-[10px] font-black text-text-muted mt-2 uppercase tracking-widest",
|
|
93
|
+
children: item.variantName || "Standard"
|
|
94
|
+
})
|
|
95
|
+
]
|
|
96
|
+
}),
|
|
97
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", {
|
|
98
|
+
class: "text-lg font-bold tracking-tighter",
|
|
99
|
+
children: formatCurrency(item.price)
|
|
100
|
+
})
|
|
101
|
+
]
|
|
102
|
+
}),
|
|
103
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
104
|
+
class: "flex justify-between items-end mt-10",
|
|
105
|
+
children: [
|
|
106
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
107
|
+
class: "flex items-center gap-4",
|
|
108
|
+
children: [
|
|
109
|
+
/* @__PURE__ */ jsxRuntime.jsxs(qwikCity.Form, {
|
|
110
|
+
action: cartAction,
|
|
111
|
+
onSubmitCompleted$: onUpdateQuantity$,
|
|
112
|
+
children: [
|
|
113
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", {
|
|
114
|
+
type: "hidden",
|
|
115
|
+
name: "type",
|
|
116
|
+
value: "update"
|
|
117
|
+
}),
|
|
118
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", {
|
|
119
|
+
type: "hidden",
|
|
120
|
+
name: "id",
|
|
121
|
+
value: item.cartItemId
|
|
122
|
+
}),
|
|
123
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", {
|
|
124
|
+
type: "hidden",
|
|
125
|
+
name: "quantity",
|
|
126
|
+
value: item.quantity - 1
|
|
127
|
+
}),
|
|
128
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", {
|
|
129
|
+
disabled: item.quantity <= 1 || cartAction.isRunning,
|
|
130
|
+
class: "w-10 h-10 flex items-center justify-center cursor-pointer rounded-xl border border-border bg-surface-dim disabled:opacity-30 transition-all shadow-sm",
|
|
131
|
+
"aria-label": "Decrease",
|
|
132
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", {
|
|
133
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
134
|
+
width: "14",
|
|
135
|
+
height: "14",
|
|
136
|
+
viewBox: "0 0 24 24",
|
|
137
|
+
fill: "none",
|
|
138
|
+
stroke: "currentColor",
|
|
139
|
+
"stroke-width": "3",
|
|
140
|
+
"stroke-linecap": "round",
|
|
141
|
+
"stroke-linejoin": "round",
|
|
142
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("line", {
|
|
143
|
+
x1: "5",
|
|
144
|
+
y1: "12",
|
|
145
|
+
x2: "19",
|
|
146
|
+
y2: "12"
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
]
|
|
151
|
+
}),
|
|
152
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
153
|
+
class: "w-8 text-center font-black text-xs",
|
|
154
|
+
children: item.quantity
|
|
155
|
+
}),
|
|
156
|
+
/* @__PURE__ */ jsxRuntime.jsxs(qwikCity.Form, {
|
|
157
|
+
action: cartAction,
|
|
158
|
+
onSubmitCompleted$: onUpdateQuantity$,
|
|
159
|
+
children: [
|
|
160
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", {
|
|
161
|
+
type: "hidden",
|
|
162
|
+
name: "type",
|
|
163
|
+
value: "update"
|
|
164
|
+
}),
|
|
165
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", {
|
|
166
|
+
type: "hidden",
|
|
167
|
+
name: "id",
|
|
168
|
+
value: item.cartItemId
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", {
|
|
171
|
+
type: "hidden",
|
|
172
|
+
name: "quantity",
|
|
173
|
+
value: item.quantity + 1
|
|
174
|
+
}),
|
|
175
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", {
|
|
176
|
+
disabled: item.quantity >= 99 || cartAction.isRunning,
|
|
177
|
+
class: "w-10 h-10 flex items-center cursor-pointer justify-center rounded-xl border border-border bg-surface-dim disabled:opacity-30 transition-all shadow-sm",
|
|
178
|
+
"aria-label": "Increase",
|
|
179
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("svg", {
|
|
180
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
181
|
+
width: "14",
|
|
182
|
+
height: "14",
|
|
183
|
+
viewBox: "0 0 24 24",
|
|
184
|
+
fill: "none",
|
|
185
|
+
stroke: "currentColor",
|
|
186
|
+
"stroke-width": "3",
|
|
187
|
+
"stroke-linecap": "round",
|
|
188
|
+
"stroke-linejoin": "round",
|
|
189
|
+
children: [
|
|
190
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", {
|
|
191
|
+
x1: "12",
|
|
192
|
+
y1: "5",
|
|
193
|
+
x2: "12",
|
|
194
|
+
y2: "19"
|
|
195
|
+
}),
|
|
196
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", {
|
|
197
|
+
x1: "5",
|
|
198
|
+
y1: "12",
|
|
199
|
+
x2: "19",
|
|
200
|
+
y2: "12"
|
|
201
|
+
})
|
|
202
|
+
]
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
]
|
|
206
|
+
})
|
|
207
|
+
]
|
|
208
|
+
}),
|
|
209
|
+
/* @__PURE__ */ jsxRuntime.jsxs(qwikCity.Form, {
|
|
210
|
+
action: cartAction,
|
|
211
|
+
onSubmitCompleted$: onRemove$,
|
|
212
|
+
children: [
|
|
213
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", {
|
|
214
|
+
type: "hidden",
|
|
215
|
+
name: "type",
|
|
216
|
+
value: "remove"
|
|
217
|
+
}),
|
|
218
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", {
|
|
219
|
+
type: "hidden",
|
|
220
|
+
name: "id",
|
|
221
|
+
value: item.cartItemId
|
|
222
|
+
}),
|
|
223
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", {
|
|
224
|
+
class: "text-[10px] font-black uppercase tracking-[0.2em] text-red-500 hover:text-red-700 transition-colors p-2 underline decoration-2 underline-offset-4",
|
|
225
|
+
children: "Remove"
|
|
226
|
+
})
|
|
227
|
+
]
|
|
228
|
+
})
|
|
229
|
+
]
|
|
230
|
+
})
|
|
231
|
+
]
|
|
232
|
+
})
|
|
233
|
+
]
|
|
234
|
+
})
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
const EmptyState = qwik.component$((props) => {
|
|
238
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
239
|
+
class: "py-24 px-6 text-center animate-in fade-in slide-in-from-bottom-4 duration-700",
|
|
240
|
+
children: [
|
|
241
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
242
|
+
class: "w-16 h-16 bg-surface-dim rounded-md lg:rounded-2xl flex items-center justify-center mx-auto mb-8 border border-border",
|
|
243
|
+
children: props.icon === "error" ? /* @__PURE__ */ jsxRuntime.jsxs("svg", {
|
|
244
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
245
|
+
width: "24",
|
|
246
|
+
height: "24",
|
|
247
|
+
viewBox: "0 0 24 24",
|
|
248
|
+
fill: "none",
|
|
249
|
+
stroke: "currentColor",
|
|
250
|
+
"stroke-width": "2",
|
|
251
|
+
"stroke-linecap": "round",
|
|
252
|
+
"stroke-linejoin": "round",
|
|
253
|
+
class: "text-text-muted",
|
|
254
|
+
children: [
|
|
255
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", {
|
|
256
|
+
cx: "12",
|
|
257
|
+
cy: "12",
|
|
258
|
+
r: "10"
|
|
259
|
+
}),
|
|
260
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", {
|
|
261
|
+
x1: "12",
|
|
262
|
+
y1: "8",
|
|
263
|
+
x2: "12",
|
|
264
|
+
y2: "12"
|
|
265
|
+
}),
|
|
266
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", {
|
|
267
|
+
x1: "12",
|
|
268
|
+
y1: "16",
|
|
269
|
+
x2: "12.01",
|
|
270
|
+
y2: "16"
|
|
271
|
+
})
|
|
272
|
+
]
|
|
273
|
+
}) : props.icon === "cart" ? /* @__PURE__ */ jsxRuntime.jsxs("svg", {
|
|
274
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
275
|
+
width: "24",
|
|
276
|
+
height: "24",
|
|
277
|
+
viewBox: "0 0 24 24",
|
|
278
|
+
fill: "none",
|
|
279
|
+
stroke: "currentColor",
|
|
280
|
+
"stroke-width": "2",
|
|
281
|
+
"stroke-linecap": "round",
|
|
282
|
+
"stroke-linejoin": "round",
|
|
283
|
+
class: "text-text-muted",
|
|
284
|
+
children: [
|
|
285
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", {
|
|
286
|
+
cx: "8",
|
|
287
|
+
cy: "21",
|
|
288
|
+
r: "1"
|
|
289
|
+
}),
|
|
290
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", {
|
|
291
|
+
cx: "19",
|
|
292
|
+
cy: "21",
|
|
293
|
+
r: "1"
|
|
294
|
+
}),
|
|
295
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", {
|
|
296
|
+
d: "M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"
|
|
297
|
+
})
|
|
298
|
+
]
|
|
299
|
+
}) : /* @__PURE__ */ jsxRuntime.jsxs("svg", {
|
|
300
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
301
|
+
width: "24",
|
|
302
|
+
height: "24",
|
|
303
|
+
viewBox: "0 0 24 24",
|
|
304
|
+
fill: "none",
|
|
305
|
+
stroke: "currentColor",
|
|
306
|
+
"stroke-width": "2",
|
|
307
|
+
"stroke-linecap": "round",
|
|
308
|
+
"stroke-linejoin": "round",
|
|
309
|
+
class: "text-text-muted",
|
|
310
|
+
children: [
|
|
311
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", {
|
|
312
|
+
cx: "11",
|
|
313
|
+
cy: "11",
|
|
314
|
+
r: "8"
|
|
315
|
+
}),
|
|
316
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", {
|
|
317
|
+
x1: "21",
|
|
318
|
+
y1: "21",
|
|
319
|
+
x2: "16.65",
|
|
320
|
+
y2: "16.65"
|
|
321
|
+
})
|
|
322
|
+
]
|
|
323
|
+
})
|
|
324
|
+
}),
|
|
325
|
+
props.title && /* @__PURE__ */ jsxRuntime.jsx("h3", {
|
|
326
|
+
class: "text-2xl font-semibold mb-2 tracking-tight uppercase",
|
|
327
|
+
children: props.title
|
|
328
|
+
}),
|
|
329
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", {
|
|
330
|
+
class: "text-text-muted max-w-sm mx-auto leading-relaxed mb-10 font-medium",
|
|
331
|
+
children: props.message
|
|
332
|
+
}),
|
|
333
|
+
props.actionLabel && props.actionHref && /* @__PURE__ */ jsxRuntime.jsx(qwikCity.Link, {
|
|
334
|
+
href: props.actionHref,
|
|
335
|
+
class: "inline-block bg-black text-white px-5 py-2.5 rounded font-semibold text-sm hover:bg-primary transition-all",
|
|
336
|
+
children: props.actionLabel
|
|
337
|
+
})
|
|
338
|
+
]
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
qwikReact.qwikify$(ProductCardQwik, {
|
|
342
|
+
eagerness: "hover"
|
|
343
|
+
});
|
|
344
|
+
qwikReact.qwikify$(CartItemQwik, {
|
|
345
|
+
eagerness: "hover"
|
|
346
|
+
});
|
|
347
|
+
const emitShopFlowEvent = (event) => {
|
|
348
|
+
if (typeof window !== "undefined") {
|
|
349
|
+
window.parent.postMessage({
|
|
350
|
+
source: "shopflow",
|
|
351
|
+
...event
|
|
352
|
+
}, "*");
|
|
353
|
+
window.dispatchEvent(new CustomEvent("shopflow-event", {
|
|
354
|
+
detail: event
|
|
355
|
+
}));
|
|
356
|
+
console.debug("[ShopFlow Bridge] Emitting event:", event);
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
exports.CartItem = CartItemQwik;
|
|
360
|
+
exports.EmptyState = EmptyState;
|
|
361
|
+
exports.ProductCard = ProductCardQwik;
|
|
362
|
+
exports.emitShopFlowEvent = emitShopFlowEvent;
|
package/pkg/index.es.js
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import { jsxs, jsx } from "@builder.io/qwik/jsx-runtime";
|
|
2
|
+
import { component$ } from "@builder.io/qwik";
|
|
3
|
+
import { Link, Form } from "@builder.io/qwik-city";
|
|
4
|
+
import { qwikify$ } from "@builder.io/qwik-react";
|
|
5
|
+
const formatCurrency = (amountInCents) => {
|
|
6
|
+
return new Intl.NumberFormat("en-US", {
|
|
7
|
+
style: "currency",
|
|
8
|
+
currency: "USD"
|
|
9
|
+
}).format((amountInCents || 0) / 100);
|
|
10
|
+
};
|
|
11
|
+
const ProductCardQwik = component$(({ product }) => {
|
|
12
|
+
const formattedPrice = formatCurrency(product.price);
|
|
13
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
14
|
+
class: "group h-full flex flex-col [container-type:inline-size]",
|
|
15
|
+
children: [
|
|
16
|
+
/* @__PURE__ */ jsx("div", {
|
|
17
|
+
class: "relative aspect-square mb-6 rounded-md @[200px]:rounded-2xl overflow-hidden bg-surface-dim border border-border group-hover:border-primary/50 transition-all duration-500 hover:shadow-premium",
|
|
18
|
+
children: /* @__PURE__ */ jsx(Link, {
|
|
19
|
+
href: `/products/${product.id}`,
|
|
20
|
+
class: "block w-full h-full",
|
|
21
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
22
|
+
src: product.images?.[0] || "https://via.placeholder.com/400",
|
|
23
|
+
alt: product.title || product.name,
|
|
24
|
+
class: "w-full h-full object-cover transform group-hover:scale-110 transition-transform duration-700",
|
|
25
|
+
width: 400,
|
|
26
|
+
height: 400,
|
|
27
|
+
loading: "lazy"
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
}),
|
|
31
|
+
/* @__PURE__ */ jsxs("div", {
|
|
32
|
+
class: "space-y-1",
|
|
33
|
+
children: [
|
|
34
|
+
/* @__PURE__ */ jsxs("div", {
|
|
35
|
+
class: "flex flex-col @[250px]:flex-row @[250px]:justify-between @[250px]:items-start gap-1",
|
|
36
|
+
children: [
|
|
37
|
+
/* @__PURE__ */ jsx(Link, {
|
|
38
|
+
href: `/products/${product.id}`,
|
|
39
|
+
class: "block",
|
|
40
|
+
children: /* @__PURE__ */ jsx("h3", {
|
|
41
|
+
class: "font-medium text-sm @[200px]:text-md group-hover:text-primary transition-colors line-clamp-1",
|
|
42
|
+
children: product.title || product.name
|
|
43
|
+
})
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ jsx("span", {
|
|
46
|
+
class: "font-medium text-sm @[200px]:text-md",
|
|
47
|
+
children: formattedPrice
|
|
48
|
+
})
|
|
49
|
+
]
|
|
50
|
+
}),
|
|
51
|
+
/* @__PURE__ */ jsx("p", {
|
|
52
|
+
class: "text-[10px] @[200px]:text-xs text-text-muted uppercase tracking-widest font-medium",
|
|
53
|
+
children: product.category || "Collection"
|
|
54
|
+
})
|
|
55
|
+
]
|
|
56
|
+
})
|
|
57
|
+
]
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
const CartItemQwik = component$(({ item, cartAction, onUpdateQuantity$, onRemove$ }) => {
|
|
61
|
+
return /* @__PURE__ */ jsx("div", {
|
|
62
|
+
class: "[container-type:inline-size] bg-surface-dim rounded-lg border border-border group transition-all hover:border-text-muted",
|
|
63
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
64
|
+
class: "flex flex-col @[500px]:flex-row gap-8 p-8",
|
|
65
|
+
children: [
|
|
66
|
+
/* @__PURE__ */ jsx("div", {
|
|
67
|
+
class: "w-full @[500px]:w-32 aspect-square rounded-lg overflow-hidden bg-white border border-border flex-shrink-0",
|
|
68
|
+
children: /* @__PURE__ */ jsx("img", {
|
|
69
|
+
src: item.images?.[0],
|
|
70
|
+
alt: item.name,
|
|
71
|
+
class: "w-full h-full object-cover transition-transform group-hover:scale-105 duration-500",
|
|
72
|
+
width: 128,
|
|
73
|
+
height: 128
|
|
74
|
+
})
|
|
75
|
+
}),
|
|
76
|
+
/* @__PURE__ */ jsxs("div", {
|
|
77
|
+
class: "flex-1 flex flex-col justify-between py-1",
|
|
78
|
+
children: [
|
|
79
|
+
/* @__PURE__ */ jsxs("div", {
|
|
80
|
+
class: "flex justify-between items-start gap-4",
|
|
81
|
+
children: [
|
|
82
|
+
/* @__PURE__ */ jsxs("div", {
|
|
83
|
+
children: [
|
|
84
|
+
/* @__PURE__ */ jsx(Link, {
|
|
85
|
+
href: `/products/${item.id}`,
|
|
86
|
+
class: "text-lg font-bold hover:text-primary transition-colors uppercase tracking-tight",
|
|
87
|
+
children: item.name
|
|
88
|
+
}),
|
|
89
|
+
/* @__PURE__ */ jsx("p", {
|
|
90
|
+
class: "text-[10px] font-black text-text-muted mt-2 uppercase tracking-widest",
|
|
91
|
+
children: item.variantName || "Standard"
|
|
92
|
+
})
|
|
93
|
+
]
|
|
94
|
+
}),
|
|
95
|
+
/* @__PURE__ */ jsx("p", {
|
|
96
|
+
class: "text-lg font-bold tracking-tighter",
|
|
97
|
+
children: formatCurrency(item.price)
|
|
98
|
+
})
|
|
99
|
+
]
|
|
100
|
+
}),
|
|
101
|
+
/* @__PURE__ */ jsxs("div", {
|
|
102
|
+
class: "flex justify-between items-end mt-10",
|
|
103
|
+
children: [
|
|
104
|
+
/* @__PURE__ */ jsxs("div", {
|
|
105
|
+
class: "flex items-center gap-4",
|
|
106
|
+
children: [
|
|
107
|
+
/* @__PURE__ */ jsxs(Form, {
|
|
108
|
+
action: cartAction,
|
|
109
|
+
onSubmitCompleted$: onUpdateQuantity$,
|
|
110
|
+
children: [
|
|
111
|
+
/* @__PURE__ */ jsx("input", {
|
|
112
|
+
type: "hidden",
|
|
113
|
+
name: "type",
|
|
114
|
+
value: "update"
|
|
115
|
+
}),
|
|
116
|
+
/* @__PURE__ */ jsx("input", {
|
|
117
|
+
type: "hidden",
|
|
118
|
+
name: "id",
|
|
119
|
+
value: item.cartItemId
|
|
120
|
+
}),
|
|
121
|
+
/* @__PURE__ */ jsx("input", {
|
|
122
|
+
type: "hidden",
|
|
123
|
+
name: "quantity",
|
|
124
|
+
value: item.quantity - 1
|
|
125
|
+
}),
|
|
126
|
+
/* @__PURE__ */ jsx("button", {
|
|
127
|
+
disabled: item.quantity <= 1 || cartAction.isRunning,
|
|
128
|
+
class: "w-10 h-10 flex items-center justify-center cursor-pointer rounded-xl border border-border bg-surface-dim disabled:opacity-30 transition-all shadow-sm",
|
|
129
|
+
"aria-label": "Decrease",
|
|
130
|
+
children: /* @__PURE__ */ jsx("svg", {
|
|
131
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
132
|
+
width: "14",
|
|
133
|
+
height: "14",
|
|
134
|
+
viewBox: "0 0 24 24",
|
|
135
|
+
fill: "none",
|
|
136
|
+
stroke: "currentColor",
|
|
137
|
+
"stroke-width": "3",
|
|
138
|
+
"stroke-linecap": "round",
|
|
139
|
+
"stroke-linejoin": "round",
|
|
140
|
+
children: /* @__PURE__ */ jsx("line", {
|
|
141
|
+
x1: "5",
|
|
142
|
+
y1: "12",
|
|
143
|
+
x2: "19",
|
|
144
|
+
y2: "12"
|
|
145
|
+
})
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
|
+
]
|
|
149
|
+
}),
|
|
150
|
+
/* @__PURE__ */ jsx("span", {
|
|
151
|
+
class: "w-8 text-center font-black text-xs",
|
|
152
|
+
children: item.quantity
|
|
153
|
+
}),
|
|
154
|
+
/* @__PURE__ */ jsxs(Form, {
|
|
155
|
+
action: cartAction,
|
|
156
|
+
onSubmitCompleted$: onUpdateQuantity$,
|
|
157
|
+
children: [
|
|
158
|
+
/* @__PURE__ */ jsx("input", {
|
|
159
|
+
type: "hidden",
|
|
160
|
+
name: "type",
|
|
161
|
+
value: "update"
|
|
162
|
+
}),
|
|
163
|
+
/* @__PURE__ */ jsx("input", {
|
|
164
|
+
type: "hidden",
|
|
165
|
+
name: "id",
|
|
166
|
+
value: item.cartItemId
|
|
167
|
+
}),
|
|
168
|
+
/* @__PURE__ */ jsx("input", {
|
|
169
|
+
type: "hidden",
|
|
170
|
+
name: "quantity",
|
|
171
|
+
value: item.quantity + 1
|
|
172
|
+
}),
|
|
173
|
+
/* @__PURE__ */ jsx("button", {
|
|
174
|
+
disabled: item.quantity >= 99 || cartAction.isRunning,
|
|
175
|
+
class: "w-10 h-10 flex items-center cursor-pointer justify-center rounded-xl border border-border bg-surface-dim disabled:opacity-30 transition-all shadow-sm",
|
|
176
|
+
"aria-label": "Increase",
|
|
177
|
+
children: /* @__PURE__ */ jsxs("svg", {
|
|
178
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
179
|
+
width: "14",
|
|
180
|
+
height: "14",
|
|
181
|
+
viewBox: "0 0 24 24",
|
|
182
|
+
fill: "none",
|
|
183
|
+
stroke: "currentColor",
|
|
184
|
+
"stroke-width": "3",
|
|
185
|
+
"stroke-linecap": "round",
|
|
186
|
+
"stroke-linejoin": "round",
|
|
187
|
+
children: [
|
|
188
|
+
/* @__PURE__ */ jsx("line", {
|
|
189
|
+
x1: "12",
|
|
190
|
+
y1: "5",
|
|
191
|
+
x2: "12",
|
|
192
|
+
y2: "19"
|
|
193
|
+
}),
|
|
194
|
+
/* @__PURE__ */ jsx("line", {
|
|
195
|
+
x1: "5",
|
|
196
|
+
y1: "12",
|
|
197
|
+
x2: "19",
|
|
198
|
+
y2: "12"
|
|
199
|
+
})
|
|
200
|
+
]
|
|
201
|
+
})
|
|
202
|
+
})
|
|
203
|
+
]
|
|
204
|
+
})
|
|
205
|
+
]
|
|
206
|
+
}),
|
|
207
|
+
/* @__PURE__ */ jsxs(Form, {
|
|
208
|
+
action: cartAction,
|
|
209
|
+
onSubmitCompleted$: onRemove$,
|
|
210
|
+
children: [
|
|
211
|
+
/* @__PURE__ */ jsx("input", {
|
|
212
|
+
type: "hidden",
|
|
213
|
+
name: "type",
|
|
214
|
+
value: "remove"
|
|
215
|
+
}),
|
|
216
|
+
/* @__PURE__ */ jsx("input", {
|
|
217
|
+
type: "hidden",
|
|
218
|
+
name: "id",
|
|
219
|
+
value: item.cartItemId
|
|
220
|
+
}),
|
|
221
|
+
/* @__PURE__ */ jsx("button", {
|
|
222
|
+
class: "text-[10px] font-black uppercase tracking-[0.2em] text-red-500 hover:text-red-700 transition-colors p-2 underline decoration-2 underline-offset-4",
|
|
223
|
+
children: "Remove"
|
|
224
|
+
})
|
|
225
|
+
]
|
|
226
|
+
})
|
|
227
|
+
]
|
|
228
|
+
})
|
|
229
|
+
]
|
|
230
|
+
})
|
|
231
|
+
]
|
|
232
|
+
})
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
const EmptyState = component$((props) => {
|
|
236
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
237
|
+
class: "py-24 px-6 text-center animate-in fade-in slide-in-from-bottom-4 duration-700",
|
|
238
|
+
children: [
|
|
239
|
+
/* @__PURE__ */ jsx("div", {
|
|
240
|
+
class: "w-16 h-16 bg-surface-dim rounded-md lg:rounded-2xl flex items-center justify-center mx-auto mb-8 border border-border",
|
|
241
|
+
children: props.icon === "error" ? /* @__PURE__ */ jsxs("svg", {
|
|
242
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
243
|
+
width: "24",
|
|
244
|
+
height: "24",
|
|
245
|
+
viewBox: "0 0 24 24",
|
|
246
|
+
fill: "none",
|
|
247
|
+
stroke: "currentColor",
|
|
248
|
+
"stroke-width": "2",
|
|
249
|
+
"stroke-linecap": "round",
|
|
250
|
+
"stroke-linejoin": "round",
|
|
251
|
+
class: "text-text-muted",
|
|
252
|
+
children: [
|
|
253
|
+
/* @__PURE__ */ jsx("circle", {
|
|
254
|
+
cx: "12",
|
|
255
|
+
cy: "12",
|
|
256
|
+
r: "10"
|
|
257
|
+
}),
|
|
258
|
+
/* @__PURE__ */ jsx("line", {
|
|
259
|
+
x1: "12",
|
|
260
|
+
y1: "8",
|
|
261
|
+
x2: "12",
|
|
262
|
+
y2: "12"
|
|
263
|
+
}),
|
|
264
|
+
/* @__PURE__ */ jsx("line", {
|
|
265
|
+
x1: "12",
|
|
266
|
+
y1: "16",
|
|
267
|
+
x2: "12.01",
|
|
268
|
+
y2: "16"
|
|
269
|
+
})
|
|
270
|
+
]
|
|
271
|
+
}) : props.icon === "cart" ? /* @__PURE__ */ jsxs("svg", {
|
|
272
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
273
|
+
width: "24",
|
|
274
|
+
height: "24",
|
|
275
|
+
viewBox: "0 0 24 24",
|
|
276
|
+
fill: "none",
|
|
277
|
+
stroke: "currentColor",
|
|
278
|
+
"stroke-width": "2",
|
|
279
|
+
"stroke-linecap": "round",
|
|
280
|
+
"stroke-linejoin": "round",
|
|
281
|
+
class: "text-text-muted",
|
|
282
|
+
children: [
|
|
283
|
+
/* @__PURE__ */ jsx("circle", {
|
|
284
|
+
cx: "8",
|
|
285
|
+
cy: "21",
|
|
286
|
+
r: "1"
|
|
287
|
+
}),
|
|
288
|
+
/* @__PURE__ */ jsx("circle", {
|
|
289
|
+
cx: "19",
|
|
290
|
+
cy: "21",
|
|
291
|
+
r: "1"
|
|
292
|
+
}),
|
|
293
|
+
/* @__PURE__ */ jsx("path", {
|
|
294
|
+
d: "M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"
|
|
295
|
+
})
|
|
296
|
+
]
|
|
297
|
+
}) : /* @__PURE__ */ jsxs("svg", {
|
|
298
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
299
|
+
width: "24",
|
|
300
|
+
height: "24",
|
|
301
|
+
viewBox: "0 0 24 24",
|
|
302
|
+
fill: "none",
|
|
303
|
+
stroke: "currentColor",
|
|
304
|
+
"stroke-width": "2",
|
|
305
|
+
"stroke-linecap": "round",
|
|
306
|
+
"stroke-linejoin": "round",
|
|
307
|
+
class: "text-text-muted",
|
|
308
|
+
children: [
|
|
309
|
+
/* @__PURE__ */ jsx("circle", {
|
|
310
|
+
cx: "11",
|
|
311
|
+
cy: "11",
|
|
312
|
+
r: "8"
|
|
313
|
+
}),
|
|
314
|
+
/* @__PURE__ */ jsx("line", {
|
|
315
|
+
x1: "21",
|
|
316
|
+
y1: "21",
|
|
317
|
+
x2: "16.65",
|
|
318
|
+
y2: "16.65"
|
|
319
|
+
})
|
|
320
|
+
]
|
|
321
|
+
})
|
|
322
|
+
}),
|
|
323
|
+
props.title && /* @__PURE__ */ jsx("h3", {
|
|
324
|
+
class: "text-2xl font-semibold mb-2 tracking-tight uppercase",
|
|
325
|
+
children: props.title
|
|
326
|
+
}),
|
|
327
|
+
/* @__PURE__ */ jsx("p", {
|
|
328
|
+
class: "text-text-muted max-w-sm mx-auto leading-relaxed mb-10 font-medium",
|
|
329
|
+
children: props.message
|
|
330
|
+
}),
|
|
331
|
+
props.actionLabel && props.actionHref && /* @__PURE__ */ jsx(Link, {
|
|
332
|
+
href: props.actionHref,
|
|
333
|
+
class: "inline-block bg-black text-white px-5 py-2.5 rounded font-semibold text-sm hover:bg-primary transition-all",
|
|
334
|
+
children: props.actionLabel
|
|
335
|
+
})
|
|
336
|
+
]
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
qwikify$(ProductCardQwik, {
|
|
340
|
+
eagerness: "hover"
|
|
341
|
+
});
|
|
342
|
+
qwikify$(CartItemQwik, {
|
|
343
|
+
eagerness: "hover"
|
|
344
|
+
});
|
|
345
|
+
const emitShopFlowEvent = (event) => {
|
|
346
|
+
if (typeof window !== "undefined") {
|
|
347
|
+
window.parent.postMessage({
|
|
348
|
+
source: "shopflow",
|
|
349
|
+
...event
|
|
350
|
+
}, "*");
|
|
351
|
+
window.dispatchEvent(new CustomEvent("shopflow-event", {
|
|
352
|
+
detail: event
|
|
353
|
+
}));
|
|
354
|
+
console.debug("[ShopFlow Bridge] Emitting event:", event);
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
export {
|
|
358
|
+
CartItemQwik as CartItem,
|
|
359
|
+
EmptyState,
|
|
360
|
+
ProductCardQwik as ProductCard,
|
|
361
|
+
emitShopFlowEvent
|
|
362
|
+
};
|
package/pkg/robots.txt
ADDED
|
File without changes
|