@salla.sa/twilight-theme-engine 1.0.10 → 1.0.12
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 +156 -68
- package/dist/{AddToCartForm-4KYCJ2UZ.js → AddToCartForm-KBJ5Q3KB.js} +3 -3
- package/dist/{AddToCartForm-4KYCJ2UZ.js.map → AddToCartForm-KBJ5Q3KB.js.map} +1 -1
- package/dist/{BlogAuthorPage-LYM6TVXX.js → BlogAuthorPage-TJ57XZFN.js} +6 -6
- package/dist/{BlogAuthorPage-LYM6TVXX.js.map → BlogAuthorPage-TJ57XZFN.js.map} +1 -1
- package/dist/{BlogCategoryPage-Q7DYUND5.js → BlogCategoryPage-AWFBDRCP.js} +6 -6
- package/dist/{BlogCategoryPage-Q7DYUND5.js.map → BlogCategoryPage-AWFBDRCP.js.map} +1 -1
- package/dist/{BlogPage-PGGJPPUB.js → BlogPage-JCK2Y3DT.js} +5 -5
- package/dist/{BlogPage-PGGJPPUB.js.map → BlogPage-JCK2Y3DT.js.map} +1 -1
- package/dist/{BlogSinglePage-ZWYO4JUJ.js → BlogSinglePage-6WEUDLUM.js} +5 -5
- package/dist/{BlogSinglePage-ZWYO4JUJ.js.map → BlogSinglePage-6WEUDLUM.js.map} +1 -1
- package/dist/{BlogTagPage-6ZAUZQEX.js → BlogTagPage-WWKH4V3O.js} +6 -6
- package/dist/{BlogTagPage-6ZAUZQEX.js.map → BlogTagPage-WWKH4V3O.js.map} +1 -1
- package/dist/{BrandsPage-KIWMKWCX.js → BrandsPage-ZIUVZLAQ.js} +5 -5
- package/dist/{BrandsPage-KIWMKWCX.js.map → BrandsPage-ZIUVZLAQ.js.map} +1 -1
- package/dist/{Breadcrumb-ZTDDSIJS.js → Breadcrumb-KH6PSJQA.js} +5 -5
- package/dist/{Breadcrumb-ZTDDSIJS.js.map → Breadcrumb-KH6PSJQA.js.map} +1 -1
- package/dist/{CartItem-GD2D3P4F.js → CartItem-QMHVBXWJ.js} +5 -5
- package/dist/{CartItem-GD2D3P4F.js.map → CartItem-QMHVBXWJ.js.map} +1 -1
- package/dist/{CartSummary-B4J42D6C.js → CartSummary-W4JV7KOI.js} +5 -5
- package/dist/{CartSummary-B4J42D6C.js.map → CartSummary-W4JV7KOI.js.map} +1 -1
- package/dist/{Copyright-AFLQBB32.js → Copyright-BA5M2XU5.js} +3 -3
- package/dist/{Copyright-AFLQBB32.js.map → Copyright-BA5M2XU5.js.map} +1 -1
- package/dist/{CustomerLayout-V5Y6I7QT.js → CustomerLayout-PWGNLADY.js} +5 -5
- package/dist/{CustomerLayout-V5Y6I7QT.js.map → CustomerLayout-PWGNLADY.js.map} +1 -1
- package/dist/{Footer-FT6ZOWK4.js → Footer-YX7RLK3U.js} +5 -5
- package/dist/{Footer-FT6ZOWK4.js.map → Footer-YX7RLK3U.js.map} +1 -1
- package/dist/{Header-EHXJSA2M.js → Header-YI566AQE.js} +4 -4
- package/dist/{Header-EHXJSA2M.js.map → Header-YI566AQE.js.map} +1 -1
- package/dist/{LoyaltyPage-ZEPAJWBL.js → LoyaltyPage-YXFWTXL7.js} +5 -5
- package/dist/{LoyaltyPage-ZEPAJWBL.js.map → LoyaltyPage-YXFWTXL7.js.map} +1 -1
- package/dist/{MainMenu-62DJ2TLV.js → MainMenu-IN45PQ63.js} +3 -3
- package/dist/{MainMenu-62DJ2TLV.js.map → MainMenu-IN45PQ63.js.map} +1 -1
- package/dist/{MasterLayout-7MMMKDNO.js → MasterLayout-GH6BJHKJ.js} +5 -5
- package/dist/{MasterLayout-7MMMKDNO.js.map → MasterLayout-GH6BJHKJ.js.map} +1 -1
- package/dist/{MobileMenu-RR7QCX7D.js → MobileMenu-DP7XKAHD.js} +5 -5
- package/dist/{MobileMenu-RR7QCX7D.js.map → MobileMenu-DP7XKAHD.js.map} +1 -1
- package/dist/{NotificationsPage-R46LMGTU.js → NotificationsPage-2KYGUEWO.js} +5 -5
- package/dist/{NotificationsPage-R46LMGTU.js.map → NotificationsPage-2KYGUEWO.js.map} +1 -1
- package/dist/{OrderSinglePage-33ZLFV46.js → OrderSinglePage-5DLIFOEY.js} +9 -9
- package/dist/OrderSinglePage-5DLIFOEY.js.map +1 -0
- package/dist/{OrdersPage-X6G6XF7R.js → OrdersPage-ZZQQE7BD.js} +5 -5
- package/dist/{OrdersPage-X6G6XF7R.js.map → OrdersPage-ZZQQE7BD.js.map} +1 -1
- package/dist/{PageSingle-2DAWIAF3.js → PageSingle-FQFOMMCJ.js} +3 -3
- package/dist/{PageSingle-2DAWIAF3.js.map → PageSingle-FQFOMMCJ.js.map} +1 -1
- package/dist/{ProductDetails-YCCGVGEN.js → ProductDetails-JZIAPA4D.js} +3 -3
- package/dist/{ProductDetails-YCCGVGEN.js.map → ProductDetails-JZIAPA4D.js.map} +1 -1
- package/dist/{ProfilePage-QY3NG3QL.js → ProfilePage-TUZM3MU3.js} +5 -5
- package/dist/{ProfilePage-QY3NG3QL.js.map → ProfilePage-TUZM3MU3.js.map} +1 -1
- package/dist/{SeoCartWidget-ARXWFPJ7.js → SeoCartWidget-UP5Z7TZI.js} +5 -5
- package/dist/{SeoCartWidget-ARXWFPJ7.js.map → SeoCartWidget-UP5Z7TZI.js.map} +1 -1
- package/dist/{SettingsPage-3VSOSHBS.js → SettingsPage-YTFFTHXC.js} +5 -5
- package/dist/{SettingsPage-3VSOSHBS.js.map → SettingsPage-YTFFTHXC.js.map} +1 -1
- package/dist/{StoreClosedNotification-5MN5QRZW.js → StoreClosedNotification-M6T32QWD.js} +6 -6
- package/dist/{StoreClosedNotification-5MN5QRZW.js.map → StoreClosedNotification-M6T32QWD.js.map} +1 -1
- package/dist/{TestimonialsPage-L2K33CLM.js → TestimonialsPage-LPXBMAF2.js} +3 -3
- package/dist/{TestimonialsPage-L2K33CLM.js.map → TestimonialsPage-LPXBMAF2.js.map} +1 -1
- package/dist/{ThankYouPage-3R4KA3BG.js → ThankYouPage-TVGZNYNM.js} +5 -5
- package/dist/{ThankYouPage-3R4KA3BG.js.map → ThankYouPage-TVGZNYNM.js.map} +1 -1
- package/dist/{WalletPage-VICZHQ4Z.js → WalletPage-SXXB4AI5.js} +5 -5
- package/dist/{WalletPage-VICZHQ4Z.js.map → WalletPage-SXXB4AI5.js.map} +1 -1
- package/dist/{WishlistPage-3ZS7RK3B.js → WishlistPage-NMNAOOU7.js} +5 -5
- package/dist/{WishlistPage-3ZS7RK3B.js.map → WishlistPage-NMNAOOU7.js.map} +1 -1
- package/dist/chunk-45IXSF4U.js +14 -0
- package/dist/{chunk-G3DZLRE7.js.map → chunk-45IXSF4U.js.map} +1 -1
- package/dist/{chunk-ACILA7G4.js → chunk-4WJ4XWX6.js} +3 -3
- package/dist/{chunk-ACILA7G4.js.map → chunk-4WJ4XWX6.js.map} +1 -1
- package/dist/{chunk-K7CYKUB4.js → chunk-4X36DPHZ.js} +7 -7
- package/dist/{chunk-K7CYKUB4.js.map → chunk-4X36DPHZ.js.map} +1 -1
- package/dist/{chunk-WFZB6WNU.js → chunk-5555H5JU.js} +3 -3
- package/dist/{chunk-WFZB6WNU.js.map → chunk-5555H5JU.js.map} +1 -1
- package/dist/{chunk-4WPUOY43.js → chunk-7JM6SHWE.js} +4 -4
- package/dist/{chunk-4WPUOY43.js.map → chunk-7JM6SHWE.js.map} +1 -1
- package/dist/{chunk-W6XHHZXP.js → chunk-D2PEQXEE.js} +3 -3
- package/dist/{chunk-W6XHHZXP.js.map → chunk-D2PEQXEE.js.map} +1 -1
- package/dist/{chunk-GDYTDRQS.js → chunk-GGXPIZ6F.js} +5 -5
- package/dist/{chunk-GDYTDRQS.js.map → chunk-GGXPIZ6F.js.map} +1 -1
- package/dist/{chunk-ABLOTMQW.js → chunk-L2AHASYC.js} +3 -3
- package/dist/{chunk-ABLOTMQW.js.map → chunk-L2AHASYC.js.map} +1 -1
- package/dist/{chunk-AHW3CCWQ.js → chunk-NJTOELGM.js} +6 -6
- package/dist/{chunk-AHW3CCWQ.js.map → chunk-NJTOELGM.js.map} +1 -1
- package/dist/{chunk-O4AHRRHE.js → chunk-V5733JK2.js} +4 -4
- package/dist/{chunk-O4AHRRHE.js.map → chunk-V5733JK2.js.map} +1 -1
- package/dist/{chunk-CWCFBRUA.js → chunk-Z2PWQVVX.js} +4 -4
- package/dist/{chunk-CWCFBRUA.js.map → chunk-Z2PWQVVX.js.map} +1 -1
- package/dist/components/cart/index.js +1 -1
- package/dist/components/common/index.js +1 -1
- package/dist/components/drawer/index.js +3 -3
- package/dist/components/home/index.js +5 -5
- package/dist/components/layout/index.js +5 -5
- package/dist/components/product/index.js +4 -4
- package/dist/components/store/index.js +5 -5
- package/dist/{document-class-UVI3RVQT.js → document-class-NKH24IV6.js} +3 -3
- package/dist/{document-class-UVI3RVQT.js.map → document-class-NKH24IV6.js.map} +1 -1
- package/dist/hooks/index.js +3 -3
- package/dist/hooks/useGtm.js +3 -3
- package/dist/hooks/useMoney.js +3 -3
- package/dist/hooks/useStore.js +3 -3
- package/dist/index.js +3 -3
- package/dist/{not-found-IKZRBSTP.js → not-found-GXVXLWBL.js} +5 -5
- package/dist/{not-found-IKZRBSTP.js.map → not-found-GXVXLWBL.js.map} +1 -1
- package/dist/providers/index.js +3 -3
- package/dist/routes/account/orders/OrderSinglePage.d.ts.map +1 -1
- package/dist/routes/account/orders.js +1 -1
- package/dist/routes/account.js +6 -6
- package/dist/routes/blog.js +5 -5
- package/dist/routes/brands.js +1 -1
- package/dist/routes/cart.js +7 -7
- package/dist/routes/home.js +6 -6
- package/dist/routes/loyalty.js +1 -1
- package/dist/routes/page.js +1 -1
- package/dist/routes/product-listing.js +5 -5
- package/dist/routes/product.js +5 -5
- package/dist/routes/testimonials.js +1 -1
- package/dist/routes/thank-you.js +1 -1
- package/dist/skeleton.js +6 -6
- package/dist/tanstack.js +2 -2
- package/package.json +1 -1
- package/dist/OrderSinglePage-33ZLFV46.js.map +0 -1
- package/dist/chunk-G3DZLRE7.js +0 -14
package/README.md
CHANGED
|
@@ -1,77 +1,123 @@
|
|
|
1
1
|
# @salla.sa/twilight-theme-engine
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The SDK behind Salla React themes. It ships the storefront routes, components, hooks, API
|
|
4
|
+
clients, and the Vite plugin that a theme composes — so a theme is a small app, not a fork of a
|
|
5
|
+
storefront.
|
|
6
|
+
|
|
7
|
+
Built for [TanStack Start](https://tanstack.com/start), server-rendered at the edge.
|
|
4
8
|
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
11
|
+
You normally don't install this yourself — `salla theme create --type react` scaffolds a theme
|
|
12
|
+
that already depends on it.
|
|
13
|
+
|
|
7
14
|
```bash
|
|
8
|
-
|
|
15
|
+
pnpm add @salla.sa/twilight-theme-engine
|
|
9
16
|
```
|
|
10
17
|
|
|
11
|
-
|
|
18
|
+
Peer dependencies are pinned to **tilde ranges** (`~1.166.2` for `@tanstack/*`, `vite ^8.1.5`,
|
|
19
|
+
`react ^19.2.4`). The engine's `dist` references `@tanstack/react-start` internals, so drifting
|
|
20
|
+
outside the tested minor breaks SSR at runtime. Let the install warn you rather than forcing a
|
|
21
|
+
resolution.
|
|
22
|
+
|
|
23
|
+
## What's in it
|
|
12
24
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
| Area | What it gives you |
|
|
26
|
+
| -------------- | ---------------------------------------------------------------------------- |
|
|
27
|
+
| **Routes** | Ready-made storefront pages — product, cart, category, blog, `/account/*`, … |
|
|
28
|
+
| **Components** | Header/Footer, product, cart, home blocks, modal/drawer/dropdown primitives |
|
|
29
|
+
| **Hooks** | `useStore`, `useTheme`, `useUser`, `useMoney`, `useAsset`, `useWishlist`, … |
|
|
30
|
+
| **Registry** | Swap any registered component by name |
|
|
31
|
+
| **Hook slots** | Inject content at defined extension points |
|
|
32
|
+
| **API** | Typed clients for the Salla store API, for use in SSR loaders |
|
|
33
|
+
| **i18n** | `react-i18next` integration, Arabic/RTL first |
|
|
34
|
+
| **Tooling** | Vite plugin (route generation, virtual modules), ESLint config, SSR runtime |
|
|
18
35
|
|
|
19
36
|
## Documentation
|
|
20
37
|
|
|
21
|
-
- [
|
|
38
|
+
Theme-facing guides live in [`docs/`](../../docs) at the repo root — start with the
|
|
39
|
+
[Getting Started track](../../docs/getting-started/README.md) or the
|
|
40
|
+
[Architecture Overview](../../docs/00-overview.md).
|
|
41
|
+
|
|
42
|
+
Engine-internal deep dives are in [`docs/`](./docs) here:
|
|
43
|
+
|
|
44
|
+
| Document | Topic |
|
|
45
|
+
| --------------------------------------------------------------- | -------------------------------------------------- |
|
|
46
|
+
| [HOME_COMPONENTS.md](./docs/HOME_COMPONENTS.md) | Home component system and the `data` prop contract |
|
|
47
|
+
| [usePageConfig.md](./docs/usePageConfig.md) | Unified page configuration |
|
|
48
|
+
| [useLocation.md](./docs/useLocation.md) | Location and query-param handling |
|
|
49
|
+
| [router-context.md](./docs/router-context.md) | Request-scoped context across SSR and CSR |
|
|
50
|
+
| [route-ids.md](./docs/route-ids.md) | Route identifiers |
|
|
51
|
+
| [route-pagination.md](./docs/route-pagination.md) | Pagination in loaders |
|
|
52
|
+
| [ProductCard.md](./docs/ProductCard.md) | The `ProductCard` contract |
|
|
53
|
+
| [gtm-integration.md](./docs/gtm-integration.md) | Google Tag Manager |
|
|
54
|
+
| [i18n-instance-lifecycle.md](./docs/i18n-instance-lifecycle.md) | How the i18n instance is created and shared |
|
|
55
|
+
| [type-improvement-guide.md](./docs/type-improvement-guide.md) | Typing conventions |
|
|
56
|
+
|
|
57
|
+
Subsystem notes: [`src/api/README.md`](./src/api/README.md),
|
|
58
|
+
[`src/vite/README.md`](./src/vite/README.md), [`tests/README.md`](./tests/README.md).
|
|
59
|
+
|
|
60
|
+
## Usage
|
|
61
|
+
|
|
62
|
+
### Wiring the engine into a theme
|
|
63
|
+
|
|
64
|
+
Two files do it. `app/start.ts` installs the request middleware:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { createStart } from '@tanstack/react-start';
|
|
68
|
+
import { twilightMiddleware, earlyHintsMiddleware } from '@salla.sa/twilight-theme-engine/tanstack';
|
|
22
69
|
|
|
23
|
-
|
|
70
|
+
export const startInstance = createStart(() => {
|
|
71
|
+
return {
|
|
72
|
+
requestMiddleware: [twilightMiddleware(), earlyHintsMiddleware()],
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
```
|
|
24
76
|
|
|
25
|
-
|
|
77
|
+
`app/routes/__root.tsx` builds the root route and renders the provider:
|
|
26
78
|
|
|
27
79
|
```tsx
|
|
28
80
|
import { TwilightProvider } from '@salla.sa/twilight-theme-engine';
|
|
29
|
-
import {
|
|
81
|
+
import { createTwilightRootRoute } from '@salla.sa/twilight-theme-engine/tanstack';
|
|
82
|
+
import themeTranslations from 'virtual:twilight/theme-translations';
|
|
30
83
|
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<TwilightProvider storeIdentifier="my-store" defaultLocale="ar">
|
|
34
|
-
<I18nProvider locale="ar" translations={translations}>
|
|
35
|
-
{children}
|
|
36
|
-
</I18nProvider>
|
|
37
|
-
</TwilightProvider>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
84
|
+
export const Route = createTwilightRootRoute()({ shellComponent: RootComponent });
|
|
40
85
|
```
|
|
41
86
|
|
|
42
|
-
|
|
87
|
+
`<TwilightProvider>` takes the bundled `translations` (plus optional `debug`, `skeleton`,
|
|
88
|
+
`onReady`, `onError`). Store, locale, and user are **not** props — the middleware resolves them
|
|
89
|
+
per request.
|
|
43
90
|
|
|
44
|
-
|
|
45
|
-
import { registry, Component, defineComponent } from '@salla.sa/twilight-theme-engine';
|
|
91
|
+
### Component registry
|
|
46
92
|
|
|
47
|
-
|
|
48
|
-
registry.
|
|
49
|
-
registry.register('product.card', ProductCard);
|
|
93
|
+
```tsx
|
|
94
|
+
import { registry, Component } from '@salla.sa/twilight-theme-engine';
|
|
50
95
|
|
|
51
|
-
|
|
52
|
-
registry.override('
|
|
96
|
+
registry.register('product:card', ProductCard);
|
|
97
|
+
registry.override('product:card', MyProductCard);
|
|
53
98
|
|
|
54
|
-
|
|
55
|
-
<Component name="product.card" product={product} />;
|
|
99
|
+
<Component name="product:card" product={product} />;
|
|
56
100
|
```
|
|
57
101
|
|
|
58
|
-
|
|
102
|
+
Keys are **colon**-separated, and the engine only resolves three of them: `product:card`, the
|
|
103
|
+
`home:*` blocks (via `registerHomeComponents()`), and `account:layout-pending`. Overriding any
|
|
104
|
+
other name is a silent no-op — everything else is imported directly.
|
|
105
|
+
|
|
106
|
+
### Hook slots
|
|
59
107
|
|
|
60
108
|
```tsx
|
|
61
109
|
import { defineHooks } from '@salla.sa/twilight-theme-engine/hooks/HookRegistry';
|
|
62
110
|
import { HookSlot } from '@salla.sa/twilight-theme-engine/hooks/HookSlot';
|
|
63
111
|
|
|
64
|
-
// Define hooks
|
|
65
112
|
defineHooks({
|
|
66
113
|
'body:start': () => <AnnouncementBar />,
|
|
67
|
-
'product:form.end': ({ product }) => <TrustBadges />,
|
|
114
|
+
'product:form.end': ({ product }) => <TrustBadges product={product} />,
|
|
68
115
|
});
|
|
69
116
|
|
|
70
|
-
// Use in pages
|
|
71
117
|
<HookSlot name="product:form.end" context={{ product }} />;
|
|
72
118
|
```
|
|
73
119
|
|
|
74
|
-
###
|
|
120
|
+
### Store, theme, and user
|
|
75
121
|
|
|
76
122
|
```tsx
|
|
77
123
|
import { useStore } from '@salla.sa/twilight-theme-engine/hooks/useStore';
|
|
@@ -80,86 +126,128 @@ import { useTwilight } from '@salla.sa/twilight-theme-engine';
|
|
|
80
126
|
|
|
81
127
|
function MyComponent() {
|
|
82
128
|
const store = useStore();
|
|
83
|
-
const
|
|
84
|
-
const { user
|
|
129
|
+
const { color, font, settings, isRTL } = useTheme();
|
|
130
|
+
const { user } = useTwilight();
|
|
85
131
|
|
|
86
|
-
const
|
|
132
|
+
const isDark = settings?.footer_is_dark ?? false;
|
|
87
133
|
}
|
|
88
134
|
```
|
|
89
135
|
|
|
136
|
+
> Settings are a plain object — read them with `?.` and your own default. There is no
|
|
137
|
+
> `settings.get()`.
|
|
138
|
+
|
|
90
139
|
### Translations
|
|
91
140
|
|
|
92
141
|
```tsx
|
|
93
|
-
import {
|
|
142
|
+
import { useTranslation } from '@salla.sa/twilight-theme-engine/i18n';
|
|
94
143
|
|
|
95
144
|
function MyComponent() {
|
|
96
|
-
const { t } =
|
|
145
|
+
const { t, locale, isRTL } = useTranslation();
|
|
97
146
|
|
|
98
147
|
return (
|
|
99
|
-
|
|
148
|
+
<>
|
|
100
149
|
<h1>{t('pages.cart.title')}</h1>
|
|
101
150
|
<p>{t('pages.products.sold_times', { count: 5 })}</p>
|
|
102
|
-
|
|
151
|
+
</>
|
|
103
152
|
);
|
|
104
153
|
}
|
|
105
154
|
```
|
|
106
155
|
|
|
107
|
-
|
|
156
|
+
`useTranslation()` returns `react-i18next`'s `t`, `i18n`, and `ready`, plus locale info
|
|
157
|
+
(`locale`, `direction`, `isRTL`, `isLTR`, `languageName`). The `/i18n` subpath also exports
|
|
158
|
+
`I18nProvider`, `FALLBACK_LOCALE`, `SUPPORTED_LOCALES`, `RTL_LOCALES`, `isLocale`, and
|
|
159
|
+
`getLanguageInfo`.
|
|
160
|
+
|
|
161
|
+
### Money and assets
|
|
108
162
|
|
|
109
163
|
```tsx
|
|
110
164
|
import { useMoney } from '@salla.sa/twilight-theme-engine/hooks/useMoney';
|
|
111
165
|
import { useAsset } from '@salla.sa/twilight-theme-engine/hooks/useAsset';
|
|
112
166
|
|
|
113
|
-
function
|
|
114
|
-
const {
|
|
115
|
-
const {
|
|
167
|
+
function ProductPrice({ product }) {
|
|
168
|
+
const { format } = useMoney(); // also: parse, isValid
|
|
169
|
+
const { cdn } = useAsset(); // also: asset, isPlaceholder
|
|
116
170
|
|
|
117
171
|
return (
|
|
118
|
-
<div
|
|
119
|
-
<img src={cdn(product.image.url, 400)} />
|
|
120
|
-
<p>{
|
|
172
|
+
<div>
|
|
173
|
+
<img src={cdn(product.image.url, 400)} alt="" loading="lazy" />
|
|
174
|
+
<p>{format(product.price)}</p>
|
|
121
175
|
</div>
|
|
122
176
|
);
|
|
123
177
|
}
|
|
124
178
|
```
|
|
125
179
|
|
|
126
|
-
|
|
180
|
+
`format()` returns a `ReactNode` (not a string) — it renders the currency symbol as markup.
|
|
127
181
|
|
|
128
|
-
|
|
182
|
+
## Import paths
|
|
183
|
+
|
|
184
|
+
The engine has ~90 subpath exports. Import from the narrowest one so bundles stay small:
|
|
129
185
|
|
|
130
186
|
```tsx
|
|
131
|
-
// Core
|
|
132
|
-
import {
|
|
187
|
+
// Core — provider, registry, context
|
|
188
|
+
import {
|
|
189
|
+
TwilightProvider,
|
|
190
|
+
useTwilight,
|
|
191
|
+
registry,
|
|
192
|
+
Component,
|
|
193
|
+
} from '@salla.sa/twilight-theme-engine';
|
|
133
194
|
|
|
134
|
-
// Hooks
|
|
195
|
+
// Hooks — one subpath each
|
|
135
196
|
import { useStore } from '@salla.sa/twilight-theme-engine/hooks/useStore';
|
|
136
|
-
import { useTheme } from '@salla.sa/twilight-theme-engine/hooks/useTheme';
|
|
137
197
|
import { useMoney } from '@salla.sa/twilight-theme-engine/hooks/useMoney';
|
|
138
|
-
import { useAsset } from '@salla.sa/twilight-theme-engine/hooks/useAsset';
|
|
139
198
|
|
|
140
199
|
// i18n
|
|
141
|
-
import {
|
|
142
|
-
useI18n,
|
|
143
|
-
I18nProvider,
|
|
144
|
-
FALLBACK_LOCALE,
|
|
145
|
-
getLanguageInfo,
|
|
146
|
-
} from '@salla.sa/twilight-theme-engine/i18n';
|
|
200
|
+
import { useTranslation, I18nProvider } from '@salla.sa/twilight-theme-engine/i18n';
|
|
147
201
|
|
|
148
|
-
// Components
|
|
202
|
+
// Components — grouped by domain
|
|
149
203
|
import { Link } from '@salla.sa/twilight-theme-engine/common';
|
|
204
|
+
import { Header, Footer } from '@salla.sa/twilight-theme-engine/layout';
|
|
205
|
+
import { CartItem, CartSummary } from '@salla.sa/twilight-theme-engine/cart';
|
|
206
|
+
import { ProductCard } from '@salla.sa/twilight-theme-engine/product';
|
|
150
207
|
|
|
151
208
|
// Routes
|
|
152
|
-
import { Home } from '@salla.sa/twilight-theme-engine/routes/home';
|
|
153
|
-
import type { HomeLoaderData } from '@salla.sa/twilight-theme-engine/routes/home';
|
|
209
|
+
import { Home, DefaultHomeComponents } from '@salla.sa/twilight-theme-engine/routes/home';
|
|
154
210
|
|
|
155
|
-
// API
|
|
211
|
+
// API clients — for loaders
|
|
156
212
|
import { store } from '@salla.sa/twilight-theme-engine/api/store';
|
|
157
|
-
|
|
213
|
+
|
|
214
|
+
// TanStack integration
|
|
215
|
+
import { createRouter, createTwilightRootRoute } from '@salla.sa/twilight-theme-engine/tanstack';
|
|
158
216
|
|
|
159
217
|
// Types
|
|
160
218
|
import type { Store, Theme, Product } from '@salla.sa/twilight-theme-engine/types';
|
|
161
219
|
```
|
|
162
220
|
|
|
221
|
+
The authoritative list is the `exports` field of [`package.json`](./package.json). Never deep-import
|
|
222
|
+
into `dist/` — those paths aren't part of the public API.
|
|
223
|
+
|
|
224
|
+
## Development
|
|
225
|
+
|
|
226
|
+
From the repo root:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
pnpm --filter @salla.sa/twilight-theme-engine build # tsup + tsc + dts stubs
|
|
230
|
+
pnpm --filter @salla.sa/twilight-theme-engine test
|
|
231
|
+
pnpm --filter @salla.sa/twilight-theme-engine test:coverage
|
|
232
|
+
pnpm --filter @salla.sa/twilight-theme-engine typecheck
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
| Command | Description |
|
|
236
|
+
| ---------------- | ---------------------------------------------------------------- |
|
|
237
|
+
| `pnpm build` | Bundle, add JS extensions, emit declarations and ambient `.d.ts` |
|
|
238
|
+
| `pnpm dev` | `tsup --watch` |
|
|
239
|
+
| `pnpm test` | Vitest (`test:watch`, `test:coverage`, `test:ci`) |
|
|
240
|
+
| `pnpm typecheck` | `tsc --noEmit` |
|
|
241
|
+
| `pnpm clean` | Remove `dist/` |
|
|
242
|
+
|
|
243
|
+
The themes consume `dist/`, so **build the engine before running or type-checking a theme.**
|
|
244
|
+
|
|
245
|
+
Adding a new public export means adding a subpath to `exports` — otherwise consumers can't
|
|
246
|
+
reach it. Verify a change survives publishing by installing Tania standalone
|
|
247
|
+
([why](../theme-tania/README.md#verifying-standalone-consumption)).
|
|
248
|
+
|
|
249
|
+
Testing conventions, including the SSR-vs-browser split, are in [`tests/README.md`](./tests/README.md).
|
|
250
|
+
|
|
163
251
|
## License
|
|
164
252
|
|
|
165
253
|
MIT
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LazyCurrencySymbol } from './chunk-
|
|
1
|
+
import { LazyCurrencySymbol } from './chunk-L2AHASYC.js';
|
|
2
2
|
import './chunk-AXW67SY7.js';
|
|
3
3
|
import './chunk-BYMOPN2S.js';
|
|
4
4
|
import './chunk-DGUM43GV.js';
|
|
@@ -299,5 +299,5 @@ function AddToCartForm({
|
|
|
299
299
|
}
|
|
300
300
|
|
|
301
301
|
export { AddToCartForm };
|
|
302
|
-
//# sourceMappingURL=AddToCartForm-
|
|
303
|
-
//# sourceMappingURL=AddToCartForm-
|
|
302
|
+
//# sourceMappingURL=AddToCartForm-KBJ5Q3KB.js.map
|
|
303
|
+
//# sourceMappingURL=AddToCartForm-KBJ5Q3KB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/product/AddToCartForm.tsx"],"names":["SallaProductOptions"],"mappings":"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","file":"AddToCartForm-4KYCJ2UZ.js","sourcesContent":["import { SallaAddProductButton } from '@salla.sa/twilight-components-react/add-product-button';\nimport { SallaButton } from '@salla.sa/twilight-components-react/button';\nimport { SallaCountDown } from '@salla.sa/twilight-components-react/count-down';\nimport { SallaFileUpload } from '@salla.sa/twilight-components-react/file-upload';\nimport { SallaGifting } from '@salla.sa/twilight-components-react/gifting';\nimport { SallaMultipleBundleProduct } from '@salla.sa/twilight-components-react/multiple-bundle-product';\n// Use the eager (non-deferred) Core export: product options are an essential form\n// control, and the deferred wrapper's visibility-triggered hydration races with the\n// gallery's image layout shift and gets stuck on the skeleton, so options never appear.\nimport { SallaProductOptionsCore as SallaProductOptions } from '@salla.sa/twilight-components-react/product-options';\nimport { SallaProductSizeGuide } from '@salla.sa/twilight-components-react/product-size-guide';\nimport { SallaQuantityInput } from '@salla.sa/twilight-components-react/quantity-input';\nimport { useTranslation } from '@salla.sa/twilight-theme-engine/i18n';\nimport type { ReactNode } from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport type { Product } from '../../types';\nimport { CurrencySymbol } from '../common';\n\ninterface AddToCartFormProps {\n product: Product;\n stickyAddToCart?: boolean;\n giftingIntro?: string;\n formStartSlot?: ReactNode;\n formEndSlot?: ReactNode;\n}\n\nconst handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n window.salla?.form.onSubmit('cart.addItem', e);\n};\n\nconst handleChange = (e: React.FormEvent<HTMLFormElement>) => {\n const form = e.currentTarget;\n if (form.reportValidity()) {\n window.salla?.product?.getPrice(new FormData(form));\n }\n};\n\nexport function AddToCartForm({\n product,\n stickyAddToCart,\n giftingIntro,\n formStartSlot,\n formEndSlot,\n}: AddToCartFormProps) {\n const { t } = useTranslation();\n const [activeCollapse, setActiveCollapse] = useState<string | null>(null);\n\n // stable ref: an inline arrow re-runs on every render and resets the user's selection\n const optionsRef = useCallback(\n (el: { setOptionsData?: (data: never[]) => void } | null) =>\n void el?.setOptionsData?.(product.options as never[]),\n [product.options]\n );\n\n // salla-product-options reads its `options` prop only in its constructor (no\n // @Watch), and on first load that constructor runs before sdk.init has set\n // page.id — so its getDetails(page.id) fallback fetches nothing and the options\n // never reflect. Seed page.id (=== product.id) and wait for the SDK to be ready\n // before mounting the element so its fallback resolves on first load too.\n const [optionsReady, setOptionsReady] = useState(false);\n useEffect(() => {\n const salla = window.salla;\n if (!salla) return;\n let alive = true;\n salla.config?.set?.('page.id', product.id);\n Promise.resolve(salla.onReady?.()).finally(() => {\n if (alive) setOptionsReady(true);\n });\n return () => {\n alive = false;\n };\n }, [product.id]);\n\n const handleCollapseToggle = useCallback((id: string) => {\n setActiveCollapse((current) => (current === id ? null : id));\n }, []);\n\n const hasPreorder = product.has_preorder_campaign && product.preorder;\n const hasWeightOrSizeGuide = product.weight || product.has_size_guide;\n const hasAttachments = product.can_add_note || product.can_upload_file;\n\n return (\n <form\n className=\"form product-form\"\n encType=\"multipart/form-data\"\n method=\"post\"\n onSubmit={handleSubmit}\n onChange={handleChange}\n >\n <input type=\"hidden\" name=\"id\" value={product.id} />\n\n {formStartSlot}\n\n {optionsReady && product.options && product.options.length > 0 && (\n <SallaProductOptions\n key={product.id}\n // constructor-only options parse: push data via ref on client remount\n ref={optionsRef}\n options={JSON.stringify(product.options)}\n productId={product.id}\n />\n )}\n\n {product.has_bundle_products && (\n <SallaMultipleBundleProduct bundleSections={JSON.stringify(product)} />\n )}\n\n {hasWeightOrSizeGuide && (\n <section className=\"bg-white p-5 rounded-md mb-5\">\n {product.weight && (\n <div\n className={`center-between ${product.has_size_guide ? 'pb-5 mb-5 border-b-[1px]' : ''}`}\n >\n <b className=\"form-label rtl:space-x-reverse space-x-1\">\n <i className=\"sicon-luggage-cart\"></i>\n <span>{t('pages.products.weight', 'Weight')}</span>\n </b>\n <span className=\"product-weight text-sm\">{product.weight}</span>\n </div>\n )}\n {product.has_size_guide && (\n <>\n <div className=\"center-between\">\n <b className=\"form-label rtl:space-x-reverse space-x-1\">\n <i className=\"sicon-pencil-ruler\"></i>\n <span>{t('pages.products.size_guides', 'Size Guides')}</span>\n </b>\n <SallaButton\n shape=\"link\"\n color=\"primary\"\n className=\"!p-0 text-sm with-arrow\"\n onClick={() =>\n window.salla?.event?.dispatch('size-guide::open', String(product.id))\n }\n >\n {t('pages.products.show_size_guides', 'Show Size Guides')}\n <i className=\"sicon-keyboard_arrow_left\"></i>\n </SallaButton>\n </div>\n <SallaProductSizeGuide />\n </>\n )}\n </section>\n )}\n\n {hasAttachments && (\n <section className=\"bg-white p-5 rounded-md mb-5\">\n <div className=\"sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start\">\n <div className=\"form-label\">\n <b className=\"block\">{t('pages.products.attachments', 'Attachments')}</b>\n </div>\n <div className=\"mt-1 sm:mt-0 sm:col-span-2 text-end\">\n <div className=\"flex rtl:space-x-reverse space-x-3\">\n {product.can_add_note && (\n <button\n type=\"button\"\n onClick={() => handleCollapseToggle(`note_${product.id}`)}\n className={`btn-tab btn--collapse ${activeCollapse === `note_${product.id}` ? 'is-opened' : 'is-closed'}`}\n >\n <i className=\"font-medium sicon-chat-conversation-alt rtl:ml-1.5 ltr:mr-1.5\"></i>\n <span className=\"fix-align\">{t('pages.products.add_note', 'Add Note')}</span>\n </button>\n )}\n {product.can_upload_file && (\n <button\n type=\"button\"\n onClick={() => handleCollapseToggle(`file_${product.id}`)}\n className={`btn-tab btn--collapse ${activeCollapse === `file_${product.id}` ? 'is-opened' : 'is-closed'}`}\n >\n <i className=\"font-medium sicon-paperclip rtl:ml-1.5 ltr:mr-1.5\"></i>\n <span className=\"fix-align\">{t('pages.products.add_file', 'Add File')}</span>\n </button>\n )}\n </div>\n\n {product.can_add_note && (\n <div\n className={`collapse-content ${activeCollapse === `note_${product.id}` ? 'is-opened' : 'is-closed'}`}\n >\n <div className=\"pt-4\">\n <textarea\n className=\"animated animatedfadeInDown fadeInDown form-input h-16 bg-gray-50 block\"\n placeholder={t('pages.products.notes_placeholder', 'Add your notes here...')}\n name=\"notes\"\n cols={30}\n rows={10}\n defaultValue={product.notes}\n ></textarea>\n </div>\n </div>\n )}\n\n {product.can_upload_file && (\n <div\n className={`collapse-content ${activeCollapse === `file_${product.id}` ? 'is-opened' : 'is-closed'}`}\n >\n <div className=\"pt-4 px-1\">\n <SallaFileUpload\n accept=\"image/png, image/jpeg, image/jpg, image/gif, video/*, application/pdf\"\n className=\"product-option-uploader\"\n >\n <div className=\"product-option-uploader-placholder\">\n <span className=\"product-option-uploader-placholder-icon\">\n <i className=\"sicon-camera\"></i>\n </span>\n <p className=\"profile-filepond-placholder-text\">\n {t('common.uploader.drag_and_drop', 'Drag and drop files here')}\n </p>\n <span className=\"filepond--label-action\">\n {t('common.uploader.browse', 'Browse')}\n </span>\n </div>\n </SallaFileUpload>\n </div>\n </div>\n )}\n </div>\n </div>\n </section>\n )}\n\n {formEndSlot}\n\n <section className=\"flex bg-white p-5 sm:pb-0 rounded-md rounded-b-none\">\n <div className=\"center-between w-full\">\n <div className=\"form-label\">\n <b className=\"block\">{t('pages.products.price', 'Price')}</b>\n </div>\n\n <div\n className={`flex whitespace-nowrap price-wrapper gap-4 items-center ${product.is_out_of_stock ? 'hidden' : ''}`}\n >\n <div\n className={`price_is_on_sale space-x-2 rtl:space-x-reverse whitespace-nowrap ${product.is_on_sale ? '' : 'hidden'}`}\n >\n <span className=\"total-price text-red-800 font-bold text-xl inline-block\">\n {product.sale_price} <CurrencySymbol currency={product.currency} />\n </span>\n <span className=\"before-price text-gray-500 line-through\">\n {product.regular_price} <CurrencySymbol currency={product.currency} />\n </span>\n </div>\n <div\n className={`starting-or-normal-price gap-4 ${product.is_on_sale ? 'hidden' : 'flex'}`}\n >\n {product.starting_price && (\n <span className=\"starting-price-title\">\n {t('pages.products.starting_price', 'Starting from')}\n </span>\n )}\n <span className=\"total-price font-bold text-xl inline-block\">\n {String(product.starting_price ?? product.price)}{' '}\n <CurrencySymbol currency={product.currency} />\n </span>\n </div>\n </div>\n\n <div\n className={`out-of-stock min-h-7 leading-7 text-base text-red-600 !opacity-50 font-bold ${product.is_out_of_stock ? 'scale-pulse' : 'hidden'}`}\n >\n {t('pages.products.out_of_stock', 'Out of Stock')}\n </div>\n </div>\n </section>\n\n {hasPreorder ? (\n <section className=\"mt-5 p-5\">\n <SallaCountDown preOrder={JSON.stringify(product.preorder)} boxed labeled />\n </section>\n ) : null}\n\n <section className=\"sticky-product-bar bg-white p-5 rounded-md rounded-b-none\">\n {product.is_hidden_quantity || product.type === 'booking' ? (\n <input\n type=\"hidden\"\n value=\"1\"\n name=\"quantity\"\n aria-label={t('pages.products.quantity', 'Quantity')}\n />\n ) : (\n <div className=\"sticky-product-bar__quantity center-between mb-5\">\n <span className=\"form-label font-bold\">{t('pages.products.quantity', 'Quantity')}</span>\n <SallaQuantityInput\n max={product.max_quantity ?? undefined}\n value={1}\n name=\"quantity\"\n aria-label={t('pages.products.quantity', 'Quantity')}\n className=\"border-gray-200 flex justify-end\"\n />\n </div>\n )}\n\n <SallaAddProductButton\n {...(product.can_quick_buy ? { quickBuy: true } : {})}\n {...(stickyAddToCart ? { supportStickyBar: true } : {})}\n {...(product.is_require_shipping ? { requiredShipping: true } : {})}\n {...(hasPreorder ? { hasPreOrder: true } : {})}\n amount={\n typeof product.base_currency_price === 'object'\n ? product.base_currency_price.amount\n : product.base_currency_price\n }\n className=\"mt-5 w-full sticky-product-bar__btn\"\n productStatus={product.status}\n productType={product.type}\n productId={product.id}\n loaderPosition=\"end\"\n type=\"submit\"\n width=\"wide\"\n {...(product.notify_availability\n ? {\n ...(product.notify_availability.subscribed ? { isSubscribed: true } : {}),\n channels: product.notify_availability.channels.join(','),\n ...(product.notify_availability.subscribed_options\n ? {\n subscribedOptions: JSON.stringify(\n product.notify_availability.subscribed_options\n ),\n }\n : {}),\n ...(product.notify_availability.options ? { notifyOptionsAvailability: true } : {}),\n }\n : {})}\n >\n {product.add_to_cart_label}\n </SallaAddProductButton>\n </section>\n\n {product.giftable && (\n <SallaGifting\n className=\"mt-5\"\n widgetSubtitle={giftingIntro}\n productId={product.id}\n {...(product.is_require_shipping ? { physicalProducts: true } : {})}\n />\n )}\n </form>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/product/AddToCartForm.tsx"],"names":["SallaProductOptions"],"mappings":";;;;;;;;;;;;;;;;;AA0BA,IAAM,YAAA,GAAe,CAAC,CAAA,KAAuB;AAC3C,EAAA,CAAA,CAAE,cAAA,EAAe;AACjB,EAAA,MAAA,CAAO,KAAA,EAAO,IAAA,CAAK,QAAA,CAAS,cAAA,EAAgB,CAAC,CAAA;AAC/C,CAAA;AAEA,IAAM,YAAA,GAAe,CAAC,CAAA,KAAwC;AAC5D,EAAA,MAAM,OAAO,CAAA,CAAE,aAAA;AACf,EAAA,IAAI,IAAA,CAAK,gBAAe,EAAG;AACzB,IAAA,MAAA,CAAO,OAAO,OAAA,EAAS,QAAA,CAAS,IAAI,QAAA,CAAS,IAAI,CAAC,CAAA;AAAA,EACpD;AACF,CAAA;AAEO,SAAS,aAAA,CAAc;AAAA,EAC5B,OAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAA,EAAuB;AACrB,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAC7B,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,SAAwB,IAAI,CAAA;AAGxE,EAAA,MAAM,UAAA,GAAa,WAAA;AAAA,IACjB,CAAC,EAAA,KACC,KAAK,EAAA,EAAI,cAAA,GAAiB,QAAQ,OAAkB,CAAA;AAAA,IACtD,CAAC,QAAQ,OAAO;AAAA,GAClB;AAOA,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,SAAS,KAAK,CAAA;AACtD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,QAAQ,MAAA,CAAO,KAAA;AACrB,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,IAAI,KAAA,GAAQ,IAAA;AACZ,IAAA,KAAA,CAAM,MAAA,EAAQ,GAAA,GAAM,SAAA,EAAW,OAAA,CAAQ,EAAE,CAAA;AACzC,IAAA,OAAA,CAAQ,QAAQ,KAAA,CAAM,OAAA,IAAW,CAAA,CAAE,QAAQ,MAAM;AAC/C,MAAA,IAAI,KAAA,kBAAuB,IAAI,CAAA;AAAA,IACjC,CAAC,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAA,KAAA,GAAQ,KAAA;AAAA,IACV,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,OAAA,CAAQ,EAAE,CAAC,CAAA;AAEf,EAAA,MAAM,oBAAA,GAAuB,WAAA,CAAY,CAAC,EAAA,KAAe;AACvD,IAAA,iBAAA,CAAkB,CAAC,OAAA,KAAa,OAAA,KAAY,EAAA,GAAK,OAAO,EAAG,CAAA;AAAA,EAC7D,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,qBAAA,IAAyB,OAAA,CAAQ,QAAA;AAC7D,EAAA,MAAM,oBAAA,GAAuB,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,cAAA;AACvD,EAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,YAAA,IAAgB,OAAA,CAAQ,eAAA;AAEvD,EAAA,uBACE,IAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,mBAAA;AAAA,MACV,OAAA,EAAQ,qBAAA;AAAA,MACR,MAAA,EAAO,MAAA;AAAA,MACP,QAAA,EAAU,YAAA;AAAA,MACV,QAAA,EAAU,YAAA;AAAA,MAEV,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,WAAM,IAAA,EAAK,QAAA,EAAS,MAAK,IAAA,EAAK,KAAA,EAAO,QAAQ,EAAA,EAAI,CAAA;AAAA,QAEjD,aAAA;AAAA,QAEA,gBAAgB,OAAA,CAAQ,OAAA,IAAW,OAAA,CAAQ,OAAA,CAAQ,SAAS,CAAA,oBAC3D,GAAA;AAAA,UAACA,uBAAA;AAAA,UAAA;AAAA,YAGC,GAAA,EAAK,UAAA;AAAA,YACL,OAAA,EAAS,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,OAAO,CAAA;AAAA,YACvC,WAAW,OAAA,CAAQ;AAAA,WAAA;AAAA,UAJd,OAAA,CAAQ;AAAA,SAKf;AAAA,QAGD,OAAA,CAAQ,uCACP,GAAA,CAAC,0BAAA,EAAA,EAA2B,gBAAgB,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA,EAAG,CAAA;AAAA,QAGtE,oBAAA,oBACC,IAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,8BAAA,EAChB,QAAA,EAAA;AAAA,UAAA,OAAA,CAAQ,MAAA,oBACP,IAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,CAAA,eAAA,EAAkB,OAAA,CAAQ,cAAA,GAAiB,6BAA6B,EAAE,CAAA,CAAA;AAAA,cAErF,QAAA,EAAA;AAAA,gCAAA,IAAA,CAAC,GAAA,EAAA,EAAE,WAAU,0CAAA,EACX,QAAA,EAAA;AAAA,kCAAA,GAAA,CAAC,GAAA,EAAA,EAAE,WAAU,oBAAA,EAAqB,CAAA;AAAA,kCAClC,GAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,CAAA,CAAE,uBAAA,EAAyB,QAAQ,CAAA,EAAE;AAAA,iBAAA,EAC9C,CAAA;AAAA,gCACA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,wBAAA,EAA0B,kBAAQ,MAAA,EAAO;AAAA;AAAA;AAAA,WAC3D;AAAA,UAED,OAAA,CAAQ,kCACP,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,gBAAA,EACb,QAAA,EAAA;AAAA,8BAAA,IAAA,CAAC,GAAA,EAAA,EAAE,WAAU,0CAAA,EACX,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,GAAA,EAAA,EAAE,WAAU,oBAAA,EAAqB,CAAA;AAAA,gCAClC,GAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,CAAA,CAAE,4BAAA,EAA8B,aAAa,CAAA,EAAE;AAAA,eAAA,EACxD,CAAA;AAAA,8BACA,IAAA;AAAA,gBAAC,WAAA;AAAA,gBAAA;AAAA,kBACC,KAAA,EAAM,MAAA;AAAA,kBACN,KAAA,EAAM,SAAA;AAAA,kBACN,SAAA,EAAU,yBAAA;AAAA,kBACV,OAAA,EAAS,MACP,MAAA,CAAO,KAAA,EAAO,KAAA,EAAO,SAAS,kBAAA,EAAoB,MAAA,CAAO,OAAA,CAAQ,EAAE,CAAC,CAAA;AAAA,kBAGrE,QAAA,EAAA;AAAA,oBAAA,CAAA,CAAE,mCAAmC,kBAAkB,CAAA;AAAA,oCACxD,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,2BAAA,EAA4B;AAAA;AAAA;AAAA;AAC3C,aAAA,EACF,CAAA;AAAA,gCACC,qBAAA,EAAA,EAAsB;AAAA,WAAA,EACzB;AAAA,SAAA,EAEJ,CAAA;AAAA,QAGD,cAAA,wBACE,SAAA,EAAA,EAAQ,SAAA,EAAU,gCACjB,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,gDAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,YAAA,EACb,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,OAAA,EAAS,QAAA,EAAA,CAAA,CAAE,4BAAA,EAA8B,aAAa,CAAA,EAAE,CAAA,EACvE,CAAA;AAAA,0BACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qCAAA,EACb,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,oCAAA,EACZ,QAAA,EAAA;AAAA,cAAA,OAAA,CAAQ,YAAA,oBACP,IAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,IAAA,EAAK,QAAA;AAAA,kBACL,SAAS,MAAM,oBAAA,CAAqB,CAAA,KAAA,EAAQ,OAAA,CAAQ,EAAE,CAAA,CAAE,CAAA;AAAA,kBACxD,SAAA,EAAW,yBAAyB,cAAA,KAAmB,CAAA,KAAA,EAAQ,QAAQ,EAAE,CAAA,CAAA,GAAK,cAAc,WAAW,CAAA,CAAA;AAAA,kBAEvG,QAAA,EAAA;AAAA,oCAAA,GAAA,CAAC,GAAA,EAAA,EAAE,WAAU,+DAAA,EAAgE,CAAA;AAAA,wCAC5E,MAAA,EAAA,EAAK,SAAA,EAAU,aAAa,QAAA,EAAA,CAAA,CAAE,yBAAA,EAA2B,UAAU,CAAA,EAAE;AAAA;AAAA;AAAA,eACxE;AAAA,cAED,QAAQ,eAAA,oBACP,IAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,IAAA,EAAK,QAAA;AAAA,kBACL,SAAS,MAAM,oBAAA,CAAqB,CAAA,KAAA,EAAQ,OAAA,CAAQ,EAAE,CAAA,CAAE,CAAA;AAAA,kBACxD,SAAA,EAAW,yBAAyB,cAAA,KAAmB,CAAA,KAAA,EAAQ,QAAQ,EAAE,CAAA,CAAA,GAAK,cAAc,WAAW,CAAA,CAAA;AAAA,kBAEvG,QAAA,EAAA;AAAA,oCAAA,GAAA,CAAC,GAAA,EAAA,EAAE,WAAU,mDAAA,EAAoD,CAAA;AAAA,wCAChE,MAAA,EAAA,EAAK,SAAA,EAAU,aAAa,QAAA,EAAA,CAAA,CAAE,yBAAA,EAA2B,UAAU,CAAA,EAAE;AAAA;AAAA;AAAA;AACxE,aAAA,EAEJ,CAAA;AAAA,YAEC,QAAQ,YAAA,oBACP,GAAA;AAAA,cAAC,KAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAW,oBAAoB,cAAA,KAAmB,CAAA,KAAA,EAAQ,QAAQ,EAAE,CAAA,CAAA,GAAK,cAAc,WAAW,CAAA,CAAA;AAAA,gBAElG,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,MAAA,EACb,QAAA,kBAAA,GAAA;AAAA,kBAAC,UAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAU,yEAAA;AAAA,oBACV,WAAA,EAAa,CAAA,CAAE,kCAAA,EAAoC,wBAAwB,CAAA;AAAA,oBAC3E,IAAA,EAAK,OAAA;AAAA,oBACL,IAAA,EAAM,EAAA;AAAA,oBACN,IAAA,EAAM,EAAA;AAAA,oBACN,cAAc,OAAA,CAAQ;AAAA;AAAA,iBACvB,EACH;AAAA;AAAA,aACF;AAAA,YAGD,QAAQ,eAAA,oBACP,GAAA;AAAA,cAAC,KAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAW,oBAAoB,cAAA,KAAmB,CAAA,KAAA,EAAQ,QAAQ,EAAE,CAAA,CAAA,GAAK,cAAc,WAAW,CAAA,CAAA;AAAA,gBAElG,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,kBAAA,GAAA;AAAA,kBAAC,eAAA;AAAA,kBAAA;AAAA,oBACC,MAAA,EAAO,uEAAA;AAAA,oBACP,SAAA,EAAU,yBAAA;AAAA,oBAEV,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oCAAA,EACb,QAAA,EAAA;AAAA,sCAAA,GAAA,CAAC,UAAK,SAAA,EAAU,yCAAA,EACd,8BAAC,GAAA,EAAA,EAAE,SAAA,EAAU,gBAAe,CAAA,EAC9B,CAAA;AAAA,0CACC,GAAA,EAAA,EAAE,SAAA,EAAU,oCACV,QAAA,EAAA,CAAA,CAAE,+BAAA,EAAiC,0BAA0B,CAAA,EAChE,CAAA;AAAA,0CACC,MAAA,EAAA,EAAK,SAAA,EAAU,0BACb,QAAA,EAAA,CAAA,CAAE,wBAAA,EAA0B,QAAQ,CAAA,EACvC;AAAA,qBAAA,EACF;AAAA;AAAA,iBACF,EACF;AAAA;AAAA;AACF,WAAA,EAEJ;AAAA,SAAA,EACF,CAAA,EACF,CAAA;AAAA,QAGD,WAAA;AAAA,4BAEA,SAAA,EAAA,EAAQ,SAAA,EAAU,uDACjB,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,uBAAA,EACb,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,YAAA,EACb,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,OAAA,EAAS,QAAA,EAAA,CAAA,CAAE,sBAAA,EAAwB,OAAO,CAAA,EAAE,CAAA,EAC3D,CAAA;AAAA,0BAEA,IAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,CAAA,wDAAA,EAA2D,OAAA,CAAQ,eAAA,GAAkB,WAAW,EAAE,CAAA,CAAA;AAAA,cAE7G,QAAA,EAAA;AAAA,gCAAA,IAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAW,CAAA,iEAAA,EAAoE,OAAA,CAAQ,UAAA,GAAa,KAAK,QAAQ,CAAA,CAAA;AAAA,oBAEjH,QAAA,EAAA;AAAA,sCAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,yDAAA,EACb,QAAA,EAAA;AAAA,wBAAA,OAAA,CAAQ,UAAA;AAAA,wBAAW,GAAA;AAAA,wCAAC,GAAA,CAAC,kBAAA,EAAA,EAAe,QAAA,EAAU,OAAA,CAAQ,QAAA,EAAU;AAAA,uBAAA,EACnE,CAAA;AAAA,sCACA,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yCAAA,EACb,QAAA,EAAA;AAAA,wBAAA,OAAA,CAAQ,aAAA;AAAA,wBAAc,GAAA;AAAA,wCAAC,GAAA,CAAC,kBAAA,EAAA,EAAe,QAAA,EAAU,OAAA,CAAQ,QAAA,EAAU;AAAA,uBAAA,EACtE;AAAA;AAAA;AAAA,iBACF;AAAA,gCACA,IAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAW,CAAA,+BAAA,EAAkC,OAAA,CAAQ,UAAA,GAAa,WAAW,MAAM,CAAA,CAAA;AAAA,oBAElF,QAAA,EAAA;AAAA,sBAAA,OAAA,CAAQ,cAAA,wBACN,MAAA,EAAA,EAAK,SAAA,EAAU,wBACb,QAAA,EAAA,CAAA,CAAE,+BAAA,EAAiC,eAAe,CAAA,EACrD,CAAA;AAAA,sCAEF,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,4CAAA,EACb,QAAA,EAAA;AAAA,wBAAA,MAAA,CAAO,OAAA,CAAQ,cAAA,IAAkB,OAAA,CAAQ,KAAK,CAAA;AAAA,wBAAG,GAAA;AAAA,wCAClD,GAAA,CAAC,kBAAA,EAAA,EAAe,QAAA,EAAU,OAAA,CAAQ,QAAA,EAAU;AAAA,uBAAA,EAC9C;AAAA;AAAA;AAAA;AACF;AAAA;AAAA,WACF;AAAA,0BAEA,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,CAAA,4EAAA,EAA+E,OAAA,CAAQ,eAAA,GAAkB,gBAAgB,QAAQ,CAAA,CAAA;AAAA,cAE3I,QAAA,EAAA,CAAA,CAAE,+BAA+B,cAAc;AAAA;AAAA;AAClD,SAAA,EACF,CAAA,EACF,CAAA;AAAA,QAEC,8BACC,GAAA,CAAC,SAAA,EAAA,EAAQ,WAAU,UAAA,EACjB,QAAA,kBAAA,GAAA,CAAC,kBAAe,QAAA,EAAU,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,QAAQ,CAAA,EAAG,KAAA,EAAK,MAAC,OAAA,EAAO,IAAA,EAAC,GAC5E,CAAA,GACE,IAAA;AAAA,wBAEJ,IAAA,CAAC,SAAA,EAAA,EAAQ,SAAA,EAAU,2DAAA,EAChB,QAAA,EAAA;AAAA,UAAA,OAAA,CAAQ,kBAAA,IAAsB,OAAA,CAAQ,IAAA,KAAS,SAAA,mBAC9C,GAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,KAAA,EAAM,GAAA;AAAA,cACN,IAAA,EAAK,UAAA;AAAA,cACL,YAAA,EAAY,CAAA,CAAE,yBAAA,EAA2B,UAAU;AAAA;AAAA,WACrD,mBAEA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kDAAA,EACb,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,UAAK,SAAA,EAAU,sBAAA,EAAwB,QAAA,EAAA,CAAA,CAAE,yBAAA,EAA2B,UAAU,CAAA,EAAE,CAAA;AAAA,4BACjF,GAAA;AAAA,cAAC,kBAAA;AAAA,cAAA;AAAA,gBACC,GAAA,EAAK,QAAQ,YAAA,IAAgB,MAAA;AAAA,gBAC7B,KAAA,EAAO,CAAA;AAAA,gBACP,IAAA,EAAK,UAAA;AAAA,gBACL,YAAA,EAAY,CAAA,CAAE,yBAAA,EAA2B,UAAU,CAAA;AAAA,gBACnD,SAAA,EAAU;AAAA;AAAA;AACZ,WAAA,EACF,CAAA;AAAA,0BAGF,GAAA;AAAA,YAAC,qBAAA;AAAA,YAAA;AAAA,cACE,GAAI,OAAA,CAAQ,aAAA,GAAgB,EAAE,QAAA,EAAU,IAAA,KAAS,EAAC;AAAA,cAClD,GAAI,eAAA,GAAkB,EAAE,gBAAA,EAAkB,IAAA,KAAS,EAAC;AAAA,cACpD,GAAI,OAAA,CAAQ,mBAAA,GAAsB,EAAE,gBAAA,EAAkB,IAAA,KAAS,EAAC;AAAA,cAChE,GAAI,WAAA,GAAc,EAAE,WAAA,EAAa,IAAA,KAAS,EAAC;AAAA,cAC5C,MAAA,EACE,OAAO,OAAA,CAAQ,mBAAA,KAAwB,WACnC,OAAA,CAAQ,mBAAA,CAAoB,SAC5B,OAAA,CAAQ,mBAAA;AAAA,cAEd,SAAA,EAAU,qCAAA;AAAA,cACV,eAAe,OAAA,CAAQ,MAAA;AAAA,cACvB,aAAa,OAAA,CAAQ,IAAA;AAAA,cACrB,WAAW,OAAA,CAAQ,EAAA;AAAA,cACnB,cAAA,EAAe,KAAA;AAAA,cACf,IAAA,EAAK,QAAA;AAAA,cACL,KAAA,EAAM,MAAA;AAAA,cACL,GAAI,QAAQ,mBAAA,GACT;AAAA,gBACE,GAAI,QAAQ,mBAAA,CAAoB,UAAA,GAAa,EAAE,YAAA,EAAc,IAAA,KAAS,EAAC;AAAA,gBACvE,QAAA,EAAU,OAAA,CAAQ,mBAAA,CAAoB,QAAA,CAAS,KAAK,GAAG,CAAA;AAAA,gBACvD,GAAI,OAAA,CAAQ,mBAAA,CAAoB,kBAAA,GAC5B;AAAA,kBACE,mBAAmB,IAAA,CAAK,SAAA;AAAA,oBACtB,QAAQ,mBAAA,CAAoB;AAAA;AAC9B,oBAEF,EAAC;AAAA,gBACL,GAAI,QAAQ,mBAAA,CAAoB,OAAA,GAAU,EAAE,yBAAA,EAA2B,IAAA,KAAS;AAAC,kBAEnF,EAAC;AAAA,cAEJ,QAAA,EAAA,OAAA,CAAQ;AAAA;AAAA;AACX,SAAA,EACF,CAAA;AAAA,QAEC,QAAQ,QAAA,oBACP,GAAA;AAAA,UAAC,YAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,MAAA;AAAA,YACV,cAAA,EAAgB,YAAA;AAAA,YAChB,WAAW,OAAA,CAAQ,EAAA;AAAA,YAClB,GAAI,OAAA,CAAQ,mBAAA,GAAsB,EAAE,gBAAA,EAAkB,IAAA,KAAS;AAAC;AAAA;AACnE;AAAA;AAAA,GAEJ;AAEJ","file":"AddToCartForm-KBJ5Q3KB.js","sourcesContent":["import { SallaAddProductButton } from '@salla.sa/twilight-components-react/add-product-button';\nimport { SallaButton } from '@salla.sa/twilight-components-react/button';\nimport { SallaCountDown } from '@salla.sa/twilight-components-react/count-down';\nimport { SallaFileUpload } from '@salla.sa/twilight-components-react/file-upload';\nimport { SallaGifting } from '@salla.sa/twilight-components-react/gifting';\nimport { SallaMultipleBundleProduct } from '@salla.sa/twilight-components-react/multiple-bundle-product';\n// Use the eager (non-deferred) Core export: product options are an essential form\n// control, and the deferred wrapper's visibility-triggered hydration races with the\n// gallery's image layout shift and gets stuck on the skeleton, so options never appear.\nimport { SallaProductOptionsCore as SallaProductOptions } from '@salla.sa/twilight-components-react/product-options';\nimport { SallaProductSizeGuide } from '@salla.sa/twilight-components-react/product-size-guide';\nimport { SallaQuantityInput } from '@salla.sa/twilight-components-react/quantity-input';\nimport { useTranslation } from '@salla.sa/twilight-theme-engine/i18n';\nimport type { ReactNode } from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport type { Product } from '../../types';\nimport { CurrencySymbol } from '../common';\n\ninterface AddToCartFormProps {\n product: Product;\n stickyAddToCart?: boolean;\n giftingIntro?: string;\n formStartSlot?: ReactNode;\n formEndSlot?: ReactNode;\n}\n\nconst handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n window.salla?.form.onSubmit('cart.addItem', e);\n};\n\nconst handleChange = (e: React.FormEvent<HTMLFormElement>) => {\n const form = e.currentTarget;\n if (form.reportValidity()) {\n window.salla?.product?.getPrice(new FormData(form));\n }\n};\n\nexport function AddToCartForm({\n product,\n stickyAddToCart,\n giftingIntro,\n formStartSlot,\n formEndSlot,\n}: AddToCartFormProps) {\n const { t } = useTranslation();\n const [activeCollapse, setActiveCollapse] = useState<string | null>(null);\n\n // stable ref: an inline arrow re-runs on every render and resets the user's selection\n const optionsRef = useCallback(\n (el: { setOptionsData?: (data: never[]) => void } | null) =>\n void el?.setOptionsData?.(product.options as never[]),\n [product.options]\n );\n\n // salla-product-options reads its `options` prop only in its constructor (no\n // @Watch), and on first load that constructor runs before sdk.init has set\n // page.id — so its getDetails(page.id) fallback fetches nothing and the options\n // never reflect. Seed page.id (=== product.id) and wait for the SDK to be ready\n // before mounting the element so its fallback resolves on first load too.\n const [optionsReady, setOptionsReady] = useState(false);\n useEffect(() => {\n const salla = window.salla;\n if (!salla) return;\n let alive = true;\n salla.config?.set?.('page.id', product.id);\n Promise.resolve(salla.onReady?.()).finally(() => {\n if (alive) setOptionsReady(true);\n });\n return () => {\n alive = false;\n };\n }, [product.id]);\n\n const handleCollapseToggle = useCallback((id: string) => {\n setActiveCollapse((current) => (current === id ? null : id));\n }, []);\n\n const hasPreorder = product.has_preorder_campaign && product.preorder;\n const hasWeightOrSizeGuide = product.weight || product.has_size_guide;\n const hasAttachments = product.can_add_note || product.can_upload_file;\n\n return (\n <form\n className=\"form product-form\"\n encType=\"multipart/form-data\"\n method=\"post\"\n onSubmit={handleSubmit}\n onChange={handleChange}\n >\n <input type=\"hidden\" name=\"id\" value={product.id} />\n\n {formStartSlot}\n\n {optionsReady && product.options && product.options.length > 0 && (\n <SallaProductOptions\n key={product.id}\n // constructor-only options parse: push data via ref on client remount\n ref={optionsRef}\n options={JSON.stringify(product.options)}\n productId={product.id}\n />\n )}\n\n {product.has_bundle_products && (\n <SallaMultipleBundleProduct bundleSections={JSON.stringify(product)} />\n )}\n\n {hasWeightOrSizeGuide && (\n <section className=\"bg-white p-5 rounded-md mb-5\">\n {product.weight && (\n <div\n className={`center-between ${product.has_size_guide ? 'pb-5 mb-5 border-b-[1px]' : ''}`}\n >\n <b className=\"form-label rtl:space-x-reverse space-x-1\">\n <i className=\"sicon-luggage-cart\"></i>\n <span>{t('pages.products.weight', 'Weight')}</span>\n </b>\n <span className=\"product-weight text-sm\">{product.weight}</span>\n </div>\n )}\n {product.has_size_guide && (\n <>\n <div className=\"center-between\">\n <b className=\"form-label rtl:space-x-reverse space-x-1\">\n <i className=\"sicon-pencil-ruler\"></i>\n <span>{t('pages.products.size_guides', 'Size Guides')}</span>\n </b>\n <SallaButton\n shape=\"link\"\n color=\"primary\"\n className=\"!p-0 text-sm with-arrow\"\n onClick={() =>\n window.salla?.event?.dispatch('size-guide::open', String(product.id))\n }\n >\n {t('pages.products.show_size_guides', 'Show Size Guides')}\n <i className=\"sicon-keyboard_arrow_left\"></i>\n </SallaButton>\n </div>\n <SallaProductSizeGuide />\n </>\n )}\n </section>\n )}\n\n {hasAttachments && (\n <section className=\"bg-white p-5 rounded-md mb-5\">\n <div className=\"sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start\">\n <div className=\"form-label\">\n <b className=\"block\">{t('pages.products.attachments', 'Attachments')}</b>\n </div>\n <div className=\"mt-1 sm:mt-0 sm:col-span-2 text-end\">\n <div className=\"flex rtl:space-x-reverse space-x-3\">\n {product.can_add_note && (\n <button\n type=\"button\"\n onClick={() => handleCollapseToggle(`note_${product.id}`)}\n className={`btn-tab btn--collapse ${activeCollapse === `note_${product.id}` ? 'is-opened' : 'is-closed'}`}\n >\n <i className=\"font-medium sicon-chat-conversation-alt rtl:ml-1.5 ltr:mr-1.5\"></i>\n <span className=\"fix-align\">{t('pages.products.add_note', 'Add Note')}</span>\n </button>\n )}\n {product.can_upload_file && (\n <button\n type=\"button\"\n onClick={() => handleCollapseToggle(`file_${product.id}`)}\n className={`btn-tab btn--collapse ${activeCollapse === `file_${product.id}` ? 'is-opened' : 'is-closed'}`}\n >\n <i className=\"font-medium sicon-paperclip rtl:ml-1.5 ltr:mr-1.5\"></i>\n <span className=\"fix-align\">{t('pages.products.add_file', 'Add File')}</span>\n </button>\n )}\n </div>\n\n {product.can_add_note && (\n <div\n className={`collapse-content ${activeCollapse === `note_${product.id}` ? 'is-opened' : 'is-closed'}`}\n >\n <div className=\"pt-4\">\n <textarea\n className=\"animated animatedfadeInDown fadeInDown form-input h-16 bg-gray-50 block\"\n placeholder={t('pages.products.notes_placeholder', 'Add your notes here...')}\n name=\"notes\"\n cols={30}\n rows={10}\n defaultValue={product.notes}\n ></textarea>\n </div>\n </div>\n )}\n\n {product.can_upload_file && (\n <div\n className={`collapse-content ${activeCollapse === `file_${product.id}` ? 'is-opened' : 'is-closed'}`}\n >\n <div className=\"pt-4 px-1\">\n <SallaFileUpload\n accept=\"image/png, image/jpeg, image/jpg, image/gif, video/*, application/pdf\"\n className=\"product-option-uploader\"\n >\n <div className=\"product-option-uploader-placholder\">\n <span className=\"product-option-uploader-placholder-icon\">\n <i className=\"sicon-camera\"></i>\n </span>\n <p className=\"profile-filepond-placholder-text\">\n {t('common.uploader.drag_and_drop', 'Drag and drop files here')}\n </p>\n <span className=\"filepond--label-action\">\n {t('common.uploader.browse', 'Browse')}\n </span>\n </div>\n </SallaFileUpload>\n </div>\n </div>\n )}\n </div>\n </div>\n </section>\n )}\n\n {formEndSlot}\n\n <section className=\"flex bg-white p-5 sm:pb-0 rounded-md rounded-b-none\">\n <div className=\"center-between w-full\">\n <div className=\"form-label\">\n <b className=\"block\">{t('pages.products.price', 'Price')}</b>\n </div>\n\n <div\n className={`flex whitespace-nowrap price-wrapper gap-4 items-center ${product.is_out_of_stock ? 'hidden' : ''}`}\n >\n <div\n className={`price_is_on_sale space-x-2 rtl:space-x-reverse whitespace-nowrap ${product.is_on_sale ? '' : 'hidden'}`}\n >\n <span className=\"total-price text-red-800 font-bold text-xl inline-block\">\n {product.sale_price} <CurrencySymbol currency={product.currency} />\n </span>\n <span className=\"before-price text-gray-500 line-through\">\n {product.regular_price} <CurrencySymbol currency={product.currency} />\n </span>\n </div>\n <div\n className={`starting-or-normal-price gap-4 ${product.is_on_sale ? 'hidden' : 'flex'}`}\n >\n {product.starting_price && (\n <span className=\"starting-price-title\">\n {t('pages.products.starting_price', 'Starting from')}\n </span>\n )}\n <span className=\"total-price font-bold text-xl inline-block\">\n {String(product.starting_price ?? product.price)}{' '}\n <CurrencySymbol currency={product.currency} />\n </span>\n </div>\n </div>\n\n <div\n className={`out-of-stock min-h-7 leading-7 text-base text-red-600 !opacity-50 font-bold ${product.is_out_of_stock ? 'scale-pulse' : 'hidden'}`}\n >\n {t('pages.products.out_of_stock', 'Out of Stock')}\n </div>\n </div>\n </section>\n\n {hasPreorder ? (\n <section className=\"mt-5 p-5\">\n <SallaCountDown preOrder={JSON.stringify(product.preorder)} boxed labeled />\n </section>\n ) : null}\n\n <section className=\"sticky-product-bar bg-white p-5 rounded-md rounded-b-none\">\n {product.is_hidden_quantity || product.type === 'booking' ? (\n <input\n type=\"hidden\"\n value=\"1\"\n name=\"quantity\"\n aria-label={t('pages.products.quantity', 'Quantity')}\n />\n ) : (\n <div className=\"sticky-product-bar__quantity center-between mb-5\">\n <span className=\"form-label font-bold\">{t('pages.products.quantity', 'Quantity')}</span>\n <SallaQuantityInput\n max={product.max_quantity ?? undefined}\n value={1}\n name=\"quantity\"\n aria-label={t('pages.products.quantity', 'Quantity')}\n className=\"border-gray-200 flex justify-end\"\n />\n </div>\n )}\n\n <SallaAddProductButton\n {...(product.can_quick_buy ? { quickBuy: true } : {})}\n {...(stickyAddToCart ? { supportStickyBar: true } : {})}\n {...(product.is_require_shipping ? { requiredShipping: true } : {})}\n {...(hasPreorder ? { hasPreOrder: true } : {})}\n amount={\n typeof product.base_currency_price === 'object'\n ? product.base_currency_price.amount\n : product.base_currency_price\n }\n className=\"mt-5 w-full sticky-product-bar__btn\"\n productStatus={product.status}\n productType={product.type}\n productId={product.id}\n loaderPosition=\"end\"\n type=\"submit\"\n width=\"wide\"\n {...(product.notify_availability\n ? {\n ...(product.notify_availability.subscribed ? { isSubscribed: true } : {}),\n channels: product.notify_availability.channels.join(','),\n ...(product.notify_availability.subscribed_options\n ? {\n subscribedOptions: JSON.stringify(\n product.notify_availability.subscribed_options\n ),\n }\n : {}),\n ...(product.notify_availability.options ? { notifyOptionsAvailability: true } : {}),\n }\n : {})}\n >\n {product.add_to_cart_label}\n </SallaAddProductButton>\n </section>\n\n {product.giftable && (\n <SallaGifting\n className=\"mt-5\"\n widgetSubtitle={giftingIntro}\n productId={product.id}\n {...(product.is_require_shipping ? { physicalProducts: true } : {})}\n />\n )}\n </form>\n );\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BlogListLayout, BlogArticleCard } from './chunk-
|
|
1
|
+
import { BlogListLayout, BlogArticleCard } from './chunk-V5733JK2.js';
|
|
2
2
|
import { blog } from './chunk-7O5DYSLX.js';
|
|
3
|
-
import './chunk-
|
|
4
|
-
import './chunk-
|
|
3
|
+
import './chunk-4X36DPHZ.js';
|
|
4
|
+
import './chunk-GGXPIZ6F.js';
|
|
5
5
|
import './chunk-JKIRRMBU.js';
|
|
6
6
|
import './chunk-2JV6WZ6O.js';
|
|
7
7
|
import './chunk-VVZNW5CB.js';
|
|
@@ -28,7 +28,7 @@ import './chunk-YMVLYYLU.js';
|
|
|
28
28
|
import './chunk-RJPPO3ET.js';
|
|
29
29
|
import { HookSlot } from './chunk-Q7VWURUR.js';
|
|
30
30
|
import './chunk-GU2KUQVD.js';
|
|
31
|
-
import { LazyBreadcrumb, LazyNoContent } from './chunk-
|
|
31
|
+
import { LazyBreadcrumb, LazyNoContent } from './chunk-L2AHASYC.js';
|
|
32
32
|
import './chunk-AXW67SY7.js';
|
|
33
33
|
import './chunk-BYMOPN2S.js';
|
|
34
34
|
import './chunk-6BZ5TKEV.js';
|
|
@@ -100,5 +100,5 @@ function BlogAuthorPage({
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
export { BlogAuthorPage };
|
|
103
|
-
//# sourceMappingURL=BlogAuthorPage-
|
|
104
|
-
//# sourceMappingURL=BlogAuthorPage-
|
|
103
|
+
//# sourceMappingURL=BlogAuthorPage-TJ57XZFN.js.map
|
|
104
|
+
//# sourceMappingURL=BlogAuthorPage-TJ57XZFN.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routes/blog/BlogAuthorPage.tsx"],"names":[],"mappings":"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","file":"BlogAuthorPage-
|
|
1
|
+
{"version":3,"sources":["../src/routes/blog/BlogAuthorPage.tsx"],"names":[],"mappings":"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","file":"BlogAuthorPage-TJ57XZFN.js","sourcesContent":["import { useRef, useCallback } from 'react';\nimport { ItemsList } from '@salla.sa/twilight-components-react';\nimport { HookSlot } from '../../hooks';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport { useLocation } from '../../providers/NavigationProvider';\nimport { Breadcrumb, NoContent } from '../../components/common';\nimport { blog } from '../../api/blog';\nimport { BlogArticleCard, BlogListLayout } from './components';\nimport type { BlogAuthorLoaderData, ArticleSummary } from './types';\n\nconst EMPTY_CATEGORIES: BlogAuthorLoaderData['categories'] = [];\nconst EMPTY_ARTICLES: ArticleSummary[] = [];\n\nexport function BlogAuthorPage({\n page,\n author,\n categories = EMPTY_CATEGORIES,\n articles = EMPTY_ARTICLES,\n cursor,\n}: BlogAuthorLoaderData) {\n const { t } = useTranslation();\n const { pathname, searchStr } = useLocation();\n const nextCursorRef = useRef<string | null>(cursor?.next ?? null);\n\n const loader = useCallback(async () => {\n const nextUrl = nextCursorRef.current;\n const cursorMatch = nextUrl?.match(/[?&]cursor=([^&]+)/);\n const cursorValue = cursorMatch ? decodeURIComponent(cursorMatch[1]) : (nextUrl ?? undefined);\n\n const result = await blog.articles.list({ author: author.name, cursor: cursorValue });\n nextCursorRef.current = result.cursor?.next ?? null;\n\n return {\n items: result.data,\n next: result.cursor?.next ?? null,\n };\n }, [author.name]);\n\n if (articles.length === 0) {\n return (\n <div className=\"container mb-8 sm:mb-24\">\n <Breadcrumb page={page} />\n <BlogListLayout categories={categories}>\n <HookSlot name=\"blog:author.start\" />\n <NoContent icon=\"sicon-inbox\" message={t('pages.blog_articles.no_articles')} />\n <HookSlot name=\"blog:author.end\" />\n </BlogListLayout>\n </div>\n );\n }\n\n return (\n <div className=\"container mb-8 sm:mb-24\">\n <Breadcrumb page={page} />\n\n <BlogListLayout categories={categories}>\n <HookSlot name=\"blog:author.start\" />\n\n <div className=\"mb-6\">\n <h1 className=\"font-bold text-xl\">{author.name}</h1>\n </div>\n\n <ItemsList<ArticleSummary>\n items={articles}\n loader={cursor?.next ? loader : undefined}\n mode={cursor?.next ? 'infinite' : 'static'}\n pageUrl={pathname + searchStr}\n className=\"s-blog-list\"\n itemsClassName=\"grid md:grid-cols-2 gap-2.5 md:gap-8\"\n empty={<NoContent icon=\"sicon-inbox\" message={t('pages.blog_articles.no_articles')} />}\n t={(key, fallback) => t(key, fallback || key)}\n >\n {(items) =>\n items.map((article) => <BlogArticleCard key={article.id} article={article} />)\n }\n </ItemsList>\n\n <HookSlot name=\"blog:author.end\" />\n </BlogListLayout>\n </div>\n );\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BlogListLayout, BlogArticleCard } from './chunk-
|
|
1
|
+
import { BlogListLayout, BlogArticleCard } from './chunk-V5733JK2.js';
|
|
2
2
|
import { blog } from './chunk-7O5DYSLX.js';
|
|
3
|
-
import './chunk-
|
|
4
|
-
import './chunk-
|
|
3
|
+
import './chunk-4X36DPHZ.js';
|
|
4
|
+
import './chunk-GGXPIZ6F.js';
|
|
5
5
|
import './chunk-JKIRRMBU.js';
|
|
6
6
|
import './chunk-2JV6WZ6O.js';
|
|
7
7
|
import './chunk-VVZNW5CB.js';
|
|
@@ -28,7 +28,7 @@ import './chunk-YMVLYYLU.js';
|
|
|
28
28
|
import './chunk-RJPPO3ET.js';
|
|
29
29
|
import { HookSlot } from './chunk-Q7VWURUR.js';
|
|
30
30
|
import './chunk-GU2KUQVD.js';
|
|
31
|
-
import { LazyBreadcrumb, LazyNoContent } from './chunk-
|
|
31
|
+
import { LazyBreadcrumb, LazyNoContent } from './chunk-L2AHASYC.js';
|
|
32
32
|
import './chunk-AXW67SY7.js';
|
|
33
33
|
import './chunk-BYMOPN2S.js';
|
|
34
34
|
import './chunk-6BZ5TKEV.js';
|
|
@@ -100,5 +100,5 @@ function BlogCategoryPage({
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
export { BlogCategoryPage };
|
|
103
|
-
//# sourceMappingURL=BlogCategoryPage-
|
|
104
|
-
//# sourceMappingURL=BlogCategoryPage-
|
|
103
|
+
//# sourceMappingURL=BlogCategoryPage-AWFBDRCP.js.map
|
|
104
|
+
//# sourceMappingURL=BlogCategoryPage-AWFBDRCP.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routes/blog/BlogCategoryPage.tsx"],"names":[],"mappings":"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","file":"BlogCategoryPage-
|
|
1
|
+
{"version":3,"sources":["../src/routes/blog/BlogCategoryPage.tsx"],"names":[],"mappings":"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","file":"BlogCategoryPage-AWFBDRCP.js","sourcesContent":["import { useRef, useCallback } from 'react';\nimport { ItemsList } from '@salla.sa/twilight-components-react';\nimport { HookSlot } from '../../hooks';\nimport { useTranslation } from '../../providers/I18nProvider';\nimport { useLocation } from '../../providers/NavigationProvider';\nimport { Breadcrumb, NoContent } from '../../components/common';\nimport { blog } from '../../api/blog';\nimport { BlogArticleCard, BlogListLayout } from './components';\nimport type { BlogCategoryLoaderData, ArticleSummary } from './types';\n\nconst EMPTY_CATEGORIES: BlogCategoryLoaderData['categories'] = [];\nconst EMPTY_ARTICLES: ArticleSummary[] = [];\n\nexport function BlogCategoryPage({\n page,\n blogCategory,\n categories = EMPTY_CATEGORIES,\n articles = EMPTY_ARTICLES,\n cursor,\n}: BlogCategoryLoaderData) {\n const { t } = useTranslation();\n const { pathname, searchStr } = useLocation();\n const nextCursorRef = useRef<string | null>(cursor?.next ?? null);\n\n const loader = useCallback(async () => {\n const nextUrl = nextCursorRef.current;\n const cursorMatch = nextUrl?.match(/[?&]cursor=([^&]+)/);\n const cursorValue = cursorMatch ? decodeURIComponent(cursorMatch[1]) : (nextUrl ?? undefined);\n\n const result = await blog.articles.list({ category: blogCategory.id, cursor: cursorValue });\n nextCursorRef.current = result.cursor?.next ?? null;\n\n return {\n items: result.data,\n next: result.cursor?.next ?? null,\n };\n }, [blogCategory.id]);\n\n if (articles.length === 0) {\n return (\n <div className=\"container mb-8 sm:mb-24\">\n <Breadcrumb page={page} />\n <BlogListLayout categories={categories}>\n <HookSlot name=\"blog:category.start\" />\n <NoContent icon=\"sicon-inbox\" message={t('pages.blog_articles.no_articles')} />\n <HookSlot name=\"blog:category.end\" />\n </BlogListLayout>\n </div>\n );\n }\n\n return (\n <div className=\"container mb-8 sm:mb-24\">\n <Breadcrumb page={page} />\n\n <BlogListLayout categories={categories}>\n <HookSlot name=\"blog:category.start\" />\n\n <div className=\"mb-6\">\n <h1 className=\"font-bold text-xl\">{blogCategory.name}</h1>\n </div>\n\n <ItemsList<ArticleSummary>\n items={articles}\n loader={cursor?.next ? loader : undefined}\n mode={cursor?.next ? 'infinite' : 'static'}\n pageUrl={pathname + searchStr}\n className=\"s-blog-list\"\n itemsClassName=\"grid md:grid-cols-2 gap-2.5 md:gap-8\"\n empty={<NoContent icon=\"sicon-inbox\" message={t('pages.blog_articles.no_articles')} />}\n t={(key, fallback) => t(key, fallback || key)}\n >\n {(items) =>\n items.map((article) => (\n <BlogArticleCard key={article.id} article={article} showAuthor />\n ))\n }\n </ItemsList>\n\n <HookSlot name=\"blog:category.end\" />\n </BlogListLayout>\n </div>\n );\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useDate } from './chunk-
|
|
2
|
-
import './chunk-
|
|
1
|
+
import { useDate } from './chunk-4X36DPHZ.js';
|
|
2
|
+
import './chunk-GGXPIZ6F.js';
|
|
3
3
|
import './chunk-JKIRRMBU.js';
|
|
4
4
|
import './chunk-2JV6WZ6O.js';
|
|
5
5
|
import './chunk-VVZNW5CB.js';
|
|
@@ -26,7 +26,7 @@ import './chunk-YMVLYYLU.js';
|
|
|
26
26
|
import './chunk-RJPPO3ET.js';
|
|
27
27
|
import { HookSlot } from './chunk-Q7VWURUR.js';
|
|
28
28
|
import './chunk-GU2KUQVD.js';
|
|
29
|
-
import { LazyBreadcrumb, Image, LazyNoContent } from './chunk-
|
|
29
|
+
import { LazyBreadcrumb, Image, LazyNoContent } from './chunk-L2AHASYC.js';
|
|
30
30
|
import { Link } from './chunk-AXW67SY7.js';
|
|
31
31
|
import './chunk-BYMOPN2S.js';
|
|
32
32
|
import './chunk-6BZ5TKEV.js';
|
|
@@ -195,5 +195,5 @@ function BlogPage({
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
export { BlogPage };
|
|
198
|
-
//# sourceMappingURL=BlogPage-
|
|
199
|
-
//# sourceMappingURL=BlogPage-
|
|
198
|
+
//# sourceMappingURL=BlogPage-JCK2Y3DT.js.map
|
|
199
|
+
//# sourceMappingURL=BlogPage-JCK2Y3DT.js.map
|