@behio/storefront-sdk 0.1.7 → 0.1.9
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 +395 -0
- package/dist/{chunk-S4DOL3OV.mjs → chunk-HYKJO2IB.mjs} +45 -1
- package/dist/{chunk-GGAO5T5P.js → chunk-QOEYSUF2.js} +45 -1
- package/dist/index.d.mts +81 -2
- package/dist/index.d.ts +81 -2
- package/dist/index.js +2 -2
- package/dist/index.mjs +1 -1
- package/dist/react.d.mts +59 -3
- package/dist/react.d.ts +59 -3
- package/dist/react.js +66 -3
- package/dist/react.mjs +65 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -509,6 +509,7 @@ const tracked = await shop.orders.track('tracking-token-uuid');
|
|
|
509
509
|
| Hook | Purpose | Auth required |
|
|
510
510
|
|------|---------|---------------|
|
|
511
511
|
| [`useShopInfo()`](#useshopinfo) | E-shop info (name, currencies, languages) | No |
|
|
512
|
+
| [`useShopSeo(opts?)`](#useshopseo) | Per-locale SEO metadata for the homepage | No |
|
|
512
513
|
| [`useProducts(query?)`](#useproducts) | Product list with filters, pagination, search | No |
|
|
513
514
|
| [`useProduct(slug)`](#useproduct) | Product detail | No |
|
|
514
515
|
| [`useCategories(locale?)`](#usecategories) | Category tree | No |
|
|
@@ -525,6 +526,9 @@ const tracked = await shop.orders.track('tracking-token-uuid');
|
|
|
525
526
|
| [`useCustomer()`](#usecustomer) | Profile + update | Yes |
|
|
526
527
|
| [`useAddresses()`](#useaddresses) | Address CRUD | Yes |
|
|
527
528
|
| [`usePages()` / `usePage(slug)`](#usepages) | CMS pages | No |
|
|
529
|
+
| [`useBundles()` / `useBundle(slug)`](#usebundles) | Active bundles (sets) with auto-computed savings | No |
|
|
530
|
+
| [`useCrossSell(productSlug)`](#usecrosssell) | Related / upsell / cross-sell products per product | No |
|
|
531
|
+
| [`useProductPromotions(productSlug)`](#useproductpromotions) | Active promotions applicable to a product (with countdown) | No |
|
|
528
532
|
|
|
529
533
|
\* Guest checkout works without auth if the e-shop allows it.
|
|
530
534
|
|
|
@@ -534,6 +538,55 @@ const { data, isLoading, error } = useShopInfo();
|
|
|
534
538
|
// data: ShopInfo
|
|
535
539
|
```
|
|
536
540
|
|
|
541
|
+
### useShopSeo
|
|
542
|
+
|
|
543
|
+
Returns per-locale SEO metadata (title, description, keywords, OG tags). Falls back to the shop's default locale when `locale` is omitted, and to `metaTitle / metaDescription` on the shop itself if there's no per-locale override.
|
|
544
|
+
|
|
545
|
+
```tsx
|
|
546
|
+
const { data: seo } = useShopSeo({ locale: 'cs' });
|
|
547
|
+
// data: { locale, title, description, keywords, ogTitle, ogDescription, ogImage }
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
**Server-side / SSR** — use the core client directly to fetch at request time and pass as `initialData`:
|
|
551
|
+
|
|
552
|
+
```tsx
|
|
553
|
+
// app/[locale]/page.tsx (Next.js RSC)
|
|
554
|
+
import { BehioStorefront } from '@behio/storefront-sdk';
|
|
555
|
+
import type { Metadata } from 'next';
|
|
556
|
+
|
|
557
|
+
const shop = new BehioStorefront({ apiKey: process.env.BEHIO_API_KEY! });
|
|
558
|
+
|
|
559
|
+
export async function generateMetadata({ params }: { params: { locale: string } }): Promise<Metadata> {
|
|
560
|
+
const seo = await shop.getShopSeo(params.locale);
|
|
561
|
+
return {
|
|
562
|
+
title: seo.title ?? undefined,
|
|
563
|
+
description: seo.description ?? undefined,
|
|
564
|
+
openGraph: {
|
|
565
|
+
title: seo.ogTitle ?? seo.title ?? undefined,
|
|
566
|
+
description: seo.ogDescription ?? seo.description ?? undefined,
|
|
567
|
+
images: seo.ogImage ? [seo.ogImage] : undefined,
|
|
568
|
+
},
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
export default async function Home({ params }: { params: { locale: string } }) {
|
|
573
|
+
const seo = await shop.getShopSeo(params.locale);
|
|
574
|
+
// Pass to client component for React Query hydration:
|
|
575
|
+
// <ClientHome initialSeo={seo} />
|
|
576
|
+
}
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
Client hydration:
|
|
580
|
+
```tsx
|
|
581
|
+
'use client';
|
|
582
|
+
import { useShopSeo } from '@behio/storefront-sdk/react';
|
|
583
|
+
|
|
584
|
+
export function ClientHome({ initialSeo }: { initialSeo: ShopSeo }) {
|
|
585
|
+
const { data } = useShopSeo({ locale: 'cs', initialData: initialSeo });
|
|
586
|
+
return <h1>{data.title}</h1>;
|
|
587
|
+
}
|
|
588
|
+
```
|
|
589
|
+
|
|
537
590
|
### useProducts
|
|
538
591
|
|
|
539
592
|
Supports **both** traditional pagination and infinite scroll from one hook.
|
|
@@ -735,6 +788,336 @@ const { data: pages } = usePages('cs');
|
|
|
735
788
|
const { data: page } = usePage('about-us', 'cs');
|
|
736
789
|
```
|
|
737
790
|
|
|
791
|
+
### useBundles / useBundle
|
|
792
|
+
|
|
793
|
+
**What it is.** A "bundle" is a merchant-curated set of products sold together
|
|
794
|
+
at a single fixed price that's (usually) lower than buying the components
|
|
795
|
+
individually — think *starter kit*, *holiday gift set*, *3-for-2 deals*, or
|
|
796
|
+
*"breakfast combo"*. The merchant defines what goes in (which products, what
|
|
797
|
+
quantities, what cover image) and sets one total price for the whole thing.
|
|
798
|
+
|
|
799
|
+
**Why it matters.** Bundles are one of the highest-ROI features in e-commerce:
|
|
800
|
+
they raise average order value without having to discount individual products,
|
|
801
|
+
they give customers a clear "good deal" signal (the savings badge), and they
|
|
802
|
+
let you clear slow-moving inventory by pairing it with fast-movers. Most eshop
|
|
803
|
+
platforms treat bundles as paid add-ons or plugins — here it's native.
|
|
804
|
+
|
|
805
|
+
**Where you use it.**
|
|
806
|
+
|
|
807
|
+
- **Homepage / landing pages** — list active bundles as hero cards with cover
|
|
808
|
+
image + `-25%` badge. Drives impulse purchase.
|
|
809
|
+
- **Category pages** — show a relevant bundle ("vše na grilování") next to
|
|
810
|
+
individual products in the same category.
|
|
811
|
+
- **Cart / checkout** — suggest a bundle as upsell ("Přidejte ještě tohle a
|
|
812
|
+
dostanete celý set s 20% slevou").
|
|
813
|
+
- **Dedicated `/bundles` page** — marketing landing for all active sets.
|
|
814
|
+
|
|
815
|
+
**What's in the data:**
|
|
816
|
+
|
|
817
|
+
- `bundlePrice` — what the customer pays for the whole set
|
|
818
|
+
- `itemsSum` — what the components would cost individually (sum of default prices)
|
|
819
|
+
- `savings` — `itemsSum - bundlePrice` (absolute savings in the currency)
|
|
820
|
+
- `savingsPercent` — pre-computed percent so you don't have to do the math in JSX
|
|
821
|
+
- `items[]` — the components with their quantities (for display and stock check)
|
|
822
|
+
- `endsAt` — optional expiry timestamp; if set, the bundle auto-deactivates
|
|
823
|
+
|
|
824
|
+
```tsx
|
|
825
|
+
import { useBundles, useBundle, useCart, useBehio } from '@behio/storefront-sdk/react';
|
|
826
|
+
|
|
827
|
+
// ---- Homepage hero: all active bundles ----
|
|
828
|
+
function BundlesGrid() {
|
|
829
|
+
const { data, isLoading } = useBundles();
|
|
830
|
+
if (isLoading) return <Skeleton />;
|
|
831
|
+
if (!data?.items.length) return null; // no active bundles → hide section
|
|
832
|
+
|
|
833
|
+
return (
|
|
834
|
+
<section className="grid grid-cols-3 gap-4">
|
|
835
|
+
{data.items.map((bundle) => (
|
|
836
|
+
<a key={bundle.id} href={`/bundle/${bundle.slug}`} className="relative">
|
|
837
|
+
{bundle.coverImage && <img src={bundle.coverImage} alt={bundle.name} />}
|
|
838
|
+
<h3>{bundle.name}</h3>
|
|
839
|
+
<div>
|
|
840
|
+
<strong>{bundle.bundlePrice} {bundle.currency}</strong>
|
|
841
|
+
{bundle.savings > 0 && (
|
|
842
|
+
<>
|
|
843
|
+
<s>{bundle.itemsSum} {bundle.currency}</s>
|
|
844
|
+
<span className="badge">-{bundle.savingsPercent}%</span>
|
|
845
|
+
</>
|
|
846
|
+
)}
|
|
847
|
+
</div>
|
|
848
|
+
<p>{bundle.items.length} produktů ušetříte {bundle.savings} {bundle.currency}</p>
|
|
849
|
+
</a>
|
|
850
|
+
))}
|
|
851
|
+
</section>
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// ---- Bundle detail page with "Add to cart" ----
|
|
856
|
+
function BundleDetail({ slug }: { slug: string }) {
|
|
857
|
+
const { data: bundle, isLoading } = useBundle(slug);
|
|
858
|
+
const { client } = useBehio();
|
|
859
|
+
const { refresh } = useCart();
|
|
860
|
+
|
|
861
|
+
if (isLoading) return <Skeleton />;
|
|
862
|
+
if (!bundle) return <NotFound />;
|
|
863
|
+
|
|
864
|
+
async function addToCart() {
|
|
865
|
+
await client.cart.addBundle(bundle.id, 1);
|
|
866
|
+
await refresh(); // cart badge updates everywhere
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
return (
|
|
870
|
+
<article>
|
|
871
|
+
<h1>{bundle.name}</h1>
|
|
872
|
+
<p>{bundle.description}</p>
|
|
873
|
+
|
|
874
|
+
<ul>
|
|
875
|
+
{bundle.items.map((item) => (
|
|
876
|
+
<li key={item.productId}>
|
|
877
|
+
{item.quantity}× {item.name}
|
|
878
|
+
{item.defaultPrice && (
|
|
879
|
+
<span className="text-muted">
|
|
880
|
+
({item.defaultPrice} {bundle.currency} /ks běžně)
|
|
881
|
+
</span>
|
|
882
|
+
)}
|
|
883
|
+
</li>
|
|
884
|
+
))}
|
|
885
|
+
</ul>
|
|
886
|
+
|
|
887
|
+
<div className="price-box">
|
|
888
|
+
<strong>{bundle.bundlePrice} {bundle.currency}</strong>
|
|
889
|
+
{bundle.savings > 0 && (
|
|
890
|
+
<p>
|
|
891
|
+
Jednotlivě by stálo <s>{bundle.itemsSum} {bundle.currency}</s> —
|
|
892
|
+
ušetříte <strong>{bundle.savings} {bundle.currency}</strong>
|
|
893
|
+
({bundle.savingsPercent}%)
|
|
894
|
+
</p>
|
|
895
|
+
)}
|
|
896
|
+
<button onClick={addToCart}>Přidat celý balíček do košíku</button>
|
|
897
|
+
</div>
|
|
898
|
+
</article>
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
**Behind the scenes at checkout.** When the customer buys a bundle, Behio
|
|
904
|
+
rozpadá balíček do order-itemů s proporčně rozpočítanou cenou podle
|
|
905
|
+
defaultních cen komponent (zachováno pro účetnictví a skladové odpisy), ale
|
|
906
|
+
total na faktuře odpovídá `bundlePrice` — zákazník vidí jednu celistvou
|
|
907
|
+
položku, sklady se odepisují správně z komponent.
|
|
908
|
+
|
|
909
|
+
---
|
|
910
|
+
|
|
911
|
+
### useCrossSell
|
|
912
|
+
|
|
913
|
+
**What it is.** Three related lists of product recommendations shown on a
|
|
914
|
+
product detail page:
|
|
915
|
+
|
|
916
|
+
- **Related (Podobné)** — alternativy ke stejnému účelu (jiné vodítko, jiné
|
|
917
|
+
krmivo). Když tě tenhle produkt zaujal, tady jsou jiné stejné kategorie.
|
|
918
|
+
- **Upsell (Lepší varianta)** — dražší / vybavenější verze. „Vidíš levný
|
|
919
|
+
obojek? Tady je verze s koženým prošitím za 2×." Cílem je zvýšit
|
|
920
|
+
average order value.
|
|
921
|
+
- **Cross-sell (Často kupováno s)** — komplementární produkty. K obojku
|
|
922
|
+
vodítko, k misce čistič. Čistý AOV boost na PDP a v košíku.
|
|
923
|
+
|
|
924
|
+
**Why to split them.** Každý z těchto typů má jinou UX roli a měla by být
|
|
925
|
+
různě formulována. Když se to smíchá, ztratí se kontext — zákazník nepozná,
|
|
926
|
+
proč mu to zobrazuješ.
|
|
927
|
+
|
|
928
|
+
**Where to use it.**
|
|
929
|
+
|
|
930
|
+
- **Product detail page** — tři samostatné sekce pod popisem (nebo v sidebar
|
|
931
|
+
sloupci). Nejvyšší konverzní dopad je **Cross-sell "často kupováno s"**
|
|
932
|
+
přímo u tlačítka "Přidat do košíku".
|
|
933
|
+
- **Cart sidebar** — mini-cross-sell widget ("Nezapomeňte ještě na tohle").
|
|
934
|
+
- **Post-purchase page** — "Chcete ještě tohle?" pro druhou objednávku.
|
|
935
|
+
|
|
936
|
+
**Pozor.** Endpoint vrací **jen aktivní produkty ve stejném eshopu**. Když
|
|
937
|
+
jsi v adminu nějaký linknul a pak ho deaktivoval/smazal, zmizí ze seznamu
|
|
938
|
+
automaticky — nemusíš to řešit na FE.
|
|
939
|
+
|
|
940
|
+
```tsx
|
|
941
|
+
import { useCrossSell, useBehio } from '@behio/storefront-sdk/react';
|
|
942
|
+
|
|
943
|
+
function CrossSellSection({ title, items }: { title: string; items: CrossSellItem[] }) {
|
|
944
|
+
if (!items?.length) return null; // nezobrazuj prázdnou sekci
|
|
945
|
+
return (
|
|
946
|
+
<section>
|
|
947
|
+
<h2>{title}</h2>
|
|
948
|
+
<div className="carousel">
|
|
949
|
+
{items.map((item) => (
|
|
950
|
+
<a key={item.productId} href={`/produkt/${item.slug}`} className="card">
|
|
951
|
+
{item.imageUrl && <img src={item.imageUrl} alt={item.name} />}
|
|
952
|
+
<h4>{item.name}</h4>
|
|
953
|
+
<span>{item.price} Kč</span>
|
|
954
|
+
{item.stockCached === 0 && <span className="text-red">Vyprodáno</span>}
|
|
955
|
+
</a>
|
|
956
|
+
))}
|
|
957
|
+
</div>
|
|
958
|
+
</section>
|
|
959
|
+
);
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
function ProductDetail({ slug }: { slug: string }) {
|
|
963
|
+
const { data: crossSell } = useCrossSell(slug);
|
|
964
|
+
|
|
965
|
+
return (
|
|
966
|
+
<>
|
|
967
|
+
{/* ... product info ... */}
|
|
968
|
+
|
|
969
|
+
<CrossSellSection
|
|
970
|
+
title="Často kupováno s"
|
|
971
|
+
items={crossSell?.crossSell ?? []}
|
|
972
|
+
/>
|
|
973
|
+
<CrossSellSection
|
|
974
|
+
title="Možná vás zaujme i"
|
|
975
|
+
items={crossSell?.related ?? []}
|
|
976
|
+
/>
|
|
977
|
+
<CrossSellSection
|
|
978
|
+
title="Chcete raději lepší variantu?"
|
|
979
|
+
items={crossSell?.upsell ?? []}
|
|
980
|
+
/>
|
|
981
|
+
</>
|
|
982
|
+
);
|
|
983
|
+
}
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
**Tip — merge do jedné sekce.** Pokud máš málo content a chceš to zjednodušit:
|
|
987
|
+
|
|
988
|
+
```tsx
|
|
989
|
+
const allRecommendations = [
|
|
990
|
+
...(crossSell?.crossSell ?? []),
|
|
991
|
+
...(crossSell?.related ?? []),
|
|
992
|
+
...(crossSell?.upsell ?? []),
|
|
993
|
+
].slice(0, 6);
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
---
|
|
997
|
+
|
|
998
|
+
### useProductPromotions
|
|
999
|
+
|
|
1000
|
+
**What it is.** Vrací aktuálně platné akce (`Eshop_Promotion`) týkající se
|
|
1001
|
+
konkrétního produktu — tedy všechny promotions, kde `startsAt <= teď < endsAt`
|
|
1002
|
+
a produkt spadá do scope akce (může to být `ALL_PRODUCTS`, `SPECIFIC_PRODUCTS`,
|
|
1003
|
+
`CATEGORIES` nebo `LABELS`, backend to vyřeší za tebe).
|
|
1004
|
+
|
|
1005
|
+
**Co to není.** Není to výpočet *konečné ceny po slevě* — na to je samostatná
|
|
1006
|
+
vrstva (cart evaluator). Tenhle hook je čistě pro **zobrazovací vrstvu**: badge,
|
|
1007
|
+
countdown, upozornění „akční cena do půlnoci".
|
|
1008
|
+
|
|
1009
|
+
**Proč je to oddělené.** Konverzně nejsilnější marketingový prvek v eshopu je
|
|
1010
|
+
**urgency + scarcity**. „Do konce akce: 2h 14m 37s" přímo na PDP zvyšuje
|
|
1011
|
+
conversion rate měřitelně — je to letitá best practice (Amazon Lightning
|
|
1012
|
+
Deals, Booking "rezervováno 3× za posledních 24h", atd.). Hook ti dodá data,
|
|
1013
|
+
ty uděláš countdown komponentu.
|
|
1014
|
+
|
|
1015
|
+
**Kde to použít.**
|
|
1016
|
+
|
|
1017
|
+
- **Product card v listu** — badge `-20%` nebo vlajka „AKCE".
|
|
1018
|
+
- **Product detail** — velký banner s countdown nad cenou: „Koupíte-li do
|
|
1019
|
+
půlnoci, ušetříte 200 Kč."
|
|
1020
|
+
- **Cart** — varování „Vaše sleva vyprší za 5 minut" aby tlačilo k
|
|
1021
|
+
dokončení objednávky.
|
|
1022
|
+
|
|
1023
|
+
**Pole z API:**
|
|
1024
|
+
|
|
1025
|
+
- `id`, `name`, `slug` — identifikace akce
|
|
1026
|
+
- `type` — `FLASH_SALE` / `SEASONAL` / `CLEARANCE` / `BOGO` / `BUNDLE` / `LOYALTY`
|
|
1027
|
+
- `discountType` — `PERCENTAGE` / `FIXED_AMOUNT` / `FREE_SHIPPING` / `BUY_X_GET_Y`
|
|
1028
|
+
- `discountValue` — hodnota (u PERCENTAGE je to %, u FIXED_AMOUNT Kč, …)
|
|
1029
|
+
- `endsAt` — timestamp konce. Pokud `null`, akce je na neurčito.
|
|
1030
|
+
- `badgeText`, `badgeColor` — merchant ručně nastavil text a barvu badge
|
|
1031
|
+
(např. „-30%" s červenou); pokud oboje `null`, vymysli default podle `discountType`.
|
|
1032
|
+
- `showCountdown` — **respect this!** Když merchant nechce countdown, nerender
|
|
1033
|
+
ho. Ne všechny akce (CLEARANCE, LOYALTY) mají smysl odpočítávat.
|
|
1034
|
+
- `couponRequired` — akce se uplatní jen po zadání kódu na checkoutu.
|
|
1035
|
+
Na PDP ukaž info box („Použijte kód LETO pro uplatnění"), neukazuj jako
|
|
1036
|
+
automatickou slevu.
|
|
1037
|
+
|
|
1038
|
+
```tsx
|
|
1039
|
+
import { useProductPromotions } from '@behio/storefront-sdk/react';
|
|
1040
|
+
import { useEffect, useState } from 'react';
|
|
1041
|
+
|
|
1042
|
+
function ProductPromotionBanner({ slug }: { slug: string }) {
|
|
1043
|
+
// Refetch každé 4 minuty aby se promotion aktualizovala když mezitím
|
|
1044
|
+
// skončila jedna a začala další. Pro pouhý countdown nemusíš refetchovat —
|
|
1045
|
+
// countdown děláš lokálně z endsAt.
|
|
1046
|
+
const { data } = useProductPromotions(slug, { refetchIntervalMs: 4 * 60_000 });
|
|
1047
|
+
const promotions = data?.items ?? [];
|
|
1048
|
+
|
|
1049
|
+
if (!promotions.length) return null;
|
|
1050
|
+
|
|
1051
|
+
// Nejvyšší priority akce (BE už vrací seřazené priority DESC + createdAt ASC)
|
|
1052
|
+
const promo = promotions[0];
|
|
1053
|
+
|
|
1054
|
+
const badge = promo.badgeText ?? formatDefaultBadge(promo);
|
|
1055
|
+
const badgeColor = promo.badgeColor ?? '#ef4444';
|
|
1056
|
+
|
|
1057
|
+
return (
|
|
1058
|
+
<div className="promo-banner" style={{ backgroundColor: badgeColor + '20', borderColor: badgeColor }}>
|
|
1059
|
+
<div>
|
|
1060
|
+
<span className="badge" style={{ backgroundColor: badgeColor }}>{badge}</span>
|
|
1061
|
+
<strong>{promo.name}</strong>
|
|
1062
|
+
{promo.couponRequired && (
|
|
1063
|
+
<p>Uplatníte zadáním kódu <code>{promo.name}</code> v košíku</p>
|
|
1064
|
+
)}
|
|
1065
|
+
</div>
|
|
1066
|
+
{promo.showCountdown && promo.endsAt && <Countdown endsAt={promo.endsAt} />}
|
|
1067
|
+
</div>
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
function Countdown({ endsAt }: { endsAt: number }) {
|
|
1072
|
+
const [now, setNow] = useState(Date.now());
|
|
1073
|
+
useEffect(() => {
|
|
1074
|
+
const id = setInterval(() => setNow(Date.now()), 1000);
|
|
1075
|
+
return () => clearInterval(id);
|
|
1076
|
+
}, []);
|
|
1077
|
+
|
|
1078
|
+
const ms = Math.max(0, endsAt - now);
|
|
1079
|
+
if (ms === 0) return <span>Akce skončila</span>;
|
|
1080
|
+
|
|
1081
|
+
const d = Math.floor(ms / 86400_000);
|
|
1082
|
+
const h = Math.floor((ms % 86400_000) / 3600_000);
|
|
1083
|
+
const m = Math.floor((ms % 3600_000) / 60_000);
|
|
1084
|
+
const s = Math.floor((ms % 60_000) / 1000);
|
|
1085
|
+
|
|
1086
|
+
if (d > 0) return <span>Končí za {d}d {h}h {m}m</span>;
|
|
1087
|
+
return <span>Končí za {h}h {m}m {s}s</span>;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
function formatDefaultBadge(p: { discountType: string; discountValue: number }) {
|
|
1091
|
+
switch (p.discountType) {
|
|
1092
|
+
case 'PERCENTAGE': return `-${p.discountValue}%`;
|
|
1093
|
+
case 'FIXED_AMOUNT': return `-${p.discountValue} Kč`;
|
|
1094
|
+
case 'FREE_SHIPPING': return 'Doprava zdarma';
|
|
1095
|
+
case 'BUY_X_GET_Y': return `${p.discountValue}+1 ZDARMA`;
|
|
1096
|
+
default: return 'AKCE';
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
```
|
|
1100
|
+
|
|
1101
|
+
**Pattern — product card badge.** Když chceš jen malou vlaječku na kartě
|
|
1102
|
+
produktu v listu (bez countdown), zavolej hook per-card a vezmi první promo:
|
|
1103
|
+
|
|
1104
|
+
```tsx
|
|
1105
|
+
function ProductCardBadge({ slug }: { slug: string }) {
|
|
1106
|
+
const { data } = useProductPromotions(slug);
|
|
1107
|
+
const promo = data?.items[0];
|
|
1108
|
+
if (!promo) return null;
|
|
1109
|
+
return (
|
|
1110
|
+
<span className="badge" style={{ background: promo.badgeColor ?? '#ef4444' }}>
|
|
1111
|
+
{promo.badgeText ?? formatDefaultBadge(promo)}
|
|
1112
|
+
</span>
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
```
|
|
1116
|
+
|
|
1117
|
+
Pozor — v listovém kontextu to dělá N dotazů (jeden per karta). Pokud máš
|
|
1118
|
+
200 produktů, radši vytvoř vlastní bulk endpoint nebo invaliduj méně často
|
|
1119
|
+
přes React Query `staleTime`.
|
|
1120
|
+
|
|
738
1121
|
## All API methods
|
|
739
1122
|
|
|
740
1123
|
### Catalog
|
|
@@ -748,6 +1131,17 @@ shop.catalog.getLabels(locale?) → { labels: ProductLabel[] }
|
|
|
748
1131
|
shop.catalog.getFeatured() → PaginatedResponse<ProductListItem>
|
|
749
1132
|
shop.catalog.getFilters() → { filters: FilterField[] }
|
|
750
1133
|
shop.catalog.search(query, opts?) → PaginatedResponse<ProductListItem>
|
|
1134
|
+
shop.catalog.getBundles() → { items: Bundle[] }
|
|
1135
|
+
shop.catalog.getBundle(slug) → Bundle
|
|
1136
|
+
shop.catalog.getCrossSell(productSlug) → { related, upsell, crossSell: CrossSellItem[] }
|
|
1137
|
+
shop.catalog.getProductPromotions(slug) → { items: ActivePromotion[] }
|
|
1138
|
+
```
|
|
1139
|
+
|
|
1140
|
+
### Cart — bundles
|
|
1141
|
+
```typescript
|
|
1142
|
+
shop.cart.addBundle(bundleId, quantity?) → Cart
|
|
1143
|
+
shop.cart.updateBundleQuantity(id, qty) → Cart
|
|
1144
|
+
shop.cart.removeBundle(bundleId) → Cart
|
|
751
1145
|
```
|
|
752
1146
|
|
|
753
1147
|
### Auth
|
|
@@ -807,6 +1201,7 @@ shop.pages.get(slug, locale?) → PageDetail
|
|
|
807
1201
|
### Instance utilities
|
|
808
1202
|
```typescript
|
|
809
1203
|
shop.getShopInfo() → ShopInfo
|
|
1204
|
+
shop.getShopSeo(locale?) → ShopSeo (per-locale SEO for SSR/metadata)
|
|
810
1205
|
shop.setTokens({ accessToken, refreshToken })
|
|
811
1206
|
shop.clearTokens()
|
|
812
1207
|
shop.getAccessToken() → string | undefined
|
|
@@ -108,6 +108,12 @@ var BehioStorefront = class {
|
|
|
108
108
|
async getShopInfo() {
|
|
109
109
|
return this.request("GET", "/shop");
|
|
110
110
|
}
|
|
111
|
+
/** Get SEO metadata for the shop homepage in the given locale (defaults to shop default). */
|
|
112
|
+
async getShopSeo(locale) {
|
|
113
|
+
return this.request("GET", "/shop/seo", {
|
|
114
|
+
query: locale ? { locale } : void 0
|
|
115
|
+
});
|
|
116
|
+
}
|
|
111
117
|
/** Set auth tokens (e.g. from localStorage) */
|
|
112
118
|
setTokens(tokens) {
|
|
113
119
|
this.accessToken = tokens.accessToken;
|
|
@@ -396,6 +402,22 @@ var CatalogModule = class {
|
|
|
396
402
|
async search(query, options) {
|
|
397
403
|
return this.getProducts({ search: query, ...options });
|
|
398
404
|
}
|
|
405
|
+
/** List all active bundles */
|
|
406
|
+
async getBundles() {
|
|
407
|
+
return this.client.request("GET", "/catalog/bundles");
|
|
408
|
+
}
|
|
409
|
+
/** Get a single bundle by slug */
|
|
410
|
+
async getBundle(slug) {
|
|
411
|
+
return this.client.request("GET", `/catalog/bundles/${slug}`);
|
|
412
|
+
}
|
|
413
|
+
/** Cross-sell / related / upsell products for a product */
|
|
414
|
+
async getCrossSell(productSlug) {
|
|
415
|
+
return this.client.request("GET", `/catalog/products/${productSlug}/cross-sell`);
|
|
416
|
+
}
|
|
417
|
+
/** Active promotions applicable to a product (with countdown end time) */
|
|
418
|
+
async getProductPromotions(productSlug) {
|
|
419
|
+
return this.client.request("GET", `/catalog/products/${productSlug}/promotions`);
|
|
420
|
+
}
|
|
399
421
|
};
|
|
400
422
|
var AuthModule = class {
|
|
401
423
|
constructor(client) {
|
|
@@ -507,6 +529,28 @@ var CartModule = class {
|
|
|
507
529
|
this.client.emit("cart:cleared");
|
|
508
530
|
return result;
|
|
509
531
|
}
|
|
532
|
+
/** Add a bundle to the cart (price is locked at the bundle's current price) */
|
|
533
|
+
async addBundle(bundleId, quantity = 1) {
|
|
534
|
+
const result = await this.client.request("POST", "/cart/bundles", {
|
|
535
|
+
body: { bundleId, quantity }
|
|
536
|
+
});
|
|
537
|
+
this.client.emit("cart:updated", result);
|
|
538
|
+
return result;
|
|
539
|
+
}
|
|
540
|
+
/** Update quantity of a bundle already in the cart */
|
|
541
|
+
async updateBundleQuantity(bundleId, quantity) {
|
|
542
|
+
const result = await this.client.request("PATCH", `/cart/bundles/${bundleId}`, {
|
|
543
|
+
body: { quantity }
|
|
544
|
+
});
|
|
545
|
+
this.client.emit("cart:updated", result);
|
|
546
|
+
return result;
|
|
547
|
+
}
|
|
548
|
+
/** Remove a bundle from the cart */
|
|
549
|
+
async removeBundle(bundleId) {
|
|
550
|
+
const result = await this.client.request("DELETE", `/cart/bundles/${bundleId}`);
|
|
551
|
+
this.client.emit("cart:updated", result);
|
|
552
|
+
return result;
|
|
553
|
+
}
|
|
510
554
|
/** Merge anonymous cart into authenticated customer cart */
|
|
511
555
|
async merge() {
|
|
512
556
|
const result = await this.client.request("POST", "/cart/merge");
|
|
@@ -561,7 +605,7 @@ var OrdersModule = class {
|
|
|
561
605
|
async cancel(orderNumber) {
|
|
562
606
|
return this.client.request("POST", `/orders/${orderNumber}/cancel`);
|
|
563
607
|
}
|
|
564
|
-
/** Track order by tracking token (no
|
|
608
|
+
/** Track order by tracking token (no customer login required, only API key) */
|
|
565
609
|
async track(trackingToken) {
|
|
566
610
|
return this.client.request("GET", `/orders/track/${trackingToken}`, { auth: false });
|
|
567
611
|
}
|
|
@@ -108,6 +108,12 @@ var BehioStorefront = class {
|
|
|
108
108
|
async getShopInfo() {
|
|
109
109
|
return this.request("GET", "/shop");
|
|
110
110
|
}
|
|
111
|
+
/** Get SEO metadata for the shop homepage in the given locale (defaults to shop default). */
|
|
112
|
+
async getShopSeo(locale) {
|
|
113
|
+
return this.request("GET", "/shop/seo", {
|
|
114
|
+
query: locale ? { locale } : void 0
|
|
115
|
+
});
|
|
116
|
+
}
|
|
111
117
|
/** Set auth tokens (e.g. from localStorage) */
|
|
112
118
|
setTokens(tokens) {
|
|
113
119
|
this.accessToken = tokens.accessToken;
|
|
@@ -396,6 +402,22 @@ var CatalogModule = class {
|
|
|
396
402
|
async search(query, options) {
|
|
397
403
|
return this.getProducts({ search: query, ...options });
|
|
398
404
|
}
|
|
405
|
+
/** List all active bundles */
|
|
406
|
+
async getBundles() {
|
|
407
|
+
return this.client.request("GET", "/catalog/bundles");
|
|
408
|
+
}
|
|
409
|
+
/** Get a single bundle by slug */
|
|
410
|
+
async getBundle(slug) {
|
|
411
|
+
return this.client.request("GET", `/catalog/bundles/${slug}`);
|
|
412
|
+
}
|
|
413
|
+
/** Cross-sell / related / upsell products for a product */
|
|
414
|
+
async getCrossSell(productSlug) {
|
|
415
|
+
return this.client.request("GET", `/catalog/products/${productSlug}/cross-sell`);
|
|
416
|
+
}
|
|
417
|
+
/** Active promotions applicable to a product (with countdown end time) */
|
|
418
|
+
async getProductPromotions(productSlug) {
|
|
419
|
+
return this.client.request("GET", `/catalog/products/${productSlug}/promotions`);
|
|
420
|
+
}
|
|
399
421
|
};
|
|
400
422
|
var AuthModule = class {
|
|
401
423
|
constructor(client) {
|
|
@@ -507,6 +529,28 @@ var CartModule = class {
|
|
|
507
529
|
this.client.emit("cart:cleared");
|
|
508
530
|
return result;
|
|
509
531
|
}
|
|
532
|
+
/** Add a bundle to the cart (price is locked at the bundle's current price) */
|
|
533
|
+
async addBundle(bundleId, quantity = 1) {
|
|
534
|
+
const result = await this.client.request("POST", "/cart/bundles", {
|
|
535
|
+
body: { bundleId, quantity }
|
|
536
|
+
});
|
|
537
|
+
this.client.emit("cart:updated", result);
|
|
538
|
+
return result;
|
|
539
|
+
}
|
|
540
|
+
/** Update quantity of a bundle already in the cart */
|
|
541
|
+
async updateBundleQuantity(bundleId, quantity) {
|
|
542
|
+
const result = await this.client.request("PATCH", `/cart/bundles/${bundleId}`, {
|
|
543
|
+
body: { quantity }
|
|
544
|
+
});
|
|
545
|
+
this.client.emit("cart:updated", result);
|
|
546
|
+
return result;
|
|
547
|
+
}
|
|
548
|
+
/** Remove a bundle from the cart */
|
|
549
|
+
async removeBundle(bundleId) {
|
|
550
|
+
const result = await this.client.request("DELETE", `/cart/bundles/${bundleId}`);
|
|
551
|
+
this.client.emit("cart:updated", result);
|
|
552
|
+
return result;
|
|
553
|
+
}
|
|
510
554
|
/** Merge anonymous cart into authenticated customer cart */
|
|
511
555
|
async merge() {
|
|
512
556
|
const result = await this.client.request("POST", "/cart/merge");
|
|
@@ -561,7 +605,7 @@ var OrdersModule = class {
|
|
|
561
605
|
async cancel(orderNumber) {
|
|
562
606
|
return this.client.request("POST", `/orders/${orderNumber}/cancel`);
|
|
563
607
|
}
|
|
564
|
-
/** Track order by tracking token (no
|
|
608
|
+
/** Track order by tracking token (no customer login required, only API key) */
|
|
565
609
|
async track(trackingToken) {
|
|
566
610
|
return this.client.request("GET", `/orders/track/${trackingToken}`, { auth: false });
|
|
567
611
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -41,6 +41,15 @@ interface ShopInfo {
|
|
|
41
41
|
metaDescription?: string;
|
|
42
42
|
allowGuestCheckout: boolean;
|
|
43
43
|
}
|
|
44
|
+
interface ShopSeo {
|
|
45
|
+
locale: string;
|
|
46
|
+
title: string | null;
|
|
47
|
+
description: string | null;
|
|
48
|
+
keywords: string | null;
|
|
49
|
+
ogTitle: string | null;
|
|
50
|
+
ogDescription: string | null;
|
|
51
|
+
ogImage: string | null;
|
|
52
|
+
}
|
|
44
53
|
interface ProductPrice {
|
|
45
54
|
amount: number;
|
|
46
55
|
currency: string;
|
|
@@ -381,6 +390,52 @@ interface ResponseInterceptorData {
|
|
|
381
390
|
interface ResponseInterceptor {
|
|
382
391
|
(response: ResponseInterceptorData): void | Promise<void>;
|
|
383
392
|
}
|
|
393
|
+
interface BundleItem {
|
|
394
|
+
productId: string;
|
|
395
|
+
slug: string | null;
|
|
396
|
+
name: string;
|
|
397
|
+
sku: string;
|
|
398
|
+
quantity: number;
|
|
399
|
+
imageUrl: string | null;
|
|
400
|
+
defaultPrice: number | null;
|
|
401
|
+
}
|
|
402
|
+
interface Bundle {
|
|
403
|
+
id: string;
|
|
404
|
+
slug: string;
|
|
405
|
+
name: string;
|
|
406
|
+
description: string | null;
|
|
407
|
+
bundlePrice: number;
|
|
408
|
+
currency: string;
|
|
409
|
+
coverImage: string | null;
|
|
410
|
+
endsAt: number | null;
|
|
411
|
+
itemsSum: number;
|
|
412
|
+
savings: number;
|
|
413
|
+
savingsPercent: number;
|
|
414
|
+
items: BundleItem[];
|
|
415
|
+
}
|
|
416
|
+
interface CrossSellItem {
|
|
417
|
+
productId: string;
|
|
418
|
+
slug: string | null;
|
|
419
|
+
name: string;
|
|
420
|
+
sku: string;
|
|
421
|
+
price: number | null;
|
|
422
|
+
imageUrl: string | null;
|
|
423
|
+
stockCached: number;
|
|
424
|
+
}
|
|
425
|
+
interface ActivePromotion {
|
|
426
|
+
id: string;
|
|
427
|
+
name: string;
|
|
428
|
+
slug: string;
|
|
429
|
+
type: string;
|
|
430
|
+
discountType: string;
|
|
431
|
+
discountValue: number;
|
|
432
|
+
startsAt: number;
|
|
433
|
+
endsAt: number | null;
|
|
434
|
+
badgeText: string | null;
|
|
435
|
+
badgeColor: string | null;
|
|
436
|
+
showCountdown: boolean;
|
|
437
|
+
couponRequired: boolean;
|
|
438
|
+
}
|
|
384
439
|
|
|
385
440
|
declare class BehioStorefront {
|
|
386
441
|
private baseUrl;
|
|
@@ -411,6 +466,8 @@ declare class BehioStorefront {
|
|
|
411
466
|
readonly pages: PagesModule;
|
|
412
467
|
/** Get basic shop info */
|
|
413
468
|
getShopInfo(): Promise<ShopInfo>;
|
|
469
|
+
/** Get SEO metadata for the shop homepage in the given locale (defaults to shop default). */
|
|
470
|
+
getShopSeo(locale?: string): Promise<ShopSeo>;
|
|
414
471
|
/** Set auth tokens (e.g. from localStorage) */
|
|
415
472
|
setTokens(tokens: {
|
|
416
473
|
accessToken: string;
|
|
@@ -488,6 +545,22 @@ declare class CatalogModule {
|
|
|
488
545
|
page?: number;
|
|
489
546
|
limit?: number;
|
|
490
547
|
}): Promise<PaginatedResponse<ProductListItem>>;
|
|
548
|
+
/** List all active bundles */
|
|
549
|
+
getBundles(): Promise<{
|
|
550
|
+
items: Bundle[];
|
|
551
|
+
}>;
|
|
552
|
+
/** Get a single bundle by slug */
|
|
553
|
+
getBundle(slug: string): Promise<Bundle>;
|
|
554
|
+
/** Cross-sell / related / upsell products for a product */
|
|
555
|
+
getCrossSell(productSlug: string): Promise<{
|
|
556
|
+
related: CrossSellItem[];
|
|
557
|
+
upsell: CrossSellItem[];
|
|
558
|
+
crossSell: CrossSellItem[];
|
|
559
|
+
}>;
|
|
560
|
+
/** Active promotions applicable to a product (with countdown end time) */
|
|
561
|
+
getProductPromotions(productSlug: string): Promise<{
|
|
562
|
+
items: ActivePromotion[];
|
|
563
|
+
}>;
|
|
491
564
|
}
|
|
492
565
|
declare class AuthModule {
|
|
493
566
|
private client;
|
|
@@ -524,6 +597,12 @@ declare class CartModule {
|
|
|
524
597
|
removeItem(itemId: string): Promise<Cart>;
|
|
525
598
|
/** Clear entire cart */
|
|
526
599
|
clear(): Promise<void>;
|
|
600
|
+
/** Add a bundle to the cart (price is locked at the bundle's current price) */
|
|
601
|
+
addBundle(bundleId: string, quantity?: number): Promise<Cart>;
|
|
602
|
+
/** Update quantity of a bundle already in the cart */
|
|
603
|
+
updateBundleQuantity(bundleId: string, quantity: number): Promise<Cart>;
|
|
604
|
+
/** Remove a bundle from the cart */
|
|
605
|
+
removeBundle(bundleId: string): Promise<Cart>;
|
|
527
606
|
/** Merge anonymous cart into authenticated customer cart */
|
|
528
607
|
merge(): Promise<Cart>;
|
|
529
608
|
/** Apply discount code */
|
|
@@ -549,7 +628,7 @@ declare class OrdersModule {
|
|
|
549
628
|
get(orderNumber: string): Promise<OrderDetail>;
|
|
550
629
|
/** Cancel a PENDING order (requires auth) */
|
|
551
630
|
cancel(orderNumber: string): Promise<OrderDetail>;
|
|
552
|
-
/** Track order by tracking token (no
|
|
631
|
+
/** Track order by tracking token (no customer login required, only API key) */
|
|
553
632
|
track(trackingToken: string): Promise<OrderDetail>;
|
|
554
633
|
}
|
|
555
634
|
declare class CustomerModule {
|
|
@@ -583,4 +662,4 @@ declare class PagesModule {
|
|
|
583
662
|
get(slug: string, locale?: string): Promise<PageDetail>;
|
|
584
663
|
}
|
|
585
664
|
|
|
586
|
-
export { type AddToCartInput, type AddressType, AddressTypes, type AuthTokens, BehioApiError, type BehioErrorCode, type BehioEventHandler, type BehioEventType, BehioNetworkError, BehioStorefront, type BehioStorefrontConfig, type Cart, type CartDiscount, type CartItem, type CartItemProduct, type Category, type CategoryDetail, type CheckoutAddress, type CheckoutInput, type CustomerAddress, type CustomerProfile, type DataGroupFieldType, type FilterField, type FulfillmentStatus, FulfillmentStatuses, type LoginInput, type MessageResponse, type OrderDetail, type OrderItem, type OrderListItem, type OrderStatus, type OrderStatusHistory, OrderStatuses, type Page, type PageDetail, type PaginatedResponse, type PaymentStatus, PaymentStatuses, type ProductDetail, type ProductLabel, type ProductListItem, type ProductPrice, ProductSort, type ProductSortValue, type ProductVariant, type ProductVolumePrice, type ProductsQuery, type RegisterInput, type RequestInterceptor, type RequestInterceptorConfig, type ResponseInterceptor, type ResponseInterceptorData, type ShopInfo };
|
|
665
|
+
export { type ActivePromotion, type AddToCartInput, type AddressType, AddressTypes, type AuthTokens, BehioApiError, type BehioErrorCode, type BehioEventHandler, type BehioEventType, BehioNetworkError, BehioStorefront, type BehioStorefrontConfig, type Bundle, type BundleItem, type Cart, type CartDiscount, type CartItem, type CartItemProduct, type Category, type CategoryDetail, type CheckoutAddress, type CheckoutInput, type CrossSellItem, type CustomerAddress, type CustomerProfile, type DataGroupFieldType, type FilterField, type FulfillmentStatus, FulfillmentStatuses, type LoginInput, type MessageResponse, type OrderDetail, type OrderItem, type OrderListItem, type OrderStatus, type OrderStatusHistory, OrderStatuses, type Page, type PageDetail, type PaginatedResponse, type PaymentStatus, PaymentStatuses, type ProductDetail, type ProductLabel, type ProductListItem, type ProductPrice, ProductSort, type ProductSortValue, type ProductVariant, type ProductVolumePrice, type ProductsQuery, type RegisterInput, type RequestInterceptor, type RequestInterceptorConfig, type ResponseInterceptor, type ResponseInterceptorData, type ShopInfo, type ShopSeo };
|
package/dist/index.d.ts
CHANGED
|
@@ -41,6 +41,15 @@ interface ShopInfo {
|
|
|
41
41
|
metaDescription?: string;
|
|
42
42
|
allowGuestCheckout: boolean;
|
|
43
43
|
}
|
|
44
|
+
interface ShopSeo {
|
|
45
|
+
locale: string;
|
|
46
|
+
title: string | null;
|
|
47
|
+
description: string | null;
|
|
48
|
+
keywords: string | null;
|
|
49
|
+
ogTitle: string | null;
|
|
50
|
+
ogDescription: string | null;
|
|
51
|
+
ogImage: string | null;
|
|
52
|
+
}
|
|
44
53
|
interface ProductPrice {
|
|
45
54
|
amount: number;
|
|
46
55
|
currency: string;
|
|
@@ -381,6 +390,52 @@ interface ResponseInterceptorData {
|
|
|
381
390
|
interface ResponseInterceptor {
|
|
382
391
|
(response: ResponseInterceptorData): void | Promise<void>;
|
|
383
392
|
}
|
|
393
|
+
interface BundleItem {
|
|
394
|
+
productId: string;
|
|
395
|
+
slug: string | null;
|
|
396
|
+
name: string;
|
|
397
|
+
sku: string;
|
|
398
|
+
quantity: number;
|
|
399
|
+
imageUrl: string | null;
|
|
400
|
+
defaultPrice: number | null;
|
|
401
|
+
}
|
|
402
|
+
interface Bundle {
|
|
403
|
+
id: string;
|
|
404
|
+
slug: string;
|
|
405
|
+
name: string;
|
|
406
|
+
description: string | null;
|
|
407
|
+
bundlePrice: number;
|
|
408
|
+
currency: string;
|
|
409
|
+
coverImage: string | null;
|
|
410
|
+
endsAt: number | null;
|
|
411
|
+
itemsSum: number;
|
|
412
|
+
savings: number;
|
|
413
|
+
savingsPercent: number;
|
|
414
|
+
items: BundleItem[];
|
|
415
|
+
}
|
|
416
|
+
interface CrossSellItem {
|
|
417
|
+
productId: string;
|
|
418
|
+
slug: string | null;
|
|
419
|
+
name: string;
|
|
420
|
+
sku: string;
|
|
421
|
+
price: number | null;
|
|
422
|
+
imageUrl: string | null;
|
|
423
|
+
stockCached: number;
|
|
424
|
+
}
|
|
425
|
+
interface ActivePromotion {
|
|
426
|
+
id: string;
|
|
427
|
+
name: string;
|
|
428
|
+
slug: string;
|
|
429
|
+
type: string;
|
|
430
|
+
discountType: string;
|
|
431
|
+
discountValue: number;
|
|
432
|
+
startsAt: number;
|
|
433
|
+
endsAt: number | null;
|
|
434
|
+
badgeText: string | null;
|
|
435
|
+
badgeColor: string | null;
|
|
436
|
+
showCountdown: boolean;
|
|
437
|
+
couponRequired: boolean;
|
|
438
|
+
}
|
|
384
439
|
|
|
385
440
|
declare class BehioStorefront {
|
|
386
441
|
private baseUrl;
|
|
@@ -411,6 +466,8 @@ declare class BehioStorefront {
|
|
|
411
466
|
readonly pages: PagesModule;
|
|
412
467
|
/** Get basic shop info */
|
|
413
468
|
getShopInfo(): Promise<ShopInfo>;
|
|
469
|
+
/** Get SEO metadata for the shop homepage in the given locale (defaults to shop default). */
|
|
470
|
+
getShopSeo(locale?: string): Promise<ShopSeo>;
|
|
414
471
|
/** Set auth tokens (e.g. from localStorage) */
|
|
415
472
|
setTokens(tokens: {
|
|
416
473
|
accessToken: string;
|
|
@@ -488,6 +545,22 @@ declare class CatalogModule {
|
|
|
488
545
|
page?: number;
|
|
489
546
|
limit?: number;
|
|
490
547
|
}): Promise<PaginatedResponse<ProductListItem>>;
|
|
548
|
+
/** List all active bundles */
|
|
549
|
+
getBundles(): Promise<{
|
|
550
|
+
items: Bundle[];
|
|
551
|
+
}>;
|
|
552
|
+
/** Get a single bundle by slug */
|
|
553
|
+
getBundle(slug: string): Promise<Bundle>;
|
|
554
|
+
/** Cross-sell / related / upsell products for a product */
|
|
555
|
+
getCrossSell(productSlug: string): Promise<{
|
|
556
|
+
related: CrossSellItem[];
|
|
557
|
+
upsell: CrossSellItem[];
|
|
558
|
+
crossSell: CrossSellItem[];
|
|
559
|
+
}>;
|
|
560
|
+
/** Active promotions applicable to a product (with countdown end time) */
|
|
561
|
+
getProductPromotions(productSlug: string): Promise<{
|
|
562
|
+
items: ActivePromotion[];
|
|
563
|
+
}>;
|
|
491
564
|
}
|
|
492
565
|
declare class AuthModule {
|
|
493
566
|
private client;
|
|
@@ -524,6 +597,12 @@ declare class CartModule {
|
|
|
524
597
|
removeItem(itemId: string): Promise<Cart>;
|
|
525
598
|
/** Clear entire cart */
|
|
526
599
|
clear(): Promise<void>;
|
|
600
|
+
/** Add a bundle to the cart (price is locked at the bundle's current price) */
|
|
601
|
+
addBundle(bundleId: string, quantity?: number): Promise<Cart>;
|
|
602
|
+
/** Update quantity of a bundle already in the cart */
|
|
603
|
+
updateBundleQuantity(bundleId: string, quantity: number): Promise<Cart>;
|
|
604
|
+
/** Remove a bundle from the cart */
|
|
605
|
+
removeBundle(bundleId: string): Promise<Cart>;
|
|
527
606
|
/** Merge anonymous cart into authenticated customer cart */
|
|
528
607
|
merge(): Promise<Cart>;
|
|
529
608
|
/** Apply discount code */
|
|
@@ -549,7 +628,7 @@ declare class OrdersModule {
|
|
|
549
628
|
get(orderNumber: string): Promise<OrderDetail>;
|
|
550
629
|
/** Cancel a PENDING order (requires auth) */
|
|
551
630
|
cancel(orderNumber: string): Promise<OrderDetail>;
|
|
552
|
-
/** Track order by tracking token (no
|
|
631
|
+
/** Track order by tracking token (no customer login required, only API key) */
|
|
553
632
|
track(trackingToken: string): Promise<OrderDetail>;
|
|
554
633
|
}
|
|
555
634
|
declare class CustomerModule {
|
|
@@ -583,4 +662,4 @@ declare class PagesModule {
|
|
|
583
662
|
get(slug: string, locale?: string): Promise<PageDetail>;
|
|
584
663
|
}
|
|
585
664
|
|
|
586
|
-
export { type AddToCartInput, type AddressType, AddressTypes, type AuthTokens, BehioApiError, type BehioErrorCode, type BehioEventHandler, type BehioEventType, BehioNetworkError, BehioStorefront, type BehioStorefrontConfig, type Cart, type CartDiscount, type CartItem, type CartItemProduct, type Category, type CategoryDetail, type CheckoutAddress, type CheckoutInput, type CustomerAddress, type CustomerProfile, type DataGroupFieldType, type FilterField, type FulfillmentStatus, FulfillmentStatuses, type LoginInput, type MessageResponse, type OrderDetail, type OrderItem, type OrderListItem, type OrderStatus, type OrderStatusHistory, OrderStatuses, type Page, type PageDetail, type PaginatedResponse, type PaymentStatus, PaymentStatuses, type ProductDetail, type ProductLabel, type ProductListItem, type ProductPrice, ProductSort, type ProductSortValue, type ProductVariant, type ProductVolumePrice, type ProductsQuery, type RegisterInput, type RequestInterceptor, type RequestInterceptorConfig, type ResponseInterceptor, type ResponseInterceptorData, type ShopInfo };
|
|
665
|
+
export { type ActivePromotion, type AddToCartInput, type AddressType, AddressTypes, type AuthTokens, BehioApiError, type BehioErrorCode, type BehioEventHandler, type BehioEventType, BehioNetworkError, BehioStorefront, type BehioStorefrontConfig, type Bundle, type BundleItem, type Cart, type CartDiscount, type CartItem, type CartItemProduct, type Category, type CategoryDetail, type CheckoutAddress, type CheckoutInput, type CrossSellItem, type CustomerAddress, type CustomerProfile, type DataGroupFieldType, type FilterField, type FulfillmentStatus, FulfillmentStatuses, type LoginInput, type MessageResponse, type OrderDetail, type OrderItem, type OrderListItem, type OrderStatus, type OrderStatusHistory, OrderStatuses, type Page, type PageDetail, type PaginatedResponse, type PaymentStatus, PaymentStatuses, type ProductDetail, type ProductLabel, type ProductListItem, type ProductPrice, ProductSort, type ProductSortValue, type ProductVariant, type ProductVolumePrice, type ProductsQuery, type RegisterInput, type RequestInterceptor, type RequestInterceptorConfig, type ResponseInterceptor, type ResponseInterceptorData, type ShopInfo, type ShopSeo };
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _chunkQOEYSUF2js = require('./chunk-QOEYSUF2.js');
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
@@ -17,4 +17,4 @@ var _chunkGGAO5T5Pjs = require('./chunk-GGAO5T5P.js');
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
exports.AddressTypes =
|
|
20
|
+
exports.AddressTypes = _chunkQOEYSUF2js.AddressTypes; exports.BehioApiError = _chunkQOEYSUF2js.BehioApiError; exports.BehioNetworkError = _chunkQOEYSUF2js.BehioNetworkError; exports.BehioStorefront = _chunkQOEYSUF2js.BehioStorefront; exports.FulfillmentStatuses = _chunkQOEYSUF2js.FulfillmentStatuses; exports.OrderStatuses = _chunkQOEYSUF2js.OrderStatuses; exports.PaymentStatuses = _chunkQOEYSUF2js.PaymentStatuses; exports.ProductSort = _chunkQOEYSUF2js.ProductSort;
|
package/dist/index.mjs
CHANGED
package/dist/react.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
3
3
|
import { QueryClient } from '@tanstack/react-query';
|
|
4
|
-
import { BehioStorefront, ProductsQuery, PaginatedResponse, ProductListItem, ProductDetail, Category, CategoryDetail, ProductLabel, FilterField, Cart, CustomerProfile, RegisterInput, CustomerAddress, OrderListItem, OrderDetail, CheckoutInput, PageDetail, Page, ShopInfo } from './index.mjs';
|
|
5
|
-
export { AddToCartInput, AuthTokens, BehioApiError, CartDiscount, CartItem, CheckoutAddress, FulfillmentStatus, LoginInput, MessageResponse, OrderItem, OrderStatus, PaymentStatus, ProductPrice, ProductVariant } from './index.mjs';
|
|
4
|
+
import { BehioStorefront, ProductsQuery, PaginatedResponse, ProductListItem, ProductDetail, Category, CategoryDetail, ProductLabel, FilterField, Cart, CustomerProfile, RegisterInput, CustomerAddress, OrderListItem, OrderDetail, CheckoutInput, PageDetail, Page, ShopInfo, ShopSeo, Bundle, CrossSellItem, ActivePromotion } from './index.mjs';
|
|
5
|
+
export { AddToCartInput, AuthTokens, BehioApiError, BundleItem, CartDiscount, CartItem, CheckoutAddress, FulfillmentStatus, LoginInput, MessageResponse, OrderItem, OrderStatus, PaymentStatus, ProductPrice, ProductVariant } from './index.mjs';
|
|
6
6
|
import * as _tanstack_query_core from '@tanstack/query-core';
|
|
7
7
|
|
|
8
8
|
interface StorageAdapter {
|
|
@@ -265,6 +265,62 @@ interface UseShopInfoOptions {
|
|
|
265
265
|
}
|
|
266
266
|
declare function useShopInfo(options?: UseShopInfoOptions): _tanstack_react_query.UseQueryResult<ShopInfo, Error>;
|
|
267
267
|
|
|
268
|
+
interface UseShopSeoOptions {
|
|
269
|
+
/** Override locale (ISO-639-1). Defaults to the shop's default locale. */
|
|
270
|
+
locale?: string;
|
|
271
|
+
/** Hydrate from SSR-fetched data (use `client.getShopSeo(locale)` on the server). */
|
|
272
|
+
initialData?: ShopSeo;
|
|
273
|
+
/** Disable the query. */
|
|
274
|
+
enabled?: boolean;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* React Query hook for per-locale shop SEO metadata. Safe to render on the
|
|
278
|
+
* server via `initialData` from `client.getShopSeo(locale)`.
|
|
279
|
+
*/
|
|
280
|
+
declare function useShopSeo(options?: UseShopSeoOptions): _tanstack_react_query.UseQueryResult<ShopSeo, Error>;
|
|
281
|
+
|
|
282
|
+
/** List all active bundles. */
|
|
283
|
+
declare function useBundles(options?: {
|
|
284
|
+
enabled?: boolean;
|
|
285
|
+
initialData?: {
|
|
286
|
+
items: Bundle[];
|
|
287
|
+
};
|
|
288
|
+
}): _tanstack_react_query.UseQueryResult<{
|
|
289
|
+
items: Bundle[];
|
|
290
|
+
}, Error>;
|
|
291
|
+
/** Get a single bundle by slug. */
|
|
292
|
+
declare function useBundle(slug: string | undefined, options?: {
|
|
293
|
+
enabled?: boolean;
|
|
294
|
+
initialData?: Bundle;
|
|
295
|
+
}): _tanstack_react_query.UseQueryResult<Bundle, Error>;
|
|
296
|
+
|
|
297
|
+
type CrossSellResponse = {
|
|
298
|
+
related: CrossSellItem[];
|
|
299
|
+
upsell: CrossSellItem[];
|
|
300
|
+
crossSell: CrossSellItem[];
|
|
301
|
+
};
|
|
302
|
+
/**
|
|
303
|
+
* Fetch related / upsell / cross-sell products for a given product.
|
|
304
|
+
* Returns all three lists separately so the UI can group them into
|
|
305
|
+
* different sections on the product detail page.
|
|
306
|
+
*/
|
|
307
|
+
declare function useCrossSell(productSlug: string | undefined, options?: {
|
|
308
|
+
enabled?: boolean;
|
|
309
|
+
initialData?: CrossSellResponse;
|
|
310
|
+
}): _tanstack_react_query.UseQueryResult<CrossSellResponse, Error>;
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Fetch currently active promotions applicable to a specific product.
|
|
314
|
+
* Use this on product detail pages to render countdown timers and
|
|
315
|
+
* "AKCE -20%" badges.
|
|
316
|
+
*/
|
|
317
|
+
declare function useProductPromotions(productSlug: string | undefined, options?: {
|
|
318
|
+
enabled?: boolean;
|
|
319
|
+
refetchIntervalMs?: number;
|
|
320
|
+
}): _tanstack_react_query.UseQueryResult<{
|
|
321
|
+
items: ActivePromotion[];
|
|
322
|
+
}, Error>;
|
|
323
|
+
|
|
268
324
|
/**
|
|
269
325
|
* Returns the raw BehioStorefront client instance.
|
|
270
326
|
*
|
|
@@ -283,4 +339,4 @@ declare function useBehioClient(): BehioStorefront;
|
|
|
283
339
|
*/
|
|
284
340
|
declare function formatPrice(amount: number, currency: string, locale?: string): string;
|
|
285
341
|
|
|
286
|
-
export { BehioProvider, type BehioProviderProps, Cart, Category, CategoryDetail, CheckoutInput, CustomerAddress, CustomerProfile, FilterField, OrderDetail, OrderListItem, Page, PageDetail, PaginatedResponse, ProductDetail, ProductLabel, ProductListItem, ProductsQuery, RegisterInput, ShopInfo, type StorageAdapter, type UseAddressesOptions, type UseCartCountOptions, type UseCartOptions, type UseCategoriesOptions, type UseCategoryOptions, type UseCustomerOptions, type UseFeaturedOptions, type UseFiltersOptions, type UseLabelsOptions, type UseOrderOptions, type UseOrdersOptions, type UsePageOptions, type UsePagesOptions, type UseProductOptions, type UseProductsOptions, type UseSearchOptions, type UseShopInfoOptions, cookieStorage, createMemoryStorage, detectStorage, formatPrice, localStorageAdapter, memoryStorage, useAddresses, useAuth, useBehio, useBehioClient, useCart, useCartCount, useCategories, useCategory, useCheckout, useCustomer, useFeatured, useFilters, useLabels, useOrder, useOrders, usePage, usePages, useProduct, useProducts, useSearch, useShopInfo };
|
|
342
|
+
export { ActivePromotion, BehioProvider, type BehioProviderProps, Bundle, Cart, Category, CategoryDetail, CheckoutInput, CrossSellItem, CustomerAddress, CustomerProfile, FilterField, OrderDetail, OrderListItem, Page, PageDetail, PaginatedResponse, ProductDetail, ProductLabel, ProductListItem, ProductsQuery, RegisterInput, ShopInfo, ShopSeo, type StorageAdapter, type UseAddressesOptions, type UseCartCountOptions, type UseCartOptions, type UseCategoriesOptions, type UseCategoryOptions, type UseCustomerOptions, type UseFeaturedOptions, type UseFiltersOptions, type UseLabelsOptions, type UseOrderOptions, type UseOrdersOptions, type UsePageOptions, type UsePagesOptions, type UseProductOptions, type UseProductsOptions, type UseSearchOptions, type UseShopInfoOptions, type UseShopSeoOptions, cookieStorage, createMemoryStorage, detectStorage, formatPrice, localStorageAdapter, memoryStorage, useAddresses, useAuth, useBehio, useBehioClient, useBundle, useBundles, useCart, useCartCount, useCategories, useCategory, useCheckout, useCrossSell, useCustomer, useFeatured, useFilters, useLabels, useOrder, useOrders, usePage, usePages, useProduct, useProductPromotions, useProducts, useSearch, useShopInfo, useShopSeo };
|
package/dist/react.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
3
3
|
import { QueryClient } from '@tanstack/react-query';
|
|
4
|
-
import { BehioStorefront, ProductsQuery, PaginatedResponse, ProductListItem, ProductDetail, Category, CategoryDetail, ProductLabel, FilterField, Cart, CustomerProfile, RegisterInput, CustomerAddress, OrderListItem, OrderDetail, CheckoutInput, PageDetail, Page, ShopInfo } from './index.js';
|
|
5
|
-
export { AddToCartInput, AuthTokens, BehioApiError, CartDiscount, CartItem, CheckoutAddress, FulfillmentStatus, LoginInput, MessageResponse, OrderItem, OrderStatus, PaymentStatus, ProductPrice, ProductVariant } from './index.js';
|
|
4
|
+
import { BehioStorefront, ProductsQuery, PaginatedResponse, ProductListItem, ProductDetail, Category, CategoryDetail, ProductLabel, FilterField, Cart, CustomerProfile, RegisterInput, CustomerAddress, OrderListItem, OrderDetail, CheckoutInput, PageDetail, Page, ShopInfo, ShopSeo, Bundle, CrossSellItem, ActivePromotion } from './index.js';
|
|
5
|
+
export { AddToCartInput, AuthTokens, BehioApiError, BundleItem, CartDiscount, CartItem, CheckoutAddress, FulfillmentStatus, LoginInput, MessageResponse, OrderItem, OrderStatus, PaymentStatus, ProductPrice, ProductVariant } from './index.js';
|
|
6
6
|
import * as _tanstack_query_core from '@tanstack/query-core';
|
|
7
7
|
|
|
8
8
|
interface StorageAdapter {
|
|
@@ -265,6 +265,62 @@ interface UseShopInfoOptions {
|
|
|
265
265
|
}
|
|
266
266
|
declare function useShopInfo(options?: UseShopInfoOptions): _tanstack_react_query.UseQueryResult<ShopInfo, Error>;
|
|
267
267
|
|
|
268
|
+
interface UseShopSeoOptions {
|
|
269
|
+
/** Override locale (ISO-639-1). Defaults to the shop's default locale. */
|
|
270
|
+
locale?: string;
|
|
271
|
+
/** Hydrate from SSR-fetched data (use `client.getShopSeo(locale)` on the server). */
|
|
272
|
+
initialData?: ShopSeo;
|
|
273
|
+
/** Disable the query. */
|
|
274
|
+
enabled?: boolean;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* React Query hook for per-locale shop SEO metadata. Safe to render on the
|
|
278
|
+
* server via `initialData` from `client.getShopSeo(locale)`.
|
|
279
|
+
*/
|
|
280
|
+
declare function useShopSeo(options?: UseShopSeoOptions): _tanstack_react_query.UseQueryResult<ShopSeo, Error>;
|
|
281
|
+
|
|
282
|
+
/** List all active bundles. */
|
|
283
|
+
declare function useBundles(options?: {
|
|
284
|
+
enabled?: boolean;
|
|
285
|
+
initialData?: {
|
|
286
|
+
items: Bundle[];
|
|
287
|
+
};
|
|
288
|
+
}): _tanstack_react_query.UseQueryResult<{
|
|
289
|
+
items: Bundle[];
|
|
290
|
+
}, Error>;
|
|
291
|
+
/** Get a single bundle by slug. */
|
|
292
|
+
declare function useBundle(slug: string | undefined, options?: {
|
|
293
|
+
enabled?: boolean;
|
|
294
|
+
initialData?: Bundle;
|
|
295
|
+
}): _tanstack_react_query.UseQueryResult<Bundle, Error>;
|
|
296
|
+
|
|
297
|
+
type CrossSellResponse = {
|
|
298
|
+
related: CrossSellItem[];
|
|
299
|
+
upsell: CrossSellItem[];
|
|
300
|
+
crossSell: CrossSellItem[];
|
|
301
|
+
};
|
|
302
|
+
/**
|
|
303
|
+
* Fetch related / upsell / cross-sell products for a given product.
|
|
304
|
+
* Returns all three lists separately so the UI can group them into
|
|
305
|
+
* different sections on the product detail page.
|
|
306
|
+
*/
|
|
307
|
+
declare function useCrossSell(productSlug: string | undefined, options?: {
|
|
308
|
+
enabled?: boolean;
|
|
309
|
+
initialData?: CrossSellResponse;
|
|
310
|
+
}): _tanstack_react_query.UseQueryResult<CrossSellResponse, Error>;
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Fetch currently active promotions applicable to a specific product.
|
|
314
|
+
* Use this on product detail pages to render countdown timers and
|
|
315
|
+
* "AKCE -20%" badges.
|
|
316
|
+
*/
|
|
317
|
+
declare function useProductPromotions(productSlug: string | undefined, options?: {
|
|
318
|
+
enabled?: boolean;
|
|
319
|
+
refetchIntervalMs?: number;
|
|
320
|
+
}): _tanstack_react_query.UseQueryResult<{
|
|
321
|
+
items: ActivePromotion[];
|
|
322
|
+
}, Error>;
|
|
323
|
+
|
|
268
324
|
/**
|
|
269
325
|
* Returns the raw BehioStorefront client instance.
|
|
270
326
|
*
|
|
@@ -283,4 +339,4 @@ declare function useBehioClient(): BehioStorefront;
|
|
|
283
339
|
*/
|
|
284
340
|
declare function formatPrice(amount: number, currency: string, locale?: string): string;
|
|
285
341
|
|
|
286
|
-
export { BehioProvider, type BehioProviderProps, Cart, Category, CategoryDetail, CheckoutInput, CustomerAddress, CustomerProfile, FilterField, OrderDetail, OrderListItem, Page, PageDetail, PaginatedResponse, ProductDetail, ProductLabel, ProductListItem, ProductsQuery, RegisterInput, ShopInfo, type StorageAdapter, type UseAddressesOptions, type UseCartCountOptions, type UseCartOptions, type UseCategoriesOptions, type UseCategoryOptions, type UseCustomerOptions, type UseFeaturedOptions, type UseFiltersOptions, type UseLabelsOptions, type UseOrderOptions, type UseOrdersOptions, type UsePageOptions, type UsePagesOptions, type UseProductOptions, type UseProductsOptions, type UseSearchOptions, type UseShopInfoOptions, cookieStorage, createMemoryStorage, detectStorage, formatPrice, localStorageAdapter, memoryStorage, useAddresses, useAuth, useBehio, useBehioClient, useCart, useCartCount, useCategories, useCategory, useCheckout, useCustomer, useFeatured, useFilters, useLabels, useOrder, useOrders, usePage, usePages, useProduct, useProducts, useSearch, useShopInfo };
|
|
342
|
+
export { ActivePromotion, BehioProvider, type BehioProviderProps, Bundle, Cart, Category, CategoryDetail, CheckoutInput, CrossSellItem, CustomerAddress, CustomerProfile, FilterField, OrderDetail, OrderListItem, Page, PageDetail, PaginatedResponse, ProductDetail, ProductLabel, ProductListItem, ProductsQuery, RegisterInput, ShopInfo, ShopSeo, type StorageAdapter, type UseAddressesOptions, type UseCartCountOptions, type UseCartOptions, type UseCategoriesOptions, type UseCategoryOptions, type UseCustomerOptions, type UseFeaturedOptions, type UseFiltersOptions, type UseLabelsOptions, type UseOrderOptions, type UseOrdersOptions, type UsePageOptions, type UsePagesOptions, type UseProductOptions, type UseProductsOptions, type UseSearchOptions, type UseShopInfoOptions, type UseShopSeoOptions, cookieStorage, createMemoryStorage, detectStorage, formatPrice, localStorageAdapter, memoryStorage, useAddresses, useAuth, useBehio, useBehioClient, useBundle, useBundles, useCart, useCartCount, useCategories, useCategory, useCheckout, useCrossSell, useCustomer, useFeatured, useFilters, useLabels, useOrder, useOrders, usePage, usePages, useProduct, useProductPromotions, useProducts, useSearch, useShopInfo, useShopSeo };
|
package/dist/react.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkQOEYSUF2js = require('./chunk-QOEYSUF2.js');
|
|
4
4
|
|
|
5
5
|
// src/react/provider.tsx
|
|
6
6
|
var _react = require('react');
|
|
@@ -114,7 +114,7 @@ function BehioProvider({
|
|
|
114
114
|
const storageAdapter = _react.useMemo.call(void 0, () => resolveStorage(storageOption), [storageOption]);
|
|
115
115
|
const clientRef = _react.useRef.call(void 0, null);
|
|
116
116
|
if (!clientRef.current) {
|
|
117
|
-
clientRef.current = new (0,
|
|
117
|
+
clientRef.current = new (0, _chunkQOEYSUF2js.BehioStorefront)({
|
|
118
118
|
apiKey,
|
|
119
119
|
baseUrl,
|
|
120
120
|
locale,
|
|
@@ -872,6 +872,64 @@ function useShopInfo(options) {
|
|
|
872
872
|
});
|
|
873
873
|
}
|
|
874
874
|
|
|
875
|
+
// src/react/hooks/use-shop-seo.ts
|
|
876
|
+
|
|
877
|
+
function useShopSeo(options) {
|
|
878
|
+
const { client } = useBehio();
|
|
879
|
+
const { locale, initialData, enabled = true } = _nullishCoalesce(options, () => ( {}));
|
|
880
|
+
return _reactquery.useQuery.call(void 0, {
|
|
881
|
+
queryKey: ["behio", "shop-seo", _nullishCoalesce(locale, () => ( "_default"))],
|
|
882
|
+
queryFn: () => client.getShopSeo(locale),
|
|
883
|
+
initialData,
|
|
884
|
+
enabled
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
// src/react/hooks/use-bundles.ts
|
|
889
|
+
|
|
890
|
+
function useBundles(options) {
|
|
891
|
+
const { client } = useBehio();
|
|
892
|
+
return _reactquery.useQuery.call(void 0, {
|
|
893
|
+
queryKey: ["behio", "bundles"],
|
|
894
|
+
queryFn: () => client.catalog.getBundles(),
|
|
895
|
+
enabled: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _60 => _60.enabled]), () => ( true)),
|
|
896
|
+
initialData: _optionalChain([options, 'optionalAccess', _61 => _61.initialData])
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
function useBundle(slug, options) {
|
|
900
|
+
const { client } = useBehio();
|
|
901
|
+
return _reactquery.useQuery.call(void 0, {
|
|
902
|
+
queryKey: ["behio", "bundle", slug],
|
|
903
|
+
queryFn: () => client.catalog.getBundle(slug),
|
|
904
|
+
enabled: Boolean(slug) && (_nullishCoalesce(_optionalChain([options, 'optionalAccess', _62 => _62.enabled]), () => ( true))),
|
|
905
|
+
initialData: _optionalChain([options, 'optionalAccess', _63 => _63.initialData])
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// src/react/hooks/use-cross-sell.ts
|
|
910
|
+
|
|
911
|
+
function useCrossSell(productSlug, options) {
|
|
912
|
+
const { client } = useBehio();
|
|
913
|
+
return _reactquery.useQuery.call(void 0, {
|
|
914
|
+
queryKey: ["behio", "cross-sell", productSlug],
|
|
915
|
+
queryFn: () => client.catalog.getCrossSell(productSlug),
|
|
916
|
+
enabled: Boolean(productSlug) && (_nullishCoalesce(_optionalChain([options, 'optionalAccess', _64 => _64.enabled]), () => ( true))),
|
|
917
|
+
initialData: _optionalChain([options, 'optionalAccess', _65 => _65.initialData])
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// src/react/hooks/use-product-promotions.ts
|
|
922
|
+
|
|
923
|
+
function useProductPromotions(productSlug, options) {
|
|
924
|
+
const { client } = useBehio();
|
|
925
|
+
return _reactquery.useQuery.call(void 0, {
|
|
926
|
+
queryKey: ["behio", "product-promotions", productSlug],
|
|
927
|
+
queryFn: () => client.catalog.getProductPromotions(productSlug),
|
|
928
|
+
enabled: Boolean(productSlug) && (_nullishCoalesce(_optionalChain([options, 'optionalAccess', _66 => _66.enabled]), () => ( true))),
|
|
929
|
+
refetchInterval: _optionalChain([options, 'optionalAccess', _67 => _67.refetchIntervalMs])
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
|
|
875
933
|
// src/react/hooks/use-behio-client.ts
|
|
876
934
|
function useBehioClient() {
|
|
877
935
|
return useBehio().client;
|
|
@@ -920,4 +978,9 @@ function formatPrice(amount, currency, locale) {
|
|
|
920
978
|
|
|
921
979
|
|
|
922
980
|
|
|
923
|
-
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
exports.BehioProvider = BehioProvider; exports.cookieStorage = cookieStorage; exports.createMemoryStorage = createMemoryStorage; exports.detectStorage = detectStorage; exports.formatPrice = formatPrice; exports.localStorageAdapter = localStorageAdapter; exports.memoryStorage = memoryStorage; exports.useAddresses = useAddresses; exports.useAuth = useAuth; exports.useBehio = useBehio; exports.useBehioClient = useBehioClient; exports.useBundle = useBundle; exports.useBundles = useBundles; exports.useCart = useCart; exports.useCartCount = useCartCount; exports.useCategories = useCategories; exports.useCategory = useCategory; exports.useCheckout = useCheckout; exports.useCrossSell = useCrossSell; exports.useCustomer = useCustomer; exports.useFeatured = useFeatured; exports.useFilters = useFilters; exports.useLabels = useLabels; exports.useOrder = useOrder; exports.useOrders = useOrders; exports.usePage = usePage; exports.usePages = usePages; exports.useProduct = useProduct; exports.useProductPromotions = useProductPromotions; exports.useProducts = useProducts; exports.useSearch = useSearch; exports.useShopInfo = useShopInfo; exports.useShopSeo = useShopSeo;
|
package/dist/react.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BehioStorefront
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HYKJO2IB.mjs";
|
|
4
4
|
|
|
5
5
|
// src/react/provider.tsx
|
|
6
6
|
import { useRef, useEffect, useMemo } from "react";
|
|
@@ -872,6 +872,64 @@ function useShopInfo(options) {
|
|
|
872
872
|
});
|
|
873
873
|
}
|
|
874
874
|
|
|
875
|
+
// src/react/hooks/use-shop-seo.ts
|
|
876
|
+
import { useQuery as useQuery15 } from "@tanstack/react-query";
|
|
877
|
+
function useShopSeo(options) {
|
|
878
|
+
const { client } = useBehio();
|
|
879
|
+
const { locale, initialData, enabled = true } = options ?? {};
|
|
880
|
+
return useQuery15({
|
|
881
|
+
queryKey: ["behio", "shop-seo", locale ?? "_default"],
|
|
882
|
+
queryFn: () => client.getShopSeo(locale),
|
|
883
|
+
initialData,
|
|
884
|
+
enabled
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
// src/react/hooks/use-bundles.ts
|
|
889
|
+
import { useQuery as useQuery16 } from "@tanstack/react-query";
|
|
890
|
+
function useBundles(options) {
|
|
891
|
+
const { client } = useBehio();
|
|
892
|
+
return useQuery16({
|
|
893
|
+
queryKey: ["behio", "bundles"],
|
|
894
|
+
queryFn: () => client.catalog.getBundles(),
|
|
895
|
+
enabled: options?.enabled ?? true,
|
|
896
|
+
initialData: options?.initialData
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
function useBundle(slug, options) {
|
|
900
|
+
const { client } = useBehio();
|
|
901
|
+
return useQuery16({
|
|
902
|
+
queryKey: ["behio", "bundle", slug],
|
|
903
|
+
queryFn: () => client.catalog.getBundle(slug),
|
|
904
|
+
enabled: Boolean(slug) && (options?.enabled ?? true),
|
|
905
|
+
initialData: options?.initialData
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// src/react/hooks/use-cross-sell.ts
|
|
910
|
+
import { useQuery as useQuery17 } from "@tanstack/react-query";
|
|
911
|
+
function useCrossSell(productSlug, options) {
|
|
912
|
+
const { client } = useBehio();
|
|
913
|
+
return useQuery17({
|
|
914
|
+
queryKey: ["behio", "cross-sell", productSlug],
|
|
915
|
+
queryFn: () => client.catalog.getCrossSell(productSlug),
|
|
916
|
+
enabled: Boolean(productSlug) && (options?.enabled ?? true),
|
|
917
|
+
initialData: options?.initialData
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// src/react/hooks/use-product-promotions.ts
|
|
922
|
+
import { useQuery as useQuery18 } from "@tanstack/react-query";
|
|
923
|
+
function useProductPromotions(productSlug, options) {
|
|
924
|
+
const { client } = useBehio();
|
|
925
|
+
return useQuery18({
|
|
926
|
+
queryKey: ["behio", "product-promotions", productSlug],
|
|
927
|
+
queryFn: () => client.catalog.getProductPromotions(productSlug),
|
|
928
|
+
enabled: Boolean(productSlug) && (options?.enabled ?? true),
|
|
929
|
+
refetchInterval: options?.refetchIntervalMs
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
|
|
875
933
|
// src/react/hooks/use-behio-client.ts
|
|
876
934
|
function useBehioClient() {
|
|
877
935
|
return useBehio().client;
|
|
@@ -903,11 +961,14 @@ export {
|
|
|
903
961
|
useAuth,
|
|
904
962
|
useBehio,
|
|
905
963
|
useBehioClient,
|
|
964
|
+
useBundle,
|
|
965
|
+
useBundles,
|
|
906
966
|
useCart,
|
|
907
967
|
useCartCount,
|
|
908
968
|
useCategories,
|
|
909
969
|
useCategory,
|
|
910
970
|
useCheckout,
|
|
971
|
+
useCrossSell,
|
|
911
972
|
useCustomer,
|
|
912
973
|
useFeatured,
|
|
913
974
|
useFilters,
|
|
@@ -917,7 +978,9 @@ export {
|
|
|
917
978
|
usePage,
|
|
918
979
|
usePages,
|
|
919
980
|
useProduct,
|
|
981
|
+
useProductPromotions,
|
|
920
982
|
useProducts,
|
|
921
983
|
useSearch,
|
|
922
|
-
useShopInfo
|
|
984
|
+
useShopInfo,
|
|
985
|
+
useShopSeo
|
|
923
986
|
};
|